/* * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Thomas Roell not be used in * advertising or publicity pertaining to distribution of the software without * specific, written prior permission. Thomas Roell makes no representations * about the suitability of this software for any purpose. It is provided * "as is" without express or implied warranty. * * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * */ /* * Copyright (c) 1994-2003 by The XFree86 Project, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of the copyright holder(s) * and author(s) shall not be used in advertising or otherwise to promote * the sale, use or other dealings in this Software without prior written * authorization from the copyright holder(s) and author(s). */ /* [JCH-96/01/21] Extended std reverse map to four buttons. */ #ifdef HAVE_XORG_CONFIG_H #include #endif #ifdef __UNIXOS2__ #define I_NEED_OS2_H #endif #include #include #include #include "misc.h" #include "compiler.h" #include "xf86.h" #include "xf86Priv.h" #define XF86_OS_PRIVS #include "xf86_OSlib.h" #include "atKeynames.h" #ifdef XFreeXDGA #include "dgaproc.h" #endif #ifdef XINPUT #include #include #else #include "inputstr.h" #endif #include "xf86Xinput.h" #include "mi.h" #include "mipointer.h" #ifdef XF86BIGFONT #define _XF86BIGFONT_SERVER_ #include #endif #ifdef XKB extern Bool noXkbExtension; #endif #ifdef DPMSExtension #define DPMS_SERVER #include #include "dpmsproc.h" #endif #define XE_POINTER 1 #define XE_KEYBOARD 2 #ifdef XINPUT #define __EqEnqueue(ev) xf86eqEnqueue(ev) #else #define __EqEnqueue(ev) mieqEnqueue(ev) #endif #define EqEnqueue(ev) { \ int __sigstate = xf86BlockSIGIO (); \ __EqEnqueue (ev); \ xf86UnblockSIGIO(__sigstate); \ } #define ENQUEUE(ev, code, direction, dev_type) \ (ev)->u.u.detail = (code); \ (ev)->u.u.type = (direction); \ EqEnqueue((ev)) /* * The first of many hacks to get VT switching to work under * Solaris 2.1 for x86. The basic problem is that Solaris is supposed * to be SVR4. It is for the most part, except where the video interface * is concerned. These hacks work around those problems. * See the comments for Linux, and SCO. * * This is a toggling variable: * FALSE = No VT switching keys have been pressed last time around * TRUE = Possible VT switch Pending * (DWH - 12/2/93) * * This has been generalised to work with Linux and *BSD+syscons (DHD) */ #ifdef USE_VT_SYSREQ Bool VTSysreqToggle = FALSE; #endif /* !USE_VT_SYSREQ */ Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for *BSD and for avoiding VT switches when using the DRI automatic full screen mode.*/ extern fd_set EnabledDevices; #if defined(XQUEUE) extern void xf86XqueRequest(void); #endif #ifdef XF86PM extern void (*xf86OSPMClose)(void); #endif static void xf86VTSwitch(void); /* * Allow arbitrary drivers or other XFree86 code to register with our main * Wakeup handler. */ typedef struct x_IHRec { int fd; InputHandlerProc ihproc; pointer data; Bool enabled; struct x_IHRec * next; } IHRec, *IHPtr; static IHPtr InputHandlers = NULL; /* * TimeSinceLastInputEvent -- * Function used for screensaver purposes by the os module. Returns the * time in milliseconds since there last was any input. */ int TimeSinceLastInputEvent() { if (xf86Info.lastEventTime == 0) { xf86Info.lastEventTime = GetTimeInMillis(); } return GetTimeInMillis() - xf86Info.lastEventTime; } /* * SetTimeSinceLastInputEvent -- * Set the lastEventTime to now. */ _X_EXPORT void SetTimeSinceLastInputEvent() { xf86Info.lastEventTime = GetTimeInMillis(); } /* * ProcessInputEvents -- * Retrieve all waiting input events and pass them to DIX in their * correct chronological order. Only reads from the system pointer * and keyboard. */ void ProcessInputEvents () { int x, y; #ifdef INHERIT_LOCK_STATE static int generation = 0; #endif /* * With INHERIT_LOCK_STATE defined, the initial state of CapsLock, NumLock * and ScrollLock will be set to match that of the VT the server is * running on. */ #ifdef INHERIT_LOCK_STATE if (generation != serverGeneration) { xEvent kevent; DevicePtr pKeyboard = xf86Info.pKeyboard; extern unsigned int xf86InitialCaps, xf86InitialNum, xf86InitialScroll; generation = serverGeneration; kevent.u.keyButtonPointer.time = GetTimeInMillis(); kevent.u.keyButtonPointer.rootX = 0; kevent.u.keyButtonPointer.rootY = 0; kevent.u.u.type = KeyPress; if (xf86InitialCaps) { kevent.u.u.detail = xf86InitialCaps; (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1); xf86InitialCaps = 0; } if (xf86InitialNum) { kevent.u.u.detail = xf86InitialNum; (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1); xf86InitialNum = 0; } if (xf86InitialScroll) { kevent.u.u.detail = xf86InitialScroll; (* pKeyboard->processInputProc)(&kevent, (DeviceIntPtr)pKeyboard, 1); xf86InitialScroll = 0; } } #endif xf86Info.inputPending = FALSE; #ifdef XINPUT xf86eqProcessInputEvents(); #else mieqProcessInputEvents(); #endif miPointerUpdate(); miPointerPosition(&x, &y); xf86SetViewport(xf86Info.currentScreen, x, y); } void xf86GrabServerCallback(CallbackListPtr *callbacks, pointer data, pointer args) { ServerGrabInfoRec *grab = (ServerGrabInfoRec*)args; xf86Info.grabInfo.server.client = grab->client; xf86Info.grabInfo.server.grabstate = grab->grabstate; } /* * Handle keyboard events that cause some kind of "action" * (i.e., server termination, video mode changes, VT switches, etc.) */ void xf86ProcessActionEvent(ActionEvent action, void *arg) { #ifdef DEBUG ErrorF("ProcessActionEvent(%d,%x)\n", (int) action, arg); #endif switch (action) { case ACTION_TERMINATE: if (!xf86Info.dontZap) { #ifdef XFreeXDGA DGAShutdown(); #endif GiveUp(0); } break; case ACTION_NEXT_MODE: if (!xf86Info.dontZoom) xf86ZoomViewport(xf86Info.currentScreen, 1); break; case ACTION_PREV_MODE: if (!xf86Info.dontZoom) xf86ZoomViewport(xf86Info.currentScreen, -1); break; case ACTION_DISABLEGRAB: if (!xf86Info.grabInfo.disabled && xf86Info.grabInfo.allowDeactivate) { if (inputInfo.pointer && inputInfo.pointer->grab != NULL && inputInfo.pointer->DeactivateGrab) inputInfo.pointer->DeactivateGrab(inputInfo.pointer); if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL && inputInfo.keyboard->DeactivateGrab) inputInfo.keyboard->DeactivateGrab(inputInfo.keyboard); } break; case ACTION_CLOSECLIENT: if (!xf86Info.grabInfo.disabled && xf86Info.grabInfo.allowClosedown) { ClientPtr pointer, keyboard, server; pointer = keyboard = server = NULL; if (inputInfo.pointer && inputInfo.pointer->grab != NULL) pointer = clients[CLIENT_ID(inputInfo.pointer->grab->resource)]; if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL) { keyboard = clients[CLIENT_ID(inputInfo.keyboard->grab->resource)]; if (keyboard == pointer) keyboard = NULL; } if ((xf86Info.grabInfo.server.grabstate == SERVER_GRABBED) && (((server = xf86Info.grabInfo.server.client) == pointer) || (server == keyboard))) server = NULL; if (pointer) CloseDownClient(pointer); if (keyboard) CloseDownClient(keyboard); if (server) CloseDownClient(server); } break; #if !defined(__SOL8__) && !defined(__UNIXOS2__) && !defined(sgi) && \ (!defined(sun) || defined(i386)) && defined(VT_ACTIVATE) case ACTION_SWITCHSCREEN: if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) { int vtno = *((int *) arg); #if defined(__SCO__) || defined(__UNIXWARE__) vtno--; #endif #if defined(QNX4) xf86Info.vtRequestsPending = vtno; #else if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vtno) < 0) ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); #endif } break; case ACTION_SWITCHSCREEN_NEXT: if (VTSwitchEnabled && !xf86Info.dontVTSwitch) { /* Shouldn't this be true for (sun) && (i386) && (SVR4) ? */ #if defined(__SCO__) || defined(__UNIXWARE__) if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno) < 0) #else if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno + 1) < 0) #endif #if defined (__SCO__) || (defined(sun) && defined (i386) && defined (SVR4)) || defined(__UNIXWARE__) if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 0) < 0) #else if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, 1) < 0) #endif ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); } break; case ACTION_SWITCHSCREEN_PREV: if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) { if (ioctl(xf86Info.consoleFd, VT_ACTIVATE, xf86Info.vtno - 1) < 0) ErrorF("Failed to switch consoles (%s)\n", strerror(errno)); } break; #endif case ACTION_MESSAGE: { char *retstr, *message = (char *) arg; ScrnInfoPtr pScr = XF86SCRNINFO(xf86Info.currentScreen); #ifdef DEBUG ErrorF("ActionMessage: '%s'\n", message); #endif /* Okay the message made it to the ddx. The common layer */ /* can check for relevant messages here and react to any */ /* that have a global effect. For example: */ /* */ /* if (!strcmp(message, "foo") { */ /* do_foo(); break */ /* } */ /* */ /* otherwise fallback to sending a key event message to */ /* the current screen's driver: */ if (*pScr->HandleMessage != NULL) { (void) (*pScr->HandleMessage)(pScr->scrnIndex, "KeyEventMessage", message, &retstr); } } break; default: break; } } /* * xf86PostKbdEvent -- * Translate the raw hardware KbdEvent into an XEvent, and tell DIX * about it. Scancode preprocessing and so on is done ... * * OS/2 specific xf86PostKbdEvent(key) has been moved to os-support/os2/os2_kbd.c * as some things differ, and I did not want to scatter this routine with * ifdefs further (hv). */ #ifdef __linux__ extern u_char SpecialServerMap[]; #endif #if !defined(__UNIXOS2__) void xf86PostKbdEvent(unsigned key) { int scanCode = (key & 0x7f); int specialkey = 0; Bool down = (key & 0x80 ? FALSE : TRUE); KeyClassRec *keyc = ((DeviceIntPtr)xf86Info.pKeyboard)->key; Bool updateLeds = FALSE; Bool UsePrefix = FALSE; Bool Direction = FALSE; xEvent kevent; KeySym *keysym; int keycode; static int lockkeys = 0; #if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT) static Bool first_time = TRUE; #endif #if defined(__sparc__) && defined(__linux__) static int kbdSun = -1; #endif /* Disable any keyboard processing while in suspend */ if (xf86inSuspend) return; #if defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT) if (first_time) { first_time = FALSE; VTSwitchEnabled = (xf86Info.consType == SYSCONS) || (xf86Info.consType == PCVT); } #endif #if defined (__sparc__) && defined(__linux__) if (kbdSun == -1) { if ((xf86Info.xkbmodel && !strcmp(xf86Info.xkbmodel, "sun")) || (xf86Info.xkbrules && !strcmp(xf86Info.xkbrules, "sun"))) kbdSun = 1; else kbdSun = 0; } if (kbdSun) goto special; #endif /* __sparc__ && __linux__ */ #ifdef __linux__ if (xf86Info.kbdCustomKeycodes) { specialkey = SpecialServerMap[scanCode]; goto customkeycodes; } #endif /* * First do some special scancode remapping ... */ if (xf86Info.scanPrefix == 0) { switch (scanCode) { case KEY_Prefix0: case KEY_Prefix1: #if defined(PCCONS_SUPPORT) || defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT) if (xf86Info.consType == PCCONS || xf86Info.consType == SYSCONS || xf86Info.consType == PCVT #ifdef WSCONS_SUPPORT || (xf86Info.consType == WSCONS && xf86Info.kbdEvents != xf86WSKbdEvents) #endif ) { #endif xf86Info.scanPrefix = scanCode; /* special prefixes */ return; #if defined(PCCONS_SUPPORT) || defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT) } break; #endif } #if defined (i386) && defined (SVR4) /* * PANIX returns DICOP standards based keycodes in using 106jp * keyboard. We need to remap some keys. */ if(xf86Info.panix106 == TRUE){ switch (scanCode) { case 0x56: scanCode = KEY_BSlash2; break; /* Backslash */ case 0x5A: scanCode = KEY_NFER; break; /* No Kanji Transfer*/ case 0x5B: scanCode = KEY_XFER; break; /* Kanji Tranfer */ case 0x5C: scanCode = KEY_Yen; break; /* Yen curs pgup */ case 0x6B: scanCode = KEY_Left; break; /* Cur Left */ case 0x6F: scanCode = KEY_PgUp; break; /* Cur PageUp */ case 0x72: scanCode = KEY_AltLang; break; /* AltLang(right) */ case 0x73: scanCode = KEY_RCtrl; break; /* not needed */ } } else #endif /* i386 && SVR4 */ #ifndef __OpenBSD__ { switch (scanCode) { case 0x59: scanCode = KEY_0x59; break; case 0x5a: scanCode = KEY_0x5A; break; case 0x5b: scanCode = KEY_0x5B; break; case 0x5c: scanCode = KEY_KP_Equal; break; /* Keypad Equal */ case 0x5d: scanCode = KEY_0x5D; break; case 0x5e: scanCode = KEY_0x5E; break; case 0x5f: scanCode = KEY_0x5F; break; case 0x62: scanCode = KEY_0x62; break; case 0x63: scanCode = KEY_0x63; break; case 0x64: scanCode = KEY_0x64; break; case 0x65: scanCode = KEY_0x65; break; case 0x66: scanCode = KEY_0x66; break; case 0x67: scanCode = KEY_0x67; break; case 0x68: scanCode = KEY_0x68; break; case 0x69: scanCode = KEY_0x69; break; case 0x6a: scanCode = KEY_0x6A; break; case 0x6b: scanCode = KEY_0x6B; break; case 0x6c: scanCode = KEY_0x6C; break; case 0x6d: scanCode = KEY_0x6D; break; case 0x6e: scanCode = KEY_0x6E; break; case 0x6f: scanCode = KEY_0x6F; break; case 0x70: scanCode = KEY_0x70; break; case 0x71: scanCode = KEY_0x71; break; case 0x72: scanCode = KEY_0x72; break; case 0x73: scanCode = KEY_0x73; break; case 0x74: scanCode = KEY_0x74; break; case 0x75: scanCode = KEY_0x75; break; case 0x76: scanCode = KEY_0x76; break; } } #endif } else if ( #ifdef CSRG_BASED (xf86Info.consType == PCCONS || xf86Info.consType == SYSCONS || xf86Info.consType == PCVT #ifdef WSCONS_SUPPORT || (xf86Info.consType == WSCONS && xf86Info.kbdEvents != xf86WSKbdEvents) #endif ) && #endif (xf86Info.scanPrefix == KEY_Prefix0)) { xf86Info.scanPrefix = 0; switch (scanCode) { case KEY_KP_7: scanCode = KEY_Home; break; /* curs home */ case KEY_KP_8: scanCode = KEY_Up; break; /* curs up */ case KEY_KP_9: scanCode = KEY_PgUp; break; /* curs pgup */ case KEY_KP_4: scanCode = KEY_Left; break; /* curs left */ case KEY_KP_5: scanCode = KEY_Begin; break; /* curs begin */ case KEY_KP_6: scanCode = KEY_Right; break; /* curs right */ case KEY_KP_1: scanCode = KEY_End; break; /* curs end */ case KEY_KP_2: scanCode = KEY_Down; break; /* curs down */ case KEY_KP_3: scanCode = KEY_PgDown; break; /* curs pgdown */ case KEY_KP_0: scanCode = KEY_Insert; break; /* curs insert */ case KEY_KP_Decimal: scanCode = KEY_Delete; break; /* curs delete */ case KEY_Enter: scanCode = KEY_KP_Enter; break; /* keypad enter */ case KEY_LCtrl: scanCode = KEY_RCtrl; break; /* right ctrl */ case KEY_KP_Multiply: scanCode = KEY_Print; break; /* print */ case KEY_Slash: scanCode = KEY_KP_Divide; break; /* keyp divide */ case KEY_Alt: scanCode = KEY_AltLang; break; /* right alt */ case KEY_ScrollLock: scanCode = KEY_Break; break; /* curs break */ case 0x5b: scanCode = KEY_LMeta; break; case 0x5c: scanCode = KEY_RMeta; break; case 0x5d: scanCode = KEY_Menu; break; case KEY_F3: scanCode = KEY_F13; break; case KEY_F4: scanCode = KEY_F14; break; case KEY_F5: scanCode = KEY_F15; break; case KEY_F6: scanCode = KEY_F16; break; case KEY_F7: scanCode = KEY_F17; break; case KEY_KP_Plus: scanCode = KEY_KP_DEC; break; /* * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */ case 0x2A: case 0x36: return; default: xf86MsgVerb(X_INFO, 4, "Unreported Prefix0 scancode: 0x%02x\n", scanCode); /* * "Internet" keyboards are generating lots of new codes. Let them * pass. There is little consistency between them, so don't bother * with symbolic names at this level. */ scanCode += 0x78; } } else if (xf86Info.scanPrefix == KEY_Prefix1) { xf86Info.scanPrefix = (scanCode == KEY_LCtrl) ? KEY_LCtrl : 0; return; } else if (xf86Info.scanPrefix == KEY_LCtrl) { xf86Info.scanPrefix = 0; if (scanCode != KEY_NumLock) return; scanCode = KEY_Pause; /* pause */ } #ifndef __sparc64__ /* * PC keyboards generate separate key codes for * Alt+Print and Control+Pause but in the X keyboard model * they need to get the same key code as the base key on the same * physical keyboard key. */ if (scanCode == KEY_SysReqest) scanCode = KEY_Print; else if (scanCode == KEY_Break) scanCode = KEY_Pause; #endif /* * and now get some special keysequences */ specialkey = scanCode; #ifdef __linux__ customkeycodes: #endif #if defined(i386) || defined(__i386__) if (xf86IsPc98()) { switch (scanCode) { case 0x0e: specialkey = 0x0e; break; /* KEY_BackSpace */ case 0x40: specialkey = 0x4a; break; /* KEY_KP_Minus */ case 0x49: specialkey = 0x4e; break; /* KEY_KP_Plus */ /* XXX needs cases for KEY_KP_Divide and KEY_KP_Multiply */ case 0x62: specialkey = 0x3b; break; /* KEY_F1 */ case 0x63: specialkey = 0x3c; break; /* KEY_F2 */ case 0x64: specialkey = 0x3d; break; /* KEY_F3 */ case 0x65: specialkey = 0x3e; break; /* KEY_F4 */ case 0x66: specialkey = 0x3f; break; /* KEY_F5 */ case 0x67: specialkey = 0x40; break; /* KEY_F6 */ case 0x68: specialkey = 0x41; break; /* KEY_F7 */ case 0x69: specialkey = 0x42; break; /* KEY_F8 */ case 0x6a: specialkey = 0x43; break; /* KEY_F9 */ case 0x6b: specialkey = 0x44; break; /* KEY_F10 */ /* case 0x73: specialkey = 0x38; break; KEY_Alt */ /* case 0x74: specialkey = 0x1d; break; KEY_LCtrl */ default: specialkey = 0x00; break; } } #endif #if defined (__sparc__) && defined(__linux__) special: if (kbdSun) { switch (scanCode) { case 0x2b: specialkey = KEY_BackSpace; break; case 0x47: specialkey = KEY_KP_Minus; break; case 0x7d: specialkey = KEY_KP_Plus; break; /* XXX needs cases for KEY_KP_Divide and KEY_KP_Multiply */ case 0x05: specialkey = KEY_F1; break; case 0x06: specialkey = KEY_F2; break; case 0x08: specialkey = KEY_F3; break; case 0x0a: specialkey = KEY_F4; break; case 0x0c: specialkey = KEY_F5; break; case 0x0e: specialkey = KEY_F6; break; case 0x10: specialkey = KEY_F7; break; case 0x11: specialkey = KEY_F8; break; case 0x12: specialkey = KEY_F9; break; case 0x07: specialkey = KEY_F10; break; case 0x09: specialkey = KEY_F11; break; case 0x0b: specialkey = KEY_F12; break; default: specialkey = 0; break; } /* * XXX XXX XXX: * * I really don't know what's wrong here, but passing the real * scanCode offsets by one from XKB's point of view. * * (ecd@skynet.be, 980405) */ scanCode--; } #endif /* defined (__sparc__) && defined(__linux__) */ #ifdef XKB if ((xf86Info.ddxSpecialKeys == SKWhenNeeded && !xf86Info.ActionKeyBindingsSet) || noXkbExtension || xf86Info.ddxSpecialKeys == SKAlways) { #endif if (!(ModifierDown(ShiftMask)) && ((ModifierDown(ControlMask | AltMask)) || (ModifierDown(ControlMask | AltLangMask)))) { switch (specialkey) { case KEY_BackSpace: xf86ProcessActionEvent(ACTION_TERMINATE, NULL); break; /* * Check grabs */ case KEY_KP_Divide: xf86ProcessActionEvent(ACTION_DISABLEGRAB, NULL); break; case KEY_KP_Multiply: xf86ProcessActionEvent(ACTION_CLOSECLIENT, NULL); break; /* * Video mode switches */ case KEY_KP_Minus: /* Keypad - */ if (down) xf86ProcessActionEvent(ACTION_PREV_MODE, NULL); if (!xf86Info.dontZoom) return; break; case KEY_KP_Plus: /* Keypad + */ if (down) xf86ProcessActionEvent(ACTION_NEXT_MODE, NULL); if (!xf86Info.dontZoom) return; break; /* Under QNX4, we set the vtPending flag for VT switching and * let the VT switch function do the rest... * This is a little different from the other OS'es. */ #if defined(QNX4) case KEY_1: case KEY_2: case KEY_3: case KEY_4: case KEY_5: case KEY_6: case KEY_7: case KEY_8: case KEY_9: if (VTSwitchEnabled && !xf86Info.dontVTSwitch) { if (down) { int vtno = specialkey - KEY_1 + 1; xf86ProcessActionEvent(ACTION_SWITCHSCREEN, (void *) &vtno); } return; } break; #endif #if defined(linux) || (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT))) || defined(__SCO__) || defined(__UNIXWARE__) /* * Under Linux, the raw keycodes are consumed before the kernel * does any processing on them, so we must emulate the vt switching * we want ourselves. */ case KEY_F1: case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: case KEY_F11: case KEY_F12: if ((VTSwitchEnabled && !xf86Info.vtSysreq && !xf86Info.dontVTSwitch) #if (defined(CSRG_BASED) && (defined(SYSCONS_SUPPORT) || defined(PCVT_SUPPORT) || defined(WSCONS_SUPPORT))) && (xf86Info.consType == SYSCONS || xf86Info.consType == PCVT) #endif ) { int vtno = specialkey - KEY_F1 + 1; if (specialkey == KEY_F11 || specialkey == KEY_F12) vtno = specialkey - KEY_F11 + 11; if (down) xf86ProcessActionEvent(ACTION_SWITCHSCREEN, (void *) &vtno); return; } break; #endif /* linux || BSD with VTs */ /* just worth mentioning here: any 386bsd keyboard driver * (pccons.c or co_kbd.c) catches CTRL-ALT-DEL and CTRL-ALT-ESC * before any application (e.g. XF86) will see it * OBS: syscons does not, nor does pcvt ! */ } } /* * Start of actual Solaris VT switching code. * This should pretty much emulate standard SVR4 switching keys. * * DWH 12/2/93 */ #ifdef USE_VT_SYSREQ if (VTSwitchEnabled && xf86Info.vtSysreq && !xf86Info.dontVTSwitch) { switch (specialkey) { /* * syscons on *BSD doesn't have a VT #0 -- don't think Linux does * either */ #if defined (sun) && defined (i386) && defined (SVR4) case KEY_H: if (VTSysreqToggle && down) { xf86ProcessActionEvent(ACTION_SWITCHSCREEN, NULL); VTSysreqToggle = 0; return; } break; /* * Yah, I know the N, and P keys seem backwards, however that's * how they work under Solaris * XXXX N means go to next active VT not necessarily vtno+1 (or vtno-1) */ case KEY_N: if (VTSysreqToggle && down) { xf86ProcessActionEvent(ACTION_SWITCHSCREEN_NEXT, NULL); VTSysreqToggle = FALSE; return; } break; case KEY_P: if (VTSysreqToggle && down) { xf86ProcessActionEvent(ACTION_SWITCHSCREEN_NEXT, NULL); VTSysreqToggle = FALSE; return; } break; #endif case KEY_F1: case KEY_F2: case KEY_F3: case KEY_F4: case KEY_F5: case KEY_F6: case KEY_F7: case KEY_F8: case KEY_F9: case KEY_F10: case KEY_F11: case KEY_F12: if (VTSysreqToggle && down) { int vtno = specialkey - KEY_F1 + 1; if (specialkey == KEY_F11 || specialkey == KEY_F12) vtno = specialkey - KEY_F11 + 11; xf86ProcessActionEvent(ACTION_SWITCHSCREEN, (void *) &vtno); VTSysreqToggle = FALSE; return; } break; /* Ignore these keys -- ie don't let them cancel an alt-sysreq */ case KEY_Alt: case KEY_AltLang: break; case KEY_SysReqest: if (down && (ModifierDown(AltMask) || ModifierDown(AltLangMask))) VTSysreqToggle = TRUE; break; default: if (VTSysreqToggle) { /* * We only land here when Alt-SysReq is followed by a * non-switching key. */ VTSysreqToggle = FALSE; } } } #endif /* USE_VT_SYSREQ */ #ifdef __SCO__ /* * With the console in raw mode, SCO will not switch consoles, * you get around this by activating the next console along, if * this fails then go back to console 0, if there is only one * then it doesn't matter, switching to yourself is a nop as far * as the console driver is concerned. * We could do something similar to linux here but SCO ODT uses * Ctrl-PrintScrn, so why change? */ if (specialkey == KEY_Print && ModifierDown(ControlMask)) { if (down) xf86ProcessActionEvent(ACTION_SWITCHSCREEN_NEXT, NULL); return; } #endif /* __SCO__ */ #ifdef XKB } #endif /* * Now map the scancodes to real X-keycodes ... */ keycode = scanCode + MIN_KEYCODE; keysym = (keyc->curKeySyms.map + keyc->curKeySyms.mapWidth * (keycode - keyc->curKeySyms.minKeyCode)); #ifdef XKB if (noXkbExtension) { #endif /* * Filter autorepeated caps/num/scroll lock keycodes. */ #define CAPSFLAG 0x01 #define NUMFLAG 0x02 #define SCROLLFLAG 0x04 #define MODEFLAG 0x08 if( down ) { switch( keysym[0] ) { case XK_Caps_Lock : if (lockkeys & CAPSFLAG) return; else lockkeys |= CAPSFLAG; break; case XK_Num_Lock : if (lockkeys & NUMFLAG) return; else lockkeys |= NUMFLAG; break; case XK_Scroll_Lock : if (lockkeys & SCROLLFLAG) return; else lockkeys |= SCROLLFLAG; break; } if (keysym[1] == XF86XK_ModeLock) { if (lockkeys & MODEFLAG) return; else lockkeys |= MODEFLAG; } } else { switch( keysym[0] ) { case XK_Caps_Lock : lockkeys &= ~CAPSFLAG; break; case XK_Num_Lock : lockkeys &= ~NUMFLAG; break; case XK_Scroll_Lock : lockkeys &= ~SCROLLFLAG; break; } if (keysym[1] == XF86XK_ModeLock) lockkeys &= ~MODEFLAG; } /* * LockKey special handling: * ignore releases, toggle on & off on presses. * Don't deal with the Caps_Lock keysym directly, but check the lock modifier */ if (keyc->modifierMap[keycode] & LockMask || keysym[0] == XK_Scroll_Lock || keysym[1] == XF86XK_ModeLock || keysym[0] == XK_Num_Lock) { Bool flag; if (!down) return; if (KeyPressed(keycode)) { down = !down; flag = FALSE; } else flag = TRUE; if (keyc->modifierMap[keycode] & LockMask) xf86Info.capsLock = flag; if (keysym[0] == XK_Num_Lock) xf86Info.numLock = flag; if (keysym[0] == XK_Scroll_Lock) xf86Info.scrollLock = flag; if (keysym[1] == XF86XK_ModeLock) xf86Info.modeSwitchLock = flag; updateLeds = TRUE; } if (!xf86Info.kbdCustomKeycodes) { /* * normal, non-keypad keys */ if (scanCode < KEY_KP_7 || scanCode > KEY_KP_Decimal) { #if !defined(CSRG_BASED) && \ !defined(__GNU__) && \ defined(KB_84) /* * magic ALT_L key on AT84 keyboards for multilingual support */ if (xf86Info.kbdType == KB_84 && ModifierDown(AltMask) && keysym[2] != NoSymbol) { UsePrefix = TRUE; Direction = TRUE; } #endif /* !CSRG_BASED && ... */ } } if (updateLeds) xf86UpdateKbdLeds(); #ifdef XKB } #endif /* * check for an autorepeat-event */ if (down && KeyPressed(keycode)) { KbdFeedbackClassRec *kbdfeed = ((DeviceIntPtr)xf86Info.pKeyboard)->kbdfeed; if ((xf86Info.autoRepeat != AutoRepeatModeOn) || keyc->modifierMap[keycode] || (kbdfeed && !(kbdfeed->ctrl.autoRepeats[keycode>>3] & ( 1<<(keycode&7) )))) return; } xf86Info.lastEventTime = kevent.u.keyButtonPointer.time = GetTimeInMillis(); /* * And now send these prefixes ... * NOTE: There cannot be multiple Mode_Switch keys !!!! */ if (UsePrefix) { ENQUEUE(&kevent, keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], (Direction ? KeyPress : KeyRelease), XE_KEYBOARD); ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD); ENQUEUE(&kevent, keyc->modifierKeyMap[keyc->maxKeysPerModifier*7], (Direction ? KeyRelease : KeyPress), XE_KEYBOARD); } else { ENQUEUE(&kevent, keycode, (down ? KeyPress : KeyRelease), XE_KEYBOARD); } } #endif /* !__UNIXOS2__ */ #define ModifierIsSet(k) ((modifiers & (k)) == (k)) _X_EXPORT Bool xf86CommonSpecialKey(int key, Bool down, int modifiers) { if ((!ModifierIsSet(ShiftMask)) && (((ModifierIsSet(ControlMask | AltMask)) || (ModifierIsSet(ControlMask | AltLangMask))))) { switch (key) { case KEY_BackSpace: xf86ProcessActionEvent(ACTION_TERMINATE, NULL); break; /* * Check grabs */ case KEY_KP_Divide: xf86ProcessActionEvent(ACTION_DISABLEGRAB, NULL); break; case KEY_KP_Multiply: xf86ProcessActionEvent(ACTION_CLOSECLIENT, NULL); break; /* * The idea here is to pass the scancode down to a list of * registered routines. There should be some standard conventions * for processing certain keys. */ case KEY_KP_Minus: /* Keypad - */ if (down) xf86ProcessActionEvent(ACTION_PREV_MODE, NULL); if (!xf86Info.dontZoom) return TRUE; break; case KEY_KP_Plus: /* Keypad + */ if (down) xf86ProcessActionEvent(ACTION_NEXT_MODE, NULL); if (!xf86Info.dontZoom) return TRUE; break; } } return FALSE; } /* * xf86Wakeup -- * Os wakeup handler. */ /* ARGSUSED */ void xf86Wakeup(pointer blockData, int err, pointer pReadmask) { #if !defined(__UNIXOS2__) && !defined(__QNX__) fd_set* LastSelectMask = (fd_set*)pReadmask; fd_set devicesWithInput; InputInfoPtr pInfo; if (err >= 0) { XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices); if (XFD_ANYSET(&devicesWithInput)) { if (xf86Info.kbdEvents) (xf86Info.kbdEvents)(); pInfo = xf86InputDevs; while (pInfo) { if (pInfo->read_input && pInfo->fd >= 0 && (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) { int sigstate = xf86BlockSIGIO(); pInfo->read_input(pInfo); xf86UnblockSIGIO(sigstate); /* * Remove the descriptior from the set because more than one * device may share the same file descriptor. */ FD_CLR(pInfo->fd, &devicesWithInput); } pInfo = pInfo->next; } } } #else /* __UNIXOS2__ and __QNX__ */ InputInfoPtr pInfo; (xf86Info.kbdEvents)(); /* Under OS/2 and QNX, always call */ pInfo = xf86InputDevs; while (pInfo) { if (pInfo->read_input && pInfo->fd >= 0) { int sigstate = xf86BlockSIGIO(); pInfo->read_input(pInfo); xf86UnblockSIGIO(sigstate); /* * Must break here because more than one device may share * the same file descriptor. */ break; } pInfo = pInfo->next; } #endif /* __UNIXOS2__ and __QNX__ */ if (err >= 0) { /* we don't want the handlers called if select() */ IHPtr ih; /* returned with an error condition, do we? */ for (ih = InputHandlers; ih; ih = ih->next) { if (ih->enabled && ih->fd >= 0 && ih->ihproc && (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) { ih->ihproc(ih->fd, ih->data); } } } if (xf86VTSwitchPending()) xf86VTSwitch(); if (xf86Info.inputPending) ProcessInputEvents(); } /* * xf86SigioReadInput -- * signal handler for the SIGIO signal. */ static void xf86SigioReadInput(int fd, void *closure) { int sigstate = xf86BlockSIGIO(); InputInfoPtr pInfo = (InputInfoPtr) closure; pInfo->read_input(pInfo); xf86UnblockSIGIO(sigstate); } /* * xf86AddEnabledDevice -- * */ _X_EXPORT void xf86AddEnabledDevice(InputInfoPtr pInfo) { if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) { AddEnabledDevice(pInfo->fd); } } /* * xf86RemoveEnabledDevice -- * */ _X_EXPORT void xf86RemoveEnabledDevice(InputInfoPtr pInfo) { if (!xf86RemoveSIGIOHandler (pInfo->fd)) { RemoveEnabledDevice(pInfo->fd); } } static int *xf86SignalIntercept = NULL; _X_EXPORT void xf86InterceptSignals(int *signo) { if ((xf86SignalIntercept = signo)) *signo = -1; } static void (*xf86SigIllHandler)(void) = NULL; _X_EXPORT void xf86InterceptSigIll(void (*sigillhandler)(void)) { xf86SigIllHandler = sigillhandler; } #ifdef HAVE_BACKTRACE #include static __inline__ void xorg_backtrace(void) { void *array[32]; /* deeper nesting than this means something's wrong */ size_t size, i; char **strings; ErrorF("\nBacktrace:\n"); size = backtrace(array, 32); strings = backtrace_symbols(array, size); for (i = 0; i < size; i++) ErrorF("%d: %s\n", i, strings[i]); free(strings); } #else /* not glibc or glibc < 2.1 */ # if defined(sun) && defined(__SVR4) # define HAVE_PSTACK # endif # if defined(HAVE_WALKCONTEXT) /* Solaris 9 & later */ # include # include # include # include #ifdef _LP64 # define ElfSym Elf64_Sym #else # define ElfSym Elf32_Sym #endif /* Called for each frame on the stack to print it's contents */ static int xorg_backtrace_frame(uintptr_t pc, int signo, void *arg) { Dl_info dlinfo; ElfSym *dlsym; char header[32]; int depth = *((int *) arg); if (signo) { char signame[SIG2STR_MAX]; if (sig2str(signo, signame) != 0) { strcpy(signame, "unknown"); } ErrorF("** Signal %d (%s)\n", signo, signame); } snprintf(header, sizeof(header), "%d: 0x%lx", depth, pc); *((int *) arg) = depth + 1; /* Ask system dynamic loader for info on the address */ if (dladdr1((void *) pc, &dlinfo, (void **) &dlsym, RTLD_DL_SYMENT)) { unsigned long offset = pc - (uintptr_t) dlinfo.dli_saddr; const char *symname; if (offset < dlsym->st_size) { /* inside a function */ symname = dlinfo.dli_sname; } else { /* found which file it was in, but not which function */ symname = "
"; offset = pc - (uintptr_t)dlinfo.dli_fbase; } ErrorF("%s: %s:%s+0x%lx\n", header, dlinfo.dli_fname, symname, offset); } else { /* Couldn't find symbol info from system dynamic loader, should * probably poke elfloader here, but haven't written that code yet, * so we just print the pc. */ ErrorF("%s\n", header); } return 0; } # endif /* HAVE_WALKCONTEXT */ # ifdef HAVE_PSTACK static int xorg_backtrace_pstack(void) { pid_t kidpid; int pipefd[2]; if (pipe(pipefd) != 0) { return -1; } kidpid = fork1(); if (kidpid == -1) { /* ERROR */ return -1; } else if (kidpid == 0) { /* CHILD */ char parent[16]; seteuid(0); close(STDIN_FILENO); close(STDOUT_FILENO); dup2(pipefd[1],STDOUT_FILENO); closefrom(STDERR_FILENO); snprintf(parent, sizeof(parent), "%d", getppid()); execle("/usr/bin/pstack", "pstack", parent, NULL); exit(1); } else { /* PARENT */ char btline[256]; int kidstat; int bytesread; int done = 0; close(pipefd[1]); while (!done) { bytesread = read(pipefd[0], btline, sizeof(btline) - 1); if (bytesread > 0) { btline[bytesread] = 0; ErrorF("%s", btline); } else if ((bytesread < 0) || ((errno != EINTR) && (errno != EAGAIN))) done = 1; } close(pipefd[0]); waitpid(kidpid, &kidstat, 0); if (kidstat != 0) return -1; } return 0; } # endif /* HAVE_PSTACK */ # if defined(HAVE_PSTACK) || defined(HAVE_WALKCONTEXT) static __inline__ void xorg_backtrace(void) { ErrorF("\nBacktrace:\n"); # ifdef HAVE_PSTACK /* First try fork/exec of pstack - otherwise fall back to walkcontext pstack is preferred since it can print names of non-exported functions */ if (xorg_backtrace_pstack() < 0) # endif { # ifdef HAVE_WALKCONTEXT ucontext_t u; int depth = 1; if (getcontext(&u) == 0) walkcontext(&u, xorg_backtrace_frame, &depth); else # endif Error("Failed to get backtrace info"); } ErrorF("\n"); } # else /* Default fallback if we can't find any way to get a backtrace */ static __inline__ void xorg_backtrace(void) { return; } # endif #endif /* * xf86SigHandler -- * Catch unexpected signals and exit or continue cleanly. */ void xf86SigHandler(int signo) { if ((signo == SIGILL) && xf86SigIllHandler) { (*xf86SigIllHandler)(); /* Re-arm handler just in case we unexpectedly return here */ (void) signal(signo, xf86SigHandler); return; } if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) { *xf86SignalIntercept = signo; /* Re-arm handler just in case */ (void) signal(signo, xf86SigHandler); return; } signal(signo,SIG_IGN); xf86Info.caughtSignal = TRUE; #ifdef XF86BIGFONT XF86BigfontCleanup(); #endif xorg_backtrace(); FatalError("Caught signal %d. Server aborting\n", signo); } #ifdef MEMDEBUG void xf86SigMemDebug(int signo) { CheckMemory(); (void) signal(signo, xf86SigMemDebug); return; } #endif /* * xf86VTSwitch -- * Handle requests for switching the vt. */ static void xf86VTSwitch() { int i, prevSIGIO; InputInfoPtr pInfo; IHPtr ih; #ifdef DEBUG ErrorF("xf86VTSwitch()\n"); #endif #ifdef XFreeXDGA if(!DGAVTSwitch()) return; #endif /* * Since all screens are currently all in the same state it is sufficient * check the first. This might change in future. */ if (xf86Screens[0]->vtSema) { #ifdef DEBUG ErrorF("xf86VTSwitch: Leaving, xf86Exiting is %s\n", BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE)); #endif #ifdef DPMSExtension if (DPMSPowerLevel != DPMSModeOn) DPMSSet(DPMSModeOn); #endif for (i = 0; i < xf86NumScreens; i++) { if (!(dispatchException & DE_TERMINATE)) if (xf86Screens[i]->EnableDisableFBAccess) (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE); } #if !defined(__UNIXOS2__) /* * Keep the order: Disable Device > LeaveVT * EnterVT > EnableDevice */ DisableDevice((DeviceIntPtr)xf86Info.pKeyboard); pInfo = xf86InputDevs; while (pInfo) { DisableDevice(pInfo->dev); pInfo = pInfo->next; } #endif /* !__UNIXOS2__ */ xf86EnterServerState(SETUP); for (i = 0; i < xf86NumScreens; i++) xf86Screens[i]->LeaveVT(i, 0); for (ih = InputHandlers; ih; ih = ih->next) xf86DisableInputHandler(ih); xf86AccessLeave(); /* We need this here, otherwise */ xf86AccessLeaveState(); /* console won't be restored */ if (!xf86VTSwitchAway()) { /* * switch failed */ #ifdef DEBUG ErrorF("xf86VTSwitch: Leave failed\n"); #endif prevSIGIO = xf86BlockSIGIO(); xf86AccessEnter(); xf86EnterServerState(SETUP); for (i = 0; i < xf86NumScreens; i++) { if (!xf86Screens[i]->EnterVT(i, 0)) FatalError("EnterVT failed for screen %d\n", i); } xf86EnterServerState(OPERATING); if (!(dispatchException & DE_TERMINATE)) { for (i = 0; i < xf86NumScreens; i++) { if (xf86Screens[i]->EnableDisableFBAccess) (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE); } } SaveScreens(SCREEN_SAVER_FORCER, ScreenSaverReset); #if !defined(__UNIXOS2__) EnableDevice((DeviceIntPtr)xf86Info.pKeyboard); pInfo = xf86InputDevs; while (pInfo) { EnableDevice(pInfo->dev); pInfo = pInfo->next; } #endif /* !__UNIXOS2__ */ for (ih = InputHandlers; ih; ih = ih->next) xf86EnableInputHandler(ih); xf86UnblockSIGIO(prevSIGIO); } else { #ifdef XF86PM if (xf86OSPMClose) xf86OSPMClose(); xf86OSPMClose = NULL; #endif for (i = 0; i < xf86NumScreens; i++) { /* * zero all access functions to * trap calls when switched away. */ xf86Screens[i]->vtSema = FALSE; xf86Screens[i]->access = NULL; xf86Screens[i]->busAccess = NULL; } if (xorgHWAccess) xf86DisableIO(); } } else { #ifdef DEBUG ErrorF("xf86VTSwitch: Entering\n"); #endif if (!xf86VTSwitchTo()) return; prevSIGIO = xf86BlockSIGIO(); #ifdef XF86PM xf86OSPMClose = xf86OSPMOpen(); #endif if (xorgHWAccess) xf86EnableIO(); xf86AccessEnter(); xf86EnterServerState(SETUP); for (i = 0; i < xf86NumScreens; i++) { xf86Screens[i]->vtSema = TRUE; if (!xf86Screens[i]->EnterVT(i, 0)) FatalError("EnterVT failed for screen %d\n", i); } xf86EnterServerState(OPERATING); for (i = 0; i < xf86NumScreens; i++) { if (xf86Screens[i]->EnableDisableFBAccess) (*xf86Screens[i]->EnableDisableFBAccess)(i, TRUE); } /* Turn screen saver off when switching back */ SaveScreens(SCREEN_SAVER_FORCER,ScreenSaverReset); #if !defined(__UNIXOS2__) EnableDevice((DeviceIntPtr)xf86Info.pKeyboard); pInfo = xf86InputDevs; while (pInfo) { EnableDevice(pInfo->dev); pInfo = pInfo->next; } #endif /* !__UNIXOS2__ */ for (ih = InputHandlers; ih; ih = ih->next) xf86EnableInputHandler(ih); xf86UnblockSIGIO(prevSIGIO); } } /* Input handler registration */ static pointer addInputHandler(int fd, InputHandlerProc proc, pointer data) { IHPtr ih; if (fd < 0 || !proc) return NULL; ih = xcalloc(sizeof(*ih), 1); if (!ih) return NULL; ih->fd = fd; ih->ihproc = proc; ih->data = data; ih->enabled = TRUE; ih->next = InputHandlers; InputHandlers = ih; return ih; } _X_EXPORT pointer xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data) { IHPtr ih = addInputHandler(fd, proc, data); if (ih) AddEnabledDevice(fd); return ih; } _X_EXPORT pointer xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data) { IHPtr ih = addInputHandler(fd, proc, data); if (ih) AddGeneralSocket(fd); return ih; } static void removeInputHandler(IHPtr ih) { IHPtr p; if (ih == InputHandlers) InputHandlers = ih->next; else { p = InputHandlers; while (p && p->next != ih) p = p->next; if (ih) p->next = ih->next; } xfree(ih); } _X_EXPORT int xf86RemoveInputHandler(pointer handler) { IHPtr ih; int fd; if (!handler) return -1; ih = handler; fd = ih->fd; if (ih->fd >= 0) RemoveEnabledDevice(ih->fd); removeInputHandler(ih); return fd; } _X_EXPORT int xf86RemoveGeneralHandler(pointer handler) { IHPtr ih; int fd; if (!handler) return -1; ih = handler; fd = ih->fd; if (ih->fd >= 0) RemoveGeneralSocket(ih->fd); removeInputHandler(ih); return fd; } _X_EXPORT void xf86DisableInputHandler(pointer handler) { IHPtr ih; if (!handler) return; ih = handler; ih->enabled = FALSE; if (ih->fd >= 0) RemoveEnabledDevice(ih->fd); } _X_EXPORT void xf86DisableGeneralHandler(pointer handler) { IHPtr ih; if (!handler) return; ih = handler; ih->enabled = FALSE; if (ih->fd >= 0) RemoveGeneralSocket(ih->fd); } _X_EXPORT void xf86EnableInputHandler(pointer handler) { IHPtr ih; if (!handler) return; ih = handler; ih->enabled = TRUE; if (ih->fd >= 0) AddEnabledDevice(ih->fd); } _X_EXPORT void xf86EnableGeneralHandler(pointer handler) { IHPtr ih; if (!handler) return; ih = handler; ih->enabled = TRUE; if (ih->fd >= 0) AddGeneralSocket(ih->fd); } /* * As used currently by the DRI, the return value is ignored. */ _X_EXPORT Bool xf86EnableVTSwitch(Bool new) { static Bool def = TRUE; Bool old; old = VTSwitchEnabled; if (!new) { /* Disable VT switching */ def = VTSwitchEnabled; VTSwitchEnabled = FALSE; } else { /* Restore VT switching to default */ VTSwitchEnabled = def; } return old; } void xf86ReloadInputDevs(int sig) { InputInfoPtr pInfo; signal(sig, (void(*)(int))xf86ReloadInputDevs); DisableDevice((DeviceIntPtr)xf86Info.pKeyboard); EnableDevice((DeviceIntPtr)xf86Info.pKeyboard); pInfo = xf86InputDevs; while (pInfo) { DisableDevice(pInfo->dev); EnableDevice(pInfo->dev); pInfo = pInfo->next; } return; } #ifdef WSCONS_SUPPORT /* XXX Currently XKB is mandatory. */ extern int WSKbdToKeycode(int); void xf86PostWSKbdEvent(struct wscons_event *event) { int type = event->type; int value = event->value; unsigned int keycode; int blocked; if (type == WSCONS_EVENT_KEY_UP || type == WSCONS_EVENT_KEY_DOWN) { Bool down = (type == WSCONS_EVENT_KEY_DOWN ? TRUE : FALSE); /* map the scancodes to standard XFree86 scancode */ keycode = WSKbdToKeycode(value); if (!down) keycode |= 0x80; /* It seems better to block SIGIO there */ blocked = xf86BlockSIGIO(); xf86PostKbdEvent(keycode); xf86UnblockSIGIO(blocked); } } #endif /* WSCONS_SUPPORT */