sunMouse.c revision 1406604b
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 = &device->public;
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 != &sunPointerDevice->public) {
136		ErrorF ("Cannot open non-system mouse\n");
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\n");
160		return !Success;
161	    }
162	    format = VUID_FIRM_EVENT;
163	    if (ioctl (sunPtrPriv.fd, VUIDSFORMAT, &format) == -1) {
164		ErrorF("sunMouseProc ioctl VUIDSFORMAT\n");
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\n");
177	    break;
178
179	case DEVICE_OFF:
180	    pMouse->on = FALSE;
181	    RemoveNotifyFd(sunPtrPriv.fd);
182	    break;
183
184	case DEVICE_ABORT:
185	    break;
186    }
187    return Success;
188}
189
190/*-
191 *-----------------------------------------------------------------------
192 * sunMouseGetEvents --
193 *	Return the events waiting in the wings for the given mouse.
194 *
195 * Results:
196 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
197 *	The number of events contained in the array.
198 *	A boolean as to whether more events might be available.
199 *
200 * Side Effects:
201 *	None.
202 *-----------------------------------------------------------------------
203 */
204
205Firm_event *
206sunMouseGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain)
207{
208    int	    	  nBytes;	    /* number of bytes of events available. */
209    static Firm_event	evBuf[SUN_MAXEVENTS];   /* Buffer for Firm_events */
210
211    if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) {
212	if (errno == EWOULDBLOCK) {
213	    *pNumEvents = 0;
214	    *pAgain = FALSE;
215	} else {
216	    ErrorF("sunMouseGetEvents read\n");
217	    FatalError ("Could not read from mouse");
218	}
219    } else {
220	if (on) {
221	    *pNumEvents = nBytes / sizeof (Firm_event);
222	    *pAgain = (nBytes == sizeof (evBuf));
223	} else {
224	    *pNumEvents = 0;
225	    *pAgain = FALSE;
226	}
227    }
228    return evBuf;
229}
230
231
232/*-
233 *-----------------------------------------------------------------------
234 * sunMouseEnqueueEvent --
235 *	Given a Firm_event for a mouse, pass it off the the dix layer
236 *	properly converted...
237 *
238 * Results:
239 *	None.
240 *
241 * Side Effects:
242 *	The cursor may be redrawn...? devPrivate/x/y will be altered.
243 *
244 *-----------------------------------------------------------------------
245 */
246
247void
248sunMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
249{
250    sunPtrPrivPtr	pPriv;	/* Private data for pointer */
251    int			bmask;	/* Temporary button mask */
252    int			x, y;
253    double		tmpx, tmpy;
254    int			type, buttons, flag;
255    int			valuators[2];
256    ValuatorMask	mask;
257
258    pPriv = (sunPtrPrivPtr)device->public.devicePrivate;
259
260    switch (fe->id) {
261    case MS_LEFT:
262    case MS_MIDDLE:
263    case MS_RIGHT:
264	/*
265	 * A button changed state. Sometimes we will get two events
266	 * for a single state change. Should we get a button event which
267	 * reflects the current state of affairs, that event is discarded.
268	 *
269	 * Mouse buttons start at 1.
270	 */
271	buttons = (fe->id - MS_LEFT) + 1;
272	bmask = 1 << buttons;
273	if (fe->value == VKEY_UP) {
274	    if (pPriv->bmask & bmask) {
275		type = ButtonRelease;
276		pPriv->bmask &= ~bmask;
277	    } else {
278		return;
279	    }
280	} else {
281	    if ((pPriv->bmask & bmask) == 0) {
282		type = ButtonPress;
283		pPriv->bmask |= bmask;
284	    } else {
285		return;
286	    }
287	}
288	flag = POINTER_RELATIVE;
289	valuator_mask_zero(&mask);
290	QueuePointerEvents(device, type, buttons, flag, &mask);
291	break;
292    case LOC_X_DELTA:
293	valuators[0] = fe->value;
294	valuators[1] = 0;
295	valuator_mask_set_range(&mask, 0, 2, valuators);
296	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
297	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
298	break;
299    case LOC_Y_DELTA:
300	/*
301	 * For some reason, motion up generates a positive y delta
302	 * and motion down a negative delta, so we must subtract
303	 * here instead of add...
304	 */
305	valuators[0] = 0;
306	valuators[1] = -fe->value;
307	valuator_mask_set_range(&mask, 0, 2, valuators);
308	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
309	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
310	break;
311    case LOC_X_ABSOLUTE:
312	miPointerGetPosition(device, &x, &y);
313	tmpx = fe->value;
314	tmpy = y;
315	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
316	break;
317    case LOC_Y_ABSOLUTE:
318	miPointerGetPosition(device, &x, &y);
319	tmpx = x;
320	tmpy = fe->value;
321	miPointerSetPosition(device, Absolute, &tmpx, &tmpy, NULL, NULL);
322	break;
323    default:
324	FatalError ("sunMouseEnqueueEvent: unrecognized id\n");
325	break;
326    }
327}
328
329/*ARGSUSED*/
330static Bool
331sunCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
332{
333    int	    index, ret = FALSE;
334    DeviceIntPtr device = sunPointerDevice;	/* XXX */
335
336    if (device && PointerConfinedToScreen(device))
337	return TRUE;
338    /*
339     * Active Zaphod implementation:
340     *    increment or decrement the current screen
341     *    if the x is to the right or the left of
342     *    the current screen.
343     */
344    if (sunActiveZaphod &&
345	screenInfo.numScreens > 1 && (*x >= (*pScreen)->width || *x < 0)) {
346	index = (*pScreen)->myNum;
347	if (*x < 0) {
348	    index = (index ? index : screenInfo.numScreens) - 1;
349	    *pScreen = screenInfo.screens[index];
350	    *x += (*pScreen)->width;
351	} else {
352	    *x -= (*pScreen)->width;
353	    index = (index + 1) % screenInfo.numScreens;
354	    *pScreen = screenInfo.screens[index];
355	}
356	ret = TRUE;
357    }
358    return ret;
359}
360
361static void
362sunCrossScreen(ScreenPtr pScreen, int entering)
363{
364    if (sunFbs[pScreen->myNum].EnterLeave)
365	(*sunFbs[pScreen->myNum].EnterLeave) (pScreen, entering ? 0 : 1);
366}
367
368static void
369sunWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
370{
371    input_lock();
372    miPointerWarpCursor (pDev, pScreen, x, y);
373    input_unlock();
374}
375