2 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Thomas Roell not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Thomas Roell makes no representations
11 * about the suitability of this software for any purpose. It is provided
12 * "as is" without express or implied warranty.
14 * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
24 * Copyright (c) 1994-2003 by The XFree86 Project, Inc.
26 * Permission is hereby granted, free of charge, to any person obtaining a
27 * copy of this software and associated documentation files (the "Software"),
28 * to deal in the Software without restriction, including without limitation
29 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
30 * and/or sell copies of the Software, and to permit persons to whom the
31 * Software is furnished to do so, subject to the following conditions:
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
36 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
39 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
40 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
41 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
42 * OTHER DEALINGS IN THE SOFTWARE.
44 * Except as contained in this notice, the name of the copyright holder(s)
45 * and author(s) shall not be used in advertising or otherwise to promote
46 * the sale, use or other dealings in this Software without prior written
47 * authorization from the copyright holder(s) and author(s).
50 /* [JCH-96/01/21] Extended std reverse map to four buttons. */
52 #ifdef HAVE_XORG_CONFIG_H
53 #include <xorg-config.h>
57 #include <X11/Xpoll.h>
58 #include <X11/Xproto.h>
64 #include "xf86_OSlib.h"
65 #include <X11/keysym.h>
71 #include <X11/extensions/XI.h>
72 #include <X11/extensions/XIproto.h>
74 #include "xf86Xinput.h"
77 #include "mipointer.h"
83 #include <X11/extensions/dpmsconst.h>
88 * This is a toggling variable:
89 * FALSE = No VT switching keys have been pressed last time around
90 * TRUE = Possible VT switch Pending
93 * This has been generalised to work with Linux and *BSD+syscons (DHD)
96 Bool VTSwitchEnabled = TRUE; /* Allows run-time disabling for
97 *BSD and for avoiding VT
98 switches when using the DRI
99 automatic full screen mode.*/
101 extern fd_set EnabledDevices;
104 extern void (*xf86OSPMClose)(void);
107 static void xf86VTSwitch(void);
110 * Allow arbitrary drivers or other XFree86 code to register with our main
113 typedef struct x_IHRec {
115 InputHandlerProc ihproc;
118 struct x_IHRec * next;
121 static IHPtr InputHandlers = NULL;
125 LegalModifier(unsigned int key, DeviceIntPtr pDev)
131 * TimeSinceLastInputEvent --
132 * Function used for screensaver purposes by the os module. Returns the
133 * time in milliseconds since there last was any input.
136 TimeSinceLastInputEvent(void)
138 if (xf86Info.lastEventTime == 0) {
139 xf86Info.lastEventTime = GetTimeInMillis();
141 return GetTimeInMillis() - xf86Info.lastEventTime;
145 * SetTimeSinceLastInputEvent --
146 * Set the lastEventTime to now.
149 SetTimeSinceLastInputEvent(void)
151 xf86Info.lastEventTime = GetTimeInMillis();
155 * ProcessInputEvents --
156 * Retrieve all waiting input events and pass them to DIX in their
157 * correct chronological order. Only reads from the system pointer
161 ProcessInputEvents (void)
165 mieqProcessInputEvents();
167 /* FIXME: This is a problem if we have multiple pointers */
168 miPointerGetPosition(inputInfo.pointer, &x, &y);
169 xf86SetViewport(xf86Info.currentScreen, x, y);
173 * Handle keyboard events that cause some kind of "action"
174 * (i.e., server termination, video mode changes, VT switches, etc.)
177 xf86ProcessActionEvent(ActionEvent action, void *arg)
179 DebugF("ProcessActionEvent(%d,%x)\n", (int) action, arg);
181 case ACTION_TERMINATE:
182 if (!xf86Info.dontZap) {
189 case ACTION_NEXT_MODE:
190 if (!xf86Info.dontZoom)
191 xf86ZoomViewport(xf86Info.currentScreen, 1);
193 case ACTION_PREV_MODE:
194 if (!xf86Info.dontZoom)
195 xf86ZoomViewport(xf86Info.currentScreen, -1);
197 case ACTION_SWITCHSCREEN:
198 if (VTSwitchEnabled && !xf86Info.dontVTSwitch && arg) {
199 int vtno = *((int *) arg);
201 if (vtno != xf86Info.vtno) {
202 if (!xf86VTActivate(vtno)) {
203 ErrorF("Failed to switch from vt%02d to vt%02d: %s\n",
204 xf86Info.vtno, vtno, strerror(errno));
209 case ACTION_SWITCHSCREEN_NEXT:
210 if (VTSwitchEnabled && !xf86Info.dontVTSwitch) {
211 if (!xf86VTActivate(xf86Info.vtno + 1)) {
212 /* If first try failed, assume this is the last VT and
213 * try wrapping around to the first vt.
215 if (!xf86VTActivate(1)) {
216 ErrorF("Failed to switch from vt%02d to next vt: %s\n",
217 xf86Info.vtno, strerror(errno));
222 case ACTION_SWITCHSCREEN_PREV:
223 if (VTSwitchEnabled && !xf86Info.dontVTSwitch && xf86Info.vtno > 0) {
224 if (!xf86VTActivate(xf86Info.vtno - 1)) {
225 /* Don't know what the maximum VT is, so can't wrap around */
226 ErrorF("Failed to switch from vt%02d to previous vt: %s\n",
227 xf86Info.vtno, strerror(errno));
243 xf86Wakeup(pointer blockData, int err, pointer pReadmask)
245 fd_set* LastSelectMask = (fd_set*)pReadmask;
246 fd_set devicesWithInput;
251 XFD_ANDSET(&devicesWithInput, LastSelectMask, &EnabledDevices);
252 if (XFD_ANYSET(&devicesWithInput)) {
253 pInfo = xf86InputDevs;
255 if (pInfo->read_input && pInfo->fd >= 0 &&
256 (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) {
257 int sigstate = xf86BlockSIGIO();
260 * Remove the descriptior from the set because more than one
261 * device may share the same file descriptor.
263 FD_CLR(pInfo->fd, &devicesWithInput);
265 pInfo->read_input(pInfo);
266 xf86UnblockSIGIO(sigstate);
273 if (err >= 0) { /* we don't want the handlers called if select() */
274 IHPtr ih; /* returned with an error condition, do we? */
276 for (ih = InputHandlers; ih; ih = ih->next) {
277 if (ih->enabled && ih->fd >= 0 && ih->ihproc &&
278 (FD_ISSET(ih->fd, ((fd_set *)pReadmask)) != 0)) {
279 ih->ihproc(ih->fd, ih->data);
284 if (xf86VTSwitchPending()) xf86VTSwitch();
289 * xf86SigioReadInput --
290 * signal handler for the SIGIO signal.
293 xf86SigioReadInput(int fd, void *closure)
295 int errno_save = errno;
296 InputInfoPtr pInfo = closure;
298 pInfo->read_input(pInfo);
304 * xf86AddEnabledDevice --
308 xf86AddEnabledDevice(InputInfoPtr pInfo)
310 if (!xf86InstallSIGIOHandler (pInfo->fd, xf86SigioReadInput, pInfo)) {
311 AddEnabledDevice(pInfo->fd);
316 * xf86RemoveEnabledDevice --
320 xf86RemoveEnabledDevice(InputInfoPtr pInfo)
322 if (!xf86RemoveSIGIOHandler (pInfo->fd)) {
323 RemoveEnabledDevice(pInfo->fd);
327 static int *xf86SignalIntercept = NULL;
330 xf86InterceptSignals(int *signo)
332 if ((xf86SignalIntercept = signo))
336 static void (*xf86SigIllHandler)(void) = NULL;
339 xf86InterceptSigIll(void (*sigillhandler)(void))
341 xf86SigIllHandler = sigillhandler;
346 * Catch unexpected signals and exit or continue cleanly.
349 xf86SigWrapper(int signo)
351 if ((signo == SIGILL) && xf86SigIllHandler) {
352 (*xf86SigIllHandler)();
353 return 0; /* continue */
356 if (xf86SignalIntercept && (*xf86SignalIntercept < 0)) {
357 *xf86SignalIntercept = signo;
358 return 0; /* continue */
361 xf86Info.caughtSignal = TRUE;
362 return 1; /* abort */
366 * xf86PrintBacktrace --
367 * Print a stack backtrace for debugging purposes.
370 xf86PrintBacktrace(void)
376 xf86ReleaseKeys(DeviceIntPtr pDev)
379 int i, j, nevents, sigstate;
381 if (!pDev || !pDev->key)
387 * Hmm... here is the biggest hack of every time !
388 * It may be possible that a switch-vt procedure has finished BEFORE
389 * you released all keys neccessary to do this. That peculiar behavior
390 * can fool the X-server pretty much, cause it assumes that some keys
391 * were not released. TWM may stuck alsmost completly....
392 * OK, what we are doing here is after returning from the vt-switch
393 * exeplicitely unrelease all keyboard keys before the input-devices
397 for (i = keyc->xkbInfo->desc->min_key_code;
398 i < keyc->xkbInfo->desc->max_key_code;
400 if (key_is_down(pDev, i, KEY_POSTED)) {
401 sigstate = xf86BlockSIGIO ();
402 nevents = GetKeyboardEvents(xf86Events, pDev, KeyRelease, i);
403 for (j = 0; j < nevents; j++)
404 mieqEnqueue(pDev, (InternalEvent*)(xf86Events + j)->event);
405 xf86UnblockSIGIO(sigstate);
412 * Handle requests for switching the vt.
421 DebugF("xf86VTSwitch()\n");
429 * Since all screens are currently all in the same state it is sufficient
430 * check the first. This might change in future.
432 if (xf86Screens[0]->vtSema) {
434 DebugF("xf86VTSwitch: Leaving, xf86Exiting is %s\n",
435 BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE));
437 if (DPMSPowerLevel != DPMSModeOn)
438 DPMSSet(serverClient, DPMSModeOn);
440 for (i = 0; i < xf86NumScreens; i++) {
441 if (!(dispatchException & DE_TERMINATE))
442 if (xf86Screens[i]->EnableDisableFBAccess)
443 (*xf86Screens[i]->EnableDisableFBAccess) (i, FALSE);
447 * Keep the order: Disable Device > LeaveVT
448 * EnterVT > EnableDevice
450 for (ih = InputHandlers; ih; ih = ih->next)
451 xf86DisableInputHandler(ih);
452 for (pInfo = xf86InputDevs; pInfo; pInfo = pInfo->next) {
454 xf86ReleaseKeys(pInfo->dev);
455 ProcessInputEvents();
456 DisableDevice(pInfo->dev, TRUE);
459 xf86EnterServerState(SETUP);
460 for (i = 0; i < xf86NumScreens; i++)
461 xf86Screens[i]->LeaveVT(i, 0);
463 xf86AccessLeave(); /* We need this here, otherwise */
465 if (!xf86VTSwitchAway()) {
470 DebugF("xf86VTSwitch: Leave failed\n");
471 prevSIGIO = xf86BlockSIGIO();
473 xf86EnterServerState(SETUP);
474 for (i = 0; i < xf86NumScreens; i++) {
475 if (!xf86Screens[i]->EnterVT(i, 0))
476 FatalError("EnterVT failed for screen %d\n", i);
478 xf86EnterServerState(OPERATING);
479 if (!(dispatchException & DE_TERMINATE)) {
480 for (i = 0; i < xf86NumScreens; i++) {
481 if (xf86Screens[i]->EnableDisableFBAccess)
482 (*xf86Screens[i]->EnableDisableFBAccess) (i, TRUE);
485 dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
487 pInfo = xf86InputDevs;
490 EnableDevice(pInfo->dev, TRUE);
493 for (ih = InputHandlers; ih; ih = ih->next)
494 xf86EnableInputHandler(ih);
496 xf86UnblockSIGIO(prevSIGIO);
502 xf86OSPMClose = NULL;
505 for (i = 0; i < xf86NumScreens; i++) {
507 * zero all access functions to
508 * trap calls when switched away.
510 xf86Screens[i]->vtSema = FALSE;
517 DebugF("xf86VTSwitch: Entering\n");
518 if (!xf86VTSwitchTo()) return;
520 prevSIGIO = xf86BlockSIGIO();
522 xf86OSPMClose = xf86OSPMOpen();
528 xf86EnterServerState(SETUP);
529 for (i = 0; i < xf86NumScreens; i++) {
530 xf86Screens[i]->vtSema = TRUE;
531 if (!xf86Screens[i]->EnterVT(i, 0))
532 FatalError("EnterVT failed for screen %d\n", i);
534 xf86EnterServerState(OPERATING);
535 for (i = 0; i < xf86NumScreens; i++) {
536 if (xf86Screens[i]->EnableDisableFBAccess)
537 (*xf86Screens[i]->EnableDisableFBAccess)(i, TRUE);
540 /* Turn screen saver off when switching back */
541 dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset);
543 pInfo = xf86InputDevs;
546 EnableDevice(pInfo->dev, TRUE);
550 for (ih = InputHandlers; ih; ih = ih->next)
551 xf86EnableInputHandler(ih);
553 xf86UnblockSIGIO(prevSIGIO);
558 /* Input handler registration */
561 addInputHandler(int fd, InputHandlerProc proc, pointer data)
568 ih = calloc(sizeof(*ih), 1);
577 ih->next = InputHandlers;
584 xf86AddInputHandler(int fd, InputHandlerProc proc, pointer data)
586 IHPtr ih = addInputHandler(fd, proc, data);
589 AddEnabledDevice(fd);
594 xf86AddGeneralHandler(int fd, InputHandlerProc proc, pointer data)
596 IHPtr ih = addInputHandler(fd, proc, data);
599 AddGeneralSocket(fd);
604 removeInputHandler(IHPtr ih)
608 if (ih == InputHandlers)
609 InputHandlers = ih->next;
612 while (p && p->next != ih)
621 xf86RemoveInputHandler(pointer handler)
633 RemoveEnabledDevice(ih->fd);
634 removeInputHandler(ih);
640 xf86RemoveGeneralHandler(pointer handler)
652 RemoveGeneralSocket(ih->fd);
653 removeInputHandler(ih);
659 xf86DisableInputHandler(pointer handler)
669 RemoveEnabledDevice(ih->fd);
673 xf86DisableGeneralHandler(pointer handler)
683 RemoveGeneralSocket(ih->fd);
687 xf86EnableInputHandler(pointer handler)
697 AddEnabledDevice(ih->fd);
701 xf86EnableGeneralHandler(pointer handler)
711 AddGeneralSocket(ih->fd);
715 * As used currently by the DRI, the return value is ignored.
718 xf86EnableVTSwitch(Bool new)
720 static Bool def = TRUE;
723 old = VTSwitchEnabled;
725 /* Disable VT switching */
726 def = VTSwitchEnabled;
727 VTSwitchEnabled = FALSE;
729 /* Restore VT switching to default */
730 VTSwitchEnabled = def;
736 DDXRingBell(int volume, int pitch, int duration) {
737 xf86OSRingBell(volume, pitch, duration);