sunMouse.c revision ee7c6486
1/* $Xorg: sunMouse.c,v 1.3 2000/08/17 19:48:32 cpqbld Exp $ */
2/*-
3 * Copyright 1987 by the Regents of the University of California
4 *
5 * Permission to use, copy, modify, and distribute this
6 * software and its documentation for any purpose and without
7 * fee is hereby granted, provided that the above copyright
8 * notice appear in all copies.  The University of California
9 * makes no representations about the suitability of this
10 * software for any purpose.  It is provided "as is" without
11 * express or implied warranty.
12 */
13
14/************************************************************
15Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
16
17                    All Rights Reserved
18
19Permission  to  use,  copy,  modify,  and  distribute   this
20software  and  its documentation for any purpose and without
21fee is hereby granted, provided that the above copyright no-
22tice  appear  in all copies and that both that copyright no-
23tice and this permission notice appear in  supporting  docu-
24mentation,  and  that the names of Sun or The Open Group
25not be used in advertising or publicity pertaining to
26distribution  of  the software  without specific prior
27written permission. Sun and The Open Group make no
28representations about the suitability of this software for
29any purpose. It is provided "as is" without any express or
30implied warranty.
31
32SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
33INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
34NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
35ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
36ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
37PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
38OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
39THE USE OR PERFORMANCE OF THIS SOFTWARE.
40
41********************************************************/
42/*
43 * Copyright 1991, 1992, 1993 Kaleb S. Keithley
44 *
45 * Permission to use, copy, modify, and distribute this
46 * software and its documentation for any purpose and without
47 * fee is hereby granted, provided that the above copyright
48 * notice appear in all copies.  Kaleb S. Keithley makes no
49 * representations about the suitability of this software for
50 * any purpose.  It is provided "as is" without express or
51 * implied warranty.
52 */
53/* $XFree86: xc/programs/Xserver/hw/sun/sunMouse.c,v 1.4 2003/11/17 22:20:36 dawes Exp $ */
54
55#define NEED_EVENTS
56#include    "sun.h"
57#include    "mi.h"
58#include    "cursor.h"
59#include    "input.h"
60#include    "inpututils.h"
61#include    "exevents.h"
62#include    "xserver-properties.h"
63
64Bool sunActiveZaphod = TRUE;
65DeviceIntPtr sunPointerDevice = NULL;
66
67static void sunMouseHandlerNotify(int, int, void *);
68static Bool sunCursorOffScreen(ScreenPtr *, int *, int *);
69static void sunCrossScreen(ScreenPtr, int);
70static void sunWarpCursor(DeviceIntPtr, ScreenPtr, int, int);
71
72miPointerScreenFuncRec sunPointerScreenFuncs = {
73    sunCursorOffScreen,
74    sunCrossScreen,
75    sunWarpCursor,
76};
77
78static void
79sunMouseHandlerNotify(int fd __unused, int ready __unused, void *data __unused)
80{
81}
82
83/*-
84 *-----------------------------------------------------------------------
85 * sunMouseCtrl --
86 *	Alter the control parameters for the mouse. Since acceleration
87 *	etc. is done from the PtrCtrl record in the mouse's device record,
88 *	there's nothing to do here.
89 *
90 * Results:
91 *	None.
92 *
93 * Side Effects:
94 *	None.
95 *
96 *-----------------------------------------------------------------------
97 */
98/*ARGSUSED*/
99static void
100sunMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
101{
102}
103
104/*-
105 *-----------------------------------------------------------------------
106 * sunMouseProc --
107 *	Handle the initialization, etc. of a mouse
108 *
109 * Results:
110 *	none.
111 *
112 * Side Effects:
113 *
114 * Note:
115 *	When using sunwindows, all input comes off a single fd, stored in the
116 *	global windowFd.  Therefore, only one device should be enabled and
117 *	disabled, even though the application still sees both mouse and
118 *	keyboard.  We have arbitrarily chosen to enable and disable windowFd
119 *	in the keyboard routine sunKbdProc rather than in sunMouseProc.
120 *
121 *-----------------------------------------------------------------------
122 */
123int
124sunMouseProc(DeviceIntPtr device, int what)
125{
126    DevicePtr	  pMouse = (DevicePtr) device;
127    int	    	  format;
128    static int	  oformat;
129    BYTE    	  map[4];
130    Atom btn_labels[3] = {0};
131    Atom axes_labels[2] = { 0, 0 };
132
133    switch (what) {
134	case DEVICE_INIT:
135	    if (pMouse != (DevicePtr)sunPointerDevice) {
136		ErrorF ("Cannot open non-system mouse");
137		return !Success;
138	    }
139	    if (sunPtrPriv.fd == -1)
140		return !Success;
141	    pMouse->devicePrivate = (void *) &sunPtrPriv;
142	    pMouse->on = FALSE;
143	    map[1] = 1;
144	    map[2] = 2;
145	    map[3] = 3;
146	    btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
147	    btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
148	    btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
149	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
150	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
151
152	    InitPointerDeviceStruct(pMouse, map, 3, btn_labels,
153		sunMouseCtrl, GetMotionHistorySize(),
154		2, axes_labels);
155	    break;
156
157	case DEVICE_ON:
158	    if (ioctl (sunPtrPriv.fd, VUIDGFORMAT, &oformat) == -1) {
159		ErrorF("sunMouseProc ioctl VUIDGFORMAT");
160		return !Success;
161	    }
162	    format = VUID_FIRM_EVENT;
163	    if (ioctl (sunPtrPriv.fd, VUIDSFORMAT, &format) == -1) {
164		ErrorF("sunMouseProc ioctl VUIDSFORMAT");
165		return !Success;
166	    }
167	    sunPtrPriv.bmask = 0;
168	    SetNotifyFd(sunPtrPriv.fd, sunMouseHandlerNotify,
169		X_NOTIFY_READ, NULL);
170	    pMouse->on = TRUE;
171	    break;
172
173	case DEVICE_CLOSE:
174	    pMouse->on = FALSE;
175	    if (ioctl (sunPtrPriv.fd, VUIDSFORMAT, &oformat) == -1)
176		ErrorF("sunMouseProc ioctl VUIDSFORMAT");
177	    break;
178
179	case DEVICE_OFF:
180	    pMouse->on = FALSE;
181	    RemoveNotifyFd(sunPtrPriv.fd);
182	    break;
183    }
184    return Success;
185}
186
187/*-
188 *-----------------------------------------------------------------------
189 * sunMouseGetEvents --
190 *	Return the events waiting in the wings for the given mouse.
191 *
192 * Results:
193 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
194 *	The number of events contained in the array.
195 *	A boolean as to whether more events might be available.
196 *
197 * Side Effects:
198 *	None.
199 *-----------------------------------------------------------------------
200 */
201
202Firm_event *
203sunMouseGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain)
204{
205    int	    	  nBytes;	    /* number of bytes of events available. */
206    static Firm_event	evBuf[SUN_MAXEVENTS];   /* Buffer for Firm_events */
207
208    if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) {
209	if (errno == EWOULDBLOCK) {
210	    *pNumEvents = 0;
211	    *pAgain = FALSE;
212	} else {
213	    ErrorF("sunMouseGetEvents read");
214	    FatalError ("Could not read from mouse");
215	}
216    } else {
217	if (on) {
218	    *pNumEvents = nBytes / sizeof (Firm_event);
219	    *pAgain = (nBytes == sizeof (evBuf));
220	} else {
221	    *pNumEvents = 0;
222	    *pAgain = FALSE;
223	}
224    }
225    return evBuf;
226}
227
228
229/*-
230 *-----------------------------------------------------------------------
231 * sunMouseEnqueueEvent --
232 *	Given a Firm_event for a mouse, pass it off the the dix layer
233 *	properly converted...
234 *
235 * Results:
236 *	None.
237 *
238 * Side Effects:
239 *	The cursor may be redrawn...? devPrivate/x/y will be altered.
240 *
241 *-----------------------------------------------------------------------
242 */
243
244void
245sunMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
246{
247    sunPtrPrivPtr	pPriv;	/* Private data for pointer */
248    int			bmask;	/* Temporary button mask */
249    int			x, y;
250    double		tmpx, tmpy;
251    int			type, buttons, flag;
252    int			valuators[2];
253    ValuatorMask	mask;
254
255    pPriv = (sunPtrPrivPtr)device->public.devicePrivate;
256
257    switch (fe->id) {
258    case MS_LEFT:
259    case MS_MIDDLE:
260    case MS_RIGHT:
261	/*
262	 * A button changed state. Sometimes we will get two events
263	 * for a single state change. Should we get a button event which
264	 * reflects the current state of affairs, that event is discarded.
265	 *
266	 * Mouse buttons start at 1.
267	 */
268	buttons = (fe->id - MS_LEFT) + 1;
269	bmask = 1 << buttons;
270	if (fe->value == VKEY_UP) {
271	    if (pPriv->bmask & bmask) {
272		type = ButtonRelease;
273		pPriv->bmask &= ~bmask;
274	    } else {
275		return;
276	    }
277	} else {
278	    if ((pPriv->bmask & bmask) == 0) {
279		type = ButtonPress;
280		pPriv->bmask |= bmask;
281	    } else {
282		return;
283	    }
284	}
285	flag = POINTER_RELATIVE;
286	valuator_mask_set_range(&mask, 0, 0, NULL);
287	QueuePointerEvents(device, type, buttons, flag, &mask);
288	break;
289    case LOC_X_DELTA:
290	valuators[0] = fe->value;
291	valuators[1] = 0;
292	valuator_mask_set_range(&mask, 0, 2, valuators);
293	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
294	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
295	break;
296    case LOC_Y_DELTA:
297	/*
298	 * For some reason, motion up generates a positive y delta
299	 * and motion down a negative delta, so we must subtract
300	 * here instead of add...
301	 */
302	valuators[0] = 0;
303	valuators[1] = -fe->value;
304	valuator_mask_set_range(&mask, 0, 2, valuators);
305	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
306	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
307	break;
308    case LOC_X_ABSOLUTE:
309	miPointerGetPosition(device, &x, &y);
310	tmpx = fe->value;
311	tmpy = y;
312	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
313	break;
314    case LOC_Y_ABSOLUTE:
315	miPointerGetPosition(device, &x, &y);
316	tmpx = x;
317	tmpy = fe->value;
318	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
319	break;
320    default:
321	FatalError ("sunMouseEnqueueEvent: unrecognized id\n");
322	break;
323    }
324}
325
326/*ARGSUSED*/
327static Bool
328sunCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
329{
330    int	    index, ret = FALSE;
331    DeviceIntPtr device = sunPointerDevice;	/* XXX */
332
333    if (device && PointerConfinedToScreen(device))
334	return TRUE;
335    /*
336     * Active Zaphod implementation:
337     *    increment or decrement the current screen
338     *    if the x is to the right or the left of
339     *    the current screen.
340     */
341    if (sunActiveZaphod &&
342	screenInfo.numScreens > 1 && (*x >= (*pScreen)->width || *x < 0)) {
343	index = (*pScreen)->myNum;
344	if (*x < 0) {
345	    index = (index ? index : screenInfo.numScreens) - 1;
346	    *pScreen = screenInfo.screens[index];
347	    *x += (*pScreen)->width;
348	} else {
349	    *x -= (*pScreen)->width;
350	    index = (index + 1) % screenInfo.numScreens;
351	    *pScreen = screenInfo.screens[index];
352	}
353	ret = TRUE;
354    }
355    return ret;
356}
357
358static void
359sunCrossScreen(ScreenPtr pScreen, int entering)
360{
361    if (sunFbs[pScreen->myNum].EnterLeave)
362	(*sunFbs[pScreen->myNum].EnterLeave) (pScreen, entering ? 0 : 1);
363}
364
365static void
366sunWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
367{
368#ifndef i386
369    sigset_t newsigmask;
370
371    (void) sigemptyset (&newsigmask);
372#ifdef SVR4
373    (void) sigaddset (&newsigmask, SIGPOLL);
374#else
375    (void) sigaddset (&newsigmask, SIGIO);
376#endif
377    (void) sigprocmask (SIG_BLOCK, &newsigmask, NULL);
378    miPointerWarpCursor (pDev, pScreen, x, y);
379    (void) sigprocmask (SIG_UNBLOCK, &newsigmask, NULL);
380#else
381    int oldmask;
382
383    oldmask = sigblock (sigmask (SIGIO));
384    miPointerWarpCursor (pDev, pScreen, x, y);
385    sigsetmask (oldmask);
386#endif
387}
388