xserver-multidpi/hw/xfree86/common/xf86Events.c
Daniel Stone 66b2c9bd2d add 'general socket' handler, port ACPI to use it
Add a general socket (not input device, but still need to be woken for it)
handler to both the DIX and XFree86, and make XFree86's ACPI handling use
it.  This stops DPMS waking up every time an ACPI notification comes in.
2006-11-08 18:10:40 +02:00

1861 lines
48 KiB
C

/*
* 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
#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); \
}
#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 */
{
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))
_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 <execinfo.h>
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
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 */