#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"
#ifdef XF86BIGFONT
#define _XF86BIGFONT_SERVER_
#include <X11/extensions/xf86bigfont.h>
#endif
#ifdef DPMSExtension
#include <X11/extensions/dpmsconst.h>
#include "dpmsproc.h"
#endif
_X_EXPORT Bool VTSwitchEnabled = TRUE;
extern fd_set EnabledDevices;
#ifdef XF86PM
extern void (*xf86OSPMClose)(void);
#endif
static void xf86VTSwitch(void);
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;
}
int
TimeSinceLastInputEvent()
{
if (xf86Info.lastEventTime == 0) {
xf86Info.lastEventTime = GetTimeInMillis();
}
return GetTimeInMillis() - xf86Info.lastEventTime;
}
_X_EXPORT void
SetTimeSinceLastInputEvent()
{
xf86Info.lastEventTime = GetTimeInMillis();
}
void
ProcessInputEvents ()
{
int x, y;
mieqProcessInputEvents();
miPointerGetPosition(inputInfo.pointer, &x, &y);
xf86SetViewport(xf86Info.currentScreen, x, y);
}
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;
#if !defined(__SOL8__) && \
(!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 (ioctl(xf86Info.consoleFd, VT_ACTIVATE, vtno) < 0)
ErrorF("Failed to switch consoles (%s)\n", strerror(errno));
}
break;
case ACTION_SWITCHSCREEN_NEXT:
if (VTSwitchEnabled && !xf86Info.dontVTSwitch) {
#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
default:
break;
}
}
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();
pInfo->read_input(pInfo);
xf86UnblockSIGIO(sigstate);
FD_CLR(pInfo->fd, &devicesWithInput);
}
pInfo = pInfo->next;
}
}
}
if (err >= 0) {
IHPtr ih;
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();
}
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;
}
_X_EXPORT void
xf86AddEnabledDevice(InputInfoPtr pInfo)
{
if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) {
AddEnabledDevice(pInfo->fd);
}
}
_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;
}
void
xf86SigHandler(int signo)
{
if ((signo == SIGILL) && xf86SigIllHandler) {
(*xf86SigIllHandler)();
(void) signal(signo, xf86SigHandler);
return;
}
if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) {
*xf86SignalIntercept = signo;
(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);
}
_X_EXPORT void
xf86PrintBacktrace(void)
{
xorg_backtrace();
}
#define KeyPressed(k) (keyc->postdown[k >> 3] & (1 << (k & 7)))
#define ModifierDown(k) ((keyc->state & (k)) == (k))
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;
for (i = keyc->curKeySyms.minKeyCode, map = keyc->curKeySyms.map;
i < keyc->curKeySyms.maxKeyCode;
i++, map += keyc->curKeySyms.mapWidth) {
if (KeyPressed(i)) {
switch (*map) {
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)->event);
xf86UnblockSIGIO(sigstate);
}
break;
}
}
}
}
static void
xf86VTSwitch()
{
int i, prevSIGIO;
InputInfoPtr pInfo;
IHPtr ih;
#ifdef DEBUG
ErrorF("xf86VTSwitch()\n");
#endif
#ifdef XFreeXDGA
if(!DGAVTSwitch())
return;
#endif
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);
}
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();
xf86AccessLeaveState();
if (!xf86VTSwitchAway()) {
#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;
}
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++) {
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);
}
dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
pInfo = xf86InputDevs;
while (pInfo) {
if (pInfo->dev) {
xf86ReleaseKeys(pInfo->dev);
EnableDevice(pInfo->dev);
}
pInfo = pInfo->next;
}
xf86ReleaseKeys(inputInfo.keyboard);
for (ih = InputHandlers; ih; ih = ih->next)
xf86EnableInputHandler(ih);
xf86UnblockSIGIO(prevSIGIO);
}
}
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);
}
_X_EXPORT Bool
xf86EnableVTSwitch(Bool new)
{
static Bool def = TRUE;
Bool old;
old = VTSwitchEnabled;
if (!new) {
def = VTSwitchEnabled;
VTSwitchEnabled = FALSE;
} else {
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);
}