diff options
Diffstat (limited to 'hw/xfree86/common/xf86Events.c')
-rw-r--r-- | hw/xfree86/common/xf86Events.c | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c new file mode 100644 index 0000000..84c0d18 --- /dev/null +++ b/hw/xfree86/common/xf86Events.c @@ -0,0 +1,753 @@ +/* + * 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 <X11/keysym.h> + +#ifdef XFreeXDGA +#include "dgaproc.h" +#endif + +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "inputstr.h" +#include "xf86Xinput.h" + +#include "mi.h" +#include "mipointer.h" + +#include "xkbsrv.h" +#include "xkbstr.h" + +#ifdef DPMSExtension +#include <X11/extensions/dpmsconst.h> +#include "dpmsproc.h" +#endif + +/* + * 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) + */ + +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(void) +{ + if (xf86Info.lastEventTime == 0) { + xf86Info.lastEventTime = GetTimeInMillis(); + } + return GetTimeInMillis() - xf86Info.lastEventTime; +} + +/* + * SetTimeSinceLastInputEvent -- + * Set the lastEventTime to now. + */ +void +SetTimeSinceLastInputEvent(void) +{ + 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 (void) +{ + int x, y; + + mieqProcessInputEvents(); + + /* FIXME: This is a problem if we have multiple pointers */ + miPointerGetPosition(inputInfo.pointer, &x, &y); + xf86SetViewport(xf86Info.currentScreen, x, y); +} + +/* + * 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) +{ + DebugF("ProcessActionEvent(%d,%x)\n", (int) action, arg); + 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_SWITCHSCREEN: + if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) { + int vtno = *((int *) arg); + + if (vtno != xf86Info.vtno) { + if (!xf86VTActivate(vtno)) { + ErrorF("Failed to switch from vt%02d to vt%02d: %s\n", + xf86Info.vtno, vtno, strerror(errno)); + } + } + } + break; + case ACTION_SWITCHSCREEN_NEXT: + if (VTSwitchEnabled && !xf86Info.dontVTSwitch) { + if (!xf86VTActivate(xf86Info.vtno + 1)) { + /* If first try failed, assume this is the last VT and + * try wrapping around to the first vt. + */ + if (!xf86VTActivate(1)) { + ErrorF("Failed to switch from vt%02d to next vt: %s\n", + xf86Info.vtno, strerror(errno)); + } + } + } + break; + case ACTION_SWITCHSCREEN_PREV: + if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) { + if (!xf86VTActivate(xf86Info.vtno - 1)) { + /* Don't know what the maximum VT is, so can't wrap around */ + ErrorF("Failed to switch from vt%02d to previous vt: %s\n", + xf86Info.vtno, strerror(errno)); + } + } + break; + default: + break; + } +} + +/* + * xf86Wakeup -- + * Os wakeup handler. + */ + +/* ARGSUSED */ +void +xf86Wakeup(pointer blockData, int err, pointer pReadmask) +{ + 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(); + + /* + * Remove the descriptior from the set because more than one + * device may share the same file descriptor. + */ + FD_CLR(pInfo->fd, &devicesWithInput); + + pInfo->read_input(pInfo); + xf86UnblockSIGIO(sigstate); + } + pInfo = pInfo->next; + } + } + } + + 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(); +} + + +/* + * xf86SigioReadInput -- + * signal handler for the SIGIO signal. + */ +static void +xf86SigioReadInput(int fd, void *closure) +{ + int errno_save = errno; + InputInfoPtr pInfo = closure; + + pInfo->read_input(pInfo); + + errno = errno_save; +} + +/* + * 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; +} + +/* + * xf86SigWrapper -- + * Catch unexpected signals and exit or continue cleanly. + */ +int +xf86SigWrapper(int signo) +{ + if ((signo == SIGILL) && xf86SigIllHandler) { + (*xf86SigIllHandler)(); + return 0; /* continue */ + } + + if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) { + *xf86SignalIntercept = signo; + return 0; /* continue */ + } + + xf86Info.caughtSignal = TRUE; + return 1; /* abort */ +} + +/* + * xf86PrintBacktrace -- + * Print a stack backtrace for debugging purposes. + */ +void +xf86PrintBacktrace(void) +{ + xorg_backtrace(); +} + +static void +xf86ReleaseKeys(DeviceIntPtr pDev) +{ + KeyClassPtr keyc; + int i, j, nevents, sigstate; + + if (!pDev || !pDev->key) + return; + + keyc = pDev->key; + + /* + * 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->xkbInfo->desc->min_key_code; + i < keyc->xkbInfo->desc->max_key_code; + i++) { + if (key_is_down(pDev, i, KEY_POSTED)) { + sigstate = xf86BlockSIGIO (); + nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i); + for (j = 0; j < nevents; j++) + mieqEnqueue(pDev, (InternalEvent*)(xf86Events + j)->event); + xf86UnblockSIGIO(sigstate); + } + } +} + +/* + * xf86VTSwitch -- + * Handle requests for switching the vt. + */ +static void +xf86VTSwitch(void) +{ + int i; + static int prevSIGIO; + InputInfoPtr pInfo; + IHPtr ih; + + DebugF("xf86VTSwitch()\n"); + +#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) { + + DebugF("xf86VTSwitch: Leaving, xf86Exiting is %s\n", + BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE)); +#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 + */ + for (ih = InputHandlers; ih; ih = ih->next) + xf86DisableInputHandler(ih); + for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) { + if (pInfo->dev) { + xf86ReleaseKeys(pInfo->dev); + ProcessInputEvents(); + DisableDevice(pInfo->dev, TRUE); + } + } + + prevSIGIO = xf86BlockSIGIO(); + for (i = 0; i < xf86NumScreens; i++) + xf86Screens[i]->LeaveVT(i, 0); + + xf86AccessLeave(); /* We need this here, otherwise */ + + if (!xf86VTSwitchAway()) { + /* + * switch failed + */ + + DebugF("xf86VTSwitch: Leave failed\n"); + xf86AccessEnter(); + for (i = 0; i < xf86NumScreens; i++) { + if (!xf86Screens[i]->EnterVT(i, 0)) + FatalError("EnterVT failed for screen %d\n", i); + } + 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) + EnableDevice(pInfo->dev, TRUE); + pInfo = pInfo->next; + } + 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; + } + if (xorgHWAccess) + xf86DisableIO(); + } + } else { + DebugF("xf86VTSwitch: Entering\n"); + if (!xf86VTSwitchTo()) return; + +#ifdef XF86PM + xf86OSPMClose = xf86OSPMOpen(); +#endif + + if (xorgHWAccess) + xf86EnableIO(); + xf86AccessEnter(); + for (i = 0; i < xf86NumScreens; i++) { + xf86Screens[i]->vtSema = TRUE; + if (!xf86Screens[i]->EnterVT(i, 0)) + FatalError("EnterVT failed for screen %d\n", i); + } + 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) + EnableDevice(pInfo->dev, TRUE); + pInfo = pInfo->next; + } + + 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 = calloc(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; +} + +pointer +xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data) +{ + IHPtr ih = addInputHandler(fd, proc, data); + + if (ih) + AddEnabledDevice(fd); + return ih; +} + +pointer +xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data) +{ + IHPtr ih = addInputHandler(fd, proc, data); + + if (ih) + AddGeneralSocket(fd); + return ih; +} + +/** + * Set the handler for the console's fd. Replaces (and returns) the previous + * handler or NULL, whichever appropriate. + * proc may be NULL if the server should not handle events on the console. + */ +InputHandlerProc +xf86SetConsoleHandler(InputHandlerProc proc, pointer data) +{ + static InputHandlerProc handler = NULL; + InputHandlerProc old_handler = handler; + + if (old_handler) + xf86RemoveGeneralHandler(old_handler); + + xf86AddGeneralHandler(xf86Info.consoleFd, proc, data); + handler = proc; + + return old_handler; +} + +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; + } + free(ih); +} + +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; +} + +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; +} + +void +xf86DisableInputHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = FALSE; + if (ih->fd >= 0) + RemoveEnabledDevice(ih->fd); +} + +void +xf86DisableGeneralHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = FALSE; + if (ih->fd >= 0) + RemoveGeneralSocket(ih->fd); +} + +void +xf86EnableInputHandler(pointer handler) +{ + IHPtr ih; + + if (!handler) + return; + + ih = handler; + ih->enabled = TRUE; + if (ih->fd >= 0) + AddEnabledDevice(ih->fd); +} + +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. + */ +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 +DDXRingBell(int volume, int pitch, int duration) { + xf86OSRingBell(volume, pitch, duration); +} |