First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / common / xf86Events.c
blob91964c9501276a815632fdb5c08815997181482e
1 /*
2 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
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.
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.
24 * Copyright (c) 1994-2003 by The XFree86 Project, Inc.
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:
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
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.
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).
50 /* [JCH-96/01/21] Extended std reverse map to four buttons. */
52 #ifdef HAVE_XORG_CONFIG_H
53 #include <xorg-config.h>
54 #endif
56 #include <X11/X.h>
57 #include <X11/Xpoll.h>
58 #include <X11/Xproto.h>
59 #include "misc.h"
61 #include "compiler.h"
63 #include "xf86.h"
64 #include "xf86Priv.h"
65 #define XF86_OS_PRIVS
66 #include "xf86_OSlib.h"
67 #include "atKeynames.h"
70 #ifdef XFreeXDGA
71 #include "dgaproc.h"
72 #endif
74 #ifdef XINPUT
75 #include <X11/extensions/XI.h>
76 #include <X11/extensions/XIproto.h>
77 #else
78 #include "inputstr.h"
79 #endif
80 #include "xf86Xinput.h"
82 #include "mi.h"
83 #include "mipointer.h"
85 #ifdef XF86BIGFONT
86 #define _XF86BIGFONT_SERVER_
87 #include <X11/extensions/xf86bigfont.h>
88 #endif
90 #ifdef XKB
91 extern Bool noXkbExtension;
92 #endif
94 #ifdef DPMSExtension
95 #define DPMS_SERVER
96 #include <X11/extensions/dpms.h>
97 #include "dpmsproc.h"
98 #endif
100 #define XE_POINTER 1
101 #define XE_KEYBOARD 2
103 #define EqEnqueue(pDev, ev) { \
104 int __sigstate = xf86BlockSIGIO (); \
105 mieqEnqueue (pDev, ev); \
106 xf86UnblockSIGIO(__sigstate); \
110 * The first of many hacks to get VT switching to work under
111 * Solaris 2.1 for x86. The basic problem is that Solaris is supposed
112 * to be SVR4. It is for the most part, except where the video interface
113 * is concerned. These hacks work around those problems.
114 * See the comments for Linux, and SCO.
116 * This is a toggling variable:
117 * FALSE = No VT switching keys have been pressed last time around
118 * TRUE = Possible VT switch Pending
119 * (DWH - 12/2/93)
121 * This has been generalised to work with Linux and *BSD+syscons (DHD)
124 _X_EXPORT Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for
125 *BSD and for avoiding VT
126 switches when using the DRI
127 automatic full screen mode.*/
129 extern fd_set EnabledDevices;
131 #ifdef XF86PM
132 extern void (*xf86OSPMClose)(void);
133 #endif
135 static void xf86VTSwitch(void);
138 * Allow arbitrary drivers or other XFree86 code to register with our main
139 * Wakeup handler.
141 typedef struct x_IHRec {
142 int fd;
143 InputHandlerProc ihproc;
144 pointer data;
145 Bool enabled;
146 struct x_IHRec * next;
147 } IHRec, *IHPtr;
149 static IHPtr InputHandlers = NULL;
152 Bool
153 LegalModifier(unsigned int key, DeviceIntPtr pDev)
155 return TRUE;
159 * TimeSinceLastInputEvent --
160 * Function used for screensaver purposes by the os module. Returns the
161 * time in milliseconds since there last was any input.
165 TimeSinceLastInputEvent()
167 if (xf86Info.lastEventTime == 0) {
168 xf86Info.lastEventTime = GetTimeInMillis();
170 return GetTimeInMillis() - xf86Info.lastEventTime;
176 * SetTimeSinceLastInputEvent --
177 * Set the lastEventTime to now.
180 _X_EXPORT void
181 SetTimeSinceLastInputEvent()
183 xf86Info.lastEventTime = GetTimeInMillis();
189 * ProcessInputEvents --
190 * Retrieve all waiting input events and pass them to DIX in their
191 * correct chronological order. Only reads from the system pointer
192 * and keyboard.
195 void
196 ProcessInputEvents ()
198 int x, y;
199 #ifdef INHERIT_LOCK_STATE
200 static int generation = 0;
201 #endif
204 * With INHERIT_LOCK_STATE defined, the initial state of CapsLock, NumLock
205 * and ScrollLock will be set to match that of the VT the server is
206 * running on.
208 #ifdef INHERIT_LOCK_STATE
209 if (generation != serverGeneration) {
210 xEvent kevent;
211 DevicePtr pKeyboard = xf86Info.pKeyboard;
212 extern unsigned int xf86InitialCaps, xf86InitialNum, xf86InitialScroll;
214 generation = serverGeneration;
215 kevent.u.keyButtonPointer.time = GetTimeInMillis();
216 kevent.u.keyButtonPointer.rootX = 0;
217 kevent.u.keyButtonPointer.rootY = 0;
218 kevent.u.u.type = KeyPress;
221 if (xf86InitialCaps) {
222 kevent.u.u.detail = xf86InitialCaps;
223 (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1);
224 xf86InitialCaps = 0;
226 if (xf86InitialNum) {
227 kevent.u.u.detail = xf86InitialNum;
228 (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1);
229 xf86InitialNum = 0;
231 if (xf86InitialScroll) {
232 kevent.u.u.detail = xf86InitialScroll;
233 (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1);
234 xf86InitialScroll = 0;
237 #endif
239 xf86Info.inputPending = FALSE;
241 mieqProcessInputEvents();
242 miPointerUpdateSprite(inputInfo.pointer);
244 miPointerGetPosition(inputInfo.pointer, &x, &y);
245 xf86SetViewport(xf86Info.currentScreen, x, y);
248 void
249 xf86GrabServerCallback(CallbackListPtr *callbacks, pointer data, pointer args)
251 ServerGrabInfoRec *grab = (ServerGrabInfoRec*)args;
253 xf86Info.grabInfo.server.client = grab->client;
254 xf86Info.grabInfo.server.grabstate = grab->grabstate;
258 * Handle keyboard events that cause some kind of "action"
259 * (i.e., server termination, video mode changes, VT switches, etc.)
261 void
262 xf86ProcessActionEvent(ActionEvent action, void *arg)
264 #ifdef DEBUG
265 ErrorF("ProcessActionEvent(%d,%x)\n", (int) action, arg);
266 #endif
267 switch (action) {
268 case ACTION_TERMINATE:
269 if (!xf86Info.dontZap) {
270 #ifdef XFreeXDGA
271 DGAShutdown();
272 #endif
273 GiveUp(0);
275 break;
276 case ACTION_NEXT_MODE:
277 if (!xf86Info.dontZoom)
278 xf86ZoomViewport(xf86Info.currentScreen, 1);
279 break;
280 case ACTION_PREV_MODE:
281 if (!xf86Info.dontZoom)
282 xf86ZoomViewport(xf86Info.currentScreen, -1);
283 break;
284 case ACTION_DISABLEGRAB:
285 if (!xf86Info.grabInfo.disabled && xf86Info.grabInfo.allowDeactivate) {
286 if (inputInfo.pointer && inputInfo.pointer->grab != NULL &&
287 inputInfo.pointer->DeactivateGrab)
288 inputInfo.pointer->DeactivateGrab(inputInfo.pointer);
289 if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL &&
290 inputInfo.keyboard->DeactivateGrab)
291 inputInfo.keyboard->DeactivateGrab(inputInfo.keyboard);
293 break;
294 case ACTION_CLOSECLIENT:
295 if (!xf86Info.grabInfo.disabled && xf86Info.grabInfo.allowClosedown) {
296 ClientPtr pointer, keyboard, server;
298 pointer = keyboard = server = NULL;
299 if (inputInfo.pointer && inputInfo.pointer->grab != NULL)
300 pointer = clients[CLIENT_ID(inputInfo.pointer->grab->resource)];
301 if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL) {
302 keyboard = clients[CLIENT_ID(inputInfo.keyboard->grab->resource)];
303 if (keyboard == pointer)
304 keyboard = NULL;
306 if ((xf86Info.grabInfo.server.grabstate == SERVER_GRABBED) &&
307 (((server = xf86Info.grabInfo.server.client) == pointer) ||
308 (server == keyboard)))
309 server = NULL;
311 if (pointer)
312 CloseDownClient(pointer);
313 if (keyboard)
314 CloseDownClient(keyboard);
315 if (server)
316 CloseDownClient(server);
318 break;
319 #if !defined(__SOL8__) && !defined(sgi) && \
320 (!defined(sun) || defined(i386)) && defined(VT_ACTIVATE)
321 case ACTION_SWITCHSCREEN:
322 if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) {
323 int vtno = *((int *) arg);
324 #if defined(__SCO__) || defined(__UNIXWARE__)
325 vtno--;
326 #endif
327 #if defined(QNX4)
328 xf86Info.vtRequestsPending = vtno;
329 #else
330 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vtno) < 0)
331 ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
332 #endif
334 break;
335 case ACTION_SWITCHSCREEN_NEXT:
336 if (VTSwitchEnabled && !xf86Info.dontVTSwitch) {
337 /* Shouldn't this be true for (sun) && (i386) && (SVR4) ? */
338 #if defined(__SCO__) || defined(__UNIXWARE__)
339 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) < 0)
340 #else
341 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1) < 0)
342 #endif
343 #if defined (__SCO__) || (defined(sun) && defined (i386) && defined (SVR4)) || defined(__UNIXWARE__)
344 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0)
345 #else
346 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) < 0)
347 #endif
348 ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
350 break;
351 case ACTION_SWITCHSCREEN_PREV:
352 if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) {
353 if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno - 1) < 0)
354 ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
356 break;
357 #endif
358 case ACTION_MESSAGE:
360 char *retstr, *message = (char *) arg;
361 ScrnInfoPtr pScr = XF86SCRNINFO(xf86Info.currentScreen);
363 #ifdef DEBUG
364 ErrorF("ActionMessage: '%s'\n", message);
365 #endif
366 /* Okay the message made it to the ddx. The common layer */
367 /* can check for relevant messages here and react to any */
368 /* that have a global effect. For example: */
369 /* */
370 /* if (!strcmp(message, "foo") { */
371 /* do_foo(); break */
372 /* } */
373 /* */
374 /* otherwise fallback to sending a key event message to */
375 /* the current screen's driver: */
376 if (*pScr->HandleMessage != NULL) {
377 (void) (*pScr->HandleMessage)(pScr->scrnIndex,
378 "KeyEventMessage", message, &retstr);
381 break;
382 default:
383 break;
387 #define ModifierIsSet(k) ((modifiers & (k)) == (k))
389 _X_EXPORT Bool
390 xf86CommonSpecialKey(int key, Bool down, int modifiers)
392 if ((!ModifierIsSet(ShiftMask)) &&
393 (((ModifierIsSet(ControlMask | AltMask)) ||
394 (ModifierIsSet(ControlMask | AltLangMask))))) {
395 switch (key) {
397 case KEY_BackSpace:
398 xf86ProcessActionEvent(ACTION_TERMINATE, NULL);
399 break;
402 * Check grabs
404 case KEY_KP_Divide:
405 xf86ProcessActionEvent(ACTION_DISABLEGRAB, NULL);
406 break;
407 case KEY_KP_Multiply:
408 xf86ProcessActionEvent(ACTION_CLOSECLIENT, NULL);
409 break;
412 * The idea here is to pass the scancode down to a list of
413 * registered routines. There should be some standard conventions
414 * for processing certain keys.
416 case KEY_KP_Minus: /* Keypad - */
417 if (down) xf86ProcessActionEvent(ACTION_PREV_MODE, NULL);
418 if (!xf86Info.dontZoom) return TRUE;
419 break;
421 case KEY_KP_Plus: /* Keypad + */
422 if (down) xf86ProcessActionEvent(ACTION_NEXT_MODE, NULL);
423 if (!xf86Info.dontZoom) return TRUE;
424 break;
427 return FALSE;
431 * xf86Wakeup --
432 * Os wakeup handler.
435 /* ARGSUSED */
436 void
437 xf86Wakeup(pointer blockData, int err, pointer pReadmask)
439 #if !defined(__QNX__)
440 fd_set* LastSelectMask = (fd_set*)pReadmask;
441 fd_set devicesWithInput;
442 InputInfoPtr pInfo;
444 if (err >= 0) {
446 XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices);
447 if (XFD_ANYSET(&devicesWithInput)) {
448 pInfo = xf86InputDevs;
449 while (pInfo) {
450 if (pInfo->read_input && pInfo->fd >= 0 &&
451 (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) {
452 int sigstate = xf86BlockSIGIO();
454 pInfo->read_input(pInfo);
455 xf86UnblockSIGIO(sigstate);
457 * Remove the descriptior from the set because more than one
458 * device may share the same file descriptor.
460 FD_CLR(pInfo->fd, &devicesWithInput);
462 pInfo = pInfo->next;
466 #else /* __QNX__ */
468 InputInfoPtr pInfo;
470 pInfo = xf86InputDevs;
471 while (pInfo) {
472 if (pInfo->read_input && pInfo->fd >= 0) {
473 int sigstate = xf86BlockSIGIO();
475 pInfo->read_input(pInfo);
476 xf86UnblockSIGIO(sigstate);
478 * Must break here because more than one device may share
479 * the same file descriptor.
481 break;
483 pInfo = pInfo->next;
486 #endif /* __QNX__ */
488 if (err >= 0) { /* we don't want the handlers called if select() */
489 IHPtr ih; /* returned with an error condition, do we? */
491 for (ih = InputHandlers; ih; ih = ih->next) {
492 if (ih->enabled && ih->fd >= 0 && ih->ihproc &&
493 (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) {
494 ih->ihproc(ih->fd, ih->data);
499 if (xf86VTSwitchPending()) xf86VTSwitch();
501 if (xf86Info.inputPending) ProcessInputEvents();
506 * xf86SigioReadInput --
507 * signal handler for the SIGIO signal.
509 static void
510 xf86SigioReadInput(int fd,
511 void *closure)
513 int sigstate = xf86BlockSIGIO();
514 InputInfoPtr pInfo = (InputInfoPtr) closure;
516 pInfo->read_input(pInfo);
518 xf86UnblockSIGIO(sigstate);
522 * xf86AddEnabledDevice --
525 _X_EXPORT void
526 xf86AddEnabledDevice(InputInfoPtr pInfo)
528 if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) {
529 AddEnabledDevice(pInfo->fd);
534 * xf86RemoveEnabledDevice --
537 _X_EXPORT void
538 xf86RemoveEnabledDevice(InputInfoPtr pInfo)
540 if (!xf86RemoveSIGIOHandler (pInfo->fd)) {
541 RemoveEnabledDevice(pInfo->fd);
545 static int *xf86SignalIntercept = NULL;
547 _X_EXPORT void
548 xf86InterceptSignals(int *signo)
550 if ((xf86SignalIntercept = signo))
551 *signo = -1;
554 static void (*xf86SigIllHandler)(void) = NULL;
556 _X_EXPORT void
557 xf86InterceptSigIll(void (*sigillhandler)(void))
559 xf86SigIllHandler = sigillhandler;
562 #ifdef HAVE_BACKTRACE
563 #include <execinfo.h>
565 static __inline__ void xorg_backtrace(void)
567 void *array[32]; /* deeper nesting than this means something's wrong */
568 size_t size, i;
569 char **strings;
570 ErrorF("\nBacktrace:\n");
571 size = backtrace(array, 32);
572 strings = backtrace_symbols(array, size);
573 for (i = 0; i < size; i++)
574 ErrorF("%d: %s\n", i, strings[i]);
575 free(strings);
578 #else /* not glibc or glibc < 2.1 */
580 # if defined(sun) && defined(__SVR4)
581 # define HAVE_PSTACK
582 # endif
584 # if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */
586 # include <ucontext.h>
587 # include <signal.h>
588 # include <dlfcn.h>
589 # include <sys/elf.h>
591 #ifdef _LP64
592 # define ElfSym Elf64_Sym
593 #else
594 # define ElfSym Elf32_Sym
595 #endif
597 /* Called for each frame on the stack to print it's contents */
598 static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg)
600 Dl_info dlinfo;
601 ElfSym *dlsym;
602 char header[32];
603 int depth = *((int *) arg);
605 if (signo) {
606 char signame[SIG2STR_MAX];
608 if (sig2str(signo, signame) != 0) {
609 strcpy(signame, "unknown");
612 ErrorF("** Signal %d (%s)\n", signo, signame);
615 snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc);
616 *((int *) arg) = depth + 1;
618 /* Ask system dynamic loader for info on the address */
619 if (dladdr1((void *) pc, &dlinfo, (void **) &dlsym, RTLD_DL_SYMENT)) {
620 unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr;
621 const char *symname;
623 if (offset < dlsym->st_size) { /* inside a function */
624 symname = dlinfo.dli_sname;
625 } else { /* found which file it was in, but not which function */
626 symname = "<section start>";
627 offset = pc - (uintptr_t)dlinfo.dli_fbase;
629 ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname,
630 symname, offset);
632 } else {
633 /* Couldn't find symbol info from system dynamic loader, should
634 * probably poke elfloader here, but haven't written that code yet,
635 * so we just print the pc.
637 ErrorF("%s\n", header);
640 return 0;
642 # endif /* HAVE_WALKCONTEXT */
644 # ifdef HAVE_PSTACK
645 static int xorg_backtrace_pstack(void) {
646 pid_t kidpid;
647 int pipefd[2];
649 if (pipe(pipefd) != 0) {
650 return -1;
653 kidpid = fork1();
655 if (kidpid == -1) {
656 /* ERROR */
657 return -1;
658 } else if (kidpid == 0) {
659 /* CHILD */
660 char parent[16];
662 seteuid(0);
663 close(STDIN_FILENO);
664 close(STDOUT_FILENO);
665 dup2(pipefd[1],STDOUT_FILENO);
666 closefrom(STDERR_FILENO);
668 snprintf(parent, sizeof(parent), "%d", getppid());
669 execle("/usr/bin/pstack", "pstack", parent, NULL);
670 exit(1);
671 } else {
672 /* PARENT */
673 char btline[256];
674 int kidstat;
675 int bytesread;
676 int done = 0;
678 close(pipefd[1]);
680 while (!done) {
681 bytesread = read(pipefd[0], btline, sizeof(btline) - 1);
683 if (bytesread > 0) {
684 btline[bytesread] = 0;
685 ErrorF("%s", btline);
687 else if ((bytesread < 0) ||
688 ((errno != EINTR) && (errno != EAGAIN)))
689 done = 1;
691 close(pipefd[0]);
692 waitpid(kidpid, &kidstat, 0);
693 if (kidstat != 0)
694 return -1;
696 return 0;
698 # endif /* HAVE_PSTACK */
701 # if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT)
703 static __inline__ void xorg_backtrace(void) {
705 ErrorF("\nBacktrace:\n");
707 # ifdef HAVE_PSTACK
708 /* First try fork/exec of pstack - otherwise fall back to walkcontext
709 pstack is preferred since it can print names of non-exported functions */
711 if (xorg_backtrace_pstack() < 0)
712 # endif
714 # ifdef HAVE_WALKCONTEXT
715 ucontext_t u;
716 int depth = 1;
718 if (getcontext(&u) == 0)
719 walkcontext(&u, xorg_backtrace_frame, &depth);
720 else
721 # endif
722 Error("Failed to get backtrace info");
724 ErrorF("\n");
727 # else
729 /* Default fallback if we can't find any way to get a backtrace */
730 static __inline__ void xorg_backtrace(void) { return; }
732 # endif
733 #endif
736 * xf86SigHandler --
737 * Catch unexpected signals and exit or continue cleanly.
739 void
740 xf86SigHandler(int signo)
742 if ((signo == SIGILL) && xf86SigIllHandler) {
743 (*xf86SigIllHandler)();
744 /* Re-arm handler just in case we unexpectedly return here */
745 (void) signal(signo, xf86SigHandler);
746 return;
749 if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) {
750 *xf86SignalIntercept = signo;
751 /* Re-arm handler just in case */
752 (void) signal(signo, xf86SigHandler);
753 return;
756 signal(signo,SIG_IGN);
757 xf86Info.caughtSignal = TRUE;
758 #ifdef XF86BIGFONT
759 XF86BigfontCleanup();
760 #endif
762 xorg_backtrace();
764 FatalError("Caught signal %d. Server aborting\n", signo);
767 static void
768 xf86ReleaseKeys(DeviceIntPtr pDev)
770 KeyClassPtr keyc = NULL;
771 KeySym *map = NULL;
772 xEvent ke;
773 int i = 0, j = 0, nevents = 0;
775 if (!pDev || !pDev->key)
776 return;
778 keyc = pDev->key;
779 map = keyc->curKeySyms.map;
782 * Hmm... here is the biggest hack of every time !
783 * It may be possible that a switch-vt procedure has finished BEFORE
784 * you released all keys neccessary to do this. That peculiar behavior
785 * can fool the X-server pretty much, cause it assumes that some keys
786 * were not released. TWM may stuck alsmost completly....
787 * OK, what we are doing here is after returning from the vt-switch
788 * exeplicitely unrelease all keyboard keys before the input-devices
789 * are reenabled.
792 for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map;
793 i < keyc->curKeySyms.maxKeyCode;
794 i++, map += keyc->curKeySyms.mapWidth) {
795 if (KeyPressed(i)) {
796 switch (*map) {
797 /* Don't release the lock keys */
798 case XK_Caps_Lock:
799 case XK_Shift_Lock:
800 case XK_Num_Lock:
801 case XK_Scroll_Lock:
802 case XK_Kana_Lock:
803 break;
804 default:
805 if (pDev == inputInfo.keyboard) {
806 ke.u.keyButtonPointer.time = GetTimeInMillis();
807 ke.u.keyButtonPointer.rootX = 0;
808 ke.u.keyButtonPointer.rootY = 0;
809 ke.u.u.type = KeyRelease;
810 ke.u.u.detail = i;
811 (*pDev->public.processInputProc) (&ke, pDev, 1);
813 else {
814 int sigstate = xf86BlockSIGIO ();
815 nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i);
816 for (j = 0; j < nevents; j++)
817 mieqEnqueue(pDev, xf86Events + j);
818 xf86UnblockSIGIO(sigstate);
820 break;
827 * xf86VTSwitch --
828 * Handle requests for switching the vt.
830 static void
831 xf86VTSwitch()
833 int i, prevSIGIO;
834 InputInfoPtr pInfo;
835 IHPtr ih;
837 #ifdef DEBUG
838 ErrorF("xf86VTSwitch()\n");
839 #endif
841 #ifdef XFreeXDGA
842 if(!DGAVTSwitch())
843 return;
844 #endif
847 * Since all screens are currently all in the same state it is sufficient
848 * check the first. This might change in future.
850 if (xf86Screens[0]->vtSema) {
852 #ifdef DEBUG
853 ErrorF("xf86VTSwitch: Leaving, xf86Exiting is %s\n",
854 BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE));
855 #endif
856 #ifdef DPMSExtension
857 if (DPMSPowerLevel != DPMSModeOn)
858 DPMSSet(DPMSModeOn);
859 #endif
860 for (i = 0; i < xf86NumScreens; i++) {
861 if (!(dispatchException & DE_TERMINATE))
862 if (xf86Screens[i]->EnableDisableFBAccess)
863 (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE);
867 * Keep the order: Disable Device > LeaveVT
868 * EnterVT > EnableDevice
870 pInfo = xf86InputDevs;
871 while (pInfo) {
872 if (pInfo->dev)
873 DisableDevice(pInfo->dev);
874 pInfo = pInfo->next;
876 xf86EnterServerState(SETUP);
877 for (i = 0; i < xf86NumScreens; i++)
878 xf86Screens[i]->LeaveVT(i, 0);
880 for (ih = InputHandlers; ih; ih = ih->next)
881 xf86DisableInputHandler(ih);
882 xf86AccessLeave(); /* We need this here, otherwise */
883 xf86AccessLeaveState(); /* console won't be restored */
885 if (!xf86VTSwitchAway()) {
887 * switch failed
890 #ifdef DEBUG
891 ErrorF("xf86VTSwitch: Leave failed\n");
892 #endif
893 prevSIGIO = xf86BlockSIGIO();
894 xf86AccessEnter();
895 xf86EnterServerState(SETUP);
896 for (i = 0; i < xf86NumScreens; i++) {
897 if (!xf86Screens[i]->EnterVT(i, 0))
898 FatalError("EnterVT failed for screen %d\n", i);
900 xf86EnterServerState(OPERATING);
901 if (!(dispatchException & DE_TERMINATE)) {
902 for (i = 0; i < xf86NumScreens; i++) {
903 if (xf86Screens[i]->EnableDisableFBAccess)
904 (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE);
907 SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset);
909 pInfo = xf86InputDevs;
910 while (pInfo) {
911 if (pInfo->dev) {
912 xf86ReleaseKeys(pInfo->dev);
913 EnableDevice(pInfo->dev);
915 pInfo = pInfo->next;
917 /* XXX HACK */
918 xf86ReleaseKeys(inputInfo.keyboard);
919 for (ih = InputHandlers; ih; ih = ih->next)
920 xf86EnableInputHandler(ih);
922 xf86UnblockSIGIO(prevSIGIO);
924 } else {
925 #ifdef XF86PM
926 if (xf86OSPMClose)
927 xf86OSPMClose();
928 xf86OSPMClose = NULL;
929 #endif
931 for (i = 0; i < xf86NumScreens; i++) {
933 * zero all access functions to
934 * trap calls when switched away.
936 xf86Screens[i]->vtSema = FALSE;
937 xf86Screens[i]->access = NULL;
938 xf86Screens[i]->busAccess = NULL;
940 if (xorgHWAccess)
941 xf86DisableIO();
943 } else {
945 #ifdef DEBUG
946 ErrorF("xf86VTSwitch: Entering\n");
947 #endif
948 if (!xf86VTSwitchTo()) return;
950 prevSIGIO = xf86BlockSIGIO();
951 #ifdef XF86PM
952 xf86OSPMClose = xf86OSPMOpen();
953 #endif
955 if (xorgHWAccess)
956 xf86EnableIO();
957 xf86AccessEnter();
958 xf86EnterServerState(SETUP);
959 for (i = 0; i < xf86NumScreens; i++) {
960 xf86Screens[i]->vtSema = TRUE;
961 if (!xf86Screens[i]->EnterVT(i, 0))
962 FatalError("EnterVT failed for screen %d\n", i);
964 xf86EnterServerState(OPERATING);
965 for (i = 0; i < xf86NumScreens; i++) {
966 if (xf86Screens[i]->EnableDisableFBAccess)
967 (*xf86Screens[i]->EnableDisableFBAccess)(i, TRUE);
970 /* Turn screen saver off when switching back */
971 SaveScreens(SCREEN_SAVER_FORCER,ScreenSaverReset);
973 pInfo = xf86InputDevs;
974 while (pInfo) {
975 if (pInfo->dev) {
976 xf86ReleaseKeys(pInfo->dev);
977 EnableDevice(pInfo->dev);
979 pInfo = pInfo->next;
981 /* XXX HACK */
982 xf86ReleaseKeys(inputInfo.keyboard);
984 for (ih = InputHandlers; ih; ih = ih->next)
985 xf86EnableInputHandler(ih);
987 xf86UnblockSIGIO(prevSIGIO);
992 /* Input handler registration */
994 static pointer
995 addInputHandler(int fd, InputHandlerProc proc, pointer data)
997 IHPtr ih;
999 if (fd < 0 || !proc)
1000 return NULL;
1002 ih = xcalloc(sizeof(*ih), 1);
1003 if (!ih)
1004 return NULL;
1006 ih->fd = fd;
1007 ih->ihproc = proc;
1008 ih->data = data;
1009 ih->enabled = TRUE;
1011 ih->next = InputHandlers;
1012 InputHandlers = ih;
1014 return ih;
1017 _X_EXPORT pointer
1018 xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data)
1020 IHPtr ih = addInputHandler(fd, proc, data);
1022 if (ih)
1023 AddEnabledDevice(fd);
1024 return ih;
1027 _X_EXPORT pointer
1028 xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data)
1030 IHPtr ih = addInputHandler(fd, proc, data);
1032 if (ih)
1033 AddGeneralSocket(fd);
1034 return ih;
1037 static void
1038 removeInputHandler(IHPtr ih)
1040 IHPtr p;
1042 if (ih == InputHandlers)
1043 InputHandlers = ih->next;
1044 else {
1045 p = InputHandlers;
1046 while (p && p->next != ih)
1047 p = p->next;
1048 if (ih)
1049 p->next = ih->next;
1051 xfree(ih);
1054 _X_EXPORT int
1055 xf86RemoveInputHandler(pointer handler)
1057 IHPtr ih;
1058 int fd;
1060 if (!handler)
1061 return -1;
1063 ih = handler;
1064 fd = ih->fd;
1066 if (ih->fd >= 0)
1067 RemoveEnabledDevice(ih->fd);
1068 removeInputHandler(ih);
1070 return fd;
1073 _X_EXPORT int
1074 xf86RemoveGeneralHandler(pointer handler)
1076 IHPtr ih;
1077 int fd;
1079 if (!handler)
1080 return -1;
1082 ih = handler;
1083 fd = ih->fd;
1085 if (ih->fd >= 0)
1086 RemoveGeneralSocket(ih->fd);
1087 removeInputHandler(ih);
1089 return fd;
1092 _X_EXPORT void
1093 xf86DisableInputHandler(pointer handler)
1095 IHPtr ih;
1097 if (!handler)
1098 return;
1100 ih = handler;
1101 ih->enabled = FALSE;
1102 if (ih->fd >= 0)
1103 RemoveEnabledDevice(ih->fd);
1106 _X_EXPORT void
1107 xf86DisableGeneralHandler(pointer handler)
1109 IHPtr ih;
1111 if (!handler)
1112 return;
1114 ih = handler;
1115 ih->enabled = FALSE;
1116 if (ih->fd >= 0)
1117 RemoveGeneralSocket(ih->fd);
1120 _X_EXPORT void
1121 xf86EnableInputHandler(pointer handler)
1123 IHPtr ih;
1125 if (!handler)
1126 return;
1128 ih = handler;
1129 ih->enabled = TRUE;
1130 if (ih->fd >= 0)
1131 AddEnabledDevice(ih->fd);
1134 _X_EXPORT void
1135 xf86EnableGeneralHandler(pointer handler)
1137 IHPtr ih;
1139 if (!handler)
1140 return;
1142 ih = handler;
1143 ih->enabled = TRUE;
1144 if (ih->fd >= 0)
1145 AddGeneralSocket(ih->fd);
1149 * As used currently by the DRI, the return value is ignored.
1151 _X_EXPORT Bool
1152 xf86EnableVTSwitch(Bool new)
1154 static Bool def = TRUE;
1155 Bool old;
1157 old = VTSwitchEnabled;
1158 if (!new) {
1159 /* Disable VT switching */
1160 def = VTSwitchEnabled;
1161 VTSwitchEnabled = FALSE;
1162 } else {
1163 /* Restore VT switching to default */
1164 VTSwitchEnabled = def;
1166 return old;
1169 void
1170 xf86ReloadInputDevs(int sig)
1172 InputInfoPtr pInfo;
1174 signal(sig, (void(*)(int))xf86ReloadInputDevs);
1176 pInfo = xf86InputDevs;
1177 while (pInfo) {
1178 DisableDevice(pInfo->dev);
1179 EnableDevice(pInfo->dev);
1180 pInfo = pInfo->next;
1183 return;
1186 _X_EXPORT void
1187 DDXRingBell(int volume, int pitch, int duration) {
1188 xf86OSRingBell(volume, pitch, duration);