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
642da8aa69Stsutsui/*
652da8aa69Stsutsui * Data private to any sun pointer device.
662da8aa69Stsutsui */
672da8aa69Stsutsuitypedef struct {
682da8aa69Stsutsui    int		fd;
692da8aa69Stsutsui    int		bmask;		/* last known button state */
702da8aa69Stsutsui    int		oformat;	/* saved value of VUIDGFORMAT */
71e83940e6Stsutsui    Firm_event	evbuf[SUN_MAXEVENTS];	/* Buffer for Firm_events */
722da8aa69Stsutsui} sunPtrPrivRec, *sunPtrPrivPtr;
732da8aa69Stsutsui
74ee7c6486StsutsuiBool sunActiveZaphod = TRUE;
75ee7c6486StsutsuiDeviceIntPtr sunPointerDevice = NULL;
76ee7c6486Stsutsui
77177290dfStsutsuistatic void sunMouseEvents(int, int, void *);
788931864aStsutsuistatic void sunMouseCtrl(DeviceIntPtr, PtrCtrl *);
79e83940e6Stsutsuistatic int sunMouseGetEvents(DeviceIntPtr);
80177290dfStsutsuistatic void sunMouseEnqueueEvent(DeviceIntPtr, Firm_event *);
81ee7c6486Stsutsuistatic Bool sunCursorOffScreen(ScreenPtr *, int *, int *);
82ee7c6486Stsutsuistatic void sunCrossScreen(ScreenPtr, int);
83ee7c6486Stsutsuistatic void sunWarpCursor(DeviceIntPtr, ScreenPtr, int, int);
84ee7c6486Stsutsui
85ee7c6486StsutsuimiPointerScreenFuncRec sunPointerScreenFuncs = {
86ee7c6486Stsutsui    sunCursorOffScreen,
87ee7c6486Stsutsui    sunCrossScreen,
88ee7c6486Stsutsui    sunWarpCursor,
89ee7c6486Stsutsui};
90ee7c6486Stsutsui
91ee7c6486Stsutsuistatic void
92177290dfStsutsuisunMouseEvents(int fd, int ready, void *data)
93ee7c6486Stsutsui{
94e83940e6Stsutsui    int i, numEvents;
95177290dfStsutsui    DeviceIntPtr device = (DeviceIntPtr)data;
96e83940e6Stsutsui    DevicePtr pMouse = &device->public;
97e83940e6Stsutsui    sunPtrPrivPtr pPriv = pMouse->devicePrivate;
98177290dfStsutsui
99177290dfStsutsui    input_lock();
100177290dfStsutsui
101177290dfStsutsui    do {
102e83940e6Stsutsui	numEvents = sunMouseGetEvents(device);
103177290dfStsutsui	for (i = 0; i < numEvents; i++) {
104e83940e6Stsutsui	    sunMouseEnqueueEvent(device, &pPriv->evbuf[i]);
105177290dfStsutsui	}
106e83940e6Stsutsui    } while (numEvents == SUN_MAXEVENTS);
107177290dfStsutsui
108177290dfStsutsui    input_unlock();
109ee7c6486Stsutsui}
110ee7c6486Stsutsui
111ee7c6486Stsutsui/*-
112ee7c6486Stsutsui *-----------------------------------------------------------------------
113ee7c6486Stsutsui * sunMouseCtrl --
114ee7c6486Stsutsui *	Alter the control parameters for the mouse. Since acceleration
115ee7c6486Stsutsui *	etc. is done from the PtrCtrl record in the mouse's device record,
116ee7c6486Stsutsui *	there's nothing to do here.
117ee7c6486Stsutsui *
118ee7c6486Stsutsui * Results:
119ee7c6486Stsutsui *	None.
120ee7c6486Stsutsui *
121ee7c6486Stsutsui * Side Effects:
122ee7c6486Stsutsui *	None.
123ee7c6486Stsutsui *
124ee7c6486Stsutsui *-----------------------------------------------------------------------
125ee7c6486Stsutsui */
126ee7c6486Stsutsui/*ARGSUSED*/
127ee7c6486Stsutsuistatic void
128ee7c6486StsutsuisunMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
129ee7c6486Stsutsui{
130ee7c6486Stsutsui}
131ee7c6486Stsutsui
132ee7c6486Stsutsui/*-
133ee7c6486Stsutsui *-----------------------------------------------------------------------
134ee7c6486Stsutsui * sunMouseProc --
135ee7c6486Stsutsui *	Handle the initialization, etc. of a mouse
136ee7c6486Stsutsui *
137ee7c6486Stsutsui * Results:
138ee7c6486Stsutsui *	none.
139ee7c6486Stsutsui *
140ee7c6486Stsutsui * Side Effects:
141ee7c6486Stsutsui *
142ee7c6486Stsutsui * Note:
143ee7c6486Stsutsui *	When using sunwindows, all input comes off a single fd, stored in the
144ee7c6486Stsutsui *	global windowFd.  Therefore, only one device should be enabled and
145ee7c6486Stsutsui *	disabled, even though the application still sees both mouse and
146ee7c6486Stsutsui *	keyboard.  We have arbitrarily chosen to enable and disable windowFd
147ee7c6486Stsutsui *	in the keyboard routine sunKbdProc rather than in sunMouseProc.
148ee7c6486Stsutsui *
149ee7c6486Stsutsui *-----------------------------------------------------------------------
150ee7c6486Stsutsui */
151ee7c6486Stsutsuiint
152ee7c6486StsutsuisunMouseProc(DeviceIntPtr device, int what)
153ee7c6486Stsutsui{
1549679a91bStsutsui    DevicePtr	  pMouse = &device->public;
15548c4760eStsutsui    sunPtrPrivPtr pPriv;
156ee7c6486Stsutsui    int	    	  format;
157ee7c6486Stsutsui    BYTE    	  map[4];
158ee7c6486Stsutsui    Atom btn_labels[3] = {0};
159ee7c6486Stsutsui    Atom axes_labels[2] = { 0, 0 };
160ee7c6486Stsutsui
161ee7c6486Stsutsui    switch (what) {
162ee7c6486Stsutsui	case DEVICE_INIT:
1632da8aa69Stsutsui	    pPriv = malloc(sizeof(*pPriv));
1642da8aa69Stsutsui	    if (pPriv == NULL) {
1652da8aa69Stsutsui		LogMessage(X_ERROR, "Cannot allocate private data for mouse\n");
166ee7c6486Stsutsui		return !Success;
167ee7c6486Stsutsui	    }
1682da8aa69Stsutsui	    pPriv->fd = open("/dev/mouse", O_RDWR | O_NONBLOCK, 0);
1692da8aa69Stsutsui	    if (pPriv->fd < 0) {
1702da8aa69Stsutsui		LogMessage(X_ERROR, "Cannot open /dev/mouse, error %d\n",
1712da8aa69Stsutsui		    errno);
1722da8aa69Stsutsui		free(pPriv);
173ee7c6486Stsutsui		return !Success;
1742da8aa69Stsutsui	    }
1752da8aa69Stsutsui	    pPriv->bmask = 0;
1762da8aa69Stsutsui	    pPriv->oformat = 0;
1772da8aa69Stsutsui	    pMouse->devicePrivate = pPriv;
178ee7c6486Stsutsui	    pMouse->on = FALSE;
1792da8aa69Stsutsui
180ee7c6486Stsutsui	    map[1] = 1;
181ee7c6486Stsutsui	    map[2] = 2;
182ee7c6486Stsutsui	    map[3] = 3;
183ee7c6486Stsutsui	    btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
184ee7c6486Stsutsui	    btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
185ee7c6486Stsutsui	    btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
186ee7c6486Stsutsui	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
187ee7c6486Stsutsui	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
188ee7c6486Stsutsui
189ee7c6486Stsutsui	    InitPointerDeviceStruct(pMouse, map, 3, btn_labels,
190ee7c6486Stsutsui		sunMouseCtrl, GetMotionHistorySize(),
191ee7c6486Stsutsui		2, axes_labels);
192d8389a6eStsutsui
193d8389a6eStsutsui	    /* X valuator */
194d8389a6eStsutsui	    InitValuatorAxisStruct(device, 0, axes_labels[0],
195d8389a6eStsutsui		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
196d8389a6eStsutsui            device->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
197d8389a6eStsutsui            device->last.valuators[0] = device->valuator->axisVal[0];
198d8389a6eStsutsui
199d8389a6eStsutsui	    /* Y valuator */
200d8389a6eStsutsui	    InitValuatorAxisStruct(device, 1, axes_labels[1],
201d8389a6eStsutsui		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
202d8389a6eStsutsui            device->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
203d8389a6eStsutsui            device->last.valuators[1] = device->valuator->axisVal[1];
204d8389a6eStsutsui
205ee7c6486Stsutsui	    break;
206ee7c6486Stsutsui
207ee7c6486Stsutsui	case DEVICE_ON:
20848c4760eStsutsui	    pPriv = (sunPtrPrivPtr)pMouse->devicePrivate;
2092da8aa69Stsutsui	    if (ioctl(pPriv->fd, VUIDGFORMAT, &pPriv->oformat) == -1) {
2102da8aa69Stsutsui		LogMessage(X_ERROR, "sunMouseProc ioctl VUIDGFORMAT\n");
211ee7c6486Stsutsui		return !Success;
212ee7c6486Stsutsui	    }
213ee7c6486Stsutsui	    format = VUID_FIRM_EVENT;
2142da8aa69Stsutsui	    if (ioctl(pPriv->fd, VUIDSFORMAT, &format) == -1) {
2152da8aa69Stsutsui		LogMessage(X_ERROR, "sunMouseProc ioctl VUIDSFORMAT\n");
216ee7c6486Stsutsui		return !Success;
217ee7c6486Stsutsui	    }
218177290dfStsutsui
21948c4760eStsutsui	    SetNotifyFd(pPriv->fd, sunMouseEvents, X_NOTIFY_READ, device);
220177290dfStsutsui
221177290dfStsutsui	    pPriv->bmask = 0;
222ee7c6486Stsutsui	    pMouse->on = TRUE;
223ee7c6486Stsutsui	    break;
224ee7c6486Stsutsui
2252da8aa69Stsutsui	case DEVICE_OFF:
22648c4760eStsutsui	    pPriv = (sunPtrPrivPtr)pMouse->devicePrivate;
2272da8aa69Stsutsui	    RemoveNotifyFd(pPriv->fd);
2282da8aa69Stsutsui	    if (ioctl(pPriv->fd, VUIDSFORMAT, &pPriv->oformat) == -1)
2292da8aa69Stsutsui		LogMessage(X_ERROR, "sunMouseProc ioctl VUIDSFORMAT\n");
23048c4760eStsutsui	    pMouse->on = FALSE;
231ee7c6486Stsutsui	    break;
232ee7c6486Stsutsui
2332da8aa69Stsutsui	case DEVICE_CLOSE:
23448c4760eStsutsui	    pPriv = (sunPtrPrivPtr)pMouse->devicePrivate;
2352da8aa69Stsutsui	    close(pPriv->fd);
2362da8aa69Stsutsui	    free(pPriv);
2372da8aa69Stsutsui	    pMouse->devicePrivate = NULL;
238ee7c6486Stsutsui	    break;
2392aa2a51fStsutsui
2402aa2a51fStsutsui	case DEVICE_ABORT:
2412aa2a51fStsutsui	    break;
242ee7c6486Stsutsui    }
243ee7c6486Stsutsui    return Success;
244ee7c6486Stsutsui}
245ee7c6486Stsutsui
246ee7c6486Stsutsui/*-
247ee7c6486Stsutsui *-----------------------------------------------------------------------
248ee7c6486Stsutsui * sunMouseGetEvents --
249ee7c6486Stsutsui *	Return the events waiting in the wings for the given mouse.
250ee7c6486Stsutsui *
251ee7c6486Stsutsui * Results:
252e83940e6Stsutsui *      Update Firm_event buffer in DeviceIntPtr if events are received.
253e83940e6Stsutsui *      Return the number of received Firm_events in the buffer.
254ee7c6486Stsutsui *
255ee7c6486Stsutsui * Side Effects:
256ee7c6486Stsutsui *	None.
257ee7c6486Stsutsui *-----------------------------------------------------------------------
258ee7c6486Stsutsui */
259ee7c6486Stsutsui
260e83940e6Stsutsuistatic int
261e83940e6StsutsuisunMouseGetEvents(DeviceIntPtr device)
262ee7c6486Stsutsui{
263e83940e6Stsutsui    DevicePtr pMouse = &device->public;
264e83940e6Stsutsui    sunPtrPrivPtr pPriv = pMouse->devicePrivate;
265e83940e6Stsutsui    int nBytes;		    /* number of bytes of events available. */
266e83940e6Stsutsui    int NumEvents = 0;
267e83940e6Stsutsui
268e83940e6Stsutsui    nBytes = read(pPriv->fd, pPriv->evbuf, sizeof(pPriv->evbuf));
269e83940e6Stsutsui    if (nBytes == -1) {
270e83940e6Stsutsui	if (errno != EWOULDBLOCK) {
271e83940e6Stsutsui	    LogMessage(X_ERROR, "Unexpected error on reading mouse\n");
272e83940e6Stsutsui	    FatalError("Could not read from mouse");
273ee7c6486Stsutsui	}
274ee7c6486Stsutsui    } else {
2752eda485bStsutsui	NumEvents = nBytes / sizeof(pPriv->evbuf[0]);
276ee7c6486Stsutsui    }
277e83940e6Stsutsui    return NumEvents;
278ee7c6486Stsutsui}
279ee7c6486Stsutsui
280ee7c6486Stsutsui
281ee7c6486Stsutsui/*-
282ee7c6486Stsutsui *-----------------------------------------------------------------------
283ee7c6486Stsutsui * sunMouseEnqueueEvent --
284ee7c6486Stsutsui *	Given a Firm_event for a mouse, pass it off the the dix layer
285ee7c6486Stsutsui *	properly converted...
286ee7c6486Stsutsui *
287ee7c6486Stsutsui * Results:
288ee7c6486Stsutsui *	None.
289ee7c6486Stsutsui *
290ee7c6486Stsutsui * Side Effects:
291ee7c6486Stsutsui *	The cursor may be redrawn...? devPrivate/x/y will be altered.
292ee7c6486Stsutsui *
293ee7c6486Stsutsui *-----------------------------------------------------------------------
294ee7c6486Stsutsui */
295ee7c6486Stsutsui
296177290dfStsutsuistatic void
297ee7c6486StsutsuisunMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
298ee7c6486Stsutsui{
299ee7c6486Stsutsui    sunPtrPrivPtr	pPriv;	/* Private data for pointer */
300ee7c6486Stsutsui    int			bmask;	/* Temporary button mask */
301ee7c6486Stsutsui    int			x, y;
302ee7c6486Stsutsui    double		tmpx, tmpy;
303ee7c6486Stsutsui    int			type, buttons, flag;
304ee7c6486Stsutsui    int			valuators[2];
305ee7c6486Stsutsui    ValuatorMask	mask;
306ee7c6486Stsutsui
307ee7c6486Stsutsui    pPriv = (sunPtrPrivPtr)device->public.devicePrivate;
308ee7c6486Stsutsui
309ee7c6486Stsutsui    switch (fe->id) {
310ee7c6486Stsutsui    case MS_LEFT:
311ee7c6486Stsutsui    case MS_MIDDLE:
312ee7c6486Stsutsui    case MS_RIGHT:
313ee7c6486Stsutsui	/*
314ee7c6486Stsutsui	 * A button changed state. Sometimes we will get two events
315ee7c6486Stsutsui	 * for a single state change. Should we get a button event which
316ee7c6486Stsutsui	 * reflects the current state of affairs, that event is discarded.
317ee7c6486Stsutsui	 *
318ee7c6486Stsutsui	 * Mouse buttons start at 1.
319ee7c6486Stsutsui	 */
320ee7c6486Stsutsui	buttons = (fe->id - MS_LEFT) + 1;
321ee7c6486Stsutsui	bmask = 1 << buttons;
322ee7c6486Stsutsui	if (fe->value == VKEY_UP) {
323ee7c6486Stsutsui	    if (pPriv->bmask & bmask) {
324ee7c6486Stsutsui		type = ButtonRelease;
325ee7c6486Stsutsui		pPriv->bmask &= ~bmask;
326ee7c6486Stsutsui	    } else {
327ee7c6486Stsutsui		return;
328ee7c6486Stsutsui	    }
329ee7c6486Stsutsui	} else {
330ee7c6486Stsutsui	    if ((pPriv->bmask & bmask) == 0) {
331ee7c6486Stsutsui		type = ButtonPress;
332ee7c6486Stsutsui		pPriv->bmask |= bmask;
333ee7c6486Stsutsui	    } else {
334ee7c6486Stsutsui		return;
335ee7c6486Stsutsui	    }
336ee7c6486Stsutsui	}
337ee7c6486Stsutsui	flag = POINTER_RELATIVE;
33819d1127dStsutsui	valuator_mask_zero(&mask);
339ee7c6486Stsutsui	QueuePointerEvents(device, type, buttons, flag, &mask);
340ee7c6486Stsutsui	break;
341ee7c6486Stsutsui    case LOC_X_DELTA:
342ee7c6486Stsutsui	valuators[0] = fe->value;
343ee7c6486Stsutsui	valuators[1] = 0;
344ee7c6486Stsutsui	valuator_mask_set_range(&mask, 0, 2, valuators);
345ee7c6486Stsutsui	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
346ee7c6486Stsutsui	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
347ee7c6486Stsutsui	break;
348ee7c6486Stsutsui    case LOC_Y_DELTA:
349ee7c6486Stsutsui	/*
350ee7c6486Stsutsui	 * For some reason, motion up generates a positive y delta
351ee7c6486Stsutsui	 * and motion down a negative delta, so we must subtract
352ee7c6486Stsutsui	 * here instead of add...
353ee7c6486Stsutsui	 */
354ee7c6486Stsutsui	valuators[0] = 0;
355ee7c6486Stsutsui	valuators[1] = -fe->value;
356ee7c6486Stsutsui	valuator_mask_set_range(&mask, 0, 2, valuators);
357ee7c6486Stsutsui	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
358ee7c6486Stsutsui	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
359ee7c6486Stsutsui	break;
360ee7c6486Stsutsui    case LOC_X_ABSOLUTE:
361ee7c6486Stsutsui	miPointerGetPosition(device, &x, &y);
362ee7c6486Stsutsui	tmpx = fe->value;
363ee7c6486Stsutsui	tmpy = y;
364ee7c6486Stsutsui	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
365ee7c6486Stsutsui	break;
366ee7c6486Stsutsui    case LOC_Y_ABSOLUTE:
367ee7c6486Stsutsui	miPointerGetPosition(device, &x, &y);
368ee7c6486Stsutsui	tmpx = x;
369ee7c6486Stsutsui	tmpy = fe->value;
370ee7c6486Stsutsui	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
371ee7c6486Stsutsui	break;
372ee7c6486Stsutsui    default:
373ee7c6486Stsutsui	FatalError ("sunMouseEnqueueEvent: unrecognized id\n");
374ee7c6486Stsutsui	break;
375ee7c6486Stsutsui    }
376ee7c6486Stsutsui}
377ee7c6486Stsutsui
378ee7c6486Stsutsui/*ARGSUSED*/
379ee7c6486Stsutsuistatic Bool
380ee7c6486StsutsuisunCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
381ee7c6486Stsutsui{
382ee7c6486Stsutsui    int	    index, ret = FALSE;
383ee7c6486Stsutsui    DeviceIntPtr device = sunPointerDevice;	/* XXX */
384ee7c6486Stsutsui
385ee7c6486Stsutsui    if (device && PointerConfinedToScreen(device))
386ee7c6486Stsutsui	return TRUE;
387ee7c6486Stsutsui    /*
388ee7c6486Stsutsui     * Active Zaphod implementation:
389ee7c6486Stsutsui     *    increment or decrement the current screen
390ee7c6486Stsutsui     *    if the x is to the right or the left of
391ee7c6486Stsutsui     *    the current screen.
392ee7c6486Stsutsui     */
393ee7c6486Stsutsui    if (sunActiveZaphod &&
394ee7c6486Stsutsui	screenInfo.numScreens > 1 && (*x >= (*pScreen)->width || *x < 0)) {
395ee7c6486Stsutsui	index = (*pScreen)->myNum;
396ee7c6486Stsutsui	if (*x < 0) {
397ee7c6486Stsutsui	    index = (index ? index : screenInfo.numScreens) - 1;
398ee7c6486Stsutsui	    *pScreen = screenInfo.screens[index];
399ee7c6486Stsutsui	    *x += (*pScreen)->width;
400ee7c6486Stsutsui	} else {
401ee7c6486Stsutsui	    *x -= (*pScreen)->width;
402ee7c6486Stsutsui	    index = (index + 1) % screenInfo.numScreens;
403ee7c6486Stsutsui	    *pScreen = screenInfo.screens[index];
404ee7c6486Stsutsui	}
405ee7c6486Stsutsui	ret = TRUE;
406ee7c6486Stsutsui    }
407ee7c6486Stsutsui    return ret;
408ee7c6486Stsutsui}
409ee7c6486Stsutsui
410ee7c6486Stsutsuistatic void
411ee7c6486StsutsuisunCrossScreen(ScreenPtr pScreen, int entering)
412ee7c6486Stsutsui{
413ee7c6486Stsutsui    if (sunFbs[pScreen->myNum].EnterLeave)
414ee7c6486Stsutsui	(*sunFbs[pScreen->myNum].EnterLeave) (pScreen, entering ? 0 : 1);
415ee7c6486Stsutsui}
416ee7c6486Stsutsui
417ee7c6486Stsutsuistatic void
418ee7c6486StsutsuisunWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
419ee7c6486Stsutsui{
4201406604bStsutsui    input_lock();
421ee7c6486Stsutsui    miPointerWarpCursor (pDev, pScreen, x, y);
4221406604bStsutsui    input_unlock();
423ee7c6486Stsutsui}
424