sunMouse.c revision 48c4760e
1ee7c6486Stsutsui/* $Xorg: sunMouse.c,v 1.3 2000/08/17 19:48:32 cpqbld Exp $ */
2ee7c6486Stsutsui/*-
3ee7c6486Stsutsui * Copyright 1987 by the Regents of the University of California
4ee7c6486Stsutsui *
5ee7c6486Stsutsui * Permission to use, copy, modify, and distribute this
6ee7c6486Stsutsui * software and its documentation for any purpose and without
7ee7c6486Stsutsui * fee is hereby granted, provided that the above copyright
8ee7c6486Stsutsui * notice appear in all copies.  The University of California
9ee7c6486Stsutsui * makes no representations about the suitability of this
10ee7c6486Stsutsui * software for any purpose.  It is provided "as is" without
11ee7c6486Stsutsui * express or implied warranty.
12ee7c6486Stsutsui */
13ee7c6486Stsutsui
14ee7c6486Stsutsui/************************************************************
15ee7c6486StsutsuiCopyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
16ee7c6486Stsutsui
17ee7c6486Stsutsui                    All Rights Reserved
18ee7c6486Stsutsui
19ee7c6486StsutsuiPermission  to  use,  copy,  modify,  and  distribute   this
20ee7c6486Stsutsuisoftware  and  its documentation for any purpose and without
21ee7c6486Stsutsuifee is hereby granted, provided that the above copyright no-
22ee7c6486Stsutsuitice  appear  in all copies and that both that copyright no-
23ee7c6486Stsutsuitice and this permission notice appear in  supporting  docu-
24ee7c6486Stsutsuimentation,  and  that the names of Sun or The Open Group
25ee7c6486Stsutsuinot be used in advertising or publicity pertaining to
26ee7c6486Stsutsuidistribution  of  the software  without specific prior
27ee7c6486Stsutsuiwritten permission. Sun and The Open Group make no
28ee7c6486Stsutsuirepresentations about the suitability of this software for
29ee7c6486Stsutsuiany purpose. It is provided "as is" without any express or
30ee7c6486Stsutsuiimplied warranty.
31ee7c6486Stsutsui
32ee7c6486StsutsuiSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
33ee7c6486StsutsuiINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
34ee7c6486StsutsuiNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
35ee7c6486StsutsuiABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
36ee7c6486StsutsuiANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
37ee7c6486StsutsuiPROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
38ee7c6486StsutsuiOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
39ee7c6486StsutsuiTHE USE OR PERFORMANCE OF THIS SOFTWARE.
40ee7c6486Stsutsui
41ee7c6486Stsutsui********************************************************/
42ee7c6486Stsutsui/*
43ee7c6486Stsutsui * Copyright 1991, 1992, 1993 Kaleb S. Keithley
44ee7c6486Stsutsui *
45ee7c6486Stsutsui * Permission to use, copy, modify, and distribute this
46ee7c6486Stsutsui * software and its documentation for any purpose and without
47ee7c6486Stsutsui * fee is hereby granted, provided that the above copyright
48ee7c6486Stsutsui * notice appear in all copies.  Kaleb S. Keithley makes no
49ee7c6486Stsutsui * representations about the suitability of this software for
50ee7c6486Stsutsui * any purpose.  It is provided "as is" without express or
51ee7c6486Stsutsui * implied warranty.
52ee7c6486Stsutsui */
53ee7c6486Stsutsui/* $XFree86: xc/programs/Xserver/hw/sun/sunMouse.c,v 1.4 2003/11/17 22:20:36 dawes Exp $ */
54ee7c6486Stsutsui
55ee7c6486Stsutsui#define NEED_EVENTS
56ee7c6486Stsutsui#include    "sun.h"
57ee7c6486Stsutsui#include    "mi.h"
58ee7c6486Stsutsui#include    "cursor.h"
59ee7c6486Stsutsui#include    "input.h"
60ee7c6486Stsutsui#include    "inpututils.h"
61ee7c6486Stsutsui#include    "exevents.h"
62ee7c6486Stsutsui#include    "xserver-properties.h"
63ee7c6486Stsutsui
64ee7c6486StsutsuiBool sunActiveZaphod = TRUE;
65ee7c6486StsutsuiDeviceIntPtr sunPointerDevice = NULL;
66ee7c6486Stsutsui
67177290dfStsutsuistatic void sunMouseEvents(int, int, void *);
68177290dfStsutsuistatic Firm_event *sunMouseGetEvents(int, Bool, int *, Bool *);
69177290dfStsutsuistatic void sunMouseEnqueueEvent(DeviceIntPtr, Firm_event *);
70ee7c6486Stsutsuistatic Bool sunCursorOffScreen(ScreenPtr *, int *, int *);
71ee7c6486Stsutsuistatic void sunCrossScreen(ScreenPtr, int);
72ee7c6486Stsutsuistatic void sunWarpCursor(DeviceIntPtr, ScreenPtr, int, int);
73ee7c6486Stsutsui
74ee7c6486StsutsuimiPointerScreenFuncRec sunPointerScreenFuncs = {
75ee7c6486Stsutsui    sunCursorOffScreen,
76ee7c6486Stsutsui    sunCrossScreen,
77ee7c6486Stsutsui    sunWarpCursor,
78ee7c6486Stsutsui};
79ee7c6486Stsutsui
80ee7c6486Stsutsuistatic void
81177290dfStsutsuisunMouseEvents(int fd, int ready, void *data)
82ee7c6486Stsutsui{
83177290dfStsutsui    int i, numEvents = 0;
84177290dfStsutsui    Bool again = FALSE;
85177290dfStsutsui    Firm_event *events;
86177290dfStsutsui    DeviceIntPtr device = (DeviceIntPtr)data;
87177290dfStsutsui
88177290dfStsutsui    input_lock();
89177290dfStsutsui
90177290dfStsutsui    do {
91177290dfStsutsui	events = sunMouseGetEvents(fd, device->public.on, &numEvents, &again);
92177290dfStsutsui	for (i = 0; i < numEvents; i++) {
93177290dfStsutsui	    sunMouseEnqueueEvent(device, &events[i]);
94177290dfStsutsui	}
95177290dfStsutsui    } while (again);
96177290dfStsutsui
97177290dfStsutsui    input_unlock();
98ee7c6486Stsutsui}
99ee7c6486Stsutsui
100ee7c6486Stsutsui/*-
101ee7c6486Stsutsui *-----------------------------------------------------------------------
102ee7c6486Stsutsui * sunMouseCtrl --
103ee7c6486Stsutsui *	Alter the control parameters for the mouse. Since acceleration
104ee7c6486Stsutsui *	etc. is done from the PtrCtrl record in the mouse's device record,
105ee7c6486Stsutsui *	there's nothing to do here.
106ee7c6486Stsutsui *
107ee7c6486Stsutsui * Results:
108ee7c6486Stsutsui *	None.
109ee7c6486Stsutsui *
110ee7c6486Stsutsui * Side Effects:
111ee7c6486Stsutsui *	None.
112ee7c6486Stsutsui *
113ee7c6486Stsutsui *-----------------------------------------------------------------------
114ee7c6486Stsutsui */
115ee7c6486Stsutsui/*ARGSUSED*/
116ee7c6486Stsutsuistatic void
117ee7c6486StsutsuisunMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
118ee7c6486Stsutsui{
119ee7c6486Stsutsui}
120ee7c6486Stsutsui
121ee7c6486Stsutsui/*-
122ee7c6486Stsutsui *-----------------------------------------------------------------------
123ee7c6486Stsutsui * sunMouseProc --
124ee7c6486Stsutsui *	Handle the initialization, etc. of a mouse
125ee7c6486Stsutsui *
126ee7c6486Stsutsui * Results:
127ee7c6486Stsutsui *	none.
128ee7c6486Stsutsui *
129ee7c6486Stsutsui * Side Effects:
130ee7c6486Stsutsui *
131ee7c6486Stsutsui * Note:
132ee7c6486Stsutsui *	When using sunwindows, all input comes off a single fd, stored in the
133ee7c6486Stsutsui *	global windowFd.  Therefore, only one device should be enabled and
134ee7c6486Stsutsui *	disabled, even though the application still sees both mouse and
135ee7c6486Stsutsui *	keyboard.  We have arbitrarily chosen to enable and disable windowFd
136ee7c6486Stsutsui *	in the keyboard routine sunKbdProc rather than in sunMouseProc.
137ee7c6486Stsutsui *
138ee7c6486Stsutsui *-----------------------------------------------------------------------
139ee7c6486Stsutsui */
140ee7c6486Stsutsuiint
141ee7c6486StsutsuisunMouseProc(DeviceIntPtr device, int what)
142ee7c6486Stsutsui{
1439679a91bStsutsui    DevicePtr	  pMouse = &device->public;
14448c4760eStsutsui    sunPtrPrivPtr pPriv;
145ee7c6486Stsutsui    int	    	  format;
146ee7c6486Stsutsui    static int	  oformat;
147ee7c6486Stsutsui    BYTE    	  map[4];
148ee7c6486Stsutsui    Atom btn_labels[3] = {0};
149ee7c6486Stsutsui    Atom axes_labels[2] = { 0, 0 };
150ee7c6486Stsutsui
151ee7c6486Stsutsui    switch (what) {
152ee7c6486Stsutsui	case DEVICE_INIT:
1539679a91bStsutsui	    if (pMouse != &sunPointerDevice->public) {
1549c576acfStsutsui		ErrorF ("Cannot open non-system mouse\n");
155ee7c6486Stsutsui		return !Success;
156ee7c6486Stsutsui	    }
157ee7c6486Stsutsui	    if (sunPtrPriv.fd == -1)
158ee7c6486Stsutsui		return !Success;
159ee7c6486Stsutsui	    pMouse->devicePrivate = (void *) &sunPtrPriv;
160ee7c6486Stsutsui	    pMouse->on = FALSE;
161ee7c6486Stsutsui	    map[1] = 1;
162ee7c6486Stsutsui	    map[2] = 2;
163ee7c6486Stsutsui	    map[3] = 3;
164ee7c6486Stsutsui	    btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
165ee7c6486Stsutsui	    btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
166ee7c6486Stsutsui	    btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
167ee7c6486Stsutsui	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
168ee7c6486Stsutsui	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
169ee7c6486Stsutsui
170ee7c6486Stsutsui	    InitPointerDeviceStruct(pMouse, map, 3, btn_labels,
171ee7c6486Stsutsui		sunMouseCtrl, GetMotionHistorySize(),
172ee7c6486Stsutsui		2, axes_labels);
173d8389a6eStsutsui
174d8389a6eStsutsui	    /* X valuator */
175d8389a6eStsutsui	    InitValuatorAxisStruct(device, 0, axes_labels[0],
176d8389a6eStsutsui		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
177d8389a6eStsutsui            device->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
178d8389a6eStsutsui            device->last.valuators[0] = device->valuator->axisVal[0];
179d8389a6eStsutsui
180d8389a6eStsutsui	    /* Y valuator */
181d8389a6eStsutsui	    InitValuatorAxisStruct(device, 1, axes_labels[1],
182d8389a6eStsutsui		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
183d8389a6eStsutsui            device->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
184d8389a6eStsutsui            device->last.valuators[1] = device->valuator->axisVal[1];
185d8389a6eStsutsui
186ee7c6486Stsutsui	    break;
187ee7c6486Stsutsui
188ee7c6486Stsutsui	case DEVICE_ON:
18948c4760eStsutsui	    pPriv = (sunPtrPrivPtr)pMouse->devicePrivate;
19048c4760eStsutsui	    if (ioctl (pPriv->fd, VUIDGFORMAT, &oformat) == -1) {
1919c576acfStsutsui		ErrorF("sunMouseProc ioctl VUIDGFORMAT\n");
192ee7c6486Stsutsui		return !Success;
193ee7c6486Stsutsui	    }
194ee7c6486Stsutsui	    format = VUID_FIRM_EVENT;
19548c4760eStsutsui	    if (ioctl (pPriv->fd, VUIDSFORMAT, &format) == -1) {
1969c576acfStsutsui		ErrorF("sunMouseProc ioctl VUIDSFORMAT\n");
197ee7c6486Stsutsui		return !Success;
198ee7c6486Stsutsui	    }
199177290dfStsutsui
20048c4760eStsutsui	    if (fcntl(pPriv->fd, F_SETFL, O_NONBLOCK) == -1) {
201177290dfStsutsui		ErrorF("Non-blocking mouse I/O failed");
202177290dfStsutsui		return !Success;
203177290dfStsutsui	    }
20448c4760eStsutsui	    SetNotifyFd(pPriv->fd, sunMouseEvents, X_NOTIFY_READ, device);
205177290dfStsutsui
206177290dfStsutsui	    pPriv->bmask = 0;
207ee7c6486Stsutsui	    pMouse->on = TRUE;
208ee7c6486Stsutsui	    break;
209ee7c6486Stsutsui
210ee7c6486Stsutsui	case DEVICE_CLOSE:
21148c4760eStsutsui	    pPriv = (sunPtrPrivPtr)pMouse->devicePrivate;
21248c4760eStsutsui	    if (ioctl (pPriv->fd, VUIDSFORMAT, &oformat) == -1)
2139c576acfStsutsui		ErrorF("sunMouseProc ioctl VUIDSFORMAT\n");
21448c4760eStsutsui	    pMouse->on = FALSE;
215ee7c6486Stsutsui	    break;
216ee7c6486Stsutsui
217ee7c6486Stsutsui	case DEVICE_OFF:
21848c4760eStsutsui	    pPriv = (sunPtrPrivPtr)pMouse->devicePrivate;
21948c4760eStsutsui	    RemoveNotifyFd(pPriv->fd);
220ee7c6486Stsutsui	    pMouse->on = FALSE;
221ee7c6486Stsutsui	    break;
2222aa2a51fStsutsui
2232aa2a51fStsutsui	case DEVICE_ABORT:
2242aa2a51fStsutsui	    break;
225ee7c6486Stsutsui    }
226ee7c6486Stsutsui    return Success;
227ee7c6486Stsutsui}
228ee7c6486Stsutsui
229ee7c6486Stsutsui/*-
230ee7c6486Stsutsui *-----------------------------------------------------------------------
231ee7c6486Stsutsui * sunMouseGetEvents --
232ee7c6486Stsutsui *	Return the events waiting in the wings for the given mouse.
233ee7c6486Stsutsui *
234ee7c6486Stsutsui * Results:
235ee7c6486Stsutsui *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
236ee7c6486Stsutsui *	The number of events contained in the array.
237ee7c6486Stsutsui *	A boolean as to whether more events might be available.
238ee7c6486Stsutsui *
239ee7c6486Stsutsui * Side Effects:
240ee7c6486Stsutsui *	None.
241ee7c6486Stsutsui *-----------------------------------------------------------------------
242ee7c6486Stsutsui */
243ee7c6486Stsutsui
244177290dfStsutsuistatic Firm_event *
245ee7c6486StsutsuisunMouseGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain)
246ee7c6486Stsutsui{
247ee7c6486Stsutsui    int	    	  nBytes;	    /* number of bytes of events available. */
248ee7c6486Stsutsui    static Firm_event	evBuf[SUN_MAXEVENTS];   /* Buffer for Firm_events */
249ee7c6486Stsutsui
250ee7c6486Stsutsui    if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) {
251ee7c6486Stsutsui	if (errno == EWOULDBLOCK) {
252ee7c6486Stsutsui	    *pNumEvents = 0;
253ee7c6486Stsutsui	    *pAgain = FALSE;
254ee7c6486Stsutsui	} else {
2559c576acfStsutsui	    ErrorF("sunMouseGetEvents read\n");
256ee7c6486Stsutsui	    FatalError ("Could not read from mouse");
257ee7c6486Stsutsui	}
258ee7c6486Stsutsui    } else {
259ee7c6486Stsutsui	if (on) {
260ee7c6486Stsutsui	    *pNumEvents = nBytes / sizeof (Firm_event);
261ee7c6486Stsutsui	    *pAgain = (nBytes == sizeof (evBuf));
262ee7c6486Stsutsui	} else {
263ee7c6486Stsutsui	    *pNumEvents = 0;
264ee7c6486Stsutsui	    *pAgain = FALSE;
265ee7c6486Stsutsui	}
266ee7c6486Stsutsui    }
267ee7c6486Stsutsui    return evBuf;
268ee7c6486Stsutsui}
269ee7c6486Stsutsui
270ee7c6486Stsutsui
271ee7c6486Stsutsui/*-
272ee7c6486Stsutsui *-----------------------------------------------------------------------
273ee7c6486Stsutsui * sunMouseEnqueueEvent --
274ee7c6486Stsutsui *	Given a Firm_event for a mouse, pass it off the the dix layer
275ee7c6486Stsutsui *	properly converted...
276ee7c6486Stsutsui *
277ee7c6486Stsutsui * Results:
278ee7c6486Stsutsui *	None.
279ee7c6486Stsutsui *
280ee7c6486Stsutsui * Side Effects:
281ee7c6486Stsutsui *	The cursor may be redrawn...? devPrivate/x/y will be altered.
282ee7c6486Stsutsui *
283ee7c6486Stsutsui *-----------------------------------------------------------------------
284ee7c6486Stsutsui */
285ee7c6486Stsutsui
286177290dfStsutsuistatic void
287ee7c6486StsutsuisunMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
288ee7c6486Stsutsui{
289ee7c6486Stsutsui    sunPtrPrivPtr	pPriv;	/* Private data for pointer */
290ee7c6486Stsutsui    int			bmask;	/* Temporary button mask */
291ee7c6486Stsutsui    int			x, y;
292ee7c6486Stsutsui    double		tmpx, tmpy;
293ee7c6486Stsutsui    int			type, buttons, flag;
294ee7c6486Stsutsui    int			valuators[2];
295ee7c6486Stsutsui    ValuatorMask	mask;
296ee7c6486Stsutsui
297ee7c6486Stsutsui    pPriv = (sunPtrPrivPtr)device->public.devicePrivate;
298ee7c6486Stsutsui
299ee7c6486Stsutsui    switch (fe->id) {
300ee7c6486Stsutsui    case MS_LEFT:
301ee7c6486Stsutsui    case MS_MIDDLE:
302ee7c6486Stsutsui    case MS_RIGHT:
303ee7c6486Stsutsui	/*
304ee7c6486Stsutsui	 * A button changed state. Sometimes we will get two events
305ee7c6486Stsutsui	 * for a single state change. Should we get a button event which
306ee7c6486Stsutsui	 * reflects the current state of affairs, that event is discarded.
307ee7c6486Stsutsui	 *
308ee7c6486Stsutsui	 * Mouse buttons start at 1.
309ee7c6486Stsutsui	 */
310ee7c6486Stsutsui	buttons = (fe->id - MS_LEFT) + 1;
311ee7c6486Stsutsui	bmask = 1 << buttons;
312ee7c6486Stsutsui	if (fe->value == VKEY_UP) {
313ee7c6486Stsutsui	    if (pPriv->bmask & bmask) {
314ee7c6486Stsutsui		type = ButtonRelease;
315ee7c6486Stsutsui		pPriv->bmask &= ~bmask;
316ee7c6486Stsutsui	    } else {
317ee7c6486Stsutsui		return;
318ee7c6486Stsutsui	    }
319ee7c6486Stsutsui	} else {
320ee7c6486Stsutsui	    if ((pPriv->bmask & bmask) == 0) {
321ee7c6486Stsutsui		type = ButtonPress;
322ee7c6486Stsutsui		pPriv->bmask |= bmask;
323ee7c6486Stsutsui	    } else {
324ee7c6486Stsutsui		return;
325ee7c6486Stsutsui	    }
326ee7c6486Stsutsui	}
327ee7c6486Stsutsui	flag = POINTER_RELATIVE;
32819d1127dStsutsui	valuator_mask_zero(&mask);
329ee7c6486Stsutsui	QueuePointerEvents(device, type, buttons, flag, &mask);
330ee7c6486Stsutsui	break;
331ee7c6486Stsutsui    case LOC_X_DELTA:
332ee7c6486Stsutsui	valuators[0] = fe->value;
333ee7c6486Stsutsui	valuators[1] = 0;
334ee7c6486Stsutsui	valuator_mask_set_range(&mask, 0, 2, valuators);
335ee7c6486Stsutsui	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
336ee7c6486Stsutsui	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
337ee7c6486Stsutsui	break;
338ee7c6486Stsutsui    case LOC_Y_DELTA:
339ee7c6486Stsutsui	/*
340ee7c6486Stsutsui	 * For some reason, motion up generates a positive y delta
341ee7c6486Stsutsui	 * and motion down a negative delta, so we must subtract
342ee7c6486Stsutsui	 * here instead of add...
343ee7c6486Stsutsui	 */
344ee7c6486Stsutsui	valuators[0] = 0;
345ee7c6486Stsutsui	valuators[1] = -fe->value;
346ee7c6486Stsutsui	valuator_mask_set_range(&mask, 0, 2, valuators);
347ee7c6486Stsutsui	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
348ee7c6486Stsutsui	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
349ee7c6486Stsutsui	break;
350ee7c6486Stsutsui    case LOC_X_ABSOLUTE:
351ee7c6486Stsutsui	miPointerGetPosition(device, &x, &y);
352ee7c6486Stsutsui	tmpx = fe->value;
353ee7c6486Stsutsui	tmpy = y;
354ee7c6486Stsutsui	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
355ee7c6486Stsutsui	break;
356ee7c6486Stsutsui    case LOC_Y_ABSOLUTE:
357ee7c6486Stsutsui	miPointerGetPosition(device, &x, &y);
358ee7c6486Stsutsui	tmpx = x;
359ee7c6486Stsutsui	tmpy = fe->value;
360ee7c6486Stsutsui	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
361ee7c6486Stsutsui	break;
362ee7c6486Stsutsui    default:
363ee7c6486Stsutsui	FatalError ("sunMouseEnqueueEvent: unrecognized id\n");
364ee7c6486Stsutsui	break;
365ee7c6486Stsutsui    }
366ee7c6486Stsutsui}
367ee7c6486Stsutsui
368ee7c6486Stsutsui/*ARGSUSED*/
369ee7c6486Stsutsuistatic Bool
370ee7c6486StsutsuisunCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
371ee7c6486Stsutsui{
372ee7c6486Stsutsui    int	    index, ret = FALSE;
373ee7c6486Stsutsui    DeviceIntPtr device = sunPointerDevice;	/* XXX */
374ee7c6486Stsutsui
375ee7c6486Stsutsui    if (device && PointerConfinedToScreen(device))
376ee7c6486Stsutsui	return TRUE;
377ee7c6486Stsutsui    /*
378ee7c6486Stsutsui     * Active Zaphod implementation:
379ee7c6486Stsutsui     *    increment or decrement the current screen
380ee7c6486Stsutsui     *    if the x is to the right or the left of
381ee7c6486Stsutsui     *    the current screen.
382ee7c6486Stsutsui     */
383ee7c6486Stsutsui    if (sunActiveZaphod &&
384ee7c6486Stsutsui	screenInfo.numScreens > 1 && (*x >= (*pScreen)->width || *x < 0)) {
385ee7c6486Stsutsui	index = (*pScreen)->myNum;
386ee7c6486Stsutsui	if (*x < 0) {
387ee7c6486Stsutsui	    index = (index ? index : screenInfo.numScreens) - 1;
388ee7c6486Stsutsui	    *pScreen = screenInfo.screens[index];
389ee7c6486Stsutsui	    *x += (*pScreen)->width;
390ee7c6486Stsutsui	} else {
391ee7c6486Stsutsui	    *x -= (*pScreen)->width;
392ee7c6486Stsutsui	    index = (index + 1) % screenInfo.numScreens;
393ee7c6486Stsutsui	    *pScreen = screenInfo.screens[index];
394ee7c6486Stsutsui	}
395ee7c6486Stsutsui	ret = TRUE;
396ee7c6486Stsutsui    }
397ee7c6486Stsutsui    return ret;
398ee7c6486Stsutsui}
399ee7c6486Stsutsui
400ee7c6486Stsutsuistatic void
401ee7c6486StsutsuisunCrossScreen(ScreenPtr pScreen, int entering)
402ee7c6486Stsutsui{
403ee7c6486Stsutsui    if (sunFbs[pScreen->myNum].EnterLeave)
404ee7c6486Stsutsui	(*sunFbs[pScreen->myNum].EnterLeave) (pScreen, entering ? 0 : 1);
405ee7c6486Stsutsui}
406ee7c6486Stsutsui
407ee7c6486Stsutsuistatic void
408ee7c6486StsutsuisunWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
409ee7c6486Stsutsui{
4101406604bStsutsui    input_lock();
411ee7c6486Stsutsui    miPointerWarpCursor (pDev, pScreen, x, y);
4121406604bStsutsui    input_unlock();
413ee7c6486Stsutsui}
414