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>
87 #include "xf86platformBus.h"
89 * This is a toggling variable:
90 * FALSE = No VT switching keys have been pressed last time around
91 * TRUE = Possible VT switch Pending
94 * This has been generalised to work with Linux and *BSD+syscons (DHD)
97 Bool VTSwitchEnabled
= TRUE
; /* Allows run-time disabling for
98 *BSD and for avoiding VT
99 switches when using the DRI
100 automatic full screen mode.*/
102 extern fd_set EnabledDevices
;
105 extern void (*xf86OSPMClose
) (void);
108 static void xf86VTSwitch(void);
111 * Allow arbitrary drivers or other XFree86 code to register with our main
114 typedef struct x_IHRec
{
116 InputHandlerProc ihproc
;
120 struct x_IHRec
*next
;
123 static IHPtr InputHandlers
= NULL
;
126 LegalModifier(unsigned int key
, DeviceIntPtr pDev
)
132 * TimeSinceLastInputEvent --
133 * Function used for screensaver purposes by the os module. Returns the
134 * time in milliseconds since there last was any input.
137 TimeSinceLastInputEvent(void)
139 if (xf86Info
.lastEventTime
== 0) {
140 xf86Info
.lastEventTime
= GetTimeInMillis();
142 return GetTimeInMillis() - xf86Info
.lastEventTime
;
146 * SetTimeSinceLastInputEvent --
147 * Set the lastEventTime to now.
150 SetTimeSinceLastInputEvent(void)
152 xf86Info
.lastEventTime
= GetTimeInMillis();
156 * ProcessInputEvents --
157 * Retrieve all waiting input events and pass them to DIX in their
158 * correct chronological order. Only reads from the system pointer
162 ProcessInputEvents(void)
166 mieqProcessInputEvents();
168 /* FIXME: This is a problem if we have multiple pointers */
169 miPointerGetPosition(inputInfo
.pointer
, &x
, &y
);
171 xf86SetViewport(xf86Info
.currentScreen
, x
, y
);
175 * Handle keyboard events that cause some kind of "action"
176 * (i.e., server termination, video mode changes, VT switches, etc.)
179 xf86ProcessActionEvent(ActionEvent action
, void *arg
)
181 DebugF("ProcessActionEvent(%d,%x)\n", (int) action
, arg
);
183 case ACTION_TERMINATE
:
184 if (!xf86Info
.dontZap
) {
185 xf86Msg(X_INFO
, "Server zapped. Shutting down.\n");
192 case ACTION_NEXT_MODE
:
193 if (!xf86Info
.dontZoom
)
194 xf86ZoomViewport(xf86Info
.currentScreen
, 1);
196 case ACTION_PREV_MODE
:
197 if (!xf86Info
.dontZoom
)
198 xf86ZoomViewport(xf86Info
.currentScreen
, -1);
200 case ACTION_SWITCHSCREEN
:
201 if (VTSwitchEnabled
&& !xf86Info
.dontVTSwitch
&& arg
) {
202 int vtno
= *((int *) arg
);
204 if (vtno
!= xf86Info
.vtno
) {
205 if (!xf86VTActivate(vtno
)) {
206 ErrorF("Failed to switch from vt%02d to vt%02d: %s\n",
207 xf86Info
.vtno
, vtno
, strerror(errno
));
212 case ACTION_SWITCHSCREEN_NEXT
:
213 if (VTSwitchEnabled
&& !xf86Info
.dontVTSwitch
) {
214 if (!xf86VTActivate(xf86Info
.vtno
+ 1)) {
215 /* If first try failed, assume this is the last VT and
216 * try wrapping around to the first vt.
218 if (!xf86VTActivate(1)) {
219 ErrorF("Failed to switch from vt%02d to next vt: %s\n",
220 xf86Info
.vtno
, strerror(errno
));
225 case ACTION_SWITCHSCREEN_PREV
:
226 if (VTSwitchEnabled
&& !xf86Info
.dontVTSwitch
&& xf86Info
.vtno
> 0) {
227 if (!xf86VTActivate(xf86Info
.vtno
- 1)) {
228 /* Don't know what the maximum VT is, so can't wrap around */
229 ErrorF("Failed to switch from vt%02d to previous vt: %s\n",
230 xf86Info
.vtno
, strerror(errno
));
246 xf86Wakeup(pointer blockData
, int err
, pointer pReadmask
)
248 fd_set
*LastSelectMask
= (fd_set
*) pReadmask
;
249 fd_set devicesWithInput
;
254 XFD_ANDSET(&devicesWithInput
, LastSelectMask
, &EnabledDevices
);
255 if (XFD_ANYSET(&devicesWithInput
)) {
256 pInfo
= xf86InputDevs
;
258 if (pInfo
->read_input
&& pInfo
->fd
>= 0 &&
259 (FD_ISSET(pInfo
->fd
, &devicesWithInput
) != 0)) {
263 * Remove the descriptior from the set because more than one
264 * device may share the same file descriptor.
266 FD_CLR(pInfo
->fd
, &devicesWithInput
);
268 pInfo
->read_input(pInfo
);
276 if (err
>= 0) { /* we don't want the handlers called if select() */
277 IHPtr ih
, ih_tmp
; /* returned with an error condition, do we? */
279 nt_list_for_each_entry_safe(ih
, ih_tmp
, InputHandlers
, next
) {
280 if (ih
->enabled
&& ih
->fd
>= 0 && ih
->ihproc
&&
281 (FD_ISSET(ih
->fd
, ((fd_set
*) pReadmask
)) != 0)) {
282 ih
->ihproc(ih
->fd
, ih
->data
);
287 if (xf86VTSwitchPending())
292 * xf86SigioReadInput --
293 * signal handler for the SIGIO signal.
296 xf86SigioReadInput(int fd
, void *closure
)
298 int errno_save
= errno
;
299 InputInfoPtr pInfo
= closure
;
301 pInfo
->read_input(pInfo
);
307 * xf86AddEnabledDevice --
311 xf86AddEnabledDevice(InputInfoPtr pInfo
)
313 if (!xf86InstallSIGIOHandler(pInfo
->fd
, xf86SigioReadInput
, pInfo
)) {
314 AddEnabledDevice(pInfo
->fd
);
319 * xf86RemoveEnabledDevice --
323 xf86RemoveEnabledDevice(InputInfoPtr pInfo
)
325 if (!xf86RemoveSIGIOHandler(pInfo
->fd
)) {
326 RemoveEnabledDevice(pInfo
->fd
);
330 static int *xf86SignalIntercept
= NULL
;
333 xf86InterceptSignals(int *signo
)
335 if ((xf86SignalIntercept
= signo
))
339 static void (*xf86SigIllHandler
) (void) = NULL
;
342 xf86InterceptSigIll(void (*sigillhandler
) (void))
344 xf86SigIllHandler
= sigillhandler
;
349 * Catch unexpected signals and exit or continue cleanly.
352 xf86SigWrapper(int signo
)
354 if ((signo
== SIGILL
) && xf86SigIllHandler
) {
355 (*xf86SigIllHandler
) ();
356 return 0; /* continue */
359 if (xf86SignalIntercept
&& (*xf86SignalIntercept
< 0)) {
360 *xf86SignalIntercept
= signo
;
361 return 0; /* continue */
364 xf86Info
.caughtSignal
= TRUE
;
365 return 1; /* abort */
369 * xf86PrintBacktrace --
370 * Print a stack backtrace for debugging purposes.
373 xf86PrintBacktrace(void)
379 xf86ReleaseKeys(DeviceIntPtr pDev
)
384 if (!pDev
|| !pDev
->key
)
390 * Hmm... here is the biggest hack of every time !
391 * It may be possible that a switch-vt procedure has finished BEFORE
392 * you released all keys neccessary to do this. That peculiar behavior
393 * can fool the X-server pretty much, cause it assumes that some keys
394 * were not released. TWM may stuck alsmost completly....
395 * OK, what we are doing here is after returning from the vt-switch
396 * exeplicitely unrelease all keyboard keys before the input-devices
400 for (i
= keyc
->xkbInfo
->desc
->min_key_code
;
401 i
< keyc
->xkbInfo
->desc
->max_key_code
; i
++) {
402 if (key_is_down(pDev
, i
, KEY_POSTED
)) {
404 QueueKeyboardEvents(pDev
, KeyRelease
, i
, NULL
);
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.
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
) (xf86Screens
[i
], FALSE
);
447 * Keep the order: Disable Device > LeaveVT
448 * EnterVT > EnableDevice
450 for (ih
= InputHandlers
; ih
; ih
= ih
->next
) {
452 xf86DisableInputHandler(ih
);
454 xf86DisableGeneralHandler(ih
);
456 for (pInfo
= xf86InputDevs
; pInfo
; pInfo
= pInfo
->next
) {
458 if (!pInfo
->dev
->enabled
)
459 pInfo
->flags
|= XI86_DEVICE_DISABLED
;
460 xf86ReleaseKeys(pInfo
->dev
);
461 ProcessInputEvents();
462 DisableDevice(pInfo
->dev
, TRUE
);
467 for (i
= 0; i
< xf86NumScreens
; i
++)
468 xf86Screens
[i
]->LeaveVT(xf86Screens
[i
]);
469 for (i
= 0; i
< xf86NumGPUScreens
; i
++)
470 xf86GPUScreens
[i
]->LeaveVT(xf86GPUScreens
[i
]);
472 xf86AccessLeave(); /* We need this here, otherwise */
474 if (!xf86VTSwitchAway()) {
479 DebugF("xf86VTSwitch: Leave failed\n");
481 for (i
= 0; i
< xf86NumScreens
; i
++) {
482 if (!xf86Screens
[i
]->EnterVT(xf86Screens
[i
]))
483 FatalError("EnterVT failed for screen %d\n", i
);
485 for (i
= 0; i
< xf86NumGPUScreens
; i
++) {
486 if (!xf86GPUScreens
[i
]->EnterVT(xf86GPUScreens
[i
]))
487 FatalError("EnterVT failed for gpu screen %d\n", i
);
489 if (!(dispatchException
& DE_TERMINATE
)) {
490 for (i
= 0; i
< xf86NumScreens
; i
++) {
491 if (xf86Screens
[i
]->EnableDisableFBAccess
)
492 (*xf86Screens
[i
]->EnableDisableFBAccess
) (xf86Screens
[i
], TRUE
);
495 dixSaveScreens(serverClient
, SCREEN_SAVER_FORCER
, ScreenSaverReset
);
497 pInfo
= xf86InputDevs
;
499 if (pInfo
->dev
&& (pInfo
->flags
& XI86_DEVICE_DISABLED
) == 0)
500 EnableDevice(pInfo
->dev
, TRUE
);
501 pInfo
->flags
&= ~XI86_DEVICE_DISABLED
;
504 for (ih
= InputHandlers
; ih
; ih
= ih
->next
) {
506 xf86EnableInputHandler(ih
);
508 xf86EnableGeneralHandler(ih
);
517 xf86OSPMClose
= NULL
;
520 for (i
= 0; i
< xf86NumScreens
; i
++) {
522 * zero all access functions to
523 * trap calls when switched away.
525 xf86Screens
[i
]->vtSema
= FALSE
;
532 DebugF("xf86VTSwitch: Entering\n");
533 if (!xf86VTSwitchTo())
537 xf86OSPMClose
= xf86OSPMOpen();
543 for (i
= 0; i
< xf86NumScreens
; i
++) {
544 xf86Screens
[i
]->vtSema
= TRUE
;
545 if (!xf86Screens
[i
]->EnterVT(xf86Screens
[i
]))
546 FatalError("EnterVT failed for screen %d\n", i
);
548 for (i
= 0; i
< xf86NumGPUScreens
; i
++) {
549 xf86GPUScreens
[i
]->vtSema
= TRUE
;
550 if (!xf86GPUScreens
[i
]->EnterVT(xf86GPUScreens
[i
]))
551 FatalError("EnterVT failed for gpu screen %d\n", i
);
553 for (i
= 0; i
< xf86NumScreens
; i
++) {
554 if (xf86Screens
[i
]->EnableDisableFBAccess
)
555 (*xf86Screens
[i
]->EnableDisableFBAccess
) (xf86Screens
[i
], TRUE
);
558 /* Turn screen saver off when switching back */
559 dixSaveScreens(serverClient
, SCREEN_SAVER_FORCER
, ScreenSaverReset
);
561 pInfo
= xf86InputDevs
;
563 if (pInfo
->dev
&& (pInfo
->flags
& XI86_DEVICE_DISABLED
) == 0)
564 EnableDevice(pInfo
->dev
, TRUE
);
565 pInfo
->flags
&= ~XI86_DEVICE_DISABLED
;
569 for (ih
= InputHandlers
; ih
; ih
= ih
->next
) {
571 xf86EnableInputHandler(ih
);
573 xf86EnableGeneralHandler(ih
);
575 #ifdef XSERVER_PLATFORM_BUS
576 /* check for any new output devices */
577 xf86platformVTProbe();
584 /* Input handler registration */
587 addInputHandler(int fd
, InputHandlerProc proc
, pointer data
)
594 ih
= calloc(sizeof(*ih
), 1);
603 ih
->next
= InputHandlers
;
610 xf86AddInputHandler(int fd
, InputHandlerProc proc
, pointer data
)
612 IHPtr ih
= addInputHandler(fd
, proc
, data
);
615 AddEnabledDevice(fd
);
622 xf86AddGeneralHandler(int fd
, InputHandlerProc proc
, pointer data
)
624 IHPtr ih
= addInputHandler(fd
, proc
, data
);
627 AddGeneralSocket(fd
);
632 * Set the handler for the console's fd. Replaces (and returns) the previous
633 * handler or NULL, whichever appropriate.
634 * proc may be NULL if the server should not handle events on the console.
637 xf86SetConsoleHandler(InputHandlerProc proc
, pointer data
)
639 static IHPtr handler
= NULL
;
640 InputHandlerProc old_proc
= NULL
;
643 old_proc
= handler
->ihproc
;
644 xf86RemoveGeneralHandler(handler
);
647 handler
= xf86AddGeneralHandler(xf86Info
.consoleFd
, proc
, data
);
653 removeInputHandler(IHPtr ih
)
657 if (ih
== InputHandlers
)
658 InputHandlers
= ih
->next
;
661 while (p
&& p
->next
!= ih
)
670 xf86RemoveInputHandler(pointer handler
)
682 RemoveEnabledDevice(ih
->fd
);
683 removeInputHandler(ih
);
689 xf86RemoveGeneralHandler(pointer handler
)
701 RemoveGeneralSocket(ih
->fd
);
702 removeInputHandler(ih
);
708 xf86DisableInputHandler(pointer handler
)
718 RemoveEnabledDevice(ih
->fd
);
722 xf86DisableGeneralHandler(pointer handler
)
732 RemoveGeneralSocket(ih
->fd
);
736 xf86EnableInputHandler(pointer handler
)
746 AddEnabledDevice(ih
->fd
);
750 xf86EnableGeneralHandler(pointer handler
)
760 AddGeneralSocket(ih
->fd
);
764 * As used currently by the DRI, the return value is ignored.
767 xf86EnableVTSwitch(Bool
new)
769 static Bool def
= TRUE
;
772 old
= VTSwitchEnabled
;
774 /* Disable VT switching */
775 def
= VTSwitchEnabled
;
776 VTSwitchEnabled
= FALSE
;
779 /* Restore VT switching to default */
780 VTSwitchEnabled
= def
;
786 DDXRingBell(int volume
, int pitch
, int duration
)
788 xf86OSRingBell(volume
, pitch
, duration
);
794 /* at system startup xf86Screens[0] won't be set - but we will own the VT */
795 if (xf86NumScreens
== 0)
797 return xf86Screens
[0]->vtSema
;