diff options
Diffstat (limited to 'xorg-server/hw/xfree86/common/xf86Events.c')
-rw-r--r-- | xorg-server/hw/xfree86/common/xf86Events.c | 1018 |
1 files changed, 1018 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c new file mode 100644 index 000000000..76c207a13 --- /dev/null +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -0,0 +1,1018 @@ +/* + * 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 <xorg-config.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 + +#define EqEnqueue(pDev, ev) { \ + int __sigstate = xf86BlockSIGIO (); \ + mieqEnqueue (pDev, ev); \ + xf86UnblockSIGIO(__sigstate); \ +} + +/* + * 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) + */ + +_X_EXPORT 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; + +#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; + + +Bool +LegalModifier(unsigned int key, DeviceIntPtr pDev) +{ + return TRUE; +} + +/* + * 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; + + mieqProcessInputEvents(); + miPointerUpdateSprite(inputInfo.pointer); + + miPointerGetPosition(inputInfo.pointer, &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(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; + } +} + +#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(__QNX__) + fd_set* LastSelectMask = (fd_set*)pReadmask; + fd_set devicesWithInput; + InputInfoPtr pInfo; + + if (err >= 0) { + + XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices); + if (XFD_ANYSET(&devicesWithInput)) { + 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 /* __QNX__ */ + + InputInfoPtr pInfo; + + 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 /* __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 errno_save = errno; + int sigstate = xf86BlockSIGIO(); + InputInfoPtr pInfo = (InputInfoPtr) closure; + + pInfo->read_input(pInfo); + + xf86UnblockSIGIO(sigstate); + errno = errno_save; +} + +/* + * 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; +} + +/* + * 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); +} + +static void +xf86ReleaseKeys(DeviceIntPtr pDev) +{ + KeyClassPtr keyc = NULL; + KeySym *map = NULL; + xEvent ke; + int i = 0, j = 0, nevents = 0; + + if (!pDev || !pDev->key) + return; + + keyc = pDev->key; + map = keyc->curKeySyms.map; + + /* + * Hmm... here is the biggest hack of every time ! + * It may be possible that a switch-vt procedure has finished BEFORE + * you released all keys neccessary to do this. That peculiar behavior + * can fool the X-server pretty much, cause it assumes that some keys + * were not released. TWM may stuck alsmost completly.... + * OK, what we are doing here is after returning from the vt-switch + * exeplicitely unrelease all keyboard keys before the input-devices + * are reenabled. + */ + + for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map; + i < keyc->curKeySyms.maxKeyCode; + i++, map += keyc->curKeySyms.mapWidth) { + if (KeyPressed(i)) { + switch (*map) { + /* Don't release the lock keys */ + case XK_Caps_Lock: + case XK_Shift_Lock: + case XK_Num_Lock: + case XK_Scroll_Lock: + case XK_Kana_Lock: + break; + default: + if (pDev == inputInfo.keyboard) { + ke.u.keyButtonPointer.time = GetTimeInMillis(); + ke.u.keyButtonPointer.rootX = 0; + ke.u.keyButtonPointer.rootY = 0; + ke.u.u.type = KeyRelease; + ke.u.u.detail = i; + (*pDev->public.processInputProc) (&ke, pDev, 1); + } + else { + int sigstate = xf86BlockSIGIO (); + nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i); + for (j = 0; j < nevents; j++) + mieqEnqueue(pDev, xf86Events + j); + xf86UnblockSIGIO(sigstate); + } + break; + } + } + } +} + +/* + * 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(serverClient, DPMSModeOn); +#endif + for (i = 0; i < xf86NumScreens; i++) { + if (!(dispatchException & DE_TERMINATE)) + if (xf86Screens[i]->EnableDisableFBAccess) + (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE); + } + + /* + * Keep the order: Disable Device > LeaveVT + * EnterVT > EnableDevice + */ + pInfo = xf86InputDevs; + while (pInfo) { + if (pInfo->dev) + DisableDevice(pInfo->dev); + pInfo = pInfo->next; + } + 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); + } + } + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + + pInfo = xf86InputDevs; + while (pInfo) { + if (pInfo->dev) { + xf86ReleaseKeys(pInfo->dev); + EnableDevice(pInfo->dev); + } + pInfo = pInfo->next; + } + /* XXX HACK */ + xf86ReleaseKeys(inputInfo.keyboard); + 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 */ + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + + pInfo = xf86InputDevs; + while (pInfo) { + if (pInfo->dev) { + xf86ReleaseKeys(pInfo->dev); + EnableDevice(pInfo->dev); + } + pInfo = pInfo->next; + } + /* XXX HACK */ + xf86ReleaseKeys(inputInfo.keyboard); + + 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); + + pInfo = xf86InputDevs; + while (pInfo) { + DisableDevice(pInfo->dev); + EnableDevice(pInfo->dev); + pInfo = pInfo->next; + } + + return; +} + +_X_EXPORT void +DDXRingBell(int volume, int pitch, int duration) { + xf86OSRingBell(volume, pitch, duration); +} |