diff options
author | marha <marha@users.sourceforge.net> | 2012-03-23 10:05:55 +0100 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-03-23 10:05:55 +0100 |
commit | 0f834b91a4768673833ab4917e87d86c237bb1a6 (patch) | |
tree | 363489504ed4b2d360259b8de4c9e392918e5d02 /xorg-server/hw/dmx/input | |
parent | fc72edebf875378459368c5383d9023730cbca54 (diff) | |
download | vcxsrv-0f834b91a4768673833ab4917e87d86c237bb1a6.tar.gz vcxsrv-0f834b91a4768673833ab4917e87d86c237bb1a6.tar.bz2 vcxsrv-0f834b91a4768673833ab4917e87d86c237bb1a6.zip |
libX11 xserver fontconfig mesa pixman xkbcomp xkeyboard-config git update
23 Mar 2012
Diffstat (limited to 'xorg-server/hw/dmx/input')
26 files changed, 6007 insertions, 5224 deletions
diff --git a/xorg-server/hw/dmx/input/ChkNotMaskEv.c b/xorg-server/hw/dmx/input/ChkNotMaskEv.c index 635332e63..bde04ae23 100644 --- a/xorg-server/hw/dmx/input/ChkNotMaskEv.c +++ b/xorg-server/hw/dmx/input/ChkNotMaskEv.c @@ -67,40 +67,40 @@ extern long const _Xevent_to_mask[]; * If not, flush buffer and see if any more events are readable. If one * matches, return. If all else fails, tell the user no events found. */ -Bool XCheckNotMaskEvent (Display *dpy, long mask, XEvent *event) +Bool +XCheckNotMaskEvent(Display * dpy, long mask, XEvent * event) { - register _XQEvent *prev, *qelt; - unsigned long qe_serial = 0; - int n; /* time through count */ + register _XQEvent *prev, *qelt; + unsigned long qe_serial = 0; + int n; /* time through count */ - LockDisplay(dpy); - prev = NULL; - for (n = 3; --n >= 0;) { - for (qelt = prev ? prev->next : dpy->head; - qelt; - prev = qelt, qelt = qelt->next) { - if (qelt->event.type >= LASTEvent - || !(_Xevent_to_mask[qelt->event.type] & mask)) { - *event = qelt->event; - _XDeq(dpy, prev, qelt); - UnlockDisplay(dpy); - return True; - } - } - if (prev) - qe_serial = prev->qserial_num; - switch (n) { - case 2: - _XEventsQueued(dpy, QueuedAfterReading); - break; - case 1: - _XFlush(dpy); - break; - } - if (prev && prev->qserial_num != qe_serial) - /* another thread has snatched this event */ - prev = NULL; - } - UnlockDisplay(dpy); - return False; + LockDisplay(dpy); + prev = NULL; + for (n = 3; --n >= 0;) { + for (qelt = prev ? prev->next : dpy->head; + qelt; prev = qelt, qelt = qelt->next) { + if (qelt->event.type >= LASTEvent + || !(_Xevent_to_mask[qelt->event.type] & mask)) { + *event = qelt->event; + _XDeq(dpy, prev, qelt); + UnlockDisplay(dpy); + return True; + } + } + if (prev) + qe_serial = prev->qserial_num; + switch (n) { + case 2: + _XEventsQueued(dpy, QueuedAfterReading); + break; + case 1: + _XFlush(dpy); + break; + } + if (prev && prev->qserial_num != qe_serial) + /* another thread has snatched this event */ + prev = NULL; + } + UnlockDisplay(dpy); + return False; } diff --git a/xorg-server/hw/dmx/input/dmxarg.c b/xorg-server/hw/dmx/input/dmxarg.c index 49a1da9af..4a74b4c9e 100644 --- a/xorg-server/hw/dmx/input/dmxarg.c +++ b/xorg-server/hw/dmx/input/dmxarg.c @@ -51,86 +51,99 @@ /** Stores the parsed argument list. */ struct _dmxArg { - int argc; /**< Number of arguments in argv */ - int argm; /**< Maximum number of arguments store-able in argv */ + int argc; /**< Number of arguments in argv */ + int argm; /**< Maximum number of arguments store-able in argv */ const char **argv; /**< Arguments */ }; /** Create an (externally opaque) \a dmxArg object. */ -dmxArg dmxArgCreate(void) +dmxArg +dmxArgCreate(void) { - dmxArg a = malloc(sizeof(*a)); - a->argc = 0; - a->argm = 2; - a->argv = malloc(a->argm * sizeof(*a->argv)); + dmxArg a = malloc(sizeof(*a)); + + a->argc = 0; + a->argm = 2; + a->argv = malloc(a->argm * sizeof(*a->argv)); a->argv[0] = NULL; return a; } /** Free the specified \a dmxArg object. */ -void dmxArgFree(dmxArg a) +void +dmxArgFree(dmxArg a) { int i; - for (i = 0; i < a->argc; i++) free((char *)a->argv[i]); + for (i = 0; i < a->argc; i++) + free((char *) a->argv[i]); free(a->argv); free(a); } /** Add the \a string as the next argument in the \a dmxArg object. */ -void dmxArgAdd(dmxArg a, const char *string) +void +dmxArgAdd(dmxArg a, const char *string) { if (a->argm <= a->argc + 2) a->argv = realloc(a->argv, sizeof(*a->argv) * (a->argm *= 2)); a->argv[a->argc++] = strdup(string); - a->argv[a->argc] = NULL; + a->argv[a->argc] = NULL; } /** Return the argument number \a item in the \a dmxArg object. * Arguments are 0 based. NULL will be returned for values less than 0 * or equal to or greater than the number of arguments in the object. */ -const char *dmxArgV(dmxArg a, int item) +const char * +dmxArgV(dmxArg a, int item) { - if (item < 0 || item >= a->argc) return NULL; + if (item < 0 || item >= a->argc) + return NULL; return a->argv[item]; } /** Return the number of arguments in the \a dmxArg object. */ -int dmxArgC(dmxArg a) +int +dmxArgC(dmxArg a) { return a->argc; } /** Parse a string into arguments delimited by commas. Return a new \a * dmxArg object containing the arguments. */ -dmxArg dmxArgParse(const char *string) +dmxArg +dmxArgParse(const char *string) { - char *tmp; - char *start, *pt; + char *tmp; + char *start, *pt; dmxArg a = dmxArgCreate(); - int done; - int len; + int done; + int len; - if (!string) return a; + if (!string) + return a; len = strlen(string) + 2; tmp = malloc(len); strncpy(tmp, string, len); for (start = pt = tmp, done = 0; !done && *pt; start = ++pt) { - for (;*pt && *pt != ','; pt++); - if (!*pt) done = 1; + for (; *pt && *pt != ','; pt++); + if (!*pt) + done = 1; *pt = '\0'; dmxArgAdd(a, start); } - if (!done) dmxArgAdd(a, ""); /* Final comma */ - + if (!done) + dmxArgAdd(a, ""); /* Final comma */ + free(tmp); return a; } #if DMX_ARG_TEST -static void dmxArgPrint(dmxArg a) +static void +dmxArgPrint(dmxArg a) { int i; @@ -139,7 +152,8 @@ static void dmxArgPrint(dmxArg a) printf(" argv[%d] = \"%s\"\n", i, dmxArgV(a, i)); } -static void dmxArgTest(const char *string) +static void +dmxArgTest(const char *string) { dmxArg a; @@ -155,7 +169,8 @@ static void dmxArgTest(const char *string) dmxArgFree(a); } -int main(void) +int +main(void) { dmxArgTest(NULL); dmxArgTest(""); diff --git a/xorg-server/hw/dmx/input/dmxbackend.c b/xorg-server/hw/dmx/input/dmxbackend.c index 35e9e9616..9463c87d3 100644 --- a/xorg-server/hw/dmx/input/dmxbackend.c +++ b/xorg-server/hw/dmx/input/dmxbackend.c @@ -1,616 +1,665 @@ -/*
- * 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;
- }
-}
+/* + * 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 29c1958ad..5f25e8832 100644 --- a/xorg-server/hw/dmx/input/dmxcommon.c +++ b/xorg-server/hw/dmx/input/dmxcommon.c @@ -1,669 +1,698 @@ -/*
- * 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 */
-}
+/* + * 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 d4d73f2e8..f63772b17 100644 --- a/xorg-server/hw/dmx/input/dmxconsole.c +++ b/xorg-server/hw/dmx/input/dmxconsole.c @@ -1,1029 +1,1090 @@ -/*
- * 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 */
- }
-}
+/* + * 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/dmxdetach.c b/xorg-server/hw/dmx/input/dmxdetach.c index cc2250683..469f9c8d0 100644 --- a/xorg-server/hw/dmx/input/dmxdetach.c +++ b/xorg-server/hw/dmx/input/dmxdetach.c @@ -42,12 +42,14 @@ #include "dmxextension.h" /* For dmxInputCount */ /** Search for input associated with \a dmxScreen, and detach. */ -void dmxInputDetach(DMXScreenInfo *dmxScreen, Bool reserveId) +void +dmxInputDetach(DMXScreenInfo * dmxScreen, Bool reserveId) { int i; for (i = 0; i < dmxNumInputs; i++) { DMXInputInfo *dmxInput = &dmxInputs[i]; + if (dmxInput->scrnIdx == dmxScreen->index) { dmxLogInput(dmxInput, "Detaching (%sreserved)\n", reserveId ? "" : "not "); diff --git a/xorg-server/hw/dmx/input/dmxdummy.c b/xorg-server/hw/dmx/input/dmxdummy.c index 971892b9f..0690177f8 100644 --- a/xorg-server/hw/dmx/input/dmxdummy.c +++ b/xorg-server/hw/dmx/input/dmxdummy.c @@ -47,40 +47,42 @@ /** Return information about the dummy keyboard device specified in \a pDev * into the structure pointed to by \a info. The keyboard is set up to * have 1 valid key code that is \a NoSymbol */ -void dmxDummyKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) +void +dmxDummyKbdGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) { static KeySym keyboard_mapping = NoSymbol; - info->keyboard = 1; - info->keyClass = 1; + info->keyboard = 1; + info->keyClass = 1; info->keySyms.minKeyCode = 8; info->keySyms.maxKeyCode = 8; - info->keySyms.mapWidth = 1; - info->keySyms.map = &keyboard_mapping; - info->freemap = 0; - info->focusClass = 1; - info->kbdFeedbackClass = 1; - info->force = 1; + info->keySyms.mapWidth = 1; + info->keySyms.map = &keyboard_mapping; + info->freemap = 0; + info->focusClass = 1; + info->kbdFeedbackClass = 1; + info->force = 1; } /** Return information about the dummy mouse device specified in \a pDev * into the structure pointed to by \a info. They mouse has 3 buttons * and two axes. */ -void dmxDummyMouGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) +void +dmxDummyMouGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) { - info->buttonClass = 1; - info->numButtons = 3; - info->map[0] = 1; - info->map[1] = 2; - info->map[2] = 3; - info->valuatorClass = 1; - info->numRelAxes = 2; - info->minval[0] = 0; - info->minval[1] = 0; - info->maxval[0] = 0; - info->maxval[1] = 0; - info->res[0] = 1; - info->minres[0] = 0; - info->maxres[0] = 1; + info->buttonClass = 1; + info->numButtons = 3; + info->map[0] = 1; + info->map[1] = 2; + info->map[2] = 3; + info->valuatorClass = 1; + info->numRelAxes = 2; + info->minval[0] = 0; + info->minval[1] = 0; + info->maxval[0] = 0; + info->maxval[1] = 0; + info->res[0] = 1; + info->minres[0] = 0; + info->maxres[0] = 1; info->ptrFeedbackClass = 1; } diff --git a/xorg-server/hw/dmx/input/dmxevents.c b/xorg-server/hw/dmx/input/dmxevents.c index 41bc4bf2d..f73480824 100644 --- a/xorg-server/hw/dmx/input/dmxevents.c +++ b/xorg-server/hw/dmx/input/dmxevents.c @@ -61,9 +61,9 @@ #include "xkbsrv.h" #include "XIstubs.h" -static int dmxGlobalX, dmxGlobalY; /* Global cursor position */ -static int dmxGlobalInvalid; /* Flag indicating dmxCoreMotion - * should move the mouse anyway. */ +static int dmxGlobalX, dmxGlobalY; /* Global cursor position */ +static int dmxGlobalInvalid; /* Flag indicating dmxCoreMotion + * should move the mouse anyway. */ #if DMX_EVENTS_DEBUG #define DMXDBG0(f) dmxLog(dmxDebug,f) @@ -85,25 +85,26 @@ static int dmxGlobalInvalid; /* Flag indicating dmxCoreMotion #define DMXDBG7(f,a,b,c,d,e,g,h) #endif -static int dmxApplyFunctions(DMXInputInfo *dmxInput, DMXFunctionType f) +static int +dmxApplyFunctions(DMXInputInfo * dmxInput, DMXFunctionType f) { int i; int rc = 0; - for (i = 0; i < dmxInput->numDevs; i+= dmxInput->devs[i]->binding) + for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) if (dmxInput->devs[i]->functions) rc += dmxInput->devs[i]->functions(dmxInput->devs[i]->private, f); return rc; } -static int dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal, - int type, - KeySym keySym) +static int +dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal, int type, KeySym keySym) { - DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx]; + DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx]; -#if 1 /* hack to detect ctrl-alt-q, etc */ +#if 1 /* hack to detect ctrl-alt-q, etc */ static int ctrl = 0, alt = 0; + /* keep track of ctrl/alt key status */ if (type == KeyPress && keySym == 0xffe3) { ctrl = 1; @@ -126,11 +127,11 @@ static int dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal, state = dmxLocalCoreKeyboard->pDevice->key->state; else if (dmxLocal->pDevice->key) state = dmxLocal->pDevice->key->state; - + DMXDBG3("dmxCheckFunctionKeys: keySym=0x%04x %s state=0x%04x\n", keySym, type == KeyPress ? "press" : "release", state); - if ((state & (ControlMask|Mod1Mask)) != (ControlMask|Mod1Mask)) + if ((state & (ControlMask | Mod1Mask)) != (ControlMask | Mod1Mask)) return 0; #endif @@ -151,34 +152,36 @@ static int dmxCheckFunctionKeys(DMXLocalInputInfoPtr dmxLocal, } return 1; } - + return 0; } - -DMXScreenInfo *dmxFindFirstScreen(int x, int y) +DMXScreenInfo * +dmxFindFirstScreen(int x, int y) { int i; for (i = 0; i < dmxNumScreens; i++) { DMXScreenInfo *dmxScreen = &dmxScreens[i]; + if (dmxOnScreen(x, y, dmxScreen)) return dmxScreen; } return NULL; } - /** * Enqueue a motion event. */ -static void enqueueMotion(DevicePtr pDev, int x, int y) +static void +enqueueMotion(DevicePtr pDev, int x, int y) { GETDMXLOCALFROMPDEV; DeviceIntPtr p = dmxLocal->pDevice; int valuators[3]; - int detail = 0; /* XXX should this be mask of pressed buttons? */ + int detail = 0; /* XXX should this be mask of pressed buttons? */ ValuatorMask mask; + valuators[0] = x; valuators[1] = y; @@ -188,50 +191,50 @@ static void enqueueMotion(DevicePtr pDev, int x, int y) return; } - void dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block) { DMXScreenInfo *dmxScreen; - DMXInputInfo *dmxInput; - ScreenPtr pScreen; - int localX; - int localY; - int i; + DMXInputInfo *dmxInput; + ScreenPtr pScreen; + int localX; + int localY; + int i; if (!dmxGlobalInvalid && dmxGlobalX == x && dmxGlobalY == y) return; - + DMXDBG5("dmxCoreMotion(%d,%d,%d) dmxGlobalX=%d dmxGlobalY=%d\n", x, y, delta, dmxGlobalX, dmxGlobalY); dmxGlobalInvalid = 0; - dmxGlobalX = x; - dmxGlobalY = y; + dmxGlobalX = x; + dmxGlobalY = y; if (dmxGlobalX < 0) dmxGlobalX = 0; if (dmxGlobalY < 0) dmxGlobalY = 0; if (dmxGlobalX >= dmxGlobalWidth) - dmxGlobalX = dmxGlobalWidth + delta -1; + dmxGlobalX = dmxGlobalWidth + delta - 1; if (dmxGlobalY >= dmxGlobalHeight) - dmxGlobalY = dmxGlobalHeight + delta -1; - + dmxGlobalY = dmxGlobalHeight + delta - 1; + if ((dmxScreen = dmxFindFirstScreen(dmxGlobalX, dmxGlobalY))) { localX = dmxGlobalX - dmxScreen->rootXOrigin; localY = dmxGlobalY - dmxScreen->rootYOrigin; if ((pScreen = miPointerGetScreen(inputInfo.pointer)) && pScreen->myNum == dmxScreen->index) { - /* Screen is old screen */ + /* Screen is old screen */ if (block) dmxSigioBlock(); if (pDev) - enqueueMotion(pDev, localX, localY); + enqueueMotion(pDev, localX, localY); if (block) dmxSigioUnblock(); - } else { - /* Screen is new */ + } + else { + /* Screen is new */ DMXDBG4(" New screen: old=%d new=%d localX=%d localY=%d\n", pScreen->myNum, dmxScreen->index, localX, localY); if (block) @@ -240,7 +243,7 @@ dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block) miPointerSetScreen(inputInfo.pointer, dmxScreen->index, localX, localY); if (pDev) - enqueueMotion(pDev, localX, localY); + enqueueMotion(pDev, localX, localY); if (block) dmxSigioUnblock(); } @@ -260,10 +263,11 @@ dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block) } #endif } - /* Send updates down to all core input - * drivers */ + /* Send updates down to all core input + * drivers */ for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) { int j; + for (j = 0; j < dmxInput->numDevs; j += dmxInput->devs[j]->binding) if (!dmxInput->detached && dmxInput->devs[j]->sendsCore @@ -271,34 +275,35 @@ dmxCoreMotion(DevicePtr pDev, int x, int y, int delta, DMXBlockType block) dmxInput->devs[j]->update_position(dmxInput->devs[j]->private, dmxGlobalX, dmxGlobalY); } - if (!dmxScreen) ProcessInputEvents(); + if (!dmxScreen) + ProcessInputEvents(); } - - #define DMX_MAX_AXES 32 /* Max axes reported by this routine */ -static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal, - int *v, int firstAxis, int axesCount, - DMXMotionType type, DMXBlockType block) +static void +dmxExtMotion(DMXLocalInputInfoPtr dmxLocal, + int *v, int firstAxis, int axesCount, + DMXMotionType type, DMXBlockType block) { - DeviceIntPtr pDevice = dmxLocal->pDevice; - xEvent xE[2 * DMX_MAX_AXES/6]; - deviceKeyButtonPointer *xev = (deviceKeyButtonPointer *)xE; - deviceValuator *xv = (deviceValuator *)xev+1; - int thisX = 0; - int thisY = 0; - int count; - ValuatorMask mask; + DeviceIntPtr pDevice = dmxLocal->pDevice; + xEvent xE[2 * DMX_MAX_AXES / 6]; + deviceKeyButtonPointer *xev = (deviceKeyButtonPointer *) xE; + deviceValuator *xv = (deviceValuator *) xev + 1; + int thisX = 0; + int thisY = 0; + int count; + ValuatorMask mask; memset(xE, 0, sizeof(xE)); - if (axesCount > DMX_MAX_AXES) axesCount = DMX_MAX_AXES; + if (axesCount > DMX_MAX_AXES) + axesCount = DMX_MAX_AXES; - if ((valuator_get_mode(pDevice,0) == Relative) && axesCount == 2) { - /* The dmx console is a relative mode - * device that sometimes reports - * absolute motion. It only has two - * axes. */ + if ((valuator_get_mode(pDevice, 0) == Relative) && axesCount == 2) { + /* The dmx console is a relative mode + * device that sometimes reports + * absolute motion. It only has two + * axes. */ if (type == DMX_RELATIVE) { thisX = -v[0]; thisY = -v[1]; @@ -307,7 +312,8 @@ static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal, if (dmxLocal->update_position) dmxLocal->update_position(dmxLocal->private, dmxLocal->lastX, dmxLocal->lastY); - } else { /* Convert to relative */ + } + else { /* Convert to relative */ if (dmxLocal->lastX || dmxLocal->lastY) { thisX = v[0] - dmxLocal->lastX; thisY = v[1] - dmxLocal->lastY; @@ -320,110 +326,155 @@ static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal, } if (axesCount <= 6) { - /* Optimize for the common case when - * only 1 or 2 axes change. */ - xev->time = GetTimeInMillis(); - xev->type = DeviceMotionNotify; - xev->detail = 0; - xev->deviceid = pDevice->id | MORE_EVENTS; - - xv->type = DeviceValuator; - xv->deviceid = pDevice->id; - xv->num_valuators = axesCount; - xv->first_valuator = firstAxis; - switch (xv->num_valuators) { - case 6: xv->valuator5 = v[5]; - case 5: xv->valuator4 = v[4]; - case 4: xv->valuator3 = v[3]; - case 3: xv->valuator2 = v[2]; - case 2: xv->valuator1 = v[1]; - case 1: xv->valuator0 = v[0]; - } - count = 2; - } else { + /* Optimize for the common case when + * only 1 or 2 axes change. */ + xev->time = GetTimeInMillis(); + xev->type = DeviceMotionNotify; + xev->detail = 0; + xev->deviceid = pDevice->id | MORE_EVENTS; + + xv->type = DeviceValuator; + xv->deviceid = pDevice->id; + xv->num_valuators = axesCount; + xv->first_valuator = firstAxis; + switch (xv->num_valuators) { + case 6: + xv->valuator5 = v[5]; + case 5: + xv->valuator4 = v[4]; + case 4: + xv->valuator3 = v[3]; + case 3: + xv->valuator2 = v[2]; + case 2: + xv->valuator1 = v[1]; + case 1: + xv->valuator0 = v[0]; + } + count = 2; + } + else { int i; + for (i = 0, count = 0; i < axesCount; i += 6) { - xev->time = GetTimeInMillis(); - xev->type = DeviceMotionNotify; - xev->detail = 0; - xev->deviceid = pDevice->id | MORE_EVENTS; - xev += 2; - - xv->type = DeviceValuator; - xv->deviceid = pDevice->id; - xv->num_valuators = (i+6 >= axesCount ? axesCount - i : 6); + xev->time = GetTimeInMillis(); + xev->type = DeviceMotionNotify; + xev->detail = 0; + xev->deviceid = pDevice->id | MORE_EVENTS; + xev += 2; + + xv->type = DeviceValuator; + xv->deviceid = pDevice->id; + xv->num_valuators = (i + 6 >= axesCount ? axesCount - i : 6); xv->first_valuator = firstAxis + i; switch (xv->num_valuators) { - case 6: xv->valuator5 = v[i+5]; - case 5: xv->valuator4 = v[i+4]; - case 4: xv->valuator3 = v[i+3]; - case 3: xv->valuator2 = v[i+2]; - case 2: xv->valuator1 = v[i+1]; - case 1: xv->valuator0 = v[i+0]; + case 6: + xv->valuator5 = v[i + 5]; + case 5: + xv->valuator4 = v[i + 4]; + case 4: + xv->valuator3 = v[i + 3]; + case 3: + xv->valuator2 = v[i + 2]; + case 2: + xv->valuator1 = v[i + 1]; + case 1: + xv->valuator0 = v[i + 0]; } - xv += 2; - count += 2; + xv += 2; + count += 2; } } if (block) dmxSigioBlock(); valuator_mask_set_range(&mask, firstAxis, axesCount, v); - QueuePointerEvents(pDevice, MotionNotify, 0, - POINTER_ABSOLUTE, &mask); + QueuePointerEvents(pDevice, MotionNotify, 0, POINTER_ABSOLUTE, &mask); if (block) dmxSigioUnblock(); } -static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, - XEvent *e, DMXBlockType block) +static int +dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, + XEvent * e, DMXBlockType block) { - int type; - int event = -1; - XDeviceKeyEvent *ke = (XDeviceKeyEvent *)e; - XDeviceMotionEvent *me = (XDeviceMotionEvent *)e; - DeviceIntPtr pDevice = dmxLocal->pDevice; - int valuators[MAX_VALUATORS]; - ValuatorMask mask; + int type; + int event = -1; + XDeviceKeyEvent *ke = (XDeviceKeyEvent *) e; + XDeviceMotionEvent *me = (XDeviceMotionEvent *) e; + DeviceIntPtr pDevice = dmxLocal->pDevice; + int valuators[MAX_VALUATORS]; + ValuatorMask mask; if (!e) - return -1; /* No extended event passed, cannot handle */ + return -1; /* No extended event passed, cannot handle */ - if ((XID)dmxLocal->deviceId != ke->deviceid) { - /* Search for the correct dmxLocal, - * since backend and console events are - * picked up for the first device on - * that X server. */ + if ((XID) dmxLocal->deviceId != ke->deviceid) { + /* Search for the correct dmxLocal, + * since backend and console events are + * picked up for the first device on + * that X server. */ int i; DMXInputInfo *dmxInput = &dmxInputs[dmxLocal->inputIdx]; + for (i = 0; i < dmxInput->numDevs; i++) { dmxLocal = dmxInput->devs[i]; - if ((XID)dmxLocal->deviceId == ke->deviceid) + if ((XID) dmxLocal->deviceId == ke->deviceid) break; } } - if ((XID)dmxLocal->deviceId != ke->deviceid + if ((XID) dmxLocal->deviceId != ke->deviceid || (type = dmxMapLookup(dmxLocal, e->type)) < 0) - return -1; /* No mapping, so this event is unhandled */ + return -1; /* No mapping, so this event is unhandled */ switch (type) { - case XI_DeviceValuator: event = DeviceValuator; break; - case XI_DeviceKeyPress: event = KeyPress; break; - case XI_DeviceKeyRelease: event = KeyRelease; break; - case XI_DeviceButtonPress: event = ButtonPress; break; - case XI_DeviceButtonRelease: event = ButtonRelease; break; - case XI_DeviceMotionNotify: event = MotionNotify; break; - case XI_DeviceFocusIn: event = DeviceFocusIn; break; - case XI_DeviceFocusOut: event = DeviceFocusOut; break; - case XI_ProximityIn: event = ProximityIn; break; - case XI_ProximityOut: event = ProximityOut; break; - case XI_DeviceStateNotify: event = DeviceStateNotify; break; - case XI_DeviceMappingNotify: event = DeviceMappingNotify; break; - case XI_ChangeDeviceNotify: event = ChangeDeviceNotify; break; - case XI_DeviceKeystateNotify: event = DeviceStateNotify; break; - case XI_DeviceButtonstateNotify: event = DeviceStateNotify; break; + case XI_DeviceValuator: + event = DeviceValuator; + break; + case XI_DeviceKeyPress: + event = KeyPress; + break; + case XI_DeviceKeyRelease: + event = KeyRelease; + break; + case XI_DeviceButtonPress: + event = ButtonPress; + break; + case XI_DeviceButtonRelease: + event = ButtonRelease; + break; + case XI_DeviceMotionNotify: + event = MotionNotify; + break; + case XI_DeviceFocusIn: + event = DeviceFocusIn; + break; + case XI_DeviceFocusOut: + event = DeviceFocusOut; + break; + case XI_ProximityIn: + event = ProximityIn; + break; + case XI_ProximityOut: + event = ProximityOut; + break; + case XI_DeviceStateNotify: + event = DeviceStateNotify; + break; + case XI_DeviceMappingNotify: + event = DeviceMappingNotify; + break; + case XI_ChangeDeviceNotify: + event = ChangeDeviceNotify; + break; + case XI_DeviceKeystateNotify: + event = DeviceStateNotify; + break; + case XI_DeviceButtonstateNotify: + event = DeviceStateNotify; + break; } #define EXTRACT_VALUATORS(ke, valuators) \ @@ -438,7 +489,8 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, case XI_DeviceKeyPress: case XI_DeviceKeyRelease: EXTRACT_VALUATORS(ke, valuators); - valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators); + valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, + valuators); if (block) dmxSigioBlock(); QueueKeyboardEvents(pDevice, event, ke->keycode, &mask); @@ -448,7 +500,8 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, case XI_DeviceButtonPress: case XI_DeviceButtonRelease: EXTRACT_VALUATORS(ke, valuators); - valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators); + valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, + valuators); if (block) dmxSigioBlock(); QueuePointerEvents(pDevice, event, ke->keycode, @@ -459,7 +512,8 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, case XI_ProximityIn: case XI_ProximityOut: EXTRACT_VALUATORS(ke, valuators); - valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators); + valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, + valuators); if (block) dmxSigioBlock(); QueueProximityEvents(pDevice, event, &mask); @@ -480,13 +534,13 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, case XI_ChangeDeviceNotify: case XI_DeviceKeystateNotify: case XI_DeviceButtonstateNotify: - /* These are ignored, since DMX will - * generate its own events of these - * types, as necessary. + /* These are ignored, since DMX will + * generate its own events of these + * types, as necessary. - * Perhaps ChangeDeviceNotify should - * generate an error, because it is - * unexpected? */ + * Perhaps ChangeDeviceNotify should + * generate an error, because it is + * unexpected? */ break; case XI_DeviceValuator: default: @@ -498,11 +552,12 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal, return 0; } -static int dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button) +static int +dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button) { ButtonClassPtr b = dmxLocal->pDevice->button; - if (button > b->numButtons) { /* This shouldn't happen. */ + if (button > b->numButtons) { /* This shouldn't happen. */ dmxLog(dmxWarning, "Button %d pressed, but only %d buttons?!?\n", button, b->numButtons); return button; @@ -512,14 +567,16 @@ static int dmxGetButtonMapping(DMXLocalInputInfoPtr dmxLocal, int button) /** Return DMX's notion of the pointer position in the global coordinate * space. */ -void dmxGetGlobalPosition(int *x, int *y) +void +dmxGetGlobalPosition(int *x, int *y) { *x = dmxGlobalX; *y = dmxGlobalY; } /** Invalidate the global position for #dmxCoreMotion. */ -void dmxInvalidateGlobalPosition(void) +void +dmxInvalidateGlobalPosition(void) { dmxGlobalInvalid = 1; } @@ -534,8 +591,9 @@ void dmxInvalidateGlobalPosition(void) * * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be * blocked around calls to \a enqueueMotion(). */ -void dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount, - DMXMotionType type, DMXBlockType block) +void +dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount, + DMXMotionType type, DMXBlockType block) { GETDMXLOCALFROMPDEV; @@ -558,8 +616,8 @@ void dmxMotion(DevicePtr pDev, int *v, int firstAxes, int axesCount, } } -static KeySym dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal, - KeyCode keyCode) +static KeySym +dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal, KeyCode keyCode) { KeySym keysym = NoSymbol; int effectiveGroup; @@ -578,21 +636,21 @@ static KeySym dmxKeyCodeToKeySym(DMXLocalInputInfoPtr dmxLocal, DMXDBG2("dmxKeyCodeToKeySym: Translated keyCode=%d to keySym=0x%04x\n", keyCode, keysym); -out: + out: return keysym; } -static KeyCode dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal, KeySym keySym, - int tryFirst) +static KeyCode +dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal, KeySym keySym, int tryFirst) { /* FIXME: this is quite ineffective, converting to a core map first and * then extracting the info from there. It'd be better to run the actual * xkb map */ XkbSrvInfoPtr xkbi = dmxLocal->pDevice->key->xkbInfo; KeySymsPtr pKeySyms = XkbGetCoreMap(dmxLocal->pDevice); - int i; + int i; - /* Optimize for similar maps */ + /* Optimize for similar maps */ if (XkbKeycodeInRange(xkbi->desc, tryFirst) && pKeySyms->map[(tryFirst - xkbi->desc->min_key_code) * pKeySyms->mapWidth] == keySym) @@ -603,18 +661,19 @@ static KeyCode dmxKeySymToKeyCode(DMXLocalInputInfoPtr dmxLocal, KeySym keySym, * pKeySyms->mapWidth] == keySym) { DMXDBG3("dmxKeySymToKeyCode: Translated keySym=0x%04x to" " keyCode=%d (reverses to core keySym=0x%04x)\n", - keySym, i, dmxKeyCodeToKeySym(dmxLocalCoreKeyboard,i)); + keySym, i, dmxKeyCodeToKeySym(dmxLocalCoreKeyboard, i)); return i; } } return 0; } -static int dmxFixup(DevicePtr pDev, int detail, KeySym keySym) +static int +dmxFixup(DevicePtr pDev, int detail, KeySym keySym) { GETDMXLOCALFROMPDEV; int keyCode; - + if (!dmxLocal->pDevice->key) { dmxLog(dmxWarning, "dmxFixup: not a keyboard device (%s)\n", dmxLocal->pDevice->name); @@ -636,9 +695,10 @@ static int dmxFixup(DevicePtr pDev, int detail, KeySym keySym) * FIXME: make the code do what the comment says, or remove this comment. * If \a block is set to \a DMX_BLOCK, then the SIGIO handler will be * blocked around calls to dmxeqEnqueue(). */ - -void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym, - XEvent *e, DMXBlockType block) + +void +dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym, + XEvent * e, DMXBlockType block) { GETDMXINPUTFROMPDEV; xEvent xE; @@ -658,7 +718,7 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym, if (dmxLocal->sendsCore && dmxLocal != dmxLocalCoreKeyboard) xE.u.u.detail = dmxFixup(pDev, detail, keySym); - /*ErrorF("KEY %d sym %d\n", detail, (int) keySym);*/ + /*ErrorF("KEY %d sym %d\n", detail, (int) keySym); */ QueueKeyboardEvents(p, type, detail, NULL); return; @@ -673,7 +733,7 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym, case MotionNotify: valuators[0] = e->xmotion.x; valuators[1] = e->xmotion.y; - valuators[2] = e->xmotion.state; /* FIXME: WTF?? */ + valuators[2] = e->xmotion.state; /* FIXME: WTF?? */ valuator_mask_set_range(&mask, 0, 3, valuators); QueuePointerEvents(p, type, detail, POINTER_ABSOLUTE | POINTER_SCREEN, &mask); @@ -682,7 +742,7 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym, case EnterNotify: case LeaveNotify: case KeymapNotify: - case MappingNotify: /* This is sent because we change the + case MappingNotify: /* This is sent because we change the * modifier map on the backend/console * input device so that we have complete * control of the input device LEDs. */ @@ -690,13 +750,14 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym, default: if (type == ProximityIn || type == ProximityOut) { if (dmxLocal->sendsCore) - return; /* Not a core event */ + return; /* Not a core event */ break; } if (type >= LASTEvent) { if (dmxTranslateAndEnqueueExtEvent(dmxLocal, e, block)) dmxLogInput(dmxInput, "Unhandled extension event: %d\n", type); - } else { + } + else { dmxLogInput(dmxInput, "Unhandled event: %d (%s)\n", type, dmxEventName(type)); } @@ -711,23 +772,28 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym, * requested termination of the DMX server, -1 is returned. If the user * has requested a switch to a VT, then the (1-based) number of that VT * is returned. */ -int dmxCheckSpecialKeys(DevicePtr pDev, KeySym keySym) +int +dmxCheckSpecialKeys(DevicePtr pDev, KeySym keySym) { GETDMXINPUTFROMPDEV; - int vt = 0; + int vt = 0; unsigned short state = 0; if (dmxLocal->sendsCore) - state = XkbStateFieldFromRec(&dmxLocalCoreKeyboard->pDevice->key->xkbInfo->state); + state = + XkbStateFieldFromRec(&dmxLocalCoreKeyboard->pDevice->key->xkbInfo-> + state); else if (dmxLocal->pDevice->key) state = XkbStateFieldFromRec(&dmxLocal->pDevice->key->xkbInfo->state); - if (!dmxLocal->sendsCore) return 0; /* Only for core devices */ + if (!dmxLocal->sendsCore) + return 0; /* Only for core devices */ + + DMXDBG2("dmxCheckSpecialKeys: keySym=0x%04x state=0x%04x\n", keySym, state); + + if ((state & (ControlMask | Mod1Mask)) != (ControlMask | Mod1Mask)) + return 0; - DMXDBG2("dmxCheckSpecialKeys: keySym=0x%04x state=0x%04x\n", keySym,state); - - if ((state & (ControlMask|Mod1Mask)) != (ControlMask|Mod1Mask)) return 0; - switch (keySym) { case XK_F1: case XK_F2: @@ -747,7 +813,7 @@ int dmxCheckSpecialKeys(DevicePtr pDev, KeySym keySym) vt = keySym - XK_F11 + 11; break; - case XK_q: /* To avoid confusion */ + case XK_q: /* To avoid confusion */ case XK_BackSpace: case XK_Delete: case XK_KP_Delete: diff --git a/xorg-server/hw/dmx/input/dmxinputinit.c b/xorg-server/hw/dmx/input/dmxinputinit.c index 16ecae38d..b22a41f56 100644 --- a/xorg-server/hw/dmx/input/dmxinputinit.c +++ b/xorg-server/hw/dmx/input/dmxinputinit.c @@ -102,7 +102,7 @@ static DMXLocalInputInfoRec DMXBackendMou = { static DMXLocalInputInfoRec DMXBackendKbd = { "backend-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_BACKEND, - 1, /* With backend-mou or console-mou */ + 1, /* With backend-mou or console-mou */ dmxCommonCopyPrivate, NULL, dmxBackendInit, NULL, NULL, dmxBackendKbdGetInfo, dmxCommonKbdOn, dmxCommonKbdOff, NULL, @@ -123,7 +123,7 @@ static DMXLocalInputInfoRec DMXConsoleMou = { static DMXLocalInputInfoRec DMXConsoleKbd = { "console-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_CONSOLE, - 1, /* With backend-mou or console-mou */ + 1, /* With backend-mou or console-mou */ dmxCommonCopyPrivate, NULL, dmxConsoleInit, dmxConsoleReInit, NULL, dmxConsoleKbdGetInfo, dmxCommonKbdOn, dmxCommonKbdOff, NULL, @@ -133,87 +133,78 @@ static DMXLocalInputInfoRec DMXConsoleKbd = { }; static DMXLocalInputInfoRec DMXLocalDevices[] = { - /* Dummy drivers that can compile on any OS */ + /* Dummy drivers that can compile on any OS */ #ifdef __linux__ - /* Linux-specific drivers */ + /* Linux-specific drivers */ { - "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate, - kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo, - kbdLinuxOn, kbdLinuxOff, NULL, - kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch, - kbdLinuxRead, NULL, NULL, NULL, - NULL, kbdLinuxCtrl, kbdLinuxBell - }, + "kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, + kbdLinuxCreatePrivate, kbdLinuxDestroyPrivate, + kbdLinuxInit, NULL, NULL, kbdLinuxGetInfo, + kbdLinuxOn, kbdLinuxOff, NULL, + kbdLinuxVTPreSwitch, kbdLinuxVTPostSwitch, kbdLinuxVTSwitch, + kbdLinuxRead, NULL, NULL, NULL, + NULL, kbdLinuxCtrl, kbdLinuxBell}, { - "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - msLinuxCreatePrivate, msLinuxDestroyPrivate, - msLinuxInit, NULL, NULL, msLinuxGetInfo, - msLinuxOn, msLinuxOff, NULL, - msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL, - msLinuxRead - }, + "ms", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + msLinuxCreatePrivate, msLinuxDestroyPrivate, + msLinuxInit, NULL, NULL, msLinuxGetInfo, + msLinuxOn, msLinuxOff, NULL, + msLinuxVTPreSwitch, msLinuxVTPostSwitch, NULL, + msLinuxRead}, { - "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate, - ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo, - ps2LinuxOn, ps2LinuxOff, NULL, - ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL, - ps2LinuxRead - }, + "ps2", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + ps2LinuxCreatePrivate, ps2LinuxDestroyPrivate, + ps2LinuxInit, NULL, NULL, ps2LinuxGetInfo, + ps2LinuxOn, ps2LinuxOff, NULL, + ps2LinuxVTPreSwitch, ps2LinuxVTPostSwitch, NULL, + ps2LinuxRead}, #endif #ifdef __linux__ - /* USB drivers, currently only for - Linux, but relatively easy to port to - other OSs */ + /* USB drivers, currently only for + Linux, but relatively easy to port to + other OSs */ { - "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - kbdUSBInit, NULL, NULL, kbdUSBGetInfo, - kbdUSBOn, usbOff, NULL, - NULL, NULL, NULL, - kbdUSBRead, NULL, NULL, NULL, - NULL, kbdUSBCtrl - }, + "usb-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, + usbCreatePrivate, usbDestroyPrivate, + kbdUSBInit, NULL, NULL, kbdUSBGetInfo, + kbdUSBOn, usbOff, NULL, + NULL, NULL, NULL, + kbdUSBRead, NULL, NULL, NULL, + NULL, kbdUSBCtrl}, { - "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - mouUSBInit, NULL, NULL, mouUSBGetInfo, - mouUSBOn, usbOff, NULL, - NULL, NULL, NULL, - mouUSBRead - }, + "usb-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + usbCreatePrivate, usbDestroyPrivate, + mouUSBInit, NULL, NULL, mouUSBGetInfo, + mouUSBOn, usbOff, NULL, + NULL, NULL, NULL, + mouUSBRead}, { - "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1, - usbCreatePrivate, usbDestroyPrivate, - othUSBInit, NULL, NULL, othUSBGetInfo, - othUSBOn, usbOff, NULL, - NULL, NULL, NULL, - othUSBRead - }, + "usb-oth", DMX_LOCAL_OTHER, DMX_LOCAL_TYPE_LOCAL, 1, + usbCreatePrivate, usbDestroyPrivate, + othUSBInit, NULL, NULL, othUSBGetInfo, + othUSBOn, usbOff, NULL, + NULL, NULL, NULL, + othUSBRead}, #endif { - "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo - }, + "dummy-mou", DMX_LOCAL_MOUSE, DMX_LOCAL_TYPE_LOCAL, 1, + NULL, NULL, NULL, NULL, NULL, dmxDummyMouGetInfo}, { - "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, - NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo - }, - { NULL } /* Must be last */ + "dummy-kbd", DMX_LOCAL_KEYBOARD, DMX_LOCAL_TYPE_LOCAL, 1, + NULL, NULL, NULL, NULL, NULL, dmxDummyKbdGetInfo}, + {NULL} /* Must be last */ }; - #if 11 /*BP*/ -void + void DDXRingBell(int volume, int pitch, int duration) { - /* NO-OP */ + /* NO-OP */ } /* taken from kdrive/src/kinput.c: */ static void -dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl) +dmxKbdCtrl(DeviceIntPtr pDevice, KeybdCtrl * ctrl) { #if 0 KdKeyboardInfo *ki; @@ -228,7 +219,7 @@ dmxKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl) KdSetLeds(ki, ctrl->leds); ki->bellPitch = ctrl->bell_pitch; - ki->bellDuration = ctrl->bell_duration; + ki->bellDuration = ctrl->bell_duration; #endif } @@ -239,7 +230,7 @@ dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something) #if 0 KeybdCtrl *ctrl = arg; KdKeyboardInfo *ki = NULL; - + for (ki = kdKeyboards; ki; ki = ki->next) { if (ki->dixdev && ki->dixdev->id == pDev->id) break; @@ -247,50 +238,56 @@ dmxBell(int volume, DeviceIntPtr pDev, pointer arg, int something) if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) return; - + KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); #endif } #endif /*BP*/ - -static void _dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal, - PtrCtrl *ctrl) + static void +_dmxChangePointerControl(DMXLocalInputInfoPtr dmxLocal, PtrCtrl * ctrl) { - if (!dmxLocal) return; + if (!dmxLocal) + return; dmxLocal->mctrl = *ctrl; - if (dmxLocal->mCtrl) dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl); + if (dmxLocal->mCtrl) + dmxLocal->mCtrl(&dmxLocal->pDevice->public, ctrl); } /** Change the pointer control information for the \a pDevice. If the * device sends core events, then also change the control information * for all of the pointer devices that send core events. */ -void dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl *ctrl) +void +dmxChangePointerControl(DeviceIntPtr pDevice, PtrCtrl * ctrl) { GETDMXLOCALFROMPDEVICE; int i, j; - if (dmxLocal->sendsCore) { /* Do for all core devices */ + if (dmxLocal->sendsCore) { /* Do for all core devices */ for (i = 0; i < dmxNumInputs; i++) { DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; + + if (dmxInput->detached) + continue; for (j = 0; j < dmxInput->numDevs; j++) if (dmxInput->devs[j]->sendsCore) _dmxChangePointerControl(dmxInput->devs[j], ctrl); } - } else { /* Do for this device only */ + } + else { /* Do for this device only */ _dmxChangePointerControl(dmxLocal, ctrl); } } -static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal, - KeybdCtrl *ctrl) +static void +_dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal, KeybdCtrl * ctrl) { dmxLocal->kctrl = *ctrl; if (dmxLocal->kCtrl) { dmxLocal->kCtrl(&dmxLocal->pDevice->public, ctrl); if (dmxLocal->pDevice->kbdfeed) { XkbEventCauseRec cause; + XkbSetCauseUnknown(&cause); /* Generate XKB events, as necessary */ XkbUpdateIndicators(dmxLocal->pDevice, XkbAllIndicatorsMask, False, @@ -299,69 +296,84 @@ static void _dmxKeyboardKbdCtrlProc(DMXLocalInputInfoPtr dmxLocal, } } - /** Change the keyboard control information for the \a pDevice. If the * device sends core events, then also change the control information * for all of the keyboard devices that send core events. */ -void dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl *ctrl) +void +dmxKeyboardKbdCtrlProc(DeviceIntPtr pDevice, KeybdCtrl * ctrl) { GETDMXLOCALFROMPDEVICE; int i, j; - if (dmxLocal->sendsCore) { /* Do for all core devices */ + if (dmxLocal->sendsCore) { /* Do for all core devices */ for (i = 0; i < dmxNumInputs; i++) { DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; + + if (dmxInput->detached) + continue; for (j = 0; j < dmxInput->numDevs; j++) if (dmxInput->devs[j]->sendsCore) _dmxKeyboardKbdCtrlProc(dmxInput->devs[j], ctrl); } - } else { /* Do for this device only */ + } + else { /* Do for this device only */ _dmxKeyboardKbdCtrlProc(dmxLocal, ctrl); } } -static void _dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent) +static void +_dmxKeyboardBellProc(DMXLocalInputInfoPtr dmxLocal, int percent) { - if (dmxLocal->kBell) dmxLocal->kBell(&dmxLocal->pDevice->public, - percent, - dmxLocal->kctrl.bell, - dmxLocal->kctrl.bell_pitch, - dmxLocal->kctrl.bell_duration); + if (dmxLocal->kBell) + dmxLocal->kBell(&dmxLocal->pDevice->public, + percent, + dmxLocal->kctrl.bell, + dmxLocal->kctrl.bell_pitch, + dmxLocal->kctrl.bell_duration); } /** Sound the bell on the device. If the device send core events, then * sound the bell on all of the devices that send core events. */ -void dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice, - pointer ctrl, int unknown) +void +dmxKeyboardBellProc(int percent, DeviceIntPtr pDevice, + pointer ctrl, int unknown) { GETDMXLOCALFROMPDEVICE; int i, j; - if (dmxLocal->sendsCore) { /* Do for all core devices */ + if (dmxLocal->sendsCore) { /* Do for all core devices */ for (i = 0; i < dmxNumInputs; i++) { DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->detached) continue; + + if (dmxInput->detached) + continue; for (j = 0; j < dmxInput->numDevs; j++) if (dmxInput->devs[j]->sendsCore) _dmxKeyboardBellProc(dmxInput->devs[j], percent); } - } else { /* Do for this device only */ + } + else { /* Do for this device only */ _dmxKeyboardBellProc(dmxLocal, percent); } } -static void dmxKeyboardFreeNames(XkbComponentNamesPtr names) +static void +dmxKeyboardFreeNames(XkbComponentNamesPtr names) { - if (names->keycodes) XFree(names->keycodes); - if (names->types) XFree(names->types); - if (names->compat) XFree(names->compat); - if (names->symbols) XFree(names->symbols); - if (names->geometry) XFree(names->geometry); + if (names->keycodes) + XFree(names->keycodes); + if (names->types) + XFree(names->types); + if (names->compat) + XFree(names->compat); + if (names->symbols) + XFree(names->symbols); + if (names->geometry) + XFree(names->geometry); } - -static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info) +static int +dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo * info) { GETDMXINPUTFROMPDEVICE; XkbRMLVOSet rmlvo; @@ -374,14 +386,14 @@ static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info) XkbSetRulesDflts(&rmlvo); if (!info->force && (dmxInput->keycodes - || dmxInput->symbols - || dmxInput->geometry)) { - if (info->freenames) dmxKeyboardFreeNames(&info->names); - info->freenames = 0; + || dmxInput->symbols || dmxInput->geometry)) { + if (info->freenames) + dmxKeyboardFreeNames(&info->names); + info->freenames = 0; info->names.keycodes = dmxInput->keycodes; - info->names.types = NULL; - info->names.compat = NULL; - info->names.symbols = dmxInput->symbols; + info->names.types = NULL; + info->names.compat = NULL; + info->names.symbols = dmxInput->symbols; info->names.geometry = dmxInput->geometry; dmxLogInput(dmxInput, "XKEYBOARD: From command line: %s", @@ -391,7 +403,8 @@ static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info) if (info->names.geometry && *info->names.geometry) dmxLogInputCont(dmxInput, " %s", info->names.geometry); dmxLogInputCont(dmxInput, "\n"); - } else if (info->names.keycodes) { + } + else if (info->names.keycodes) { dmxLogInput(dmxInput, "XKEYBOARD: From device: %s", info->names.keycodes); if (info->names.symbols && *info->names.symbols) @@ -399,36 +412,36 @@ static int dmxKeyboardOn(DeviceIntPtr pDevice, DMXLocalInitInfo *info) if (info->names.geometry && *info->names.geometry) dmxLogInputCont(dmxInput, " %s", info->names.geometry); dmxLogInputCont(dmxInput, "\n"); - } else { + } + else { dmxLogInput(dmxInput, "XKEYBOARD: Defaults: %s %s %s %s %s\n", dmxConfigGetXkbRules(), dmxConfigGetXkbLayout(), - dmxConfigGetXkbModel(), - dmxConfigGetXkbVariant() - ? dmxConfigGetXkbVariant() : "", - dmxConfigGetXkbOptions() + dmxConfigGetXkbModel(), dmxConfigGetXkbVariant() + ? dmxConfigGetXkbVariant() : "", dmxConfigGetXkbOptions() ? dmxConfigGetXkbOptions() : ""); } InitKeyboardDeviceStruct(pDevice, &rmlvo, - dmxKeyboardBellProc, - dmxKeyboardKbdCtrlProc); + dmxKeyboardBellProc, dmxKeyboardKbdCtrlProc); - if (info->freenames) dmxKeyboardFreeNames(&info->names); + if (info->freenames) + dmxKeyboardFreeNames(&info->names); return Success; } - -static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) +static int +dmxDeviceOnOff(DeviceIntPtr pDevice, int what) { GETDMXINPUTFROMPDEVICE; - int fd; + int fd; DMXLocalInitInfo info; - int i; - Atom btn_labels[MAX_BUTTONS] = {0}; /* FIXME */ - Atom axis_labels[MAX_VALUATORS] = {0}; /* FIXME */ + int i; + Atom btn_labels[MAX_BUTTONS] = { 0 }; /* FIXME */ + Atom axis_labels[MAX_VALUATORS] = { 0 }; /* FIXME */ - if (dmxInput->detached) return Success; + if (dmxInput->detached) + return Success; memset(&info, 0, sizeof(info)); switch (what) { @@ -450,9 +463,7 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) rmlvo.variant = dmxConfigGetXkbVariant(); rmlvo.options = dmxConfigGetXkbOptions(); - InitKeyboardDeviceStruct(pDevice, - &rmlvo, - dmxBell, dmxKbdCtrl); + InitKeyboardDeviceStruct(pDevice, &rmlvo, dmxBell, dmxKbdCtrl); } if (info.buttonClass) { InitButtonClassDeviceStruct(pDevice, info.numButtons, @@ -462,15 +473,15 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) if (info.numRelAxes && dmxLocal->sendsCore) { InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, axis_labels, - GetMaximumEventsNum(), - Relative); + GetMaximumEventsNum(), Relative); for (i = 0; i < info.numRelAxes; i++) InitValuatorAxisStruct(pDevice, i, axis_labels[i], info.minval[i], info.maxval[i], info.res[i], info.minres[i], info.maxres[i], Relative); - } else if (info.numRelAxes) { + } + else if (info.numRelAxes) { InitValuatorClassDeviceStruct(pDevice, info.numRelAxes, axis_labels, dmxPointerGetMotionBufferSize(), @@ -481,7 +492,8 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) info.maxval[i], info.res[i], info.minres[i], info.maxres[i], Relative); - } else if (info.numAbsAxes) { + } + else if (info.numAbsAxes) { InitValuatorClassDeviceStruct(pDevice, info.numAbsAxes, axis_labels, dmxPointerGetMotionBufferSize(), @@ -494,8 +506,10 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) info.maxres[i], Absolute); } } - if (info.focusClass) InitFocusClassDeviceStruct(pDevice); - if (info.proximityClass) InitProximityClassDeviceStruct(pDevice); + if (info.focusClass) + InitFocusClassDeviceStruct(pDevice); + if (info.proximityClass) + InitProximityClassDeviceStruct(pDevice); if (info.ptrFeedbackClass) InitPtrFeedbackClassDeviceStruct(pDevice, dmxChangePointerControl); if (info.intFeedbackClass || info.strFeedbackClass) @@ -516,12 +530,13 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) break; case DEVICE_OFF: case DEVICE_CLOSE: - /* This can get called twice consecutively: once for a - * detached screen (DEVICE_OFF), and then again at server - * generation time (DEVICE_CLOSE). */ + /* This can get called twice consecutively: once for a + * detached screen (DEVICE_OFF), and then again at server + * generation time (DEVICE_CLOSE). */ if (pDev->on) { dmxSigioUnregister(dmxInput); - if (dmxLocal->off) dmxLocal->off(pDev); + if (dmxLocal->off) + dmxLocal->off(pDev); pDev->on = FALSE; } break; @@ -530,17 +545,19 @@ static int dmxDeviceOnOff(DeviceIntPtr pDevice, int what) XFree(info.keySyms.map); info.keySyms.map = NULL; } - if (info.xkb) XkbFreeKeyboard(info.xkb, 0, True); + if (info.xkb) + XkbFreeKeyboard(info.xkb, 0, True); return Success; } -static void dmxProcessInputEvents(DMXInputInfo *dmxInput) +static void +dmxProcessInputEvents(DMXInputInfo * dmxInput) { int i; mieqProcessInputEvents(); #if 00 /*BP*/ - miPointerUpdate(); + miPointerUpdate(); #endif if (dmxInput->detached) return; @@ -550,30 +567,44 @@ static void dmxProcessInputEvents(DMXInputInfo *dmxInput) } #if 11 /*BP*/ - mieqProcessInputEvents(); + mieqProcessInputEvents(); #endif } -static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput, - DMXUpdateType type, - WindowPtr pWindow) +static void +dmxUpdateWindowInformation(DMXInputInfo * dmxInput, + DMXUpdateType type, WindowPtr pWindow) { int i; #ifdef PANORAMIX - if (!noPanoramiXExtension && pWindow && pWindow->parent != screenInfo.screens[0]->root) + if (!noPanoramiXExtension && pWindow && + pWindow->parent != screenInfo.screens[0]->root) return; #endif #if DMX_WINDOW_DEBUG { const char *name = "Unknown"; + switch (type) { - case DMX_UPDATE_REALIZE: name = "Realize"; break; - case DMX_UPDATE_UNREALIZE: name = "Unrealize"; break; - case DMX_UPDATE_RESTACK: name = "Restack"; break; - case DMX_UPDATE_COPY: name = "Copy"; break; - case DMX_UPDATE_RESIZE: name = "Resize"; break; - case DMX_UPDATE_REPARENT: name = "Repaint"; break; + case DMX_UPDATE_REALIZE: + name = "Realize"; + break; + case DMX_UPDATE_UNREALIZE: + name = "Unrealize"; + break; + case DMX_UPDATE_RESTACK: + name = "Restack"; + break; + case DMX_UPDATE_COPY: + name = "Copy"; + break; + case DMX_UPDATE_RESIZE: + name = "Resize"; + break; + case DMX_UPDATE_REPARENT: + name = "Repaint"; + break; } dmxLog(dmxDebug, "Window %p changed: %s\n", pWindow, name); } @@ -587,7 +618,8 @@ static void dmxUpdateWindowInformation(DMXInputInfo *dmxInput, type, pWindow); } -static void dmxCollectAll(DMXInputInfo *dmxInput) +static void +dmxCollectAll(DMXInputInfo * dmxInput) { int i; @@ -595,29 +627,29 @@ static void dmxCollectAll(DMXInputInfo *dmxInput) return; for (i = 0; i < dmxInput->numDevs; i += dmxInput->devs[i]->binding) if (dmxInput->devs[i]->collect_events) - dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice->public, - dmxMotion, - dmxEnqueue, + dmxInput->devs[i]->collect_events(&dmxInput->devs[i]->pDevice-> + public, dmxMotion, dmxEnqueue, dmxCheckSpecialKeys, DMX_BLOCK); } -static void dmxBlockHandler(pointer blockData, OSTimePtr pTimeout, - pointer pReadMask) +static void +dmxBlockHandler(pointer blockData, OSTimePtr pTimeout, pointer pReadMask) { - DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t)blockData]; + DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t) blockData]; static unsigned long generation = 0; - + if (generation != serverGeneration) { generation = serverGeneration; dmxCollectAll(dmxInput); } } -static void dmxSwitchReturn(pointer p) +static void +dmxSwitchReturn(pointer p) { DMXInputInfo *dmxInput = p; - int i; - + int i; + dmxLog(dmxInfo, "Returning from VT %d\n", dmxInput->vt_switched); if (!dmxInput->vt_switched) @@ -629,25 +661,25 @@ static void dmxSwitchReturn(pointer p) dmxInput->vt_switched = 0; } -static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask) +static void +dmxWakeupHandler(pointer blockData, int result, pointer pReadMask) { - DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t)blockData]; - int i; + DMXInputInfo *dmxInput = &dmxInputs[(uintptr_t) blockData]; + int i; if (dmxInput->vt_switch_pending) { dmxLog(dmxInfo, "Switching to VT %d\n", dmxInput->vt_switch_pending); for (i = 0; i < dmxInput->numDevs; i++) if (dmxInput->devs[i]->vt_pre_switch) dmxInput->devs[i]->vt_pre_switch(dmxInput->devs[i]->private); - dmxInput->vt_switched = dmxInput->vt_switch_pending; + dmxInput->vt_switched = dmxInput->vt_switch_pending; dmxInput->vt_switch_pending = 0; for (i = 0; i < dmxInput->numDevs; i++) { if (dmxInput->devs[i]->vt_switch) { dmxSigioDisableInput(); if (!dmxInput->devs[i]->vt_switch(dmxInput->devs[i]->private, dmxInput->vt_switched, - dmxSwitchReturn, - dmxInput)) + dmxSwitchReturn, dmxInput)) dmxSwitchReturn(dmxInput); break; /* Only call one vt_switch routine */ } @@ -656,35 +688,44 @@ static void dmxWakeupHandler(pointer blockData, int result, pointer pReadMask) dmxCollectAll(dmxInput); } -static char *dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal) +static char * +dmxMakeUniqueDeviceName(DMXLocalInputInfoPtr dmxLocal) { - static int k = 0; - static int m = 0; - static int o = 0; + static int k = 0; + static int m = 0; + static int o = 0; static unsigned long dmxGeneration = 0; + #define LEN 32 - char * buf = malloc(LEN); + char *buf = malloc(LEN); if (dmxGeneration != serverGeneration) { - k = m = o = 0; + k = m = o = 0; dmxGeneration = serverGeneration; } switch (dmxLocal->type) { - case DMX_LOCAL_KEYBOARD: snprintf(buf, LEN, "Keyboard%d", k++); break; - case DMX_LOCAL_MOUSE: snprintf(buf, LEN, "Mouse%d", m++); break; - default: snprintf(buf, LEN, "Other%d", o++); break; + case DMX_LOCAL_KEYBOARD: + snprintf(buf, LEN, "Keyboard%d", k++); + break; + case DMX_LOCAL_MOUSE: + snprintf(buf, LEN, "Mouse%d", m++); + break; + default: + snprintf(buf, LEN, "Other%d", o++); + break; } return buf; } -static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal) +static DeviceIntPtr +dmxAddDevice(DMXLocalInputInfoPtr dmxLocal) { DeviceIntPtr pDevice; - Atom atom; - const char *name = NULL; - char *devname; + Atom atom; + const char *name = NULL; + char *devname; DMXInputInfo *dmxInput; if (!dmxLocal) @@ -693,41 +734,41 @@ static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal) if (dmxLocal->sendsCore) { if (dmxLocal->type == DMX_LOCAL_KEYBOARD && !dmxLocalCoreKeyboard) { - dmxLocal->isCore = 1; + dmxLocal->isCore = 1; dmxLocalCoreKeyboard = dmxLocal; - name = "keyboard"; + name = "keyboard"; } if (dmxLocal->type == DMX_LOCAL_MOUSE && !dmxLocalCorePointer) { - dmxLocal->isCore = 1; - dmxLocalCorePointer = dmxLocal; - name = "pointer"; + dmxLocal->isCore = 1; + dmxLocalCorePointer = dmxLocal; + name = "pointer"; } } if (!name) { - name = "extension"; + name = "extension"; } if (!name) dmxLog(dmxFatal, "Cannot add device %s\n", dmxLocal->name); - pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE); + pDevice = AddInputDevice(serverClient, dmxDeviceOnOff, TRUE); if (!pDevice) { dmxLog(dmxError, "Too many devices -- cannot add device %s\n", dmxLocal->name); return NULL; } pDevice->public.devicePrivate = dmxLocal; - dmxLocal->pDevice = pDevice; + dmxLocal->pDevice = pDevice; - devname = dmxMakeUniqueDeviceName(dmxLocal); - atom = MakeAtom((char *)devname, strlen(devname), TRUE); + devname = dmxMakeUniqueDeviceName(dmxLocal); + atom = MakeAtom((char *) devname, strlen(devname), TRUE); pDevice->type = atom; pDevice->name = devname; if (dmxLocal->isCore && dmxLocal->type == DMX_LOCAL_MOUSE) { -#if 00 /*BP*/ - miRegisterPointerDevice(screenInfo.screens[0], pDevice); +#if 00 /*BP*/ + miRegisterPointerDevice(screenInfo.screens[0], pDevice); #else /* Nothing? dmxDeviceOnOff() should get called to init, right? */ #endif @@ -740,60 +781,62 @@ static DeviceIntPtr dmxAddDevice(DMXLocalInputInfoPtr dmxLocal) dmxLocal->name, name, devname, dmxLocal->isCore ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); + : (dmxLocal->sendsCore ? " [sends core events]" : "")); return pDevice; } -static DMXLocalInputInfoPtr dmxLookupLocal(const char *name) +static DMXLocalInputInfoPtr +dmxLookupLocal(const char *name) { DMXLocalInputInfoPtr pt; - + for (pt = &DMXLocalDevices[0]; pt->name; ++pt) - if (!strcmp(pt->name, name)) return pt; /* search for device name */ + if (!strcmp(pt->name, name)) + return pt; /* search for device name */ return NULL; } /** Copy the local input information from \a s into a new \a devs slot * in \a dmxInput. */ -DMXLocalInputInfoPtr dmxInputCopyLocal(DMXInputInfo *dmxInput, - DMXLocalInputInfoPtr s) +DMXLocalInputInfoPtr +dmxInputCopyLocal(DMXInputInfo * dmxInput, DMXLocalInputInfoPtr s) { DMXLocalInputInfoPtr dmxLocal = malloc(sizeof(*dmxLocal)); - + if (!dmxLocal) dmxLog(dmxFatal, "DMXLocalInputInfoPtr: out of memory\n"); memcpy(dmxLocal, s, sizeof(*dmxLocal)); - dmxLocal->inputIdx = dmxInput->inputIdx; - dmxLocal->sendsCore = dmxInput->core; + dmxLocal->inputIdx = dmxInput->inputIdx; + dmxLocal->sendsCore = dmxInput->core; dmxLocal->savedSendsCore = dmxInput->core; - dmxLocal->deviceId = -1; + dmxLocal->deviceId = -1; ++dmxInput->numDevs; dmxInput->devs = realloc(dmxInput->devs, - dmxInput->numDevs * sizeof(*dmxInput->devs)); - dmxInput->devs[dmxInput->numDevs-1] = dmxLocal; - + dmxInput->numDevs * sizeof(*dmxInput->devs)); + dmxInput->devs[dmxInput->numDevs - 1] = dmxLocal; + return dmxLocal; } -static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a) +static void +dmxPopulateLocal(DMXInputInfo * dmxInput, dmxArg a) { - int i; - int help = 0; + int i; + int help = 0; DMXLocalInputInfoRec *pt; for (i = 1; i < dmxArgC(a); i++) { const char *name = dmxArgV(a, i); + if ((pt = dmxLookupLocal(name))) { dmxInputCopyLocal(dmxInput, pt); - } else { + } + else { if (strlen(name)) - dmxLog(dmxWarning, - "Could not find a driver called %s\n", name); + dmxLog(dmxWarning, "Could not find a driver called %s\n", name); ++help; } } @@ -801,10 +844,17 @@ static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a) dmxLog(dmxInfo, "Available local device drivers:\n"); for (pt = &DMXLocalDevices[0]; pt->name; ++pt) { const char *type; + switch (pt->type) { - case DMX_LOCAL_KEYBOARD: type = "keyboard"; break; - case DMX_LOCAL_MOUSE: type = "pointer"; break; - default: type = "unknown"; break; + case DMX_LOCAL_KEYBOARD: + type = "keyboard"; + break; + case DMX_LOCAL_MOUSE: + type = "pointer"; + break; + default: + type = "unknown"; + break; } dmxLog(dmxInfo, " %s (%s)\n", pt->name, type); } @@ -812,30 +862,35 @@ static void dmxPopulateLocal(DMXInputInfo *dmxInput, dmxArg a) } } -int dmxInputExtensionErrorHandler(Display *dsp, _Xconst char *name, _Xconst char *reason) +int +dmxInputExtensionErrorHandler(Display * dsp, _Xconst char *name, + _Xconst char *reason) { return 0; } -static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI) +static void +dmxInputScanForExtensions(DMXInputInfo * dmxInput, int doXI) { - XExtensionVersion *ext; - XDeviceInfo *devices; - Display *display; - int num; - int i, j; - XextErrorHandler handler; - - if (!(display = XOpenDisplay(dmxInput->name))) return; - + XExtensionVersion *ext; + XDeviceInfo *devices; + Display *display; + int num; + int i, j; + XextErrorHandler handler; + + if (!(display = XOpenDisplay(dmxInput->name))) + return; + /* Print out information about the XInput Extension. */ handler = XSetExtensionErrorHandler(dmxInputExtensionErrorHandler); - ext = XGetExtensionVersion(display, INAME); + ext = XGetExtensionVersion(display, INAME); XSetExtensionErrorHandler(handler); - - if (!ext || ext == (XExtensionVersion *)NoSuchExtension) { + + if (!ext || ext == (XExtensionVersion *) NoSuchExtension) { dmxLogInput(dmxInput, "%s is not available\n", INAME); - } else { + } + else { dmxLogInput(dmxInput, "Locating devices on %s (%s version %d.%d)\n", dmxInput->name, INAME, ext->major_version, ext->minor_version); @@ -844,31 +899,41 @@ static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI) XFree(ext); ext = NULL; - /* Print a list of all devices */ + /* Print a list of all devices */ for (i = 0; i < num; i++) { const char *use = "Unknown"; + switch (devices[i].use) { - case IsXPointer: use = "XPointer"; break; - case IsXKeyboard: use = "XKeyboard"; break; - case IsXExtensionDevice: use = "XExtensionDevice"; break; - case IsXExtensionPointer: use = "XExtensionPointer"; break; - case IsXExtensionKeyboard: use = "XExtensionKeyboard"; break; + case IsXPointer: + use = "XPointer"; + break; + case IsXKeyboard: + use = "XKeyboard"; + break; + case IsXExtensionDevice: + use = "XExtensionDevice"; + break; + case IsXExtensionPointer: + use = "XExtensionPointer"; + break; + case IsXExtensionKeyboard: + use = "XExtensionKeyboard"; + break; } dmxLogInput(dmxInput, " %2d %-10.10s %-16.16s\n", devices[i].id, - devices[i].name ? devices[i].name : "", - use); + devices[i].name ? devices[i].name : "", use); } - /* Search for extensions */ + /* Search for extensions */ for (i = 0; i < num; i++) { switch (devices[i].use) { case IsXKeyboard: for (j = 0; j < dmxInput->numDevs; j++) { DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; - if (dmxL->type == DMX_LOCAL_KEYBOARD - && dmxL->deviceId < 0) { - dmxL->deviceId = devices[i].id; + + if (dmxL->type == DMX_LOCAL_KEYBOARD && dmxL->deviceId < 0) { + dmxL->deviceId = devices[i].id; dmxL->deviceName = (devices[i].name ? strdup(devices[i].name) : NULL); @@ -878,8 +943,9 @@ static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI) case IsXPointer: for (j = 0; j < dmxInput->numDevs; j++) { DMXLocalInputInfoPtr dmxL = dmxInput->devs[j]; + if (dmxL->type == DMX_LOCAL_MOUSE && dmxL->deviceId < 0) { - dmxL->deviceId = devices[i].id; + dmxL->deviceId = devices[i].id; dmxL->deviceName = (devices[i].name ? xstrdup(devices[i].name) : NULL); @@ -895,12 +961,14 @@ static void dmxInputScanForExtensions(DMXInputInfo *dmxInput, int doXI) /** Re-initialize all the devices described in \a dmxInput. Called from #dmxAdjustCursorBoundaries before the cursor is redisplayed. */ -void dmxInputReInit(DMXInputInfo *dmxInput) +void +dmxInputReInit(DMXInputInfo * dmxInput) { int i; for (i = 0; i < dmxInput->numDevs; i++) { DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + if (dmxLocal->reinit) dmxLocal->reinit(&dmxLocal->pDevice->public); } @@ -908,28 +976,31 @@ void dmxInputReInit(DMXInputInfo *dmxInput) /** Re-initialize all the devices described in \a dmxInput. Called from #dmxAdjustCursorBoundaries after the cursor is redisplayed. */ -void dmxInputLateReInit(DMXInputInfo *dmxInput) +void +dmxInputLateReInit(DMXInputInfo * dmxInput) { int i; for (i = 0; i < dmxInput->numDevs; i++) { DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + if (dmxLocal->latereinit) dmxLocal->latereinit(&dmxLocal->pDevice->public); } } /** Initialize all of the devices described in \a dmxInput. */ -void dmxInputInit(DMXInputInfo *dmxInput) +void +dmxInputInit(DMXInputInfo * dmxInput) { - DeviceIntPtr pPointer = NULL, pKeyboard = NULL; - dmxArg a; - const char *name; - int i; - int doXI = 1; /* Include by default */ - int forceConsole = 0; - int doWindows = 1; /* On by default */ - int hasXkb = 0; + DeviceIntPtr pPointer = NULL, pKeyboard = NULL; + dmxArg a; + const char *name; + int i; + int doXI = 1; /* Include by default */ + int forceConsole = 0; + int doWindows = 1; /* On by default */ + int hasXkb = 0; a = dmxArgParse(dmxInput->name); @@ -940,7 +1011,7 @@ void dmxInputInit(DMXInputInfo *dmxInput) ++hasXkb; break; case 2: - dmxInput->symbols = xstrdup(dmxArgV(a, i)); + dmxInput->symbols = xstrdup(dmxArgV(a, i)); ++hasXkb; break; case 3: @@ -948,16 +1019,22 @@ void dmxInputInit(DMXInputInfo *dmxInput) hasXkb = 0; break; case 0: - if (!strcmp(dmxArgV(a, i), "noxi")) doXI = 0; - else if (!strcmp(dmxArgV(a, i), "xi")) doXI = 1; - else if (!strcmp(dmxArgV(a, i), "console")) forceConsole = 1; - else if (!strcmp(dmxArgV(a, i), "noconsole")) forceConsole = 0; - else if (!strcmp(dmxArgV(a, i), "windows")) doWindows = 1; - else if (!strcmp(dmxArgV(a, i), "nowindows")) doWindows = 0; - else if (!strcmp(dmxArgV(a, i), "xkb")) hasXkb = 1; + if (!strcmp(dmxArgV(a, i), "noxi")) + doXI = 0; + else if (!strcmp(dmxArgV(a, i), "xi")) + doXI = 1; + else if (!strcmp(dmxArgV(a, i), "console")) + forceConsole = 1; + else if (!strcmp(dmxArgV(a, i), "noconsole")) + forceConsole = 0; + else if (!strcmp(dmxArgV(a, i), "windows")) + doWindows = 1; + else if (!strcmp(dmxArgV(a, i), "nowindows")) + doWindows = 0; + else if (!strcmp(dmxArgV(a, i), "xkb")) + hasXkb = 1; else { - dmxLog(dmxFatal, - "Unknown input argument: %s\n", dmxArgV(a, i)); + dmxLog(dmxFatal, "Unknown input argument: %s\n", dmxArgV(a, i)); } } } @@ -966,11 +1043,13 @@ void dmxInputInit(DMXInputInfo *dmxInput) if (!strcmp(name, "local")) { dmxPopulateLocal(dmxInput, a); - } else if (!strcmp(name, "dummy")) { + } + else if (!strcmp(name, "dummy")) { dmxInputCopyLocal(dmxInput, &DMXDummyMou); dmxInputCopyLocal(dmxInput, &DMXDummyKbd); dmxLogInput(dmxInput, "Using dummy input\n"); - } else { + } + else { int found; for (found = 0, i = 0; i < dmxNumScreens; i++) { @@ -983,10 +1062,13 @@ void dmxInputInit(DMXInputInfo *dmxInput) dmxLog(dmxWarning, "Cannot use core devices on a backend (%s)" " as XInput devices\n", name); - } else { + } + else { char *pt; - for (pt = (char *)dmxInput->name; pt && *pt; pt++) - if (*pt == ',') *pt = '\0'; + + for (pt = (char *) dmxInput->name; pt && *pt; pt++) + if (*pt == ',') + *pt = '\0'; dmxInputCopyLocal(dmxInput, &DMXBackendMou); dmxInputCopyLocal(dmxInput, &DMXBackendKbd); dmxInput->scrnIdx = i; @@ -999,13 +1081,16 @@ void dmxInputInit(DMXInputInfo *dmxInput) } if (!found || forceConsole) { char *pt; - if (found) dmxInput->console = TRUE; - for (pt = (char *)dmxInput->name; pt && *pt; pt++) - if (*pt == ',') *pt = '\0'; + + if (found) + dmxInput->console = TRUE; + for (pt = (char *) dmxInput->name; pt && *pt; pt++) + if (*pt == ',') + *pt = '\0'; dmxInputCopyLocal(dmxInput, &DMXConsoleMou); dmxInputCopyLocal(dmxInput, &DMXConsoleKbd); if (doWindows) { - dmxInput->windows = TRUE; + dmxInput->windows = TRUE; dmxInput->updateWindowInfo = dmxUpdateWindowInformation; } dmxLogInput(dmxInput, @@ -1016,50 +1101,56 @@ void dmxInputInit(DMXInputInfo *dmxInput) dmxArgFree(a); - /* Locate extensions we may be interested in */ + /* Locate extensions we may be interested in */ dmxInputScanForExtensions(dmxInput, doXI); - + for (i = 0; i < dmxInput->numDevs; i++) { DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + dmxLocal->pDevice = dmxAddDevice(dmxLocal); if (dmxLocal->isCore) { if (dmxLocal->type == DMX_LOCAL_MOUSE) - pPointer = dmxLocal->pDevice; + pPointer = dmxLocal->pDevice; if (dmxLocal->type == DMX_LOCAL_KEYBOARD) pKeyboard = dmxLocal->pDevice; } } - - dmxInput->processInputEvents = dmxProcessInputEvents; - dmxInput->detached = False; - + + dmxInput->processInputEvents = dmxProcessInputEvents; + dmxInput->detached = False; + RegisterBlockAndWakeupHandlers(dmxBlockHandler, dmxWakeupHandler, - (void *)(uintptr_t)dmxInput->inputIdx); + (void *) (uintptr_t) dmxInput->inputIdx); } -static void dmxInputFreeLocal(DMXLocalInputInfoRec *local) +static void +dmxInputFreeLocal(DMXLocalInputInfoRec * local) { - if (!local) return; + if (!local) + return; if (local->isCore && local->type == DMX_LOCAL_MOUSE) - dmxLocalCorePointer = NULL; + dmxLocalCorePointer = NULL; if (local->isCore && local->type == DMX_LOCAL_KEYBOARD) dmxLocalCoreKeyboard = NULL; - if (local->destroy_private) local->destroy_private(local->private); + if (local->destroy_private) + local->destroy_private(local->private); free(local->history); free(local->valuators); free(local->deviceName); - local->private = NULL; - local->history = NULL; + local->private = NULL; + local->history = NULL; local->deviceName = NULL; free(local); } /** Free all of the memory associated with \a dmxInput */ -void dmxInputFree(DMXInputInfo *dmxInput) +void +dmxInputFree(DMXInputInfo * dmxInput) { int i; - - if (!dmxInput) return; + + if (!dmxInput) + return; free(dmxInput->keycodes); free(dmxInput->symbols); @@ -1070,14 +1161,16 @@ void dmxInputFree(DMXInputInfo *dmxInput) dmxInput->devs[i] = NULL; } free(dmxInput->devs); - dmxInput->devs = NULL; + dmxInput->devs = NULL; dmxInput->numDevs = 0; - if (dmxInput->freename) free(dmxInput->name); - dmxInput->name = NULL; + if (dmxInput->freename) + free(dmxInput->name); + dmxInput->name = NULL; } /** Log information about all of the known devices using #dmxLog(). */ -void dmxInputLogDevices(void) +void +dmxInputLogDevices(void) { int i, j; @@ -1085,34 +1178,43 @@ void dmxInputLogDevices(void) dmxLog(dmxInfo, " Id Name Classes\n"); for (j = 0; j < dmxNumInputs; j++) { DMXInputInfo *dmxInput = &dmxInputs[j]; - const char *pt = strchr(dmxInput->name, ','); - int len = (pt - ? (size_t)(pt-dmxInput->name) - : strlen(dmxInput->name)); + const char *pt = strchr(dmxInput->name, ','); + int len = (pt ? (size_t) (pt - dmxInput->name) + : strlen(dmxInput->name)); for (i = 0; i < dmxInput->numDevs; i++) { DeviceIntPtr pDevice = dmxInput->devs[i]->pDevice; + if (pDevice) { dmxLog(dmxInfo, " %2d%c %-20.20s", pDevice->id, - dmxInput->detached ? 'D' : ' ', - pDevice->name); - if (pDevice->key) dmxLogCont(dmxInfo, " key"); - if (pDevice->valuator) dmxLogCont(dmxInfo, " val"); - if (pDevice->button) dmxLogCont(dmxInfo, " btn"); - if (pDevice->focus) dmxLogCont(dmxInfo, " foc"); - if (pDevice->kbdfeed) dmxLogCont(dmxInfo, " fb/kbd"); - if (pDevice->ptrfeed) dmxLogCont(dmxInfo, " fb/ptr"); - if (pDevice->intfeed) dmxLogCont(dmxInfo, " fb/int"); - if (pDevice->stringfeed) dmxLogCont(dmxInfo, " fb/str"); - if (pDevice->bell) dmxLogCont(dmxInfo, " fb/bel"); - if (pDevice->leds) dmxLogCont(dmxInfo, " fb/led"); + dmxInput->detached ? 'D' : ' ', pDevice->name); + if (pDevice->key) + dmxLogCont(dmxInfo, " key"); + if (pDevice->valuator) + dmxLogCont(dmxInfo, " val"); + if (pDevice->button) + dmxLogCont(dmxInfo, " btn"); + if (pDevice->focus) + dmxLogCont(dmxInfo, " foc"); + if (pDevice->kbdfeed) + dmxLogCont(dmxInfo, " fb/kbd"); + if (pDevice->ptrfeed) + dmxLogCont(dmxInfo, " fb/ptr"); + if (pDevice->intfeed) + dmxLogCont(dmxInfo, " fb/int"); + if (pDevice->stringfeed) + dmxLogCont(dmxInfo, " fb/str"); + if (pDevice->bell) + dmxLogCont(dmxInfo, " fb/bel"); + if (pDevice->leds) + dmxLogCont(dmxInfo, " fb/led"); if (!pDevice->key && !pDevice->valuator && !pDevice->button && !pDevice->focus && !pDevice->kbdfeed && !pDevice->ptrfeed && !pDevice->intfeed - && !pDevice->stringfeed && !pDevice->bell - && !pDevice->leds) dmxLogCont(dmxInfo, " (none)"); - + && !pDevice->stringfeed && !pDevice->bell && !pDevice->leds) + dmxLogCont(dmxInfo, " (none)"); + dmxLogCont(dmxInfo, "\t[i%d/%*.*s", dmxInput->inputIdx, len, len, dmxInput->name); if (dmxInput->devs[i]->deviceId >= 0) @@ -1123,30 +1225,30 @@ void dmxInputLogDevices(void) dmxInput->devs[i]->isCore ? "core" : (dmxInput->devs[i]->sendsCore - ? "extension (sends core events)" - : "extension")); + ? "extension (sends core events)" : "extension")); } } } } /** Detach an input */ -int dmxInputDetach(DMXInputInfo *dmxInput) +int +dmxInputDetach(DMXInputInfo * dmxInput) { int i; - if (dmxInput->detached) return BadAccess; - + if (dmxInput->detached) + return BadAccess; + for (i = 0; i < dmxInput->numDevs; i++) { DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; + dmxLogInput(dmxInput, "Detaching device id %d: %s%s\n", dmxLocal->pDevice->id, dmxLocal->pDevice->name, dmxLocal->isCore ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); + : (dmxLocal->sendsCore ? " [sends core events]" : "")); DisableDevice(dmxLocal->pDevice, TRUE); } dmxInput->detached = True; @@ -1155,116 +1257,133 @@ int dmxInputDetach(DMXInputInfo *dmxInput) } /** Search for input associated with \a dmxScreen, and detach. */ -void dmxInputDetachAll(DMXScreenInfo *dmxScreen) +void +dmxInputDetachAll(DMXScreenInfo * dmxScreen) { int i; for (i = 0; i < dmxNumInputs; i++) { DMXInputInfo *dmxInput = &dmxInputs[i]; - if (dmxInput->scrnIdx == dmxScreen->index) dmxInputDetach(dmxInput); + + if (dmxInput->scrnIdx == dmxScreen->index) + dmxInputDetach(dmxInput); } } /** Search for input associated with \a deviceId, and detach. */ -int dmxInputDetachId(int id) +int +dmxInputDetachId(int id) { DMXInputInfo *dmxInput = dmxInputLocateId(id); - if (!dmxInput) return BadValue; - + if (!dmxInput) + return BadValue; + return dmxInputDetach(dmxInput); } -DMXInputInfo *dmxInputLocateId(int id) +DMXInputInfo * +dmxInputLocateId(int id) { int i, j; - + for (i = 0; i < dmxNumInputs; i++) { DMXInputInfo *dmxInput = &dmxInputs[i]; + for (j = 0; j < dmxInput->numDevs; j++) { DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j]; - if (dmxLocal->pDevice->id == id) return dmxInput; + + if (dmxLocal->pDevice->id == id) + return dmxInput; } } return NULL; } -static int dmxInputAttachNew(DMXInputInfo *dmxInput, int *id) +static int +dmxInputAttachNew(DMXInputInfo * dmxInput, int *id) { dmxInputInit(dmxInput); InitAndStartDevices(); - if (id && dmxInput->devs) *id = dmxInput->devs[0]->pDevice->id; + if (id && dmxInput->devs) + *id = dmxInput->devs[0]->pDevice->id; dmxInputLogDevices(); return 0; } -static int dmxInputAttachOld(DMXInputInfo *dmxInput, int *id) +static int +dmxInputAttachOld(DMXInputInfo * dmxInput, int *id) { int i; - + dmxInput->detached = False; for (i = 0; i < dmxInput->numDevs; i++) { DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[i]; - if (id) *id = dmxLocal->pDevice->id; + + if (id) + *id = dmxLocal->pDevice->id; dmxLogInput(dmxInput, "Attaching device id %d: %s%s\n", dmxLocal->pDevice->id, dmxLocal->pDevice->name, dmxLocal->isCore ? " [core]" - : (dmxLocal->sendsCore - ? " [sends core events]" - : "")); + : (dmxLocal->sendsCore ? " [sends core events]" : "")); EnableDevice(dmxLocal->pDevice, TRUE); } dmxInputLogDevices(); return 0; } -int dmxInputAttachConsole(const char *name, int isCore, int *id) +int +dmxInputAttachConsole(const char *name, int isCore, int *id) { - DMXInputInfo *dmxInput; - int i; + DMXInputInfo *dmxInput; + int i; for (i = 0; i < dmxNumInputs; i++) { dmxInput = &dmxInputs[i]; if (dmxInput->scrnIdx == -1 - && dmxInput->detached - && !strcmp(dmxInput->name, name)) { - /* Found match */ + && dmxInput->detached && !strcmp(dmxInput->name, name)) { + /* Found match */ dmxLogInput(dmxInput, "Reattaching detached console input\n"); return dmxInputAttachOld(dmxInput, id); } } - /* No match found */ + /* No match found */ dmxInput = dmxConfigAddInput(xstrdup(name), isCore); dmxInput->freename = TRUE; dmxLogInput(dmxInput, "Attaching new console input\n"); return dmxInputAttachNew(dmxInput, id); } -int dmxInputAttachBackend(int physicalScreen, int isCore, int *id) +int +dmxInputAttachBackend(int physicalScreen, int isCore, int *id) { - DMXInputInfo *dmxInput; + DMXInputInfo *dmxInput; DMXScreenInfo *dmxScreen; - int i; - - if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) return BadValue; + int i; + + if (physicalScreen < 0 || physicalScreen >= dmxNumScreens) + return BadValue; for (i = 0; i < dmxNumInputs; i++) { dmxInput = &dmxInputs[i]; if (dmxInput->scrnIdx != -1 && dmxInput->scrnIdx == physicalScreen) { - /* Found match */ - if (!dmxInput->detached) return BadAccess; /* Already attached */ + /* Found match */ + if (!dmxInput->detached) + return BadAccess; /* Already attached */ dmxScreen = &dmxScreens[physicalScreen]; - if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ + if (!dmxScreen->beDisplay) + return BadAccess; /* Screen detached */ dmxLogInput(dmxInput, "Reattaching detached backend input\n"); return dmxInputAttachOld(dmxInput, id); } } - /* No match found */ + /* No match found */ dmxScreen = &dmxScreens[physicalScreen]; - if (!dmxScreen->beDisplay) return BadAccess; /* Screen detached */ + if (!dmxScreen->beDisplay) + return BadAccess; /* Screen detached */ dmxInput = dmxConfigAddInput(dmxScreen->name, isCore); dmxLogInput(dmxInput, "Attaching new backend input\n"); return dmxInputAttachNew(dmxInput, id); diff --git a/xorg-server/hw/dmx/input/dmxinputinit.h b/xorg-server/hw/dmx/input/dmxinputinit.h index d23ad7a38..94ec1019b 100644 --- a/xorg-server/hw/dmx/input/dmxinputinit.h +++ b/xorg-server/hw/dmx/input/dmxinputinit.h @@ -1,291 +1,284 @@ -/*
- * 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
+/* + * 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/dmxmap.c b/xorg-server/hw/dmx/input/dmxmap.c index 1eccd3d28..1a8d4c937 100644 --- a/xorg-server/hw/dmx/input/dmxmap.c +++ b/xorg-server/hw/dmx/input/dmxmap.c @@ -59,15 +59,16 @@ * remoteEvent is the type returned from the remote server. The \a * serverEvent is from the XI_* list of events in * include/extensions/XIproto.h. */ -void dmxMapInsert(DMXLocalInputInfoPtr dmxLocal, - int remoteEvent, int serverEvent) +void +dmxMapInsert(DMXLocalInputInfoPtr dmxLocal, int remoteEvent, int serverEvent) { int hash = remoteEvent & DMX_MAP_MASK; int i; - /* Return if this has already been mapped */ + /* Return if this has already been mapped */ if (dmxLocal->map[hash].remote == remoteEvent - && dmxLocal->map[hash].server == serverEvent) return; + && dmxLocal->map[hash].server == serverEvent) + return; if (dmxLocal->map[hash].remote) { dmxLocal->mapOptimize = 0; @@ -81,18 +82,21 @@ void dmxMapInsert(DMXLocalInputInfoPtr dmxLocal, dmxLog(dmxWarning, "Out of map entries, cannot map remove event type %d\n", remoteEvent); - } else { + } + else { dmxLocal->map[hash].remote = remoteEvent; dmxLocal->map[hash].server = serverEvent; } } /** Remove all mappings there were inserted with #dmxMapInsert. */ -void dmxMapClear(DMXLocalInputInfoPtr dmxLocal) +void +dmxMapClear(DMXLocalInputInfoPtr dmxLocal) { int i; - for (i = 0; i < DMX_MAP_ENTRIES; i++) dmxLocal->map[i].remote = 0; + for (i = 0; i < DMX_MAP_ENTRIES; i++) + dmxLocal->map[i].remote = 0; dmxLocal->mapOptimize = 1; } @@ -100,16 +104,18 @@ void dmxMapClear(DMXLocalInputInfoPtr dmxLocal) * returned from the remote server. The return value is that which was * passed into #dmxMapInsert (i.e., a value from the XI_* list in * include/extensions/XIproto.h). If a mapping is not available, -1 is - * returned. */ -int dmxMapLookup(DMXLocalInputInfoPtr dmxLocal, int remoteEvent) + * returned. */ +int +dmxMapLookup(DMXLocalInputInfoPtr dmxLocal, int remoteEvent) { - int hash = remoteEvent & DMX_MAP_MASK; + int hash = remoteEvent & DMX_MAP_MASK; int serverEvent = -1; int i; if (dmxLocal->mapOptimize && dmxLocal->map[hash].remote == remoteEvent) { serverEvent = dmxLocal->map[hash].server; - } else { + } + else { for (i = 0; i < DMX_MAP_ENTRIES; i++) if (dmxLocal->map[i].remote == remoteEvent) { serverEvent = dmxLocal->map[hash].server; diff --git a/xorg-server/hw/dmx/input/dmxmotion.c b/xorg-server/hw/dmx/input/dmxmotion.c index 7a4b8a0dc..1642894a2 100644 --- a/xorg-server/hw/dmx/input/dmxmotion.c +++ b/xorg-server/hw/dmx/input/dmxmotion.c @@ -1,141 +1,149 @@ -/*
- * 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
- * This file provides functions similar to miPointerGetMotionEvents and
- * miPointerPutMotionEvents, with the exception that devices with more
- * than two axes are fully supported. These routines may be used only
- * for motion buffers for extension devices, and are \a not compatible
- * replacements for the mi routines. */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "inputstr.h"
-#include "dmxinputinit.h"
-#include "dmxcommon.h"
-#include "dmxmotion.h"
-
-#define OFFSET(offset,element) ((offset) * (numAxes + 1) + (element))
-
-/** Return size of motion buffer. \see DMX_MOTION_SIZE */
-int dmxPointerGetMotionBufferSize(void)
-{
- return DMX_MOTION_SIZE;
-}
-
-/** This routine performs the same function as \a miPointerGetMotionEvents:
- * the events in the motion history that are between the start and stop
- * times (in mS) are placed in the coords vector, and the count of the
- * number of items so placed is returned. This routine is called from
- * dix/devices.c so that coords can hold valuator->numMotionEvents
- * events. This routine is called from \a Xi/gtmotion.c with coords large
- * enough to hold the same number of events in a variable-length
- * extended \a xTimecoord structure. This provides sufficient data for the
- * \a XGetDeviceMotionEvents library call, and would be identical to
- * \a miPointerGetMotionEvents for devices with only 2 axes (i.e., core
- * pointers) if \a xTimecoord used 32bit integers.
- *
- * Because DMX uses the mi* routines for all core devices, this routine
- * only has to support extension devices using the polymorphic coords.
- * Because compatibility with miPointerGetMotionEvents is not possible,
- * it is not provided. */
-int dmxPointerGetMotionEvents(DeviceIntPtr pDevice,
- xTimecoord *coords,
- unsigned long start,
- unsigned long stop,
- ScreenPtr pScreen)
-{
- GETDMXLOCALFROMPDEVICE;
- int numAxes = pDevice->valuator->numAxes;
- unsigned long *c = (unsigned long *)coords;
- int count = 0;
- int i, j;
-
- if (!dmxLocal->history) return 0;
- for (i = dmxLocal->head; i != dmxLocal->tail;) {
- if (dmxLocal->history[OFFSET(i,0)] >= stop) break;
- if (dmxLocal->history[OFFSET(i,0)] >= start) {
- for (j = 0; j < numAxes + 1; j++)
- c[OFFSET(count,j)] = dmxLocal->history[OFFSET(i,j)];
- ++count;
- }
- if (++i >= DMX_MOTION_SIZE) i = 0;
- }
- return count;
-}
-
-/** This routine adds an event to the motion history. A similar
- * function is performed by miPointerMove for the mi versions of these
- * routines. */
-void dmxPointerPutMotionEvent(DeviceIntPtr pDevice,
- int firstAxis, int axesCount, int *v,
- unsigned long time)
-{
- GETDMXLOCALFROMPDEVICE;
- int numAxes = pDevice->valuator->numAxes;
- int i;
-
- if (!dmxLocal->history) {
- dmxLocal->history = malloc(sizeof(*dmxLocal->history)
- * (numAxes + 1)
- * DMX_MOTION_SIZE);
- dmxLocal->head = 0;
- dmxLocal->tail = 0;
- dmxLocal->valuators = calloc(sizeof(*dmxLocal->valuators), numAxes);
- } else {
- if (++dmxLocal->tail >= DMX_MOTION_SIZE) dmxLocal->tail = 0;
- if (dmxLocal->head == dmxLocal->tail)
- if (++dmxLocal->head >= DMX_MOTION_SIZE) dmxLocal->head = 0;
- }
-
- dmxLocal->history[OFFSET(dmxLocal->tail,0)] = time;
-
- /* Initialize the data from the known
- * values (if Absolute) or to zero (if
- * Relative) */
- for (i = 0; i < numAxes; i++) {
- if (pDevice->valuator->axes[i].mode == Absolute)
- dmxLocal->history[OFFSET(dmxLocal->tail,i+1)]
- = dmxLocal->valuators[i];
- else
- dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0;
- }
-
- for (i = firstAxis; i < axesCount; i++) {
- dmxLocal->history[OFFSET(dmxLocal->tail,i+i)]
- = (unsigned long)v[i-firstAxis];
- dmxLocal->valuators[i] = v[i-firstAxis];
- }
-}
+/* + * 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 + * This file provides functions similar to miPointerGetMotionEvents and + * miPointerPutMotionEvents, with the exception that devices with more + * than two axes are fully supported. These routines may be used only + * for motion buffers for extension devices, and are \a not compatible + * replacements for the mi routines. */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "inputstr.h" +#include "dmxinputinit.h" +#include "dmxcommon.h" +#include "dmxmotion.h" + +#define OFFSET(offset,element) ((offset) * (numAxes + 1) + (element)) + +/** Return size of motion buffer. \see DMX_MOTION_SIZE */ +int +dmxPointerGetMotionBufferSize(void) +{ + return DMX_MOTION_SIZE; +} + +/** This routine performs the same function as \a miPointerGetMotionEvents: + * the events in the motion history that are between the start and stop + * times (in mS) are placed in the coords vector, and the count of the + * number of items so placed is returned. This routine is called from + * dix/devices.c so that coords can hold valuator->numMotionEvents + * events. This routine is called from \a Xi/gtmotion.c with coords large + * enough to hold the same number of events in a variable-length + * extended \a xTimecoord structure. This provides sufficient data for the + * \a XGetDeviceMotionEvents library call, and would be identical to + * \a miPointerGetMotionEvents for devices with only 2 axes (i.e., core + * pointers) if \a xTimecoord used 32bit integers. + * + * Because DMX uses the mi* routines for all core devices, this routine + * only has to support extension devices using the polymorphic coords. + * Because compatibility with miPointerGetMotionEvents is not possible, + * it is not provided. */ +int +dmxPointerGetMotionEvents(DeviceIntPtr pDevice, + xTimecoord * coords, + unsigned long start, + unsigned long stop, ScreenPtr pScreen) +{ + GETDMXLOCALFROMPDEVICE; + int numAxes = pDevice->valuator->numAxes; + unsigned long *c = (unsigned long *) coords; + int count = 0; + int i, j; + + if (!dmxLocal->history) + return 0; + for (i = dmxLocal->head; i != dmxLocal->tail;) { + if (dmxLocal->history[OFFSET(i, 0)] >= stop) + break; + if (dmxLocal->history[OFFSET(i, 0)] >= start) { + for (j = 0; j < numAxes + 1; j++) + c[OFFSET(count, j)] = dmxLocal->history[OFFSET(i, j)]; + ++count; + } + if (++i >= DMX_MOTION_SIZE) + i = 0; + } + return count; +} + +/** This routine adds an event to the motion history. A similar + * function is performed by miPointerMove for the mi versions of these + * routines. */ +void +dmxPointerPutMotionEvent(DeviceIntPtr pDevice, + int firstAxis, int axesCount, int *v, + unsigned long time) +{ + GETDMXLOCALFROMPDEVICE; + int numAxes = pDevice->valuator->numAxes; + int i; + + if (!dmxLocal->history) { + dmxLocal->history = malloc(sizeof(*dmxLocal->history) + * (numAxes + 1) + * DMX_MOTION_SIZE); + dmxLocal->head = 0; + dmxLocal->tail = 0; + dmxLocal->valuators = calloc(sizeof(*dmxLocal->valuators), numAxes); + } + else { + if (++dmxLocal->tail >= DMX_MOTION_SIZE) + dmxLocal->tail = 0; + if (dmxLocal->head == dmxLocal->tail) + if (++dmxLocal->head >= DMX_MOTION_SIZE) + dmxLocal->head = 0; + } + + dmxLocal->history[OFFSET(dmxLocal->tail, 0)] = time; + + /* Initialize the data from the known + * values (if Absolute) or to zero (if + * Relative) */ + for (i = 0; i < numAxes; i++) { + if (pDevice->valuator->axes[i].mode == Absolute) + dmxLocal->history[OFFSET(dmxLocal->tail, i + 1)] + = dmxLocal->valuators[i]; + else + dmxLocal->history[OFFSET(dmxLocal->tail, i + 1)] = 0; + } + + for (i = firstAxis; i < axesCount; i++) { + dmxLocal->history[OFFSET(dmxLocal->tail, i + i)] + = (unsigned long) v[i - firstAxis]; + dmxLocal->valuators[i] = v[i - firstAxis]; + } +} diff --git a/xorg-server/hw/dmx/input/dmxmotion.h b/xorg-server/hw/dmx/input/dmxmotion.h index 88aeb3d09..5ccdbe4ad 100644 --- a/xorg-server/hw/dmx/input/dmxmotion.h +++ b/xorg-server/hw/dmx/input/dmxmotion.h @@ -37,12 +37,11 @@ #ifndef _DMXMOTION_H_ #define _DMXMOTION_H_ -extern int dmxPointerGetMotionBufferSize(void); -extern int dmxPointerGetMotionEvents(DeviceIntPtr pDevice, - xTimecoord *coords, - unsigned long start, - unsigned long stop, - ScreenPtr pScreen); +extern int dmxPointerGetMotionBufferSize(void); +extern int dmxPointerGetMotionEvents(DeviceIntPtr pDevice, + xTimecoord * coords, + unsigned long start, + unsigned long stop, ScreenPtr pScreen); extern void dmxPointerPutMotionEvent(DeviceIntPtr pDevice, int firstAxis, int axesCount, int *v, unsigned long time); diff --git a/xorg-server/hw/dmx/input/dmxsigio.c b/xorg-server/hw/dmx/input/dmxsigio.c index 03c3070d7..9b1b493b8 100644 --- a/xorg-server/hw/dmx/input/dmxsigio.c +++ b/xorg-server/hw/dmx/input/dmxsigio.c @@ -47,36 +47,37 @@ #include <unistd.h> #include <fcntl.h> -static int dmxFdCount = 0; +static int dmxFdCount = 0; static Bool dmxInputEnabled = TRUE; /* Define equivalents for non-POSIX systems (e.g., SGI IRIX, Solaris) */ #ifndef O_ASYNC -# ifdef FASYNC -# define O_ASYNC FASYNC -# else -# define O_ASYNC 0 -# endif +#ifdef FASYNC +#define O_ASYNC FASYNC +#else +#define O_ASYNC 0 +#endif #endif #ifndef O_NONBLOCK #define O_NONBLOCK FNONBLK #endif -static void dmxSigioHandler(int sig) +static void +dmxSigioHandler(int sig) { - int i, j; + int i, j; DMXInputInfo *dmxInput; for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) { if (dmxInput->sigioState == DMX_ACTIVESIGIO) { for (j = 0; j < dmxInput->numDevs; j++) { DMXLocalInputInfoPtr dmxLocal = dmxInput->devs[j]; + if (dmxLocal->collect_events) { dmxLocal->collect_events(&dmxLocal->pDevice->public, dmxMotion, dmxEnqueue, - dmxCheckSpecialKeys, - DMX_NO_BLOCK); + dmxCheckSpecialKeys, DMX_NO_BLOCK); } } } @@ -84,7 +85,8 @@ static void dmxSigioHandler(int sig) } /** Block SIGIO handling. */ -void dmxSigioBlock(void) +void +dmxSigioBlock(void) { sigset_t s; @@ -94,7 +96,8 @@ void dmxSigioBlock(void) } /** Unblock SIGIO handling. */ -void dmxSigioUnblock(void) +void +dmxSigioUnblock(void) { sigset_t s; @@ -103,10 +106,11 @@ void dmxSigioUnblock(void) sigprocmask(SIG_UNBLOCK, &s, 0); } -static void dmxSigioHook(void) +static void +dmxSigioHook(void) { struct sigaction a; - sigset_t s; + sigset_t s; memset(&a, 0, sizeof(a)); a.sa_handler = dmxSigioHandler; @@ -115,81 +119,95 @@ static void dmxSigioHook(void) sigaddset(&a.sa_mask, SIGALRM); sigaddset(&a.sa_mask, SIGVTALRM); sigaction(SIGIO, &a, 0); - + sigemptyset(&s); sigprocmask(SIG_SETMASK, &s, 0); } -static void dmxSigioUnhook(void) +static void +dmxSigioUnhook(void) { struct sigaction a; - memset (&a, 0, sizeof(a)); + memset(&a, 0, sizeof(a)); a.sa_handler = SIG_IGN; sigemptyset(&a.sa_mask); sigaction(SIGIO, &a, 0); } -static void dmxSigioAdd(DMXInputInfo *dmxInput) +static void +dmxSigioAdd(DMXInputInfo * dmxInput) { int flags; int i; switch (dmxInput->sigioState) { - case DMX_NOSIGIO: return; - case DMX_USESIGIO: dmxInput->sigioState = DMX_ACTIVESIGIO; break; - case DMX_ACTIVESIGIO: return; + case DMX_NOSIGIO: + return; + case DMX_USESIGIO: + dmxInput->sigioState = DMX_ACTIVESIGIO; + break; + case DMX_ACTIVESIGIO: + return; } for (i = 0; i < dmxInput->sigioFdCount; i++) { if (!dmxInput->sigioAdded[i]) { int fd = dmxInput->sigioFd[i]; - + fcntl(fd, F_SETOWN, getpid()); flags = fcntl(fd, F_GETFL); - flags |= O_ASYNC|O_NONBLOCK; + flags |= O_ASYNC | O_NONBLOCK; fcntl(fd, F_SETFL, flags); - + AddEnabledDevice(fd); dmxInput->sigioAdded[i] = TRUE; - if (++dmxFdCount == 1) dmxSigioHook(); + if (++dmxFdCount == 1) + dmxSigioHook(); } } } -static void dmxSigioRemove(DMXInputInfo *dmxInput) +static void +dmxSigioRemove(DMXInputInfo * dmxInput) { int flags; int i; - + switch (dmxInput->sigioState) { - case DMX_NOSIGIO: return; - case DMX_USESIGIO: return; - case DMX_ACTIVESIGIO: dmxInput->sigioState = DMX_USESIGIO; break; + case DMX_NOSIGIO: + return; + case DMX_USESIGIO: + return; + case DMX_ACTIVESIGIO: + dmxInput->sigioState = DMX_USESIGIO; + break; } for (i = 0; i < dmxInput->sigioFdCount; i++) { if (dmxInput->sigioAdded[i]) { int fd = dmxInput->sigioFd[i]; - + dmxInput->sigioAdded[i] = FALSE; RemoveEnabledDevice(fd); - + flags = fcntl(fd, F_GETFL); - flags &= ~(O_ASYNC|O_NONBLOCK); + flags &= ~(O_ASYNC | O_NONBLOCK); fcntl(fd, F_SETFL, flags); - if (!--dmxFdCount) dmxSigioUnhook(); + if (!--dmxFdCount) + dmxSigioUnhook(); } } } /** Enable SIGIO handling. This instantiates the handler with the OS. */ -void dmxSigioEnableInput(void) +void +dmxSigioEnableInput(void) { - int i; - DMXInputInfo *dmxInput; + int i; + DMXInputInfo *dmxInput; dmxInputEnabled = TRUE; for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) @@ -197,10 +215,11 @@ void dmxSigioEnableInput(void) } /** Disable SIGIO handling. This removes the hanlder from the OS. */ -void dmxSigioDisableInput(void) +void +dmxSigioDisableInput(void) { - int i; - DMXInputInfo *dmxInput; + int i; + DMXInputInfo *dmxInput; dmxInputEnabled = FALSE; for (i = 0, dmxInput = &dmxInputs[0]; i < dmxNumInputs; i++, dmxInput++) @@ -211,23 +230,27 @@ void dmxSigioDisableInput(void) * using the file descriptor \a fd for SIGIO signals. Calls * AddEnabledDevice ifi SIGIO handling has been enabled with * #dmxSigioEnableInput(). */ -void dmxSigioRegister(DMXInputInfo *dmxInput, int fd) +void +dmxSigioRegister(DMXInputInfo * dmxInput, int fd) { dmxInput->sigioState = DMX_USESIGIO; if (dmxInput->sigioFdCount >= DMX_MAX_SIGIO_FDS) dmxLog(dmxFatal, "Too many SIGIO file descriptors (%d >= %d)\n", dmxInput->sigioFdCount, DMX_MAX_SIGIO_FDS); - + dmxInput->sigioFd[dmxInput->sigioFdCount++] = fd; - if (dmxInputEnabled) dmxSigioAdd(dmxInput); + if (dmxInputEnabled) + dmxSigioAdd(dmxInput); } /** Remove the notes that \a dmxInput is using any file descriptors for * SIGIO signals. Calls RemoveEnabledDevice. */ -void dmxSigioUnregister(DMXInputInfo *dmxInput) +void +dmxSigioUnregister(DMXInputInfo * dmxInput) { - if (dmxInput->sigioState == DMX_NOSIGIO) return; + if (dmxInput->sigioState == DMX_NOSIGIO) + return; dmxSigioRemove(dmxInput); - dmxInput->sigioState = DMX_NOSIGIO; + dmxInput->sigioState = DMX_NOSIGIO; dmxInput->sigioFdCount = 0; } diff --git a/xorg-server/hw/dmx/input/dmxxinput.c b/xorg-server/hw/dmx/input/dmxxinput.c index b28a80d4d..fccab5ff1 100644 --- a/xorg-server/hw/dmx/input/dmxxinput.c +++ b/xorg-server/hw/dmx/input/dmxxinput.c @@ -1,76 +1,75 @@ -/*
- * 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
- *
- * This file implements support required by the XINPUT extension.
- */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "inputstr.h"
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "XIstubs.h"
-
-#include "mipointer.h"
-#include "dmxinputinit.h"
-#include "exevents.h"
-
-/** Set device mode to \a mode. This is not implemented. */
-int SetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode)
-{
- return BadMatch;
-}
-
-/** Set device valuators. This is not implemented. */
-int SetDeviceValuators (ClientPtr client,
- DeviceIntPtr dev,
- int *valuators,
- int first_valuator,
- int num_valuators)
-{
- return BadMatch;
-}
-
-/** Change device control. This is not implemented. */
-int ChangeDeviceControl(ClientPtr client,
- DeviceIntPtr dev,
- xDeviceCtl *control)
-{
- return BadMatch;
-}
+/* + * 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 + * + * This file implements support required by the XINPUT extension. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "inputstr.h" +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "XIstubs.h" + +#include "mipointer.h" +#include "dmxinputinit.h" +#include "exevents.h" + +/** Set device mode to \a mode. This is not implemented. */ +int +SetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode) +{ + return BadMatch; +} + +/** Set device valuators. This is not implemented. */ +int +SetDeviceValuators(ClientPtr client, + DeviceIntPtr dev, + int *valuators, int first_valuator, int num_valuators) +{ + return BadMatch; +} + +/** Change device control. This is not implemented. */ +int +ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev, xDeviceCtl * control) +{ + return BadMatch; +} diff --git a/xorg-server/hw/dmx/input/lnx-keyboard.c b/xorg-server/hw/dmx/input/lnx-keyboard.c index 06e9ec722..ecf4f591c 100644 --- a/xorg-server/hw/dmx/input/lnx-keyboard.c +++ b/xorg-server/hw/dmx/input/lnx-keyboard.c @@ -172,26 +172,25 @@ #define NUM_AT2LNX (sizeof(at2lnx) / sizeof(at2lnx[0])) #define NUM_STATE_ENTRIES (256/32) - /* Private area for Linux-style keyboards. */ typedef struct _myPrivate { - int fd; - int vtno; - int vtcurrent; - int kbdtrans; + int fd; + int vtno; + int vtcurrent; + int kbdtrans; struct termios kbdtty; - int kbdType; - CARD32 kbdState[NUM_STATE_ENTRIES]; - DeviceIntPtr pKeyboard; - unsigned char prefix; - - int switched; - SWITCHRETPROC switch_return; - void *switch_return_data; - - /* For bell */ - int pitch; - unsigned long duration; + int kbdType; + CARD32 kbdState[NUM_STATE_ENTRIES]; + DeviceIntPtr pKeyboard; + unsigned char prefix; + + int switched; + SWITCHRETPROC switch_return; + void *switch_return_data; + + /* For bell */ + int pitch; + unsigned long duration; } myPrivate; static myPrivate *PRIV = NULL; @@ -199,174 +198,182 @@ static myPrivate *PRIV = NULL; #undef SYSCALL #define SYSCALL(call) while(((call) == -1) && (errno == EINTR)) -static int kbdLinuxKeyDown(myPrivate *priv, int keyCode) +static int +kbdLinuxKeyDown(myPrivate * priv, int keyCode) { - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); - if (byte > NUM_STATE_ENTRIES) return 0; + if (byte > NUM_STATE_ENTRIES) + return 0; return priv->kbdState[byte] & bit; } -static void kbdLinuxKeyState(myPrivate *priv, int type, int keyCode) +static void +kbdLinuxKeyState(myPrivate * priv, int type, int keyCode) { - CARD8 byte = keyCode >> 5; - CARD32 bit = 1 << (keyCode & 0x1f); - - if (byte > NUM_STATE_ENTRIES) return; - if (type == KeyPress) priv->kbdState[byte] |= bit; - else priv->kbdState[byte] &= ~bit; + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); + + if (byte > NUM_STATE_ENTRIES) + return; + if (type == KeyPress) + priv->kbdState[byte] |= bit; + else + priv->kbdState[byte] &= ~bit; } static KeySym linux_to_x[256] = { - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, XK_Escape, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_space, XK_exclam, XK_quotedbl, XK_numbersign, - XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, - XK_parenleft, XK_parenright, XK_asterisk, XK_plus, - XK_comma, XK_minus, XK_period, XK_slash, - XK_0, XK_1, XK_2, XK_3, - XK_4, XK_5, XK_6, XK_7, - XK_8, XK_9, XK_colon, XK_semicolon, - XK_less, XK_equal, XK_greater, XK_question, - XK_at, XK_A, XK_B, XK_C, - XK_D, XK_E, XK_F, XK_G, - XK_H, XK_I, XK_J, XK_K, - XK_L, XK_M, XK_N, XK_O, - XK_P, XK_Q, XK_R, XK_S, - XK_T, XK_U, XK_V, XK_W, - XK_X, XK_Y, XK_Z, XK_bracketleft, - XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore, - XK_grave, XK_a, XK_b, XK_c, - XK_d, XK_e, XK_f, XK_g, - XK_h, XK_i, XK_j, XK_k, - XK_l, XK_m, XK_n, XK_o, - XK_p, XK_q, XK_r, XK_s, - XK_t, XK_u, XK_v, XK_w, - XK_x, XK_y, XK_z, XK_braceleft, - XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - NoSymbol, NoSymbol, NoSymbol, NoSymbol, - XK_nobreakspace,XK_exclamdown, XK_cent, XK_sterling, - XK_currency, XK_yen, XK_brokenbar, XK_section, - XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, - XK_notsign, XK_hyphen, XK_registered, XK_macron, - XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, - XK_acute, XK_mu, XK_paragraph, XK_periodcentered, - XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, - XK_onequarter, XK_onehalf, XK_threequarters,XK_questiondown, - XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, - XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, - XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, - XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, - XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, - XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, - XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, - XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, - XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, - XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, - XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, - XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, - XK_eth, XK_ntilde, XK_ograve, XK_oacute, - XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, - XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, - XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, XK_Escape, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_space, XK_exclam, XK_quotedbl, XK_numbersign, + XK_dollar, XK_percent, XK_ampersand, XK_apostrophe, + XK_parenleft, XK_parenright, XK_asterisk, XK_plus, + XK_comma, XK_minus, XK_period, XK_slash, + XK_0, XK_1, XK_2, XK_3, + XK_4, XK_5, XK_6, XK_7, + XK_8, XK_9, XK_colon, XK_semicolon, + XK_less, XK_equal, XK_greater, XK_question, + XK_at, XK_A, XK_B, XK_C, + XK_D, XK_E, XK_F, XK_G, + XK_H, XK_I, XK_J, XK_K, + XK_L, XK_M, XK_N, XK_O, + XK_P, XK_Q, XK_R, XK_S, + XK_T, XK_U, XK_V, XK_W, + XK_X, XK_Y, XK_Z, XK_bracketleft, + XK_backslash, XK_bracketright, XK_asciicircum, XK_underscore, + XK_grave, XK_a, XK_b, XK_c, + XK_d, XK_e, XK_f, XK_g, + XK_h, XK_i, XK_j, XK_k, + XK_l, XK_m, XK_n, XK_o, + XK_p, XK_q, XK_r, XK_s, + XK_t, XK_u, XK_v, XK_w, + XK_x, XK_y, XK_z, XK_braceleft, + XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + NoSymbol, NoSymbol, NoSymbol, NoSymbol, + XK_nobreakspace, XK_exclamdown, XK_cent, XK_sterling, + XK_currency, XK_yen, XK_brokenbar, XK_section, + XK_diaeresis, XK_copyright, XK_ordfeminine, XK_guillemotleft, + XK_notsign, XK_hyphen, XK_registered, XK_macron, + XK_degree, XK_plusminus, XK_twosuperior, XK_threesuperior, + XK_acute, XK_mu, XK_paragraph, XK_periodcentered, + XK_cedilla, XK_onesuperior, XK_masculine, XK_guillemotright, + XK_onequarter, XK_onehalf, XK_threequarters, XK_questiondown, + XK_Agrave, XK_Aacute, XK_Acircumflex, XK_Atilde, + XK_Adiaeresis, XK_Aring, XK_AE, XK_Ccedilla, + XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis, + XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis, + XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute, + XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_multiply, + XK_Ooblique, XK_Ugrave, XK_Uacute, XK_Ucircumflex, + XK_Udiaeresis, XK_Yacute, XK_THORN, XK_ssharp, + XK_agrave, XK_aacute, XK_acircumflex, XK_atilde, + XK_adiaeresis, XK_aring, XK_ae, XK_ccedilla, + XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis, + XK_igrave, XK_iacute, XK_icircumflex, XK_idiaeresis, + XK_eth, XK_ntilde, XK_ograve, XK_oacute, + XK_ocircumflex, XK_otilde, XK_odiaeresis, XK_division, + XK_oslash, XK_ugrave, XK_uacute, XK_ucircumflex, + XK_udiaeresis, XK_yacute, XK_thorn, XK_ydiaeresis }; /* * Maps the AT keycodes to Linux keycodes */ -static unsigned char at2lnx[NUM_KEYCODES] = -{ - 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ - 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ - 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ - 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ - 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ - 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ - 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ - 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ - 0x11, /* KEY_W */ 0x12, /* KEY_E */ - 0x13, /* KEY_R */ 0x14, /* KEY_T */ - 0x15, /* KEY_Y */ 0x16, /* KEY_U */ - 0x17, /* KEY_I */ 0x18, /* KEY_O */ - 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ - 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ - 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ - 0x1f, /* KEY_S */ 0x20, /* KEY_D */ - 0x21, /* KEY_F */ 0x22, /* KEY_G */ - 0x23, /* KEY_H */ 0x24, /* KEY_J */ - 0x25, /* KEY_K */ 0x26, /* KEY_L */ - 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ - 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ - 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ - 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ - 0x2f, /* KEY_V */ 0x30, /* KEY_B */ - 0x31, /* KEY_N */ 0x32, /* KEY_M */ - 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ - 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ - 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ - 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ - 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ - 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ - 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ - 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ - 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ - 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ - 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ - 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ - 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ - 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ - 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ - 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ - 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ - 0x00, /* 0x55 */ 0x56, /* KEY_Less */ - 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ - 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ - 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ - 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ - 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ - 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ - 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ - 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ - 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ - 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ - 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ - 0x7A, /* KEY_Menu/FOCUS_PF11*/0x00, /* 0x6e */ - 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ - 0x00, /* 0x71 */ 0x00, /* 0x72 */ - 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ - 0x00, /* 0x75 */ 0x00, /* 0x76 */ - 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ - 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ - 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ - 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ - 0x00, /* 0x7f */ +static unsigned char at2lnx[NUM_KEYCODES] = { + 0x01, /* KEY_Escape */ 0x02, /* KEY_1 */ + 0x03, /* KEY_2 */ 0x04, /* KEY_3 */ + 0x05, /* KEY_4 */ 0x06, /* KEY_5 */ + 0x07, /* KEY_6 */ 0x08, /* KEY_7 */ + 0x09, /* KEY_8 */ 0x0a, /* KEY_9 */ + 0x0b, /* KEY_0 */ 0x0c, /* KEY_Minus */ + 0x0d, /* KEY_Equal */ 0x0e, /* KEY_BackSpace */ + 0x0f, /* KEY_Tab */ 0x10, /* KEY_Q */ + 0x11, /* KEY_W */ 0x12, /* KEY_E */ + 0x13, /* KEY_R */ 0x14, /* KEY_T */ + 0x15, /* KEY_Y */ 0x16, /* KEY_U */ + 0x17, /* KEY_I */ 0x18, /* KEY_O */ + 0x19, /* KEY_P */ 0x1a, /* KEY_LBrace */ + 0x1b, /* KEY_RBrace */ 0x1c, /* KEY_Enter */ + 0x1d, /* KEY_LCtrl */ 0x1e, /* KEY_A */ + 0x1f, /* KEY_S */ 0x20, /* KEY_D */ + 0x21, /* KEY_F */ 0x22, /* KEY_G */ + 0x23, /* KEY_H */ 0x24, /* KEY_J */ + 0x25, /* KEY_K */ 0x26, /* KEY_L */ + 0x27, /* KEY_SemiColon */ 0x28, /* KEY_Quote */ + 0x29, /* KEY_Tilde */ 0x2a, /* KEY_ShiftL */ + 0x2b, /* KEY_BSlash */ 0x2c, /* KEY_Z */ + 0x2d, /* KEY_X */ 0x2e, /* KEY_C */ + 0x2f, /* KEY_V */ 0x30, /* KEY_B */ + 0x31, /* KEY_N */ 0x32, /* KEY_M */ + 0x33, /* KEY_Comma */ 0x34, /* KEY_Period */ + 0x35, /* KEY_Slash */ 0x36, /* KEY_ShiftR */ + 0x37, /* KEY_KP_Multiply */ 0x38, /* KEY_Alt */ + 0x39, /* KEY_Space */ 0x3a, /* KEY_CapsLock */ + 0x3b, /* KEY_F1 */ 0x3c, /* KEY_F2 */ + 0x3d, /* KEY_F3 */ 0x3e, /* KEY_F4 */ + 0x3f, /* KEY_F5 */ 0x40, /* KEY_F6 */ + 0x41, /* KEY_F7 */ 0x42, /* KEY_F8 */ + 0x43, /* KEY_F9 */ 0x44, /* KEY_F10 */ + 0x45, /* KEY_NumLock */ 0x46, /* KEY_ScrollLock */ + 0x47, /* KEY_KP_7 */ 0x48, /* KEY_KP_8 */ + 0x49, /* KEY_KP_9 */ 0x4a, /* KEY_KP_Minus */ + 0x4b, /* KEY_KP_4 */ 0x4c, /* KEY_KP_5 */ + 0x4d, /* KEY_KP_6 */ 0x4e, /* KEY_KP_Plus */ + 0x4f, /* KEY_KP_1 */ 0x50, /* KEY_KP_2 */ + 0x51, /* KEY_KP_3 */ 0x52, /* KEY_KP_0 */ + 0x53, /* KEY_KP_Decimal */ 0x54, /* KEY_SysReqest */ + 0x00, /* 0x55 */ 0x56, /* KEY_Less */ + 0x57, /* KEY_F11 */ 0x58, /* KEY_F12 */ + 0x66, /* KEY_Home */ 0x67, /* KEY_Up */ + 0x68, /* KEY_PgUp */ 0x69, /* KEY_Left */ + 0x5d, /* KEY_Begin */ 0x6a, /* KEY_Right */ + 0x6b, /* KEY_End */ 0x6c, /* KEY_Down */ + 0x6d, /* KEY_PgDown */ 0x6e, /* KEY_Insert */ + 0x6f, /* KEY_Delete */ 0x60, /* KEY_KP_Enter */ + 0x61, /* KEY_RCtrl */ 0x77, /* KEY_Pause */ + 0x63, /* KEY_Print */ 0x62, /* KEY_KP_Divide */ + 0x64, /* KEY_AltLang */ 0x65, /* KEY_Break */ + 0x00, /* KEY_LMeta */ 0x00, /* KEY_RMeta */ + 0x7A, /* KEY_Menu/FOCUS_PF11 */ 0x00, /* 0x6e */ + 0x7B, /* FOCUS_PF12 */ 0x00, /* 0x70 */ + 0x00, /* 0x71 */ 0x00, /* 0x72 */ + 0x59, /* FOCUS_PF2 */ 0x78, /* FOCUS_PF9 */ + 0x00, /* 0x75 */ 0x00, /* 0x76 */ + 0x5A, /* FOCUS_PF3 */ 0x5B, /* FOCUS_PF4 */ + 0x5C, /* FOCUS_PF5 */ 0x5D, /* FOCUS_PF6 */ + 0x5E, /* FOCUS_PF7 */ 0x5F, /* FOCUS_PF8 */ + 0x7C, /* JAP_86 */ 0x79, /* FOCUS_PF10 */ + 0x00, /* 0x7f */ }; /** Create a private structure for use within this file. */ -pointer kbdLinuxCreatePrivate(DeviceIntPtr pKeyboard) +pointer +kbdLinuxCreatePrivate(DeviceIntPtr pKeyboard) { myPrivate *priv = calloc(1, sizeof(*priv)); - priv->fd = -1; + + priv->fd = -1; priv->pKeyboard = pKeyboard; return priv; } /** Destroy a private structure. */ -void kbdLinuxDestroyPrivate(pointer priv) +void +kbdLinuxDestroyPrivate(pointer priv) { free(priv); } @@ -387,36 +394,37 @@ void kbdLinuxDestroyPrivate(pointer priv) * if we ignore the volume and set the duration correctly, then we'll * get one parameter "wrong" -- but if we use the volume to scale the * duration, then we'll get both parameters "wrong"). */ -void kbdLinuxBell(DevicePtr pDev, int percent, - int volume, int pitch, int duration) +void +kbdLinuxBell(DevicePtr pDev, int percent, int volume, int pitch, int duration) { GETPRIV; if (duration && pitch) { - ioctl(priv->fd, - KDMKTONE, - ((1193190 / pitch) & 0xffff) /* Low bits specify cycle time */ - | (duration << 16)); /* High bits are duration in msec */ + ioctl(priv->fd, KDMKTONE, ((1193190 / pitch) & 0xffff) /* Low bits specify cycle time */ + |(duration << 16)); /* High bits are duration in msec */ } } /** Set the LEDs. */ -void kbdLinuxCtrl(DevicePtr pDev, KeybdCtrl *ctrl) +void +kbdLinuxCtrl(DevicePtr pDev, KeybdCtrl * ctrl) { GETPRIV; ioctl(priv->fd, KDSETLED, ctrl->leds & 0x07); } -static int kbdLinuxGetFreeVTNumber(void) +static int +kbdLinuxGetFreeVTNumber(void) { - int fd = -1; - int vtno; - int i; + int fd = -1; + int vtno; + int i; const char *tty0[] = { "/dev/tty0", "/dev/vc/0", NULL }; - + for (i = 0; tty0[i]; i++) - if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) break; + if ((fd = open(tty0[i], O_WRONLY, 0)) >= 0) + break; if (fd < 0) FATAL1("kbdLinuxGetFreeVTNumber: Cannot open tty0 (%s)\n", strerror(errno)); @@ -425,16 +433,18 @@ static int kbdLinuxGetFreeVTNumber(void) return vtno; } -static int kbdLinuxOpenVT(int vtno) +static int +kbdLinuxOpenVT(int vtno) { - int fd = -1; - int i; + int fd = -1; + int i; const char *vcs[] = { "/dev/vc/", "/dev/tty", NULL }; - char name[64]; /* RATS: Only used in snprintf */ + char name[64]; /* RATS: Only used in snprintf */ for (i = 0; vcs[i]; i++) { snprintf(name, sizeof(name), "%s%d", vcs[i], vtno); - if ((fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) break; + if ((fd = open(name, O_RDWR | O_NONBLOCK, 0)) >= 0) + break; } if (fd < 0) FATAL2("kbdLinuxOpenVT: Cannot open VT %d (%s)\n", @@ -442,23 +452,27 @@ static int kbdLinuxOpenVT(int vtno) return fd; } -static int kbdLinuxGetCurrentVTNumber(int fd) +static int +kbdLinuxGetCurrentVTNumber(int fd) { struct vt_stat vts; - - if (!ioctl(fd, VT_GETSTATE, &vts)) return vts.v_active; + + if (!ioctl(fd, VT_GETSTATE, &vts)) + return vts.v_active; return -1; } static int kbdLinuxActivate(int fd, int vtno, int setSig); /** Currently unused hook called prior to an VT switch. */ -void kbdLinuxVTPreSwitch(pointer p) +void +kbdLinuxVTPreSwitch(pointer p) { } /** Currently unused hook called after returning from a VT switch. */ -void kbdLinuxVTPostSwitch(pointer p) +void +kbdLinuxVTPostSwitch(pointer p) { } @@ -466,28 +480,31 @@ void kbdLinuxVTPostSwitch(pointer p) * function is called with the \a switch_return_data when the VT is * switched back to the pre-switch VT (i.e., the user returns to the DMX * session). */ -int kbdLinuxVTSwitch(pointer p, int vt, - void (*switch_return)(pointer), - pointer switch_return_data) +int +kbdLinuxVTSwitch(pointer p, int vt, + void (*switch_return) (pointer), pointer switch_return_data) { myPrivate *priv = p; - if (priv->switched) FATAL0("kbdLinuxVTSwitch: already switched...\n"); - if (priv->vtno == vt) return 0; + if (priv->switched) + FATAL0("kbdLinuxVTSwitch: already switched...\n"); + if (priv->vtno == vt) + return 0; - PRIV = priv; - priv->switched = 0; /* Will switch to 1 in handler */ - priv->switch_return = switch_return; + PRIV = priv; + priv->switched = 0; /* Will switch to 1 in handler */ + priv->switch_return = switch_return; priv->switch_return_data = switch_return_data; kbdLinuxActivate(priv->fd, vt, 0); return 1; } /* RATS: This function is only ever used to handle SIGUSR1. */ -static void kbdLinuxVTSignalHandler(int sig) +static void +kbdLinuxVTSignalHandler(int sig) { myPrivate *priv = PRIV; - + signal(sig, kbdLinuxVTSignalHandler); if (priv) { ioctl(priv->fd, VT_RELDISP, VT_ACKACQ); @@ -499,19 +516,23 @@ static void kbdLinuxVTSignalHandler(int sig) } } -static int kbdLinuxActivate(int fd, int vtno, int setSig) +static int +kbdLinuxActivate(int fd, int vtno, int setSig) { - int result; + int result; struct vt_mode VT; SYSCALL(result = ioctl(fd, VT_ACTIVATE, vtno)); - if (result) FATAL0("kbdLinuxActivate: VT_ACTIVATE failed\n"); + if (result) + FATAL0("kbdLinuxActivate: VT_ACTIVATE failed\n"); SYSCALL(result = ioctl(fd, VT_WAITACTIVE, vtno)); - if (result) FATAL0("kbdLinuxActivate: VT_WAITACTIVE failed\n"); + if (result) + FATAL0("kbdLinuxActivate: VT_WAITACTIVE failed\n"); if (setSig) { SYSCALL(result = ioctl(fd, VT_GETMODE, &VT)); - if (result < 0) FATAL0("kbdLinuxActivate: VT_GETMODE failed\n"); - VT.mode = VT_PROCESS; + if (result < 0) + FATAL0("kbdLinuxActivate: VT_GETMODE failed\n"); + VT.mode = VT_PROCESS; VT.relsig = SIGUSR1; VT.acqsig = SIGUSR1; if (ioctl(fd, VT_SETMODE, &VT)) @@ -521,86 +542,148 @@ static int kbdLinuxActivate(int fd, int vtno, int setSig) return Success; } -static void kbdLinuxOpenConsole(DevicePtr pDev) +static void +kbdLinuxOpenConsole(DevicePtr pDev) { GETPRIV; const char *msg = MESSAGE; - if (priv->fd >= 0) return; - priv->vtno = kbdLinuxGetFreeVTNumber(); - priv->fd = kbdLinuxOpenVT(priv->vtno); + if (priv->fd >= 0) + return; + priv->vtno = kbdLinuxGetFreeVTNumber(); + priv->fd = kbdLinuxOpenVT(priv->vtno); priv->vtcurrent = kbdLinuxGetCurrentVTNumber(priv->fd); LOG2("kbdLinuxOpenConsole: current VT %d; using free VT %d\n", priv->vtcurrent, priv->vtno); kbdLinuxActivate(priv->fd, priv->vtno, 1); - ioctl(priv->fd, KDSETMODE, KD_GRAPHICS); /* To turn off gpm */ - if (msg) write(priv->fd, msg, strlen(msg)); + ioctl(priv->fd, KDSETMODE, KD_GRAPHICS); /* To turn off gpm */ + if (msg) + write(priv->fd, msg, strlen(msg)); } -static void kbdLinuxCloseConsole(DevicePtr pDev) +static void +kbdLinuxCloseConsole(DevicePtr pDev) { GETPRIV; struct vt_mode VT; - const char *msg = FINALMESSAGE; + const char *msg = FINALMESSAGE; - if (priv->fd < 0) return; + if (priv->fd < 0) + return; ioctl(priv->fd, KDSETMODE, KD_TEXT); - if (msg) write(priv->fd, msg, strlen(msg)); + if (msg) + write(priv->fd, msg, strlen(msg)); if (ioctl(priv->fd, VT_GETMODE, &VT) != -1) { VT.mode = VT_AUTO; ioctl(priv->fd, VT_SETMODE, &VT); } LOG1("kbdLinuxCloseConsole: switching to VT %d\n", priv->vtcurrent); - if (priv->vtcurrent >= 0) kbdLinuxActivate(priv->fd, priv->vtcurrent, 0); - + if (priv->vtcurrent >= 0) + kbdLinuxActivate(priv->fd, priv->vtcurrent, 0); + close(priv->fd); priv->fd = -1; } /** Initialize the \a pDev as a Linux keyboard. */ -void kbdLinuxInit(DevicePtr pDev) +void +kbdLinuxInit(DevicePtr pDev) { GETPRIV; - if (priv->fd <= 0) kbdLinuxOpenConsole(pDev); - + if (priv->fd <= 0) + kbdLinuxOpenConsole(pDev); + ioctl(priv->fd, KDGKBMODE, &priv->kbdtrans); if (tcgetattr(priv->fd, &priv->kbdtty) < 0) FATAL1("kbdLinuxInit: tcgetattr failed (%s)\n", strerror(errno)); } -static int kbdLinuxPrefix0Mapping(unsigned char *scanCode) +static int +kbdLinuxPrefix0Mapping(unsigned char *scanCode) { - /* Table from xfree86/common/xf86Events.c */ + /* Table from xfree86/common/xf86Events.c */ switch (*scanCode) { - case KEY_KP_7: *scanCode = KEY_Home; break; /* curs home */ - case KEY_KP_8: *scanCode = KEY_Up; break; /* curs up */ - case KEY_KP_9: *scanCode = KEY_PgUp; break; /* curs pgup */ - case KEY_KP_4: *scanCode = KEY_Left; break; /* curs left */ - case KEY_KP_5: *scanCode = KEY_Begin; break; /* curs begin */ - case KEY_KP_6: *scanCode = KEY_Right; break; /* curs right */ - case KEY_KP_1: *scanCode = KEY_End; break; /* curs end */ - case KEY_KP_2: *scanCode = KEY_Down; break; /* curs down */ - case KEY_KP_3: *scanCode = KEY_PgDown; break; /* curs pgdown */ - case KEY_KP_0: *scanCode = KEY_Insert; break; /* curs insert */ - case KEY_KP_Decimal: *scanCode = KEY_Delete; break; /* curs delete */ - case KEY_Enter: *scanCode = KEY_KP_Enter; break; /* keypad enter */ - case KEY_LCtrl: *scanCode = KEY_RCtrl; break; /* right ctrl */ - case KEY_KP_Multiply: *scanCode = KEY_Print; break; /* print */ - case KEY_Slash: *scanCode = KEY_KP_Divide; break; /* keyp divide */ - case KEY_Alt: *scanCode = KEY_AltLang; break; /* right alt */ - case KEY_ScrollLock: *scanCode = KEY_Break; break; /* curs break */ - case 0x5b: *scanCode = KEY_LMeta; break; - case 0x5c: *scanCode = KEY_RMeta; break; - case 0x5d: *scanCode = KEY_Menu; break; - case KEY_F3: *scanCode = KEY_F13; break; - case KEY_F4: *scanCode = KEY_F14; break; - case KEY_F5: *scanCode = KEY_F15; break; - case KEY_F6: *scanCode = KEY_F16; break; - case KEY_F7: *scanCode = KEY_F17; break; - case KEY_KP_Plus: *scanCode = KEY_KP_DEC; break; + case KEY_KP_7: + *scanCode = KEY_Home; + break; /* curs home */ + case KEY_KP_8: + *scanCode = KEY_Up; + break; /* curs up */ + case KEY_KP_9: + *scanCode = KEY_PgUp; + break; /* curs pgup */ + case KEY_KP_4: + *scanCode = KEY_Left; + break; /* curs left */ + case KEY_KP_5: + *scanCode = KEY_Begin; + break; /* curs begin */ + case KEY_KP_6: + *scanCode = KEY_Right; + break; /* curs right */ + case KEY_KP_1: + *scanCode = KEY_End; + break; /* curs end */ + case KEY_KP_2: + *scanCode = KEY_Down; + break; /* curs down */ + case KEY_KP_3: + *scanCode = KEY_PgDown; + break; /* curs pgdown */ + case KEY_KP_0: + *scanCode = KEY_Insert; + break; /* curs insert */ + case KEY_KP_Decimal: + *scanCode = KEY_Delete; + break; /* curs delete */ + case KEY_Enter: + *scanCode = KEY_KP_Enter; + break; /* keypad enter */ + case KEY_LCtrl: + *scanCode = KEY_RCtrl; + break; /* right ctrl */ + case KEY_KP_Multiply: + *scanCode = KEY_Print; + break; /* print */ + case KEY_Slash: + *scanCode = KEY_KP_Divide; + break; /* keyp divide */ + case KEY_Alt: + *scanCode = KEY_AltLang; + break; /* right alt */ + case KEY_ScrollLock: + *scanCode = KEY_Break; + break; /* curs break */ + case 0x5b: + *scanCode = KEY_LMeta; + break; + case 0x5c: + *scanCode = KEY_RMeta; + break; + case 0x5d: + *scanCode = KEY_Menu; + break; + case KEY_F3: + *scanCode = KEY_F13; + break; + case KEY_F4: + *scanCode = KEY_F14; + break; + case KEY_F5: + *scanCode = KEY_F15; + break; + case KEY_F6: + *scanCode = KEY_F16; + break; + case KEY_F7: + *scanCode = KEY_F17; + break; + case KEY_KP_Plus: + *scanCode = KEY_KP_DEC; + break; /* * Ignore virtual shifts (E0 2A, E0 AA, E0 36, E0 B6) */ @@ -618,12 +701,13 @@ static int kbdLinuxPrefix0Mapping(unsigned char *scanCode) return 0; } -static int kbdLinuxPrefixMapping(myPrivate *priv, unsigned char *scanCode) +static int +kbdLinuxPrefixMapping(myPrivate * priv, unsigned char *scanCode) { - int pressed = *scanCode & 0x80; - unsigned char code = *scanCode & 0x7f; + int pressed = *scanCode & 0x80; + unsigned char code = *scanCode & 0x7f; - /* If we don't have a prefix, check for one */ + /* If we don't have a prefix, check for one */ if (!priv->prefix) { switch (code) { case KEY_Prefix0: @@ -634,43 +718,45 @@ static int kbdLinuxPrefixMapping(myPrivate *priv, unsigned char *scanCode) return 0; /* No change */ } - /* We have a prefix from the last scanCode */ + /* We have a prefix from the last scanCode */ switch (priv->prefix) { case KEY_Prefix0: priv->prefix = 0; - if (kbdLinuxPrefix0Mapping(&code)) return 1; /* Skip sequence */ + if (kbdLinuxPrefix0Mapping(&code)) + return 1; /* Skip sequence */ break; case KEY_Prefix1: priv->prefix = (code = KEY_LCtrl) ? KEY_LCtrl : 0; - return 1; /* Use new prefix */ + return 1; /* Use new prefix */ case KEY_LCtrl: priv->prefix = 0; - if (code != KEY_NumLock) return 1; /* Skip sequence*/ + if (code != KEY_NumLock) + return 1; /* Skip sequence */ code = KEY_Pause; break; } *scanCode = code | (pressed ? 0x80 : 0x00); - return 0; /* Use old scanCode */ + return 0; /* Use old scanCode */ } -static void kbdLinuxConvert(DevicePtr pDev, - unsigned char scanCode, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) +static void +kbdLinuxConvert(DevicePtr pDev, + unsigned char scanCode, + ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) { GETPRIV; - XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; - int type; - KeySym keySym = NoSymbol; - int keyCode; - int switching; + XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; + int type; + KeySym keySym = NoSymbol; + int keyCode; + int switching; /* Do special PC/AT prefix mapping -- may change scanCode! */ - if (kbdLinuxPrefixMapping(priv, &scanCode)) return; + if (kbdLinuxPrefixMapping(priv, &scanCode)) + return; - type = (scanCode & 0x80) ? KeyRelease : KeyPress; + type = (scanCode & 0x80) ? KeyRelease : KeyPress; keyCode = (scanCode & 0x7f) + MIN_KEYCODE; /* Handle repeats */ @@ -681,6 +767,7 @@ static void kbdLinuxConvert(DevicePtr pDev, int effectiveGroup = XkbGetEffectiveGroup(xkbi, &xkbi->state, scanCode); + keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); #if 0 switch (keySym) { @@ -689,9 +776,12 @@ static void kbdLinuxConvert(DevicePtr pDev, case XK_Shift_Lock: case XK_Caps_Lock: /* Ignore releases and all but first press */ - if (kbdLinuxModIgnore(priv, &xE, keySym)) return; - if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease; - else xE.u.u.type = KeyPress; + if (kbdLinuxModIgnore(priv, &xE, keySym)) + return; + if (kbdLinuxKeyDown(priv, &xE)) + xE.u.u.type = KeyRelease; + else + xE.u.u.type = KeyPress; break; } #endif @@ -703,17 +793,18 @@ static void kbdLinuxConvert(DevicePtr pDev, /* No auto-repeat? */ if ((feed && !feed->ctrl.autoRepeat) || priv->pKeyboard->key->xkbInfo->desc->map->modmap[keyCode] - || (feed - && !(feed->ctrl.autoRepeats[keyCode >> 3] - & (1 << (keyCode & 7))))) return; /* Ignore */ - + || (feed && !(feed->ctrl.autoRepeats[keyCode >> 3] + & (1 << (keyCode & 7))))) + return; /* Ignore */ + /* Do auto-repeat */ enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); type = KeyPress; } - + /* If key is already up, ignore */ - if (type == KeyRelease && !kbdLinuxKeyDown(priv, keyCode)) return; + if (type == KeyRelease && !kbdLinuxKeyDown(priv, keyCode)) + return; } switching = 0; @@ -722,7 +813,7 @@ static void kbdLinuxConvert(DevicePtr pDev, if (!switching) { if (enqueue) enqueue(pDev, type, keyCode, keySym, NULL, block); - kbdLinuxKeyState(priv, type, keyCode); /* Update our state bitmap */ + kbdLinuxKeyState(priv, type, keyCode); /* Update our state bitmap */ } } @@ -732,16 +823,15 @@ static void kbdLinuxConvert(DevicePtr pDev, * 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 kbdLinuxRead(DevicePtr pDev, - MOTIONPROC motion, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) +void +kbdLinuxRead(DevicePtr pDev, + MOTIONPROC motion, + ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) { GETPRIV; unsigned char buf[256]; /* RATS: Only used in length-limited call */ unsigned char *pt; - int n; + int n; while ((n = read(priv->fd, buf, sizeof(buf))) > 0) for (pt = buf; n; --n, ++pt) @@ -749,20 +839,21 @@ void kbdLinuxRead(DevicePtr pDev, } /** Turn \a pDev on (i.e., take input from \a pDev). */ -int kbdLinuxOn(DevicePtr pDev) +int +kbdLinuxOn(DevicePtr pDev) { GETPRIV; struct termios nTty; ioctl(priv->fd, KDSKBMODE, K_RAW); - nTty = priv->kbdtty; - nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); - nTty.c_oflag = 0; - nTty.c_cflag = CREAD | CS8; - nTty.c_lflag = 0; + nTty = priv->kbdtty; + nTty.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + nTty.c_oflag = 0; + nTty.c_cflag = CREAD | CS8; + nTty.c_lflag = 0; nTty.c_cc[VTIME] = 0; - nTty.c_cc[VMIN] = 1; + nTty.c_cc[VMIN] = 1; cfsetispeed(&nTty, B9600); cfsetospeed(&nTty, B9600); if (tcsetattr(priv->fd, TCSANOW, &nTty) < 0) @@ -771,7 +862,8 @@ int kbdLinuxOn(DevicePtr pDev) } /** Turn \a pDev off (i.e., stop taking input from \a pDev). */ -void kbdLinuxOff(DevicePtr pDev) +void +kbdLinuxOff(DevicePtr pDev) { GETPRIV; @@ -780,165 +872,261 @@ void kbdLinuxOff(DevicePtr pDev) kbdLinuxCloseConsole(pDev); } - -static void kbdLinuxReadKernelMapping(int fd, KeySymsPtr pKeySyms) +static void +kbdLinuxReadKernelMapping(int fd, KeySymsPtr pKeySyms) { - KeySym *k; - int i; - int maxkey; - static unsigned char tbl[GLYPHS_PER_KEY] = { /* RATS: Use ok */ - 0, /* unshifted */ - 1, /* shifted */ - 0, /* modeswitch unshifted */ - 0 /* modeswitch shifted */ + KeySym *k; + int i; + int maxkey; + + static unsigned char tbl[GLYPHS_PER_KEY] = { /* RATS: Use ok */ + 0, /* unshifted */ + 1, /* shifted */ + 0, /* modeswitch unshifted */ + 0 /* modeswitch shifted */ }; - /* - * Read the mapping from the kernel. - * Since we're still using the XFree86 scancode->AT keycode mapping - * routines, we need to convert the AT keycodes to Linux keycodes, - * then translate the Linux keysyms into X keysyms. - * - * First, figure out which tables to use for the modeswitch columns - * above, from the XF86Config fields. - */ - tbl[2] = 8; /* alt */ - tbl[3] = tbl[2] | 1; - -#if 00/*BP*/ - k = map+GLYPHS_PER_KEY; + /* + * Read the mapping from the kernel. + * Since we're still using the XFree86 scancode->AT keycode mapping + * routines, we need to convert the AT keycodes to Linux keycodes, + * then translate the Linux keysyms into X keysyms. + * + * First, figure out which tables to use for the modeswitch columns + * above, from the XF86Config fields. + */ + tbl[2] = 8; /* alt */ + tbl[3] = tbl[2] | 1; + +#if 00 /*BP*/ + k = map + GLYPHS_PER_KEY; #else - ErrorF("kbdLinuxReadKernelMapping() is broken/no-op'd\n"); - return; + ErrorF("kbdLinuxReadKernelMapping() is broken/no-op'd\n"); + return; #endif - maxkey = NUM_AT2LNX; - - for (i = 0; i < maxkey; ++i) { - struct kbentry kbe; - int j; - - kbe.kb_index = at2lnx[i]; - - for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) { - unsigned short kval; - - *k = NoSymbol; - - kbe.kb_table = tbl[j]; - if (kbe.kb_index == 0 || ioctl(fd, KDGKBENT, &kbe)) continue; - - kval = KVAL(kbe.kb_value); - switch (KTYP(kbe.kb_value)) { - case KT_LATIN: - case KT_LETTER: *k = linux_to_x[kval]; break; - case KT_FN: - if (kval <= 19) *k = XK_F1 + kval; - else switch (kbe.kb_value) { - case K_FIND: *k = XK_Home; /* or XK_Find */ break; - case K_INSERT: *k = XK_Insert; break; - case K_REMOVE: *k = XK_Delete; break; - case K_SELECT: *k = XK_End; /* or XK_Select */ break; - case K_PGUP: *k = XK_Prior; break; - case K_PGDN: *k = XK_Next; break; - case K_HELP: *k = XK_Help; break; - case K_DO: *k = XK_Execute; break; - case K_PAUSE: *k = XK_Pause; break; - case K_MACRO: *k = XK_Menu; break; - default: break; - } - break; - case KT_SPEC: - switch (kbe.kb_value) { - case K_ENTER: *k = XK_Return; break; - case K_BREAK: *k = XK_Break; break; - case K_CAPS: *k = XK_Caps_Lock; break; - case K_NUM: *k = XK_Num_Lock; break; - case K_HOLD: *k = XK_Scroll_Lock; break; - case K_COMPOSE: *k = XK_Multi_key; break; - default: break; - } - break; - case KT_PAD: - switch (kbe.kb_value) { - case K_PPLUS: *k = XK_KP_Add; break; - case K_PMINUS: *k = XK_KP_Subtract; break; - case K_PSTAR: *k = XK_KP_Multiply; break; - case K_PSLASH: *k = XK_KP_Divide; break; - case K_PENTER: *k = XK_KP_Enter; break; - case K_PCOMMA: *k = XK_KP_Separator; break; - case K_PDOT: *k = XK_KP_Decimal; break; - case K_PPLUSMINUS: *k = XK_KP_Subtract; break; - default: if (kval <= 9) *k = XK_KP_0 + kval; break; - } - break; - case KT_DEAD: - /* KT_DEAD keys are for accelerated diacritical creation. */ - switch (kbe.kb_value) { - case K_DGRAVE: *k = XK_dead_grave; break; - case K_DACUTE: *k = XK_dead_acute; break; - case K_DCIRCM: *k = XK_dead_circumflex; break; - case K_DTILDE: *k = XK_dead_tilde; break; - case K_DDIERE: *k = XK_dead_diaeresis; break; - } - break; - case KT_CUR: - switch (kbe.kb_value) { - case K_DOWN: *k = XK_Down; break; - case K_LEFT: *k = XK_Left; break; - case K_RIGHT: *k = XK_Right; break; - case K_UP: *k = XK_Up; break; - } - break; - case KT_SHIFT: - switch (kbe.kb_value) { - case K_ALTGR: *k = XK_Alt_R; break; - case K_ALT: - *k = (kbe.kb_index == 0x64 ? XK_Alt_R : XK_Alt_L); - break; - case K_CTRL: - *k = (kbe.kb_index == 0x61 ? XK_Control_R : XK_Control_L); - break; - case K_CTRLL: *k = XK_Control_L; break; - case K_CTRLR: *k = XK_Control_R; break; - case K_SHIFT: - *k = (kbe.kb_index == 0x36 ? XK_Shift_R : XK_Shift_L); - break; - case K_SHIFTL: *k = XK_Shift_L; break; - case K_SHIFTR: *k = XK_Shift_R; break; - default: break; - } - break; - case KT_ASCII: - /* KT_ASCII keys accumulate a 3 digit decimal number that - * gets emitted when the shift state changes. We can't - * emulate that. - */ - break; - case KT_LOCK: - if (kbe.kb_value == K_SHIFTLOCK) *k = XK_Shift_Lock; - break; - default: break; - } - } - - if (k[-1] == k[-2]) k[-1] = NoSymbol; - if (k[-2] == k[-3]) k[-2] = NoSymbol; - if (k[-3] == k[-4]) k[-3] = NoSymbol; - if (k[-4] == k[-2] && k[-3] == k[-1]) k[-2] = k[-1] = NoSymbol; - if (k[-1] == k[-4] && k[-2] == k[-3] - && k[-2] == NoSymbol) k[-1] = NoSymbol; - } + maxkey = NUM_AT2LNX; + + for (i = 0; i < maxkey; ++i) { + struct kbentry kbe; + int j; + + kbe.kb_index = at2lnx[i]; + + for (j = 0; j < GLYPHS_PER_KEY; ++j, ++k) { + unsigned short kval; + + *k = NoSymbol; + + kbe.kb_table = tbl[j]; + if (kbe.kb_index == 0 || ioctl(fd, KDGKBENT, &kbe)) + continue; + + kval = KVAL(kbe.kb_value); + switch (KTYP(kbe.kb_value)) { + case KT_LATIN: + case KT_LETTER: + *k = linux_to_x[kval]; + break; + case KT_FN: + if (kval <= 19) + *k = XK_F1 + kval; + else + switch (kbe.kb_value) { + case K_FIND: + *k = XK_Home; /* or XK_Find */ + break; + case K_INSERT: + *k = XK_Insert; + break; + case K_REMOVE: + *k = XK_Delete; + break; + case K_SELECT: + *k = XK_End; /* or XK_Select */ + break; + case K_PGUP: + *k = XK_Prior; + break; + case K_PGDN: + *k = XK_Next; + break; + case K_HELP: + *k = XK_Help; + break; + case K_DO: + *k = XK_Execute; + break; + case K_PAUSE: + *k = XK_Pause; + break; + case K_MACRO: + *k = XK_Menu; + break; + default: + break; + } + break; + case KT_SPEC: + switch (kbe.kb_value) { + case K_ENTER: + *k = XK_Return; + break; + case K_BREAK: + *k = XK_Break; + break; + case K_CAPS: + *k = XK_Caps_Lock; + break; + case K_NUM: + *k = XK_Num_Lock; + break; + case K_HOLD: + *k = XK_Scroll_Lock; + break; + case K_COMPOSE: + *k = XK_Multi_key; + break; + default: + break; + } + break; + case KT_PAD: + switch (kbe.kb_value) { + case K_PPLUS: + *k = XK_KP_Add; + break; + case K_PMINUS: + *k = XK_KP_Subtract; + break; + case K_PSTAR: + *k = XK_KP_Multiply; + break; + case K_PSLASH: + *k = XK_KP_Divide; + break; + case K_PENTER: + *k = XK_KP_Enter; + break; + case K_PCOMMA: + *k = XK_KP_Separator; + break; + case K_PDOT: + *k = XK_KP_Decimal; + break; + case K_PPLUSMINUS: + *k = XK_KP_Subtract; + break; + default: + if (kval <= 9) + *k = XK_KP_0 + kval; + break; + } + break; + case KT_DEAD: + /* KT_DEAD keys are for accelerated diacritical creation. */ + switch (kbe.kb_value) { + case K_DGRAVE: + *k = XK_dead_grave; + break; + case K_DACUTE: + *k = XK_dead_acute; + break; + case K_DCIRCM: + *k = XK_dead_circumflex; + break; + case K_DTILDE: + *k = XK_dead_tilde; + break; + case K_DDIERE: + *k = XK_dead_diaeresis; + break; + } + break; + case KT_CUR: + switch (kbe.kb_value) { + case K_DOWN: + *k = XK_Down; + break; + case K_LEFT: + *k = XK_Left; + break; + case K_RIGHT: + *k = XK_Right; + break; + case K_UP: + *k = XK_Up; + break; + } + break; + case KT_SHIFT: + switch (kbe.kb_value) { + case K_ALTGR: + *k = XK_Alt_R; + break; + case K_ALT: + *k = (kbe.kb_index == 0x64 ? XK_Alt_R : XK_Alt_L); + break; + case K_CTRL: + *k = (kbe.kb_index == 0x61 ? XK_Control_R : XK_Control_L); + break; + case K_CTRLL: + *k = XK_Control_L; + break; + case K_CTRLR: + *k = XK_Control_R; + break; + case K_SHIFT: + *k = (kbe.kb_index == 0x36 ? XK_Shift_R : XK_Shift_L); + break; + case K_SHIFTL: + *k = XK_Shift_L; + break; + case K_SHIFTR: + *k = XK_Shift_R; + break; + default: + break; + } + break; + case KT_ASCII: + /* KT_ASCII keys accumulate a 3 digit decimal number that + * gets emitted when the shift state changes. We can't + * emulate that. + */ + break; + case KT_LOCK: + if (kbe.kb_value == K_SHIFTLOCK) + *k = XK_Shift_Lock; + break; + default: + break; + } + } + + if (k[-1] == k[-2]) + k[-1] = NoSymbol; + if (k[-2] == k[-3]) + k[-2] = NoSymbol; + if (k[-3] == k[-4]) + k[-3] = NoSymbol; + if (k[-4] == k[-2] && k[-3] == k[-1]) + k[-2] = k[-1] = NoSymbol; + if (k[-1] == k[-4] && k[-2] == k[-3] + && k[-2] == NoSymbol) + k[-1] = NoSymbol; + } } -static void kbdLinuxGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) +static void +kbdLinuxGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) { GETPRIV; - KeySym *k, *mapCopy; - char type; - int i; + KeySym *k, *mapCopy; + char type; + int i; -#if 00/*BP*/ - mapCopy = malloc(sizeof(map)); +#if 00 /*BP*/ + mapCopy = malloc(sizeof(map)); memcpy(mapCopy, map, sizeof(map)); #else ErrorF("kbdLinuxGetMap() is broken/no-op'd\n"); @@ -950,41 +1138,57 @@ static void kbdLinuxGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) /* compute the modifier map */ for (i = 0; i < MAP_LENGTH; i++) pModMap[i] = NoSymbol; /* make sure it is restored */ - + for (k = mapCopy, i = MIN_KEYCODE; - i < NUM_KEYCODES + MIN_KEYCODE; - i++, k += 4) { - switch(*k) { + i < NUM_KEYCODES + MIN_KEYCODE; i++, k += 4) { + switch (*k) { case XK_Shift_L: - case XK_Shift_R: pModMap[i] = ShiftMask; break; + case XK_Shift_R: + pModMap[i] = ShiftMask; + break; case XK_Control_L: - case XK_Control_R: pModMap[i] = ControlMask; break; - case XK_Caps_Lock: pModMap[i] = LockMask; break; + case XK_Control_R: + pModMap[i] = ControlMask; + break; + case XK_Caps_Lock: + pModMap[i] = LockMask; + break; case XK_Alt_L: - case XK_Alt_R: pModMap[i] = AltMask; break; - case XK_Num_Lock: pModMap[i] = NumLockMask; break; - case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break; + case XK_Alt_R: + pModMap[i] = AltMask; + break; + case XK_Num_Lock: + pModMap[i] = NumLockMask; + break; + case XK_Scroll_Lock: + pModMap[i] = ScrollLockMask; + break; case XK_Kana_Lock: - case XK_Kana_Shift: pModMap[i] = KanaMask; break; - case XK_Mode_switch: pModMap[i] = AltLangMask; break; + case XK_Kana_Shift: + pModMap[i] = KanaMask; + break; + case XK_Mode_switch: + pModMap[i] = AltLangMask; + break; } } priv->kbdType = (ioctl(priv->fd, KDGKBTYPE, &type) < 0) ? KB_101 : type; - pKeySyms->map = mapCopy; /* Must be XFree'able */ - pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->map = mapCopy; /* Must be XFree'able */ + pKeySyms->mapWidth = GLYPHS_PER_KEY; pKeySyms->minKeyCode = MIN_KEYCODE; pKeySyms->maxKeyCode = MAX_KEYCODE; } /** Fill the \a info structure with information needed to initialize \a - * pDev. */ -void kbdLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) + * pDev. */ +void +kbdLinuxGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) { - info->keyboard = 1; - info->keyClass = 1; + info->keyboard = 1; + info->keyClass = 1; kbdLinuxGetMap(pDev, &info->keySyms, info->modMap); - info->focusClass = 1; + info->focusClass = 1; info->kbdFeedbackClass = 1; } diff --git a/xorg-server/hw/dmx/input/lnx-ms.c b/xorg-server/hw/dmx/input/lnx-ms.c index e6d203c4b..7e1acf450 100644 --- a/xorg-server/hw/dmx/input/lnx-ms.c +++ b/xorg-server/hw/dmx/input/lnx-ms.c @@ -1,321 +1,348 @@ -/* 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;
-}
+/* 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 f40441fe7..67c73a0c5 100644 --- a/xorg-server/hw/dmx/input/lnx-ps2.c +++ b/xorg-server/hw/dmx/input/lnx-ps2.c @@ -1,289 +1,318 @@ -/* 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;
-}
+/* 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 944033eba..c7c166cce 100644 --- a/xorg-server/hw/dmx/input/usb-common.c +++ b/xorg-server/hw/dmx/input/usb-common.c @@ -74,7 +74,6 @@ /* 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 @@ -84,16 +83,14 @@ * 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) +void +usbRead(DevicePtr pDev, + MOTIONPROC motion, ENQUEUEPROC enqueue, int minButton, BLOCK block) { GETPRIV; struct input_event raw; - int v[DMX_MAX_AXES]; - int axis; + int v[DMX_MAX_AXES]; + int axis; #define PRESS(b) \ do { \ @@ -112,11 +109,14 @@ void usbRead(DevicePtr pDev, #endif switch (raw.type) { case EV_KEY: - /* raw.value = 1 for first, 2 for repeat */ + /* 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 { + 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); } @@ -134,10 +134,11 @@ void usbRead(DevicePtr pDev, motion(pDev, v, 0, 2, DMX_RELATIVE, block); break; case REL_WHEEL: - if ((int)raw.value > 0) { + if ((int) raw.value > 0) { PRESS(4); RELEASE(4); - } else if ((int)raw.value < 0) { + } + else if ((int) raw.value < 0) { PRESS(5); RELEASE(5); } @@ -162,126 +163,228 @@ void usbRead(DevicePtr pDev, #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) +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. */ + 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 */ + 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"; + 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; - } + 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"; + 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; - } + 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"; + 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; - } + 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"; + 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; - } + 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; + 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] ? "]" : ""); + 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) +device. */ +void +usbInit(DevicePtr pDev, usbType type) { GETPRIV; - char name[64]; /* RATS: Only used in snprintf */ - 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. */ + char name[64]; /* RATS: Only used in snprintf */ + 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; + if (priv->fd >= 0) + return; for (i = 0; i < 32; i++) { snprintf(name, sizeof(name), "/dev/input/event%d", i); @@ -293,15 +396,18 @@ void usbInit(DevicePtr pDev, usbType type) for (j = 0; j < EV_MAX; j++) { if (test_bit(j)) { - switch(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; + 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; } } @@ -320,7 +426,8 @@ void usbInit(DevicePtr pDev, usbType type) 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; + if (test_bits(k)) + ++priv->numLeds; } break; } @@ -350,32 +457,36 @@ void usbInit(DevicePtr pDev, usbType type) 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: + " 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) +void +usbOff(DevicePtr pDev) { GETPRIV; - if (priv->fd >= 0) close(priv->fd); + if (priv->fd >= 0) + close(priv->fd); priv->fd = -1; } /** Create a private structure for use within this file. */ -pointer usbCreatePrivate(DeviceIntPtr pDevice) +pointer +usbCreatePrivate(DeviceIntPtr pDevice) { myPrivate *priv = calloc(1, sizeof(*priv)); - priv->fd = -1; - priv->pDevice = pDevice; + + priv->fd = -1; + priv->pDevice = pDevice; return priv; } /** Destroy a private structure. */ -void usbDestroyPrivate(pointer priv) +void +usbDestroyPrivate(pointer priv) { free(priv); } diff --git a/xorg-server/hw/dmx/input/usb-common.h b/xorg-server/hw/dmx/input/usb-common.h index 5ebfd1e78..eea98afbe 100644 --- a/xorg-server/hw/dmx/input/usb-common.h +++ b/xorg-server/hw/dmx/input/usb-common.h @@ -44,12 +44,11 @@ typedef enum { } usbType; extern pointer usbCreatePrivate(DeviceIntPtr pDevice); -extern void usbDestroyPrivate(pointer priv); -extern void usbRead(DevicePtr pDev, - dmxMotionProcPtr motion, - dmxEnqueueProcPtr enqueue, - int minButton, - DMXBlockType block); -extern void usbInit(DevicePtr pDev, usbType type); -extern void usbOff(DevicePtr pDev); +extern void usbDestroyPrivate(pointer priv); +extern void usbRead(DevicePtr pDev, + dmxMotionProcPtr motion, + dmxEnqueueProcPtr enqueue, + int minButton, DMXBlockType block); +extern void usbInit(DevicePtr pDev, usbType type); +extern void usbOff(DevicePtr pDev); #endif diff --git a/xorg-server/hw/dmx/input/usb-keyboard.c b/xorg-server/hw/dmx/input/usb-keyboard.c index c2b49039f..65bfcd00d 100644 --- a/xorg-server/hw/dmx/input/usb-keyboard.c +++ b/xorg-server/hw/dmx/input/usb-keyboard.c @@ -1,444 +1,477 @@ -/* Portions of this file were derived from the following files:
- *
- **********************************************************************
- *
- * xfree86/common/xf86KbdLnx.c
- *
- * Linux version of keymapping setup. The kernel (since 0.99.14) has support
- * for fully remapping the keyboard, but there are some differences between
- * the Linux map and the SVR4 map (esp. in the extended keycodes). We also
- * remove the restriction on what keycodes can be remapped.
- * Orest Zborowski.
- *
- * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Thomas Roell not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Thomas Roell makes no representations
- * about the suitability of this software for any purpose. It is provided
- * "as is" without express or implied warranty.
- *
- * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-/*
- * Copyright 2001,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
- *
- * This code implements a low-level device driver for a USB keyboard
- * under Linux. The keymap description is derived from code by Thomas
- * Roell, Orest Zborowski. */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "atKeynames.h"
-#include "usb-private.h"
-
-#define USB_KEYBOARD_DEBUG 0
-
-/*****************************************************************************/
-/* 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-keyboard.h"
-#include <xkbsrv.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. */
-/*****************************************************************************/
-
-#define GLYPHS_PER_KEY 4
-#define NUM_KEYCODES 248
-#define MIN_KEYCODE 8
-#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1)
-
-static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = {
-/* Table modified from xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h */
- /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol,
- /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol,
- /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol,
- /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol,
- /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol,
- /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol,
- /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol,
- /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol,
- /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol,
- /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol,
- /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol,
- /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol,
- /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol,
- /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol,
- /* 0x0f */ XK_Tab, XK_ISO_Left_Tab,NoSymbol, NoSymbol,
- /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol,
- /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol,
- /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol,
- /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol,
- /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol,
- /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol,
- /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol,
- /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol,
- /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol,
- /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol,
- /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol,
- /* 0x1b */ XK_bracketright,XK_braceright, NoSymbol, NoSymbol,
- /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol,
- /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol,
- /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol,
- /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol,
- /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol,
- /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol,
- /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol,
- /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol,
- /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol,
- /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol,
- /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol,
- /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol,
- /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol,
- /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol,
- /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol,
- /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol,
- /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol,
- /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol,
- /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol,
- /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol,
- /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol,
- /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol,
- /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol,
- /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol,
- /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol,
- /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol,
- /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol,
- /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol,
- /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol,
- /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol,
- /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol,
- /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol,
- /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol,
- /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol,
- /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol,
- /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol,
- /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol,
- /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol,
- /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol,
- /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol,
- /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol,
- /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol,
- /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol,
- /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol,
- /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol,
- /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol,
- /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol,
- /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol,
- /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol,
- /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol,
- /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol,
- /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol,
- /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol,
- /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol,
- /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol,
- /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol,
- /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol,
- /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol,
- /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol,
- /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol,
- /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol,
- /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x60 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol,
- /* 0x61 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol,
- /* 0x62 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol,
- /* 0x63 */ XK_Print, NoSymbol, NoSymbol, NoSymbol,
- /* 0x64 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol,
- /* 0x65 */ XK_Break, NoSymbol, NoSymbol, NoSymbol,
- /* 0x66 */ XK_Home, NoSymbol, NoSymbol, NoSymbol,
- /* 0x67 */ XK_Up, NoSymbol, NoSymbol, NoSymbol,
- /* 0x68 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol,
- /* 0x69 */ XK_Left, NoSymbol, NoSymbol, NoSymbol,
- /* 0x6a */ XK_Right, NoSymbol, NoSymbol, NoSymbol,
- /* 0x6b */ XK_End, NoSymbol, NoSymbol, NoSymbol,
- /* 0x6c */ XK_Down, NoSymbol, NoSymbol, NoSymbol,
- /* 0x6d */ XK_Next, NoSymbol, NoSymbol, NoSymbol,
- /* 0x6e */ XK_Insert, NoSymbol, NoSymbol, NoSymbol,
- /* 0x6f */ XK_Delete, NoSymbol, NoSymbol, NoSymbol,
- /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x77 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol,
- /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x7a */ XK_Menu, NoSymbol, NoSymbol, NoSymbol,
- /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- /* 0x7d */ XK_Super_L, NoSymbol, NoSymbol, NoSymbol,
- /* 0x7e */ XK_Super_R, NoSymbol, NoSymbol, NoSymbol,
- /* 0x7f */ XK_Menu, NoSymbol, NoSymbol, NoSymbol,
-};
-
-static int kbdUSBKeyDown(myPrivate *priv, int keyCode)
-{
- CARD8 byte = keyCode >> 5;
- CARD32 bit = 1 << (keyCode & 0x1f);
-
- if (byte > NUM_STATE_ENTRIES) return 0;
- return priv->kbdState[byte] & bit;
-}
-
-static void kbdUSBKeyState(myPrivate *priv, int type, int keyCode)
-{
- CARD8 byte = keyCode >> 5;
- CARD32 bit = 1 << (keyCode & 0x1f);
-
- if (byte > NUM_STATE_ENTRIES) return;
- if (type == KeyPress) priv->kbdState[byte] |= bit;
- else priv->kbdState[byte] &= ~bit;
-}
-
-/** Set the LEDs. */
-void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl *ctrl)
-{
- GETPRIV;
- struct timeval tv;
- struct input_event event;
- int i, led;
-
- gettimeofday(&tv, NULL);
- for (i = 0; i < 5; i++) {
- event.time.tv_sec = tv.tv_sec;
- event.time.tv_usec = tv.tv_usec;
- event.type = EV_LED;
- if (i == 0) led = 1; /* LED_CAPSL == 0x01 */
- else if (i == 1) led = 0; /* LED_NUML == 0x00 */
- else led = i;
- event.code = led;
- event.value = !!(ctrl->leds & (1 << led));
- write(priv->fd, &event, sizeof(event));
- }
-}
-
-/** Initialize \a pDev using #usbInit. */
-void kbdUSBInit(DevicePtr pDev)
-{
- usbInit(pDev, usbKeyboard);
-}
-
-static void kbdUSBConvert(DevicePtr pDev,
- unsigned int scanCode,
- int value,
- ENQUEUEPROC enqueue,
- CHECKPROC checkspecial,
- BLOCK block)
-{
- GETPRIV;
- XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo;
- int type;
- int keyCode;
- KeySym keySym = NoSymbol;
- int switching;
-
- /* Set up xEvent information */
- type = value ? KeyPress : KeyRelease;
- keyCode = (scanCode & 0xff) + MIN_KEYCODE;
-
- /* Handle repeats */
-
- if (keyCode >= xkbi->desc->min_key_code &&
- keyCode <= xkbi->desc->max_key_code) {
-
- int effectiveGroup = XkbGetEffectiveGroup(xkbi,
- &xkbi->state,
- scanCode);
- keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup);
-#if 0
- switch (keySym) {
- case XK_Num_Lock:
- case XK_Scroll_Lock:
- case XK_Shift_Lock:
- case XK_Caps_Lock:
- /* Ignore releases and all but first press */
- if (kbdLinuxModIgnore(priv, &xE, keySym)) return;
- if (kbdLinuxKeyDown(priv, &xE)) xE.u.u.type = KeyRelease;
- else xE.u.u.type = KeyPress;
- break;
- }
-#endif
-
- /* If key is already down, ignore or autorepeat */
- if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) {
- KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed;
-
- /* No auto-repeat? */
- if ((feed && !feed->ctrl.autoRepeat)
- || priv->pDevice->key->xkbInfo->desc->map->modmap[keyCode]
- || (feed
- && !(feed->ctrl.autoRepeats[keyCode >> 3]
- & (1 << (keyCode & 7))))) return; /* Ignore */
-
- /* Do auto-repeat */
- enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block);
- type = KeyPress;
- }
-
- /* If key is already up, ignore */
- if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) return;
- }
-
- switching = 0;
- if (checkspecial && type == KeyPress)
- switching = checkspecial(pDev, keySym);
- if (!switching) {
- if (enqueue)
- enqueue(pDev, type, keyCode, keySym, NULL, block);
- kbdUSBKeyState(priv, type, keyCode); /* Update our state bitmap */
- }
-}
-
-/** 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 kbdUSBRead(DevicePtr pDev,
- MOTIONPROC motion,
- ENQUEUEPROC enqueue,
- CHECKPROC checkspecial,
- BLOCK block)
-{
- GETPRIV;
- struct input_event raw;
-
- while (read(priv->fd, &raw, sizeof(raw)) > 0) {
-#if USB_KEYBOARD_DEBUG
- LOG3("KBD: type = %d, code = 0x%02x, value = %d\n",
- raw.type, raw.code, raw.value);
-#endif
- kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block);
- }
-}
-
-/** Turn \a pDev on (i.e., take input from \a pDev). */
-int kbdUSBOn(DevicePtr pDev)
-{
- GETPRIV;
-
- if (priv->fd < 0) kbdUSBInit(pDev);
- return priv->fd;
-}
-
-static void kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap)
-{
- KeySym *k, *mapCopy;
- int i;
-
- mapCopy = malloc(sizeof(map));
- memcpy(mapCopy, map, sizeof(map));
-
- /* compute the modifier map */
- for (i = 0; i < MAP_LENGTH; i++)
- pModMap[i] = NoSymbol; /* make sure it is restored */
-
- for (k = mapCopy, i = MIN_KEYCODE;
- i < NUM_KEYCODES + MIN_KEYCODE;
- i++, k += 4) {
- switch(*k) {
- case XK_Shift_L:
- case XK_Shift_R: pModMap[i] = ShiftMask; break;
- case XK_Control_L:
- case XK_Control_R: pModMap[i] = ControlMask; break;
- case XK_Caps_Lock: pModMap[i] = LockMask; break;
- case XK_Alt_L:
- case XK_Alt_R: pModMap[i] = AltMask; break;
- case XK_Num_Lock: pModMap[i] = NumLockMask; break;
- case XK_Scroll_Lock: pModMap[i] = ScrollLockMask; break;
- case XK_Kana_Lock:
- case XK_Kana_Shift: pModMap[i] = KanaMask; break;
- case XK_Mode_switch: pModMap[i] = AltLangMask; break;
- }
- }
-
- pKeySyms->map = mapCopy; /* Must be XFree'able */
- pKeySyms->mapWidth = GLYPHS_PER_KEY;
- pKeySyms->minKeyCode = MIN_KEYCODE;
- pKeySyms->maxKeyCode = MAX_KEYCODE;
-}
-
-/** Fill the \a info structure with information needed to initialize \a
- * pDev. */
-void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info)
-{
- info->keyboard = 1;
- info->keyClass = 1;
- kbdUSBGetMap(pDev, &info->keySyms, info->modMap);
- info->focusClass = 1;
- info->kbdFeedbackClass = 1;
- info->names.keycodes = strdup("powerpcps2");
- info->force = 1;
-}
+/* Portions of this file were derived from the following files: + * + ********************************************************************** + * + * xfree86/common/xf86KbdLnx.c + * + * Linux version of keymapping setup. The kernel (since 0.99.14) has support + * for fully remapping the keyboard, but there are some differences between + * the Linux map and the SVR4 map (esp. in the extended keycodes). We also + * remove the restriction on what keycodes can be remapped. + * Orest Zborowski. + * + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Thomas Roell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Thomas Roell makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * THOMAS ROELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THOMAS ROELL BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * Copyright 2001,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 + * + * This code implements a low-level device driver for a USB keyboard + * under Linux. The keymap description is derived from code by Thomas + * Roell, Orest Zborowski. */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "atKeynames.h" +#include "usb-private.h" + +#define USB_KEYBOARD_DEBUG 0 + +/*****************************************************************************/ +/* 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-keyboard.h" +#include <xkbsrv.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. */ +/*****************************************************************************/ + +#define GLYPHS_PER_KEY 4 +#define NUM_KEYCODES 248 +#define MIN_KEYCODE 8 +#define MAX_KEYCODE (NUM_KEYCODES + MIN_KEYCODE - 1) + +static KeySym map[NUM_KEYCODES * GLYPHS_PER_KEY] = { +/* Table modified from xc/programs/Xserver/hw/xfree86/common/xf86Keymap.h */ + /* 0x00 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x01 */ XK_Escape, NoSymbol, NoSymbol, NoSymbol, + /* 0x02 */ XK_1, XK_exclam, NoSymbol, NoSymbol, + /* 0x03 */ XK_2, XK_at, NoSymbol, NoSymbol, + /* 0x04 */ XK_3, XK_numbersign, NoSymbol, NoSymbol, + /* 0x05 */ XK_4, XK_dollar, NoSymbol, NoSymbol, + /* 0x06 */ XK_5, XK_percent, NoSymbol, NoSymbol, + /* 0x07 */ XK_6, XK_asciicircum, NoSymbol, NoSymbol, + /* 0x08 */ XK_7, XK_ampersand, NoSymbol, NoSymbol, + /* 0x09 */ XK_8, XK_asterisk, NoSymbol, NoSymbol, + /* 0x0a */ XK_9, XK_parenleft, NoSymbol, NoSymbol, + /* 0x0b */ XK_0, XK_parenright, NoSymbol, NoSymbol, + /* 0x0c */ XK_minus, XK_underscore, NoSymbol, NoSymbol, + /* 0x0d */ XK_equal, XK_plus, NoSymbol, NoSymbol, + /* 0x0e */ XK_BackSpace, NoSymbol, NoSymbol, NoSymbol, + /* 0x0f */ XK_Tab, XK_ISO_Left_Tab, NoSymbol, NoSymbol, + /* 0x10 */ XK_Q, NoSymbol, NoSymbol, NoSymbol, + /* 0x11 */ XK_W, NoSymbol, NoSymbol, NoSymbol, + /* 0x12 */ XK_E, NoSymbol, NoSymbol, NoSymbol, + /* 0x13 */ XK_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x14 */ XK_T, NoSymbol, NoSymbol, NoSymbol, + /* 0x15 */ XK_Y, NoSymbol, NoSymbol, NoSymbol, + /* 0x16 */ XK_U, NoSymbol, NoSymbol, NoSymbol, + /* 0x17 */ XK_I, NoSymbol, NoSymbol, NoSymbol, + /* 0x18 */ XK_O, NoSymbol, NoSymbol, NoSymbol, + /* 0x19 */ XK_P, NoSymbol, NoSymbol, NoSymbol, + /* 0x1a */ XK_bracketleft, XK_braceleft, NoSymbol, NoSymbol, + /* 0x1b */ XK_bracketright, XK_braceright, NoSymbol, NoSymbol, + /* 0x1c */ XK_Return, NoSymbol, NoSymbol, NoSymbol, + /* 0x1d */ XK_Control_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x1e */ XK_A, NoSymbol, NoSymbol, NoSymbol, + /* 0x1f */ XK_S, NoSymbol, NoSymbol, NoSymbol, + /* 0x20 */ XK_D, NoSymbol, NoSymbol, NoSymbol, + /* 0x21 */ XK_F, NoSymbol, NoSymbol, NoSymbol, + /* 0x22 */ XK_G, NoSymbol, NoSymbol, NoSymbol, + /* 0x23 */ XK_H, NoSymbol, NoSymbol, NoSymbol, + /* 0x24 */ XK_J, NoSymbol, NoSymbol, NoSymbol, + /* 0x25 */ XK_K, NoSymbol, NoSymbol, NoSymbol, + /* 0x26 */ XK_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x27 */ XK_semicolon, XK_colon, NoSymbol, NoSymbol, + /* 0x28 */ XK_quoteright, XK_quotedbl, NoSymbol, NoSymbol, + /* 0x29 */ XK_quoteleft, XK_asciitilde, NoSymbol, NoSymbol, + /* 0x2a */ XK_Shift_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x2b */ XK_backslash, XK_bar, NoSymbol, NoSymbol, + /* 0x2c */ XK_Z, NoSymbol, NoSymbol, NoSymbol, + /* 0x2d */ XK_X, NoSymbol, NoSymbol, NoSymbol, + /* 0x2e */ XK_C, NoSymbol, NoSymbol, NoSymbol, + /* 0x2f */ XK_V, NoSymbol, NoSymbol, NoSymbol, + /* 0x30 */ XK_B, NoSymbol, NoSymbol, NoSymbol, + /* 0x31 */ XK_N, NoSymbol, NoSymbol, NoSymbol, + /* 0x32 */ XK_M, NoSymbol, NoSymbol, NoSymbol, + /* 0x33 */ XK_comma, XK_less, NoSymbol, NoSymbol, + /* 0x34 */ XK_period, XK_greater, NoSymbol, NoSymbol, + /* 0x35 */ XK_slash, XK_question, NoSymbol, NoSymbol, + /* 0x36 */ XK_Shift_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x37 */ XK_KP_Multiply, NoSymbol, NoSymbol, NoSymbol, + /* 0x38 */ XK_Alt_L, XK_Meta_L, NoSymbol, NoSymbol, + /* 0x39 */ XK_space, NoSymbol, NoSymbol, NoSymbol, + /* 0x3a */ XK_Caps_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x3b */ XK_F1, NoSymbol, NoSymbol, NoSymbol, + /* 0x3c */ XK_F2, NoSymbol, NoSymbol, NoSymbol, + /* 0x3d */ XK_F3, NoSymbol, NoSymbol, NoSymbol, + /* 0x3e */ XK_F4, NoSymbol, NoSymbol, NoSymbol, + /* 0x3f */ XK_F5, NoSymbol, NoSymbol, NoSymbol, + /* 0x40 */ XK_F6, NoSymbol, NoSymbol, NoSymbol, + /* 0x41 */ XK_F7, NoSymbol, NoSymbol, NoSymbol, + /* 0x42 */ XK_F8, NoSymbol, NoSymbol, NoSymbol, + /* 0x43 */ XK_F9, NoSymbol, NoSymbol, NoSymbol, + /* 0x44 */ XK_F10, NoSymbol, NoSymbol, NoSymbol, + /* 0x45 */ XK_Num_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x46 */ XK_Scroll_Lock, NoSymbol, NoSymbol, NoSymbol, + /* 0x47 */ XK_KP_Home, XK_KP_7, NoSymbol, NoSymbol, + /* 0x48 */ XK_KP_Up, XK_KP_8, NoSymbol, NoSymbol, + /* 0x49 */ XK_KP_Prior, XK_KP_9, NoSymbol, NoSymbol, + /* 0x4a */ XK_KP_Subtract, NoSymbol, NoSymbol, NoSymbol, + /* 0x4b */ XK_KP_Left, XK_KP_4, NoSymbol, NoSymbol, + /* 0x4c */ XK_KP_Begin, XK_KP_5, NoSymbol, NoSymbol, + /* 0x4d */ XK_KP_Right, XK_KP_6, NoSymbol, NoSymbol, + /* 0x4e */ XK_KP_Add, NoSymbol, NoSymbol, NoSymbol, + /* 0x4f */ XK_KP_End, XK_KP_1, NoSymbol, NoSymbol, + /* 0x50 */ XK_KP_Down, XK_KP_2, NoSymbol, NoSymbol, + /* 0x51 */ XK_KP_Next, XK_KP_3, NoSymbol, NoSymbol, + /* 0x52 */ XK_KP_Insert, XK_KP_0, NoSymbol, NoSymbol, + /* 0x53 */ XK_KP_Delete, XK_KP_Decimal, NoSymbol, NoSymbol, + /* 0x54 */ XK_Sys_Req, NoSymbol, NoSymbol, NoSymbol, + /* 0x55 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x56 */ XK_less, XK_greater, NoSymbol, NoSymbol, + /* 0x57 */ XK_F11, NoSymbol, NoSymbol, NoSymbol, + /* 0x58 */ XK_F12, NoSymbol, NoSymbol, NoSymbol, + /* 0x59 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5a */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5d */ XK_Begin, NoSymbol, NoSymbol, NoSymbol, + /* 0x5e */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x5f */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x60 */ XK_KP_Enter, NoSymbol, NoSymbol, NoSymbol, + /* 0x61 */ XK_Control_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x62 */ XK_KP_Divide, NoSymbol, NoSymbol, NoSymbol, + /* 0x63 */ XK_Print, NoSymbol, NoSymbol, NoSymbol, + /* 0x64 */ XK_Alt_R, XK_Meta_R, NoSymbol, NoSymbol, + /* 0x65 */ XK_Break, NoSymbol, NoSymbol, NoSymbol, + /* 0x66 */ XK_Home, NoSymbol, NoSymbol, NoSymbol, + /* 0x67 */ XK_Up, NoSymbol, NoSymbol, NoSymbol, + /* 0x68 */ XK_Prior, NoSymbol, NoSymbol, NoSymbol, + /* 0x69 */ XK_Left, NoSymbol, NoSymbol, NoSymbol, + /* 0x6a */ XK_Right, NoSymbol, NoSymbol, NoSymbol, + /* 0x6b */ XK_End, NoSymbol, NoSymbol, NoSymbol, + /* 0x6c */ XK_Down, NoSymbol, NoSymbol, NoSymbol, + /* 0x6d */ XK_Next, NoSymbol, NoSymbol, NoSymbol, + /* 0x6e */ XK_Insert, NoSymbol, NoSymbol, NoSymbol, + /* 0x6f */ XK_Delete, NoSymbol, NoSymbol, NoSymbol, + /* 0x70 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x71 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x72 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x73 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x74 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x75 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x76 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x77 */ XK_Pause, NoSymbol, NoSymbol, NoSymbol, + /* 0x78 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x79 */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7a */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, + /* 0x7b */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7c */ NoSymbol, NoSymbol, NoSymbol, NoSymbol, + /* 0x7d */ XK_Super_L, NoSymbol, NoSymbol, NoSymbol, + /* 0x7e */ XK_Super_R, NoSymbol, NoSymbol, NoSymbol, + /* 0x7f */ XK_Menu, NoSymbol, NoSymbol, NoSymbol, +}; + +static int +kbdUSBKeyDown(myPrivate * priv, int keyCode) +{ + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); + + if (byte > NUM_STATE_ENTRIES) + return 0; + return priv->kbdState[byte] & bit; +} + +static void +kbdUSBKeyState(myPrivate * priv, int type, int keyCode) +{ + CARD8 byte = keyCode >> 5; + CARD32 bit = 1 << (keyCode & 0x1f); + + if (byte > NUM_STATE_ENTRIES) + return; + if (type == KeyPress) + priv->kbdState[byte] |= bit; + else + priv->kbdState[byte] &= ~bit; +} + +/** Set the LEDs. */ +void +kbdUSBCtrl(DevicePtr pDev, KeybdCtrl * ctrl) +{ + GETPRIV; + struct timeval tv; + struct input_event event; + int i, led; + + gettimeofday(&tv, NULL); + for (i = 0; i < 5; i++) { + event.time.tv_sec = tv.tv_sec; + event.time.tv_usec = tv.tv_usec; + event.type = EV_LED; + if (i == 0) + led = 1; /* LED_CAPSL == 0x01 */ + else if (i == 1) + led = 0; /* LED_NUML == 0x00 */ + else + led = i; + event.code = led; + event.value = ! !(ctrl->leds & (1 << led)); + write(priv->fd, &event, sizeof(event)); + } +} + +/** Initialize \a pDev using #usbInit. */ +void +kbdUSBInit(DevicePtr pDev) +{ + usbInit(pDev, usbKeyboard); +} + +static void +kbdUSBConvert(DevicePtr pDev, + unsigned int scanCode, + int value, + ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) +{ + GETPRIV; + XkbSrvInfoPtr xkbi = priv->pKeyboard->key->xkbInfo; + int type; + int keyCode; + KeySym keySym = NoSymbol; + int switching; + + /* Set up xEvent information */ + type = value ? KeyPress : KeyRelease; + keyCode = (scanCode & 0xff) + MIN_KEYCODE; + + /* Handle repeats */ + + if (keyCode >= xkbi->desc->min_key_code && + keyCode <= xkbi->desc->max_key_code) { + + int effectiveGroup = XkbGetEffectiveGroup(xkbi, + &xkbi->state, + scanCode); + + keySym = XkbKeySym(xkbi->desc, scanCode, effectiveGroup); +#if 0 + switch (keySym) { + case XK_Num_Lock: + case XK_Scroll_Lock: + case XK_Shift_Lock: + case XK_Caps_Lock: + /* Ignore releases and all but first press */ + if (kbdLinuxModIgnore(priv, &xE, keySym)) + return; + if (kbdLinuxKeyDown(priv, &xE)) + xE.u.u.type = KeyRelease; + else + xE.u.u.type = KeyPress; + break; + } +#endif + + /* If key is already down, ignore or autorepeat */ + if (type == KeyPress && kbdUSBKeyDown(priv, keyCode)) { + KbdFeedbackClassRec *feed = priv->pDevice->kbdfeed; + + /* No auto-repeat? */ + if ((feed && !feed->ctrl.autoRepeat) + || priv->pDevice->key->xkbInfo->desc->map->modmap[keyCode] + || (feed && !(feed->ctrl.autoRepeats[keyCode >> 3] + & (1 << (keyCode & 7))))) + return; /* Ignore */ + + /* Do auto-repeat */ + enqueue(pDev, KeyRelease, keyCode, keySym, NULL, block); + type = KeyPress; + } + + /* If key is already up, ignore */ + if (type == KeyRelease && !kbdUSBKeyDown(priv, keyCode)) + return; + } + + switching = 0; + if (checkspecial && type == KeyPress) + switching = checkspecial(pDev, keySym); + if (!switching) { + if (enqueue) + enqueue(pDev, type, keyCode, keySym, NULL, block); + kbdUSBKeyState(priv, type, keyCode); /* Update our state bitmap */ + } +} + +/** 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 +kbdUSBRead(DevicePtr pDev, + MOTIONPROC motion, + ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) +{ + GETPRIV; + struct input_event raw; + + while (read(priv->fd, &raw, sizeof(raw)) > 0) { +#if USB_KEYBOARD_DEBUG + LOG3("KBD: type = %d, code = 0x%02x, value = %d\n", + raw.type, raw.code, raw.value); +#endif + kbdUSBConvert(pDev, raw.code, raw.value, enqueue, checkspecial, block); + } +} + +/** Turn \a pDev on (i.e., take input from \a pDev). */ +int +kbdUSBOn(DevicePtr pDev) +{ + GETPRIV; + + if (priv->fd < 0) + kbdUSBInit(pDev); + return priv->fd; +} + +static void +kbdUSBGetMap(DevicePtr pDev, KeySymsPtr pKeySyms, CARD8 *pModMap) +{ + KeySym *k, *mapCopy; + int i; + + mapCopy = malloc(sizeof(map)); + memcpy(mapCopy, map, sizeof(map)); + + /* compute the modifier map */ + for (i = 0; i < MAP_LENGTH; i++) + pModMap[i] = NoSymbol; /* make sure it is restored */ + + for (k = mapCopy, i = MIN_KEYCODE; + i < NUM_KEYCODES + MIN_KEYCODE; i++, k += 4) { + switch (*k) { + case XK_Shift_L: + case XK_Shift_R: + pModMap[i] = ShiftMask; + break; + case XK_Control_L: + case XK_Control_R: + pModMap[i] = ControlMask; + break; + case XK_Caps_Lock: + pModMap[i] = LockMask; + break; + case XK_Alt_L: + case XK_Alt_R: + pModMap[i] = AltMask; + break; + case XK_Num_Lock: + pModMap[i] = NumLockMask; + break; + case XK_Scroll_Lock: + pModMap[i] = ScrollLockMask; + break; + case XK_Kana_Lock: + case XK_Kana_Shift: + pModMap[i] = KanaMask; + break; + case XK_Mode_switch: + pModMap[i] = AltLangMask; + break; + } + } + + pKeySyms->map = mapCopy; /* Must be XFree'able */ + pKeySyms->mapWidth = GLYPHS_PER_KEY; + pKeySyms->minKeyCode = MIN_KEYCODE; + pKeySyms->maxKeyCode = MAX_KEYCODE; +} + +/** Fill the \a info structure with information needed to initialize \a + * pDev. */ +void +kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) +{ + info->keyboard = 1; + info->keyClass = 1; + kbdUSBGetMap(pDev, &info->keySyms, info->modMap); + info->focusClass = 1; + info->kbdFeedbackClass = 1; + info->names.keycodes = strdup("powerpcps2"); + info->force = 1; +} diff --git a/xorg-server/hw/dmx/input/usb-keyboard.h b/xorg-server/hw/dmx/input/usb-keyboard.h index 1f9614eef..e14cca1c2 100644 --- a/xorg-server/hw/dmx/input/usb-keyboard.h +++ b/xorg-server/hw/dmx/input/usb-keyboard.h @@ -36,13 +36,12 @@ #ifndef _USB_KEYBOARD_H_ #define _USB_KEYBOARD_H_ -extern void kbdUSBInit(DevicePtr pDev); -extern void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info); -extern int kbdUSBOn(DevicePtr pDev); -extern void kbdUSBRead(DevicePtr pDev, - dmxMotionProcPtr motion, - dmxEnqueueProcPtr enqueue, - dmxCheckSpecialProcPtr checkspecial, - DMXBlockType block); -extern void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl *ctrl); +extern void kbdUSBInit(DevicePtr pDev); +extern void kbdUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info); +extern int kbdUSBOn(DevicePtr pDev); +extern void kbdUSBRead(DevicePtr pDev, + dmxMotionProcPtr motion, + dmxEnqueueProcPtr enqueue, + dmxCheckSpecialProcPtr checkspecial, DMXBlockType block); +extern void kbdUSBCtrl(DevicePtr pDev, KeybdCtrl * ctrl); #endif diff --git a/xorg-server/hw/dmx/input/usb-mouse.c b/xorg-server/hw/dmx/input/usb-mouse.c index efa9d00ec..644342ee3 100644 --- a/xorg-server/hw/dmx/input/usb-mouse.c +++ b/xorg-server/hw/dmx/input/usb-mouse.c @@ -66,61 +66,68 @@ /*****************************************************************************/ /** Read the USB device using #usbRead. */ -void mouUSBRead(DevicePtr pDev, - MOTIONPROC motion, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) +void +mouUSBRead(DevicePtr pDev, + MOTIONPROC motion, + ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) { usbRead(pDev, motion, enqueue, BTN_MISC, block); } /** Initialize \a pDev using #usbInit. */ -void mouUSBInit(DevicePtr pDev) +void +mouUSBInit(DevicePtr pDev) { usbInit(pDev, usbMouse); } /** Turn \a pDev on (i.e., take input from \a pDev). */ -int mouUSBOn(DevicePtr pDev) +int +mouUSBOn(DevicePtr pDev) { GETPRIV; - if (priv->fd < 0) mouUSBInit(pDev); + if (priv->fd < 0) + mouUSBInit(pDev); return priv->fd; } -static void mouUSBGetMap(DevicePtr pDev, unsigned char *map, int *nButtons) +static void +mouUSBGetMap(DevicePtr pDev, unsigned char *map, int *nButtons) { int i; - - if (nButtons) *nButtons = 5; - if (map) for (i = 0; i <= *nButtons; i++) map[i] = i; + + if (nButtons) + *nButtons = 5; + if (map) + for (i = 0; i <= *nButtons; i++) + map[i] = i; } /** Fill the \a info structure with information needed to initialize \a - * pDev. */ -void mouUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) + * pDev. */ +void +mouUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) { static KeySym keyboard_mapping = NoSymbol; - info->buttonClass = 1; + info->buttonClass = 1; mouUSBGetMap(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; - - /* Some USB mice devices return key - * events from their pair'd - * keyboard... */ - info->keyClass = 1; + 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; + + /* Some USB mice devices return key + * events from their pair'd + * keyboard... */ + info->keyClass = 1; info->keySyms.minKeyCode = 8; info->keySyms.maxKeyCode = 8; - info->keySyms.mapWidth = 1; - info->keySyms.map = &keyboard_mapping; + info->keySyms.mapWidth = 1; + info->keySyms.map = &keyboard_mapping; } diff --git a/xorg-server/hw/dmx/input/usb-mouse.h b/xorg-server/hw/dmx/input/usb-mouse.h index 918bf6481..91f6fcf86 100644 --- a/xorg-server/hw/dmx/input/usb-mouse.h +++ b/xorg-server/hw/dmx/input/usb-mouse.h @@ -36,13 +36,12 @@ #ifndef _USB_MOU_H_ #define _USB_MOU_H_ -extern void mouUSBRead(DevicePtr pDev, - dmxMotionProcPtr motion, - dmxEnqueueProcPtr enqueue, - dmxCheckSpecialProcPtr checkspecial, - DMXBlockType block); -extern void mouUSBInit(DevicePtr pDev); -extern void mouUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info); -extern int mouUSBOn(DevicePtr pDev); -extern void mouUSBCtrl(DevicePtr pDev, PtrCtrl *ctrl); +extern void mouUSBRead(DevicePtr pDev, + dmxMotionProcPtr motion, + dmxEnqueueProcPtr enqueue, + dmxCheckSpecialProcPtr checkspecial, DMXBlockType block); +extern void mouUSBInit(DevicePtr pDev); +extern void mouUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info); +extern int mouUSBOn(DevicePtr pDev); +extern void mouUSBCtrl(DevicePtr pDev, PtrCtrl * ctrl); #endif diff --git a/xorg-server/hw/dmx/input/usb-other.c b/xorg-server/hw/dmx/input/usb-other.c index d1074b8e1..f24f259c1 100644 --- a/xorg-server/hw/dmx/input/usb-other.c +++ b/xorg-server/hw/dmx/input/usb-other.c @@ -68,92 +68,97 @@ /*****************************************************************************/ /** Read the USB device using #usbRead. */ -void othUSBRead(DevicePtr pDev, - MOTIONPROC motion, - ENQUEUEPROC enqueue, - CHECKPROC checkspecial, - BLOCK block) +void +othUSBRead(DevicePtr pDev, + MOTIONPROC motion, + ENQUEUEPROC enqueue, CHECKPROC checkspecial, BLOCK block) { usbRead(pDev, motion, enqueue, 0xffff, block); } /** Initialize \a pDev using #usbInit. */ -void othUSBInit(DevicePtr pDev) +void +othUSBInit(DevicePtr pDev) { usbInit(pDev, usbOther); } /** Turn \a pDev on (i.e., take input from \a pDev). */ -int othUSBOn(DevicePtr pDev) +int +othUSBOn(DevicePtr pDev) { GETPRIV; - if (priv->fd < 0) othUSBInit(pDev); + if (priv->fd < 0) + othUSBInit(pDev); return priv->fd; } /** Fill the \a info structure with information needed to initialize \a - * pDev. */ -void othUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) + * pDev. */ +void +othUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info) { GETPRIV; - int i, j; + int i, j; static KeySym keyboard_mapping = NoSymbol; - int absolute[5]; - + int absolute[5]; + #define test_bit(bit) (priv->mask[(bit)/8] & (1 << ((bit)%8))) - /* Some USB mice devices return key - * events from their pair'd - * keyboard... */ - info->keyClass = 1; + /* Some USB mice devices return key + * events from their pair'd + * keyboard... */ + info->keyClass = 1; info->keySyms.minKeyCode = 8; info->keySyms.maxKeyCode = 8; - info->keySyms.mapWidth = 1; - info->keySyms.map = &keyboard_mapping; + info->keySyms.mapWidth = 1; + info->keySyms.map = &keyboard_mapping; for (i = 0; i < EV_MAX; i++) { if (test_bit(i)) { switch (i) { case EV_KEY: - /* See above */ + /* See above */ break; case EV_REL: - info->valuatorClass = 1; + info->valuatorClass = 1; if (info->numRelAxes + info->numAbsAxes > DMX_MAX_AXES - 1) { - info->numRelAxes = DMX_MAX_AXES - info->numAbsAxes - 1; + info->numRelAxes = DMX_MAX_AXES - info->numAbsAxes - 1; dmxLog(dmxWarning, "Can only use %d relative axes\n", info->numRelAxes); - } else - info->numRelAxes = priv->numRel; - info->minval[0] = 0; - info->maxval[0] = 0; - info->res[0] = 1; - info->minres[0] = 0; - info->maxres[0] = 1; + } + else + info->numRelAxes = priv->numRel; + info->minval[0] = 0; + info->maxval[0] = 0; + info->res[0] = 1; + info->minres[0] = 0; + info->maxres[0] = 1; break; case EV_ABS: - info->valuatorClass = 1; + info->valuatorClass = 1; if (info->numRelAxes + info->numAbsAxes > DMX_MAX_AXES - 1) { - info->numAbsAxes = DMX_MAX_AXES - info->numRelAxes - 1; + info->numAbsAxes = DMX_MAX_AXES - info->numRelAxes - 1; dmxLog(dmxWarning, "Can only use %d absolute axes\n", info->numAbsAxes); - } else - info->numAbsAxes = priv->numAbs; + } + else + info->numAbsAxes = priv->numAbs; for (j = 0; j < info->numAbsAxes; j++) { ioctl(priv->fd, EVIOCGABS(j), absolute); - info->minval[1+j] = absolute[1]; - info->maxval[1+j] = absolute[2]; - info->res[1+j] = absolute[3]; - info->minres[1+j] = absolute[3]; - info->maxres[1+j] = absolute[3]; + info->minval[1 + j] = absolute[1]; + info->maxval[1 + j] = absolute[2]; + info->res[1 + j] = absolute[3]; + info->minres[1 + j] = absolute[3]; + info->maxres[1 + j] = absolute[3]; } break; case EV_LED: - info->ledFeedbackClass = 0; /* Not supported at this time */ + info->ledFeedbackClass = 0; /* Not supported at this time */ break; case EV_SND: - info->belFeedbackClass = 0; /* Not supported at this time */ + info->belFeedbackClass = 0; /* Not supported at this time */ break; } } diff --git a/xorg-server/hw/dmx/input/usb-other.h b/xorg-server/hw/dmx/input/usb-other.h index b69e65933..89939a0a2 100644 --- a/xorg-server/hw/dmx/input/usb-other.h +++ b/xorg-server/hw/dmx/input/usb-other.h @@ -36,13 +36,12 @@ #ifndef _USB_OTHER_H_ #define _USB_OTHER_H_ -extern void othUSBRead(DevicePtr pDev, - dmxMotionProcPtr motion, - dmxEnqueueProcPtr enqueue, - dmxCheckSpecialProcPtr checkspecial, - DMXBlockType block); -extern void othUSBInit(DevicePtr pDev); -extern void othUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info); -extern int othUSBOn(DevicePtr pDev); -extern void othUSBCtrl(DevicePtr pDev, PtrCtrl *ctrl); +extern void othUSBRead(DevicePtr pDev, + dmxMotionProcPtr motion, + dmxEnqueueProcPtr enqueue, + dmxCheckSpecialProcPtr checkspecial, DMXBlockType block); +extern void othUSBInit(DevicePtr pDev); +extern void othUSBGetInfo(DevicePtr pDev, DMXLocalInitInfoPtr info); +extern int othUSBOn(DevicePtr pDev); +extern void othUSBCtrl(DevicePtr pDev, PtrCtrl * ctrl); #endif |