sunMouse.c revision 85d6961b
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 Bool sunCursorOffScreen(ScreenPtr *, int *, int *);
68static void sunCrossScreen(ScreenPtr, int);
69static void sunWarpCursor(DeviceIntPtr, ScreenPtr, int, int);
70
71miPointerScreenFuncRec sunPointerScreenFuncs = {
72    sunCursorOffScreen,
73    sunCrossScreen,
74    sunWarpCursor,
75    NULL,
76    NULL,
77};
78
79/*-
80 *-----------------------------------------------------------------------
81 * sunMouseCtrl --
82 *	Alter the control parameters for the mouse. Since acceleration
83 *	etc. is done from the PtrCtrl record in the mouse's device record,
84 *	there's nothing to do here.
85 *
86 * Results:
87 *	None.
88 *
89 * Side Effects:
90 *	None.
91 *
92 *-----------------------------------------------------------------------
93 */
94/*ARGSUSED*/
95static void
96sunMouseCtrl(DeviceIntPtr device, PtrCtrl *ctrl)
97{
98}
99
100/*-
101 *-----------------------------------------------------------------------
102 * sunMouseProc --
103 *	Handle the initialization, etc. of a mouse
104 *
105 * Results:
106 *	none.
107 *
108 * Side Effects:
109 *
110 * Note:
111 *	When using sunwindows, all input comes off a single fd, stored in the
112 *	global windowFd.  Therefore, only one device should be enabled and
113 *	disabled, even though the application still sees both mouse and
114 *	keyboard.  We have arbitrarily chosen to enable and disable windowFd
115 *	in the keyboard routine sunKbdProc rather than in sunMouseProc.
116 *
117 *-----------------------------------------------------------------------
118 */
119int
120sunMouseProc(DeviceIntPtr device, int what)
121{
122    DevicePtr	  pMouse = &device->public;
123    int	    	  format;
124    static int	  oformat;
125    BYTE    	  map[4];
126    Atom btn_labels[3] = {0};
127    Atom axes_labels[2] = { 0, 0 };
128
129    switch (what) {
130	case DEVICE_INIT:
131	    if (pMouse != &sunPointerDevice->public) {
132		ErrorF ("Cannot open non-system mouse");
133		return !Success;
134	    }
135	    if (sunPtrPriv.fd == -1)
136		return !Success;
137	    pMouse->devicePrivate = (pointer) &sunPtrPriv;
138	    pMouse->on = FALSE;
139	    map[1] = 1;
140	    map[2] = 2;
141	    map[3] = 3;
142	    btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
143	    btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
144	    btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
145	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
146	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
147
148	    InitPointerDeviceStruct(pMouse, map, 3, btn_labels,
149		sunMouseCtrl, GetMotionHistorySize(),
150		2, axes_labels);
151	    break;
152
153	case DEVICE_ON:
154	    if (ioctl (sunPtrPriv.fd, VUIDGFORMAT, &oformat) == -1) {
155		Error ("sunMouseProc ioctl VUIDGFORMAT");
156		return !Success;
157	    }
158	    format = VUID_FIRM_EVENT;
159	    if (ioctl (sunPtrPriv.fd, VUIDSFORMAT, &format) == -1) {
160		Error ("sunMouseProc ioctl VUIDSFORMAT");
161		return !Success;
162	    }
163	    sunPtrPriv.bmask = 0;
164	    AddEnabledDevice (sunPtrPriv.fd);
165	    pMouse->on = TRUE;
166	    break;
167
168	case DEVICE_CLOSE:
169	    pMouse->on = FALSE;
170	    if (ioctl (sunPtrPriv.fd, VUIDSFORMAT, &oformat) == -1)
171		Error ("sunMouseProc ioctl VUIDSFORMAT");
172	    break;
173
174	case DEVICE_OFF:
175	    pMouse->on = FALSE;
176	    RemoveEnabledDevice (sunPtrPriv.fd);
177	    break;
178    }
179    return Success;
180}
181
182/*-
183 *-----------------------------------------------------------------------
184 * sunMouseGetEvents --
185 *	Return the events waiting in the wings for the given mouse.
186 *
187 * Results:
188 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
189 *	The number of events contained in the array.
190 *	A boolean as to whether more events might be available.
191 *
192 * Side Effects:
193 *	None.
194 *-----------------------------------------------------------------------
195 */
196
197Firm_event *
198sunMouseGetEvents(int fd, Bool on, int *pNumEvents, Bool *pAgain)
199{
200    int	    	  nBytes;	    /* number of bytes of events available. */
201    static Firm_event	evBuf[MAXEVENTS];   /* Buffer for Firm_events */
202
203    if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) {
204	if (errno == EWOULDBLOCK) {
205	    *pNumEvents = 0;
206	    *pAgain = FALSE;
207	} else {
208	    Error ("sunMouseGetEvents read");
209	    FatalError ("Could not read from mouse");
210	}
211    } else {
212	if (on) {
213	    *pNumEvents = nBytes / sizeof (Firm_event);
214	    *pAgain = (nBytes == sizeof (evBuf));
215	} else {
216	    *pNumEvents = 0;
217	    *pAgain = FALSE;
218	}
219    }
220    return evBuf;
221}
222
223
224/*-
225 *-----------------------------------------------------------------------
226 * sunMouseEnqueueEvent --
227 *	Given a Firm_event for a mouse, pass it off the the dix layer
228 *	properly converted...
229 *
230 * Results:
231 *	None.
232 *
233 * Side Effects:
234 *	The cursor may be redrawn...? devPrivate/x/y will be altered.
235 *
236 *-----------------------------------------------------------------------
237 */
238
239void
240sunMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
241{
242    sunPtrPrivPtr	pPriv;	/* Private data for pointer */
243    int			bmask;	/* Temporary button mask */
244    int			x, y;
245    int			type, buttons, flag;
246    int			i, nevents, valuators[2];
247    ValuatorMask	mask;
248
249    GetEventList(&sunEvents);
250
251    pPriv = (sunPtrPrivPtr)device->public.devicePrivate;
252
253    switch (fe->id) {
254    case MS_LEFT:
255    case MS_MIDDLE:
256    case MS_RIGHT:
257	/*
258	 * A button changed state. Sometimes we will get two events
259	 * for a single state change. Should we get a button event which
260	 * reflects the current state of affairs, that event is discarded.
261	 *
262	 * Mouse buttons start at 1.
263	 */
264	buttons = (fe->id - MS_LEFT) + 1;
265	bmask = 1 << buttons;
266	if (fe->value == VKEY_UP) {
267	    if (pPriv->bmask & bmask) {
268		type = ButtonRelease;
269		pPriv->bmask &= ~bmask;
270	    } else {
271		return;
272	    }
273	} else {
274	    if ((pPriv->bmask & bmask) == 0) {
275		type = ButtonPress;
276		pPriv->bmask |= bmask;
277	    } else {
278		return;
279	    }
280	}
281	flag = POINTER_RELATIVE;
282	valuator_mask_set_range(&mask, 0, 0, NULL);
283	nevents = GetPointerEvents(sunEvents, device,
284	    type, buttons, flag, &mask);
285	for (i = 0; i < nevents; i++)
286	    mieqEnqueue(device, (InternalEvent*)(sunEvents + i)->event);
287	break;
288    case LOC_X_DELTA:
289	valuators[0] = fe->value;
290	valuators[1] = 0;
291	valuator_mask_set_range(&mask, 0, 2, valuators);
292	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
293	nevents = GetPointerEvents(sunEvents, device,
294	    MotionNotify, 0, flag, &mask);
295	for (i = 0; i < nevents; i++)
296	    mieqEnqueue(device, (InternalEvent*)(sunEvents + i)->event);
297	break;
298    case LOC_Y_DELTA:
299	/*
300	 * For some reason, motion up generates a positive y delta
301	 * and motion down a negative delta, so we must subtract
302	 * here instead of add...
303	 */
304	valuators[0] = 0;
305	valuators[1] = -fe->value;
306	valuator_mask_set_range(&mask, 0, 2, valuators);
307	flag = POINTER_RELATIVE | POINTER_ACCELERATE;
308	nevents = GetPointerEvents(sunEvents, device,
309	    MotionNotify, 0, flag, &mask);
310	for (i = 0; i < nevents; i++)
311	    mieqEnqueue(device, (InternalEvent*)(sunEvents + i)->event);
312	break;
313    case LOC_X_ABSOLUTE:
314	miPointerGetPosition(device, &x, &y);
315	x = fe->value;
316	miPointerSetPosition(device, &x, &y);
317	break;
318    case LOC_Y_ABSOLUTE:
319	miPointerGetPosition(device, &x, &y);
320	y = fe->value;
321	miPointerSetPosition(device, &x, &y);
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#ifndef i386
372    sigset_t newsigmask;
373
374    (void) sigemptyset (&newsigmask);
375#ifdef SVR4
376    (void) sigaddset (&newsigmask, SIGPOLL);
377#else
378    (void) sigaddset (&newsigmask, SIGIO);
379#endif
380    (void) sigprocmask (SIG_BLOCK, &newsigmask, (sigset_t *)NULL);
381    miPointerWarpCursor (pDev, pScreen, x, y);
382    (void) sigprocmask (SIG_UNBLOCK, &newsigmask, (sigset_t *)NULL);
383#else
384    int oldmask;
385
386    oldmask = sigblock (sigmask (SIGIO));
387    miPointerWarpCursor (pDev, pScreen, x, y);
388    sigsetmask (oldmask);
389#endif
390}
391