|
|
1.1 root 1: /*-
2: * sunMouse.c --
3: * Functions for playing cat and mouse... sorry.
4: *
5: * Copyright (c) 1987 by the Regents of the University of California
6: *
7: * Permission to use, copy, modify, and distribute this
8: * software and its documentation for any purpose and without
9: * fee is hereby granted, provided that the above copyright
10: * notice appear in all copies. The University of California
11: * makes no representations about the suitability of this
12: * software for any purpose. It is provided "as is" without
13: * express or implied warranty.
14: *
15: *
16: */
17:
18: /************************************************************
19: Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
20:
21: All Rights Reserved
22:
23: Permission to use, copy, modify, and distribute this
24: software and its documentation for any purpose and without
25: fee is hereby granted, provided that the above copyright no-
26: tice appear in all copies and that both that copyright no-
27: tice and this permission notice appear in supporting docu-
28: mentation, and that the names of Sun or MIT not be used in
29: advertising or publicity pertaining to distribution of the
30: software without specific prior written permission. Sun and
31: M.I.T. make no representations about the suitability of this
32: software for any purpose. It is provided "as is" without any
33: express or implied warranty.
34:
35: SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
36: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
37: NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI-
38: ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
39: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
40: PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
41: OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
42: THE USE OR PERFORMANCE OF THIS SOFTWARE.
43:
44: ********************************************************/
45:
46: #ifndef lint
47: static char sccsid[] = "%W %G Copyright 1987 Sun Micro";
48: #endif
49:
50: #define NEED_EVENTS
51: #include "sun.h"
52:
53: typedef struct {
54: int bmask; /* Current button state */
55: Bool mouseMoved; /* Mouse has moved */
56: } SunMsPrivRec, *SunMsPrivPtr;
57:
58: static void sunMouseCtrl();
59: static int sunMouseGetMotionEvents();
60: static Firm_event *sunMouseGetEvents();
61: static void sunMouseProcessEvent();
62: static void sunMouseDoneEvents();
63:
64: static SunMsPrivRec sunMousePriv;
65: static PtrPrivRec sysMousePriv = {
66: -1, /* Descriptor to device */
67: sunMouseGetEvents, /* Function to read events */
68: sunMouseProcessEvent, /* Function to process an event */
69: sunMouseDoneEvents, /* When all the events have been */
70: /* handled, this function will be */
71: /* called. */
72: 0, /* Current X coordinate of pointer */
73: 0, /* Current Y coordinate */
74: NULL, /* Screen pointer is on */
75: (pointer)&sunMousePriv, /* Field private to device */
76: };
77:
78: /*-
79: *-----------------------------------------------------------------------
80: * sunMouseProc --
81: * Handle the initialization, etc. of a mouse
82: *
83: * Results:
84: * none.
85: *
86: * Side Effects:
87: *
88: * Note:
89: * When using sunwindows, all input comes off a single fd, stored in the
90: * global windowFd. Therefore, only one device should be enabled and
91: * disabled, even though the application still sees both mouse and
92: * keyboard. We have arbitrarily chosen to enable and disable windowFd
93: * in the keyboard routine sunKbdProc rather than in sunMouseProc.
94: *
95: *-----------------------------------------------------------------------
96: */
97: int
98: sunMouseProc (pMouse, what)
99: DevicePtr pMouse; /* Mouse to play with */
100: int what; /* What to do with it */
101: {
102: register int fd;
103: int format;
104: static int oformat;
105: BYTE map[4];
106:
107: switch (what) {
108: case DEVICE_INIT:
109: if (pMouse != LookupPointerDevice()) {
110: ErrorF ("Cannot open non-system mouse");
111: return (!Success);
112: }
113:
114: if (! sunUseSunWindows()) {
115: if (sysMousePriv.fd >= 0) {
116: fd = sysMousePriv.fd;
117: } else {
118: fd = open ("/dev/mouse", O_RDWR, 0);
119: if (fd < 0) {
120: Error ("Opening /dev/mouse");
121: return (!Success);
122: }
123: if (fcntl (fd, F_SETFL, (FNDELAY|FASYNC)) < 0
124: || fcntl(fd, F_SETOWN, getpid()) < 0) {
125: perror("sunMouseProc");
126: ErrorF("Can't set up mouse on fd %d\n", fd);
127: }
128:
129: sysMousePriv.fd = fd;
130: }
131: }
132:
133: sysMousePriv.pScreen = &screenInfo.screen[0];
134: sysMousePriv.x = sysMousePriv.pScreen->width / 2;
135: sysMousePriv.y = sysMousePriv.pScreen->height / 2;
136:
137: sunMousePriv.bmask = 0;
138: sunMousePriv.mouseMoved = FALSE;
139:
140: pMouse->devicePrivate = (pointer) &sysMousePriv;
141: pMouse->on = FALSE;
142: map[1] = 1;
143: map[2] = 2;
144: map[3] = 3;
145: InitPointerDeviceStruct(
146: pMouse, map, 3, sunMouseGetMotionEvents, sunMouseCtrl);
147: break;
148:
149: case DEVICE_ON:
150: if (! sunUseSunWindows()) {
151: if (ioctl (((PtrPrivPtr)pMouse->devicePrivate)->fd,
152: VUIDGFORMAT, &oformat) < 0) {
153: Error ("VUIDGFORMAT");
154: return(!Success);
155: }
156: format = VUID_FIRM_EVENT;
157: if (ioctl (((PtrPrivPtr)pMouse->devicePrivate)->fd,
158: VUIDSFORMAT, &format) < 0) {
159: Error ("VUIDSFORMAT");
160: return(!Success);
161: }
162: AddEnabledDevice (((PtrPrivPtr)pMouse->devicePrivate)->fd);
163: }
164:
165: pMouse->on = TRUE;
166: break;
167:
168: case DEVICE_CLOSE:
169: if (! sunUseSunWindows()) {
170: if (ioctl (((PtrPrivPtr)pMouse->devicePrivate)->fd,
171: VUIDSFORMAT, &oformat) < 0) {
172: Error ("VUIDSFORMAT");
173: }
174: }
175: break;
176:
177: case DEVICE_OFF:
178: pMouse->on = FALSE;
179: if (! sunUseSunWindows()) {
180: RemoveEnabledDevice (((PtrPrivPtr)pMouse->devicePrivate)->fd);
181: }
182: break;
183: }
184: return (Success);
185: }
186:
187: /*-
188: *-----------------------------------------------------------------------
189: * sunMouseCtrl --
190: * Alter the control parameters for the mouse. Since acceleration
191: * etc. is done from the PtrCtrl record in the mouse's device record,
192: * there's nothing to do here.
193: *
194: * Results:
195: * None.
196: *
197: * Side Effects:
198: * None.
199: *
200: *-----------------------------------------------------------------------
201: */
202: static void
203: sunMouseCtrl (pMouse)
204: DevicePtr pMouse;
205: {
206: }
207:
208: /*-
209: *-----------------------------------------------------------------------
210: * sunMouseGetMotionEvents --
211: * Return the (number of) motion events in the "motion history
212: * buffer" (snicker) between the given times.
213: *
214: * Results:
215: * The number of events stuffed.
216: *
217: * Side Effects:
218: * The relevant xTimecoord's are stuffed in the passed memory.
219: *
220: *-----------------------------------------------------------------------
221: */
222: static int
223: sunMouseGetMotionEvents (buff, start, stop)
224: CARD32 start, stop;
225: xTimecoord *buff;
226: {
227: return 0;
228: }
229:
230: /*-
231: *-----------------------------------------------------------------------
232: * sunMouseGetEvents --
233: * Return the events waiting in the wings for the given mouse.
234: *
235: * Results:
236: * A pointer to an array of Firm_events or (Firm_event *)0 if no events
237: * The number of events contained in the array.
238: *
239: * Side Effects:
240: * None.
241: *-----------------------------------------------------------------------
242: */
243: static Firm_event *
244: sunMouseGetEvents (pMouse, pNumEvents)
245: DevicePtr pMouse; /* Mouse to read */
246: int *pNumEvents; /* Place to return number of events */
247: {
248: int nBytes; /* number of bytes of events available. */
249: register PtrPrivPtr pPriv;
250: static Firm_event evBuf[MAXEVENTS]; /* Buffer for Firm_events */
251:
252: pPriv = (PtrPrivPtr) pMouse->devicePrivate;
253:
254: nBytes = read (pPriv->fd, evBuf, sizeof(evBuf));
255:
256: if (nBytes < 0) {
257: if (errno == EWOULDBLOCK) {
258: *pNumEvents = 0;
259: } else {
260: Error ("Reading mouse");
261: FatalError ("Could not read from mouse");
262: }
263: } else {
264: *pNumEvents = nBytes / sizeof (Firm_event);
265: }
266: return (evBuf);
267: }
268:
269:
270: /*-
271: *-----------------------------------------------------------------------
272: * MouseAccelerate --
273: * Given a delta and a mouse, return the acceleration of the delta.
274: *
275: * Results:
276: * The corrected delta
277: *
278: * Side Effects:
279: * None.
280: *
281: *-----------------------------------------------------------------------
282: */
283: static short
284: MouseAccelerate (pMouse, delta)
285: DevicePtr pMouse;
286: int delta;
287: {
288: register int sgn = sign(delta);
289: register PtrCtrl *pCtrl;
290:
291: delta = abs(delta);
292: pCtrl = &((DeviceIntPtr) pMouse)->u.ptr.ctrl;
293:
294: if (delta > pCtrl->threshold) {
295: return ((short) (sgn * (pCtrl->threshold +
296: ((delta - pCtrl->threshold) * pCtrl->num) /
297: pCtrl->den)));
298: } else {
299: return ((short) (sgn * delta));
300: }
301: }
302:
303: /*-
304: *-----------------------------------------------------------------------
305: * sunMouseProcessEvent --
306: * Given a Firm_event for a mouse, pass it off the the dix layer
307: * properly converted...
308: *
309: * Results:
310: * None.
311: *
312: * Side Effects:
313: * The cursor may be redrawn...? devPrivate/x/y will be altered.
314: *
315: *-----------------------------------------------------------------------
316: */
317: static void
318: sunMouseProcessEvent (pMouse, fe)
319: DevicePtr pMouse; /* Mouse from which the event came */
320: Firm_event *fe; /* Event to process */
321: {
322: int index; /* screen index */
323: xEvent xE;
324: register PtrPrivPtr pPriv; /* Private data for pointer */
325: register SunMsPrivPtr pSunPriv; /* Private data for mouse */
326: register int bmask; /* Temporary button mask */
327:
328: pPriv = (PtrPrivPtr)pMouse->devicePrivate;
329: pSunPriv = (SunMsPrivPtr) pPriv->devPrivate;
330:
331: xE.u.keyButtonPointer.time = TVTOMILLI(fe->time);
332:
333: switch (fe->id) {
334: case MS_LEFT:
335: case MS_MIDDLE:
336: case MS_RIGHT:
337: /*
338: * A button changed state. Sometimes we will get two events
339: * for a single state change. Should we get a button event which
340: * reflects the current state of affairs, that event is discarded.
341: *
342: * Mouse buttons start at 1.
343: */
344: xE.u.u.detail = (fe->id - MS_LEFT) + 1;
345: bmask = 1 << xE.u.u.detail;
346: if (fe->value == VKEY_UP) {
347: if (pSunPriv->bmask & bmask) {
348: xE.u.u.type = ButtonRelease;
349: pSunPriv->bmask &= ~bmask;
350: } else {
351: return;
352: }
353: } else {
354: if ((pSunPriv->bmask & bmask) == 0) {
355: xE.u.u.type = ButtonPress;
356: pSunPriv->bmask |= bmask;
357: } else {
358: return;
359: }
360: }
361: /*
362: * If the mouse has moved, we must update any interested client
363: * as well as DIX before sending a button event along.
364: */
365: if (pSunPriv->mouseMoved) {
366: sunMouseDoneEvents (pMouse, FALSE);
367: }
368:
369: break;
370: case LOC_X_DELTA:
371: /*
372: * When we detect a change in the mouse coordinates, we call
373: * the cursor module to move the cursor. It has the option of
374: * simply removing the cursor or just shifting it a bit.
375: * If it is removed, DIX will restore it before we goes to sleep...
376: *
377: * What should be done if it goes off the screen? Move to another
378: * screen? For now, we just force the pointer to stay on the
379: * screen...
380: */
381: pPriv->x += MouseAccelerate (pMouse, fe->value);
382:
383: /*
384: * Active Zaphod implementation:
385: * increment or decrement the current screen
386: * if the x is to the right or the left of
387: * the current screen.
388: */
389: if (screenInfo.numScreens > 1 &&
390: (pPriv->x > pPriv->pScreen->width ||
391: pPriv->x < 0)) {
392: sunRemoveCursor();
393: /* disable color plane if it's current */
394: index = pPriv->pScreen->myNum;
395: (*sunFbs[index].EnterLeave) (pPriv->pScreen, 1);
396: if (pPriv->x < 0) {
397: if (pPriv->pScreen->myNum != 0)
398: (pPriv->pScreen)--;
399: else
400: pPriv->pScreen = &screenInfo.screen[screenInfo.numScreens -1];
401:
402: pPriv->x += pPriv->pScreen->width;
403: }
404: else {
405: pPriv->x -= pPriv->pScreen->width;
406:
407: if (pPriv->pScreen->myNum != screenInfo.numScreens -1)
408: (pPriv->pScreen)++;
409: else
410: pPriv->pScreen = &screenInfo.screen[0];
411: }
412:
413: index = pPriv->pScreen->myNum;
414: /* enable color plane if new current screen */
415: (*sunFbs[index].EnterLeave) (pPriv->pScreen, 0);
416: }
417:
418: if (!sunConstrainXY (&pPriv->x, &pPriv->y)) {
419: return;
420: }
421:
422: NewCurrentScreen (pPriv->pScreen, pPriv->x, pPriv->y);
423:
424: #ifdef SUN_ALL_MOTION
425: xE.u.u.type = MotionNotify;
426: sunMoveCursor (pPriv->pScreen, pPriv->x, pPriv->y);
427: break;
428: #else
429: ((SunMsPrivPtr)pPriv->devPrivate)->mouseMoved = TRUE;
430: return;
431: #endif
432: case LOC_Y_DELTA:
433: /*
434: * For some reason, motion up generates a positive y delta
435: * and motion down a negative delta, so we must subtract
436: * here instead of add...
437: */
438: pPriv->y -= MouseAccelerate (pMouse, fe->value);
439: if (!sunConstrainXY (&pPriv->x, &pPriv->y)) {
440: return;
441: }
442: #ifdef SUN_ALL_MOTION
443: xE.u.u.type = MotionNotify;
444: sunMoveCursor (pPriv->pScreen, pPriv->x, pPriv->y);
445: break;
446: #else
447: ((SunMsPrivPtr)pPriv->devPrivate)->mouseMoved = TRUE;
448: return;
449: #endif SUN_ALL_MOTION
450: default:
451: FatalError ("sunMouseProcessEvent: unrecognized id\n");
452: break;
453: }
454:
455: xE.u.keyButtonPointer.rootX = pPriv->x;
456: xE.u.keyButtonPointer.rootY = pPriv->y;
457:
458: (* pMouse->processInputProc) (&xE, pMouse);
459: }
460:
461: /*-
462: *-----------------------------------------------------------------------
463: * sunMouseDoneEvents --
464: * Finish off any mouse motions we haven't done yet. (At the moment
465: * this code is unused since we never save mouse motions as I'm
466: * unsure of the effect of getting a keystroke at a given [x,y] w/o
467: * having gotten a motion event to that [x,y])
468: *
469: * Results:
470: * None.
471: *
472: * Side Effects:
473: * A MotionNotify event may be generated.
474: *
475: *-----------------------------------------------------------------------
476: */
477: /*ARGSUSED*/
478: static void
479: sunMouseDoneEvents (pMouse,final)
480: DevicePtr pMouse;
481: Bool final;
482: {
483: PtrPrivPtr pPriv;
484: SunMsPrivPtr pSunPriv;
485: xEvent xE;
486:
487: pPriv = (PtrPrivPtr) pMouse->devicePrivate;
488: pSunPriv = (SunMsPrivPtr) pPriv->devPrivate;
489:
490: if (pSunPriv->mouseMoved) {
491: sunMoveCursor (pPriv->pScreen, pPriv->x, pPriv->y);
492: xE.u.keyButtonPointer.rootX = pPriv->x;
493: xE.u.keyButtonPointer.rootY = pPriv->y;
494: xE.u.keyButtonPointer.time = lastEventTime;
495: xE.u.u.type = MotionNotify;
496: (* pMouse->processInputProc) (&xE, pMouse);
497: pSunPriv->mouseMoved = FALSE;
498: }
499: }
500:
501: #ifdef SUN_WINDOWS
502:
503: /*
504: * Process a sunwindows mouse event. The possible events are
505: * LOC_MOVE
506: * MS_LEFT
507: * MS_MIDDLE
508: * MS_RIGHT
509: */
510:
511: void
512: sunMouseProcessEventSunWin(pMouse,se)
513: DeviceRec *pMouse;
514: register struct inputevent *se;
515: {
516: xEvent xE;
517: register int bmask; /* Temporary button mask */
518: register PtrPrivPtr pPriv; /* Private data for pointer */
519: register SunMsPrivPtr pSunPriv; /* Private data for mouse */
520:
521: pPriv = (PtrPrivPtr)pMouse->devicePrivate;
522: pSunPriv = (SunMsPrivPtr) pPriv->devPrivate;
523:
524: xE.u.keyButtonPointer.time = TVTOMILLI(event_time(se));
525:
526: switch (event_id(se)) {
527: case MS_LEFT:
528: case MS_MIDDLE:
529: case MS_RIGHT:
530: /*
531: * A button changed state. Sometimes we will get two events
532: * for a single state change. Should we get a button event which
533: * reflects the current state of affairs, that event is discarded.
534: *
535: * Mouse buttons start at 1.
536: */
537: xE.u.u.detail = (event_id(se) - MS_LEFT) + 1;
538: bmask = 1 << xE.u.u.detail;
539: if (win_inputnegevent(se)) {
540: if (pSunPriv->bmask & bmask) {
541: xE.u.u.type = ButtonRelease;
542: pSunPriv->bmask &= ~bmask;
543: } else {
544: return;
545: }
546: } else {
547: if ((pSunPriv->bmask & bmask) == 0) {
548: xE.u.u.type = ButtonPress;
549: pSunPriv->bmask |= bmask;
550: } else {
551: return;
552: }
553: }
554: break;
555: case LOC_MOVE:
556: xE.u.u.type = MotionNotify;
557: xE.u.u.detail = 0;
558: pPriv->x = event_x(se);
559: pPriv->y = event_y(se);
560: if (!sunConstrainXY (&pPriv->x, &pPriv->y)) {
561: return;
562: }
563: sunMoveCursor (pPriv->pScreen, pPriv->x, pPriv->y);
564: if ((pPriv->x != event_x(se)) || (pPriv->y != event_y(se))) {
565: /*
566: * We constrained the pointer motion. Tell the pointer
567: * where it really needs to be.
568: */
569: win_setmouseposition(windowFd, pPriv->x, pPriv->y);
570: }
571: break;
572: default:
573: FatalError ("sunMouseProcessEventSunWin: unrecognized id\n");
574: break;
575: }
576:
577: xE.u.keyButtonPointer.rootX = event_x(se);
578: xE.u.keyButtonPointer.rootY = event_y(se);
579:
580: (* pMouse->processInputProc) (&xE, pMouse);
581:
582: }
583: #endif SUN_WINDOWS
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.