diff options
Diffstat (limited to 'nx-X11/programs/Xserver/hw/xfree86/common/xf86Events.c')
-rw-r--r-- | nx-X11/programs/Xserver/hw/xfree86/common/xf86Events.c | 1865 |
1 files changed, 1865 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/xfree86/common/xf86Events.c b/nx-X11/programs/Xserver/hw/xfree86/common/xf86Events.c new file mode 100644 index 000000000..c1b478ee2 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/common/xf86Events.c @@ -0,0 +1,1865 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/common/xf86Events.c,v 3.159 2003/11/22 04:22:11 dawes Exp $ */ +/* + * 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). + */ + +/* $XConsortium: xf86Events.c /main/46 1996/10/25 11:36:30 kaleb $ */ +/* $XdotOrg: xc/programs/Xserver/hw/xfree86/common/xf86Events.c,v 1.21 2005/11/08 06:33:28 jkj Exp $ */ + +/* [JCH-96/01/21] Extended std reverse map to four buttons. */ + +#ifdef HAVE_XORG_CONFIG_H +#include <xorg-config.h> +#endif + +#ifdef __UNIXOS2__ +#define I_NEED_OS2_H +#endif + +#include <X11/X.h> +#include <X11/Xpoll.h> +#include <X11/Xproto.h> +#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 <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#else +#include "inputstr.h" +#endif +#include "xf86Xinput.h" + +#include "mi.h" +#include "mipointer.h" + +#ifdef XF86BIGFONT +#define _XF86BIGFONT_SERVER_ +#include <X11/extensions/xf86bigfont.h> +#endif + +#ifdef XKB +extern Bool noXkbExtension; +#endif + +#ifdef DPMSExtension +#define DPMS_SERVER +#include <X11/extensions/dpms.h> +#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); \ +} + +#ifdef XTESTEXT1 + +#define XTestSERVER_SIDE +#include <X11/extensions/xtestext1.h> +extern short xtest_mousex; +extern short xtest_mousey; +extern int on_steal_input; +extern Bool XTestStealKeyData(); +extern void XTestStealMotionData(); +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + if (!on_steal_input || \ + XTestStealKeyData((ev)->u.u.detail, (ev)->u.u.type, dev_type, \ + xtest_mousex, xtest_mousey)) \ + EqEnqueue((ev)) +#else /* ! XTESTEXT1 */ + +#define ENQUEUE(ev, code, direction, dev_type) \ + (ev)->u.u.detail = (code); \ + (ev)->u.u.type = (direction); \ + EqEnqueue((ev)) + +#endif + +/* + * 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. + */ + +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 */ + { + 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; + } + } + } + + 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)) + +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 -- + * + */ +void +xf86AddEnabledDevice(InputInfoPtr pInfo) +{ + if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) { + AddEnabledDevice(pInfo->fd); + } +} + +/* + * xf86RemoveEnabledDevice -- + * + */ +void +xf86RemoveEnabledDevice(InputInfoPtr pInfo) +{ + if (!xf86RemoveSIGIOHandler (pInfo->fd)) { + RemoveEnabledDevice(pInfo->fd); + } +} + +static int *xf86SignalIntercept = NULL; + +void +xf86InterceptSignals(int *signo) +{ + if ((xf86SignalIntercept = signo)) + *signo = -1; +} + +static void (*xf86SigIllHandler)(void) = NULL; + +void +xf86InterceptSigIll(void (*sigillhandler)(void)) +{ + xf86SigIllHandler = sigillhandler; +} + +#ifdef HAVE_EXECINFO_H +#define HAVE_BACKTRACE +#include <execinfo.h> +#endif + +#ifdef HAVE_BACKTRACE + +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 <ucontext.h> +# include <signal.h> +# include <dlfcn.h> +# include <sys/elf.h> + +#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 = "<section start>"; + 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 +#if defined(XFree86LOADER) + if (xf86Initialising) + LoaderCheckUnresolved(LD_RESOLV_IFDONE); + ErrorF("\n" + " *** If unresolved symbols were reported above, they might not\n" + " *** be the reason for the server aborting.\n"); +#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 */ + +pointer +xf86AddInputHandler(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; + + AddEnabledDevice(fd); + + return ih; +} + +int +xf86RemoveInputHandler(pointer handler) +{ + IHPtr ih, p; + int fd; + + if (!handler) + return -1; + + ih = handler; + fd = ih->fd; + + if (ih->fd >= 0) + RemoveEnabledDevice(ih->fd); + + 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); + return fd; +} + +void +xf86DisableInputHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = FALSE; + if (ih->fd >= 0) + RemoveEnabledDevice(ih->fd); +} + +void +xf86EnableInputHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = TRUE; + if (ih->fd >= 0) + AddEnabledDevice(ih->fd); +} + +/* + * As used currently by the DRI, the return value is ignored. + */ +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; +} + +#ifdef XTESTEXT1 + +void +XTestGetPointerPos(short *fmousex, short *fmousey) +{ + int x,y; + + miPointerPosition(&x, &y); + *fmousex = x; + *fmousey = y; +} + + + +void +XTestJumpPointer(int jx, int jy, int dev_type) +{ + miPointerAbsoluteCursor(jx, jy, GetTimeInMillis() ); +} + +void +XTestGenerateEvent(int dev_type, int keycode, int keystate, int mousex, + int mousey) +{ + xEvent tevent; + + tevent.u.u.type = (dev_type == XE_POINTER) ? + (keystate == XTestKEY_UP) ? ButtonRelease : ButtonPress : + (keystate == XTestKEY_UP) ? KeyRelease : KeyPress; + tevent.u.u.detail = keycode; + tevent.u.keyButtonPointer.rootX = mousex; + tevent.u.keyButtonPointer.rootY = mousey; + tevent.u.keyButtonPointer.time = xf86Info.lastEventTime = GetTimeInMillis(); +#ifdef XINPUT + xf86eqEnqueue(&tevent); +#else + mieqEnqueue(&tevent); +#endif + xf86Info.inputPending = TRUE; /* virtual event */ +} + +#endif /* XTESTEXT1 */ + +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 */ |