From f4092abdf94af6a99aff944d6264bc1284e8bdd4 Mon Sep 17 00:00:00 2001 From: Reinhard Tartler Date: Mon, 10 Oct 2011 17:43:39 +0200 Subject: Imported nx-X11-3.1.0-1.tar.gz Summary: Imported nx-X11-3.1.0-1.tar.gz Keywords: Imported nx-X11-3.1.0-1.tar.gz into Git repository --- .../Xserver/hw/xfree86/os-support/usl/usl_xqueue.c | 360 +++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c (limited to 'nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c') diff --git a/nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c b/nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c new file mode 100644 index 000000000..8b66ee1f8 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c @@ -0,0 +1,360 @@ +/* $XdotOrg: xc/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c,v 1.3 2005/11/10 02:41:20 jkj Exp $ */ +/* + * Copyright 2005 by Kean Johnston + * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany + * Copyright 1993-1999 by The XFree86 Project, Inc. + * + * 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 the copyright holders not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. The copyright holders make no + * representations about the suitability of this software for any purpose. + * It is provided "as is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS 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. + * + */ +/* $XConsortium$ */ + +#include "X.h" +#include "compiler.h" + +#include "xf86.h" +#include "xf86Priv.h" +#include "xf86_OSlib.h" +#include "xf86Xinput.h" +#include "xf86OSmouse.h" +#include "xf86OSKbd.h" +#include "usl_xqueue.h" + +#ifdef XKB +#include "inputstr.h" +#include +#include +#include +extern Bool noXkbExtension; +#endif + +#include "xf86Xinput.h" +#include "mipointer.h" + +#if !defined(XQ_WHEEL) +# define XQ_WHEEL 4 +#endif + +/* + * Implementation notes + * + * This code is based on a mixture of the original XFree86 sysv/xqueue.c + * and information gathered from the SCO X server code (no actual code + * was used, just the principles). + * + * The XFree86 XQUEUE code went to some considerable lengths to implement + * what it calls "asynchronous XQUEUE". This involved creating a pipe, + * and writing to that pipe each time an XQUEUE signal is received. The + * one end of that pipe was then added to the list of selectable file + * descriptors with AddEnabledDevice(). I completely fail to see the need + * for this, and this code does not implement that mechanism. The server + * will be interrupted anyway by the XQUEUE driver, so whether we pull the + * events off the queue at the time we receive the signal or whether we + * write to a pipe and then have the main select() loop stop and call us, + * it makes no difference I can fathom. + * + * The code also differs from the original XFree86 code in that it maintains + * local variables for the number of devices initialized. The original code + * stored that information in the private data pointer of the mouse structure, + * but this same code is used for both the keyboard and the mouse, so that + * was changed. + * + * Part of the difficulty in dealing with XQUEUE is that it is a single + * interface to two devices. The recent changes in XFree86/Xorg try to + * treat the mouse and keyboard as discrete devices, and the code is + * structured in such a way that they should be able to be independently + * opened and closed. But we can't do that with XQUEUE, so we have to + * centralize XQUEUE access here in this module. + */ + +static xqEventQueue *xqQaddr = NULL; +static int xqSigEnable = 1; +static int xqEnableCount = 0; +static struct kd_quemode xqMode; + +/* + * These two pointers are set when the keyboard/mouse handler procs + * are called to turn them on or off. This is so that we can call the + * correct PostEvent for the device. + */ +static InputInfoPtr xqMouse = NULL; +static InputInfoPtr xqKeyboard = NULL; + +static void XqSignalHandler (int signo); + +/* + * Private functions + */ +static void +XqReset (void) +{ + if (xqEnableCount > 0) { + xqQaddr->xq_head = xqQaddr->xq_tail; + xqQaddr->xq_sigenable = xqSigEnable; + } +} + +#ifdef NOTNEEDED +static void +XqLock (void) +{ + xqSigEnable = 0; + if (xqEnableCount > 0) { + xqQaddr->xq_sigenable = xqSigEnable; + } +} + +static void +XqUnlock (void) +{ + xqSigEnable = 1; + if (xqEnableCount > 0) { + xqQaddr->xq_sigenable = xqSigEnable; + } +} +#endif /* NOTNEEDED */ + +/* + * Since this code is shared between two devices, we need to keep track + * of how many times we've been enabled or disabled. For example, if the + * keyboard has been turned off, but the mouse hasn't, then we do not + * want the whole queue off. Only when both devices are turned off do we + * actually disable Xqueue mode. When either device is turned on, we + * enable it. + */ +static int +XqEnable (InputInfoPtr pInfo) +{ + struct sigaction xqsig; + static int msefd = -1; + + if (msefd == -1) { + msefd = open ("/dev/mouse", O_RDONLY | O_NONBLOCK); +#if 0 + msefd = open ("/dev/mouse", O_RDONLY | O_NONBLOCK | O_NOCTTY); + if (msefd < 0) { + /* + * Try giving it a controlling tty + */ + msefd = open (ttyname(xf86Info.consoleFd), O_RDWR | O_NONBLOCK); + if (msefd >= 0) + close (msefd); + msefd = open ("/dev/mouse", O_RDONLY | O_NONBLOCK | O_NOCTTY); + if (msefd < 0) + sleep(2); + } +#endif + } + + if (msefd < 0) { + if (xf86GetAllowMouseOpenFail()) { + ErrorF("%s: cannot open /dev/mouse (%s)\n", + ttyname(xf86Info.consoleFd), strerror(errno)); + } else { + sleep(5); + FatalError ("%s: cannot open /dev/mouse (%s)\n", + ttyname(xf86Info.consoleFd), strerror(errno)); + } + } + + if (xqEnableCount++ == 0) { + xqMode.qaddr = 0; + ioctl (xf86Info.consoleFd, KDQUEMODE, NULL); + + /* + * Note: We need to make sure the signal is armed before we enable + * XQUEUE mode, so that if we get events immediately after the ioctl + * we dont have an unhandled signal coming to the Xserver. + * Also note that we use sigaction, so that we do not have to re-arm + * the signal every time it is delivered, which just slows things + * down (setting a signal is a fairly expensive operation). + */ + + xqsig.sa_handler = XqSignalHandler; + sigfillset (&xqsig.sa_mask); + xqsig.sa_flags = 0; + sigaction (SIGUSR2, &xqsig, NULL); + + /* + * This is a fairly large queue size. Since we are reacting to events + * asynchronously, its best for performance if we deal with as many + * events as possible, and high resolution mice generate a lot of + * events. + */ + xqMode.qsize = 64; + xqMode.signo = SIGUSR2; + xqMode.qaddr = 0; + if (ioctl (xf86Info.consoleFd, KDQUEMODE, &xqMode) < 0) { + xf86Msg (X_ERROR, "%s: could not set XQUEUE mode (%s)", pInfo->name, + strerror(errno)); + xqEnableCount--; + + xqsig.sa_handler = SIG_DFL; + sigfillset (&xqsig.sa_mask); + xqsig.sa_flags = 0; + sigaction (SIGUSR2, &xqsig, NULL); + + return !Success; + } + + /* + * We're in business. The workstation is now in XQUEUE mode. + */ + xqQaddr = (xqEventQueue *)xqMode.qaddr; + xqQaddr->xq_sigenable = 0; /* LOCK */ + nap(500); + XqReset(); + } + return Success; +} + +static int +XqDisable (InputInfoPtr pInfo) +{ + struct sigaction xqsig; + + if (xqEnableCount-- == 1) { + xqQaddr->xq_sigenable = 0; /* LOCK */ + + if (ioctl (xf86Info.consoleFd, KDQUEMODE, NULL) < 0) { + xf86Msg (X_ERROR, "%s: could not unset XQUEUE mode (%s)", pInfo->name, + strerror(errno)); + xqEnableCount++; + return !Success; + } + + xqsig.sa_handler = SIG_DFL; + sigfillset (&xqsig.sa_mask); + xqsig.sa_flags = 0; + sigaction (SIGUSR2, &xqsig, NULL); + } + + return Success; +} + +/* + * XQUEUE signal handler. This is what goes through the list of events + * we've already received and dispatches them to either the keyboard or + * mouse event poster. + */ +static void +XqSignalHandler (int signo) +{ + xqEvent *xqEvents = xqQaddr->xq_events; + int xqHead = xqQaddr->xq_head; + xEvent xE; + MouseDevPtr pMse = NULL; + KbdDevPtr pKbd = NULL; + signed char dx, dy; + + if (xqMouse) + pMse = (MouseDevPtr)xqMouse->private; + if (xqKeyboard) + pKbd = (KbdDevPtr)xqKeyboard->private; + + while (xqHead != xqQaddr->xq_tail) { + + switch (xqEvents[xqHead].xq_type) { + case XQ_MOTION: + dx = (signed char)xqEvents[xqHead].xq_x; + dy = (signed char)xqEvents[xqHead].xq_y; + if (pMse) + pMse->PostEvent(xqMouse, ~(xqEvents[xqHead].xq_code) & 0x07, + (int)dx, (int)dy, 0, 0); + break; + + case XQ_BUTTON: + if (pMse) + pMse->PostEvent(xqMouse, ~(xqEvents[xqHead].xq_code) & 0x07, + 0, 0, 0, 0); + break; + + case XQ_WHEEL: + if (pMse) { + int wbut = pMse->lastButtons, dz; + if (xqEvents[xqHead].xq_code == 1) + dz = 1; + else + dz = -1; + pMse->PostEvent(xqMouse, wbut, 0, 0, dz, 0); + } + break; + + case XQ_KEY: + if (pKbd) + pKbd->PostEvent(xqKeyboard, xqEvents[xqHead].xq_code & 0x7f, + xqEvents[xqHead].xq_code & 0x80 ? FALSE : TRUE); + break; + + default: + xf86Msg(X_WARNING, "XQUEUE: unknown event type %d\n", + xqEvents[xqHead].xq_type); + break; + } + + xqHead++; + if (xqHead == xqQaddr->xq_size) + xqHead = 0; + xf86Info.inputPending = TRUE; + } + + XqReset(); +} + +/* + * Public functions + */ +int +XqMseOnOff (InputInfoPtr pInfo, int on) +{ + if (on) { + if (xqMouse) { + if (xqMouse != pInfo) + xf86Msg(X_WARNING, "XqMseOnOff: mouse pointer structure changed!\n"); + xqMouse = pInfo; + } else { + xqMouse = pInfo; + return XqEnable(pInfo); + } + } else { + xqMouse = NULL; + return XqDisable(pInfo); + } + return Success; +} + +int +XqKbdOnOff (InputInfoPtr pInfo, int on) +{ + if (on) { + if (xqKeyboard) { + if (xqKeyboard != pInfo) + xf86Msg(X_WARNING, "XqKbdOnOff: keyboard pointer structure changed!\n"); + xqKeyboard = pInfo; + } else { + xqKeyboard = pInfo; + return XqEnable(pInfo); + } + } else { + xqKeyboard = NULL; + return XqDisable(pInfo); + } + return Success; +} + -- cgit v1.2.3