aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c')
-rw-r--r--nx-X11/programs/Xserver/hw/xfree86/os-support/usl/usl_xqueue.c360
1 files changed, 360 insertions, 0 deletions
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 <jkj@sco.com>
+ * 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 <X11/extensions/XKB.h>
+#include <X11/extensions/XKBstr.h>
+#include <X11/extensions/XKBsrv.h>
+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;
+}
+