initial commit
[profile/ivi/xorg-x11-server.git] / hw / xfree86 / common / xf86Events.c
1 /*
2  * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of Thomas Roell not be used in
9  * advertising or publicity pertaining to distribution of the software without
10  * specific, written prior permission.  Thomas Roell makes no representations
11  * about the suitability of this software for any purpose.  It is provided
12  * "as is" without express or implied warranty.
13  *
14  * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20  * PERFORMANCE OF THIS SOFTWARE.
21  *
22  */
23 /*
24  * Copyright (c) 1994-2003 by The XFree86 Project, Inc.
25  *
26  * Permission is hereby granted, free of charge, to any person obtaining a
27  * copy of this software and associated documentation files (the "Software"),
28  * to deal in the Software without restriction, including without limitation
29  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
30  * and/or sell copies of the Software, and to permit persons to whom the
31  * Software is furnished to do so, subject to the following conditions:
32  *
33  * The above copyright notice and this permission notice shall be included in
34  * all copies or substantial portions of the Software.
35  *
36  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
39  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
40  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
41  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
42  * OTHER DEALINGS IN THE SOFTWARE.
43  *
44  * Except as contained in this notice, the name of the copyright holder(s)
45  * and author(s) shall not be used in advertising or otherwise to promote
46  * the sale, use or other dealings in this Software without prior written
47  * authorization from the copyright holder(s) and author(s).
48  */
49
50 /* [JCH-96/01/21] Extended std reverse map to four buttons. */
51
52 #ifdef HAVE_XORG_CONFIG_H
53 #include <xorg-config.h>
54 #endif
55
56 #include <X11/X.h>
57 #include <X11/Xpoll.h>
58 #include <X11/Xproto.h>
59 #include "misc.h"
60 #include "compiler.h"
61 #include "xf86.h"
62 #include "xf86Priv.h"
63 #define XF86_OS_PRIVS
64 #include "xf86_OSlib.h"
65 #include <X11/keysym.h>
66
67 #ifdef XFreeXDGA
68 #include "dgaproc.h"
69 #endif
70
71 #include <X11/extensions/XI.h>
72 #include <X11/extensions/XIproto.h>
73 #include "inputstr.h"
74 #include "xf86Xinput.h"
75
76 #include "mi.h"
77 #include "mipointer.h"
78
79 #include "xkbsrv.h"
80 #include "xkbstr.h"
81
82 #ifdef DPMSExtension
83 #include <X11/extensions/dpmsconst.h>
84 #include "dpmsproc.h"
85 #endif
86
87 /*
88  * This is a toggling variable:
89  *  FALSE = No VT switching keys have been pressed last time around
90  *  TRUE  = Possible VT switch Pending
91  * (DWH - 12/2/93)
92  *
93  * This has been generalised to work with Linux and *BSD+syscons (DHD)
94  */
95
96 Bool VTSwitchEnabled = TRUE;            /* Allows run-time disabling for
97                                          *BSD and for avoiding VT
98                                          switches when using the DRI
99                                          automatic full screen mode.*/
100
101 extern fd_set EnabledDevices;
102
103 #ifdef XF86PM
104 extern void (*xf86OSPMClose)(void);
105 #endif
106
107 static void xf86VTSwitch(void);
108
109 /*
110  * Allow arbitrary drivers or other XFree86 code to register with our main
111  * Wakeup handler.
112  */
113 typedef struct x_IHRec {
114     int                 fd;
115     InputHandlerProc    ihproc;
116     pointer             data;
117     Bool                enabled;
118     struct x_IHRec *    next;
119 } IHRec, *IHPtr;
120
121 static IHPtr InputHandlers = NULL;
122
123
124 Bool
125 LegalModifier(unsigned int key, DeviceIntPtr pDev)
126 {
127     return TRUE;
128 }
129
130 /*
131  * TimeSinceLastInputEvent --
132  *      Function used for screensaver purposes by the os module. Returns the
133  *      time in milliseconds since there last was any input.
134  */
135 int
136 TimeSinceLastInputEvent(void)
137 {
138   if (xf86Info.lastEventTime == 0) {
139     xf86Info.lastEventTime = GetTimeInMillis();
140   }
141   return GetTimeInMillis() - xf86Info.lastEventTime;
142 }
143
144 /*
145  * SetTimeSinceLastInputEvent --
146  *      Set the lastEventTime to now.
147  */
148 void
149 SetTimeSinceLastInputEvent(void)
150 {
151   xf86Info.lastEventTime = GetTimeInMillis();
152 }
153
154 /*
155  * ProcessInputEvents --
156  *      Retrieve all waiting input events and pass them to DIX in their
157  *      correct chronological order. Only reads from the system pointer
158  *      and keyboard.
159  */
160 void
161 ProcessInputEvents (void)
162 {
163   int x, y;
164
165   mieqProcessInputEvents();
166
167   /* FIXME: This is a problem if we have multiple pointers */
168   miPointerGetPosition(inputInfo.pointer, &x, &y);
169   xf86SetViewport(xf86Info.currentScreen, x, y);
170 }
171
172 /*
173  * Handle keyboard events that cause some kind of "action"
174  * (i.e., server termination, video mode changes, VT switches, etc.)
175  */
176 void
177 xf86ProcessActionEvent(ActionEvent action, void *arg)
178 {
179     DebugF("ProcessActionEvent(%d,%x)\n", (int) action, arg);
180     switch (action) {
181     case ACTION_TERMINATE:
182         if (!xf86Info.dontZap) {
183 #ifdef XFreeXDGA
184             DGAShutdown();
185 #endif
186             GiveUp(0);
187         }
188         break;
189     case ACTION_NEXT_MODE:
190         if (!xf86Info.dontZoom)
191             xf86ZoomViewport(xf86Info.currentScreen,  1);
192         break;
193     case ACTION_PREV_MODE:
194         if (!xf86Info.dontZoom)
195             xf86ZoomViewport(xf86Info.currentScreen, -1);
196         break;
197     case ACTION_SWITCHSCREEN:
198         if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) {
199             int vtno = *((int *) arg);
200
201             if (vtno != xf86Info.vtno) {
202                 if (!xf86VTActivate(vtno)) {
203                     ErrorF("Failed to switch from vt%02d to vt%02d: %s\n",
204                            xf86Info.vtno, vtno, strerror(errno));
205                 }
206             }
207         }
208         break;
209     case ACTION_SWITCHSCREEN_NEXT:
210         if (VTSwitchEnabled && !xf86Info.dontVTSwitch) {
211             if (!xf86VTActivate(xf86Info.vtno + 1)) {
212                 /* If first try failed, assume this is the last VT and
213                  * try wrapping around to the first vt.
214                  */
215                 if (!xf86VTActivate(1)) {
216                     ErrorF("Failed to switch from vt%02d to next vt: %s\n",
217                            xf86Info.vtno, strerror(errno));
218                 }
219             }
220         }
221         break;
222     case ACTION_SWITCHSCREEN_PREV:
223         if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) {
224             if (!xf86VTActivate(xf86Info.vtno - 1)) {
225                 /* Don't know what the maximum VT is, so can't wrap around */
226                 ErrorF("Failed to switch from vt%02d to previous vt: %s\n",
227                        xf86Info.vtno, strerror(errno));
228             }
229         }
230         break;
231     default:
232         break;
233     }
234 }
235
236 /*
237  * xf86Wakeup --
238  *      Os wakeup handler.
239  */
240
241 /* ARGSUSED */
242 void
243 xf86Wakeup(pointer blockData, int err, pointer pReadmask)
244 {
245     fd_set* LastSelectMask = (fd_set*)pReadmask;
246     fd_set devicesWithInput;
247     InputInfoPtr pInfo;
248
249     if (err >= 0) {
250
251         XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices);
252         if (XFD_ANYSET(&devicesWithInput)) {
253             pInfo = xf86InputDevs;
254             while (pInfo) {
255                 if (pInfo->read_input && pInfo->fd >= 0 &&
256                     (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) {
257                     int sigstate = xf86BlockSIGIO();
258
259                     /*
260                      * Remove the descriptior from the set because more than one
261                      * device may share the same file descriptor.
262                      */
263                     FD_CLR(pInfo->fd, &devicesWithInput);
264
265                     pInfo->read_input(pInfo);
266                     xf86UnblockSIGIO(sigstate);
267                 }
268                 pInfo = pInfo->next;
269             }
270         }
271     }
272
273     if (err >= 0) { /* we don't want the handlers called if select() */
274         IHPtr ih;   /* returned with an error condition, do we?      */
275         
276         for (ih = InputHandlers; ih; ih = ih->next) {
277             if (ih->enabled && ih->fd >= 0 && ih->ihproc &&
278                 (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) {
279                 ih->ihproc(ih->fd, ih->data);
280             }
281         }
282     }
283
284     if (xf86VTSwitchPending()) xf86VTSwitch();
285 }
286
287
288 /*
289  * xf86SigioReadInput --
290  *    signal handler for the SIGIO signal.
291  */
292 static void
293 xf86SigioReadInput(int fd, void *closure)
294 {
295     int errno_save = errno;
296     InputInfoPtr pInfo = closure;
297
298     pInfo->read_input(pInfo);
299
300     errno = errno_save;
301 }
302
303 /*
304  * xf86AddEnabledDevice --
305  *
306  */
307 void
308 xf86AddEnabledDevice(InputInfoPtr pInfo)
309 {
310     if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) {
311         AddEnabledDevice(pInfo->fd);
312     }
313 }
314
315 /*
316  * xf86RemoveEnabledDevice --
317  *
318  */
319 void
320 xf86RemoveEnabledDevice(InputInfoPtr pInfo)
321 {
322     if (!xf86RemoveSIGIOHandler (pInfo->fd)) {
323         RemoveEnabledDevice(pInfo->fd);
324     }
325 }
326
327 static int *xf86SignalIntercept = NULL;
328
329 void
330 xf86InterceptSignals(int *signo)
331 {
332     if ((xf86SignalIntercept = signo))
333         *signo = -1;
334 }
335
336 static void (*xf86SigIllHandler)(void) = NULL;
337
338 void
339 xf86InterceptSigIll(void (*sigillhandler)(void))
340 {
341     xf86SigIllHandler = sigillhandler;
342 }
343
344 /*
345  * xf86SigWrapper --
346  *    Catch unexpected signals and exit or continue cleanly.
347  */
348 int
349 xf86SigWrapper(int signo)
350 {
351   if ((signo == SIGILL) && xf86SigIllHandler) {
352     (*xf86SigIllHandler)();
353     return 0; /* continue */
354   }
355
356   if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) {
357     *xf86SignalIntercept = signo;
358     return 0; /* continue */
359   }
360
361   xf86Info.caughtSignal = TRUE;
362   return 1; /* abort */
363 }
364
365 /*
366  * xf86PrintBacktrace --
367  *    Print a stack backtrace for debugging purposes.
368  */
369 void
370 xf86PrintBacktrace(void)
371 {
372     xorg_backtrace();
373 }
374
375 static void
376 xf86ReleaseKeys(DeviceIntPtr pDev)
377 {
378     KeyClassPtr keyc;
379     int i, j, nevents, sigstate;
380
381     if (!pDev || !pDev->key)
382         return;
383
384     keyc = pDev->key;
385
386     /*
387      * Hmm... here is the biggest hack of every time !
388      * It may be possible that a switch-vt procedure has finished BEFORE
389      * you released all keys neccessary to do this. That peculiar behavior
390      * can fool the X-server pretty much, cause it assumes that some keys
391      * were not released. TWM may stuck alsmost completly....
392      * OK, what we are doing here is after returning from the vt-switch
393      * exeplicitely unrelease all keyboard keys before the input-devices
394      * are reenabled.
395      */
396
397     for (i = keyc->xkbInfo->desc->min_key_code;
398          i < keyc->xkbInfo->desc->max_key_code;
399          i++) {
400         if (key_is_down(pDev, i, KEY_POSTED)) {
401             sigstate = xf86BlockSIGIO ();
402             nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i);
403             for (j = 0; j < nevents; j++)
404                 mieqEnqueue(pDev, (InternalEvent*)(xf86Events + j)->event);
405             xf86UnblockSIGIO(sigstate);
406         }
407     }
408 }
409
410 /*
411  * xf86VTSwitch --
412  *      Handle requests for switching the vt.
413  */
414 static void
415 xf86VTSwitch(void)
416 {
417   int i, prevSIGIO;
418   InputInfoPtr pInfo;
419   IHPtr ih;
420
421   DebugF("xf86VTSwitch()\n");
422
423 #ifdef XFreeXDGA
424   if(!DGAVTSwitch())
425         return;
426 #endif
427
428   /*
429    * Since all screens are currently all in the same state it is sufficient
430    * check the first.  This might change in future.
431    */
432   if (xf86Screens[0]->vtSema) {
433
434     DebugF("xf86VTSwitch: Leaving, xf86Exiting is %s\n",
435            BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE));
436 #ifdef DPMSExtension
437     if (DPMSPowerLevel != DPMSModeOn)
438         DPMSSet(serverClient, DPMSModeOn);
439 #endif
440     for (i = 0; i < xf86NumScreens; i++) {
441       if (!(dispatchException & DE_TERMINATE))
442         if (xf86Screens[i]->EnableDisableFBAccess)
443           (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE);
444     }
445
446     /*
447      * Keep the order: Disable Device > LeaveVT
448      *                        EnterVT > EnableDevice
449      */
450     for (ih = InputHandlers; ih; ih = ih->next)
451       xf86DisableInputHandler(ih);
452     for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) {
453       if (pInfo->dev) {
454           xf86ReleaseKeys(pInfo->dev);
455           ProcessInputEvents();
456           DisableDevice(pInfo->dev, TRUE);
457       }
458     }
459     xf86EnterServerState(SETUP);
460     for (i = 0; i < xf86NumScreens; i++)
461         xf86Screens[i]->LeaveVT(i, 0);
462
463     xf86AccessLeave();      /* We need this here, otherwise */
464
465     if (!xf86VTSwitchAway()) {
466       /*
467        * switch failed
468        */
469
470       DebugF("xf86VTSwitch: Leave failed\n");
471       prevSIGIO = xf86BlockSIGIO();
472       xf86AccessEnter();
473       xf86EnterServerState(SETUP);
474       for (i = 0; i < xf86NumScreens; i++) {
475         if (!xf86Screens[i]->EnterVT(i, 0))
476           FatalError("EnterVT failed for screen %d\n", i);
477       }
478       xf86EnterServerState(OPERATING);
479       if (!(dispatchException & DE_TERMINATE)) {
480         for (i = 0; i < xf86NumScreens; i++) {
481           if (xf86Screens[i]->EnableDisableFBAccess)
482             (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE);
483         }
484       }
485       dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
486
487       pInfo = xf86InputDevs;
488       while (pInfo) {
489         if (pInfo->dev)
490             EnableDevice(pInfo->dev, TRUE);
491         pInfo = pInfo->next;
492       }
493       for (ih = InputHandlers; ih; ih = ih->next)
494         xf86EnableInputHandler(ih);
495
496       xf86UnblockSIGIO(prevSIGIO);
497
498     } else {
499 #ifdef XF86PM
500           if (xf86OSPMClose)
501               xf86OSPMClose();
502           xf86OSPMClose = NULL;
503 #endif
504
505         for (i = 0; i < xf86NumScreens; i++) {
506             /*
507              * zero all access functions to
508              * trap calls when switched away.
509              */
510             xf86Screens[i]->vtSema = FALSE;
511         }
512         if (xorgHWAccess)
513             xf86DisableIO();
514     }
515   } else {
516
517     DebugF("xf86VTSwitch: Entering\n");
518     if (!xf86VTSwitchTo()) return;
519
520     prevSIGIO = xf86BlockSIGIO();
521 #ifdef XF86PM
522     xf86OSPMClose = xf86OSPMOpen();
523 #endif
524
525     if (xorgHWAccess)
526         xf86EnableIO();
527     xf86AccessEnter();
528     xf86EnterServerState(SETUP);
529     for (i = 0; i < xf86NumScreens; i++) {
530       xf86Screens[i]->vtSema = TRUE;
531       if (!xf86Screens[i]->EnterVT(i, 0))
532           FatalError("EnterVT failed for screen %d\n", i);
533     }
534     xf86EnterServerState(OPERATING);
535     for (i = 0; i < xf86NumScreens; i++) {
536       if (xf86Screens[i]->EnableDisableFBAccess)
537         (*xf86Screens[i]->EnableDisableFBAccess)(i, TRUE);
538     }
539
540     /* Turn screen saver off when switching back */
541     dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
542
543     pInfo = xf86InputDevs;
544     while (pInfo) {
545       if (pInfo->dev)
546           EnableDevice(pInfo->dev, TRUE);
547       pInfo = pInfo->next;
548     }
549
550     for (ih = InputHandlers; ih; ih = ih->next)
551       xf86EnableInputHandler(ih);
552
553     xf86UnblockSIGIO(prevSIGIO);
554   }
555 }
556
557
558 /* Input handler registration */
559
560 static pointer
561 addInputHandler(int fd, InputHandlerProc proc, pointer data)
562 {
563     IHPtr ih;
564
565     if (fd < 0 || !proc)
566         return NULL;
567
568     ih = calloc(sizeof(*ih), 1);
569     if (!ih)
570         return NULL;
571
572     ih->fd = fd;
573     ih->ihproc = proc;
574     ih->data = data;
575     ih->enabled = TRUE;
576
577     ih->next = InputHandlers;
578     InputHandlers = ih;
579
580     return ih;
581 }
582
583 pointer
584 xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data)
585 {
586     IHPtr ih = addInputHandler(fd, proc, data);
587
588     if (ih)
589         AddEnabledDevice(fd);
590     return ih;
591 }
592
593 pointer
594 xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data)
595 {
596     IHPtr ih = addInputHandler(fd, proc, data);
597
598     if (ih)
599         AddGeneralSocket(fd);
600     return ih;
601 }
602
603 static void
604 removeInputHandler(IHPtr ih)
605 {
606     IHPtr p;
607
608     if (ih == InputHandlers)
609         InputHandlers = ih->next;
610     else {
611         p = InputHandlers;
612         while (p && p->next != ih)
613             p = p->next;
614         if (ih)
615             p->next = ih->next;
616     }
617     free(ih);
618 }
619
620 int
621 xf86RemoveInputHandler(pointer handler)
622 {
623     IHPtr ih;
624     int fd;
625
626     if (!handler)
627         return -1;
628
629     ih = handler;
630     fd = ih->fd;
631
632     if (ih->fd >= 0)
633         RemoveEnabledDevice(ih->fd);
634     removeInputHandler(ih);
635
636     return fd;
637 }
638
639 int
640 xf86RemoveGeneralHandler(pointer handler)
641 {
642     IHPtr ih;
643     int fd;
644
645     if (!handler)
646         return -1;
647
648     ih = handler;
649     fd = ih->fd;
650
651     if (ih->fd >= 0)
652         RemoveGeneralSocket(ih->fd);
653     removeInputHandler(ih);
654
655     return fd;
656 }
657
658 void
659 xf86DisableInputHandler(pointer handler)
660 {
661     IHPtr ih;
662
663     if (!handler)
664         return;
665
666     ih = handler;
667     ih->enabled = FALSE;
668     if (ih->fd >= 0)
669         RemoveEnabledDevice(ih->fd);
670 }
671
672 void
673 xf86DisableGeneralHandler(pointer handler)
674 {
675     IHPtr ih;
676
677     if (!handler)
678         return;
679
680     ih = handler;
681     ih->enabled = FALSE;
682     if (ih->fd >= 0)
683         RemoveGeneralSocket(ih->fd);
684 }
685
686 void
687 xf86EnableInputHandler(pointer handler)
688 {
689     IHPtr ih;
690
691     if (!handler)
692         return;
693
694     ih = handler;
695     ih->enabled = TRUE;
696     if (ih->fd >= 0)
697         AddEnabledDevice(ih->fd);
698 }
699
700 void
701 xf86EnableGeneralHandler(pointer handler)
702 {
703     IHPtr ih;
704
705     if (!handler)
706         return;
707
708     ih = handler;
709     ih->enabled = TRUE;
710     if (ih->fd >= 0)
711         AddGeneralSocket(ih->fd);
712 }
713
714 /*
715  * As used currently by the DRI, the return value is ignored.
716  */
717 Bool
718 xf86EnableVTSwitch(Bool new)
719 {
720     static Bool def = TRUE;
721     Bool old;
722
723     old = VTSwitchEnabled;
724     if (!new) {
725         /* Disable VT switching */
726         def = VTSwitchEnabled;
727         VTSwitchEnabled = FALSE;
728     } else {
729         /* Restore VT switching to default */
730         VTSwitchEnabled = def;
731     }
732     return old;
733 }
734
735 void
736 DDXRingBell(int volume, int pitch, int duration) {
737     xf86OSRingBell(volume, pitch, duration);
738 }