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