aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/dmx/input
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/dmx/input')
-rw-r--r--xorg-server/hw/dmx/input/dmxbackend.c1232
-rw-r--r--xorg-server/hw/dmx/input/dmxcommon.c1339
-rw-r--r--xorg-server/hw/dmx/input/dmxconsole.c2059
-rw-r--r--xorg-server/hw/dmx/input/dmxinputinit.c18
-rw-r--r--xorg-server/hw/dmx/input/dmxinputinit.h582
-rw-r--r--xorg-server/hw/dmx/input/lnx-keyboard.c2
-rw-r--r--xorg-server/hw/dmx/input/lnx-ms.c642
-rw-r--r--xorg-server/hw/dmx/input/lnx-ps2.c578
-rw-r--r--xorg-server/hw/dmx/input/usb-common.c762
9 files changed, 3606 insertions, 3608 deletions
diff --git a/xorg-server/hw/dmx/input/dmxbackend.c b/xorg-server/hw/dmx/input/dmxbackend.c
index 55615cf39..35e9e9616 100644
--- a/xorg-server/hw/dmx/input/dmxbackend.c
+++ b/xorg-server/hw/dmx/input/dmxbackend.c
@@ -1,616 +1,616 @@
-/*
- * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * David H. Dawes <dawes@xfree86.org>
- * Kevin E. Martin <kem@redhat.com>
- * Rickard E. (Rik) Faith <faith@redhat.com>
- */
-
-/** \file
- * These routines support taking input from devices on the backend
- * (output) displays. \see dmxcommon.c. */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#define DMX_BACKEND_DEBUG 0
-
-#include "dmxinputinit.h"
-#include "dmxbackend.h"
-#include "dmxcommon.h"
-#include "dmxconsole.h"
-#include "dmxcursor.h"
-#include "dmxprop.h"
-#include "dmxsync.h"
-#include "dmxcb.h" /* For dmxGlobalWidth and dmxGlobalHeight */
-#include "dmxevents.h" /* For dmxGetGlobalPosition */
-#include "ChkNotMaskEv.h"
-
-#include "inputstr.h"
-#include "input.h"
-#include <X11/keysym.h>
-#include "mipointer.h"
-#include "scrnintstr.h"
-#include "windowstr.h"
-
-/* Private area for backend devices. */
-typedef struct _myPrivate {
- DMX_COMMON_PRIVATE;
- int myScreen;
- DMXScreenInfo *grabbedScreen;
-
- int lastX, lastY;
- int centerX, centerY;
- int relative;
- int newscreen;
- int initialized;
- DevicePtr mou, kbd;
- int entered;
- int offX, offY;
-} myPrivate;
-
-#if DMX_BACKEND_DEBUG
-#define DMXDBG0(f) dmxLog(dmxDebug,f)
-#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
-#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
-#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
-#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
-#define DMXDBG8(f,a,b,c,d,e,g,h,i) dmxLog(dmxDebug,f,a,b,c,d,e,g,h,i)
-#define DMXDBG9(f,a,b,c,d,e,g,h,i,j) dmxLog(dmxDebug,f,a,b,c,d,e,g,h,i,j)
-#else
-#define DMXDBG0(f)
-#define DMXDBG1(f,a)
-#define DMXDBG2(f,a,b)
-#define DMXDBG3(f,a,b,c)
-#define DMXDBG4(f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h)
-#define DMXDBG8(f,a,b,c,d,e,g,h,i)
-#define DMXDBG9(f,a,b,c,d,e,g,h,i,j)
-#endif
-
-/** Create and return a private data structure. */
-pointer dmxBackendCreatePrivate(DeviceIntPtr pDevice)
-{
- GETDMXLOCALFROMPDEVICE;
- myPrivate *priv = calloc(1, sizeof(*priv));
- priv->dmxLocal = dmxLocal;
- return priv;
-}
-
-/** Destroy the private data structure. No checking is performed to
- * verify that the structure was actually created by
- * #dmxBackendCreatePrivate. */
-void dmxBackendDestroyPrivate(pointer private)
-{
- if (private) free(private);
-}
-
-static void *dmxBackendTestScreen(DMXScreenInfo *dmxScreen, void *closure)
-{
- long target = (long)closure;
-
- if (dmxScreen->index == target) return dmxScreen;
- return NULL;
-}
-
-/* Return non-zero if screen and priv->myScreen are on the same physical
- * backend display (1 if they are the same screen, 2 if they are
- * different screens). Since this is a common operation, the results
- * are cached. The cache is invalidated if \a priv is NULL (this should
- * be done with each server generation and reconfiguration). */
-static int dmxBackendSameDisplay(myPrivate *priv, long screen)
-{
- static myPrivate *oldpriv = NULL;
- static int oldscreen = -1;
- static int retcode = 0;
-
- if (priv == oldpriv && screen == oldscreen) return retcode;
- if (!priv) { /* Invalidate cache */
- oldpriv = NULL;
- oldscreen = -1;
- retcode = 0;
- return 0;
- }
-
- if (screen == priv->myScreen) retcode = 1;
- else if (screen < 0 || screen >= dmxNumScreens) retcode = 0;
- else if (dmxPropertyIterate(priv->be,
- dmxBackendTestScreen,
- (void *)screen)) retcode = 2;
- else retcode = 0;
-
- oldpriv = priv;
- oldscreen = screen;
- return retcode;
-}
-
-static void *dmxBackendTestEvents(DMXScreenInfo *dmxScreen, void *closure)
-{
- XEvent *X = (XEvent *)closure;
-
- if (XCheckNotMaskEvent(dmxScreen->beDisplay, ExposureMask, X))
- return dmxScreen;
- return NULL;
-}
-
-static void *dmxBackendTestMotionEvent(DMXScreenInfo *dmxScreen, void *closure)
-{
- XEvent *X = (XEvent *)closure;
-
- if (XCheckTypedEvent(dmxScreen->beDisplay, MotionNotify, X))
- return dmxScreen;
- return NULL;
-}
-
-static DMXScreenInfo *dmxBackendGetEvent(myPrivate *priv, XEvent *X)
-{
- DMXScreenInfo *dmxScreen;
-
- if ((dmxScreen = dmxPropertyIterate(priv->be, dmxBackendTestEvents, X)))
- return dmxScreen;
- return NULL;
-}
-
-static DMXScreenInfo *dmxBackendPendingMotionEvent(myPrivate *priv, int save)
-{
- DMXScreenInfo *dmxScreen;
- XEvent N;
-
- if ((dmxScreen = dmxPropertyIterate(priv->be,
- dmxBackendTestMotionEvent, &N))) {
- if (save) XPutBackEvent(dmxScreen->beDisplay, &N);
- return dmxScreen;
- }
- return NULL;
-}
-
-static void *dmxBackendTestWindow(DMXScreenInfo *dmxScreen, void *closure)
-{
- Window win = (Window)(long)closure;
- if (dmxScreen->scrnWin == win) return dmxScreen;
- return NULL;
-}
-
-static DMXScreenInfo *dmxBackendFindWindow(myPrivate *priv, Window win)
-{
- return dmxPropertyIterate(priv->be, dmxBackendTestWindow,
- (void *)(long)win);
-}
-
-/* If the cursor is over a set of overlapping screens and one of those
- * screens takes backend input, then we want that particular screen to
- * be current, not one of the other ones. */
-static int dmxBackendFindOverlapping(myPrivate *priv, int screen, int x, int y)
-{
- DMXScreenInfo *start = &dmxScreens[screen];
- DMXScreenInfo *pt;
-
- if (!start->over) return screen;
-
- for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
- if (pt->index == priv->myScreen
- && dmxOnScreen(x, y, &dmxScreens[pt->index])) return pt->index;
- if (pt == start) break;
- }
- return screen;
-}
-
-/* Return non-zero if \a x and \a y are off \a screen. */
-static int dmxBackendOffscreen(int screen, int x, int y)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[screen];
-
- return (!dmxOnScreen(x, y, dmxScreen));
-}
-
-/** This routine is called from #dmxCoreMotion for each motion
- * event. \a x and \a y are global coordinants. */
-void dmxBackendUpdatePosition(pointer private, int x, int y)
-{
- GETPRIVFROMPRIVATE;
- int screen = miPointerGetScreen(inputInfo.pointer)->myNum;
- DMXScreenInfo *dmxScreen = &dmxScreens[priv->myScreen];
- int oldRelative = priv->relative;
- int topscreen = dmxBackendFindOverlapping(priv, screen, x, y);
- int same = dmxBackendSameDisplay(priv, topscreen);
- int offscreen = dmxBackendOffscreen(priv->myScreen, x, y);
- int offthis = dmxBackendOffscreen(screen, x, y);
-
- DMXDBG9("dmxBackendUpdatePosition(%d,%d) my=%d mi=%d rel=%d"
- " topscreen=%d same=%d offscreen=%d offthis=%d\n",
- x, y, priv->myScreen, screen, priv->relative,
- topscreen, same, offscreen, offthis);
-
- if (offscreen) {
- /* If the cursor is off the input screen, it should be moving
- * relative unless it is visible on a screen of the same display
- * (i.e., one that shares the mouse). */
- if (same == 2 && !offthis) {
- if (priv->relative) {
- DMXDBG0(" Off screen, but not absolute\n");
- priv->relative = 0;
- }
- } else {
- if (!priv->relative) {
- DMXDBG0(" Off screen, but not relative\n");
- priv->relative = 1;
- }
- }
- } else {
- if (topscreen != screen) {
- DMXDBG2(" Using screen %d instead of %d (from mi)\n",
- topscreen, screen);
- }
- if (same) {
- if (priv->relative) {
- DMXDBG0(" On screen, but not absolute\n");
- priv->relative = 0;
- }
- } else {
- if (!priv->relative) {
- DMXDBG0(" Not on screen, but not relative\n");
- priv->relative = 1;
- }
- }
- }
-
- if (oldRelative != priv->relative) {
- DMXDBG2(" Do switch, relative=%d same=%d\n",
- priv->relative, same);
- /* Discard all pre-switch events */
- dmxSync(dmxScreen, TRUE);
- while (dmxBackendPendingMotionEvent(priv, FALSE));
-
- if (dmxInput->console && offscreen) {
- /* Our special case is a console window and a backend window
- * share a display. In this case, the cursor is either on
- * the backend window (taking absolute input), or not (in
- * which case the cursor needs to be in the console
- * window). */
- if (priv->grabbedScreen) {
- DMXDBG2(" *** force ungrab on %s, display=%p\n",
- priv->grabbedScreen->name,
- priv->grabbedScreen->beDisplay);
- XUngrabPointer(priv->grabbedScreen->beDisplay, CurrentTime);
- dmxSync(priv->grabbedScreen, TRUE);
- priv->grabbedScreen = NULL;
- }
- DMXDBG0(" Capturing console\n");
- dmxConsoleCapture(dmxInput);
- } else {
- priv->newscreen = 1;
- if (priv->relative && !dmxInput->console) {
- DMXDBG5(" Hide cursor; warp from %d,%d to %d,%d on %d\n",
- priv->lastX, priv->lastY, priv->centerX, priv->centerY,
- priv->myScreen);
- dmxConsoleUncapture(dmxInput);
- dmxHideCursor(dmxScreen);
- priv->lastX = priv->centerX;
- priv->lastY = priv->centerY;
- XWarpPointer(priv->display, None, priv->window,
- 0, 0, 0, 0, priv->lastX, priv->lastY);
- dmxSync(dmxScreen, TRUE);
- } else {
- DMXDBG0(" Check cursor\n");
- dmxCheckCursor();
- }
- }
- }
-}
-
-/** Get events from the X queue on the backend servers and put the
- * events into the DMX event queue. */
-void dmxBackendCollectEvents(DevicePtr pDev,
- dmxMotionProcPtr motion,
- dmxEnqueueProcPtr enqueue,
- dmxCheckSpecialProcPtr checkspecial,
- DMXBlockType block)
-{
- GETPRIVFROMPDEV;
- GETDMXINPUTFROMPRIV;
- XEvent X;
- DMXScreenInfo *dmxScreen;
- int left = 0;
- int entered = priv->entered;
- int ignoreLeave = 0;
- int v[2];
- int retcode;
-
- while ((dmxScreen = dmxBackendGetEvent(priv, &X))) {
- switch (X.type) {
- case EnterNotify:
- dmxCommonSaveState(priv);
- if (entered++)
- continue;
- priv->entered = 1;
- ignoreLeave = 1;
- DMXDBG5("dmxBackendCollectEvents: Enter %lu %d,%d; GRAB %s %p\n",
- X.xcrossing.root, X.xcrossing.x, X.xcrossing.y,
- dmxScreen->name, dmxScreen->beDisplay);
- XRaiseWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
- priv->grabbedScreen = dmxScreen;
- if ((retcode = XGrabPointer(dmxScreen->beDisplay,
- dmxScreen->scrnWin,
- True, 0, GrabModeAsync,
- GrabModeAsync, None, None,
- CurrentTime))) {
- dmxLog(dmxError,
- "XGrabPointer failed during backend enter (%d)\n",
- retcode);
- }
- break;
- case LeaveNotify:
- if (ignoreLeave) {
- ignoreLeave = 0;
- continue;
- }
- dmxCommonRestoreState(priv);
- if (left++)
- continue;
- DMXDBG7("dmxBackendCollectEvents: Leave %lu %d,%d %d %d %s %s\n",
- X.xcrossing.root, X.xcrossing.x, X.xcrossing.y,
- X.xcrossing.detail, X.xcrossing.focus,
- priv->grabbedScreen ? "UNGRAB" : "",
- dmxScreen->name);
- if (priv->grabbedScreen) {
- XUngrabPointer(priv->grabbedScreen->beDisplay, CurrentTime);
- dmxSync(priv->grabbedScreen, TRUE);
- priv->grabbedScreen = NULL;
- }
- break;
- case MotionNotify:
- DMXDBG9("dmxBackendCollectEvents: MotionNotify %d/%d (mi %d)"
- " newscreen=%d: %d %d (e=%d; last=%d,%d)\n",
- dmxScreen->index, priv->myScreen,
- miPointerCurrentScreen()->myNum,
- priv->newscreen,
- X.xmotion.x, X.xmotion.y,
- entered, priv->lastX, priv->lastY);
- if (dmxBackendPendingMotionEvent(priv, TRUE))
- continue;
- if (!(dmxScreen = dmxBackendFindWindow(priv, X.xmotion.window)))
- dmxLog(dmxFatal,
- " Event on non-existant window %lu\n",
- X.xmotion.window);
- if (!priv->relative || dmxInput->console) {
- int newX = X.xmotion.x - dmxScreen->rootX;
- int newY = X.xmotion.y - dmxScreen->rootY;
-
- if (!priv->newscreen) {
- int width = dmxScreen->rootWidth;
- int height = dmxScreen->rootHeight;
- if (!newX) newX = -1;
- if (newX == width - 1) newX = width;
- if (!newY) newY = -1;
- if (newY == height - 1) newY = height;
- }
- priv->newscreen = 0;
- v[0] = dmxScreen->rootXOrigin + newX;
- v[1] = dmxScreen->rootYOrigin + newY;
- DMXDBG8(" Absolute move: %d,%d (r=%dx%d+%d+%d s=%dx%d)\n",
- v[0], v[1],
- priv->be->rootWidth, priv->be->rootHeight,
- priv->be->rootX, priv->be->rootY,
- priv->be->scrnWidth, priv->be->scrnHeight);
- motion(priv->mou, v, 0, 2, DMX_ABSOLUTE, block);
- priv->entered = 0;
- } else {
- int newX = priv->lastX - X.xmotion.x;
- int newY = priv->lastY - X.xmotion.y;
- priv->lastX = X.xmotion.x;
- priv->lastY = X.xmotion.y;
- v[0] = newX;
- v[1] = newY;
- DMXDBG2(" Relative move: %d, %d\n", v[0], v[1]);
- motion(priv->mou, v, 0, 2, DMX_RELATIVE, block);
- }
- if (entered && priv->relative) {
- DMXDBG4(" **** Relative %d %d instead of absolute %d %d\n",
- v[0], v[1],
- (dmxScreen->rootXOrigin + X.xmotion.x
- - dmxScreen->rootX),
- (dmxScreen->rootYOrigin + X.xmotion.y
- - dmxScreen->rootY));
- }
- break;
-
- case KeyPress:
- case KeyRelease:
- enqueue(priv->kbd, X.type, X.xkey.keycode, 0, NULL, block);
- break;
- case ButtonPress:
- case ButtonRelease:
- /* fall-through */
- default:
- /* Pass the whole event here, because
- * this may be an extension event. */
- enqueue(priv->mou, X.type, X.xbutton.button, 0, &X, block);
- break;
- }
- }
-}
-
-/** Called after input events are processed from the DMX queue. No
- * event processing actually takes place here, but this is a convenient
- * place to update the pointer. */
-void dmxBackendProcessInput(pointer private)
-{
- GETPRIVFROMPRIVATE;
-
- DMXDBG6("dmxBackendProcessInput: myScreen=%d relative=%d"
- " last=%d,%d center=%d,%d\n",
- priv->myScreen, priv->relative,
- priv->lastX, priv->lastY,
- priv->centerX, priv->centerY);
-
- if (priv->relative
- && !dmxInput->console
- && (priv->lastX != priv->centerX || priv->lastY != priv->centerY)) {
- DMXDBG4(" warping pointer from last=%d,%d to center=%d,%d\n",
- priv->lastX, priv->lastY, priv->centerX, priv->centerY);
- priv->lastX = priv->centerX;
- priv->lastY = priv->centerY;
- XWarpPointer(priv->display, None, priv->window,
- 0, 0, 0, 0, priv->lastX, priv->lastY);
- dmxSync(&dmxScreens[priv->myScreen], TRUE);
- }
-}
-
-static void dmxBackendComputeCenter(myPrivate *priv)
-{
- int centerX;
- int centerY;
-
- centerX = priv->be->rootWidth / 2 + priv->be->rootX;
- centerY = priv->be->rootHeight / 2 + priv->be->rootY;
-
- if (centerX > priv->be->rootWidth) centerX = priv->be->rootWidth - 1;
- if (centerY > priv->be->rootHeight) centerY = priv->be->rootHeight - 1;
- if (centerX < 1) centerX = 1;
- if (centerY < 1) centerY = 1;
-
- priv->centerX = centerX;
- priv->centerY = centerY;
-}
-
-static DMXScreenInfo *dmxBackendInitPrivate(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
- DMXScreenInfo *dmxScreen;
- int i;
-
- /* Fill in myPrivate */
- for (i = 0,dmxScreen = &dmxScreens[0]; i<dmxNumScreens; i++,dmxScreen++) {
- if (dmxPropertySameDisplay(dmxScreen, dmxInput->name)) {
- priv->display = dmxScreen->beDisplay;
- priv->window = dmxScreen->scrnWin;
- priv->be = dmxScreen;
- break;
- }
- }
-
- if (i >= dmxNumScreens)
- dmxLog(dmxFatal,
- "%s is not an existing backend display - cannot initialize\n",
- dmxInput->name);
-
- return dmxScreen;
-}
-
-/** Re-initialized the backend device described by \a pDev (after a
- * reconfig). */
-void dmxBackendLateReInit(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- int x, y;
-
- DMXDBG1("dmxBackendLateReInit miPointerCurrentScreen() = %p\n",
- miPointerCurrentScreen());
-
- dmxBackendSameDisplay(NULL, 0); /* Invalidate cache */
- dmxBackendInitPrivate(pDev);
- dmxBackendComputeCenter(priv);
- dmxGetGlobalPosition(&x, &y);
- dmxInvalidateGlobalPosition(); /* To force event processing */
- dmxBackendUpdatePosition(priv, x, y);
-}
-
-/** Initialized the backend device described by \a pDev. */
-void dmxBackendInit(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- DMXScreenInfo *dmxScreen;
-
- dmxBackendSameDisplay(NULL, 0); /* Invalidate cache */
-
- if (dmxLocal->type == DMX_LOCAL_MOUSE) priv->mou = pDev;
- if (dmxLocal->type == DMX_LOCAL_KEYBOARD) priv->kbd = pDev;
- if (priv->initialized++) return; /* Only do once for mouse/keyboard pair */
-
- dmxScreen = dmxBackendInitPrivate(pDev);
-
- /* Finish initialization using computed values or constants. */
- dmxBackendComputeCenter(priv);
- priv->eventMask = (EnterWindowMask|LeaveWindowMask);
- priv->myScreen = dmxScreen->index;
- priv->lastX = priv->centerX;
- priv->lastY = priv->centerY;
- priv->relative = 0;
- priv->newscreen = 0;
-}
-
-/** Get information about the backend pointer (for initialization). */
-void dmxBackendMouGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- const DMXScreenInfo *dmxScreen = dmxBackendInitPrivate(pDev);
-
- info->buttonClass = 1;
- dmxCommonMouGetMap(pDev, info->map, &info->numButtons);
- info->valuatorClass = 1;
- info->numRelAxes = 2;
- info->minval[0] = 0;
- info->minval[1] = 0;
- info->maxval[0] = dmxScreen->beWidth;
- info->maxval[1] = dmxScreen->beHeight;
- info->res[0] = 1;
- info->minres[0] = 0;
- info->maxres[0] = 1;
- info->ptrFeedbackClass = 1;
-}
-
-/** Get information about the backend keyboard (for initialization). */
-void dmxBackendKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- dmxCommonKbdGetInfo(pDev, info);
- info->keyboard = 1;
- info->keyClass = 1;
- dmxCommonKbdGetMap(pDev, &info->keySyms, info->modMap);
- info->freemap = 1;
- info->focusClass = 1;
- info->kbdFeedbackClass = 1;
-}
-
-/** Process #DMXFunctionType functions. The only function handled here
- * is to acknowledge a pending server shutdown. */
-int dmxBackendFunctions(pointer private, DMXFunctionType function)
-{
- switch (function) {
- case DMX_FUNCTION_TERMINATE:
- return 1;
- default:
- return 0;
- }
-}
+/*
+ * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * David H. Dawes <dawes@xfree86.org>
+ * Kevin E. Martin <kem@redhat.com>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ */
+
+/** \file
+ * These routines support taking input from devices on the backend
+ * (output) displays. \see dmxcommon.c. */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#define DMX_BACKEND_DEBUG 0
+
+#include "dmxinputinit.h"
+#include "dmxbackend.h"
+#include "dmxcommon.h"
+#include "dmxconsole.h"
+#include "dmxcursor.h"
+#include "dmxprop.h"
+#include "dmxsync.h"
+#include "dmxcb.h" /* For dmxGlobalWidth and dmxGlobalHeight */
+#include "dmxevents.h" /* For dmxGetGlobalPosition */
+#include "ChkNotMaskEv.h"
+
+#include "inputstr.h"
+#include "input.h"
+#include <X11/keysym.h>
+#include "mipointer.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+
+/* Private area for backend devices. */
+typedef struct _myPrivate {
+ DMX_COMMON_PRIVATE;
+ int myScreen;
+ DMXScreenInfo *grabbedScreen;
+
+ int lastX, lastY;
+ int centerX, centerY;
+ int relative;
+ int newscreen;
+ int initialized;
+ DevicePtr mou, kbd;
+ int entered;
+ int offX, offY;
+} myPrivate;
+
+#if DMX_BACKEND_DEBUG
+#define DMXDBG0(f) dmxLog(dmxDebug,f)
+#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
+#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
+#define DMXDBG8(f,a,b,c,d,e,g,h,i) dmxLog(dmxDebug,f,a,b,c,d,e,g,h,i)
+#define DMXDBG9(f,a,b,c,d,e,g,h,i,j) dmxLog(dmxDebug,f,a,b,c,d,e,g,h,i,j)
+#else
+#define DMXDBG0(f)
+#define DMXDBG1(f,a)
+#define DMXDBG2(f,a,b)
+#define DMXDBG3(f,a,b,c)
+#define DMXDBG4(f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h)
+#define DMXDBG8(f,a,b,c,d,e,g,h,i)
+#define DMXDBG9(f,a,b,c,d,e,g,h,i,j)
+#endif
+
+/** Create and return a private data structure. */
+pointer dmxBackendCreatePrivate(DeviceIntPtr pDevice)
+{
+ GETDMXLOCALFROMPDEVICE;
+ myPrivate *priv = calloc(1, sizeof(*priv));
+ priv->dmxLocal = dmxLocal;
+ return priv;
+}
+
+/** Destroy the private data structure. No checking is performed to
+ * verify that the structure was actually created by
+ * #dmxBackendCreatePrivate. */
+void dmxBackendDestroyPrivate(pointer private)
+{
+ free(private);
+}
+
+static void *dmxBackendTestScreen(DMXScreenInfo *dmxScreen, void *closure)
+{
+ long target = (long)closure;
+
+ if (dmxScreen->index == target) return dmxScreen;
+ return NULL;
+}
+
+/* Return non-zero if screen and priv->myScreen are on the same physical
+ * backend display (1 if they are the same screen, 2 if they are
+ * different screens). Since this is a common operation, the results
+ * are cached. The cache is invalidated if \a priv is NULL (this should
+ * be done with each server generation and reconfiguration). */
+static int dmxBackendSameDisplay(myPrivate *priv, long screen)
+{
+ static myPrivate *oldpriv = NULL;
+ static int oldscreen = -1;
+ static int retcode = 0;
+
+ if (priv == oldpriv && screen == oldscreen) return retcode;
+ if (!priv) { /* Invalidate cache */
+ oldpriv = NULL;
+ oldscreen = -1;
+ retcode = 0;
+ return 0;
+ }
+
+ if (screen == priv->myScreen) retcode = 1;
+ else if (screen < 0 || screen >= dmxNumScreens) retcode = 0;
+ else if (dmxPropertyIterate(priv->be,
+ dmxBackendTestScreen,
+ (void *)screen)) retcode = 2;
+ else retcode = 0;
+
+ oldpriv = priv;
+ oldscreen = screen;
+ return retcode;
+}
+
+static void *dmxBackendTestEvents(DMXScreenInfo *dmxScreen, void *closure)
+{
+ XEvent *X = (XEvent *)closure;
+
+ if (XCheckNotMaskEvent(dmxScreen->beDisplay, ExposureMask, X))
+ return dmxScreen;
+ return NULL;
+}
+
+static void *dmxBackendTestMotionEvent(DMXScreenInfo *dmxScreen, void *closure)
+{
+ XEvent *X = (XEvent *)closure;
+
+ if (XCheckTypedEvent(dmxScreen->beDisplay, MotionNotify, X))
+ return dmxScreen;
+ return NULL;
+}
+
+static DMXScreenInfo *dmxBackendGetEvent(myPrivate *priv, XEvent *X)
+{
+ DMXScreenInfo *dmxScreen;
+
+ if ((dmxScreen = dmxPropertyIterate(priv->be, dmxBackendTestEvents, X)))
+ return dmxScreen;
+ return NULL;
+}
+
+static DMXScreenInfo *dmxBackendPendingMotionEvent(myPrivate *priv, int save)
+{
+ DMXScreenInfo *dmxScreen;
+ XEvent N;
+
+ if ((dmxScreen = dmxPropertyIterate(priv->be,
+ dmxBackendTestMotionEvent, &N))) {
+ if (save) XPutBackEvent(dmxScreen->beDisplay, &N);
+ return dmxScreen;
+ }
+ return NULL;
+}
+
+static void *dmxBackendTestWindow(DMXScreenInfo *dmxScreen, void *closure)
+{
+ Window win = (Window)(long)closure;
+ if (dmxScreen->scrnWin == win) return dmxScreen;
+ return NULL;
+}
+
+static DMXScreenInfo *dmxBackendFindWindow(myPrivate *priv, Window win)
+{
+ return dmxPropertyIterate(priv->be, dmxBackendTestWindow,
+ (void *)(long)win);
+}
+
+/* If the cursor is over a set of overlapping screens and one of those
+ * screens takes backend input, then we want that particular screen to
+ * be current, not one of the other ones. */
+static int dmxBackendFindOverlapping(myPrivate *priv, int screen, int x, int y)
+{
+ DMXScreenInfo *start = &dmxScreens[screen];
+ DMXScreenInfo *pt;
+
+ if (!start->over) return screen;
+
+ for (pt = start->over; /* condition at end of loop */; pt = pt->over) {
+ if (pt->index == priv->myScreen
+ && dmxOnScreen(x, y, &dmxScreens[pt->index])) return pt->index;
+ if (pt == start) break;
+ }
+ return screen;
+}
+
+/* Return non-zero if \a x and \a y are off \a screen. */
+static int dmxBackendOffscreen(int screen, int x, int y)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[screen];
+
+ return (!dmxOnScreen(x, y, dmxScreen));
+}
+
+/** This routine is called from #dmxCoreMotion for each motion
+ * event. \a x and \a y are global coordinants. */
+void dmxBackendUpdatePosition(pointer private, int x, int y)
+{
+ GETPRIVFROMPRIVATE;
+ int screen = miPointerGetScreen(inputInfo.pointer)->myNum;
+ DMXScreenInfo *dmxScreen = &dmxScreens[priv->myScreen];
+ int oldRelative = priv->relative;
+ int topscreen = dmxBackendFindOverlapping(priv, screen, x, y);
+ int same = dmxBackendSameDisplay(priv, topscreen);
+ int offscreen = dmxBackendOffscreen(priv->myScreen, x, y);
+ int offthis = dmxBackendOffscreen(screen, x, y);
+
+ DMXDBG9("dmxBackendUpdatePosition(%d,%d) my=%d mi=%d rel=%d"
+ " topscreen=%d same=%d offscreen=%d offthis=%d\n",
+ x, y, priv->myScreen, screen, priv->relative,
+ topscreen, same, offscreen, offthis);
+
+ if (offscreen) {
+ /* If the cursor is off the input screen, it should be moving
+ * relative unless it is visible on a screen of the same display
+ * (i.e., one that shares the mouse). */
+ if (same == 2 && !offthis) {
+ if (priv->relative) {
+ DMXDBG0(" Off screen, but not absolute\n");
+ priv->relative = 0;
+ }
+ } else {
+ if (!priv->relative) {
+ DMXDBG0(" Off screen, but not relative\n");
+ priv->relative = 1;
+ }
+ }
+ } else {
+ if (topscreen != screen) {
+ DMXDBG2(" Using screen %d instead of %d (from mi)\n",
+ topscreen, screen);
+ }
+ if (same) {
+ if (priv->relative) {
+ DMXDBG0(" On screen, but not absolute\n");
+ priv->relative = 0;
+ }
+ } else {
+ if (!priv->relative) {
+ DMXDBG0(" Not on screen, but not relative\n");
+ priv->relative = 1;
+ }
+ }
+ }
+
+ if (oldRelative != priv->relative) {
+ DMXDBG2(" Do switch, relative=%d same=%d\n",
+ priv->relative, same);
+ /* Discard all pre-switch events */
+ dmxSync(dmxScreen, TRUE);
+ while (dmxBackendPendingMotionEvent(priv, FALSE));
+
+ if (dmxInput->console && offscreen) {
+ /* Our special case is a console window and a backend window
+ * share a display. In this case, the cursor is either on
+ * the backend window (taking absolute input), or not (in
+ * which case the cursor needs to be in the console
+ * window). */
+ if (priv->grabbedScreen) {
+ DMXDBG2(" *** force ungrab on %s, display=%p\n",
+ priv->grabbedScreen->name,
+ priv->grabbedScreen->beDisplay);
+ XUngrabPointer(priv->grabbedScreen->beDisplay, CurrentTime);
+ dmxSync(priv->grabbedScreen, TRUE);
+ priv->grabbedScreen = NULL;
+ }
+ DMXDBG0(" Capturing console\n");
+ dmxConsoleCapture(dmxInput);
+ } else {
+ priv->newscreen = 1;
+ if (priv->relative && !dmxInput->console) {
+ DMXDBG5(" Hide cursor; warp from %d,%d to %d,%d on %d\n",
+ priv->lastX, priv->lastY, priv->centerX, priv->centerY,
+ priv->myScreen);
+ dmxConsoleUncapture(dmxInput);
+ dmxHideCursor(dmxScreen);
+ priv->lastX = priv->centerX;
+ priv->lastY = priv->centerY;
+ XWarpPointer(priv->display, None, priv->window,
+ 0, 0, 0, 0, priv->lastX, priv->lastY);
+ dmxSync(dmxScreen, TRUE);
+ } else {
+ DMXDBG0(" Check cursor\n");
+ dmxCheckCursor();
+ }
+ }
+ }
+}
+
+/** Get events from the X queue on the backend servers and put the
+ * events into the DMX event queue. */
+void dmxBackendCollectEvents(DevicePtr pDev,
+ dmxMotionProcPtr motion,
+ dmxEnqueueProcPtr enqueue,
+ dmxCheckSpecialProcPtr checkspecial,
+ DMXBlockType block)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+ XEvent X;
+ DMXScreenInfo *dmxScreen;
+ int left = 0;
+ int entered = priv->entered;
+ int ignoreLeave = 0;
+ int v[2];
+ int retcode;
+
+ while ((dmxScreen = dmxBackendGetEvent(priv, &X))) {
+ switch (X.type) {
+ case EnterNotify:
+ dmxCommonSaveState(priv);
+ if (entered++)
+ continue;
+ priv->entered = 1;
+ ignoreLeave = 1;
+ DMXDBG5("dmxBackendCollectEvents: Enter %lu %d,%d; GRAB %s %p\n",
+ X.xcrossing.root, X.xcrossing.x, X.xcrossing.y,
+ dmxScreen->name, dmxScreen->beDisplay);
+ XRaiseWindow(dmxScreen->beDisplay, dmxScreen->scrnWin);
+ priv->grabbedScreen = dmxScreen;
+ if ((retcode = XGrabPointer(dmxScreen->beDisplay,
+ dmxScreen->scrnWin,
+ True, 0, GrabModeAsync,
+ GrabModeAsync, None, None,
+ CurrentTime))) {
+ dmxLog(dmxError,
+ "XGrabPointer failed during backend enter (%d)\n",
+ retcode);
+ }
+ break;
+ case LeaveNotify:
+ if (ignoreLeave) {
+ ignoreLeave = 0;
+ continue;
+ }
+ dmxCommonRestoreState(priv);
+ if (left++)
+ continue;
+ DMXDBG7("dmxBackendCollectEvents: Leave %lu %d,%d %d %d %s %s\n",
+ X.xcrossing.root, X.xcrossing.x, X.xcrossing.y,
+ X.xcrossing.detail, X.xcrossing.focus,
+ priv->grabbedScreen ? "UNGRAB" : "",
+ dmxScreen->name);
+ if (priv->grabbedScreen) {
+ XUngrabPointer(priv->grabbedScreen->beDisplay, CurrentTime);
+ dmxSync(priv->grabbedScreen, TRUE);
+ priv->grabbedScreen = NULL;
+ }
+ break;
+ case MotionNotify:
+ DMXDBG9("dmxBackendCollectEvents: MotionNotify %d/%d (mi %d)"
+ " newscreen=%d: %d %d (e=%d; last=%d,%d)\n",
+ dmxScreen->index, priv->myScreen,
+ miPointerCurrentScreen()->myNum,
+ priv->newscreen,
+ X.xmotion.x, X.xmotion.y,
+ entered, priv->lastX, priv->lastY);
+ if (dmxBackendPendingMotionEvent(priv, TRUE))
+ continue;
+ if (!(dmxScreen = dmxBackendFindWindow(priv, X.xmotion.window)))
+ dmxLog(dmxFatal,
+ " Event on non-existant window %lu\n",
+ X.xmotion.window);
+ if (!priv->relative || dmxInput->console) {
+ int newX = X.xmotion.x - dmxScreen->rootX;
+ int newY = X.xmotion.y - dmxScreen->rootY;
+
+ if (!priv->newscreen) {
+ int width = dmxScreen->rootWidth;
+ int height = dmxScreen->rootHeight;
+ if (!newX) newX = -1;
+ if (newX == width - 1) newX = width;
+ if (!newY) newY = -1;
+ if (newY == height - 1) newY = height;
+ }
+ priv->newscreen = 0;
+ v[0] = dmxScreen->rootXOrigin + newX;
+ v[1] = dmxScreen->rootYOrigin + newY;
+ DMXDBG8(" Absolute move: %d,%d (r=%dx%d+%d+%d s=%dx%d)\n",
+ v[0], v[1],
+ priv->be->rootWidth, priv->be->rootHeight,
+ priv->be->rootX, priv->be->rootY,
+ priv->be->scrnWidth, priv->be->scrnHeight);
+ motion(priv->mou, v, 0, 2, DMX_ABSOLUTE, block);
+ priv->entered = 0;
+ } else {
+ int newX = priv->lastX - X.xmotion.x;
+ int newY = priv->lastY - X.xmotion.y;
+ priv->lastX = X.xmotion.x;
+ priv->lastY = X.xmotion.y;
+ v[0] = newX;
+ v[1] = newY;
+ DMXDBG2(" Relative move: %d, %d\n", v[0], v[1]);
+ motion(priv->mou, v, 0, 2, DMX_RELATIVE, block);
+ }
+ if (entered && priv->relative) {
+ DMXDBG4(" **** Relative %d %d instead of absolute %d %d\n",
+ v[0], v[1],
+ (dmxScreen->rootXOrigin + X.xmotion.x
+ - dmxScreen->rootX),
+ (dmxScreen->rootYOrigin + X.xmotion.y
+ - dmxScreen->rootY));
+ }
+ break;
+
+ case KeyPress:
+ case KeyRelease:
+ enqueue(priv->kbd, X.type, X.xkey.keycode, 0, NULL, block);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ /* fall-through */
+ default:
+ /* Pass the whole event here, because
+ * this may be an extension event. */
+ enqueue(priv->mou, X.type, X.xbutton.button, 0, &X, block);
+ break;
+ }
+ }
+}
+
+/** Called after input events are processed from the DMX queue. No
+ * event processing actually takes place here, but this is a convenient
+ * place to update the pointer. */
+void dmxBackendProcessInput(pointer private)
+{
+ GETPRIVFROMPRIVATE;
+
+ DMXDBG6("dmxBackendProcessInput: myScreen=%d relative=%d"
+ " last=%d,%d center=%d,%d\n",
+ priv->myScreen, priv->relative,
+ priv->lastX, priv->lastY,
+ priv->centerX, priv->centerY);
+
+ if (priv->relative
+ && !dmxInput->console
+ && (priv->lastX != priv->centerX || priv->lastY != priv->centerY)) {
+ DMXDBG4(" warping pointer from last=%d,%d to center=%d,%d\n",
+ priv->lastX, priv->lastY, priv->centerX, priv->centerY);
+ priv->lastX = priv->centerX;
+ priv->lastY = priv->centerY;
+ XWarpPointer(priv->display, None, priv->window,
+ 0, 0, 0, 0, priv->lastX, priv->lastY);
+ dmxSync(&dmxScreens[priv->myScreen], TRUE);
+ }
+}
+
+static void dmxBackendComputeCenter(myPrivate *priv)
+{
+ int centerX;
+ int centerY;
+
+ centerX = priv->be->rootWidth / 2 + priv->be->rootX;
+ centerY = priv->be->rootHeight / 2 + priv->be->rootY;
+
+ if (centerX > priv->be->rootWidth) centerX = priv->be->rootWidth - 1;
+ if (centerY > priv->be->rootHeight) centerY = priv->be->rootHeight - 1;
+ if (centerX < 1) centerX = 1;
+ if (centerY < 1) centerY = 1;
+
+ priv->centerX = centerX;
+ priv->centerY = centerY;
+}
+
+static DMXScreenInfo *dmxBackendInitPrivate(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
+ DMXScreenInfo *dmxScreen;
+ int i;
+
+ /* Fill in myPrivate */
+ for (i = 0,dmxScreen = &dmxScreens[0]; i<dmxNumScreens; i++,dmxScreen++) {
+ if (dmxPropertySameDisplay(dmxScreen, dmxInput->name)) {
+ priv->display = dmxScreen->beDisplay;
+ priv->window = dmxScreen->scrnWin;
+ priv->be = dmxScreen;
+ break;
+ }
+ }
+
+ if (i >= dmxNumScreens)
+ dmxLog(dmxFatal,
+ "%s is not an existing backend display - cannot initialize\n",
+ dmxInput->name);
+
+ return dmxScreen;
+}
+
+/** Re-initialized the backend device described by \a pDev (after a
+ * reconfig). */
+void dmxBackendLateReInit(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ int x, y;
+
+ DMXDBG1("dmxBackendLateReInit miPointerCurrentScreen() = %p\n",
+ miPointerCurrentScreen());
+
+ dmxBackendSameDisplay(NULL, 0); /* Invalidate cache */
+ dmxBackendInitPrivate(pDev);
+ dmxBackendComputeCenter(priv);
+ dmxGetGlobalPosition(&x, &y);
+ dmxInvalidateGlobalPosition(); /* To force event processing */
+ dmxBackendUpdatePosition(priv, x, y);
+}
+
+/** Initialized the backend device described by \a pDev. */
+void dmxBackendInit(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ DMXScreenInfo *dmxScreen;
+
+ dmxBackendSameDisplay(NULL, 0); /* Invalidate cache */
+
+ if (dmxLocal->type == DMX_LOCAL_MOUSE) priv->mou = pDev;
+ if (dmxLocal->type == DMX_LOCAL_KEYBOARD) priv->kbd = pDev;
+ if (priv->initialized++) return; /* Only do once for mouse/keyboard pair */
+
+ dmxScreen = dmxBackendInitPrivate(pDev);
+
+ /* Finish initialization using computed values or constants. */
+ dmxBackendComputeCenter(priv);
+ priv->eventMask = (EnterWindowMask|LeaveWindowMask);
+ priv->myScreen = dmxScreen->index;
+ priv->lastX = priv->centerX;
+ priv->lastY = priv->centerY;
+ priv->relative = 0;
+ priv->newscreen = 0;
+}
+
+/** Get information about the backend pointer (for initialization). */
+void dmxBackendMouGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ const DMXScreenInfo *dmxScreen = dmxBackendInitPrivate(pDev);
+
+ info->buttonClass = 1;
+ dmxCommonMouGetMap(pDev, info->map, &info->numButtons);
+ info->valuatorClass = 1;
+ info->numRelAxes = 2;
+ info->minval[0] = 0;
+ info->minval[1] = 0;
+ info->maxval[0] = dmxScreen->beWidth;
+ info->maxval[1] = dmxScreen->beHeight;
+ info->res[0] = 1;
+ info->minres[0] = 0;
+ info->maxres[0] = 1;
+ info->ptrFeedbackClass = 1;
+}
+
+/** Get information about the backend keyboard (for initialization). */
+void dmxBackendKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ dmxCommonKbdGetInfo(pDev, info);
+ info->keyboard = 1;
+ info->keyClass = 1;
+ dmxCommonKbdGetMap(pDev, &info->keySyms, info->modMap);
+ info->freemap = 1;
+ info->focusClass = 1;
+ info->kbdFeedbackClass = 1;
+}
+
+/** Process #DMXFunctionType functions. The only function handled here
+ * is to acknowledge a pending server shutdown. */
+int dmxBackendFunctions(pointer private, DMXFunctionType function)
+{
+ switch (function) {
+ case DMX_FUNCTION_TERMINATE:
+ return 1;
+ default:
+ return 0;
+ }
+}
diff --git a/xorg-server/hw/dmx/input/dmxcommon.c b/xorg-server/hw/dmx/input/dmxcommon.c
index da5b77893..29c1958ad 100644
--- a/xorg-server/hw/dmx/input/dmxcommon.c
+++ b/xorg-server/hw/dmx/input/dmxcommon.c
@@ -1,670 +1,669 @@
-/*
- * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * David H. Dawes <dawes@xfree86.org>
- * Kevin E. Martin <kem@redhat.com>
- * Rickard E. (Rik) Faith <faith@redhat.com>
- */
-
-/** \file
- *
- * This file implements common routines used by the backend and console
- * input devices.
- */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#define DMX_STATE_DEBUG 0
-
-#include "dmxinputinit.h"
-#include "dmxcommon.h"
-#include "dmxconsole.h"
-#include "dmxprop.h"
-#include "dmxsync.h"
-#include "dmxmap.h"
-
-#include "inputstr.h"
-#include "input.h"
-#include <X11/keysym.h>
-#include "mipointer.h"
-#include "scrnintstr.h"
-
-#include <unistd.h> /* For usleep() */
-
-#if DMX_STATE_DEBUG
-#define DMXDBG0(f) dmxLog(dmxDebug,f)
-#else
-#define DMXDBG0(f)
-#endif
-
-/** Each device has a private area that is visible only from inside the
- * driver code. */
-typedef struct _myPrivate {
- DMX_COMMON_PRIVATE;
-} myPrivate;
-
-static void dmxCommonKbdSetAR(Display *display,
- unsigned char *old, unsigned char *new)
-{
- XKeyboardControl kc;
- XKeyboardState ks;
- unsigned long mask = KBKey | KBAutoRepeatMode;
- int i, j;
- int minKeycode, maxKeycode;
-
- if (!old) {
- XGetKeyboardControl(display, &ks);
- old = (unsigned char *)ks.auto_repeats;
- }
-
- XDisplayKeycodes(display, &minKeycode, &maxKeycode);
- for (i = 1; i < 32; i++) {
- if (!old || old[i] != new[i]) {
- for (j = 0; j < 8; j++) {
- if ((new[i] & (1 << j)) != (old[i] & (1 << j))) {
- kc.key = i * 8 + j;
- kc.auto_repeat_mode = ((new[i] & (1 << j))
- ? AutoRepeatModeOn
- : AutoRepeatModeOff);
- if (kc.key >= minKeycode && kc.key <= maxKeycode)
- XChangeKeyboardControl(display, mask, &kc);
- }
- }
- }
- }
-}
-
-static void dmxCommonKbdSetLeds(Display *display, unsigned long new)
-{
- int i;
- XKeyboardControl kc;
-
- for (i = 0; i < 32; i++) {
- kc.led = i + 1;
- kc.led_mode = (new & (1 << i)) ? LedModeOn : LedModeOff;
- XChangeKeyboardControl(display, KBLed | KBLedMode, &kc);
- }
-}
-
-static void dmxCommonKbdSetCtrl(Display *display,
- KeybdCtrl *old, KeybdCtrl *new)
-{
- XKeyboardControl kc;
- unsigned long mask = KBKeyClickPercent | KBAutoRepeatMode;
-
- if (!old
- || old->click != new->click
- || old->autoRepeat != new->autoRepeat) {
-
- kc.key_click_percent = new->click;
- kc.auto_repeat_mode = new->autoRepeat;
-
- XChangeKeyboardControl(display, mask, &kc);
- }
-
- dmxCommonKbdSetLeds(display, new->leds);
- dmxCommonKbdSetAR(display, old ? old->autoRepeats : NULL,
- new->autoRepeats);
-}
-
-static void dmxCommonMouSetCtrl(Display *display, PtrCtrl *old, PtrCtrl *new)
-{
- Bool do_accel, do_threshold;
-
- if (!old
- || old->num != new->num
- || old->den != new->den
- || old->threshold != new->threshold) {
- do_accel = (new->num > 0 && new->den > 0);
- do_threshold = (new->threshold > 0);
- if (do_accel || do_threshold) {
- XChangePointerControl(display, do_accel, do_threshold,
- new->num, new->den, new->threshold);
- }
- }
-}
-
-/** Update the keyboard control. */
-void dmxCommonKbdCtrl(DevicePtr pDev, KeybdCtrl *ctrl)
-{
- GETPRIVFROMPDEV;
-
- if (!priv->stateSaved && priv->be) dmxCommonSaveState(priv);
- if (!priv->display || !priv->stateSaved) return;
- dmxCommonKbdSetCtrl(priv->display,
- priv->kctrlset ? &priv->kctrl : NULL,
- ctrl);
- priv->kctrl = *ctrl;
- priv->kctrlset = 1;
-}
-
-/** Update the mouse control. */
-void dmxCommonMouCtrl(DevicePtr pDev, PtrCtrl *ctrl)
-{
- GETPRIVFROMPDEV;
-
- /* Don't set the acceleration for the
- * console, because that should be
- * controlled by the X server that the
- * console is running on. Otherwise,
- * the acceleration for the console
- * window would be unexpected for the
- * scale of the window. */
- if (priv->be) {
- dmxCommonMouSetCtrl(priv->display,
- priv->mctrlset ? &priv->mctrl : NULL,
- ctrl);
- priv->mctrl = *ctrl;
- priv->mctrlset = 1;
- }
-}
-
-/** Sound they keyboard bell. */
-void dmxCommonKbdBell(DevicePtr pDev, int percent,
- int volume, int pitch, int duration)
-{
- GETPRIVFROMPDEV;
- XKeyboardControl kc;
- XKeyboardState ks;
- unsigned long mask = KBBellPercent | KBBellPitch | KBBellDuration;
-
- if (!priv->be) XGetKeyboardControl(priv->display, &ks);
- kc.bell_percent = volume;
- kc.bell_pitch = pitch;
- kc.bell_duration = duration;
- XChangeKeyboardControl(priv->display, mask, &kc);
- XBell(priv->display, percent);
- if (!priv->be) {
- kc.bell_percent = ks.bell_percent;
- kc.bell_pitch = ks.bell_pitch;
- kc.bell_duration = ks.bell_duration;
- XChangeKeyboardControl(priv->display, mask, &kc);
- }
-}
-
-/** Get the keyboard mapping. */
-void dmxCommonKbdGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap)
-{
- GETPRIVFROMPDEV;
- int min_keycode;
- int max_keycode;
- int map_width;
- KeySym *keyboard_mapping;
- XModifierKeymap *modifier_mapping;
- int i, j;
-
- /* Compute pKeySyms. Cast
- * XGetKeyboardMapping because of
- * compiler warning on 64-bit machines.
- * We assume pointers to 32-bit and
- * 64-bit ints are the same. */
- XDisplayKeycodes(priv->display, &min_keycode, &max_keycode);
- keyboard_mapping = (KeySym *)XGetKeyboardMapping(priv->display,
- min_keycode,
- max_keycode
- - min_keycode + 1,
- &map_width);
- pKeySyms->minKeyCode = min_keycode;
- pKeySyms->maxKeyCode = max_keycode;
- pKeySyms->mapWidth = map_width;
- pKeySyms->map = keyboard_mapping;
-
-
- /* Compute pModMap */
- modifier_mapping = XGetModifierMapping(priv->display);
- for (i = 0; i < MAP_LENGTH; i++)
- pModMap[i] = 0;
- for (j = 0; j < 8; j++) {
- int max_keypermod = modifier_mapping->max_keypermod;
-
- for (i = 0; i < max_keypermod; i++) {
- CARD8 keycode = modifier_mapping->modifiermap[j*max_keypermod + i];
- if (keycode)
- pModMap[keycode] |= 1 << j;
- }
- }
- XFreeModifiermap(modifier_mapping);
-}
-
-/** Fill in the XKEYBOARD parts of the \a info structure for the
- * specified \a pDev. */
-void dmxCommonKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- GETPRIVFROMPDEV;
- GETDMXINPUTFROMPRIV;
- char *pt;
-
- dmxCommonSaveState(priv);
- if (priv->xkb) {
-#define NAME(x) \
- priv->xkb->names->x ? XGetAtomName(priv->display,priv->xkb->names->x) : NULL
- info->names.keycodes = NAME(keycodes);
- info->names.types = NAME(types);
- info->names.compat = NAME(compat);
- info->names.symbols = NAME(symbols);
- info->names.geometry = NAME(geometry);
- info->freenames = 1;
-#undef NAME
- dmxLogInput(dmxInput,
- "XKEYBOARD: keycodes = %s\n", info->names.keycodes);
- dmxLogInput(dmxInput,
- "XKEYBOARD: symbols = %s\n", info->names.symbols);
- dmxLogInput(dmxInput,
- "XKEYBOARD: geometry = %s\n", info->names.geometry);
- if ((pt = strchr(info->names.keycodes, '+'))) *pt = '\0';
- }
- dmxCommonRestoreState(priv);
-}
-
-/** Turn \a pDev on (i.e., take input from \a pDev). */
-int dmxCommonKbdOn(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- if (priv->be) dmxCommonSaveState(priv);
- priv->eventMask |= DMX_KEYBOARD_EVENT_MASK;
- XSelectInput(priv->display, priv->window, priv->eventMask);
- if (priv->be)
- XSetInputFocus(priv->display, priv->window, RevertToPointerRoot,
- CurrentTime);
- return -1;
-}
-
-/** Turn \a pDev off. */
-void dmxCommonKbdOff(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- priv->eventMask &= ~DMX_KEYBOARD_EVENT_MASK;
- XSelectInput(priv->display, priv->window, priv->eventMask);
- dmxCommonRestoreState(priv);
-}
-
-/** Turn \a pDev on (i.e., take input from \a pDev). */
-int dmxCommonOthOn(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- GETDMXINPUTFROMPRIV;
- XEventClass event_list[DMX_MAX_XINPUT_EVENT_TYPES];
- int event_type[DMX_MAX_XINPUT_EVENT_TYPES];
- int count = 0;
-
-#define ADD(type) \
- if (count < DMX_MAX_XINPUT_EVENT_TYPES) { \
- type(priv->xi, event_type[count], event_list[count]); \
- if (event_type[count]) { \
- dmxMapInsert(dmxLocal, event_type[count], XI_##type); \
- ++count; \
- } \
- } else { \
- dmxLog(dmxWarning, "More than %d event types for %s\n", \
- DMX_MAX_XINPUT_EVENT_TYPES, dmxInput->name); \
- }
-
- if (!(priv->xi = XOpenDevice(priv->display, dmxLocal->deviceId))) {
- dmxLog(dmxWarning, "Cannot open %s device (id=%d) on %s\n",
- dmxLocal->deviceName ? dmxLocal->deviceName : "(unknown)",
- dmxLocal->deviceId, dmxInput->name);
- return -1;
- }
- ADD(DeviceKeyPress);
- ADD(DeviceKeyRelease);
- ADD(DeviceButtonPress);
- ADD(DeviceButtonRelease);
- ADD(DeviceMotionNotify);
- ADD(DeviceFocusIn);
- ADD(DeviceFocusOut);
- ADD(ProximityIn);
- ADD(ProximityOut);
- ADD(DeviceStateNotify);
- ADD(DeviceMappingNotify);
- ADD(ChangeDeviceNotify);
- XSelectExtensionEvent(priv->display, priv->window, event_list, count);
-
- return -1;
-}
-
-/** Turn \a pDev off. */
-void dmxCommonOthOff(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
-
- if (priv->xi) XCloseDevice(priv->display, priv->xi);
- priv->xi = NULL;
-}
-
-/** Fill the \a info structure with information needed to initialize \a
- * pDev. */
-void dmxCommonOthGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- GETPRIVFROMPDEV;
- GETDMXINPUTFROMPRIV;
- XExtensionVersion *ext;
- XDeviceInfo *devices;
- Display *display = priv->display;
- int num;
- int i, j, k;
- int (*handler)(Display *, char *, char *);
-
- if (!display && !(display = XOpenDisplay(dmxInput->name)))
- return;
-
- /* Print out information about the XInput Extension. */
- handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler);
- ext = XGetExtensionVersion(display, INAME);
- XSetExtensionErrorHandler(handler);
-
- if (ext && ext != (XExtensionVersion *)NoSuchExtension) {
- XFree(ext);
- devices = XListInputDevices(display, &num);
- for (i = 0; i < num; i++) {
- if (devices[i].id == (XID)dmxLocal->deviceId) {
- XAnyClassPtr any;
- XKeyInfoPtr ki;
- XButtonInfoPtr bi;
- XValuatorInfoPtr vi;
- for (j = 0, any = devices[i].inputclassinfo;
- j < devices[i].num_classes;
- any = (XAnyClassPtr)((char *)any + any->length), j++) {
- switch (any->class) {
- case KeyClass:
- ki = (XKeyInfoPtr)any;
- info->keyboard = 1;
- info->keyClass = 1;
- info->keySyms.minKeyCode = ki->min_keycode;
- info->keySyms.maxKeyCode = ki->max_keycode;
- info->kbdFeedbackClass = 1;
- break;
- case ButtonClass:
- bi = (XButtonInfoPtr)any;
- info->buttonClass = 1;
- info->numButtons = bi->num_buttons;
- info->ptrFeedbackClass = 1;
- break;
- case ValuatorClass:
- /* This assume all axes are either
- * Absolute or Relative. */
- vi = (XValuatorInfoPtr)any;
- info->valuatorClass = 1;
- if (vi->mode == Absolute)
- info->numAbsAxes = vi->num_axes;
- else
- info->numRelAxes = vi->num_axes;
- for (k = 0; k < vi->num_axes; k++) {
- info->res[k] = vi->axes[k].resolution;
- info->minres[k] = vi->axes[k].resolution;
- info->maxres[k] = vi->axes[k].resolution;
- info->minval[k] = vi->axes[k].min_value;
- info->maxval[k] = vi->axes[k].max_value;
- }
- break;
- case FeedbackClass:
- /* Only keyboard and pointer feedback
- * are handled at this time. */
- break;
- case ProximityClass:
- info->proximityClass = 1;
- break;
- case FocusClass:
- info->focusClass = 1;
- break;
- case OtherClass:
- break;
- }
- }
- }
- }
- XFreeDeviceList(devices);
- }
- if (display != priv->display) XCloseDisplay(display);
-}
-
-/** Obtain the mouse button mapping. */
-void dmxCommonMouGetMap(DevicePtr pDev, unsigned char *map, int *nButtons)
-{
- GETPRIVFROMPDEV;
- int i;
-
- *nButtons = XGetPointerMapping(priv->display, map, DMX_MAX_BUTTONS);
- for (i = 0; i <= *nButtons; i++) map[i] = i;
-}
-
-static void *dmxCommonXSelect(DMXScreenInfo *dmxScreen, void *closure)
-{
- myPrivate *priv = closure;
- XSelectInput(dmxScreen->beDisplay, dmxScreen->scrnWin, priv->eventMask);
- return NULL;
-}
-
-static void *dmxCommonAddEnabledDevice(DMXScreenInfo *dmxScreen, void *closure)
-{
- AddEnabledDevice(XConnectionNumber(dmxScreen->beDisplay));
- return NULL;
-}
-
-static void *dmxCommonRemoveEnabledDevice(DMXScreenInfo *dmxScreen,
- void *closure)
-{
- RemoveEnabledDevice(XConnectionNumber(dmxScreen->beDisplay));
- return NULL;
-}
-
-/** Turn \a pDev on (i.e., take input from \a pDev). */
-int dmxCommonMouOn(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- GETDMXINPUTFROMPRIV;
-
- priv->eventMask |= DMX_POINTER_EVENT_MASK;
- if (dmxShadowFB) {
- XWarpPointer(priv->display, priv->window, priv->window,
- 0, 0, 0, 0,
- priv->initPointerX,
- priv->initPointerY);
- dmxSync(&dmxScreens[dmxInput->scrnIdx], TRUE);
- }
- if (!priv->be) {
- XSelectInput(priv->display, priv->window, priv->eventMask);
- AddEnabledDevice(XConnectionNumber(priv->display));
- } else {
- dmxPropertyIterate(priv->be, dmxCommonXSelect, priv);
- dmxPropertyIterate(priv->be, dmxCommonAddEnabledDevice, dmxInput);
- }
-
- return -1;
-}
-
-/** Turn \a pDev off. */
-void dmxCommonMouOff(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- GETDMXINPUTFROMPRIV;
-
- priv->eventMask &= ~DMX_POINTER_EVENT_MASK;
- if (!priv->be) {
- RemoveEnabledDevice(XConnectionNumber(priv->display));
- XSelectInput(priv->display, priv->window, priv->eventMask);
- } else {
- dmxPropertyIterate(priv->be, dmxCommonRemoveEnabledDevice, dmxInput);
- dmxPropertyIterate(priv->be, dmxCommonXSelect, priv);
- }
-}
-
-/** Given the global coordinates \a x and \a y, determine the screen
- * with the lowest number on which those coordinates lie. If they are
- * not on any screen, return -1. The number returned is an index into
- * \a dmxScreenInfo and is between -1 and \a dmxNumScreens - 1,
- * inclusive. */
-int dmxFindPointerScreen(int x, int y)
-{
- int i;
-
- for (i = 0; i < dmxNumScreens; i++) {
- if (x >= dixScreenOrigins[i].x
- && x < dixScreenOrigins[i].x + screenInfo.screens[i]->width
- && y >= dixScreenOrigins[i].y
- && y < dixScreenOrigins[i].y + screenInfo.screens[i]->height)
- return i;
- }
- return -1;
-}
-
-/** Returns a pointer to the private area for the device that comes just
- * prior to \a pDevice in the current \a dmxInput device list. This is
- * used as the private area for the current device in some situations
- * (e.g., when a keyboard and mouse form a pair that should share the
- * same private area). If the requested private area cannot be located,
- * then NULL is returned. */
-pointer dmxCommonCopyPrivate(DeviceIntPtr pDevice)
-{
- GETDMXLOCALFROMPDEVICE;
- DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
- int i;
-
- for (i = 0; i < dmxInput->numDevs; i++)
- if (dmxInput->devs[i] == dmxLocal && i)
- return dmxInput->devs[i-1]->private;
- return NULL;
-}
-
-/** This routine saves and resets some important state for the backend
- * and console device drivers:
- * - the modifier map is saved and set to 0 (so DMX controls the LEDs)
- * - the key click, bell, led, and repeat masks are saved and set to the
- * values that DMX claims to be using
- *
- * This routine and #dmxCommonRestoreState are used when the pointer
- * enters and leaves the console window, or when the backend window is
- * active or not active (for a full-screen window, this only happens at
- * server startup and server shutdown).
- */
-void dmxCommonSaveState(pointer private)
-{
- GETPRIVFROMPRIVATE;
- XKeyboardState ks;
- unsigned long i;
- XModifierKeymap *modmap;
-
- if (dmxInput->console) priv = dmxInput->devs[0]->private;
- if (!priv->display || priv->stateSaved) return;
- DMXDBG0("dmxCommonSaveState\n");
- if (dmxUseXKB && (priv->xkb = XkbAllocKeyboard())) {
- if (XkbGetIndicatorMap(priv->display, XkbAllIndicatorsMask, priv->xkb)
- || XkbGetNames(priv->display, XkbAllNamesMask, priv->xkb)) {
- dmxLogInput(dmxInput, "Could not get XKB information\n");
- XkbFreeKeyboard(priv->xkb, 0, True);
- priv->xkb = NULL;
- } else {
- if (priv->xkb->indicators) {
- priv->savedIndicators = *priv->xkb->indicators;
- for (i = 0; i < XkbNumIndicators; i++)
- if (priv->xkb->indicators->phys_indicators & (1 << i)) {
- priv->xkb->indicators->maps[i].flags
- = XkbIM_NoAutomatic;
- }
- XkbSetIndicatorMap(priv->display, ~0, priv->xkb);
- }
- }
- }
-
- XGetKeyboardControl(priv->display, &ks);
- priv->savedKctrl.click = ks.key_click_percent;
- priv->savedKctrl.bell = ks.bell_percent;
- priv->savedKctrl.bell_pitch = ks.bell_pitch;
- priv->savedKctrl.bell_duration = ks.bell_duration;
- priv->savedKctrl.leds = ks.led_mask;
- priv->savedKctrl.autoRepeat = ks.global_auto_repeat;
- for (i = 0; i < 32; i++)
- priv->savedKctrl.autoRepeats[i] = ks.auto_repeats[i];
-
- dmxCommonKbdSetCtrl(priv->display, &priv->savedKctrl,
- &priv->dmxLocal->kctrl);
-
- priv->savedModMap = XGetModifierMapping(priv->display);
-
- modmap = XNewModifiermap(0);
- XSetModifierMapping(priv->display, modmap);
- if (dmxInput->scrnIdx != -1)
- dmxSync(&dmxScreens[dmxInput->scrnIdx], TRUE);
- XFreeModifiermap(modmap);
-
- priv->stateSaved = 1;
-}
-
-/** This routine restores all the information saved by #dmxCommonSaveState. */
-void dmxCommonRestoreState(pointer private)
-{
- GETPRIVFROMPRIVATE;
- int retcode = -1;
- CARD32 start;
-
- if (dmxInput->console)
- priv = dmxInput->devs[0]->private;
- if (!priv->stateSaved)
- return;
- priv->stateSaved = 0;
-
- DMXDBG0("dmxCommonRestoreState\n");
- if (priv->xkb) {
- *priv->xkb->indicators = priv->savedIndicators;
- XkbSetIndicatorMap(priv->display, ~0, priv->xkb);
- XkbFreeKeyboard(priv->xkb, 0, True);
- priv->xkb = 0;
- }
-
- for (start = GetTimeInMillis(); GetTimeInMillis() - start < 5000;) {
- CARD32 tmp;
-
- retcode = XSetModifierMapping(priv->display, priv->savedModMap);
- if (retcode == MappingSuccess)
- break;
- if (retcode == MappingBusy)
- dmxLogInput(dmxInput, "Keyboard busy, waiting\n");
- else
- dmxLogInput(dmxInput, "Keyboard error, waiting\n");
-
- /* Don't generate X11 protocol for a bit */
- for (tmp = GetTimeInMillis(); GetTimeInMillis() - tmp < 250;) {
- usleep(250); /* This ends up sleeping only until
- * the next key press generates an
- * interruption. We make the delay
- * relatively short in case the user
- * pressed they keys quickly. */
- }
-
- }
- if (retcode != MappingSuccess)
- dmxLog(dmxWarning, "Unable to restore keyboard modifier state!\n");
-
- XFreeModifiermap(priv->savedModMap);
- priv->savedModMap = NULL;
-
- dmxCommonKbdSetCtrl(priv->display, NULL, &priv->savedKctrl);
- priv->kctrlset = 0; /* Invalidate copy */
-}
+/*
+ * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * David H. Dawes <dawes@xfree86.org>
+ * Kevin E. Martin <kem@redhat.com>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ */
+
+/** \file
+ *
+ * This file implements common routines used by the backend and console
+ * input devices.
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#define DMX_STATE_DEBUG 0
+
+#include "dmxinputinit.h"
+#include "dmxcommon.h"
+#include "dmxconsole.h"
+#include "dmxprop.h"
+#include "dmxsync.h"
+#include "dmxmap.h"
+
+#include "inputstr.h"
+#include "input.h"
+#include <X11/keysym.h>
+#include "mipointer.h"
+#include "scrnintstr.h"
+
+#include <unistd.h> /* For usleep() */
+
+#if DMX_STATE_DEBUG
+#define DMXDBG0(f) dmxLog(dmxDebug,f)
+#else
+#define DMXDBG0(f)
+#endif
+
+/** Each device has a private area that is visible only from inside the
+ * driver code. */
+typedef struct _myPrivate {
+ DMX_COMMON_PRIVATE;
+} myPrivate;
+
+static void dmxCommonKbdSetAR(Display *display,
+ unsigned char *old, unsigned char *new)
+{
+ XKeyboardControl kc;
+ XKeyboardState ks;
+ unsigned long mask = KBKey | KBAutoRepeatMode;
+ int i, j;
+ int minKeycode, maxKeycode;
+
+ if (!old) {
+ XGetKeyboardControl(display, &ks);
+ old = (unsigned char *)ks.auto_repeats;
+ }
+
+ XDisplayKeycodes(display, &minKeycode, &maxKeycode);
+ for (i = 1; i < 32; i++) {
+ if (!old || old[i] != new[i]) {
+ for (j = 0; j < 8; j++) {
+ if ((new[i] & (1 << j)) != (old[i] & (1 << j))) {
+ kc.key = i * 8 + j;
+ kc.auto_repeat_mode = ((new[i] & (1 << j))
+ ? AutoRepeatModeOn
+ : AutoRepeatModeOff);
+ if (kc.key >= minKeycode && kc.key <= maxKeycode)
+ XChangeKeyboardControl(display, mask, &kc);
+ }
+ }
+ }
+ }
+}
+
+static void dmxCommonKbdSetLeds(Display *display, unsigned long new)
+{
+ int i;
+ XKeyboardControl kc;
+
+ for (i = 0; i < 32; i++) {
+ kc.led = i + 1;
+ kc.led_mode = (new & (1 << i)) ? LedModeOn : LedModeOff;
+ XChangeKeyboardControl(display, KBLed | KBLedMode, &kc);
+ }
+}
+
+static void dmxCommonKbdSetCtrl(Display *display,
+ KeybdCtrl *old, KeybdCtrl *new)
+{
+ XKeyboardControl kc;
+ unsigned long mask = KBKeyClickPercent | KBAutoRepeatMode;
+
+ if (!old
+ || old->click != new->click
+ || old->autoRepeat != new->autoRepeat) {
+
+ kc.key_click_percent = new->click;
+ kc.auto_repeat_mode = new->autoRepeat;
+
+ XChangeKeyboardControl(display, mask, &kc);
+ }
+
+ dmxCommonKbdSetLeds(display, new->leds);
+ dmxCommonKbdSetAR(display, old ? old->autoRepeats : NULL,
+ new->autoRepeats);
+}
+
+static void dmxCommonMouSetCtrl(Display *display, PtrCtrl *old, PtrCtrl *new)
+{
+ Bool do_accel, do_threshold;
+
+ if (!old
+ || old->num != new->num
+ || old->den != new->den
+ || old->threshold != new->threshold) {
+ do_accel = (new->num > 0 && new->den > 0);
+ do_threshold = (new->threshold > 0);
+ if (do_accel || do_threshold) {
+ XChangePointerControl(display, do_accel, do_threshold,
+ new->num, new->den, new->threshold);
+ }
+ }
+}
+
+/** Update the keyboard control. */
+void dmxCommonKbdCtrl(DevicePtr pDev, KeybdCtrl *ctrl)
+{
+ GETPRIVFROMPDEV;
+
+ if (!priv->stateSaved && priv->be) dmxCommonSaveState(priv);
+ if (!priv->display || !priv->stateSaved) return;
+ dmxCommonKbdSetCtrl(priv->display,
+ priv->kctrlset ? &priv->kctrl : NULL,
+ ctrl);
+ priv->kctrl = *ctrl;
+ priv->kctrlset = 1;
+}
+
+/** Update the mouse control. */
+void dmxCommonMouCtrl(DevicePtr pDev, PtrCtrl *ctrl)
+{
+ GETPRIVFROMPDEV;
+
+ /* Don't set the acceleration for the
+ * console, because that should be
+ * controlled by the X server that the
+ * console is running on. Otherwise,
+ * the acceleration for the console
+ * window would be unexpected for the
+ * scale of the window. */
+ if (priv->be) {
+ dmxCommonMouSetCtrl(priv->display,
+ priv->mctrlset ? &priv->mctrl : NULL,
+ ctrl);
+ priv->mctrl = *ctrl;
+ priv->mctrlset = 1;
+ }
+}
+
+/** Sound they keyboard bell. */
+void dmxCommonKbdBell(DevicePtr pDev, int percent,
+ int volume, int pitch, int duration)
+{
+ GETPRIVFROMPDEV;
+ XKeyboardControl kc;
+ XKeyboardState ks;
+ unsigned long mask = KBBellPercent | KBBellPitch | KBBellDuration;
+
+ if (!priv->be) XGetKeyboardControl(priv->display, &ks);
+ kc.bell_percent = volume;
+ kc.bell_pitch = pitch;
+ kc.bell_duration = duration;
+ XChangeKeyboardControl(priv->display, mask, &kc);
+ XBell(priv->display, percent);
+ if (!priv->be) {
+ kc.bell_percent = ks.bell_percent;
+ kc.bell_pitch = ks.bell_pitch;
+ kc.bell_duration = ks.bell_duration;
+ XChangeKeyboardControl(priv->display, mask, &kc);
+ }
+}
+
+/** Get the keyboard mapping. */
+void dmxCommonKbdGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap)
+{
+ GETPRIVFROMPDEV;
+ int min_keycode;
+ int max_keycode;
+ int map_width;
+ KeySym *keyboard_mapping;
+ XModifierKeymap *modifier_mapping;
+ int i, j;
+
+ /* Compute pKeySyms. Cast
+ * XGetKeyboardMapping because of
+ * compiler warning on 64-bit machines.
+ * We assume pointers to 32-bit and
+ * 64-bit ints are the same. */
+ XDisplayKeycodes(priv->display, &min_keycode, &max_keycode);
+ keyboard_mapping = (KeySym *)XGetKeyboardMapping(priv->display,
+ min_keycode,
+ max_keycode
+ - min_keycode + 1,
+ &map_width);
+ pKeySyms->minKeyCode = min_keycode;
+ pKeySyms->maxKeyCode = max_keycode;
+ pKeySyms->mapWidth = map_width;
+ pKeySyms->map = keyboard_mapping;
+
+
+ /* Compute pModMap */
+ modifier_mapping = XGetModifierMapping(priv->display);
+ for (i = 0; i < MAP_LENGTH; i++)
+ pModMap[i] = 0;
+ for (j = 0; j < 8; j++) {
+ int max_keypermod = modifier_mapping->max_keypermod;
+
+ for (i = 0; i < max_keypermod; i++) {
+ CARD8 keycode = modifier_mapping->modifiermap[j*max_keypermod + i];
+ if (keycode)
+ pModMap[keycode] |= 1 << j;
+ }
+ }
+ XFreeModifiermap(modifier_mapping);
+}
+
+/** Fill in the XKEYBOARD parts of the \a info structure for the
+ * specified \a pDev. */
+void dmxCommonKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+ char *pt;
+
+ dmxCommonSaveState(priv);
+ if (priv->xkb) {
+#define NAME(x) \
+ priv->xkb->names->x ? XGetAtomName(priv->display,priv->xkb->names->x) : NULL
+ info->names.keycodes = NAME(keycodes);
+ info->names.types = NAME(types);
+ info->names.compat = NAME(compat);
+ info->names.symbols = NAME(symbols);
+ info->names.geometry = NAME(geometry);
+ info->freenames = 1;
+#undef NAME
+ dmxLogInput(dmxInput,
+ "XKEYBOARD: keycodes = %s\n", info->names.keycodes);
+ dmxLogInput(dmxInput,
+ "XKEYBOARD: symbols = %s\n", info->names.symbols);
+ dmxLogInput(dmxInput,
+ "XKEYBOARD: geometry = %s\n", info->names.geometry);
+ if ((pt = strchr(info->names.keycodes, '+'))) *pt = '\0';
+ }
+ dmxCommonRestoreState(priv);
+}
+
+/** Turn \a pDev on (i.e., take input from \a pDev). */
+int dmxCommonKbdOn(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ if (priv->be) dmxCommonSaveState(priv);
+ priv->eventMask |= DMX_KEYBOARD_EVENT_MASK;
+ XSelectInput(priv->display, priv->window, priv->eventMask);
+ if (priv->be)
+ XSetInputFocus(priv->display, priv->window, RevertToPointerRoot,
+ CurrentTime);
+ return -1;
+}
+
+/** Turn \a pDev off. */
+void dmxCommonKbdOff(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ priv->eventMask &= ~DMX_KEYBOARD_EVENT_MASK;
+ XSelectInput(priv->display, priv->window, priv->eventMask);
+ dmxCommonRestoreState(priv);
+}
+
+/** Turn \a pDev on (i.e., take input from \a pDev). */
+int dmxCommonOthOn(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+ XEventClass event_list[DMX_MAX_XINPUT_EVENT_TYPES];
+ int event_type[DMX_MAX_XINPUT_EVENT_TYPES];
+ int count = 0;
+
+#define ADD(type) \
+ if (count < DMX_MAX_XINPUT_EVENT_TYPES) { \
+ type(priv->xi, event_type[count], event_list[count]); \
+ if (event_type[count]) { \
+ dmxMapInsert(dmxLocal, event_type[count], XI_##type); \
+ ++count; \
+ } \
+ } else { \
+ dmxLog(dmxWarning, "More than %d event types for %s\n", \
+ DMX_MAX_XINPUT_EVENT_TYPES, dmxInput->name); \
+ }
+
+ if (!(priv->xi = XOpenDevice(priv->display, dmxLocal->deviceId))) {
+ dmxLog(dmxWarning, "Cannot open %s device (id=%d) on %s\n",
+ dmxLocal->deviceName ? dmxLocal->deviceName : "(unknown)",
+ dmxLocal->deviceId, dmxInput->name);
+ return -1;
+ }
+ ADD(DeviceKeyPress);
+ ADD(DeviceKeyRelease);
+ ADD(DeviceButtonPress);
+ ADD(DeviceButtonRelease);
+ ADD(DeviceMotionNotify);
+ ADD(DeviceFocusIn);
+ ADD(DeviceFocusOut);
+ ADD(ProximityIn);
+ ADD(ProximityOut);
+ ADD(DeviceStateNotify);
+ ADD(DeviceMappingNotify);
+ ADD(ChangeDeviceNotify);
+ XSelectExtensionEvent(priv->display, priv->window, event_list, count);
+
+ return -1;
+}
+
+/** Turn \a pDev off. */
+void dmxCommonOthOff(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+
+ if (priv->xi) XCloseDevice(priv->display, priv->xi);
+ priv->xi = NULL;
+}
+
+/** Fill the \a info structure with information needed to initialize \a
+ * pDev. */
+void dmxCommonOthGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+ XExtensionVersion *ext;
+ XDeviceInfo *devices;
+ Display *display = priv->display;
+ int num;
+ int i, j, k;
+ XextErrorHandler handler;
+
+ if (!display && !(display = XOpenDisplay(dmxInput->name)))
+ return;
+
+ /* Print out information about the XInput Extension. */
+ handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler);
+ ext = XGetExtensionVersion(display, INAME);
+ XSetExtensionErrorHandler(handler);
+
+ if (ext && ext != (XExtensionVersion *)NoSuchExtension) {
+ XFree(ext);
+ devices = XListInputDevices(display, &num);
+ for (i = 0; i < num; i++) {
+ if (devices[i].id == (XID)dmxLocal->deviceId) {
+ XAnyClassPtr any;
+ XKeyInfoPtr ki;
+ XButtonInfoPtr bi;
+ XValuatorInfoPtr vi;
+ for (j = 0, any = devices[i].inputclassinfo;
+ j < devices[i].num_classes;
+ any = (XAnyClassPtr)((char *)any + any->length), j++) {
+ switch (any->class) {
+ case KeyClass:
+ ki = (XKeyInfoPtr)any;
+ info->keyboard = 1;
+ info->keyClass = 1;
+ info->keySyms.minKeyCode = ki->min_keycode;
+ info->keySyms.maxKeyCode = ki->max_keycode;
+ info->kbdFeedbackClass = 1;
+ break;
+ case ButtonClass:
+ bi = (XButtonInfoPtr)any;
+ info->buttonClass = 1;
+ info->numButtons = bi->num_buttons;
+ info->ptrFeedbackClass = 1;
+ break;
+ case ValuatorClass:
+ /* This assume all axes are either
+ * Absolute or Relative. */
+ vi = (XValuatorInfoPtr)any;
+ info->valuatorClass = 1;
+ if (vi->mode == Absolute)
+ info->numAbsAxes = vi->num_axes;
+ else
+ info->numRelAxes = vi->num_axes;
+ for (k = 0; k < vi->num_axes; k++) {
+ info->res[k] = vi->axes[k].resolution;
+ info->minres[k] = vi->axes[k].resolution;
+ info->maxres[k] = vi->axes[k].resolution;
+ info->minval[k] = vi->axes[k].min_value;
+ info->maxval[k] = vi->axes[k].max_value;
+ }
+ break;
+ case FeedbackClass:
+ /* Only keyboard and pointer feedback
+ * are handled at this time. */
+ break;
+ case ProximityClass:
+ info->proximityClass = 1;
+ break;
+ case FocusClass:
+ info->focusClass = 1;
+ break;
+ case OtherClass:
+ break;
+ }
+ }
+ }
+ }
+ XFreeDeviceList(devices);
+ }
+ if (display != priv->display) XCloseDisplay(display);
+}
+
+/** Obtain the mouse button mapping. */
+void dmxCommonMouGetMap(DevicePtr pDev, unsigned char *map, int *nButtons)
+{
+ GETPRIVFROMPDEV;
+ int i;
+
+ *nButtons = XGetPointerMapping(priv->display, map, DMX_MAX_BUTTONS);
+ for (i = 0; i <= *nButtons; i++) map[i] = i;
+}
+
+static void *dmxCommonXSelect(DMXScreenInfo *dmxScreen, void *closure)
+{
+ myPrivate *priv = closure;
+ XSelectInput(dmxScreen->beDisplay, dmxScreen->scrnWin, priv->eventMask);
+ return NULL;
+}
+
+static void *dmxCommonAddEnabledDevice(DMXScreenInfo *dmxScreen, void *closure)
+{
+ AddEnabledDevice(XConnectionNumber(dmxScreen->beDisplay));
+ return NULL;
+}
+
+static void *dmxCommonRemoveEnabledDevice(DMXScreenInfo *dmxScreen,
+ void *closure)
+{
+ RemoveEnabledDevice(XConnectionNumber(dmxScreen->beDisplay));
+ return NULL;
+}
+
+/** Turn \a pDev on (i.e., take input from \a pDev). */
+int dmxCommonMouOn(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+
+ priv->eventMask |= DMX_POINTER_EVENT_MASK;
+ if (dmxShadowFB) {
+ XWarpPointer(priv->display, priv->window, priv->window,
+ 0, 0, 0, 0,
+ priv->initPointerX,
+ priv->initPointerY);
+ dmxSync(&dmxScreens[dmxInput->scrnIdx], TRUE);
+ }
+ if (!priv->be) {
+ XSelectInput(priv->display, priv->window, priv->eventMask);
+ AddEnabledDevice(XConnectionNumber(priv->display));
+ } else {
+ dmxPropertyIterate(priv->be, dmxCommonXSelect, priv);
+ dmxPropertyIterate(priv->be, dmxCommonAddEnabledDevice, dmxInput);
+ }
+
+ return -1;
+}
+
+/** Turn \a pDev off. */
+void dmxCommonMouOff(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+
+ priv->eventMask &= ~DMX_POINTER_EVENT_MASK;
+ if (!priv->be) {
+ RemoveEnabledDevice(XConnectionNumber(priv->display));
+ XSelectInput(priv->display, priv->window, priv->eventMask);
+ } else {
+ dmxPropertyIterate(priv->be, dmxCommonRemoveEnabledDevice, dmxInput);
+ dmxPropertyIterate(priv->be, dmxCommonXSelect, priv);
+ }
+}
+
+/** Given the global coordinates \a x and \a y, determine the screen
+ * with the lowest number on which those coordinates lie. If they are
+ * not on any screen, return -1. The number returned is an index into
+ * \a dmxScreenInfo and is between -1 and \a dmxNumScreens - 1,
+ * inclusive. */
+int dmxFindPointerScreen(int x, int y)
+{
+ int i;
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ if (x >= pScreen->x && x < pScreen->x + pScreen->width &&
+ y >= pScreen->y && y < pScreen->y + pScreen->height)
+ return i;
+ }
+ return -1;
+}
+
+/** Returns a pointer to the private area for the device that comes just
+ * prior to \a pDevice in the current \a dmxInput device list. This is
+ * used as the private area for the current device in some situations
+ * (e.g., when a keyboard and mouse form a pair that should share the
+ * same private area). If the requested private area cannot be located,
+ * then NULL is returned. */
+pointer dmxCommonCopyPrivate(DeviceIntPtr pDevice)
+{
+ GETDMXLOCALFROMPDEVICE;
+ DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
+ int i;
+
+ for (i = 0; i < dmxInput->numDevs; i++)
+ if (dmxInput->devs[i] == dmxLocal && i)
+ return dmxInput->devs[i-1]->private;
+ return NULL;
+}
+
+/** This routine saves and resets some important state for the backend
+ * and console device drivers:
+ * - the modifier map is saved and set to 0 (so DMX controls the LEDs)
+ * - the key click, bell, led, and repeat masks are saved and set to the
+ * values that DMX claims to be using
+ *
+ * This routine and #dmxCommonRestoreState are used when the pointer
+ * enters and leaves the console window, or when the backend window is
+ * active or not active (for a full-screen window, this only happens at
+ * server startup and server shutdown).
+ */
+void dmxCommonSaveState(pointer private)
+{
+ GETPRIVFROMPRIVATE;
+ XKeyboardState ks;
+ unsigned long i;
+ XModifierKeymap *modmap;
+
+ if (dmxInput->console) priv = dmxInput->devs[0]->private;
+ if (!priv->display || priv->stateSaved) return;
+ DMXDBG0("dmxCommonSaveState\n");
+ if (dmxUseXKB && (priv->xkb = XkbAllocKeyboard())) {
+ if (XkbGetIndicatorMap(priv->display, XkbAllIndicatorsMask, priv->xkb)
+ || XkbGetNames(priv->display, XkbAllNamesMask, priv->xkb)) {
+ dmxLogInput(dmxInput, "Could not get XKB information\n");
+ XkbFreeKeyboard(priv->xkb, 0, True);
+ priv->xkb = NULL;
+ } else {
+ if (priv->xkb->indicators) {
+ priv->savedIndicators = *priv->xkb->indicators;
+ for (i = 0; i < XkbNumIndicators; i++)
+ if (priv->xkb->indicators->phys_indicators & (1 << i)) {
+ priv->xkb->indicators->maps[i].flags
+ = XkbIM_NoAutomatic;
+ }
+ XkbSetIndicatorMap(priv->display, ~0, priv->xkb);
+ }
+ }
+ }
+
+ XGetKeyboardControl(priv->display, &ks);
+ priv->savedKctrl.click = ks.key_click_percent;
+ priv->savedKctrl.bell = ks.bell_percent;
+ priv->savedKctrl.bell_pitch = ks.bell_pitch;
+ priv->savedKctrl.bell_duration = ks.bell_duration;
+ priv->savedKctrl.leds = ks.led_mask;
+ priv->savedKctrl.autoRepeat = ks.global_auto_repeat;
+ for (i = 0; i < 32; i++)
+ priv->savedKctrl.autoRepeats[i] = ks.auto_repeats[i];
+
+ dmxCommonKbdSetCtrl(priv->display, &priv->savedKctrl,
+ &priv->dmxLocal->kctrl);
+
+ priv->savedModMap = XGetModifierMapping(priv->display);
+
+ modmap = XNewModifiermap(0);
+ XSetModifierMapping(priv->display, modmap);
+ if (dmxInput->scrnIdx != -1)
+ dmxSync(&dmxScreens[dmxInput->scrnIdx], TRUE);
+ XFreeModifiermap(modmap);
+
+ priv->stateSaved = 1;
+}
+
+/** This routine restores all the information saved by #dmxCommonSaveState. */
+void dmxCommonRestoreState(pointer private)
+{
+ GETPRIVFROMPRIVATE;
+ int retcode = -1;
+ CARD32 start;
+
+ if (dmxInput->console)
+ priv = dmxInput->devs[0]->private;
+ if (!priv->stateSaved)
+ return;
+ priv->stateSaved = 0;
+
+ DMXDBG0("dmxCommonRestoreState\n");
+ if (priv->xkb) {
+ *priv->xkb->indicators = priv->savedIndicators;
+ XkbSetIndicatorMap(priv->display, ~0, priv->xkb);
+ XkbFreeKeyboard(priv->xkb, 0, True);
+ priv->xkb = 0;
+ }
+
+ for (start = GetTimeInMillis(); GetTimeInMillis() - start < 5000;) {
+ CARD32 tmp;
+
+ retcode = XSetModifierMapping(priv->display, priv->savedModMap);
+ if (retcode == MappingSuccess)
+ break;
+ if (retcode == MappingBusy)
+ dmxLogInput(dmxInput, "Keyboard busy, waiting\n");
+ else
+ dmxLogInput(dmxInput, "Keyboard error, waiting\n");
+
+ /* Don't generate X11 protocol for a bit */
+ for (tmp = GetTimeInMillis(); GetTimeInMillis() - tmp < 250;) {
+ usleep(250); /* This ends up sleeping only until
+ * the next key press generates an
+ * interruption. We make the delay
+ * relatively short in case the user
+ * pressed they keys quickly. */
+ }
+
+ }
+ if (retcode != MappingSuccess)
+ dmxLog(dmxWarning, "Unable to restore keyboard modifier state!\n");
+
+ XFreeModifiermap(priv->savedModMap);
+ priv->savedModMap = NULL;
+
+ dmxCommonKbdSetCtrl(priv->display, NULL, &priv->savedKctrl);
+ priv->kctrlset = 0; /* Invalidate copy */
+}
diff --git a/xorg-server/hw/dmx/input/dmxconsole.c b/xorg-server/hw/dmx/input/dmxconsole.c
index 9542efacd..d4d73f2e8 100644
--- a/xorg-server/hw/dmx/input/dmxconsole.c
+++ b/xorg-server/hw/dmx/input/dmxconsole.c
@@ -1,1030 +1,1029 @@
-/*
- * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * David H. Dawes <dawes@xfree86.org>
- * Kevin E. Martin <kem@redhat.com>
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- *
- * This file implements the console input devices.
- */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#define DMX_CONSOLE_DEBUG 0
-#define DMX_WINDOW_DEBUG 0
-
-#include "dmxinputinit.h"
-#include "dmxevents.h"
-#include "dmxconsole.h"
-#include "dmxcommon.h"
-#include "dmxscrinit.h"
-#include "dmxcb.h"
-#include "dmxsync.h"
-
-#include "inputstr.h"
-#include "input.h"
-#include "mipointer.h"
-#include "windowstr.h"
-
-#define CONSOLE_NUM 3
-#define CONSOLE_DEN 4
-#define DMX_CONSOLE_NAME "DMX Console"
-#define DMX_RES_NAME "Xdmx"
-#define DMX_RES_CLASS "XDmx"
-#define CONSOLE_BG_COLOR "gray75"
-#define CONSOLE_FG_COLOR "black"
-#define CONSOLE_SCREEN_BG_COLOR "white"
-#define CONSOLE_SCREEN_FG_COLOR "black"
-#define CONSOLE_SCREEN_DET_COLOR "gray75"
-#define CONSOLE_SCREEN_CUR_COLOR "red"
-
-#if DMX_CONSOLE_DEBUG
-#define DMXDBG0(f) dmxLog(dmxDebug,f)
-#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
-#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
-#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
-#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
-#else
-#define DMXDBG0(f)
-#define DMXDBG1(f,a)
-#define DMXDBG2(f,a,b)
-#define DMXDBG3(f,a,b,c)
-#define DMXDBG4(f,a,b,c,d)
-#define DMXDBG5(f,a,b,c,d,e)
-#define DMXDBG6(f,a,b,c,d,e,g)
-#define DMXDBG7(f,a,b,c,d,e,g,h)
-#endif
-
-/* Private area for consoles. */
-typedef struct _myPrivate {
- DMX_COMMON_PRIVATE;
- int lastX;
- int lastY;
- int globalX;
- int globalY;
- int curX;
- int curY;
- int width;
- int height;
- int consWidth;
- int consHeight;
- double xScale;
- double yScale;
- XlibGC gc, gcDet, gcRev, gcCur;
- int grabbed, fine, captured;
- Cursor cursorNormal, cursorGrabbed, cursorEmpty;
- Pixmap pixmap;
-
- CloseScreenProcPtr CloseScreen;
- struct _myPrivate *next; /* for closing multiple consoles */
- int initialized;
- DevicePtr mou, kbd;
-} myPrivate;
-
-static int scalex(myPrivate *priv, int x)
-{
- return (int)((x * priv->xScale) + .5);
-}
-
-static int scaley(myPrivate *priv, int y)
-{
- return (int)((y * priv->yScale) + .5);
-}
-
-static int unscalex(myPrivate *priv, int x)
-{
- return (int)((x / priv->xScale) + .5);
-}
-
-static int unscaley(myPrivate *priv, int y)
-{
- return (int)((y / priv->yScale) + .5);
-}
-
-/** Create the private area for \a pDevice. */
-pointer dmxConsoleCreatePrivate(DeviceIntPtr pDevice)
-{
- GETDMXLOCALFROMPDEVICE;
- myPrivate *priv = calloc(1, sizeof(*priv));
- priv->dmxLocal = dmxLocal;
- return priv;
-}
-
-/** If \a private is non-NULL, free its associated memory. */
-void dmxConsoleDestroyPrivate(pointer private)
-{
- if (private) free(private);
-}
-
-static void dmxConsoleDrawFineCursor(myPrivate *priv, XRectangle *rect)
-{
- int size = 6;
- int x, y;
-
- XDrawLine(priv->display, priv->pixmap, priv->gcCur,
- x = scalex(priv, priv->globalX) - size,
- scaley(priv, priv->globalY),
- scalex(priv, priv->globalX) + size,
- scaley(priv, priv->globalY));
- XDrawLine(priv->display, priv->pixmap, priv->gcCur,
- scalex(priv, priv->globalX),
- y = scaley(priv, priv->globalY) - size,
- scalex(priv, priv->globalX),
- scaley(priv, priv->globalY) + size);
- if (priv->grabbed) {
- XDrawLine(priv->display, priv->pixmap, priv->gcCur,
- scalex(priv, priv->globalX) - (int)(size / 1.4),
- scaley(priv, priv->globalY) - (int)(size / 1.4),
- scalex(priv, priv->globalX) + (int)(size / 1.4),
- scaley(priv, priv->globalY) + (int)(size / 1.4));
- XDrawLine(priv->display, priv->pixmap, priv->gcCur,
- scalex(priv, priv->globalX) - (int)(size / 1.4),
- scaley(priv, priv->globalY) + (int)(size / 1.4),
- scalex(priv, priv->globalX) + (int)(size / 1.4),
- scaley(priv, priv->globalY) - (int)(size / 1.4));
- }
- if (rect) {
- rect->x = x;
- rect->y = y;
- rect->width = 2 * size;
- rect->height = 2 * size;
- }
-}
-
-static void dmxConsoleDrawWindows(pointer private)
-{
- GETONLYPRIVFROMPRIVATE;
- Display *dpy = priv->display;
- int i;
- Region whole, used, avail;
- XRectangle rect;
-
- whole = XCreateRegion();
- used = XCreateRegion();
- avail = XCreateRegion();
- rect.x = 0;
- rect.y = 0;
- rect.width = priv->consWidth;
- rect.height = priv->consHeight;
- XUnionRectWithRegion(&rect, whole, whole);
-
- for (i = 0; i < dmxNumScreens; i++) {
- WindowPtr pRoot = WindowTable[i];
- WindowPtr pChild;
-
-#if DMX_WINDOW_DEBUG
- dmxLog(dmxDebug, "%lu %p %p %p 2\n",
- pRoot->drawable.id,
- pRoot->parent, pRoot->firstChild, pRoot->lastChild);
-#endif
-
- for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib) {
- if (pChild->mapped
- && pChild->realized) {
-#if DMX_WINDOW_DEBUG
- dmxLog(dmxDebug, " %p %d,%d %dx%d %d %d %d RECTS\n",
- pChild,
- pChild->drawable.x,
- pChild->drawable.y,
- pChild->drawable.width,
- pChild->drawable.height,
- pChild->visibility,
- pChild->overrideRedirect,
- REGION_NUM_RECTS(&pChild->clipList));
-#endif
- rect.x = scalex(priv, pChild->drawable.x
- + dixScreenOrigins[i].x);
- rect.y = scaley(priv, pChild->drawable.y
- + dixScreenOrigins[i].y);
- rect.width = scalex(priv, pChild->drawable.width);
- rect.height = scaley(priv, pChild->drawable.height);
- XDrawRectangle(dpy, priv->pixmap, priv->gc,
- rect.x, rect.y, rect.width, rect.height);
- XUnionRectWithRegion(&rect, used, used);
- XSubtractRegion(whole, used, avail);
- XSetRegion(dpy, priv->gc, avail);
- }
- }
-#ifdef PANORAMIX
- if (!noPanoramiXExtension) break; /* Screen 0 valid with Xinerama */
-#endif
- }
- XDestroyRegion(avail);
- XDestroyRegion(used);
- XDestroyRegion(whole);
- XSetClipMask(dpy, priv->gc, None);
-}
-
-static void dmxConsoleDraw(myPrivate *priv, int updateCursor, int update)
-{
- GETDMXINPUTFROMPRIV;
- Display *dpy = priv->display;
- int i;
-
- XFillRectangle(dpy, priv->pixmap, priv->gc, 0, 0,
- priv->consWidth, priv->consHeight);
-
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
- XFillRectangle(dpy, priv->pixmap,
- dmxScreen->beDisplay ? priv->gcRev : priv->gcDet,
- scalex(priv, dixScreenOrigins[i].x),
- scaley(priv, dixScreenOrigins[i].y),
- scalex(priv, screenInfo.screens[i]->width),
- scaley(priv, screenInfo.screens[i]->height));
- }
- for (i = 0; i < dmxNumScreens; i++) {
- XDrawRectangle(dpy, priv->pixmap, priv->gc,
- scalex(priv, dixScreenOrigins[i].x),
- scaley(priv, dixScreenOrigins[i].y),
- scalex(priv, screenInfo.screens[i]->width),
- scaley(priv, screenInfo.screens[i]->height));
- }
- if (dmxInput->windows) dmxConsoleDrawWindows(priv);
- if (priv->fine && updateCursor) dmxConsoleDrawFineCursor(priv, 0);
- if (update) {
- XCopyArea(priv->display, priv->pixmap, priv->window, priv->gc,
- 0, 0, priv->consWidth, priv->consHeight, 0, 0);
- XSync(priv->display, False); /* Not a backend display */
- }
-}
-
-static void dmxConsoleClearCursor(myPrivate *priv, int x, int y,
- XRectangle *rect)
-{
- int cw = 14, ch = 14; /* Clear width and height */
-
- rect->x = scalex(priv, x) - cw/2;
- rect->y = scaley(priv, y) - ch/2;
- rect->width = cw;
- rect->height = ch;
- XSetClipRectangles(priv->display, priv->gc, 0, 0, rect, 1, Unsorted);
- XSetClipRectangles(priv->display, priv->gcDet, 0, 0, rect, 1, Unsorted);
- XSetClipRectangles(priv->display, priv->gcRev, 0, 0, rect, 1, Unsorted);
- dmxConsoleDraw(priv, 0, 0);
- XSetClipMask(priv->display, priv->gc, None);
- XSetClipMask(priv->display, priv->gcDet, None);
- XSetClipMask(priv->display, priv->gcRev, None);
-}
-
-
-static void dmxConsoleUpdateFineCursor(myPrivate *priv)
-{
- int leave = 0;
- XRectangle rects[2];
-
- dmxConsoleClearCursor(priv, priv->globalX, priv->globalY, &rects[0]);
- if (priv->dmxLocal->sendsCore) {
- dmxGetGlobalPosition(&priv->globalX, &priv->globalY);
- } else {
- priv->globalX = priv->dmxLocal->lastX;
- priv->globalY = priv->dmxLocal->lastY;
- }
-
- priv->lastX = scalex(priv, priv->width / 2);
- priv->lastY = scaley(priv, priv->height / 2);
-
- /* Compute new warp position, which may be
- outside the window */
- if (priv->globalX < 1 || priv->globalX >= priv->width) {
- if (priv->globalX < 1) priv->lastX = 0;
- else priv->lastX = scalex(priv, priv->width);
- priv->lastY = scaley(priv, priv->globalY);
- ++leave;
- }
- if (priv->globalY < 1 || priv->globalY >= priv->height) {
- if (priv->globalY < 1) priv->lastY = 0;
- else priv->lastY = scaley(priv, priv->height);
- priv->lastX = scalex(priv, priv->globalX);
- ++leave;
- }
-
- /* Draw pseudo cursor in window */
- dmxConsoleDrawFineCursor(priv, &rects[1]);
-
- XSetClipRectangles(priv->display, priv->gc, 0, 0, rects, 2, Unsorted);
- XCopyArea(priv->display, priv->pixmap, priv->window, priv->gc,
- 0, 0, priv->consWidth, priv->consHeight, 0, 0);
- XSetClipMask(priv->display, priv->gc, None);
-
- DMXDBG2("dmxConsoleUpdateFineCursor: WARP %d %d\n",
- priv->lastX, priv->lastY);
- XWarpPointer(priv->display, priv->window, priv->window,
- 0, 0, 0, 0, priv->lastX, priv->lastY);
- XSync(priv->display, False); /* Not a backend display */
-
- if (leave) {
- XEvent X;
- while (XCheckMaskEvent(priv->display, PointerMotionMask, &X)) {
- if (X.type == MotionNotify) {
- if (X.xmotion.x != priv->lastX || X.xmotion.y != priv->lastY) {
- DMXDBG4("Ignoring motion to %d %d after leave frm %d %d\n",
- X.xmotion.x, X.xmotion.y,
- priv->lastX, priv->lastY);
- }
- } else {
- dmxLog(dmxInfo, "Ignoring event (%d): %s ****************\n",
- X.type, dmxEventName(X.type));
- }
- }
- }
- DMXDBG6("dmxConsoleUpdateFineCursor: Warp %d %d on %d %d [%d %d]\n",
- priv->lastX, priv->lastY,
- scalex(priv, priv->width),
- scaley(priv, priv->height),
- priv->globalX, priv->globalY);
-}
-
-/** Whenever the window layout (size, position, stacking order) might be
- * changed, this routine is called with the \a pWindow that changed and
- * the \a type of change. This routine is called in a conservative
- * fashion: the actual layout of the windows of the screen might not
- * have had any human-visible changes. */
-void dmxConsoleUpdateInfo(pointer private, DMXUpdateType type,
- WindowPtr pWindow)
-{
- GETONLYPRIVFROMPRIVATE;
- dmxConsoleDraw(priv, 1, 1);
-}
-
-static void dmxConsoleMoveAbsolute(myPrivate *priv, int x, int y,
- DevicePtr pDev, dmxMotionProcPtr motion,
- DMXBlockType block)
-{
- int tmpX, tmpY, v[2];
-
- tmpX = unscalex(priv, x);
- tmpY = unscalex(priv, y);
- DMXDBG6("dmxConsoleMoveAbsolute(,%d,%d) %d %d =? %d %d\n",
- x, y, tmpX, tmpY, priv->curX, priv->curY);
- if (tmpX == priv->curX && tmpY == priv->curY) return;
- v[0] = unscalex(priv, x);
- v[1] = unscaley(priv, y);
- motion(pDev, v, 0, 2, DMX_ABSOLUTE_CONFINED, block);
- /* dmxConsoleUpdatePosition gets called here by dmxCoreMotion */
-}
-
-static void dmxConsoleMoveRelative(myPrivate *priv, int x, int y,
- DevicePtr pDev, dmxMotionProcPtr motion,
- DMXBlockType block)
-{
- int v[2];
- /* Ignore the event generated from * warping back to middle */
- if (x == priv->lastX && y == priv->lastY) return;
- v[0] = priv->lastX - x;
- v[1] = priv->lastY - y;
- motion(pDev, v, 0, 2, DMX_RELATIVE, block);
- /* dmxConsoleUpdatePosition gets called here by dmxCoreMotion */
-}
-
-/** This routine gets called from #dmxCoreMotion for each motion. This
- * allows the console's notion of the cursor postion to change when
- * another input device actually caused the change. */
-void dmxConsoleUpdatePosition(pointer private, int x, int y)
-{
- GETONLYPRIVFROMPRIVATE;
- int tmpX, tmpY;
- Display *dpy = priv->display;
- static unsigned long dmxGeneration = 0;
-
-
- tmpX = scalex(priv, x);
- tmpY = scaley(priv, y);
- DMXDBG6("dmxConsoleUpdatePosition(,%d,%d) new=%d,%d dims=%d,%d\n",
- x, y, tmpX, tmpY, priv->consWidth, priv->consHeight);
-
- if (priv->fine) dmxConsoleUpdateFineCursor(priv);
- if (tmpX != priv->curX || tmpY != priv->curY) {
- if (tmpX < 0) tmpX = 0;
- if (tmpY < 0) tmpY = 0;
- if (tmpX >= priv->consWidth) tmpX = priv->consWidth - 1;
- if (tmpY >= priv->consHeight) tmpY = priv->consHeight - 1;
- priv->curX = tmpX;
- priv->curY = tmpY;
- if (!priv->fine) {
- DMXDBG2(" WARP B %d %d\n", priv->curX, priv->curY);
- XWarpPointer(dpy, priv->window,
- priv->window, 0, 0, 0, 0, tmpX, tmpY);
- XSync(dpy, False); /* Not a backend display */
- }
- }
-
- if (dmxGeneration != serverGeneration) {
- dmxGeneration = serverGeneration;
- dmxConsoleDraw(priv, 1, 1);
- }
-}
-
-/** Collect all pending events from the console's display. Plase these
- * events on the server event queue using the \a motion and \a enqueue
- * routines. The \a checkspecial routine is used to check for special
- * keys that need handling. \a block tells if signals should be blocked
- * when updating the event queue. */
-void dmxConsoleCollectEvents(DevicePtr pDev,
- dmxMotionProcPtr motion,
- dmxEnqueueProcPtr enqueue,
- dmxCheckSpecialProcPtr checkspecial,
- DMXBlockType block)
-{
- GETPRIVFROMPDEV;
- GETDMXINPUTFROMPRIV;
- Display *dpy = priv->display;
- Window win = priv->window;
- int width = priv->width;
- int height = priv->height;
- XEvent X, N;
- XSetWindowAttributes attribs;
- static int rInitialized = 0;
- static Region r;
- XRectangle rect;
- static int raising = 0, raiseX, raiseY; /* FIXME */
-
- while (XPending(dpy)) {
- XNextEvent(dpy, &X);
- switch(X.type) {
- case VisibilityNotify:
- break;
- case Expose:
- DMXDBG5("dmxConsoleCollectEvents: Expose #%d %d %d %d %d\n",
- X.xexpose.count,
- X.xexpose.x, X.xexpose.y,
- X.xexpose.width, X.xexpose.height);
- if (!rInitialized++) r = XCreateRegion();
- rect.x = X.xexpose.x;
- rect.y = X.xexpose.y;
- rect.width = X.xexpose.width;
- rect.height = X.xexpose.height;
- XUnionRectWithRegion(&rect, r, r);
- if (X.xexpose.count == 0) {
- XSetRegion(dpy, priv->gc, r);
- XSetRegion(dpy, priv->gcDet, r);
- XSetRegion(dpy, priv->gcRev, r);
- dmxConsoleDraw(priv, 1, 1);
- XSetClipMask(dpy, priv->gc, None);
- XSetClipMask(dpy, priv->gcDet, None);
- XSetClipMask(dpy, priv->gcRev, None);
- XDestroyRegion(r);
- rInitialized = 0;
- }
- break;
- case ResizeRequest:
- DMXDBG2("dmxConsoleCollectEvents: Resize %d %d\n",
- X.xresizerequest.width, X.xresizerequest.height);
- priv->consWidth = X.xresizerequest.width;
- priv->consHeight = X.xresizerequest.height;
- priv->xScale = (double)priv->consWidth / width;
- priv->yScale = (double)priv->consHeight / height;
- attribs.override_redirect = True;
- XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &attribs);
- XResizeWindow(dpy, win, priv->consWidth, priv->consHeight);
- XFreePixmap(dpy, priv->pixmap);
- priv->pixmap = XCreatePixmap(dpy,
- RootWindow(dpy, DefaultScreen(dpy)),
- priv->consWidth,
- priv->consHeight,
- DefaultDepth(dpy,DefaultScreen(dpy)));
- dmxConsoleDraw(priv, 1, 1);
- attribs.override_redirect = False;
- XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &attribs);
- break;
- case LeaveNotify:
- DMXDBG4("dmxConsoleCollectEvents: Leave @ %d,%d; r=%d f=%d\n",
- X.xcrossing.x, X.xcrossing.y, raising, priv->fine);
- if (!priv->captured) dmxCommonRestoreState(priv);
- else {
- dmxConsoleUncapture(dmxInput);
- dmxCommonRestoreState(priv);
- }
- break;
- case EnterNotify:
- DMXDBG6("dmxConsoleCollectEvents: Enter %d,%d r=%d f=%d (%d,%d)\n",
- X.xcrossing.x, X.xcrossing.y, raising, priv->fine,
- priv->curX, priv->curY);
- dmxCommonSaveState(priv);
- if (raising) {
- raising = 0;
- dmxConsoleMoveAbsolute(priv, raiseX, raiseY,
- priv->mou, motion, block);
- } else {
- if (priv->fine) {
- /* The raise will generate an event near the center,
- * which is not where the cursor should be. So we
- * save the real position, do the raise, and move
- * the cursor here again after the raise generates
- * the event. */
- raising = 1;
- raiseX = X.xcrossing.x;
- raiseY = X.xcrossing.y;
- XRaiseWindow(dpy, priv->window);
- }
- XSync(dpy, False); /* Not a backend display */
- if (!X.xcrossing.x && !X.xcrossing.y)
- dmxConsoleMoveAbsolute(priv, priv->curX, priv->curY,
- priv->mou, motion, block);
- }
- break;
- case MotionNotify:
- if (priv->curX == X.xmotion.x && priv->curY == X.xmotion.y)
- continue;
- if (XPending(dpy)) { /* do motion compression */
- XPeekEvent(dpy, &N);
- if (N.type == MotionNotify) continue;
- }
- DMXDBG2("dmxConsoleCollectEvents: Motion %d %d\n",
- X.xmotion.x, X.xmotion.y);
- if (raising) {
- raising = 0;
- dmxConsoleMoveAbsolute(priv, raiseX, raiseY,
- priv->mou, motion, block);
- } else {
- if (priv->fine)
- dmxConsoleMoveRelative(priv, X.xmotion.x, X.xmotion.y,
- priv->mou, motion, block);
- else
- dmxConsoleMoveAbsolute(priv, X.xmotion.x, X.xmotion.y,
- priv->mou, motion, block);
- }
- break;
- case KeyPress:
- case KeyRelease:
- enqueue(priv->kbd, X.type, X.xkey.keycode, 0, NULL, block);
- break;
- default:
- /* Pass the whole event here, because
- * this may be an extension event. */
- enqueue(priv->mou, X.type, X.xbutton.button, 0, &X, block);
- break;
- }
- }
-}
-
-static void dmxCloseConsole(myPrivate *priv)
-{
- GETDMXINPUTFROMPRIV;
- dmxCommonRestoreState(priv);
- if (priv->display) {
- XFreeGC(priv->display, priv->gc);
- XFreeGC(priv->display, priv->gcDet);
- XFreeGC(priv->display, priv->gcRev);
- XFreeGC(priv->display, priv->gcCur);
- if (!dmxInput->console) XCloseDisplay(priv->display);
- }
- priv->display = NULL;
-}
-
-static Bool dmxCloseConsoleScreen(int idx, ScreenPtr pScreen)
-{
- myPrivate *priv, *last;
-
- for (last = priv = (myPrivate *)dixLookupPrivate(&pScreen->devPrivates,
- dmxScreenPrivateKey);
- priv;
- priv = priv->next) dmxCloseConsole(last = priv);
-
- DMX_UNWRAP(CloseScreen, last, pScreen);
- return pScreen->CloseScreen(idx, pScreen);
-}
-
-static Cursor dmxConsoleCreateEmptyCursor(myPrivate *priv)
-{
- char noCursorData[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- Pixmap pixmap;
- Cursor cursor;
- XColor color, tmpColor;
- Display *dpy = priv->display;
-
- /* Create empty cursor for window */
- pixmap = XCreateBitmapFromData(priv->display, priv->window,
- noCursorData, 8, 8);
- if (!XAllocNamedColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
- "black",
- &color,
- &tmpColor))
- dmxLog(dmxFatal, "Cannot allocate color for cursor\n");
- cursor = XCreatePixmapCursor(dpy, pixmap, pixmap, &color, &color, 0, 0);
- XFreePixmap(dpy, pixmap);
- return cursor;
-}
-
-static void dmxConsoleComputeWidthHeight(myPrivate *priv,
- int *width, int *height,
- double *xScale, double *yScale,
- int *consWidth, int *consHeight)
-{
- int screen;
- Display *dpy = priv->display;
-
- *width = 0;
- *height = 0;
- *xScale = 1.0;
- *yScale = 1.0;
-
- screen = DefaultScreen(dpy);
- *consWidth = DisplayWidth(dpy, screen) * CONSOLE_NUM / CONSOLE_DEN;
- *consHeight = DisplayHeight(dpy, screen) * CONSOLE_NUM / CONSOLE_DEN;
-
- if (*consWidth < 1) *consWidth = 1;
- if (*consHeight < 1) *consHeight = 1;
-
-#if 1
- /* Always keep the console size similar
- * to the global bounding box. */
- *width = dmxGlobalWidth;
- *height = dmxGlobalHeight;
-#else
- /* Make the console window as big as
- * possible by computing the visible
- * bounding box. */
- for (i = 0; i < dmxNumScreens; i++) {
- if (dixScreenOrigins[i].x+screenInfo.screens[i]->width > *width)
- *width = dixScreenOrigins[i].x+screenInfo.screens[i]->width;
-
- if (dixScreenOrigins[i].y+screenInfo.screens[i]->height > *height)
- *height = dixScreenOrigins[i].y+screenInfo.screens[i]->height;
- }
-#endif
-
- if ((double)*consWidth / *width < (double)*consHeight / *height)
- *xScale = *yScale = (double)*consWidth / *width;
- else
- *xScale = *yScale = (double)*consHeight / *height;
-
- *consWidth = scalex(priv, *width);
- *consHeight = scaley(priv, *height);
- if (*consWidth < 1) *consWidth = 1;
- if (*consHeight < 1) *consHeight = 1;
-}
-
-/** Re-initialized the console device described by \a pDev (after a
- * reconfig). */
-void dmxConsoleReInit(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- Display *dpy;
-
- if (!priv || !priv->initialized) return;
- dpy = priv->display;
-
- dmxConsoleComputeWidthHeight(priv,
- &priv->width, &priv->height,
- &priv->xScale, &priv->yScale,
- &priv->consWidth, &priv->consHeight);
- XResizeWindow(dpy, priv->window, priv->consWidth, priv->consHeight);
- XFreePixmap(dpy, priv->pixmap);
- priv->pixmap = XCreatePixmap(dpy,
- RootWindow(dpy, DefaultScreen(dpy)),
- priv->consWidth,
- priv->consHeight,
- DefaultDepth(dpy,DefaultScreen(dpy)));
- dmxConsoleDraw(priv, 1, 1);
-}
-
-/** Initialized the console device described by \a pDev. */
-void dmxConsoleInit(DevicePtr pDev)
-{
- GETPRIVFROMPDEV;
- DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
- int screen;
- unsigned long mask;
- XSetWindowAttributes attribs;
- Display *dpy;
- Window win;
- XGCValues gcvals;
- XColor color;
- XClassHint class_hints;
- unsigned long tmp;
-
- if (dmxLocal->type == DMX_LOCAL_MOUSE) priv->mou = pDev;
- if (dmxLocal->type == DMX_LOCAL_KEYBOARD) priv->kbd = pDev;
- if (priv->initialized++) return; /* Only do once for mouse/keyboard pair */
-
- if (!(dpy = priv->display = XOpenDisplay(dmxInput->name)))
- dmxLog(dmxFatal,
- "dmxOpenConsole: cannot open console display %s\n",
- dmxInput->name);
-
- /* Set up defaults */
- dmxConsoleComputeWidthHeight(priv,
- &priv->width, &priv->height,
- &priv->xScale, &priv->yScale,
- &priv->consWidth, &priv->consHeight);
-
- /* Private initialization using computed values or constants. */
- screen = DefaultScreen(dpy);
- priv->initPointerX = scalex(priv, priv->width / 2);
- priv->initPointerY = scaley(priv, priv->height / 2);
- priv->eventMask = (ButtonPressMask
- | ButtonReleaseMask
- | PointerMotionMask
- | EnterWindowMask
- | LeaveWindowMask
- | KeyPressMask
- | KeyReleaseMask
- | ExposureMask
- | ResizeRedirectMask);
-
- mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
- attribs.colormap = DefaultColormap(dpy, screen);
- if (XParseColor(dpy, attribs.colormap, CONSOLE_BG_COLOR, &color)
- && XAllocColor(dpy, attribs.colormap, &color)) {
- attribs.background_pixel = color.pixel;
- } else
- attribs.background_pixel = WhitePixel(dpy, screen);
-
- attribs.event_mask = priv->eventMask;
- attribs.override_redirect = False;
-
- win = priv->window = XCreateWindow(dpy,
- RootWindow(dpy, screen),
- 0, 0, priv->consWidth, priv->consHeight,
- 0,
- DefaultDepth(dpy, screen),
- InputOutput,
- DefaultVisual(dpy, screen),
- mask, &attribs);
- priv->pixmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
- priv->consWidth, priv->consHeight,
- DefaultDepth(dpy, screen));
-
- /* Set up properties */
- XStoreName(dpy, win, DMX_CONSOLE_NAME);
- class_hints.res_name = DMX_RES_NAME;
- class_hints.res_class = DMX_RES_CLASS;
- XSetClassHint(dpy, win, &class_hints);
-
-
- /* Map the window */
- XMapWindow(dpy, win);
-
- /* Create cursors */
- priv->cursorNormal = XCreateFontCursor(dpy, XC_circle);
- priv->cursorGrabbed = XCreateFontCursor(dpy, XC_spider);
- priv->cursorEmpty = dmxConsoleCreateEmptyCursor(priv);
- XDefineCursor(dpy, priv->window, priv->cursorNormal);
-
- /* Create GC */
- mask = (GCFunction | GCPlaneMask | GCClipMask | GCForeground |
- GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
- GCFillStyle | GCGraphicsExposures);
- gcvals.function = GXcopy;
- gcvals.plane_mask = AllPlanes;
- gcvals.clip_mask = None;
- if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_FG_COLOR, &color)
- && XAllocColor(dpy, attribs.colormap, &color)) {
- gcvals.foreground = color.pixel;
- } else
- gcvals.foreground = BlackPixel(dpy, screen);
- if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_BG_COLOR, &color)
- && XAllocColor(dpy, attribs.colormap, &color)) {
- gcvals.background = color.pixel;
- } else
- gcvals.background = WhitePixel(dpy, screen);
- gcvals.line_width = 0;
- gcvals.line_style = LineSolid;
- gcvals.cap_style = CapNotLast;
- gcvals.fill_style = FillSolid;
- gcvals.graphics_exposures = False;
-
- priv->gc = XCreateGC(dpy, win, mask, &gcvals);
-
- tmp = gcvals.foreground;
- if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_DET_COLOR, &color)
- && XAllocColor(dpy, attribs.colormap, &color)) {
- gcvals.foreground = color.pixel;
- } else
- gcvals.foreground = BlackPixel(dpy, screen);
- priv->gcDet = XCreateGC(dpy, win, mask, &gcvals);
- gcvals.foreground = tmp;
-
- tmp = gcvals.background;
- gcvals.background = gcvals.foreground;
- gcvals.foreground = tmp;
- priv->gcRev = XCreateGC(dpy, win, mask, &gcvals);
-
- gcvals.background = gcvals.foreground;
- if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_CUR_COLOR, &color)
- && XAllocColor(dpy, attribs.colormap, &color)) {
- gcvals.foreground = color.pixel;
- } else
- gcvals.foreground = BlackPixel(dpy, screen);
- priv->gcCur = XCreateGC(dpy, win, mask, &gcvals);
-
- dmxConsoleDraw(priv, 1, 1);
-
- if (dixLookupPrivate(&screenInfo.screens[0]->devPrivates,
- dmxScreenPrivateKey))
- priv->next = dixLookupPrivate(&screenInfo.screens[0]->devPrivates,
- dmxScreenPrivateKey);
- else
- DMX_WRAP(CloseScreen, dmxCloseConsoleScreen,
- priv, screenInfo.screens[0]);
- dixSetPrivate(&screenInfo.screens[0]->devPrivates, dmxScreenPrivateKey,
- priv);
-}
-
-/** Fill in the \a info structure for the specified \a pDev. Only used
- * for pointers. */
-void dmxConsoleMouGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- GETPRIVFROMPDEV;
-
- info->buttonClass = 1;
- dmxCommonMouGetMap(pDev, info->map, &info->numButtons);
- info->valuatorClass = 1;
- info->numRelAxes = 2;
- info->minval[0] = 0;
- info->minval[1] = 0;
- /* max possible console window size: */
- info->maxval[0] = DisplayWidth(priv->display, DefaultScreen(priv->display));
- info->maxval[1] = DisplayHeight(priv->display, DefaultScreen(priv->display));
- info->res[0] = 1;
- info->minres[0] = 0;
- info->maxres[0] = 1;
- info->ptrFeedbackClass = 1;
-}
-
-/** Fill in the \a info structure for the specified \a pDev. Only used
- * for keyboard. */
-void dmxConsoleKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- dmxCommonKbdGetInfo(pDev, info);
- info->keyboard = 1;
- info->keyClass = 1;
- dmxCommonKbdGetMap(pDev, &info->keySyms, info->modMap);
- info->freemap = 1;
- info->focusClass = 1;
- info->kbdFeedbackClass = 1;
-}
-
-/** Handle special console-only keys. */
-int dmxConsoleFunctions(pointer private, DMXFunctionType function)
-{
- GETONLYPRIVFROMPRIVATE;
- XRectangle rect;
- Display *dpy = priv->display;
-
- switch (function) {
- case DMX_FUNCTION_FINE:
- if (priv->fine) {
- priv->fine = 0;
- dmxConsoleClearCursor(priv, priv->globalX, priv->globalY, &rect);
- XSetClipRectangles(dpy, priv->gc, 0, 0, &rect, 1, Unsorted);
- XCopyArea(dpy, priv->pixmap, priv->window, priv->gc,
- 0, 0, priv->consWidth, priv->consHeight, 0, 0);
- XSetClipMask(dpy, priv->gc, None);
-
- XDefineCursor(dpy, priv->window,
- priv->grabbed
- ? priv->cursorGrabbed
- : priv->cursorNormal);
- XWarpPointer(dpy, priv->window, priv->window,
- 0, 0, 0, 0,
- scalex(priv, priv->globalX),
- scaley(priv, priv->globalY));
- XSync(dpy, False); /* Not a backend display */
- } else {
- priv->fine = 1;
- XRaiseWindow(dpy, priv->window);
- XDefineCursor(dpy, priv->window, priv->cursorEmpty);
- dmxConsoleUpdateFineCursor(priv);
- }
- return 1;
- case DMX_FUNCTION_GRAB:
- if (priv->grabbed) {
- XUngrabKeyboard(dpy, CurrentTime);
- XUngrabPointer(dpy, CurrentTime);
- XDefineCursor(dpy, priv->window,
- priv->fine
- ? priv->cursorEmpty
- : priv->cursorNormal);
- } else {
- if (XGrabPointer(dpy, priv->window, True,
- 0, GrabModeAsync, GrabModeAsync, priv->window,
- None, CurrentTime)) {
- dmxLog(dmxError, "XGrabPointer failed\n");
- return 0;
- }
- if (XGrabKeyboard(dpy, priv->window, True,
- GrabModeAsync, GrabModeAsync, CurrentTime)) {
- dmxLog(dmxError, "XGrabKeyboard failed\n");
- XUngrabPointer(dpy, CurrentTime);
- return 0;
- }
- XDefineCursor(dpy, priv->window,
- priv->fine
- ? priv->cursorEmpty
- : priv->cursorGrabbed);
- }
- priv->grabbed = !priv->grabbed;
- if (priv->fine) dmxConsoleUpdateFineCursor(priv);
- return 1;
- case DMX_FUNCTION_TERMINATE:
- return 1;
- default:
- return 0;
- }
-}
-
-static void dmxDump(void)
-{
- int i, j;
- DMXInputInfo *dmxInput;
- XEvent X;
-
- for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) {
- for (j = 0; j < dmxInput->numDevs; j++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
- myPrivate *priv = dmxLocal->private;
- while (priv
- && priv->display
- && XCheckTypedEvent(priv->display, MotionNotify, &X)) {
- DMXDBG4("dmxDump: %s/%d threw event away %d %s\n",
- dmxInput->name, j, X.type, dmxEventName(X.type));
- }
- }
- }
-}
-
-/** This routine is used to warp the pointer into the console window
- * from anywhere on the screen. It is used when backend and console
- * input are both being taken from the same X display. */
-void dmxConsoleCapture(DMXInputInfo *dmxInput)
-{
- int i;
- XEvent X;
-
- DMXDBG0("dmxConsoleCapture\n");
- dmxSync(NULL, TRUE);
- for (i = 0; i < dmxInput->numDevs; i++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
- myPrivate *priv = dmxLocal->private;
- if (dmxLocal->extType != DMX_LOCAL_TYPE_CONSOLE) continue;
- if (dmxLocal->type != DMX_LOCAL_MOUSE) continue;
- if (priv->captured) continue;
- priv->captured = 2; /* Ungrab only after proximal events. */
- XRaiseWindow(priv->display, priv->window);
- XSync(priv->display, False); /* Not a backend display */
- while (XCheckTypedEvent(priv->display, MotionNotify, &X)) {
- DMXDBG3(" Ignoring motion to %d %d after capture on %s\n",
- X.xmotion.x, X.xmotion.y, dmxInput->name);
- }
- XWarpPointer(priv->display, None,
- priv->window, 0, 0, 0, 0, priv->curX, priv->curY);
- XSync(priv->display, False); /* Not a backend display */
- dmxDump();
- if (priv->fine) dmxConsoleUpdateFineCursor(priv);
- }
-}
-
-/** Undo the capture that was done by #dmxConsoleCapture. */
-void dmxConsoleUncapture(DMXInputInfo *dmxInput)
-{
- int i;
-
- DMXDBG0("dmxConsoleUncapture\n");
- dmxSync(NULL, TRUE);
- for (i = 0; i < dmxInput->numDevs; i++) {
- DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
- myPrivate *priv = dmxLocal->private;
- if (dmxLocal->extType != DMX_LOCAL_TYPE_CONSOLE) continue;
- if (dmxLocal->type != DMX_LOCAL_MOUSE) continue;
- if (!priv->captured) continue;
- priv->captured = 0;
- XSync(priv->display, False); /* Not a backend display */
- }
-}
+/*
+ * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * David H. Dawes <dawes@xfree86.org>
+ * Kevin E. Martin <kem@redhat.com>
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ *
+ * This file implements the console input devices.
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#define DMX_CONSOLE_DEBUG 0
+#define DMX_WINDOW_DEBUG 0
+
+#include "dmxinputinit.h"
+#include "dmxevents.h"
+#include "dmxconsole.h"
+#include "dmxcommon.h"
+#include "dmxscrinit.h"
+#include "dmxcb.h"
+#include "dmxsync.h"
+
+#include "inputstr.h"
+#include "input.h"
+#include "mipointer.h"
+#include "windowstr.h"
+
+#define CONSOLE_NUM 3
+#define CONSOLE_DEN 4
+#define DMX_CONSOLE_NAME "DMX Console"
+#define DMX_RES_NAME "Xdmx"
+#define DMX_RES_CLASS "XDmx"
+#define CONSOLE_BG_COLOR "gray75"
+#define CONSOLE_FG_COLOR "black"
+#define CONSOLE_SCREEN_BG_COLOR "white"
+#define CONSOLE_SCREEN_FG_COLOR "black"
+#define CONSOLE_SCREEN_DET_COLOR "gray75"
+#define CONSOLE_SCREEN_CUR_COLOR "red"
+
+#if DMX_CONSOLE_DEBUG
+#define DMXDBG0(f) dmxLog(dmxDebug,f)
+#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
+#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
+#else
+#define DMXDBG0(f)
+#define DMXDBG1(f,a)
+#define DMXDBG2(f,a,b)
+#define DMXDBG3(f,a,b,c)
+#define DMXDBG4(f,a,b,c,d)
+#define DMXDBG5(f,a,b,c,d,e)
+#define DMXDBG6(f,a,b,c,d,e,g)
+#define DMXDBG7(f,a,b,c,d,e,g,h)
+#endif
+
+/* Private area for consoles. */
+typedef struct _myPrivate {
+ DMX_COMMON_PRIVATE;
+ int lastX;
+ int lastY;
+ int globalX;
+ int globalY;
+ int curX;
+ int curY;
+ int width;
+ int height;
+ int consWidth;
+ int consHeight;
+ double xScale;
+ double yScale;
+ XlibGC gc, gcDet, gcRev, gcCur;
+ int grabbed, fine, captured;
+ Cursor cursorNormal, cursorGrabbed, cursorEmpty;
+ Pixmap pixmap;
+
+ CloseScreenProcPtr CloseScreen;
+ struct _myPrivate *next; /* for closing multiple consoles */
+ int initialized;
+ DevicePtr mou, kbd;
+} myPrivate;
+
+static int scalex(myPrivate *priv, int x)
+{
+ return (int)((x * priv->xScale) + .5);
+}
+
+static int scaley(myPrivate *priv, int y)
+{
+ return (int)((y * priv->yScale) + .5);
+}
+
+static int unscalex(myPrivate *priv, int x)
+{
+ return (int)((x / priv->xScale) + .5);
+}
+
+static int unscaley(myPrivate *priv, int y)
+{
+ return (int)((y / priv->yScale) + .5);
+}
+
+/** Create the private area for \a pDevice. */
+pointer dmxConsoleCreatePrivate(DeviceIntPtr pDevice)
+{
+ GETDMXLOCALFROMPDEVICE;
+ myPrivate *priv = calloc(1, sizeof(*priv));
+ priv->dmxLocal = dmxLocal;
+ return priv;
+}
+
+/** If \a private is non-NULL, free its associated memory. */
+void dmxConsoleDestroyPrivate(pointer private)
+{
+ free(private);
+}
+
+static void dmxConsoleDrawFineCursor(myPrivate *priv, XRectangle *rect)
+{
+ int size = 6;
+ int x, y;
+
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ x = scalex(priv, priv->globalX) - size,
+ scaley(priv, priv->globalY),
+ scalex(priv, priv->globalX) + size,
+ scaley(priv, priv->globalY));
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ scalex(priv, priv->globalX),
+ y = scaley(priv, priv->globalY) - size,
+ scalex(priv, priv->globalX),
+ scaley(priv, priv->globalY) + size);
+ if (priv->grabbed) {
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ scalex(priv, priv->globalX) - (int)(size / 1.4),
+ scaley(priv, priv->globalY) - (int)(size / 1.4),
+ scalex(priv, priv->globalX) + (int)(size / 1.4),
+ scaley(priv, priv->globalY) + (int)(size / 1.4));
+ XDrawLine(priv->display, priv->pixmap, priv->gcCur,
+ scalex(priv, priv->globalX) - (int)(size / 1.4),
+ scaley(priv, priv->globalY) + (int)(size / 1.4),
+ scalex(priv, priv->globalX) + (int)(size / 1.4),
+ scaley(priv, priv->globalY) - (int)(size / 1.4));
+ }
+ if (rect) {
+ rect->x = x;
+ rect->y = y;
+ rect->width = 2 * size;
+ rect->height = 2 * size;
+ }
+}
+
+static void dmxConsoleDrawWindows(pointer private)
+{
+ GETONLYPRIVFROMPRIVATE;
+ Display *dpy = priv->display;
+ int i;
+ Region whole, used, avail;
+ XRectangle rect;
+
+ whole = XCreateRegion();
+ used = XCreateRegion();
+ avail = XCreateRegion();
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = priv->consWidth;
+ rect.height = priv->consHeight;
+ XUnionRectWithRegion(&rect, whole, whole);
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ WindowPtr pRoot = pScreen->root;
+ WindowPtr pChild;
+
+#if DMX_WINDOW_DEBUG
+ dmxLog(dmxDebug, "%lu %p %p %p 2\n",
+ pRoot->drawable.id,
+ pRoot->parent, pRoot->firstChild, pRoot->lastChild);
+#endif
+
+ for (pChild = pRoot->firstChild; pChild; pChild = pChild->nextSib) {
+ if (pChild->mapped
+ && pChild->realized) {
+#if DMX_WINDOW_DEBUG
+ dmxLog(dmxDebug, " %p %d,%d %dx%d %d %d %d RECTS\n",
+ pChild,
+ pChild->drawable.x,
+ pChild->drawable.y,
+ pChild->drawable.width,
+ pChild->drawable.height,
+ pChild->visibility,
+ pChild->overrideRedirect,
+ RegionNumRects(&pChild->clipList));
+#endif
+ rect.x = scalex(priv, pChild->drawable.x + pScreen->x);
+ rect.y = scaley(priv, pChild->drawable.y + pScreen->y);
+ rect.width = scalex(priv, pChild->drawable.width);
+ rect.height = scaley(priv, pChild->drawable.height);
+ XDrawRectangle(dpy, priv->pixmap, priv->gc,
+ rect.x, rect.y, rect.width, rect.height);
+ XUnionRectWithRegion(&rect, used, used);
+ XSubtractRegion(whole, used, avail);
+ XSetRegion(dpy, priv->gc, avail);
+ }
+ }
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) break; /* Screen 0 valid with Xinerama */
+#endif
+ }
+ XDestroyRegion(avail);
+ XDestroyRegion(used);
+ XDestroyRegion(whole);
+ XSetClipMask(dpy, priv->gc, None);
+}
+
+static void dmxConsoleDraw(myPrivate *priv, int updateCursor, int update)
+{
+ GETDMXINPUTFROMPRIV;
+ Display *dpy = priv->display;
+ int i;
+
+ XFillRectangle(dpy, priv->pixmap, priv->gc, 0, 0,
+ priv->consWidth, priv->consHeight);
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ XFillRectangle(dpy, priv->pixmap,
+ dmxScreen->beDisplay ? priv->gcRev : priv->gcDet,
+ scalex(priv, screenInfo.screens[i]->x),
+ scaley(priv, screenInfo.screens[i]->y),
+ scalex(priv, screenInfo.screens[i]->width),
+ scaley(priv, screenInfo.screens[i]->height));
+ }
+ for (i = 0; i < dmxNumScreens; i++) {
+ XDrawRectangle(dpy, priv->pixmap, priv->gc,
+ scalex(priv, screenInfo.screens[i]->x),
+ scaley(priv, screenInfo.screens[i]->y),
+ scalex(priv, screenInfo.screens[i]->width),
+ scaley(priv, screenInfo.screens[i]->height));
+ }
+ if (dmxInput->windows) dmxConsoleDrawWindows(priv);
+ if (priv->fine && updateCursor) dmxConsoleDrawFineCursor(priv, 0);
+ if (update) {
+ XCopyArea(priv->display, priv->pixmap, priv->window, priv->gc,
+ 0, 0, priv->consWidth, priv->consHeight, 0, 0);
+ XSync(priv->display, False); /* Not a backend display */
+ }
+}
+
+static void dmxConsoleClearCursor(myPrivate *priv, int x, int y,
+ XRectangle *rect)
+{
+ int cw = 14, ch = 14; /* Clear width and height */
+
+ rect->x = scalex(priv, x) - cw/2;
+ rect->y = scaley(priv, y) - ch/2;
+ rect->width = cw;
+ rect->height = ch;
+ XSetClipRectangles(priv->display, priv->gc, 0, 0, rect, 1, Unsorted);
+ XSetClipRectangles(priv->display, priv->gcDet, 0, 0, rect, 1, Unsorted);
+ XSetClipRectangles(priv->display, priv->gcRev, 0, 0, rect, 1, Unsorted);
+ dmxConsoleDraw(priv, 0, 0);
+ XSetClipMask(priv->display, priv->gc, None);
+ XSetClipMask(priv->display, priv->gcDet, None);
+ XSetClipMask(priv->display, priv->gcRev, None);
+}
+
+
+static void dmxConsoleUpdateFineCursor(myPrivate *priv)
+{
+ int leave = 0;
+ XRectangle rects[2];
+
+ dmxConsoleClearCursor(priv, priv->globalX, priv->globalY, &rects[0]);
+ if (priv->dmxLocal->sendsCore) {
+ dmxGetGlobalPosition(&priv->globalX, &priv->globalY);
+ } else {
+ priv->globalX = priv->dmxLocal->lastX;
+ priv->globalY = priv->dmxLocal->lastY;
+ }
+
+ priv->lastX = scalex(priv, priv->width / 2);
+ priv->lastY = scaley(priv, priv->height / 2);
+
+ /* Compute new warp position, which may be
+ outside the window */
+ if (priv->globalX < 1 || priv->globalX >= priv->width) {
+ if (priv->globalX < 1) priv->lastX = 0;
+ else priv->lastX = scalex(priv, priv->width);
+ priv->lastY = scaley(priv, priv->globalY);
+ ++leave;
+ }
+ if (priv->globalY < 1 || priv->globalY >= priv->height) {
+ if (priv->globalY < 1) priv->lastY = 0;
+ else priv->lastY = scaley(priv, priv->height);
+ priv->lastX = scalex(priv, priv->globalX);
+ ++leave;
+ }
+
+ /* Draw pseudo cursor in window */
+ dmxConsoleDrawFineCursor(priv, &rects[1]);
+
+ XSetClipRectangles(priv->display, priv->gc, 0, 0, rects, 2, Unsorted);
+ XCopyArea(priv->display, priv->pixmap, priv->window, priv->gc,
+ 0, 0, priv->consWidth, priv->consHeight, 0, 0);
+ XSetClipMask(priv->display, priv->gc, None);
+
+ DMXDBG2("dmxConsoleUpdateFineCursor: WARP %d %d\n",
+ priv->lastX, priv->lastY);
+ XWarpPointer(priv->display, priv->window, priv->window,
+ 0, 0, 0, 0, priv->lastX, priv->lastY);
+ XSync(priv->display, False); /* Not a backend display */
+
+ if (leave) {
+ XEvent X;
+ while (XCheckMaskEvent(priv->display, PointerMotionMask, &X)) {
+ if (X.type == MotionNotify) {
+ if (X.xmotion.x != priv->lastX || X.xmotion.y != priv->lastY) {
+ DMXDBG4("Ignoring motion to %d %d after leave frm %d %d\n",
+ X.xmotion.x, X.xmotion.y,
+ priv->lastX, priv->lastY);
+ }
+ } else {
+ dmxLog(dmxInfo, "Ignoring event (%d): %s ****************\n",
+ X.type, dmxEventName(X.type));
+ }
+ }
+ }
+ DMXDBG6("dmxConsoleUpdateFineCursor: Warp %d %d on %d %d [%d %d]\n",
+ priv->lastX, priv->lastY,
+ scalex(priv, priv->width),
+ scaley(priv, priv->height),
+ priv->globalX, priv->globalY);
+}
+
+/** Whenever the window layout (size, position, stacking order) might be
+ * changed, this routine is called with the \a pWindow that changed and
+ * the \a type of change. This routine is called in a conservative
+ * fashion: the actual layout of the windows of the screen might not
+ * have had any human-visible changes. */
+void dmxConsoleUpdateInfo(pointer private, DMXUpdateType type,
+ WindowPtr pWindow)
+{
+ GETONLYPRIVFROMPRIVATE;
+ dmxConsoleDraw(priv, 1, 1);
+}
+
+static void dmxConsoleMoveAbsolute(myPrivate *priv, int x, int y,
+ DevicePtr pDev, dmxMotionProcPtr motion,
+ DMXBlockType block)
+{
+ int tmpX, tmpY, v[2];
+
+ tmpX = unscalex(priv, x);
+ tmpY = unscalex(priv, y);
+ DMXDBG6("dmxConsoleMoveAbsolute(,%d,%d) %d %d =? %d %d\n",
+ x, y, tmpX, tmpY, priv->curX, priv->curY);
+ if (tmpX == priv->curX && tmpY == priv->curY) return;
+ v[0] = unscalex(priv, x);
+ v[1] = unscaley(priv, y);
+ motion(pDev, v, 0, 2, DMX_ABSOLUTE_CONFINED, block);
+ /* dmxConsoleUpdatePosition gets called here by dmxCoreMotion */
+}
+
+static void dmxConsoleMoveRelative(myPrivate *priv, int x, int y,
+ DevicePtr pDev, dmxMotionProcPtr motion,
+ DMXBlockType block)
+{
+ int v[2];
+ /* Ignore the event generated from * warping back to middle */
+ if (x == priv->lastX && y == priv->lastY) return;
+ v[0] = priv->lastX - x;
+ v[1] = priv->lastY - y;
+ motion(pDev, v, 0, 2, DMX_RELATIVE, block);
+ /* dmxConsoleUpdatePosition gets called here by dmxCoreMotion */
+}
+
+/** This routine gets called from #dmxCoreMotion for each motion. This
+ * allows the console's notion of the cursor postion to change when
+ * another input device actually caused the change. */
+void dmxConsoleUpdatePosition(pointer private, int x, int y)
+{
+ GETONLYPRIVFROMPRIVATE;
+ int tmpX, tmpY;
+ Display *dpy = priv->display;
+ static unsigned long dmxGeneration = 0;
+
+
+ tmpX = scalex(priv, x);
+ tmpY = scaley(priv, y);
+ DMXDBG6("dmxConsoleUpdatePosition(,%d,%d) new=%d,%d dims=%d,%d\n",
+ x, y, tmpX, tmpY, priv->consWidth, priv->consHeight);
+
+ if (priv->fine) dmxConsoleUpdateFineCursor(priv);
+ if (tmpX != priv->curX || tmpY != priv->curY) {
+ if (tmpX < 0) tmpX = 0;
+ if (tmpY < 0) tmpY = 0;
+ if (tmpX >= priv->consWidth) tmpX = priv->consWidth - 1;
+ if (tmpY >= priv->consHeight) tmpY = priv->consHeight - 1;
+ priv->curX = tmpX;
+ priv->curY = tmpY;
+ if (!priv->fine) {
+ DMXDBG2(" WARP B %d %d\n", priv->curX, priv->curY);
+ XWarpPointer(dpy, priv->window,
+ priv->window, 0, 0, 0, 0, tmpX, tmpY);
+ XSync(dpy, False); /* Not a backend display */
+ }
+ }
+
+ if (dmxGeneration != serverGeneration) {
+ dmxGeneration = serverGeneration;
+ dmxConsoleDraw(priv, 1, 1);
+ }
+}
+
+/** Collect all pending events from the console's display. Plase these
+ * events on the server event queue using the \a motion and \a enqueue
+ * routines. The \a checkspecial routine is used to check for special
+ * keys that need handling. \a block tells if signals should be blocked
+ * when updating the event queue. */
+void dmxConsoleCollectEvents(DevicePtr pDev,
+ dmxMotionProcPtr motion,
+ dmxEnqueueProcPtr enqueue,
+ dmxCheckSpecialProcPtr checkspecial,
+ DMXBlockType block)
+{
+ GETPRIVFROMPDEV;
+ GETDMXINPUTFROMPRIV;
+ Display *dpy = priv->display;
+ Window win = priv->window;
+ int width = priv->width;
+ int height = priv->height;
+ XEvent X, N;
+ XSetWindowAttributes attribs;
+ static int rInitialized = 0;
+ static Region r;
+ XRectangle rect;
+ static int raising = 0, raiseX, raiseY; /* FIXME */
+
+ while (XPending(dpy)) {
+ XNextEvent(dpy, &X);
+ switch(X.type) {
+ case VisibilityNotify:
+ break;
+ case Expose:
+ DMXDBG5("dmxConsoleCollectEvents: Expose #%d %d %d %d %d\n",
+ X.xexpose.count,
+ X.xexpose.x, X.xexpose.y,
+ X.xexpose.width, X.xexpose.height);
+ if (!rInitialized++) r = XCreateRegion();
+ rect.x = X.xexpose.x;
+ rect.y = X.xexpose.y;
+ rect.width = X.xexpose.width;
+ rect.height = X.xexpose.height;
+ XUnionRectWithRegion(&rect, r, r);
+ if (X.xexpose.count == 0) {
+ XSetRegion(dpy, priv->gc, r);
+ XSetRegion(dpy, priv->gcDet, r);
+ XSetRegion(dpy, priv->gcRev, r);
+ dmxConsoleDraw(priv, 1, 1);
+ XSetClipMask(dpy, priv->gc, None);
+ XSetClipMask(dpy, priv->gcDet, None);
+ XSetClipMask(dpy, priv->gcRev, None);
+ XDestroyRegion(r);
+ rInitialized = 0;
+ }
+ break;
+ case ResizeRequest:
+ DMXDBG2("dmxConsoleCollectEvents: Resize %d %d\n",
+ X.xresizerequest.width, X.xresizerequest.height);
+ priv->consWidth = X.xresizerequest.width;
+ priv->consHeight = X.xresizerequest.height;
+ priv->xScale = (double)priv->consWidth / width;
+ priv->yScale = (double)priv->consHeight / height;
+ attribs.override_redirect = True;
+ XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &attribs);
+ XResizeWindow(dpy, win, priv->consWidth, priv->consHeight);
+ XFreePixmap(dpy, priv->pixmap);
+ priv->pixmap = XCreatePixmap(dpy,
+ RootWindow(dpy, DefaultScreen(dpy)),
+ priv->consWidth,
+ priv->consHeight,
+ DefaultDepth(dpy,DefaultScreen(dpy)));
+ dmxConsoleDraw(priv, 1, 1);
+ attribs.override_redirect = False;
+ XChangeWindowAttributes(dpy, win, CWOverrideRedirect, &attribs);
+ break;
+ case LeaveNotify:
+ DMXDBG4("dmxConsoleCollectEvents: Leave @ %d,%d; r=%d f=%d\n",
+ X.xcrossing.x, X.xcrossing.y, raising, priv->fine);
+ if (!priv->captured) dmxCommonRestoreState(priv);
+ else {
+ dmxConsoleUncapture(dmxInput);
+ dmxCommonRestoreState(priv);
+ }
+ break;
+ case EnterNotify:
+ DMXDBG6("dmxConsoleCollectEvents: Enter %d,%d r=%d f=%d (%d,%d)\n",
+ X.xcrossing.x, X.xcrossing.y, raising, priv->fine,
+ priv->curX, priv->curY);
+ dmxCommonSaveState(priv);
+ if (raising) {
+ raising = 0;
+ dmxConsoleMoveAbsolute(priv, raiseX, raiseY,
+ priv->mou, motion, block);
+ } else {
+ if (priv->fine) {
+ /* The raise will generate an event near the center,
+ * which is not where the cursor should be. So we
+ * save the real position, do the raise, and move
+ * the cursor here again after the raise generates
+ * the event. */
+ raising = 1;
+ raiseX = X.xcrossing.x;
+ raiseY = X.xcrossing.y;
+ XRaiseWindow(dpy, priv->window);
+ }
+ XSync(dpy, False); /* Not a backend display */
+ if (!X.xcrossing.x && !X.xcrossing.y)
+ dmxConsoleMoveAbsolute(priv, priv->curX, priv->curY,
+ priv->mou, motion, block);
+ }
+ break;
+ case MotionNotify:
+ if (priv->curX == X.xmotion.x && priv->curY == X.xmotion.y)
+ continue;
+ if (XPending(dpy)) { /* do motion compression */
+ XPeekEvent(dpy, &N);
+ if (N.type == MotionNotify) continue;
+ }
+ DMXDBG2("dmxConsoleCollectEvents: Motion %d %d\n",
+ X.xmotion.x, X.xmotion.y);
+ if (raising) {
+ raising = 0;
+ dmxConsoleMoveAbsolute(priv, raiseX, raiseY,
+ priv->mou, motion, block);
+ } else {
+ if (priv->fine)
+ dmxConsoleMoveRelative(priv, X.xmotion.x, X.xmotion.y,
+ priv->mou, motion, block);
+ else
+ dmxConsoleMoveAbsolute(priv, X.xmotion.x, X.xmotion.y,
+ priv->mou, motion, block);
+ }
+ break;
+ case KeyPress:
+ case KeyRelease:
+ enqueue(priv->kbd, X.type, X.xkey.keycode, 0, NULL, block);
+ break;
+ default:
+ /* Pass the whole event here, because
+ * this may be an extension event. */
+ enqueue(priv->mou, X.type, X.xbutton.button, 0, &X, block);
+ break;
+ }
+ }
+}
+
+static void dmxCloseConsole(myPrivate *priv)
+{
+ GETDMXINPUTFROMPRIV;
+ dmxCommonRestoreState(priv);
+ if (priv->display) {
+ XFreeGC(priv->display, priv->gc);
+ XFreeGC(priv->display, priv->gcDet);
+ XFreeGC(priv->display, priv->gcRev);
+ XFreeGC(priv->display, priv->gcCur);
+ if (!dmxInput->console) XCloseDisplay(priv->display);
+ }
+ priv->display = NULL;
+}
+
+static Bool dmxCloseConsoleScreen(int idx, ScreenPtr pScreen)
+{
+ myPrivate *priv, *last;
+
+ for (last = priv = (myPrivate *)dixLookupPrivate(&pScreen->devPrivates,
+ dmxScreenPrivateKey);
+ priv;
+ priv = priv->next) dmxCloseConsole(last = priv);
+
+ DMX_UNWRAP(CloseScreen, last, pScreen);
+ return pScreen->CloseScreen(idx, pScreen);
+}
+
+static Cursor dmxConsoleCreateEmptyCursor(myPrivate *priv)
+{
+ char noCursorData[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ Pixmap pixmap;
+ Cursor cursor;
+ XColor color, tmpColor;
+ Display *dpy = priv->display;
+
+ /* Create empty cursor for window */
+ pixmap = XCreateBitmapFromData(priv->display, priv->window,
+ noCursorData, 8, 8);
+ if (!XAllocNamedColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
+ "black",
+ &color,
+ &tmpColor))
+ dmxLog(dmxFatal, "Cannot allocate color for cursor\n");
+ cursor = XCreatePixmapCursor(dpy, pixmap, pixmap, &color, &color, 0, 0);
+ XFreePixmap(dpy, pixmap);
+ return cursor;
+}
+
+static void dmxConsoleComputeWidthHeight(myPrivate *priv,
+ int *width, int *height,
+ double *xScale, double *yScale,
+ int *consWidth, int *consHeight)
+{
+ int screen;
+ Display *dpy = priv->display;
+
+ *width = 0;
+ *height = 0;
+ *xScale = 1.0;
+ *yScale = 1.0;
+
+ screen = DefaultScreen(dpy);
+ *consWidth = DisplayWidth(dpy, screen) * CONSOLE_NUM / CONSOLE_DEN;
+ *consHeight = DisplayHeight(dpy, screen) * CONSOLE_NUM / CONSOLE_DEN;
+
+ if (*consWidth < 1) *consWidth = 1;
+ if (*consHeight < 1) *consHeight = 1;
+
+#if 1
+ /* Always keep the console size similar
+ * to the global bounding box. */
+ *width = dmxGlobalWidth;
+ *height = dmxGlobalHeight;
+#else
+ /* Make the console window as big as
+ * possible by computing the visible
+ * bounding box. */
+ for (i = 0; i < dmxNumScreens; i++) {
+ if (screenInfo.screens[i]->x+screenInfo.screens[i]->width > *width)
+ *width = screenInfo.screens[i]->x+screenInfo.screens[i]->width;
+
+ if (screenInfo.screens[i]->y+screenInfo.screens[i]->height > *height)
+ *height = screenInfo.screens[i]->y+screenInfo.screens[i]->height;
+ }
+#endif
+
+ if ((double)*consWidth / *width < (double)*consHeight / *height)
+ *xScale = *yScale = (double)*consWidth / *width;
+ else
+ *xScale = *yScale = (double)*consHeight / *height;
+
+ *consWidth = scalex(priv, *width);
+ *consHeight = scaley(priv, *height);
+ if (*consWidth < 1) *consWidth = 1;
+ if (*consHeight < 1) *consHeight = 1;
+}
+
+/** Re-initialized the console device described by \a pDev (after a
+ * reconfig). */
+void dmxConsoleReInit(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ Display *dpy;
+
+ if (!priv || !priv->initialized) return;
+ dpy = priv->display;
+
+ dmxConsoleComputeWidthHeight(priv,
+ &priv->width, &priv->height,
+ &priv->xScale, &priv->yScale,
+ &priv->consWidth, &priv->consHeight);
+ XResizeWindow(dpy, priv->window, priv->consWidth, priv->consHeight);
+ XFreePixmap(dpy, priv->pixmap);
+ priv->pixmap = XCreatePixmap(dpy,
+ RootWindow(dpy, DefaultScreen(dpy)),
+ priv->consWidth,
+ priv->consHeight,
+ DefaultDepth(dpy,DefaultScreen(dpy)));
+ dmxConsoleDraw(priv, 1, 1);
+}
+
+/** Initialized the console device described by \a pDev. */
+void dmxConsoleInit(DevicePtr pDev)
+{
+ GETPRIVFROMPDEV;
+ DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx];
+ int screen;
+ unsigned long mask;
+ XSetWindowAttributes attribs;
+ Display *dpy;
+ Window win;
+ XGCValues gcvals;
+ XColor color;
+ XClassHint class_hints;
+ unsigned long tmp;
+
+ if (dmxLocal->type == DMX_LOCAL_MOUSE) priv->mou = pDev;
+ if (dmxLocal->type == DMX_LOCAL_KEYBOARD) priv->kbd = pDev;
+ if (priv->initialized++) return; /* Only do once for mouse/keyboard pair */
+
+ if (!(dpy = priv->display = XOpenDisplay(dmxInput->name)))
+ dmxLog(dmxFatal,
+ "dmxOpenConsole: cannot open console display %s\n",
+ dmxInput->name);
+
+ /* Set up defaults */
+ dmxConsoleComputeWidthHeight(priv,
+ &priv->width, &priv->height,
+ &priv->xScale, &priv->yScale,
+ &priv->consWidth, &priv->consHeight);
+
+ /* Private initialization using computed values or constants. */
+ screen = DefaultScreen(dpy);
+ priv->initPointerX = scalex(priv, priv->width / 2);
+ priv->initPointerY = scaley(priv, priv->height / 2);
+ priv->eventMask = (ButtonPressMask
+ | ButtonReleaseMask
+ | PointerMotionMask
+ | EnterWindowMask
+ | LeaveWindowMask
+ | KeyPressMask
+ | KeyReleaseMask
+ | ExposureMask
+ | ResizeRedirectMask);
+
+ mask = CWBackPixel | CWEventMask | CWColormap | CWOverrideRedirect;
+ attribs.colormap = DefaultColormap(dpy, screen);
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_BG_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ attribs.background_pixel = color.pixel;
+ } else
+ attribs.background_pixel = WhitePixel(dpy, screen);
+
+ attribs.event_mask = priv->eventMask;
+ attribs.override_redirect = False;
+
+ win = priv->window = XCreateWindow(dpy,
+ RootWindow(dpy, screen),
+ 0, 0, priv->consWidth, priv->consHeight,
+ 0,
+ DefaultDepth(dpy, screen),
+ InputOutput,
+ DefaultVisual(dpy, screen),
+ mask, &attribs);
+ priv->pixmap = XCreatePixmap(dpy, RootWindow(dpy, screen),
+ priv->consWidth, priv->consHeight,
+ DefaultDepth(dpy, screen));
+
+ /* Set up properties */
+ XStoreName(dpy, win, DMX_CONSOLE_NAME);
+ class_hints.res_name = DMX_RES_NAME;
+ class_hints.res_class = DMX_RES_CLASS;
+ XSetClassHint(dpy, win, &class_hints);
+
+
+ /* Map the window */
+ XMapWindow(dpy, win);
+
+ /* Create cursors */
+ priv->cursorNormal = XCreateFontCursor(dpy, XC_circle);
+ priv->cursorGrabbed = XCreateFontCursor(dpy, XC_spider);
+ priv->cursorEmpty = dmxConsoleCreateEmptyCursor(priv);
+ XDefineCursor(dpy, priv->window, priv->cursorNormal);
+
+ /* Create GC */
+ mask = (GCFunction | GCPlaneMask | GCClipMask | GCForeground |
+ GCBackground | GCLineWidth | GCLineStyle | GCCapStyle |
+ GCFillStyle | GCGraphicsExposures);
+ gcvals.function = GXcopy;
+ gcvals.plane_mask = AllPlanes;
+ gcvals.clip_mask = None;
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_FG_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.foreground = color.pixel;
+ } else
+ gcvals.foreground = BlackPixel(dpy, screen);
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_BG_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.background = color.pixel;
+ } else
+ gcvals.background = WhitePixel(dpy, screen);
+ gcvals.line_width = 0;
+ gcvals.line_style = LineSolid;
+ gcvals.cap_style = CapNotLast;
+ gcvals.fill_style = FillSolid;
+ gcvals.graphics_exposures = False;
+
+ priv->gc = XCreateGC(dpy, win, mask, &gcvals);
+
+ tmp = gcvals.foreground;
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_DET_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.foreground = color.pixel;
+ } else
+ gcvals.foreground = BlackPixel(dpy, screen);
+ priv->gcDet = XCreateGC(dpy, win, mask, &gcvals);
+ gcvals.foreground = tmp;
+
+ tmp = gcvals.background;
+ gcvals.background = gcvals.foreground;
+ gcvals.foreground = tmp;
+ priv->gcRev = XCreateGC(dpy, win, mask, &gcvals);
+
+ gcvals.background = gcvals.foreground;
+ if (XParseColor(dpy, attribs.colormap, CONSOLE_SCREEN_CUR_COLOR, &color)
+ && XAllocColor(dpy, attribs.colormap, &color)) {
+ gcvals.foreground = color.pixel;
+ } else
+ gcvals.foreground = BlackPixel(dpy, screen);
+ priv->gcCur = XCreateGC(dpy, win, mask, &gcvals);
+
+ dmxConsoleDraw(priv, 1, 1);
+
+ if (dixLookupPrivate(&screenInfo.screens[0]->devPrivates,
+ dmxScreenPrivateKey))
+ priv->next = dixLookupPrivate(&screenInfo.screens[0]->devPrivates,
+ dmxScreenPrivateKey);
+ else
+ DMX_WRAP(CloseScreen, dmxCloseConsoleScreen,
+ priv, screenInfo.screens[0]);
+ dixSetPrivate(&screenInfo.screens[0]->devPrivates, dmxScreenPrivateKey,
+ priv);
+}
+
+/** Fill in the \a info structure for the specified \a pDev. Only used
+ * for pointers. */
+void dmxConsoleMouGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ GETPRIVFROMPDEV;
+
+ info->buttonClass = 1;
+ dmxCommonMouGetMap(pDev, info->map, &info->numButtons);
+ info->valuatorClass = 1;
+ info->numRelAxes = 2;
+ info->minval[0] = 0;
+ info->minval[1] = 0;
+ /* max possible console window size: */
+ info->maxval[0] = DisplayWidth(priv->display, DefaultScreen(priv->display));
+ info->maxval[1] = DisplayHeight(priv->display, DefaultScreen(priv->display));
+ info->res[0] = 1;
+ info->minres[0] = 0;
+ info->maxres[0] = 1;
+ info->ptrFeedbackClass = 1;
+}
+
+/** Fill in the \a info structure for the specified \a pDev. Only used
+ * for keyboard. */
+void dmxConsoleKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ dmxCommonKbdGetInfo(pDev, info);
+ info->keyboard = 1;
+ info->keyClass = 1;
+ dmxCommonKbdGetMap(pDev, &info->keySyms, info->modMap);
+ info->freemap = 1;
+ info->focusClass = 1;
+ info->kbdFeedbackClass = 1;
+}
+
+/** Handle special console-only keys. */
+int dmxConsoleFunctions(pointer private, DMXFunctionType function)
+{
+ GETONLYPRIVFROMPRIVATE;
+ XRectangle rect;
+ Display *dpy = priv->display;
+
+ switch (function) {
+ case DMX_FUNCTION_FINE:
+ if (priv->fine) {
+ priv->fine = 0;
+ dmxConsoleClearCursor(priv, priv->globalX, priv->globalY, &rect);
+ XSetClipRectangles(dpy, priv->gc, 0, 0, &rect, 1, Unsorted);
+ XCopyArea(dpy, priv->pixmap, priv->window, priv->gc,
+ 0, 0, priv->consWidth, priv->consHeight, 0, 0);
+ XSetClipMask(dpy, priv->gc, None);
+
+ XDefineCursor(dpy, priv->window,
+ priv->grabbed
+ ? priv->cursorGrabbed
+ : priv->cursorNormal);
+ XWarpPointer(dpy, priv->window, priv->window,
+ 0, 0, 0, 0,
+ scalex(priv, priv->globalX),
+ scaley(priv, priv->globalY));
+ XSync(dpy, False); /* Not a backend display */
+ } else {
+ priv->fine = 1;
+ XRaiseWindow(dpy, priv->window);
+ XDefineCursor(dpy, priv->window, priv->cursorEmpty);
+ dmxConsoleUpdateFineCursor(priv);
+ }
+ return 1;
+ case DMX_FUNCTION_GRAB:
+ if (priv->grabbed) {
+ XUngrabKeyboard(dpy, CurrentTime);
+ XUngrabPointer(dpy, CurrentTime);
+ XDefineCursor(dpy, priv->window,
+ priv->fine
+ ? priv->cursorEmpty
+ : priv->cursorNormal);
+ } else {
+ if (XGrabPointer(dpy, priv->window, True,
+ 0, GrabModeAsync, GrabModeAsync, priv->window,
+ None, CurrentTime)) {
+ dmxLog(dmxError, "XGrabPointer failed\n");
+ return 0;
+ }
+ if (XGrabKeyboard(dpy, priv->window, True,
+ GrabModeAsync, GrabModeAsync, CurrentTime)) {
+ dmxLog(dmxError, "XGrabKeyboard failed\n");
+ XUngrabPointer(dpy, CurrentTime);
+ return 0;
+ }
+ XDefineCursor(dpy, priv->window,
+ priv->fine
+ ? priv->cursorEmpty
+ : priv->cursorGrabbed);
+ }
+ priv->grabbed = !priv->grabbed;
+ if (priv->fine) dmxConsoleUpdateFineCursor(priv);
+ return 1;
+ case DMX_FUNCTION_TERMINATE:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static void dmxDump(void)
+{
+ int i, j;
+ DMXInputInfo *dmxInput;
+ XEvent X;
+
+ for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) {
+ for (j = 0; j < dmxInput->numDevs; j++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j];
+ myPrivate *priv = dmxLocal->private;
+ while (priv
+ && priv->display
+ && XCheckTypedEvent(priv->display, MotionNotify, &X)) {
+ DMXDBG4("dmxDump: %s/%d threw event away %d %s\n",
+ dmxInput->name, j, X.type, dmxEventName(X.type));
+ }
+ }
+ }
+}
+
+/** This routine is used to warp the pointer into the console window
+ * from anywhere on the screen. It is used when backend and console
+ * input are both being taken from the same X display. */
+void dmxConsoleCapture(DMXInputInfo *dmxInput)
+{
+ int i;
+ XEvent X;
+
+ DMXDBG0("dmxConsoleCapture\n");
+ dmxSync(NULL, TRUE);
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ myPrivate *priv = dmxLocal->private;
+ if (dmxLocal->extType != DMX_LOCAL_TYPE_CONSOLE) continue;
+ if (dmxLocal->type != DMX_LOCAL_MOUSE) continue;
+ if (priv->captured) continue;
+ priv->captured = 2; /* Ungrab only after proximal events. */
+ XRaiseWindow(priv->display, priv->window);
+ XSync(priv->display, False); /* Not a backend display */
+ while (XCheckTypedEvent(priv->display, MotionNotify, &X)) {
+ DMXDBG3(" Ignoring motion to %d %d after capture on %s\n",
+ X.xmotion.x, X.xmotion.y, dmxInput->name);
+ }
+ XWarpPointer(priv->display, None,
+ priv->window, 0, 0, 0, 0, priv->curX, priv->curY);
+ XSync(priv->display, False); /* Not a backend display */
+ dmxDump();
+ if (priv->fine) dmxConsoleUpdateFineCursor(priv);
+ }
+}
+
+/** Undo the capture that was done by #dmxConsoleCapture. */
+void dmxConsoleUncapture(DMXInputInfo *dmxInput)
+{
+ int i;
+
+ DMXDBG0("dmxConsoleUncapture\n");
+ dmxSync(NULL, TRUE);
+ for (i = 0; i < dmxInput->numDevs; i++) {
+ DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i];
+ myPrivate *priv = dmxLocal->private;
+ if (dmxLocal->extType != DMX_LOCAL_TYPE_CONSOLE) continue;
+ if (dmxLocal->type != DMX_LOCAL_MOUSE) continue;
+ if (!priv->captured) continue;
+ priv->captured = 0;
+ XSync(priv->display, False); /* Not a backend display */
+ }
+}
diff --git a/xorg-server/hw/dmx/input/dmxinputinit.c b/xorg-server/hw/dmx/input/dmxinputinit.c
index c700a1246..2e062ef79 100644
--- a/xorg-server/hw/dmx/input/dmxinputinit.c
+++ b/xorg-server/hw/dmx/input/dmxinputinit.c
@@ -570,7 +570,7 @@ static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput,
int i;
#ifdef PANORAMIX
- if (!noPanoramiXExtension && pWindow && pWindow->parent != WindowTable[0])
+ if (!noPanoramiXExtension && pWindow && pWindow->parent != screenInfo.screens[0]->root)
return;
#endif
#if DMX_WINDOW_DEBUG
@@ -827,7 +827,7 @@ static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a)
}
}
-int dmxInputExtensionErrorHandler(Display *dsp, char *name, char *reason)
+int dmxInputExtensionErrorHandler(Display *dsp, _Xconst char *name, _Xconst char *reason)
{
return 0;
}
@@ -839,7 +839,7 @@ static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI)
Display *display;
int num;
int i, j;
- int (*handler)(Display *, char *, char *);
+ XextErrorHandler handler;
if (!(display = XOpenDisplay(dmxInput->name))) return;
@@ -1084,9 +1084,9 @@ static void dmxInputFreeLocal(DMXLocalInputInfoRec *local)
if (local->isCore && local->type == DMX_LOCAL_KEYBOARD)
dmxLocalCoreKeyboard = NULL;
if (local->destroy_private) local->destroy_private(local->private);
- if (local->history) free(local->history);
- if (local->valuators) free(local->valuators);
- if (local->deviceName) free(local->deviceName);
+ free(local->history);
+ free(local->valuators);
+ free(local->deviceName);
local->private = NULL;
local->history = NULL;
local->deviceName = NULL;
@@ -1100,9 +1100,9 @@ void dmxInputFree(DMXInputInfo *dmxInput)
if (!dmxInput) return;
- if (dmxInput->keycodes) free(dmxInput->keycodes);
- if (dmxInput->symbols) free(dmxInput->symbols);
- if (dmxInput->geometry) free(dmxInput->geometry);
+ free(dmxInput->keycodes);
+ free(dmxInput->symbols);
+ free(dmxInput->geometry);
for (i = 0; i < dmxInput->numDevs; i++) {
dmxInputFreeLocal(dmxInput->devs[i]);
diff --git a/xorg-server/hw/dmx/input/dmxinputinit.h b/xorg-server/hw/dmx/input/dmxinputinit.h
index 2e625cfd4..d23ad7a38 100644
--- a/xorg-server/hw/dmx/input/dmxinputinit.h
+++ b/xorg-server/hw/dmx/input/dmxinputinit.h
@@ -1,291 +1,291 @@
-/*
- * Copyright 2002 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- * Interface for low-level input support. \see dmxinputinit.c */
-
-#ifndef _DMXINPUTINIT_H_
-#define _DMXINPUTINIT_H_
-
-#include "dmx.h"
-#include "dmxinput.h"
-#include "dmxlog.h"
-
-
-#define DMX_LOCAL_DEFAULT_KEYBOARD "kbd"
-#define DMX_LOCAL_DEFAULT_POINTER "ps2"
-#define DMX_MAX_BUTTONS 256
-#define DMX_MOTION_SIZE 256
-#define DMX_MAX_VALUATORS 32
-#define DMX_MAX_AXES 32
-#define DMX_MAX_XINPUT_EVENT_TYPES 100
-#define DMX_MAP_ENTRIES 16 /* Must be a power of 2 */
-#define DMX_MAP_MASK (DMX_MAP_ENTRIES - 1)
-
-typedef enum {
- DMX_FUNCTION_GRAB,
- DMX_FUNCTION_TERMINATE,
- DMX_FUNCTION_FINE
-} DMXFunctionType;
-
-typedef enum {
- DMX_LOCAL_HIGHLEVEL,
- DMX_LOCAL_KEYBOARD,
- DMX_LOCAL_MOUSE,
- DMX_LOCAL_OTHER
-} DMXLocalInputType;
-
-typedef enum {
- DMX_LOCAL_TYPE_LOCAL,
- DMX_LOCAL_TYPE_CONSOLE,
- DMX_LOCAL_TYPE_BACKEND,
- DMX_LOCAL_TYPE_COMMON
-} DMXLocalInputExtType;
-
-typedef enum {
- DMX_RELATIVE,
- DMX_ABSOLUTE,
- DMX_ABSOLUTE_CONFINED
-} DMXMotionType;
-
-/** Stores information from low-level device that is used to initialize
- * the device at the dix level. */
-typedef struct _DMXLocalInitInfo {
- int keyboard; /**< Non-zero if the device is a keyboard */
-
- int keyClass; /**< Non-zero if keys are present */
- KeySymsRec keySyms; /**< Key symbols */
- int freemap; /**< If non-zero, free keySyms.map */
- CARD8 modMap[MAP_LENGTH]; /**< Modifier map */
- XkbDescPtr xkb; /**< XKB description */
- XkbComponentNamesRec names; /**< XKB component names */
- int freenames; /**< Non-zero if names should be free'd */
- int force; /**< Do not allow command line override */
-
- int buttonClass; /**< Non-zero if buttons are present */
- int numButtons; /**< Number of buttons */
- unsigned char map[DMX_MAX_BUTTONS]; /**< Button map */
-
- int valuatorClass; /**< Non-zero if valuators are
- * present */
- int numRelAxes; /**< Number of relative axes */
- int numAbsAxes; /**< Number of absolute axes */
- int minval[DMX_MAX_AXES]; /**< Minimum values */
- int maxval[DMX_MAX_AXES]; /**< Maximum values */
- int res[DMX_MAX_AXES]; /**< Resolution */
- int minres[DMX_MAX_AXES]; /**< Minimum resolutions */
- int maxres[DMX_MAX_AXES]; /**< Maximum resolutions */
-
- int focusClass; /**< Non-zero if device can
- * cause focus */
- int proximityClass; /**< Non-zero if device
- * causes proximity events */
- int kbdFeedbackClass; /**< Non-zero if device has
- * keyboard feedback */
- int ptrFeedbackClass; /**< Non-zero if device has
- * pointer feedback */
- int ledFeedbackClass; /**< Non-zero if device has
- * LED indicators */
- int belFeedbackClass; /**< Non-zero if device has a
- * bell */
- int intFeedbackClass; /**< Non-zero if device has
- * integer feedback */
- int strFeedbackClass; /**< Non-zero if device has
- * string feedback */
-
- int maxSymbols; /**< Maximum symbols */
- int maxSymbolsSupported; /**< Maximum symbols supported */
- KeySym *symbols; /**< Key symbols */
-} DMXLocalInitInfo, *DMXLocalInitInfoPtr;
-
-typedef pointer (*dmxCreatePrivateProcPtr)(DeviceIntPtr);
-typedef void (*dmxDestroyPrivateProcPtr)(pointer);
-
-typedef void (*dmxInitProcPtr)(DevicePtr);
-typedef void (*dmxReInitProcPtr)(DevicePtr);
-typedef void (*dmxLateReInitProcPtr)(DevicePtr);
-typedef void (*dmxGetInfoProcPtr)(DevicePtr, DMXLocalInitInfoPtr);
-typedef int (*dmxOnProcPtr)(DevicePtr);
-typedef void (*dmxOffProcPtr)(DevicePtr);
-typedef void (*dmxUpdatePositionProcPtr)(pointer, int x, int y);
-
-typedef void (*dmxVTPreSwitchProcPtr)(pointer); /* Turn I/O Off */
-typedef void (*dmxVTPostSwitchProcPtr)(pointer); /* Turn I/O On */
-typedef void (*dmxVTSwitchReturnProcPtr)(pointer);
-typedef int (*dmxVTSwitchProcPtr)(pointer, int vt,
- dmxVTSwitchReturnProcPtr, pointer);
-
-typedef void (*dmxMotionProcPtr)(DevicePtr,
- int *valuators,
- int firstAxis,
- int axesCount,
- DMXMotionType type,
- DMXBlockType block);
-typedef void (*dmxEnqueueProcPtr)(DevicePtr, int type, int detail,
- KeySym keySym, XEvent *e,
- DMXBlockType block);
-typedef int (*dmxCheckSpecialProcPtr)(DevicePtr, KeySym keySym);
-typedef void (*dmxCollectEventsProcPtr)(DevicePtr,
- dmxMotionProcPtr,
- dmxEnqueueProcPtr,
- dmxCheckSpecialProcPtr,
- DMXBlockType);
-typedef void (*dmxProcessInputProcPtr)(pointer);
-typedef void (*dmxUpdateInfoProcPtr)(pointer, DMXUpdateType, WindowPtr);
-typedef int (*dmxFunctionsProcPtr)(pointer, DMXFunctionType);
-
-typedef void (*dmxKBCtrlProcPtr)(DevicePtr, KeybdCtrl *ctrl);
-typedef void (*dmxMCtrlProcPtr)(DevicePtr, PtrCtrl *ctrl);
-typedef void (*dmxKBBellProcPtr)(DevicePtr, int percent,
- int volume, int pitch, int duration);
-
-/** Stores a mapping between the device id on the remote X server and
- * the id on the DMX server */
-typedef struct _DMXEventMap {
- int remote; /**< Event number on remote X server */
- int server; /**< Event number (unbiased) on DMX server */
-} DMXEventMap;
-
-/** This is the device-independent structure used by the low-level input
- * routines. The contents are not exposed to top-level .c files (except
- * dmxextensions.c). \see dmxinput.h \see dmxextensions.c */
-typedef struct _DMXLocalInputInfo {
- const char *name; /**< Device name */
- DMXLocalInputType type; /**< Device type */
- DMXLocalInputExtType extType; /**< Extended device type */
- int binding; /**< Count of how many consecutive
- * structs are bound to the same
- * device */
-
- /* Low-level (e.g., keyboard/mouse drivers) */
-
- dmxCreatePrivateProcPtr create_private; /**< Create
- * device-dependent
- * private */
- dmxDestroyPrivateProcPtr destroy_private; /**< Destroy
- * device-dependent
- * private */
- dmxInitProcPtr init; /**< Initialize device */
- dmxReInitProcPtr reinit; /**< Reinitialize device
- * (during a
- * reconfiguration) */
- dmxLateReInitProcPtr latereinit; /**< Reinitialize a device
- * (called very late
- * during a
- * reconfiguration) */
- dmxGetInfoProcPtr get_info; /**< Get device information */
- dmxOnProcPtr on; /**< Turn device on */
- dmxOffProcPtr off; /**< Turn device off */
- dmxUpdatePositionProcPtr update_position; /**< Called when another
- * device updates the
- * cursor position */
- dmxVTPreSwitchProcPtr vt_pre_switch; /**< Called before a VT switch */
- dmxVTPostSwitchProcPtr vt_post_switch; /**< Called after a VT switch */
- dmxVTSwitchProcPtr vt_switch; /**< Causes a VT switch */
-
- dmxCollectEventsProcPtr collect_events; /**< Collect and enqueue
- * events from the
- * device*/
- dmxProcessInputProcPtr process_input; /**< Process event (from
- * queue) */
- dmxFunctionsProcPtr functions;
- dmxUpdateInfoProcPtr update_info; /**< Update window layout
- * information */
-
- dmxMCtrlProcPtr mCtrl; /**< Pointer control */
- dmxKBCtrlProcPtr kCtrl; /**< Keyboard control */
- dmxKBBellProcPtr kBell; /**< Bell control */
-
- pointer private; /**< Device-dependent private */
- int isCore; /**< Is a DMX core device */
- int sendsCore; /**< Sends DMX core events */
- KeybdCtrl kctrl; /**< Keyboard control */
- PtrCtrl mctrl; /**< Pointer control */
-
- DeviceIntPtr pDevice; /**< X-level device */
- int inputIdx; /**< High-level index */
- int lastX, lastY; /**< Last known position;
- * for XInput in
- * dmxevents.c */
-
- int head; /**< XInput motion history
- * head */
- int tail; /**< XInput motion history
- * tail */
- unsigned long *history; /**< XInput motion history */
- int *valuators; /**< Cache of previous values */
-
- /* for XInput ChangePointerDevice */
- int (*savedMotionProc)(DeviceIntPtr,
- xTimecoord *,
- unsigned long,
- unsigned long,
- ScreenPtr);
- int savedMotionEvents; /**< Saved motion events */
- int savedSendsCore; /**< Saved sends-core flag */
-
- DMXEventMap map[DMX_MAP_ENTRIES]; /**< XInput device id map */
- int mapOptimize; /**< XInput device id
- * map
- * optimization */
-
- long deviceId; /**< device id on remote side,
- * if any */
- const char *deviceName; /**< devive name on remote
- * side, if any */
-} DMXLocalInputInfoRec;
-
-extern DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard;
-
-extern void dmxLocalInitInput(DMXInputInfo *dmxInput);
-extern DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput,
- DMXLocalInputInfoPtr s);
-
-extern void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl);
-extern void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl);
-extern void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice,
- pointer ctrl, int unknown);
-
-extern int dmxInputExtensionErrorHandler(Display *dsp, char *name,
- char *reason);
-
-extern int dmxInputDetach(DMXInputInfo *dmxInput);
-extern void dmxInputDetachAll(DMXScreenInfo *dmxScreen);
-extern int dmxInputDetachId(int id);
-extern DMXInputInfo *dmxInputLocateId(int id);
-extern int dmxInputAttachConsole(const char *name, int isCore,
- int *id);
-extern int dmxInputAttachBackend(int physicalScreen, int isCore,
- int *id);
-
-#endif
+/*
+ * Copyright 2002 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ * Interface for low-level input support. \see dmxinputinit.c */
+
+#ifndef _DMXINPUTINIT_H_
+#define _DMXINPUTINIT_H_
+
+#include "dmx.h"
+#include "dmxinput.h"
+#include "dmxlog.h"
+
+
+#define DMX_LOCAL_DEFAULT_KEYBOARD "kbd"
+#define DMX_LOCAL_DEFAULT_POINTER "ps2"
+#define DMX_MAX_BUTTONS 256
+#define DMX_MOTION_SIZE 256
+#define DMX_MAX_VALUATORS 32
+#define DMX_MAX_AXES 32
+#define DMX_MAX_XINPUT_EVENT_TYPES 100
+#define DMX_MAP_ENTRIES 16 /* Must be a power of 2 */
+#define DMX_MAP_MASK (DMX_MAP_ENTRIES - 1)
+
+typedef enum {
+ DMX_FUNCTION_GRAB,
+ DMX_FUNCTION_TERMINATE,
+ DMX_FUNCTION_FINE
+} DMXFunctionType;
+
+typedef enum {
+ DMX_LOCAL_HIGHLEVEL,
+ DMX_LOCAL_KEYBOARD,
+ DMX_LOCAL_MOUSE,
+ DMX_LOCAL_OTHER
+} DMXLocalInputType;
+
+typedef enum {
+ DMX_LOCAL_TYPE_LOCAL,
+ DMX_LOCAL_TYPE_CONSOLE,
+ DMX_LOCAL_TYPE_BACKEND,
+ DMX_LOCAL_TYPE_COMMON
+} DMXLocalInputExtType;
+
+typedef enum {
+ DMX_RELATIVE,
+ DMX_ABSOLUTE,
+ DMX_ABSOLUTE_CONFINED
+} DMXMotionType;
+
+/** Stores information from low-level device that is used to initialize
+ * the device at the dix level. */
+typedef struct _DMXLocalInitInfo {
+ int keyboard; /**< Non-zero if the device is a keyboard */
+
+ int keyClass; /**< Non-zero if keys are present */
+ KeySymsRec keySyms; /**< Key symbols */
+ int freemap; /**< If non-zero, free keySyms.map */
+ CARD8 modMap[MAP_LENGTH]; /**< Modifier map */
+ XkbDescPtr xkb; /**< XKB description */
+ XkbComponentNamesRec names; /**< XKB component names */
+ int freenames; /**< Non-zero if names should be free'd */
+ int force; /**< Do not allow command line override */
+
+ int buttonClass; /**< Non-zero if buttons are present */
+ int numButtons; /**< Number of buttons */
+ unsigned char map[DMX_MAX_BUTTONS]; /**< Button map */
+
+ int valuatorClass; /**< Non-zero if valuators are
+ * present */
+ int numRelAxes; /**< Number of relative axes */
+ int numAbsAxes; /**< Number of absolute axes */
+ int minval[DMX_MAX_AXES]; /**< Minimum values */
+ int maxval[DMX_MAX_AXES]; /**< Maximum values */
+ int res[DMX_MAX_AXES]; /**< Resolution */
+ int minres[DMX_MAX_AXES]; /**< Minimum resolutions */
+ int maxres[DMX_MAX_AXES]; /**< Maximum resolutions */
+
+ int focusClass; /**< Non-zero if device can
+ * cause focus */
+ int proximityClass; /**< Non-zero if device
+ * causes proximity events */
+ int kbdFeedbackClass; /**< Non-zero if device has
+ * keyboard feedback */
+ int ptrFeedbackClass; /**< Non-zero if device has
+ * pointer feedback */
+ int ledFeedbackClass; /**< Non-zero if device has
+ * LED indicators */
+ int belFeedbackClass; /**< Non-zero if device has a
+ * bell */
+ int intFeedbackClass; /**< Non-zero if device has
+ * integer feedback */
+ int strFeedbackClass; /**< Non-zero if device has
+ * string feedback */
+
+ int maxSymbols; /**< Maximum symbols */
+ int maxSymbolsSupported; /**< Maximum symbols supported */
+ KeySym *symbols; /**< Key symbols */
+} DMXLocalInitInfo, *DMXLocalInitInfoPtr;
+
+typedef pointer (*dmxCreatePrivateProcPtr)(DeviceIntPtr);
+typedef void (*dmxDestroyPrivateProcPtr)(pointer);
+
+typedef void (*dmxInitProcPtr)(DevicePtr);
+typedef void (*dmxReInitProcPtr)(DevicePtr);
+typedef void (*dmxLateReInitProcPtr)(DevicePtr);
+typedef void (*dmxGetInfoProcPtr)(DevicePtr, DMXLocalInitInfoPtr);
+typedef int (*dmxOnProcPtr)(DevicePtr);
+typedef void (*dmxOffProcPtr)(DevicePtr);
+typedef void (*dmxUpdatePositionProcPtr)(pointer, int x, int y);
+
+typedef void (*dmxVTPreSwitchProcPtr)(pointer); /* Turn I/O Off */
+typedef void (*dmxVTPostSwitchProcPtr)(pointer); /* Turn I/O On */
+typedef void (*dmxVTSwitchReturnProcPtr)(pointer);
+typedef int (*dmxVTSwitchProcPtr)(pointer, int vt,
+ dmxVTSwitchReturnProcPtr, pointer);
+
+typedef void (*dmxMotionProcPtr)(DevicePtr,
+ int *valuators,
+ int firstAxis,
+ int axesCount,
+ DMXMotionType type,
+ DMXBlockType block);
+typedef void (*dmxEnqueueProcPtr)(DevicePtr, int type, int detail,
+ KeySym keySym, XEvent *e,
+ DMXBlockType block);
+typedef int (*dmxCheckSpecialProcPtr)(DevicePtr, KeySym keySym);
+typedef void (*dmxCollectEventsProcPtr)(DevicePtr,
+ dmxMotionProcPtr,
+ dmxEnqueueProcPtr,
+ dmxCheckSpecialProcPtr,
+ DMXBlockType);
+typedef void (*dmxProcessInputProcPtr)(pointer);
+typedef void (*dmxUpdateInfoProcPtr)(pointer, DMXUpdateType, WindowPtr);
+typedef int (*dmxFunctionsProcPtr)(pointer, DMXFunctionType);
+
+typedef void (*dmxKBCtrlProcPtr)(DevicePtr, KeybdCtrl *ctrl);
+typedef void (*dmxMCtrlProcPtr)(DevicePtr, PtrCtrl *ctrl);
+typedef void (*dmxKBBellProcPtr)(DevicePtr, int percent,
+ int volume, int pitch, int duration);
+
+/** Stores a mapping between the device id on the remote X server and
+ * the id on the DMX server */
+typedef struct _DMXEventMap {
+ int remote; /**< Event number on remote X server */
+ int server; /**< Event number (unbiased) on DMX server */
+} DMXEventMap;
+
+/** This is the device-independent structure used by the low-level input
+ * routines. The contents are not exposed to top-level .c files (except
+ * dmxextensions.c). \see dmxinput.h \see dmxextensions.c */
+typedef struct _DMXLocalInputInfo {
+ const char *name; /**< Device name */
+ DMXLocalInputType type; /**< Device type */
+ DMXLocalInputExtType extType; /**< Extended device type */
+ int binding; /**< Count of how many consecutive
+ * structs are bound to the same
+ * device */
+
+ /* Low-level (e.g., keyboard/mouse drivers) */
+
+ dmxCreatePrivateProcPtr create_private; /**< Create
+ * device-dependent
+ * private */
+ dmxDestroyPrivateProcPtr destroy_private; /**< Destroy
+ * device-dependent
+ * private */
+ dmxInitProcPtr init; /**< Initialize device */
+ dmxReInitProcPtr reinit; /**< Reinitialize device
+ * (during a
+ * reconfiguration) */
+ dmxLateReInitProcPtr latereinit; /**< Reinitialize a device
+ * (called very late
+ * during a
+ * reconfiguration) */
+ dmxGetInfoProcPtr get_info; /**< Get device information */
+ dmxOnProcPtr on; /**< Turn device on */
+ dmxOffProcPtr off; /**< Turn device off */
+ dmxUpdatePositionProcPtr update_position; /**< Called when another
+ * device updates the
+ * cursor position */
+ dmxVTPreSwitchProcPtr vt_pre_switch; /**< Called before a VT switch */
+ dmxVTPostSwitchProcPtr vt_post_switch; /**< Called after a VT switch */
+ dmxVTSwitchProcPtr vt_switch; /**< Causes a VT switch */
+
+ dmxCollectEventsProcPtr collect_events; /**< Collect and enqueue
+ * events from the
+ * device*/
+ dmxProcessInputProcPtr process_input; /**< Process event (from
+ * queue) */
+ dmxFunctionsProcPtr functions;
+ dmxUpdateInfoProcPtr update_info; /**< Update window layout
+ * information */
+
+ dmxMCtrlProcPtr mCtrl; /**< Pointer control */
+ dmxKBCtrlProcPtr kCtrl; /**< Keyboard control */
+ dmxKBBellProcPtr kBell; /**< Bell control */
+
+ pointer private; /**< Device-dependent private */
+ int isCore; /**< Is a DMX core device */
+ int sendsCore; /**< Sends DMX core events */
+ KeybdCtrl kctrl; /**< Keyboard control */
+ PtrCtrl mctrl; /**< Pointer control */
+
+ DeviceIntPtr pDevice; /**< X-level device */
+ int inputIdx; /**< High-level index */
+ int lastX, lastY; /**< Last known position;
+ * for XInput in
+ * dmxevents.c */
+
+ int head; /**< XInput motion history
+ * head */
+ int tail; /**< XInput motion history
+ * tail */
+ unsigned long *history; /**< XInput motion history */
+ int *valuators; /**< Cache of previous values */
+
+ /* for XInput ChangePointerDevice */
+ int (*savedMotionProc)(DeviceIntPtr,
+ xTimecoord *,
+ unsigned long,
+ unsigned long,
+ ScreenPtr);
+ int savedMotionEvents; /**< Saved motion events */
+ int savedSendsCore; /**< Saved sends-core flag */
+
+ DMXEventMap map[DMX_MAP_ENTRIES]; /**< XInput device id map */
+ int mapOptimize; /**< XInput device id
+ * map
+ * optimization */
+
+ long deviceId; /**< device id on remote side,
+ * if any */
+ const char *deviceName; /**< devive name on remote
+ * side, if any */
+} DMXLocalInputInfoRec;
+
+extern DMXLocalInputInfoPtr dmxLocalCorePointer, dmxLocalCoreKeyboard;
+
+extern void dmxLocalInitInput(DMXInputInfo *dmxInput);
+extern DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput,
+ DMXLocalInputInfoPtr s);
+
+extern void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl);
+extern void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl);
+extern void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice,
+ pointer ctrl, int unknown);
+
+extern int dmxInputExtensionErrorHandler(Display *dsp, _Xconst char *name,
+ _Xconst char *reason);
+
+extern int dmxInputDetach(DMXInputInfo *dmxInput);
+extern void dmxInputDetachAll(DMXScreenInfo *dmxScreen);
+extern int dmxInputDetachId(int id);
+extern DMXInputInfo *dmxInputLocateId(int id);
+extern int dmxInputAttachConsole(const char *name, int isCore,
+ int *id);
+extern int dmxInputAttachBackend(int physicalScreen, int isCore,
+ int *id);
+
+#endif
diff --git a/xorg-server/hw/dmx/input/lnx-keyboard.c b/xorg-server/hw/dmx/input/lnx-keyboard.c
index 11f21e25c..269e84435 100644
--- a/xorg-server/hw/dmx/input/lnx-keyboard.c
+++ b/xorg-server/hw/dmx/input/lnx-keyboard.c
@@ -368,7 +368,7 @@ pointer kbdLinuxCreatePrivate(DeviceIntPtr pKeyboard)
/** Destroy a private structure. */
void kbdLinuxDestroyPrivate(pointer priv)
{
- if (priv) free(priv);
+ free(priv);
}
/** Ring the bell.
diff --git a/xorg-server/hw/dmx/input/lnx-ms.c b/xorg-server/hw/dmx/input/lnx-ms.c
index 549df46e2..e6d203c4b 100644
--- a/xorg-server/hw/dmx/input/lnx-ms.c
+++ b/xorg-server/hw/dmx/input/lnx-ms.c
@@ -1,321 +1,321 @@
-/* Portions of this file were derived from the following files:
- *
- **********************************************************************
- *
- * Xserver/hw/kdrive/linux/ms.c
- *
- * Copyright (c) 2001 by Juliusz Chroboczek
- * Copyright (c) 1999 by Keith Packard
- *
- * 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 AUTHORS OR COPYRIGHT HOLDERS
- * 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.
- *
- */
-
-/*
- * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- *
- * This code implements a low-level device driver for a serial MS mouse.
- * The code is derived from code by Juliusz Chroboczek and Keith Packard
- * (see the source code for complete references). */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "inputstr.h"
-#include <X11/Xos.h>
-#include <errno.h>
-#include <termios.h>
-
-/*****************************************************************************/
-/* Define some macros to make it easier to move this file to another
- * part of the Xserver tree. All calls to the dmx* layer are #defined
- * here for the .c file. The .h file will also have to be edited. */
-#include "dmxinputinit.h"
-#include "lnx-ms.h"
-
-#define GETPRIV myPrivate *priv \
- = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
-
-#define LOG0(f) dmxLog(dmxDebug,f)
-#define LOG1(f,a) dmxLog(dmxDebug,f,a)
-#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
-#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
-#define FATAL0(f) dmxLog(dmxFatal,f)
-#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
-#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
-#define MOTIONPROC dmxMotionProcPtr
-#define ENQUEUEPROC dmxEnqueueProcPtr
-#define CHECKPROC dmxCheckSpecialProcPtr
-#define BLOCK DMXBlockType
-
-/* End of interface definitions. */
-/*****************************************************************************/
-
-/* Private area for MS mouse devices. */
-typedef struct _myPrivate {
- DeviceIntPtr pMouse;
- int fd;
- struct termios tty;
- enum {
- button1 = 0x0001,
- button2 = 0x0002,
- button3 = 0x0004,
- button4 = 0x0008,
- button5 = 0x0010
- } buttons;
-} myPrivate;
-
-static int msLinuxReadBytes(int fd, unsigned char *buf, int len, int min)
-{
- int n, tot;
- fd_set set;
- struct timeval tv;
-
- tot = 0;
- while (len) {
- n = read(fd, buf, len);
- if (n > 0) {
- tot += n;
- buf += n;
- len -= n;
- }
- if (tot % min == 0) break;
- FD_ZERO(&set);
- FD_SET(fd, &set);
- tv.tv_sec = 0;
- tv.tv_usec = 100 * 1000;
- n = select(fd + 1, &set, 0, 0, &tv);
- if (n <= 0) break;
- }
- return tot;
-}
-
-static void msLinuxButton(DevicePtr pDev, ENQUEUEPROC enqueue, int buttons,
- BLOCK block)
-{
- GETPRIV;
-
-#define PRESS(b) \
- do { \
- enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
- } while (0)
-
-#define RELEASE(b) \
- do { \
- enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
- } while (0)
-
- if ((buttons & button1) && !(priv->buttons & button1)) PRESS(1);
- if (!(buttons & button1) && (priv->buttons & button1)) RELEASE(1);
-
- if ((buttons & button2) && !(priv->buttons & button2)) PRESS(2);
- if (!(buttons & button2) && (priv->buttons & button2)) RELEASE(2);
-
- if ((buttons & button3) && !(priv->buttons & button3)) PRESS(3);
- if (!(buttons & button3) && (priv->buttons & button3)) RELEASE(3);
-
- if ((buttons & button4) && !(priv->buttons & button4)) PRESS(4);
- if (!(buttons & button4) && (priv->buttons & button4)) RELEASE(4);
-
- if ((buttons & button5) && !(priv->buttons & button5)) PRESS(5);
- if (!(buttons & button5) && (priv->buttons & button5)) RELEASE(5);
-
- priv->buttons = buttons;
-}
-
-/** Read an event from the \a pDev device. If the event is a motion
- * event, enqueue it with the \a motion function. Otherwise, check for
- * special keys with the \a checkspecial function and enqueue the event
- * with the \a enqueue function. The \a block type is passed to the
- * functions so that they may block SIGIO handling as appropriate to the
- * caller of this function. */
-void msLinuxRead(DevicePtr pDev,
- MOTIONPROC motion,
- ENQUEUEPROC enqueue,
- CHECKPROC checkspecial,
- BLOCK block)
-{
- GETPRIV;
- unsigned char buf[3 * 200]; /* RATS: Use ok */
- unsigned char *b;
- int n;
- int dx, dy, v[2];
-
- while ((n = msLinuxReadBytes(priv->fd, buf, sizeof(buf), 3)) > 0) {
- b = buf;
- while (n >= 3) {
- dx = (char)(((b[0] & 0x03) << 6) | (b[1] & 0x3f));
- dy = (char)(((b[0] & 0x0c) << 4) | (b[2] & 0x3f));
- v[0] = -dx;
- v[1] = -dy;
-
- motion(pDev, v, 0, 2, 1, block);
- msLinuxButton(pDev, enqueue, (((b[0] & 0x10) ? button3 : 0)
- | ((b[0] & 0x20) ? button1 : 0)),
- block);
- n -= 3;
- b += 3;
- }
- }
-}
-
-/** Initialize \a pDev. */
-void msLinuxInit(DevicePtr pDev)
-{
- GETPRIV;
- const char *names[] = { "/dev/serialmouse", "/dev/mouse", NULL };
- int i;
-
- if (priv->fd >=0) return;
-
- for (i = 0; names[i]; i++) {
- if ((priv->fd = open(names[i], O_RDWR | O_NONBLOCK, 0)) >= 0) break;
- }
- if (priv->fd < 0)
- FATAL1("msLinuxInit: Cannot open mouse port (%s)\n",
- strerror(errno));
-
- if (!isatty(priv->fd))
- FATAL1("msLinuxInit: Mouse port %s is not a tty\n", names[i]);
-
- if (tcgetattr(priv->fd, &priv->tty) < 0)
- FATAL1("msLinuxInit: tcgetattr failed (%s)\n", strerror(errno));
-
- write(priv->fd, "*n", 2); /* 1200 baud */
- usleep(100000);
-}
-
-/** Turn \a pDev on (i.e., take input from \a pDev). */
-int msLinuxOn(DevicePtr pDev)
-{
- GETPRIV;
- struct termios nTty;
-
- if (priv->fd < 0) msLinuxInit(pDev);
-
- nTty = priv->tty;
- nTty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
- | IGNCR | ICRNL | IXON | IXOFF);
- nTty.c_oflag &= ~OPOST;
- nTty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- nTty.c_cflag &= ~(CSIZE | PARENB);
- nTty.c_cflag |= CS8 | CLOCAL | CSTOPB;
- nTty.c_cc[VTIME] = 0;
- nTty.c_cc[VMIN] = 1;
- cfsetispeed (&nTty, B1200);
- cfsetospeed (&nTty, B1200);
- if (tcsetattr(priv->fd, TCSANOW, &nTty) < 0)
- FATAL1("msLinuxInit: tcsetattr failed (%s)\n", strerror(errno));
- write(priv->fd, "*V", 2); /* 2 button 3 byte protocol */
- return priv->fd;
-}
-
-/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
-void msLinuxOff(DevicePtr pDev)
-{
- GETPRIV;
-
- tcsetattr(priv->fd, TCSANOW, &priv->tty);
- close(priv->fd);
- priv->fd = -1;
-}
-
-static void msLinuxGetMap(DevicePtr pDev, unsigned char *map, int *nButtons)
-{
- int i;
-
- if (nButtons) *nButtons = 3;
- if (map) for (i = 0; i <= *nButtons; i++) map[i] = i;
-}
-
-/** Currently unused hook called prior to an VT switch. */
-void msLinuxVTPreSwitch(pointer p)
-{
-}
-
-/** Currently unused hook called after returning from a VT switch. */
-void msLinuxVTPostSwitch(pointer p)
-{
-}
-
-/** Create a private structure for use within this file. */
-pointer msLinuxCreatePrivate(DeviceIntPtr pMouse)
-{
- myPrivate *priv = calloc(1, sizeof(*priv));
- priv->fd = -1;
- priv->pMouse = pMouse;
- return priv;
-}
-
-/** Destroy a private structure. */
-void msLinuxDestroyPrivate(pointer priv)
-{
- if (priv) free(priv);
-}
-
-/** Fill the \a info structure with information needed to initialize \a
- * pDev. */
-void msLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- info->buttonClass = 1;
- msLinuxGetMap(pDev, info->map, &info->numButtons);
- info->valuatorClass = 1;
- info->numRelAxes = 2;
- info->minval[0] = 0;
- info->maxval[0] = 0;
- info->res[0] = 1;
- info->minres[0] = 0;
- info->maxres[0] = 1;
- info->ptrFeedbackClass = 1;
-}
+/* Portions of this file were derived from the following files:
+ *
+ **********************************************************************
+ *
+ * Xserver/hw/kdrive/linux/ms.c
+ *
+ * Copyright (c) 2001 by Juliusz Chroboczek
+ * Copyright (c) 1999 by Keith Packard
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS
+ * 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.
+ *
+ */
+
+/*
+ * Copyright 2001-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ *
+ * This code implements a low-level device driver for a serial MS mouse.
+ * The code is derived from code by Juliusz Chroboczek and Keith Packard
+ * (see the source code for complete references). */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "inputstr.h"
+#include <X11/Xos.h>
+#include <errno.h>
+#include <termios.h>
+
+/*****************************************************************************/
+/* Define some macros to make it easier to move this file to another
+ * part of the Xserver tree. All calls to the dmx* layer are #defined
+ * here for the .c file. The .h file will also have to be edited. */
+#include "dmxinputinit.h"
+#include "lnx-ms.h"
+
+#define GETPRIV myPrivate *priv \
+ = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
+
+#define LOG0(f) dmxLog(dmxDebug,f)
+#define LOG1(f,a) dmxLog(dmxDebug,f,a)
+#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define FATAL0(f) dmxLog(dmxFatal,f)
+#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
+#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
+#define MOTIONPROC dmxMotionProcPtr
+#define ENQUEUEPROC dmxEnqueueProcPtr
+#define CHECKPROC dmxCheckSpecialProcPtr
+#define BLOCK DMXBlockType
+
+/* End of interface definitions. */
+/*****************************************************************************/
+
+/* Private area for MS mouse devices. */
+typedef struct _myPrivate {
+ DeviceIntPtr pMouse;
+ int fd;
+ struct termios tty;
+ enum {
+ button1 = 0x0001,
+ button2 = 0x0002,
+ button3 = 0x0004,
+ button4 = 0x0008,
+ button5 = 0x0010
+ } buttons;
+} myPrivate;
+
+static int msLinuxReadBytes(int fd, unsigned char *buf, int len, int min)
+{
+ int n, tot;
+ fd_set set;
+ struct timeval tv;
+
+ tot = 0;
+ while (len) {
+ n = read(fd, buf, len);
+ if (n > 0) {
+ tot += n;
+ buf += n;
+ len -= n;
+ }
+ if (tot % min == 0) break;
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ n = select(fd + 1, &set, 0, 0, &tv);
+ if (n <= 0) break;
+ }
+ return tot;
+}
+
+static void msLinuxButton(DevicePtr pDev, ENQUEUEPROC enqueue, int buttons,
+ BLOCK block)
+{
+ GETPRIV;
+
+#define PRESS(b) \
+ do { \
+ enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
+ } while (0)
+
+#define RELEASE(b) \
+ do { \
+ enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
+ } while (0)
+
+ if ((buttons & button1) && !(priv->buttons & button1)) PRESS(1);
+ if (!(buttons & button1) && (priv->buttons & button1)) RELEASE(1);
+
+ if ((buttons & button2) && !(priv->buttons & button2)) PRESS(2);
+ if (!(buttons & button2) && (priv->buttons & button2)) RELEASE(2);
+
+ if ((buttons & button3) && !(priv->buttons & button3)) PRESS(3);
+ if (!(buttons & button3) && (priv->buttons & button3)) RELEASE(3);
+
+ if ((buttons & button4) && !(priv->buttons & button4)) PRESS(4);
+ if (!(buttons & button4) && (priv->buttons & button4)) RELEASE(4);
+
+ if ((buttons & button5) && !(priv->buttons & button5)) PRESS(5);
+ if (!(buttons & button5) && (priv->buttons & button5)) RELEASE(5);
+
+ priv->buttons = buttons;
+}
+
+/** Read an event from the \a pDev device. If the event is a motion
+ * event, enqueue it with the \a motion function. Otherwise, check for
+ * special keys with the \a checkspecial function and enqueue the event
+ * with the \a enqueue function. The \a block type is passed to the
+ * functions so that they may block SIGIO handling as appropriate to the
+ * caller of this function. */
+void msLinuxRead(DevicePtr pDev,
+ MOTIONPROC motion,
+ ENQUEUEPROC enqueue,
+ CHECKPROC checkspecial,
+ BLOCK block)
+{
+ GETPRIV;
+ unsigned char buf[3 * 200]; /* RATS: Use ok */
+ unsigned char *b;
+ int n;
+ int dx, dy, v[2];
+
+ while ((n = msLinuxReadBytes(priv->fd, buf, sizeof(buf), 3)) > 0) {
+ b = buf;
+ while (n >= 3) {
+ dx = (char)(((b[0] & 0x03) << 6) | (b[1] & 0x3f));
+ dy = (char)(((b[0] & 0x0c) << 4) | (b[2] & 0x3f));
+ v[0] = -dx;
+ v[1] = -dy;
+
+ motion(pDev, v, 0, 2, 1, block);
+ msLinuxButton(pDev, enqueue, (((b[0] & 0x10) ? button3 : 0)
+ | ((b[0] & 0x20) ? button1 : 0)),
+ block);
+ n -= 3;
+ b += 3;
+ }
+ }
+}
+
+/** Initialize \a pDev. */
+void msLinuxInit(DevicePtr pDev)
+{
+ GETPRIV;
+ const char *names[] = { "/dev/serialmouse", "/dev/mouse", NULL };
+ int i;
+
+ if (priv->fd >=0) return;
+
+ for (i = 0; names[i]; i++) {
+ if ((priv->fd = open(names[i], O_RDWR | O_NONBLOCK, 0)) >= 0) break;
+ }
+ if (priv->fd < 0)
+ FATAL1("msLinuxInit: Cannot open mouse port (%s)\n",
+ strerror(errno));
+
+ if (!isatty(priv->fd))
+ FATAL1("msLinuxInit: Mouse port %s is not a tty\n", names[i]);
+
+ if (tcgetattr(priv->fd, &priv->tty) < 0)
+ FATAL1("msLinuxInit: tcgetattr failed (%s)\n", strerror(errno));
+
+ write(priv->fd, "*n", 2); /* 1200 baud */
+ usleep(100000);
+}
+
+/** Turn \a pDev on (i.e., take input from \a pDev). */
+int msLinuxOn(DevicePtr pDev)
+{
+ GETPRIV;
+ struct termios nTty;
+
+ if (priv->fd < 0) msLinuxInit(pDev);
+
+ nTty = priv->tty;
+ nTty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR
+ | IGNCR | ICRNL | IXON | IXOFF);
+ nTty.c_oflag &= ~OPOST;
+ nTty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
+ nTty.c_cflag &= ~(CSIZE | PARENB);
+ nTty.c_cflag |= CS8 | CLOCAL | CSTOPB;
+ nTty.c_cc[VTIME] = 0;
+ nTty.c_cc[VMIN] = 1;
+ cfsetispeed (&nTty, B1200);
+ cfsetospeed (&nTty, B1200);
+ if (tcsetattr(priv->fd, TCSANOW, &nTty) < 0)
+ FATAL1("msLinuxInit: tcsetattr failed (%s)\n", strerror(errno));
+ write(priv->fd, "*V", 2); /* 2 button 3 byte protocol */
+ return priv->fd;
+}
+
+/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
+void msLinuxOff(DevicePtr pDev)
+{
+ GETPRIV;
+
+ tcsetattr(priv->fd, TCSANOW, &priv->tty);
+ close(priv->fd);
+ priv->fd = -1;
+}
+
+static void msLinuxGetMap(DevicePtr pDev, unsigned char *map, int *nButtons)
+{
+ int i;
+
+ if (nButtons) *nButtons = 3;
+ if (map) for (i = 0; i <= *nButtons; i++) map[i] = i;
+}
+
+/** Currently unused hook called prior to an VT switch. */
+void msLinuxVTPreSwitch(pointer p)
+{
+}
+
+/** Currently unused hook called after returning from a VT switch. */
+void msLinuxVTPostSwitch(pointer p)
+{
+}
+
+/** Create a private structure for use within this file. */
+pointer msLinuxCreatePrivate(DeviceIntPtr pMouse)
+{
+ myPrivate *priv = calloc(1, sizeof(*priv));
+ priv->fd = -1;
+ priv->pMouse = pMouse;
+ return priv;
+}
+
+/** Destroy a private structure. */
+void msLinuxDestroyPrivate(pointer priv)
+{
+ free(priv);
+}
+
+/** Fill the \a info structure with information needed to initialize \a
+ * pDev. */
+void msLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ info->buttonClass = 1;
+ msLinuxGetMap(pDev, info->map, &info->numButtons);
+ info->valuatorClass = 1;
+ info->numRelAxes = 2;
+ info->minval[0] = 0;
+ info->maxval[0] = 0;
+ info->res[0] = 1;
+ info->minres[0] = 0;
+ info->maxres[0] = 1;
+ info->ptrFeedbackClass = 1;
+}
diff --git a/xorg-server/hw/dmx/input/lnx-ps2.c b/xorg-server/hw/dmx/input/lnx-ps2.c
index 70918eef4..f40441fe7 100644
--- a/xorg-server/hw/dmx/input/lnx-ps2.c
+++ b/xorg-server/hw/dmx/input/lnx-ps2.c
@@ -1,289 +1,289 @@
-/* Portions of this file were derived from the following files:
- *
- **********************************************************************
- *
- * Xserver/hw/kdrive/linux/ps2.c
- *
- * Copyright (c) 1999 by Keith Packard
- *
- * 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 Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD 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 2001,2003 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- *
- * This code implements a low-level device driver for a serial MS mouse.
- * The code is derived from code by Keith Packard (see the source code
- * for complete references). */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "inputstr.h"
-#include <X11/Xos.h>
-#include <errno.h>
-#include <termios.h>
-
-/*****************************************************************************/
-/* Define some macros to make it easier to move this file to another
- * part of the Xserver tree. All calls to the dmx* layer are #defined
- * here for the .c file. The .h file will also have to be edited. */
-#include "dmxinputinit.h"
-#include "lnx-ps2.h"
-
-#define GETPRIV myPrivate *priv \
- = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
-
-#define LOG0(f) dmxLog(dmxDebug,f)
-#define LOG1(f,a) dmxLog(dmxDebug,f,a)
-#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
-#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
-#define FATAL0(f) dmxLog(dmxFatal,f)
-#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
-#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
-#define MOTIONPROC dmxMotionProcPtr
-#define ENQUEUEPROC dmxEnqueueProcPtr
-#define CHECKPROC dmxCheckSpecialProcPtr
-#define BLOCK DMXBlockType
-
-/* End of interface definitions. */
-/*****************************************************************************/
-
-/* Private area for PS/2 devices. */
-typedef struct _myPrivate {
- DeviceIntPtr pMouse;
- int fd;
- enum {
- button1 = 0x0001,
- button2 = 0x0002,
- button3 = 0x0004,
- button4 = 0x0008,
- button5 = 0x0010
- } buttons;
-} myPrivate;
-
-static int ps2LinuxReadBytes(int fd, unsigned char *buf, int len, int min)
-{
- int n, tot;
- fd_set set;
- struct timeval tv;
-
- tot = 0;
- while (len) {
- n = read(fd, buf, len);
- if (n > 0) {
- tot += n;
- buf += n;
- len -= n;
- }
- if (tot % min == 0) break;
- FD_ZERO(&set);
- FD_SET(fd, &set);
- tv.tv_sec = 0;
- tv.tv_usec = 100 * 1000;
- n = select(fd + 1, &set, 0, 0, &tv);
- if (n <= 0) break;
- }
- return tot;
-}
-
-static void ps2LinuxButton(DevicePtr pDev, ENQUEUEPROC enqueue,
- int buttons, BLOCK block)
-{
- GETPRIV;
-
-#define PRESS(b) \
- do { \
- enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
- } while (0)
-
-#define RELEASE(b) \
- do { \
- enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
- } while (0)
-
- if ((buttons & button1) && !(priv->buttons & button1)) PRESS(1);
- if (!(buttons & button1) && (priv->buttons & button1)) RELEASE(1);
-
- if ((buttons & button2) && !(priv->buttons & button2)) PRESS(2);
- if (!(buttons & button2) && (priv->buttons & button2)) RELEASE(2);
-
- if ((buttons & button3) && !(priv->buttons & button3)) PRESS(3);
- if (!(buttons & button3) && (priv->buttons & button3)) RELEASE(3);
-
- if ((buttons & button4) && !(priv->buttons & button4)) PRESS(4);
- if (!(buttons & button4) && (priv->buttons & button4)) RELEASE(4);
-
- if ((buttons & button5) && !(priv->buttons & button5)) PRESS(5);
- if (!(buttons & button5) && (priv->buttons & button5)) RELEASE(5);
-
- priv->buttons = buttons;
-}
-
-/** Read an event from the \a pDev device. If the event is a motion
- * event, enqueue it with the \a motion function. Otherwise, check for
- * special keys with the \a checkspecial function and enqueue the event
- * with the \a enqueue function. The \a block type is passed to the
- * functions so that they may block SIGIO handling as appropriate to the
- * caller of this function. */
-void ps2LinuxRead(DevicePtr pDev, MOTIONPROC motion,
- ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block)
-{
- GETPRIV;
- unsigned char buf[3 * 200]; /* RATS: Use ok */
- unsigned char *b;
- int n;
- int dx, dy, v[2];
-
- while ((n = ps2LinuxReadBytes(priv->fd, buf, sizeof(buf), 3)) > 0) {
- b = buf;
- while (n >= 3) {
- dx = b[1] - ((b[0] & 0x10) ? 256 : 0);
- dy = -b[2] + ((b[0] & 0x20) ? 256 : 0);
- v[0] = -dx;
- v[1] = -dy;
-
- motion(pDev, v, 0, 2, 1, block);
- ps2LinuxButton(pDev, enqueue, (((b[0] & 4) ? button2 : 0)
- | ((b[0] & 2) ? button3 : 0)
- | ((b[0] & 1) ? button1 : 0)),
- block);
- n -= 3;
- b += 3;
- }
- }
-}
-
-/** Initialize \a pDev. */
-void ps2LinuxInit(DevicePtr pDev)
-{
- GETPRIV;
- const char *names[] = { "/dev/mouse", "/dev/psaux", NULL };
- int i;
-
- if (priv->fd >=0) return;
-
- for (i = 0; names[i]; i++) {
- if ((priv->fd = open(names[i], O_RDWR | O_NONBLOCK, 0)) >= 0) break;
- }
- if (priv->fd < 0)
- FATAL1("ps2LinuxInit: Cannot open mouse port (%s)\n",
- strerror(errno));
-}
-
-/** Turn \a pDev on (i.e., take input from \a pDev). */
-int ps2LinuxOn(DevicePtr pDev)
-{
- GETPRIV;
-
- if (priv->fd < 0) ps2LinuxInit(pDev);
- return priv->fd;
-}
-
-/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
-void ps2LinuxOff(DevicePtr pDev)
-{
- GETPRIV;
-
- close(priv->fd);
- priv->fd = -1;
-}
-
-static void ps2LinuxGetMap(DevicePtr pDev, unsigned char *map, int *nButtons)
-{
- int i;
-
- if (nButtons) *nButtons = 3;
- if (map) for (i = 0; i <= *nButtons; i++) map[i] = i;
-}
-
-/** Currently unused hook called prior to an VT switch. */
-void ps2LinuxVTPreSwitch(pointer p)
-{
-}
-
-/** Currently unused hook called after returning from a VT switch. */
-void ps2LinuxVTPostSwitch(pointer p)
-{
-}
-
-/** Create a private structure for use within this file. */
-pointer ps2LinuxCreatePrivate(DeviceIntPtr pMouse)
-{
- myPrivate *priv = calloc(1, sizeof(*priv));
- priv->fd = -1;
- priv->pMouse = pMouse;
- return priv;
-}
-
-/** Destroy a private structure. */
-void ps2LinuxDestroyPrivate(pointer priv)
-{
- if (priv) free(priv);
-}
-
-/** Fill the \a info structure with information needed to initialize \a
- * pDev. */
-void ps2LinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- info->buttonClass = 1;
- ps2LinuxGetMap(pDev, info->map, &info->numButtons);
- info->valuatorClass = 1;
- info->numRelAxes = 2;
- info->minval[0] = 0;
- info->maxval[0] = 0;
- info->res[0] = 1;
- info->minres[0] = 0;
- info->maxres[0] = 1;
- info->ptrFeedbackClass = 1;
-}
+/* Portions of this file were derived from the following files:
+ *
+ **********************************************************************
+ *
+ * Xserver/hw/kdrive/linux/ps2.c
+ *
+ * Copyright (c) 1999 by Keith Packard
+ *
+ * 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 Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 2001,2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ *
+ * This code implements a low-level device driver for a serial MS mouse.
+ * The code is derived from code by Keith Packard (see the source code
+ * for complete references). */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "inputstr.h"
+#include <X11/Xos.h>
+#include <errno.h>
+#include <termios.h>
+
+/*****************************************************************************/
+/* Define some macros to make it easier to move this file to another
+ * part of the Xserver tree. All calls to the dmx* layer are #defined
+ * here for the .c file. The .h file will also have to be edited. */
+#include "dmxinputinit.h"
+#include "lnx-ps2.h"
+
+#define GETPRIV myPrivate *priv \
+ = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
+
+#define LOG0(f) dmxLog(dmxDebug,f)
+#define LOG1(f,a) dmxLog(dmxDebug,f,a)
+#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define FATAL0(f) dmxLog(dmxFatal,f)
+#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
+#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
+#define MOTIONPROC dmxMotionProcPtr
+#define ENQUEUEPROC dmxEnqueueProcPtr
+#define CHECKPROC dmxCheckSpecialProcPtr
+#define BLOCK DMXBlockType
+
+/* End of interface definitions. */
+/*****************************************************************************/
+
+/* Private area for PS/2 devices. */
+typedef struct _myPrivate {
+ DeviceIntPtr pMouse;
+ int fd;
+ enum {
+ button1 = 0x0001,
+ button2 = 0x0002,
+ button3 = 0x0004,
+ button4 = 0x0008,
+ button5 = 0x0010
+ } buttons;
+} myPrivate;
+
+static int ps2LinuxReadBytes(int fd, unsigned char *buf, int len, int min)
+{
+ int n, tot;
+ fd_set set;
+ struct timeval tv;
+
+ tot = 0;
+ while (len) {
+ n = read(fd, buf, len);
+ if (n > 0) {
+ tot += n;
+ buf += n;
+ len -= n;
+ }
+ if (tot % min == 0) break;
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100 * 1000;
+ n = select(fd + 1, &set, 0, 0, &tv);
+ if (n <= 0) break;
+ }
+ return tot;
+}
+
+static void ps2LinuxButton(DevicePtr pDev, ENQUEUEPROC enqueue,
+ int buttons, BLOCK block)
+{
+ GETPRIV;
+
+#define PRESS(b) \
+ do { \
+ enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
+ } while (0)
+
+#define RELEASE(b) \
+ do { \
+ enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
+ } while (0)
+
+ if ((buttons & button1) && !(priv->buttons & button1)) PRESS(1);
+ if (!(buttons & button1) && (priv->buttons & button1)) RELEASE(1);
+
+ if ((buttons & button2) && !(priv->buttons & button2)) PRESS(2);
+ if (!(buttons & button2) && (priv->buttons & button2)) RELEASE(2);
+
+ if ((buttons & button3) && !(priv->buttons & button3)) PRESS(3);
+ if (!(buttons & button3) && (priv->buttons & button3)) RELEASE(3);
+
+ if ((buttons & button4) && !(priv->buttons & button4)) PRESS(4);
+ if (!(buttons & button4) && (priv->buttons & button4)) RELEASE(4);
+
+ if ((buttons & button5) && !(priv->buttons & button5)) PRESS(5);
+ if (!(buttons & button5) && (priv->buttons & button5)) RELEASE(5);
+
+ priv->buttons = buttons;
+}
+
+/** Read an event from the \a pDev device. If the event is a motion
+ * event, enqueue it with the \a motion function. Otherwise, check for
+ * special keys with the \a checkspecial function and enqueue the event
+ * with the \a enqueue function. The \a block type is passed to the
+ * functions so that they may block SIGIO handling as appropriate to the
+ * caller of this function. */
+void ps2LinuxRead(DevicePtr pDev, MOTIONPROC motion,
+ ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block)
+{
+ GETPRIV;
+ unsigned char buf[3 * 200]; /* RATS: Use ok */
+ unsigned char *b;
+ int n;
+ int dx, dy, v[2];
+
+ while ((n = ps2LinuxReadBytes(priv->fd, buf, sizeof(buf), 3)) > 0) {
+ b = buf;
+ while (n >= 3) {
+ dx = b[1] - ((b[0] & 0x10) ? 256 : 0);
+ dy = -b[2] + ((b[0] & 0x20) ? 256 : 0);
+ v[0] = -dx;
+ v[1] = -dy;
+
+ motion(pDev, v, 0, 2, 1, block);
+ ps2LinuxButton(pDev, enqueue, (((b[0] & 4) ? button2 : 0)
+ | ((b[0] & 2) ? button3 : 0)
+ | ((b[0] & 1) ? button1 : 0)),
+ block);
+ n -= 3;
+ b += 3;
+ }
+ }
+}
+
+/** Initialize \a pDev. */
+void ps2LinuxInit(DevicePtr pDev)
+{
+ GETPRIV;
+ const char *names[] = { "/dev/mouse", "/dev/psaux", NULL };
+ int i;
+
+ if (priv->fd >=0) return;
+
+ for (i = 0; names[i]; i++) {
+ if ((priv->fd = open(names[i], O_RDWR | O_NONBLOCK, 0)) >= 0) break;
+ }
+ if (priv->fd < 0)
+ FATAL1("ps2LinuxInit: Cannot open mouse port (%s)\n",
+ strerror(errno));
+}
+
+/** Turn \a pDev on (i.e., take input from \a pDev). */
+int ps2LinuxOn(DevicePtr pDev)
+{
+ GETPRIV;
+
+ if (priv->fd < 0) ps2LinuxInit(pDev);
+ return priv->fd;
+}
+
+/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
+void ps2LinuxOff(DevicePtr pDev)
+{
+ GETPRIV;
+
+ close(priv->fd);
+ priv->fd = -1;
+}
+
+static void ps2LinuxGetMap(DevicePtr pDev, unsigned char *map, int *nButtons)
+{
+ int i;
+
+ if (nButtons) *nButtons = 3;
+ if (map) for (i = 0; i <= *nButtons; i++) map[i] = i;
+}
+
+/** Currently unused hook called prior to an VT switch. */
+void ps2LinuxVTPreSwitch(pointer p)
+{
+}
+
+/** Currently unused hook called after returning from a VT switch. */
+void ps2LinuxVTPostSwitch(pointer p)
+{
+}
+
+/** Create a private structure for use within this file. */
+pointer ps2LinuxCreatePrivate(DeviceIntPtr pMouse)
+{
+ myPrivate *priv = calloc(1, sizeof(*priv));
+ priv->fd = -1;
+ priv->pMouse = pMouse;
+ return priv;
+}
+
+/** Destroy a private structure. */
+void ps2LinuxDestroyPrivate(pointer priv)
+{
+ free(priv);
+}
+
+/** Fill the \a info structure with information needed to initialize \a
+ * pDev. */
+void ps2LinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
+{
+ info->buttonClass = 1;
+ ps2LinuxGetMap(pDev, info->map, &info->numButtons);
+ info->valuatorClass = 1;
+ info->numRelAxes = 2;
+ info->minval[0] = 0;
+ info->maxval[0] = 0;
+ info->res[0] = 1;
+ info->minres[0] = 0;
+ info->maxres[0] = 1;
+ info->ptrFeedbackClass = 1;
+}
diff --git a/xorg-server/hw/dmx/input/usb-common.c b/xorg-server/hw/dmx/input/usb-common.c
index 95c00b839..c655a2984 100644
--- a/xorg-server/hw/dmx/input/usb-common.c
+++ b/xorg-server/hw/dmx/input/usb-common.c
@@ -1,381 +1,381 @@
-/*
- * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
- *
- * All Rights Reserved.
- *
- * 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 on 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 (including the
- * next paragraph) 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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.
- */
-
-/*
- * Authors:
- * Rickard E. (Rik) Faith <faith@redhat.com>
- *
- */
-
-/** \file
- *
- * Routines that are common between \a usb-keyboard.c, \a usb-mouse.c, and
- * \a usb-other.c */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "usb-private.h"
-
-#define USB_COMMON_DEBUG 1
-
-/*****************************************************************************/
-/* Define some macros to make it easier to move this file to another
- * part of the Xserver tree. All calls to the dmx* layer are #defined
- * here for the .c file. The .h file will also have to be edited. */
-#include "usb-mouse.h"
-
-#define GETPRIV myPrivate *priv \
- = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
-
-#define GETNAME ((DMXLocalInputInfoPtr)(pDevice->public.devicePrivate)) \
- ->name
-
-#define LOG0(f) dmxLog(dmxDebug,f)
-#define LOG1(f,a) dmxLog(dmxDebug,f,a)
-#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
-#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
-#define LOG1INPUT(p,f,a) dmxLogInput(p->dmxInput,f,a)
-#define LOG3INPUT(p,f,a,b,c) dmxLogInput(p->dmxInput,f,a,b,c)
-#define LOG5INPUT(p,f,a,b,c,d,e) dmxLogInput(p->dmxInput,f,a,b,c,d,e)
-#define FATAL0(f) dmxLog(dmxFatal,f)
-#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
-#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
-#define MOTIONPROC dmxMotionProcPtr
-#define ENQUEUEPROC dmxEnqueueProcPtr
-#define CHECKPROC dmxCheckSpecialProcPtr
-#define BLOCK DMXBlockType
-
-/* End of interface definitions. */
-/*****************************************************************************/
-
-
-/** Read an event from the \a pDev device. If the event is a motion
- * event, enqueue it with the \a motion function. Otherwise, enqueue
- * the event with the \a enqueue function. The \a block type is passed
- * to the functions so that they may block SIGIO handling as appropriate
- * to the caller of this function.
- *
- * Since USB devices return EV_KEY events for buttons and keys, \a
- * minButton is used to decide if a Button or Key event should be
- * queued.*/
-void usbRead(DevicePtr pDev,
- MOTIONPROC motion,
- ENQUEUEPROC enqueue,
- int minButton,
- BLOCK block)
-{
- GETPRIV;
- struct input_event raw;
- int v[DMX_MAX_AXES];
- int axis;
-
-#define PRESS(b) \
- do { \
- enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
- } while (0)
-
-#define RELEASE(b) \
- do { \
- enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
- } while (0)
-
- while (read(priv->fd, &raw, sizeof(raw)) > 0) {
-#if USB_COMMON_DEBUG > 1
- LOG3("USB: type = %d, code = 0x%02x, value = %d\n",
- raw.type, raw.code, raw.value);
-#endif
- switch (raw.type) {
- case EV_KEY:
- /* raw.value = 1 for first, 2 for repeat */
- if (raw.code > minButton) {
- if (raw.value) PRESS((raw.code & 0x0f) + 1);
- else RELEASE((raw.code & 0x0f) + 1);
- } else {
- enqueue(pDev, raw.value ? KeyPress : KeyRelease,
- 0, 0, NULL, block);
- }
- break;
- case EV_REL:
- switch (raw.code) {
- case REL_X:
- v[0] = -raw.value;
- v[1] = 0;
- motion(pDev, v, 0, 2, DMX_RELATIVE, block);
- break;
- case REL_Y:
- v[0] = 0;
- v[1] = -raw.value;
- motion(pDev, v, 0, 2, DMX_RELATIVE, block);
- break;
- case REL_WHEEL:
- if ((int)raw.value > 0) {
- PRESS(4);
- RELEASE(4);
- } else if ((int)raw.value < 0) {
- PRESS(5);
- RELEASE(5);
- }
- break;
- default:
- memset(v, 0, sizeof(v));
- axis = priv->relmap[raw.code];
- v[axis] = raw.value;
- motion(pDev, v, axis, 1, DMX_RELATIVE, block);
- }
- break;
- case EV_ABS:
- memset(v, 0, sizeof(v));
- axis = priv->absmap[raw.code];
- v[axis] = raw.value;
- motion(pDev, v, axis, 1, DMX_ABSOLUTE, block);
- break;
- }
- }
-}
-
-#define test_bit(bit) (priv->mask[(bit)/8] & (1 << ((bit)%8)))
-#define test_bits(bit) (bits[(bit)/8] & (1 << ((bit)%8)))
-
-static void usbPrint(myPrivate *priv,
- const char *filename, const char *devname, int fd)
-{
- int j, k;
- DeviceIntPtr pDevice = priv->pDevice;
- unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
- * KEY_MAX is greater than
- * REL_MAX, ABS_MAX, SND_MAX, and
- * LED_MAX. */
-
- LOG3INPUT(priv, "%s (%s) using %s\n", pDevice->name, GETNAME, filename);
- LOG1INPUT(priv, " %s\n", devname);
- for (j = 0; j < EV_MAX; j++) {
- if (test_bit(j)) {
- const char *type = "unknown";
- char extra[256]; /* FIXME: may cause buffer overflow */
- extra[0] = '\0';
- switch(j) {
- case EV_KEY: type = "keys/buttons"; break;
- case EV_REL: type = "relative";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
- for (k = 0; k < REL_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case REL_X: strcat(extra, " X"); break;
- case REL_Y: strcat(extra, " Y"); break;
- case REL_Z: strcat(extra, " Z"); break;
- case REL_HWHEEL: strcat(extra, " HWheel"); break;
- case REL_DIAL: strcat(extra, " Dial"); break;
- case REL_WHEEL: strcat(extra, " Wheel"); break;
- case REL_MISC: strcat(extra, " Misc"); break;
- }
- }
- break;
- case EV_ABS: type = "absolute";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
- for (k = 0; k < ABS_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case ABS_X: strcat(extra," X"); break;
- case ABS_Y: strcat(extra," Y"); break;
- case ABS_Z: strcat(extra," Z"); break;
- case ABS_RX: strcat(extra," RX"); break;
- case ABS_RY: strcat(extra," RY"); break;
- case ABS_RZ: strcat(extra," RZ"); break;
- case ABS_THROTTLE: strcat(extra," Throttle");break;
- case ABS_RUDDER: strcat(extra," Rudder"); break;
- case ABS_WHEEL: strcat(extra," Wheel"); break;
- case ABS_GAS: strcat(extra," Gas"); break;
- case ABS_BRAKE: strcat(extra," Break"); break;
- case ABS_HAT0X: strcat(extra," Hat0X"); break;
- case ABS_HAT0Y: strcat(extra," Hat0Y"); break;
- case ABS_HAT1X: strcat(extra," Hat1X"); break;
- case ABS_HAT1Y: strcat(extra," Hat1Y"); break;
- case ABS_HAT2X: strcat(extra," Hat2X"); break;
- case ABS_HAT2Y: strcat(extra," Hat2Y"); break;
- case ABS_HAT3X: strcat(extra," Hat3X"); break;
- case ABS_HAT3Y: strcat(extra," Hat3Y"); break;
- case ABS_PRESSURE: strcat(extra," Pressure");break;
- case ABS_DISTANCE: strcat(extra," Distance");break;
- case ABS_TILT_X: strcat(extra," TiltX"); break;
- case ABS_TILT_Y: strcat(extra," TiltY"); break;
- case ABS_MISC: strcat(extra," Misc"); break;
- }
- }
- break;
- case EV_MSC: type = "reserved"; break;
- case EV_LED: type = "leds";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
- for (k = 0; k < LED_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case LED_NUML: strcat(extra," NumLock"); break;
- case LED_CAPSL: strcat(extra," CapsLock"); break;
- case LED_SCROLLL: strcat(extra," ScrlLock"); break;
- case LED_COMPOSE: strcat(extra," Compose"); break;
- case LED_KANA: strcat(extra," Kana"); break;
- case LED_SLEEP: strcat(extra," Sleep"); break;
- case LED_SUSPEND: strcat(extra," Suspend"); break;
- case LED_MUTE: strcat(extra," Mute"); break;
- case LED_MISC: strcat(extra," Misc"); break;
- }
- }
- break;
- case EV_SND: type = "sound";
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_SND, sizeof(bits)), bits);
- for (k = 0; k < SND_MAX; k++) {
- if (test_bits(k)) switch (k) {
- case SND_CLICK: strcat(extra," Click"); break;
- case SND_BELL: strcat(extra," Bell"); break;
- }
- }
- break;
- case EV_REP: type = "repeat"; break;
- case EV_FF: type = "feedback"; break;
- }
- LOG5INPUT(priv, " Feature 0x%02x = %s%s%s%s\n", j, type,
- extra[0] ? " [" : "",
- extra[0] ? extra+1 : "",
- extra[0] ? "]" : "");
- }
- }
-}
-
-/** Initialized \a pDev as a \a usbMouse, \a usbKeyboard, or \a usbOther
-device. */
-void usbInit(DevicePtr pDev, usbType type)
-{
- GETPRIV;
- char name[64]; /* RATS: Only used in XmuSnprintf */
- int i, j, k;
- char buf[256] = { 0, }; /* RATS: Use ok */
- int version;
- unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
- * KEY_MAX is greater than
- * REL_MAX, ABS_MAX, SND_MAX, and
- * LED_MAX. */
-
- if (priv->fd >=0) return;
-
- for (i = 0; i < 32; i++) {
- XmuSnprintf(name, sizeof(name), "/dev/input/event%d", i);
- if ((priv->fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) {
- ioctl(priv->fd, EVIOCGVERSION, &version);
- ioctl(priv->fd, EVIOCGNAME(sizeof(buf)), buf);
- memset(priv->mask, 0, sizeof(priv->mask));
- ioctl(priv->fd, EVIOCGBIT(0, sizeof(priv->mask)), priv->mask);
-
- for (j = 0; j < EV_MAX; j++) {
- if (test_bit(j)) {
- switch(j) {
- case EV_REL:
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
- for (k = 0; k < REL_MAX; k++) {
- if (test_bits(k)) {
- if (k == REL_X) priv->relmap[k] = 0;
- else if (k == REL_Y) priv->relmap[k] = 1;
- else priv->relmap[k] = 2 + priv->numAbs;
- ++priv->numRel;
- }
- }
- break;
- case EV_ABS:
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
- for (k = 0; k < ABS_MAX; k++) {
- if (test_bits(k)) {
- priv->absmap[k] = priv->numAbs;
- ++priv->numAbs;
- }
- }
- break;
- case EV_LED:
- memset(bits, 0, sizeof(bits));
- ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
- for (k = 0; k < LED_MAX; k++) {
- if (test_bits(k)) ++priv->numLeds;
- }
- break;
- }
- }
- }
- switch (type) {
- case usbMouse:
- if (test_bit(EV_REL) && test_bit(EV_KEY))
- goto found;
- break;
- case usbKeyboard:
- if (test_bit(EV_KEY) && test_bit(EV_LED) && !test_bit(EV_ABS))
- goto found;
- break;
- case usbOther:
- if (!(test_bit(EV_REL) && test_bit(EV_KEY))
- && !(test_bit(EV_KEY) && test_bit(EV_LED)
- && !test_bit(EV_ABS)))
- goto found;
- break;
- }
- close(priv->fd);
- priv->fd = -1;
- }
- }
- if (priv->fd < 0)
- FATAL1("usbInit: Cannot open /dev/input/event* port (%s)\n"
- " If you have not done so, you may need to:\n"
- " rmmod mousedev; rmmod keybdev\n"
- " modprobe evdev\n",
- strerror(errno));
- found:
- usbPrint(priv, name, buf, priv->fd);
-}
-
-/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
-void usbOff(DevicePtr pDev)
-{
- GETPRIV;
-
- if (priv->fd >= 0) close(priv->fd);
- priv->fd = -1;
-}
-
-/** Create a private structure for use within this file. */
-pointer usbCreatePrivate(DeviceIntPtr pDevice)
-{
- myPrivate *priv = calloc(1, sizeof(*priv));
- priv->fd = -1;
- priv->pDevice = pDevice;
- return priv;
-}
-
-/** Destroy a private structure. */
-void usbDestroyPrivate(pointer priv)
-{
- if (priv) free(priv);
-}
+/*
+ * Copyright 2002-2003 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Rickard E. (Rik) Faith <faith@redhat.com>
+ *
+ */
+
+/** \file
+ *
+ * Routines that are common between \a usb-keyboard.c, \a usb-mouse.c, and
+ * \a usb-other.c */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "usb-private.h"
+
+#define USB_COMMON_DEBUG 1
+
+/*****************************************************************************/
+/* Define some macros to make it easier to move this file to another
+ * part of the Xserver tree. All calls to the dmx* layer are #defined
+ * here for the .c file. The .h file will also have to be edited. */
+#include "usb-mouse.h"
+
+#define GETPRIV myPrivate *priv \
+ = ((DMXLocalInputInfoPtr)(pDev->devicePrivate))->private
+
+#define GETNAME ((DMXLocalInputInfoPtr)(pDevice->public.devicePrivate)) \
+ ->name
+
+#define LOG0(f) dmxLog(dmxDebug,f)
+#define LOG1(f,a) dmxLog(dmxDebug,f,a)
+#define LOG2(f,a,b) dmxLog(dmxDebug,f,a,b)
+#define LOG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
+#define LOG1INPUT(p,f,a) dmxLogInput(p->dmxInput,f,a)
+#define LOG3INPUT(p,f,a,b,c) dmxLogInput(p->dmxInput,f,a,b,c)
+#define LOG5INPUT(p,f,a,b,c,d,e) dmxLogInput(p->dmxInput,f,a,b,c,d,e)
+#define FATAL0(f) dmxLog(dmxFatal,f)
+#define FATAL1(f,a) dmxLog(dmxFatal,f,a)
+#define FATAL2(f,a,b) dmxLog(dmxFatal,f,a,b)
+#define MOTIONPROC dmxMotionProcPtr
+#define ENQUEUEPROC dmxEnqueueProcPtr
+#define CHECKPROC dmxCheckSpecialProcPtr
+#define BLOCK DMXBlockType
+
+/* End of interface definitions. */
+/*****************************************************************************/
+
+
+/** Read an event from the \a pDev device. If the event is a motion
+ * event, enqueue it with the \a motion function. Otherwise, enqueue
+ * the event with the \a enqueue function. The \a block type is passed
+ * to the functions so that they may block SIGIO handling as appropriate
+ * to the caller of this function.
+ *
+ * Since USB devices return EV_KEY events for buttons and keys, \a
+ * minButton is used to decide if a Button or Key event should be
+ * queued.*/
+void usbRead(DevicePtr pDev,
+ MOTIONPROC motion,
+ ENQUEUEPROC enqueue,
+ int minButton,
+ BLOCK block)
+{
+ GETPRIV;
+ struct input_event raw;
+ int v[DMX_MAX_AXES];
+ int axis;
+
+#define PRESS(b) \
+ do { \
+ enqueue(pDev, ButtonPress, 0, 0, NULL, block); \
+ } while (0)
+
+#define RELEASE(b) \
+ do { \
+ enqueue(pDev, ButtonRelease, 0, 0, NULL, block); \
+ } while (0)
+
+ while (read(priv->fd, &raw, sizeof(raw)) > 0) {
+#if USB_COMMON_DEBUG > 1
+ LOG3("USB: type = %d, code = 0x%02x, value = %d\n",
+ raw.type, raw.code, raw.value);
+#endif
+ switch (raw.type) {
+ case EV_KEY:
+ /* raw.value = 1 for first, 2 for repeat */
+ if (raw.code > minButton) {
+ if (raw.value) PRESS((raw.code & 0x0f) + 1);
+ else RELEASE((raw.code & 0x0f) + 1);
+ } else {
+ enqueue(pDev, raw.value ? KeyPress : KeyRelease,
+ 0, 0, NULL, block);
+ }
+ break;
+ case EV_REL:
+ switch (raw.code) {
+ case REL_X:
+ v[0] = -raw.value;
+ v[1] = 0;
+ motion(pDev, v, 0, 2, DMX_RELATIVE, block);
+ break;
+ case REL_Y:
+ v[0] = 0;
+ v[1] = -raw.value;
+ motion(pDev, v, 0, 2, DMX_RELATIVE, block);
+ break;
+ case REL_WHEEL:
+ if ((int)raw.value > 0) {
+ PRESS(4);
+ RELEASE(4);
+ } else if ((int)raw.value < 0) {
+ PRESS(5);
+ RELEASE(5);
+ }
+ break;
+ default:
+ memset(v, 0, sizeof(v));
+ axis = priv->relmap[raw.code];
+ v[axis] = raw.value;
+ motion(pDev, v, axis, 1, DMX_RELATIVE, block);
+ }
+ break;
+ case EV_ABS:
+ memset(v, 0, sizeof(v));
+ axis = priv->absmap[raw.code];
+ v[axis] = raw.value;
+ motion(pDev, v, axis, 1, DMX_ABSOLUTE, block);
+ break;
+ }
+ }
+}
+
+#define test_bit(bit) (priv->mask[(bit)/8] & (1 << ((bit)%8)))
+#define test_bits(bit) (bits[(bit)/8] & (1 << ((bit)%8)))
+
+static void usbPrint(myPrivate *priv,
+ const char *filename, const char *devname, int fd)
+{
+ int j, k;
+ DeviceIntPtr pDevice = priv->pDevice;
+ unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
+ * KEY_MAX is greater than
+ * REL_MAX, ABS_MAX, SND_MAX, and
+ * LED_MAX. */
+
+ LOG3INPUT(priv, "%s (%s) using %s\n", pDevice->name, GETNAME, filename);
+ LOG1INPUT(priv, " %s\n", devname);
+ for (j = 0; j < EV_MAX; j++) {
+ if (test_bit(j)) {
+ const char *type = "unknown";
+ char extra[256]; /* FIXME: may cause buffer overflow */
+ extra[0] = '\0';
+ switch(j) {
+ case EV_KEY: type = "keys/buttons"; break;
+ case EV_REL: type = "relative";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
+ for (k = 0; k < REL_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case REL_X: strcat(extra, " X"); break;
+ case REL_Y: strcat(extra, " Y"); break;
+ case REL_Z: strcat(extra, " Z"); break;
+ case REL_HWHEEL: strcat(extra, " HWheel"); break;
+ case REL_DIAL: strcat(extra, " Dial"); break;
+ case REL_WHEEL: strcat(extra, " Wheel"); break;
+ case REL_MISC: strcat(extra, " Misc"); break;
+ }
+ }
+ break;
+ case EV_ABS: type = "absolute";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
+ for (k = 0; k < ABS_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case ABS_X: strcat(extra," X"); break;
+ case ABS_Y: strcat(extra," Y"); break;
+ case ABS_Z: strcat(extra," Z"); break;
+ case ABS_RX: strcat(extra," RX"); break;
+ case ABS_RY: strcat(extra," RY"); break;
+ case ABS_RZ: strcat(extra," RZ"); break;
+ case ABS_THROTTLE: strcat(extra," Throttle");break;
+ case ABS_RUDDER: strcat(extra," Rudder"); break;
+ case ABS_WHEEL: strcat(extra," Wheel"); break;
+ case ABS_GAS: strcat(extra," Gas"); break;
+ case ABS_BRAKE: strcat(extra," Break"); break;
+ case ABS_HAT0X: strcat(extra," Hat0X"); break;
+ case ABS_HAT0Y: strcat(extra," Hat0Y"); break;
+ case ABS_HAT1X: strcat(extra," Hat1X"); break;
+ case ABS_HAT1Y: strcat(extra," Hat1Y"); break;
+ case ABS_HAT2X: strcat(extra," Hat2X"); break;
+ case ABS_HAT2Y: strcat(extra," Hat2Y"); break;
+ case ABS_HAT3X: strcat(extra," Hat3X"); break;
+ case ABS_HAT3Y: strcat(extra," Hat3Y"); break;
+ case ABS_PRESSURE: strcat(extra," Pressure");break;
+ case ABS_DISTANCE: strcat(extra," Distance");break;
+ case ABS_TILT_X: strcat(extra," TiltX"); break;
+ case ABS_TILT_Y: strcat(extra," TiltY"); break;
+ case ABS_MISC: strcat(extra," Misc"); break;
+ }
+ }
+ break;
+ case EV_MSC: type = "reserved"; break;
+ case EV_LED: type = "leds";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
+ for (k = 0; k < LED_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case LED_NUML: strcat(extra," NumLock"); break;
+ case LED_CAPSL: strcat(extra," CapsLock"); break;
+ case LED_SCROLLL: strcat(extra," ScrlLock"); break;
+ case LED_COMPOSE: strcat(extra," Compose"); break;
+ case LED_KANA: strcat(extra," Kana"); break;
+ case LED_SLEEP: strcat(extra," Sleep"); break;
+ case LED_SUSPEND: strcat(extra," Suspend"); break;
+ case LED_MUTE: strcat(extra," Mute"); break;
+ case LED_MISC: strcat(extra," Misc"); break;
+ }
+ }
+ break;
+ case EV_SND: type = "sound";
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_SND, sizeof(bits)), bits);
+ for (k = 0; k < SND_MAX; k++) {
+ if (test_bits(k)) switch (k) {
+ case SND_CLICK: strcat(extra," Click"); break;
+ case SND_BELL: strcat(extra," Bell"); break;
+ }
+ }
+ break;
+ case EV_REP: type = "repeat"; break;
+ case EV_FF: type = "feedback"; break;
+ }
+ LOG5INPUT(priv, " Feature 0x%02x = %s%s%s%s\n", j, type,
+ extra[0] ? " [" : "",
+ extra[0] ? extra+1 : "",
+ extra[0] ? "]" : "");
+ }
+ }
+}
+
+/** Initialized \a pDev as a \a usbMouse, \a usbKeyboard, or \a usbOther
+device. */
+void usbInit(DevicePtr pDev, usbType type)
+{
+ GETPRIV;
+ char name[64]; /* RATS: Only used in XmuSnprintf */
+ int i, j, k;
+ char buf[256] = { 0, }; /* RATS: Use ok */
+ int version;
+ unsigned char bits[KEY_MAX/8 + 1]; /* RATS: Use ok assuming that
+ * KEY_MAX is greater than
+ * REL_MAX, ABS_MAX, SND_MAX, and
+ * LED_MAX. */
+
+ if (priv->fd >=0) return;
+
+ for (i = 0; i < 32; i++) {
+ XmuSnprintf(name, sizeof(name), "/dev/input/event%d", i);
+ if ((priv->fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) {
+ ioctl(priv->fd, EVIOCGVERSION, &version);
+ ioctl(priv->fd, EVIOCGNAME(sizeof(buf)), buf);
+ memset(priv->mask, 0, sizeof(priv->mask));
+ ioctl(priv->fd, EVIOCGBIT(0, sizeof(priv->mask)), priv->mask);
+
+ for (j = 0; j < EV_MAX; j++) {
+ if (test_bit(j)) {
+ switch(j) {
+ case EV_REL:
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_REL, sizeof(bits)), bits);
+ for (k = 0; k < REL_MAX; k++) {
+ if (test_bits(k)) {
+ if (k == REL_X) priv->relmap[k] = 0;
+ else if (k == REL_Y) priv->relmap[k] = 1;
+ else priv->relmap[k] = 2 + priv->numAbs;
+ ++priv->numRel;
+ }
+ }
+ break;
+ case EV_ABS:
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_ABS, sizeof(bits)), bits);
+ for (k = 0; k < ABS_MAX; k++) {
+ if (test_bits(k)) {
+ priv->absmap[k] = priv->numAbs;
+ ++priv->numAbs;
+ }
+ }
+ break;
+ case EV_LED:
+ memset(bits, 0, sizeof(bits));
+ ioctl(priv->fd, EVIOCGBIT(EV_LED, sizeof(bits)), bits);
+ for (k = 0; k < LED_MAX; k++) {
+ if (test_bits(k)) ++priv->numLeds;
+ }
+ break;
+ }
+ }
+ }
+ switch (type) {
+ case usbMouse:
+ if (test_bit(EV_REL) && test_bit(EV_KEY))
+ goto found;
+ break;
+ case usbKeyboard:
+ if (test_bit(EV_KEY) && test_bit(EV_LED) && !test_bit(EV_ABS))
+ goto found;
+ break;
+ case usbOther:
+ if (!(test_bit(EV_REL) && test_bit(EV_KEY))
+ && !(test_bit(EV_KEY) && test_bit(EV_LED)
+ && !test_bit(EV_ABS)))
+ goto found;
+ break;
+ }
+ close(priv->fd);
+ priv->fd = -1;
+ }
+ }
+ if (priv->fd < 0)
+ FATAL1("usbInit: Cannot open /dev/input/event* port (%s)\n"
+ " If you have not done so, you may need to:\n"
+ " rmmod mousedev; rmmod keybdev\n"
+ " modprobe evdev\n",
+ strerror(errno));
+ found:
+ usbPrint(priv, name, buf, priv->fd);
+}
+
+/** Turn \a pDev off (i.e., stop taking input from \a pDev). */
+void usbOff(DevicePtr pDev)
+{
+ GETPRIV;
+
+ if (priv->fd >= 0) close(priv->fd);
+ priv->fd = -1;
+}
+
+/** Create a private structure for use within this file. */
+pointer usbCreatePrivate(DeviceIntPtr pDevice)
+{
+ myPrivate *priv = calloc(1, sizeof(*priv));
+ priv->fd = -1;
+ priv->pDevice = pDevice;
+ return priv;
+}
+
+/** Destroy a private structure. */
+void usbDestroyPrivate(pointer priv)
+{
+ free(priv);
+}