summaryrefslogtreecommitdiff
path: root/hw/xgl
diff options
context:
space:
mode:
authorJon Smirl <jonsmirl@yahoo.com>2005-06-04 23:33:03 +0000
committerJon Smirl <jonsmirl@yahoo.com>2005-06-04 23:33:03 +0000
commitaa959672863aad71c807d6c09938bb296c347bcf (patch)
tree5e4c00379e3786054ded24a0d46e896f12690e97 /hw/xgl
parent88d49bed008264092245c4f6c53174f93f6ab387 (diff)
downloadxserver-aa959672863aad71c807d6c09938bb296c347bcf.tar.gz
Initial Xegl check-in. Works on EGL fbdev driver Input is totally broken.
Diffstat (limited to 'hw/xgl')
-rw-r--r--hw/xgl/egl/Makefile.am16
-rw-r--r--hw/xgl/egl/evdev.c643
-rw-r--r--hw/xgl/egl/kinput.c1683
-rw-r--r--hw/xgl/egl/kkeymap.h58
-rw-r--r--hw/xgl/egl/xegl.c798
-rw-r--r--hw/xgl/egl/xegl.h131
-rw-r--r--hw/xgl/egl/xeglinput.c168
7 files changed, 3497 insertions, 0 deletions
diff --git a/hw/xgl/egl/Makefile.am b/hw/xgl/egl/Makefile.am
new file mode 100644
index 000000000..0a8a736a7
--- /dev/null
+++ b/hw/xgl/egl/Makefile.am
@@ -0,0 +1,16 @@
+INCLUDES = \
+ @XGL_INCS@ \
+ @XEGLSERVER_CFLAGS@ \
+ @XSERVER_CFLAGS@
+
+bin_PROGRAMS = Xegl
+
+Xegl_SOURCES = xegl.c xeglinput.c kinput.c evdev.c
+
+Xegl_LDADD = \
+ @XGL_LIBS@ \
+ @XEGLSERVER_LIBS@ \
+ @XSERVER_LIBS@
+
+Xegl_DEPENDENCIES = @XGL_LIBS@
+
diff --git a/hw/xgl/egl/evdev.c b/hw/xgl/egl/evdev.c
new file mode 100644
index 000000000..a8585cf4d
--- /dev/null
+++ b/hw/xgl/egl/evdev.c
@@ -0,0 +1,643 @@
+/*
+ * $Id$
+ *
+ * Copyright © 2004 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#define NEED_EVENTS
+#include <errno.h>
+#include <linux/input.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xpoll.h>
+#define XK_PUBLISHING
+#include <X11/keysym.h>
+#include "inputstr.h"
+#include "kkeymap.h"
+#include "scrnintstr.h"
+#include "xegl.h"
+
+#define NUM_EVENTS 128
+#define ABS_UNSET -65535
+
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define ISBITSET(x,y) ((x)[LONG(y)] & BIT(y))
+#define OFF(x) ((x)%BITS_PER_LONG)
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define BIT(x) (1 << OFF(x))
+#define SETBIT(x,y) ((x)[LONG(y)] |= BIT(y))
+#define CLRBIT(x,y) ((x)[LONG(y)] &= ~BIT(y))
+#define ASSIGNBIT(x,y,z) ((x)[LONG(y)] = ((x)[LONG(y)] & ~BIT(y)) | (z << OFF(y)))
+
+typedef struct _kevdevMouse {
+ /* current device state */
+ int rel[REL_MAX + 1];
+ int abs[ABS_MAX + 1];
+ int prevabs[ABS_MAX + 1];
+ long key[NBITS(KEY_MAX + 1)];
+
+ /* supported device info */
+ long relbits[NBITS(REL_MAX + 1)];
+ long absbits[NBITS(ABS_MAX + 1)];
+ long keybits[NBITS(KEY_MAX + 1)];
+ struct input_absinfo absinfo[ABS_MAX + 1];
+ int max_rel;
+ int max_abs;
+} Kevdev;
+
+static int flags = 0;
+
+static void
+EvdevMotion (KdMouseInfo *mi)
+{
+ Kevdev *ke = mi->driver;
+ int i;
+
+ for (i = 0; i <= ke->max_rel; i++)
+ if (ke->rel[i])
+ {
+ KdEnqueueMouseEvent (mi, flags | KD_MOUSE_DELTA, ke->rel[0], ke->rel[1]);
+ int a;
+// ErrorF ("rel");
+ for (a = 0; a <= ke->max_rel; a++)
+ {
+// if (ISBITSET (ke->relbits, a))
+// ErrorF (" %d=%d", a, ke->rel[a]);
+ ke->rel[a] = 0;
+ }
+// ErrorF ("\n");
+ break;
+ }
+ for (i = 0; i < ke->max_abs; i++)
+ if (ke->abs[i] != ke->prevabs[i])
+ {
+ KdEnqueueMouseEvent (mi, flags, ke->abs[0], ke->abs[1]);
+ int a;
+// ErrorF ("abs");
+ for (a = 0; a <= ke->max_abs; a++)
+ {
+// if (ISBITSET (ke->absbits, a))
+// ErrorF (" %d=%d", a, ke->abs[a]);
+ ke->prevabs[a] = ke->abs[a];
+ }
+// ErrorF ("\n");
+ break;
+ }
+}
+
+static void
+EvdevRead (int evdevPort, void *closure)
+{
+ KdMouseInfo *mi = closure;
+ Kevdev *ke = mi->driver;
+ int i, n, f;
+ struct input_event events[NUM_EVENTS];
+
+ n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));
+ if (n <= 0)
+ return;
+ n /= sizeof (struct input_event);
+ for (i = 0; i < n; i++)
+ {
+ switch (events[i].type) {
+ case EV_SYN:
+ break;
+ case EV_KEY:
+ EvdevMotion (mi);
+ ASSIGNBIT(ke->key,events[i].code, events[i].value);
+ if (events[i].code < 0x100)
+ ErrorF ("key %d %d\n", events[i].code, events[i].value);
+ else
+ ErrorF ("key 0x%x %d\n", events[i].code, events[i].value);
+ switch (events[i].code) {
+ case BTN_LEFT:
+ f = KD_BUTTON_1;
+ break;
+ case BTN_RIGHT:
+ f = KD_BUTTON_2;
+ break;
+ case BTN_MIDDLE:
+ f = KD_BUTTON_3;
+ break;
+ case BTN_FORWARD:
+ f = KD_BUTTON_4;
+ break;
+ case BTN_BACK:
+ f = KD_BUTTON_5;
+ break;
+ }
+ flags |= f;
+ KdEnqueueMouseEvent (mi, KD_MOUSE_DELTA | flags, 0, 0);
+ ErrorF("Flags is %x\n", flags);
+ break;
+ case EV_REL:
+ ErrorF("EV_REL\n");
+ ke->rel[events[i].code] += events[i].value;
+ break;
+ case EV_ABS:
+ ErrorF("EV_ABS\n");
+ ke->abs[events[i].code] = events[i].value;
+ break;
+ }
+ }
+ EvdevMotion (mi);
+}
+
+int EvdevInputType;
+
+char *kdefaultEvdev[] = {
+// "/dev/input/event0",
+// "/dev/input/event1",
+// "/dev/input/event2",
+// "/dev/input/event3",
+// "/dev/input/event4",
+ "/dev/input/event5",
+};
+
+#define NUM_DEFAULT_EVDEV (sizeof (kdefaultEvdev) / sizeof (kdefaultEvdev[0]))
+
+static Bool
+EvdevInit (void)
+{
+ int i;
+ int fd;
+ KdMouseInfo *mi, *next;
+ int n = 0;
+ char *prot;
+ char name[100];
+
+ if (!EvdevInputType)
+ EvdevInputType = KdAllocInputType ();
+
+ for (mi = kdMouseInfo; mi; mi = next)
+ {
+ next = mi->next;
+ prot = mi->prot;
+ if (mi->inputType)
+ continue;
+ if (!mi->name)
+ {
+ for (i = 0; i < NUM_DEFAULT_EVDEV; i++)
+ {
+ fd = open (kdefaultEvdev[i], 2);
+ if (fd >= 0)
+ {
+ ioctl(fd, EVIOCGRAB, 1);
+
+ ioctl(fd, EVIOCGNAME(sizeof(name)), name);
+ ErrorF("Name is %s\n", name);
+ ioctl(fd, EVIOCGPHYS(sizeof(name)), name);
+ ErrorF("Phys Loc is %s\n", name);
+ ioctl(fd, EVIOCGUNIQ(sizeof(name)), name);
+ ErrorF("Unique is %s\n", name);
+
+ mi->name = KdSaveString (kdefaultEvdev[i]);
+ break;
+ }
+ }
+ }
+ else
+ fd = open (mi->name, 2);
+
+ if (fd >= 0)
+ {
+ unsigned long ev[NBITS(EV_MAX)];
+ Kevdev *ke;
+
+ if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0)
+ {
+ perror ("EVIOCGBIT 0");
+ close (fd);
+ continue;
+ }
+ ke = xalloc (sizeof (Kevdev));
+ if (!ke)
+ {
+ close (fd);
+ continue;
+ }
+ memset (ke, '\0', sizeof (Kevdev));
+ if (ISBITSET (ev, EV_KEY))
+ {
+ if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)),
+ ke->keybits) < 0)
+ {
+ perror ("EVIOCGBIT EV_KEY");
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ }
+ if (ISBITSET (ev, EV_REL))
+ {
+ if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)),
+ ke->relbits) < 0)
+ {
+ perror ("EVIOCGBIT EV_REL");
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--)
+ if (ISBITSET(ke->relbits, ke->max_rel))
+ break;
+ }
+ if (ISBITSET (ev, EV_ABS))
+ {
+ int i;
+
+ if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)),
+ ke->absbits) < 0)
+ {
+ perror ("EVIOCGBIT EV_ABS");
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--)
+ if (ISBITSET(ke->absbits, ke->max_abs))
+ break;
+ for (i = 0; i <= ke->max_abs; i++)
+ {
+ if (ISBITSET (ke->absbits, i))
+ if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0)
+ {
+ perror ("EVIOCGABS");
+ break;
+ }
+ ke->prevabs[i] = ABS_UNSET;
+ }
+ if (i <= ke->max_abs)
+ {
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ }
+ mi->driver = ke;
+ mi->inputType = EvdevInputType;
+ if (KdRegisterFd (EvdevInputType, fd, EvdevRead, (void *) mi))
+ n++;
+ }
+ }
+ return TRUE;
+}
+
+static void
+EvdevFini (void)
+{
+ KdMouseInfo *mi;
+
+ KdUnregisterFds (EvdevInputType, TRUE);
+ for (mi = kdMouseInfo; mi; mi = mi->next)
+ {
+ if (mi->inputType == EvdevInputType)
+ {
+ xfree (mi->driver);
+ mi->driver = 0;
+ mi->inputType = 0;
+ }
+ }
+}
+
+KdMouseFuncs LinuxEvdevMouseFuncs = {
+ EvdevInit,
+ EvdevFini,
+};
+
+
+static void EvdevKbdLoad(void)
+{
+}
+
+static const KeySym linux_to_x[128] = {
+/*KEY_RESERVED*/ NoSymbol,
+/*KEY_ESC*/ XK_Escape,
+/*KEY_1*/ XK_1,
+/*KEY_2*/ XK_2,
+/*KEY_3*/ XK_3,
+/*KEY_4*/ XK_4,
+/*KEY_5*/ XK_5,
+/*KEY_6*/ XK_6,
+/*KEY_7*/ XK_7,
+/*KEY_8*/ XK_8,
+/*KEY_9*/ XK_9,
+/*KEY_0*/ XK_0,
+/*KEY_MINUS*/ XK_minus,
+/*KEY_EQUAL*/ XK_equal,
+/*KEY_BACKSPACE*/ XK_BackSpace,
+/*KEY_TAB*/ XK_Tab,
+/*KEY_Q*/ XK_Q,
+/*KEY_W*/ XK_W,
+/*KEY_E*/ XK_E,
+/*KEY_R*/ XK_R,
+/*KEY_T*/ XK_T,
+/*KEY_Y*/ XK_Y,
+/*KEY_U*/ XK_U,
+/*KEY_I*/ XK_I,
+/*KEY_O*/ XK_O,
+/*KEY_P*/ XK_P,
+/*KEY_LEFTBRACE*/ XK_braceleft,
+/*KEY_RIGHTBRACE*/ XK_braceright,
+/*KEY_ENTER*/ XK_Return,
+/*KEY_LEFTCTRL*/ XK_Control_L,
+/*KEY_A*/ XK_A,
+/*KEY_S*/ XK_S,
+/*KEY_D*/ XK_D,
+/*KEY_F*/ XK_F,
+/*KEY_G*/ XK_G,
+/*KEY_H*/ XK_H,
+/*KEY_J*/ XK_J,
+/*KEY_K*/ XK_K,
+/*KEY_L*/ XK_L,
+/*KEY_SEMICOLON*/ XK_semicolon,
+/*KEY_APOSTROPHE*/ XK_apostrophe,
+/*KEY_GRAVE*/ XK_grave,
+/*KEY_LEFTSHIFT*/ XK_Shift_L,
+/*KEY_BACKSLASH*/ XK_backslash,
+/*KEY_Z*/ XK_Z,
+/*KEY_X*/ XK_X,
+/*KEY_C*/ XK_C,
+/*KEY_V*/ XK_V,
+/*KEY_B*/ XK_B,
+/*KEY_N*/ XK_N,
+/*KEY_M*/ XK_M,
+/*KEY_COMMA*/ XK_comma,
+/*KEY_DOT*/ XK_period,
+/*KEY_SLASH*/ XK_slash,
+/*KEY_RIGHTSHIFT*/ XK_Shift_R,
+/*KEY_KPASTERISK*/ XK_KP_Multiply,
+/*KEY_LEFTALT*/ XK_Alt_L,
+/*KEY_SPACE*/ XK_space,
+/*KEY_CAPSLOCK*/ XK_Caps_Lock,
+/*KEY_F1*/ XK_F1,
+/*KEY_F2*/ XK_F2,
+/*KEY_F3*/ XK_F3,
+/*KEY_F4*/ XK_F4,
+/*KEY_F5*/ XK_F5,
+/*KEY_F6*/ XK_F6,
+/*KEY_F7*/ XK_F7,
+/*KEY_F8*/ XK_F8,
+/*KEY_F9*/ XK_F9,
+/*KEY_F10*/ XK_F10,
+/*KEY_NUMLOCK*/ XK_Num_Lock,
+/*KEY_SCROLLLOCK*/ XK_Scroll_Lock,
+/*KEY_KP7*/ XK_KP_7,
+/*KEY_KP8*/ XK_KP_8,
+/*KEY_KP9*/ XK_KP_9,
+/*KEY_KPMINUS*/ XK_KP_Subtract,
+/*KEY_KP4*/ XK_KP_4,
+/*KEY_KP5*/ XK_KP_5,
+/*KEY_KP6*/ XK_KP_6,
+/*KEY_KPPLUS*/ XK_KP_Add,
+/*KEY_KP1*/ XK_KP_1,
+/*KEY_KP2*/ XK_KP_2,
+/*KEY_KP3*/ XK_KP_3,
+/*KEY_KP0*/ XK_KP_0,
+/*KEY_KPDOT*/ XK_KP_Decimal,
+/*KEY_ZENKAKUHANKAKU*/ NoSymbol,
+/*KEY_102ND*/ NoSymbol,
+/*KEY_F11*/ XK_F11,
+/*KEY_F12*/ XK_F12,
+/*KEY_RO*/ NoSymbol,
+/*KEY_KATAKANA*/ NoSymbol,
+/*KEY_HIRAGANA*/ NoSymbol,
+/*KEY_HENKAN*/ NoSymbol,
+/*KEY_KATAKANAHIRAGANA*/ NoSymbol,
+/*KEY_MUHENKAN*/ NoSymbol,
+/*KEY_KPJPCOMMA*/ NoSymbol,
+/*KEY_KPENTER*/ XK_KP_Enter,
+/*KEY_RIGHTCTRL*/ XK_Control_R,
+/*KEY_KPSLASH*/ XK_KP_Divide,
+/*KEY_SYSRQ*/ NoSymbol,
+/*KEY_RIGHTALT*/ XK_Alt_R,
+/*KEY_LINEFEED*/ XK_Linefeed,
+/*KEY_HOME*/ XK_Home,
+/*KEY_UP*/ XK_Up,
+/*KEY_PAGEUP*/ XK_Prior,
+/*KEY_LEFT*/ XK_Left,
+/*KEY_RIGHT*/ XK_Right,
+/*KEY_END*/ XK_End,
+/*KEY_DOWN*/ XK_Down,
+/*KEY_PAGEDOWN*/ XK_Next,
+/*KEY_INSERT*/ XK_Insert,
+/*KEY_DELETE*/ XK_Delete,
+/*KEY_MACRO*/ NoSymbol,
+/*KEY_MUTE*/ NoSymbol,
+/*KEY_VOLUMEDOWN*/ NoSymbol,
+/*KEY_VOLUMEUP*/ NoSymbol,
+/*KEY_POWER*/ NoSymbol,
+/*KEY_KPEQUAL*/ NoSymbol,
+/*KEY_KPPLUSMINUS*/ NoSymbol,
+/*KEY_PAUSE*/ NoSymbol,
+/*KEY_KPCOMMA*/ XK_KP_Separator,
+/*KEY_HANGUEL*/ NoSymbol,
+/*KEY_HANJA*/ NoSymbol,
+/*KEY_YEN*/ NoSymbol,
+/*KEY_LEFTMETA*/ NoSymbol,
+/*KEY_RIGHTMETA*/ NoSymbol,
+/*KEY_COMPOSE*/ NoSymbol,
+};
+
+static void
+EvdevRead1 (int evdevPort, void *closure)
+{
+ int i, n, xk;
+ struct input_event events[NUM_EVENTS];
+
+ n = read (evdevPort, &events, NUM_EVENTS * sizeof (struct input_event));
+ if (n <= 0)
+ return;
+ n /= sizeof (struct input_event);
+ for (i = 0; i < n; i++)
+ {
+ switch (events[i].type) {
+ case EV_SYN:
+ break;
+ case EV_KEY:
+ xk = NoSymbol;
+ if (events[i].code < 128)
+ xk = linux_to_x[events[i].code];
+ if (events[i].code < 0x100)
+ ErrorF ("key %d %d xk %d\n", events[i].code, events[i].value, xk);
+ else
+ ErrorF ("key 0x%x %d xk %d\n", events[i].code, events[i].value, xk);
+ if (events[i].value == 2) {
+ KdEnqueueKeyboardEvent (xk - KD_MIN_KEYCODE, 0);
+ KdEnqueueKeyboardEvent (xk - KD_MIN_KEYCODE, 1);
+ } else
+ KdEnqueueKeyboardEvent (xk - KD_MIN_KEYCODE, !events[i].value);
+ break;
+ }
+ }
+}
+
+char *kdefaultEvdev1[] = {
+// "/dev/input/event0",
+// "/dev/input/event1",
+// "/dev/input/event2",
+ "/dev/input/event3",
+// "/dev/input/event4",
+// "/dev/input/event5",
+};
+
+#define NUM_DEFAULT_EVDEV1 (sizeof (kdefaultEvdev1) / sizeof (kdefaultEvdev1[0]))
+
+static Bool
+EvdevKbdInit (void)
+{
+ int i;
+ int fd;
+ int n = 0;
+ char name[100];
+
+ kdMinScanCode = 0;
+ kdMaxScanCode = 255;
+
+ if (!EvdevInputType)
+ EvdevInputType = KdAllocInputType ();
+
+ for (i = 0; i < NUM_DEFAULT_EVDEV; i++)
+ {
+ fd = open (kdefaultEvdev1[i], 2);
+ if (fd >= 0)
+ {
+ ioctl(fd, EVIOCGRAB, 1);
+
+ ioctl(fd, EVIOCGNAME(sizeof(name)), name);
+ ErrorF("Name is %s\n", name);
+ ioctl(fd, EVIOCGPHYS(sizeof(name)), name);
+ ErrorF("Phys Loc is %s\n", name);
+ ioctl(fd, EVIOCGUNIQ(sizeof(name)), name);
+ ErrorF("Unique is %s\n", name);
+
+ }
+
+ if (fd >= 0)
+ {
+ unsigned long ev[NBITS(EV_MAX)];
+ Kevdev *ke;
+
+ if (ioctl (fd, EVIOCGBIT(0 /*EV*/, sizeof (ev)), ev) < 0)
+ {
+ perror ("EVIOCGBIT 0");
+ close (fd);
+ continue;
+ }
+ ke = xalloc (sizeof (Kevdev));
+ if (!ke)
+ {
+ close (fd);
+ continue;
+ }
+ memset (ke, '\0', sizeof (Kevdev));
+ if (ISBITSET (ev, EV_KEY))
+ {
+ if (ioctl (fd, EVIOCGBIT (EV_KEY, sizeof (ke->keybits)),
+ ke->keybits) < 0)
+ {
+ perror ("EVIOCGBIT EV_KEY");
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ }
+ if (ISBITSET (ev, EV_REL))
+ {
+ if (ioctl (fd, EVIOCGBIT (EV_REL, sizeof (ke->relbits)),
+ ke->relbits) < 0)
+ {
+ perror ("EVIOCGBIT EV_REL");
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ for (ke->max_rel = REL_MAX; ke->max_rel >= 0; ke->max_rel--)
+ if (ISBITSET(ke->relbits, ke->max_rel))
+ break;
+ }
+ if (ISBITSET (ev, EV_ABS))
+ {
+ int i;
+
+ if (ioctl (fd, EVIOCGBIT (EV_ABS, sizeof (ke->absbits)),
+ ke->absbits) < 0)
+ {
+ perror ("EVIOCGBIT EV_ABS");
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ for (ke->max_abs = ABS_MAX; ke->max_abs >= 0; ke->max_abs--)
+ if (ISBITSET(ke->absbits, ke->max_abs))
+ break;
+ for (i = 0; i <= ke->max_abs; i++)
+ {
+ if (ISBITSET (ke->absbits, i))
+ if (ioctl (fd, EVIOCGABS(i), &ke->absinfo[i]) < 0)
+ {
+ perror ("EVIOCGABS");
+ break;
+ }
+ ke->prevabs[i] = ABS_UNSET;
+ }
+ if (i <= ke->max_abs)
+ {
+ xfree (ke);
+ close (fd);
+ continue;
+ }
+ }
+ if (KdRegisterFd (EvdevInputType, fd, EvdevRead1, NULL))
+ n++;
+ }
+ }
+ return TRUE;
+}
+
+static void
+EvdevKbdFini (void)
+{
+}
+
+static void
+EvdevKbdLeds (int leds)
+{
+}
+
+
+static void EvdevKbdBell(int volume, int pitch, int duration)
+{
+}
+
+
+KdKeyboardFuncs LinuxEvdevKeyboardFuncs = {
+ EvdevKbdLoad,
+ EvdevKbdInit,
+ EvdevKbdLeds,
+ EvdevKbdBell,
+ EvdevKbdFini,
+ 0,
+};
diff --git a/hw/xgl/egl/kinput.c b/hw/xgl/egl/kinput.c
new file mode 100644
index 000000000..231331941
--- /dev/null
+++ b/hw/xgl/egl/kinput.c
@@ -0,0 +1,1683 @@
+/*
+ * Id: kinput.c,v 1.1 1999/11/02 03:54:46 keithp Exp $
+ *
+ * Copyright 1999 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.
+ */
+/* $RCSId: xc/programs/Xserver/hw/kdrive/kinput.c,v 1.30 2002/11/13 16:37:39 keithp Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdio.h>
+
+#include "xgl.h"
+#include "xegl.h"
+#include "mipointer.h"
+#include "inputstr.h"
+
+#define XK_PUBLISHING
+#include <X11/keysym.h>
+#if HAVE_X11_XF86KEYSYM_H
+#include <X11/XF86keysym.h>
+#endif
+#include "kkeymap.h"
+
+#ifdef XKB
+#define XKB_IN_SERVER
+#include <X11/extensions/XKBsrv.h>
+#endif
+
+static DeviceIntPtr pKdKeyboard, pKdPointer;
+
+#define MAX_MOUSE_DRIVERS 6
+
+static KdMouseFuncs *kdMouseFuncs[MAX_MOUSE_DRIVERS];
+static int kdNMouseFuncs;
+static KdKeyboardFuncs *kdKeyboardFuncs;
+static int kdBellPitch;
+static int kdBellDuration;
+static int kdLeds;
+static Bool kdInputEnabled;
+static Bool kdOffScreen;
+static unsigned long kdOffScreenTime;
+static KdMouseMatrix kdMouseMatrix = {
+ { { 1, 0, 0 },
+ { 0, 1, 0 } }
+};
+
+int kdMouseButtonCount;
+int kdMinScanCode;
+int kdMaxScanCode;
+int kdMinKeyCode;
+int kdMaxKeyCode;
+int kdKeymapWidth = KD_MAX_WIDTH;
+KeySym kdKeymap[KD_MAX_LENGTH * KD_MAX_WIDTH];
+CARD8 kdModMap[MAP_LENGTH];
+KeySymsRec kdKeySyms;
+
+
+void
+KdResetInputMachine (void);
+
+#define KD_KEY_COUNT 248
+
+CARD8 kdKeyState[KD_KEY_COUNT/8];
+
+#define IsKeyDown(key) ((kdKeyState[(key) >> 3] >> ((key) & 7)) & 1)
+
+#define KD_MAX_INPUT_FDS 8
+
+typedef struct _kdInputFd {
+ int type;
+ int fd;
+ void (*read) (int fd, void *closure);
+ int (*enable) (int fd, void *closure);
+ void (*disable) (int fd, void *closure);
+ void *closure;
+} KdInputFd;
+
+KdInputFd kdInputFds[KD_MAX_INPUT_FDS];
+int kdNumInputFds;
+int kdInputTypeSequence;
+
+static void
+KdSigio (int sig)
+{
+ int i;
+
+ for (i = 0; i < kdNumInputFds; i++)
+ (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
+}
+
+static void
+KdBlockSigio (void)
+{
+ sigset_t set;
+
+ sigemptyset (&set);
+ sigaddset (&set, SIGIO);
+ sigprocmask (SIG_BLOCK, &set, 0);
+}
+
+static void
+KdUnblockSigio (void)
+{
+ sigset_t set;
+
+ sigemptyset (&set);
+ sigaddset (&set, SIGIO);
+ sigprocmask (SIG_UNBLOCK, &set, 0);
+}
+
+#undef VERIFY_SIGIO
+#ifdef VERIFY_SIGIO
+
+void
+KdAssertSigioBlocked (char *where)
+{
+ sigset_t set, old;
+
+ sigemptyset (&set);
+ sigprocmask (SIG_BLOCK, &set, &old);
+ if (!sigismember (&old, SIGIO))
+ ErrorF ("SIGIO not blocked at %s\n", where);
+}
+
+#else
+
+#define KdAssertSigioBlocked(s)
+
+#endif
+
+static int kdnFds;
+
+#ifdef FNONBLOCK
+#define NOBLOCK FNONBLOCK
+#else
+#define NOBLOCK FNDELAY
+#endif
+
+static void
+KdNonBlockFd (int fd)
+{
+ int flags;
+ flags = fcntl (fd, F_GETFL);
+ flags |= FASYNC|NOBLOCK;
+ fcntl (fd, F_SETFL, flags);
+}
+
+static void
+KdAddFd (int fd)
+{
+ struct sigaction act;
+ sigset_t set;
+
+ kdnFds++;
+ fcntl (fd, F_SETOWN, getpid());
+ KdNonBlockFd (fd);
+ AddEnabledDevice (fd);
+ memset (&act, '\0', sizeof act);
+ act.sa_handler = KdSigio;
+ sigemptyset (&act.sa_mask);
+ sigaddset (&act.sa_mask, SIGIO);
+ sigaddset (&act.sa_mask, SIGALRM);
+ sigaddset (&act.sa_mask, SIGVTALRM);
+ sigaction (SIGIO, &act, 0);
+ sigemptyset (&set);
+ sigprocmask (SIG_SETMASK, &set, 0);
+}
+
+static void
+KdRemoveFd (int fd)
+{
+ struct sigaction act;
+ int flags;
+
+ kdnFds--;
+ RemoveEnabledDevice (fd);
+ flags = fcntl (fd, F_GETFL);
+ flags &= ~(FASYNC|NOBLOCK);
+ fcntl (fd, F_SETFL, flags);
+ if (kdnFds == 0)
+ {
+ memset (&act, '\0', sizeof act);
+ act.sa_handler = SIG_IGN;
+ sigemptyset (&act.sa_mask);
+ sigaction (SIGIO, &act, 0);
+ }
+}
+
+int
+KdAllocInputType (void)
+{
+ return ++kdInputTypeSequence;
+}
+
+Bool
+KdRegisterFd (int type, int fd, void (*read) (int fd, void *closure), void *closure)
+{
+ if (kdNumInputFds == KD_MAX_INPUT_FDS)
+ return FALSE;
+ kdInputFds[kdNumInputFds].type = type;
+ kdInputFds[kdNumInputFds].fd = fd;
+ kdInputFds[kdNumInputFds].read = read;
+ kdInputFds[kdNumInputFds].enable = 0;
+ kdInputFds[kdNumInputFds].disable = 0;
+ kdInputFds[kdNumInputFds].closure = closure;
+ ++kdNumInputFds;
+ if (kdInputEnabled)
+ KdAddFd (fd);
+ return TRUE;
+}
+
+void
+KdRegisterFdEnableDisable (int fd,
+ int (*enable) (int fd, void *closure),
+ void (*disable) (int fd, void *closure))
+{
+ int i;
+
+ for (i = 0; i < kdNumInputFds; i++)
+ if (kdInputFds[i].fd == fd)
+ {
+ kdInputFds[i].enable = enable;
+ kdInputFds[i].disable = disable;
+ break;
+ }
+}
+
+void
+KdUnregisterFds (int type, Bool do_close)
+{
+ int i, j;
+
+ for (i = 0; i < kdNumInputFds;)
+ {
+ if (kdInputFds[i].type == type)
+ {
+ if (kdInputEnabled)
+ KdRemoveFd (kdInputFds[i].fd);
+ if (do_close)
+ close (kdInputFds[i].fd);
+ --kdNumInputFds;
+ for (j = i; j < kdNumInputFds; j++)
+ kdInputFds[j] = kdInputFds[j+1];
+ }
+ else
+ i++;
+ }
+}
+
+static void
+KdDisableInput (void)
+{
+ int i;
+
+ KdBlockSigio ();
+
+ for (i = 0; i < kdNumInputFds; i++)
+ {
+ KdRemoveFd (kdInputFds[i].fd);
+ if (kdInputFds[i].disable)
+ (*kdInputFds[i].disable) (kdInputFds[i].fd, kdInputFds[i].closure);
+ }
+ kdInputEnabled = FALSE;
+}
+
+static void
+KdEnableInput (void)
+{
+ xEvent xE;
+ int i;
+
+ kdInputEnabled = TRUE;
+ for (i = 0; i < kdNumInputFds; i++)
+ {
+ KdNonBlockFd (kdInputFds[i].fd);
+ if (kdInputFds[i].enable)
+ kdInputFds[i].fd = (*kdInputFds[i].enable) (kdInputFds[i].fd, kdInputFds[i].closure);
+ KdAddFd (kdInputFds[i].fd);
+ }
+
+ /* reset screen saver */
+ xE.u.keyButtonPointer.time = GetTimeInMillis ();
+ NoticeEventTime (&xE);
+
+ KdUnblockSigio ();
+}
+
+static int
+KdMouseProc(DeviceIntPtr pDevice, int onoff)
+{
+ BYTE map[KD_MAX_BUTTON];
+ DevicePtr pDev = (DevicePtr)pDevice;
+ int i;
+
+ if (!pDev)
+ return BadImplementation;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ for (i = 1; i <= kdMouseButtonCount; i++)
+ map[i] = i;
+ InitPointerDeviceStruct(pDev, map, kdMouseButtonCount,
+ miPointerGetMotionEvents,
+ (PtrCtrlProcPtr)NoopDDA,
+ miPointerGetMotionBufferSize());
+ break;
+
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ pKdPointer = pDevice;
+ for (i = 0; i < kdNMouseFuncs; i++)
+ (*kdMouseFuncs[i]->Init)();
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ if (pDev->on)
+ {
+ pDev->on = FALSE;
+ pKdPointer = 0;
+ for (i = 0; i < kdNMouseFuncs; i++)
+ (*kdMouseFuncs[i]->Fini) ();
+ }
+ break;
+ }
+ return Success;
+}
+
+Bool
+LegalModifier(unsigned int key, DevicePtr pDev)
+{
+ return TRUE;
+}
+
+static void
+KdBell (int volume, DeviceIntPtr pDev, pointer ctrl, int something)
+{
+ if (kdInputEnabled)
+ (*kdKeyboardFuncs->Bell) (volume, kdBellPitch, kdBellDuration);
+}
+
+
+static void
+KdSetLeds (void)
+{
+ if (kdInputEnabled)
+ (*kdKeyboardFuncs->Leds) (kdLeds);
+}
+
+static void
+KdSetLed (int led, Bool on)
+{
+ NoteLedState (pKdKeyboard, led, on);
+ kdLeds = pKdKeyboard->kbdfeed->ctrl.leds;
+ KdSetLeds ();
+}
+
+static void
+KdSetMouseMatrix (KdMouseMatrix *matrix)
+{
+ kdMouseMatrix = *matrix;
+}
+
+static void
+KdComputeMouseMatrix (KdMouseMatrix *m, Rotation randr, int width, int height)
+{
+ int x_dir = 1, y_dir = 1;
+ int i, j;
+ int size[2];
+
+ size[0] = width; size[1] = height;
+ if (randr & RR_Reflect_X)
+ x_dir = -1;
+ if (randr & RR_Reflect_Y)
+ y_dir = -1;
+ switch (randr & (RR_Rotate_All)) {
+ case RR_Rotate_0:
+ m->matrix[0][0] = x_dir; m->matrix[0][1] = 0;
+ m->matrix[1][0] = 0; m->matrix[1][1] = y_dir;
+ break;
+ case RR_Rotate_90:
+ m->matrix[0][0] = 0; m->matrix[0][1] = -x_dir;
+ m->matrix[1][0] = y_dir; m->matrix[1][1] = 0;
+ break;
+ case RR_Rotate_180:
+ m->matrix[0][0] = -x_dir; m->matrix[0][1] = 0;
+ m->matrix[1][0] = 0; m->matrix[1][1] = -y_dir;
+ break;
+ case RR_Rotate_270:
+ m->matrix[0][0] = 0; m->matrix[0][1] = x_dir;
+ m->matrix[1][0] = -y_dir; m->matrix[1][1] = 0;
+ break;
+ }
+ for (i = 0; i < 2; i++)
+ {
+ m->matrix[i][2] = 0;
+ for (j = 0 ; j < 2; j++)
+ if (m->matrix[i][j] < 0)
+ m->matrix[i][2] = size[j] - 1;
+ }
+}
+
+static void
+KdKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl)
+{
+ kdLeds = ctrl->leds;
+ kdBellPitch = ctrl->bell_pitch;
+ kdBellDuration = ctrl->bell_duration;
+ KdSetLeds ();
+}
+
+static int
+KdKeybdProc(DeviceIntPtr pDevice, int onoff)
+{
+ Bool ret;
+ DevicePtr pDev = (DevicePtr)pDevice;
+#ifdef XKB
+ XkbComponentNamesRec names;
+#endif
+
+ if (!pDev)
+ return BadImplementation;
+
+ switch (onoff)
+ {
+ case DEVICE_INIT:
+ if (pDev != LookupKeyboardDevice())
+ {
+ return !Success;
+ }
+#ifndef XKB
+ ret = InitKeyboardDeviceStruct(pDev,
+ &kdKeySyms,
+ kdModMap,
+ KdBell, KdKbdCtrl);
+#else
+ memset(&names, 0, sizeof(XkbComponentNamesRec));
+
+ if (XkbInitialMap)
+ names.keymap = XkbInitialMap;
+
+ XkbSetRulesDflts ("base", "pc101", "us", NULL, NULL);
+ ret = XkbInitKeyboardDeviceStruct (pDev,
+ &names,
+ &kdKeySyms,
+ kdModMap,
+ KdBell, KdKbdCtrl);
+#endif
+ if (!ret)
+ return BadImplementation;
+ break;
+ case DEVICE_ON:
+ pDev->on = TRUE;
+ pKdKeyboard = pDevice;
+ if (kdKeyboardFuncs)
+ (*kdKeyboardFuncs->Init) ();
+ break;
+ case DEVICE_OFF:
+ case DEVICE_CLOSE:
+ pKdKeyboard = 0;
+ if (pDev->on)
+ {
+ pDev->on = FALSE;
+ if (kdKeyboardFuncs)
+ (*kdKeyboardFuncs->Fini) ();
+ }
+ break;
+ }
+ return Success;
+}
+
+extern KeybdCtrl defaultKeyboardControl;
+
+static void
+KdInitAutoRepeats (void)
+{
+ int key_code;
+ unsigned char mask;
+ int i;
+ unsigned char *repeats;
+
+ repeats = defaultKeyboardControl.autoRepeats;
+ memset (repeats, '\0', 32);
+ for (key_code = KD_MIN_KEYCODE; key_code <= KD_MAX_KEYCODE; key_code++)
+ {
+ if (!kdModMap[key_code])
+ {
+ i = key_code >> 3;
+ mask = 1 << (key_code & 7);
+ repeats[i] |= mask;
+ }
+ }
+}
+
+const KdKeySymModsRec kdKeySymMods[] = {
+ { XK_Control_L, ControlMask },
+ { XK_Control_R, ControlMask },
+ { XK_Shift_L, ShiftMask },
+ { XK_Shift_R, ShiftMask },
+ { XK_Caps_Lock, LockMask },
+ { XK_Shift_Lock, LockMask },
+ { XK_Alt_L, Mod1Mask },
+ { XK_Alt_R, Mod1Mask },
+ { XK_Meta_L, Mod1Mask },
+ { XK_Meta_R, Mod1Mask },
+ { XK_Num_Lock, Mod2Mask },
+ { XK_Super_L, Mod3Mask },
+ { XK_Super_R, Mod3Mask },
+ { XK_Hyper_L, Mod3Mask },
+ { XK_Hyper_R, Mod3Mask },
+ { XK_Mode_switch, Mod4Mask },
+#ifdef TOUCHSCREEN
+ /* PDA specific hacks */
+#ifdef XF86XK_Start
+ { XF86XK_Start, ControlMask },
+#endif
+ { XK_Menu, ShiftMask },
+ { XK_telephone, Mod1Mask },
+#ifdef XF86XK_AudioRecord
+ { XF86XK_AudioRecord, Mod2Mask },
+#endif
+#ifdef XF86XK_Calendar
+ { XF86XK_Calendar, Mod3Mask }
+#endif
+#endif
+};
+
+#define NUM_SYM_MODS (sizeof(kdKeySymMods) / sizeof(kdKeySymMods[0]))
+
+static void
+KdInitModMap (void)
+{
+ int key_code;
+ int row;
+ int width;
+ KeySym *syms;
+ int i;
+
+ width = kdKeySyms.mapWidth;
+ for (key_code = kdMinKeyCode; key_code <= kdMaxKeyCode; key_code++)
+ {
+ kdModMap[key_code] = 0;
+ syms = kdKeymap + (key_code - kdMinKeyCode) * width;
+ for (row = 0; row < width; row++, syms++)
+ {
+ for (i = 0; i < NUM_SYM_MODS; i++)
+ {
+ if (*syms == kdKeySymMods[i].modsym)
+ kdModMap[key_code] |= kdKeySymMods[i].modbit;
+ }
+ }
+ }
+}
+
+static void
+KdAddMouseDriver(KdMouseFuncs *pMouseFuncs)
+{
+ if (kdNMouseFuncs < MAX_MOUSE_DRIVERS)
+ kdMouseFuncs[kdNMouseFuncs++] = pMouseFuncs;
+}
+
+void
+eglInitInput(KdMouseFuncs *pMouseFuncs,
+ KdKeyboardFuncs *pKeyboardFuncs)
+{
+ DeviceIntPtr pKeyboard, pPointer;
+ KdMouseInfo *mi;
+
+ if (!kdMouseInfo)
+ KdParseMouse (0);
+ kdMouseButtonCount = 0;
+ for (mi = kdMouseInfo; mi; mi = mi->next)
+ {
+ if (mi->nbutton > kdMouseButtonCount)
+ kdMouseButtonCount = mi->nbutton;
+ }
+
+ kdNMouseFuncs = 0;
+ KdAddMouseDriver (pMouseFuncs);
+ kdKeyboardFuncs = pKeyboardFuncs;
+ memset (kdKeyState, '\0', sizeof (kdKeyState));
+ if (kdKeyboardFuncs)
+ (*kdKeyboardFuncs->Load) ();
+ kdMinKeyCode = kdMinScanCode + KD_KEY_OFFSET;
+ kdMaxKeyCode = kdMaxScanCode + KD_KEY_OFFSET;
+ kdKeySyms.map = kdKeymap;
+ kdKeySyms.minKeyCode = kdMinKeyCode;
+ kdKeySyms.maxKeyCode = kdMaxKeyCode;
+ kdKeySyms.mapWidth = kdKeymapWidth;
+ kdLeds = 0;
+ kdBellPitch = 1000;
+ kdBellDuration = 200;
+ kdInputEnabled = TRUE;
+ KdInitModMap ();
+ KdInitAutoRepeats ();
+ KdResetInputMachine ();
+ pPointer = AddInputDevice(KdMouseProc, TRUE);
+ pKeyboard = AddInputDevice(KdKeybdProc, TRUE);
+ RegisterPointerDevice(pPointer);
+ RegisterKeyboardDevice(pKeyboard);
+ miRegisterPointerDevice(screenInfo.screens[0], pPointer);
+ mieqInit(&pKeyboard->public, &pPointer->public);
+#ifdef XINPUT
+ {
+ static long zero1, zero2;
+
+ //SetExtInputCheck (&zero1, &zero2);
+ ErrorF("Extended Input Devices not yet supported. Impelement it at line %d in %s\n",
+ __LINE__, __FILE__);
+ }
+#endif
+}
+
+/*
+ * Middle button emulation state machine
+ *
+ * Possible transitions:
+ * Button 1 press v1
+ * Button 1 release ^1
+ * Button 2 press v2
+ * Button 2 release ^2
+ * Button 3 press v3
+ * Button 3 release ^3
+ * Button other press vo
+ * Button other release ^o
+ * Mouse motion <>
+ * Keyboard event k
+ * timeout ...
+ * outside box <->
+ *
+ * States:
+ * start
+ * button_1_pend
+ * button_1_down
+ * button_2_down
+ * button_3_pend
+ * button_3_down
+ * synthetic_2_down_13
+ * synthetic_2_down_3
+ * synthetic_2_down_1
+ *
+ * Transition diagram
+ *
+ * start
+ * v1 -> (hold) (settimeout) button_1_pend
+ * ^1 -> (deliver) start
+ * v2 -> (deliver) button_2_down
+ * ^2 -> (deliever) start
+ * v3 -> (hold) (settimeout) button_3_pend
+ * ^3 -> (deliver) start
+ * vo -> (deliver) start
+ * ^o -> (deliver) start
+ * <> -> (deliver) start
+ * k -> (deliver) start
+ *
+ * button_1_pend (button 1 is down, timeout pending)
+ * ^1 -> (release) (deliver) start
+ * v2 -> (release) (deliver) button_1_down
+ * ^2 -> (release) (deliver) button_1_down
+ * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13
+ * ^3 -> (release) (deliver) button_1_down
+ * vo -> (release) (deliver) button_1_down
+ * ^o -> (release) (deliver) button_1_down
+ * <-> -> (release) (deliver) button_1_down
+ * <> -> (deliver) button_1_pend
+ * k -> (release) (deliver) button_1_down
+ * ... -> (release) button_1_down
+ *
+ * button_1_down (button 1 is down)
+ * ^1 -> (deliver) start
+ * v2 -> (deliver) button_1_down
+ * ^2 -> (deliver) button_1_down
+ * v3 -> (deliver) button_1_down
+ * ^3 -> (deliver) button_1_down
+ * vo -> (deliver) button_1_down
+ * ^o -> (deliver) button_1_down
+ * <> -> (deliver) button_1_down
+ * k -> (deliver) button_1_down
+ *
+ * button_2_down (button 2 is down)
+ * v1 -> (deliver) button_2_down
+ * ^1 -> (deliver) button_2_down
+ * ^2 -> (deliver) start
+ * v3 -> (deliver) button_2_down
+ * ^3 -> (deliver) button_2_down
+ * vo -> (deliver) button_2_down
+ * ^o -> (deliver) button_2_down
+ * <> -> (deliver) button_2_down
+ * k -> (deliver) button_2_down
+ *
+ * button_3_pend (button 3 is down, timeout pending)
+ * v1 -> (generate v2) synthetic_2_down
+ * ^1 -> (release) (deliver) button_3_down
+ * v2 -> (release) (deliver) button_3_down
+ * ^2 -> (release) (deliver) button_3_down
+ * ^3 -> (release) (deliver) start
+ * vo -> (release) (deliver) button_3_down
+ * ^o -> (release) (deliver) button_3_down
+ * <-> -> (release) (deliver) button_3_down
+ * <> -> (deliver) button_3_pend
+ * k -> (release) (deliver) button_3_down
+ * ... -> (release) button_3_down
+ *
+ * button_3_down (button 3 is down)
+ * v1 -> (deliver) button_3_down
+ * ^1 -> (deliver) button_3_down
+ * v2 -> (deliver) button_3_down
+ * ^2 -> (deliver) button_3_down
+ * ^3 -> (deliver) start
+ * vo -> (deliver) button_3_down
+ * ^o -> (deliver) button_3_down
+ * <> -> (deliver) button_3_down
+ * k -> (deliver) button_3_down
+ *
+ * synthetic_2_down_13 (button 1 and 3 are down)
+ * ^1 -> (generate ^2) synthetic_2_down_3
+ * v2 -> synthetic_2_down_13
+ * ^2 -> synthetic_2_down_13
+ * ^3 -> (generate ^2) synthetic_2_down_1
+ * vo -> (deliver) synthetic_2_down_13
+ * ^o -> (deliver) synthetic_2_down_13
+ * <> -> (deliver) synthetic_2_down_13
+ * k -> (deliver) synthetic_2_down_13
+ *
+ * synthetic_2_down_3 (button 3 is down)
+ * v1 -> (deliver) synthetic_2_down_3
+ * ^1 -> (deliver) synthetic_2_down_3
+ * v2 -> synthetic_2_down_3
+ * ^2 -> synthetic_2_down_3
+ * ^3 -> start
+ * vo -> (deliver) synthetic_2_down_3
+ * ^o -> (deliver) synthetic_2_down_3
+ * <> -> (deliver) synthetic_2_down_3
+ * k -> (deliver) synthetic_2_down_3
+ *
+ * synthetic_2_down_1 (button 1 is down)
+ * ^1 -> start
+ * v2 -> synthetic_2_down_1
+ * ^2 -> synthetic_2_down_1
+ * v3 -> (deliver) synthetic_2_down_1
+ * ^3 -> (deliver) synthetic_2_down_1
+ * vo -> (deliver) synthetic_2_down_1
+ * ^o -> (deliver) synthetic_2_down_1
+ * <> -> (deliver) synthetic_2_down_1
+ * k -> (deliver) synthetic_2_down_1
+ */
+
+typedef enum _inputClass {
+ down_1, up_1,
+ down_2, up_2,
+ down_3, up_3,
+ down_o, up_o,
+ motion, outside_box,
+ keyboard, timeout,
+ num_input_class
+} KdInputClass;
+
+typedef enum _inputAction {
+ noop,
+ hold,
+ setto,
+ deliver,
+ release,
+ clearto,
+ gen_down_2,
+ gen_up_2
+} KdInputAction;
+
+#define MAX_ACTIONS 2
+
+typedef struct _inputTransition {
+ KdInputAction actions[MAX_ACTIONS];
+ KdMouseState nextState;
+} KdInputTransition;
+
+KdInputTransition kdInputMachine[num_input_states][num_input_class] = {
+ /* start */
+ {
+ { { hold, setto }, button_1_pend }, /* v1 */
+ { { deliver, noop }, start }, /* ^1 */
+ { { deliver, noop }, button_2_down }, /* v2 */
+ { { deliver, noop }, start }, /* ^2 */
+ { { hold, setto }, button_3_pend }, /* v3 */
+ { { deliver, noop }, start }, /* ^3 */
+ { { deliver, noop }, start }, /* vo */
+ { { deliver, noop }, start }, /* ^o */
+ { { deliver, noop }, start }, /* <> */
+ { { deliver, noop }, start }, /* <-> */
+ { { noop, noop }, start }, /* k */
+ { { noop, noop }, start }, /* ... */
+ },
+ /* button_1_pend */
+ {
+ { { noop, noop }, button_1_pend }, /* v1 */
+ { { release, deliver }, start }, /* ^1 */
+ { { release, deliver }, button_1_down }, /* v2 */
+ { { release, deliver }, button_1_down }, /* ^2 */
+ { { clearto, gen_down_2 }, synth_2_down_13 }, /* v3 */
+ { { release, deliver }, button_1_down }, /* ^3 */
+ { { release, deliver }, button_1_down }, /* vo */
+ { { release, deliver }, button_1_down }, /* ^o */
+ { { deliver, noop }, button_1_pend }, /* <> */
+ { { release, deliver }, button_1_down }, /* <-> */
+ { { noop, noop }, button_1_down }, /* k */
+ { { release, noop }, button_1_down }, /* ... */
+ },
+ /* button_1_down */
+ {
+ { { noop, noop }, button_1_down }, /* v1 */
+ { { deliver, noop }, start }, /* ^1 */
+ { { deliver, noop }, button_1_down }, /* v2 */
+ { { deliver, noop }, button_1_down }, /* ^2 */
+ { { deliver, noop }, button_1_down }, /* v3 */
+ { { deliver, noop }, button_1_down }, /* ^3 */
+ { { deliver, noop }, button_1_down }, /* vo */
+ { { deliver, noop }, button_1_down }, /* ^o */
+ { { deliver, noop }, button_1_down }, /* <> */
+ { { deliver, noop }, button_1_down }, /* <-> */
+ { { noop, noop }, button_1_down }, /* k */
+ { { noop, noop }, button_1_down }, /* ... */
+ },
+ /* button_2_down */
+ {
+ { { deliver, noop }, button_2_down }, /* v1 */
+ { { deliver, noop }, button_2_down }, /* ^1 */
+ { { noop, noop }, button_2_down }, /* v2 */
+ { { deliver, noop }, start }, /* ^2 */
+ { { deliver, noop }, button_2_down }, /* v3 */
+ { { deliver, noop }, button_2_down }, /* ^3 */
+ { { deliver, noop }, button_2_down }, /* vo */
+ { { deliver, noop }, button_2_down }, /* ^o */
+ { { deliver, noop }, button_2_down }, /* <> */
+ { { deliver, noop }, button_2_down }, /* <-> */
+ { { noop, noop }, button_2_down }, /* k */
+ { { noop, noop }, button_2_down }, /* ... */
+ },
+ /* button_3_pend */
+ {
+ { { clearto, gen_down_2 }, synth_2_down_13 }, /* v1 */
+ { { release, deliver }, button_3_down }, /* ^1 */
+ { { release, deliver }, button_3_down }, /* v2 */
+ { { release, deliver }, button_3_down }, /* ^2 */
+ { { release, deliver }, button_3_down }, /* v3 */
+ { { release, deliver }, start }, /* ^3 */
+ { { release, deliver }, button_3_down }, /* vo */
+ { { release, deliver }, button_3_down }, /* ^o */
+ { { deliver, noop }, button_3_pend }, /* <> */
+ { { release, deliver }, button_3_down }, /* <-> */
+ { { release, noop }, button_3_down }, /* k */
+ { { release, noop }, button_3_down }, /* ... */
+ },
+ /* button_3_down */
+ {
+ { { deliver, noop }, button_3_down }, /* v1 */
+ { { deliver, noop }, button_3_down }, /* ^1 */
+ { { deliver, noop }, button_3_down }, /* v2 */
+ { { deliver, noop }, button_3_down }, /* ^2 */
+ { { noop, noop }, button_3_down }, /* v3 */
+ { { deliver, noop }, start }, /* ^3 */
+ { { deliver, noop }, button_3_down }, /* vo */
+ { { deliver, noop }, button_3_down }, /* ^o */
+ { { deliver, noop }, button_3_down }, /* <> */
+ { { deliver, noop }, button_3_down }, /* <-> */
+ { { noop, noop }, button_3_down }, /* k */
+ { { noop, noop }, button_3_down }, /* ... */
+ },
+ /* synthetic_2_down_13 */
+ {
+ { { noop, noop }, synth_2_down_13 }, /* v1 */
+ { { gen_up_2, noop }, synth_2_down_3 }, /* ^1 */
+ { { noop, noop }, synth_2_down_13 }, /* v2 */
+ { { noop, noop }, synth_2_down_13 }, /* ^2 */
+ { { noop, noop }, synth_2_down_13 }, /* v3 */
+ { { gen_up_2, noop }, synth_2_down_1 }, /* ^3 */
+ { { deliver, noop }, synth_2_down_13 }, /* vo */
+ { { deliver, noop }, synth_2_down_13 }, /* ^o */
+ { { deliver, noop }, synth_2_down_13 }, /* <> */
+ { { deliver, noop }, synth_2_down_13 }, /* <-> */
+ { { noop, noop }, synth_2_down_13 }, /* k */
+ { { noop, noop }, synth_2_down_13 }, /* ... */
+ },
+ /* synthetic_2_down_3 */
+ {
+ { { deliver, noop }, synth_2_down_3 }, /* v1 */
+ { { deliver, noop }, synth_2_down_3 }, /* ^1 */
+ { { deliver, noop }, synth_2_down_3 }, /* v2 */
+ { { deliver, noop }, synth_2_down_3 }, /* ^2 */
+ { { noop, noop }, synth_2_down_3 }, /* v3 */
+ { { noop, noop }, start }, /* ^3 */
+ { { deliver, noop }, synth_2_down_3 }, /* vo */
+ { { deliver, noop }, synth_2_down_3 }, /* ^o */
+ { { deliver, noop }, synth_2_down_3 }, /* <> */
+ { { deliver, noop }, synth_2_down_3 }, /* <-> */
+ { { noop, noop }, synth_2_down_3 }, /* k */
+ { { noop, noop }, synth_2_down_3 }, /* ... */
+ },
+ /* synthetic_2_down_1 */
+ {
+ { { noop, noop }, synth_2_down_1 }, /* v1 */
+ { { noop, noop }, start }, /* ^1 */
+ { { deliver, noop }, synth_2_down_1 }, /* v2 */
+ { { deliver, noop }, synth_2_down_1 }, /* ^2 */
+ { { deliver, noop }, synth_2_down_1 }, /* v3 */
+ { { deliver, noop }, synth_2_down_1 }, /* ^3 */
+ { { deliver, noop }, synth_2_down_1 }, /* vo */
+ { { deliver, noop }, synth_2_down_1 }, /* ^o */
+ { { deliver, noop }, synth_2_down_1 }, /* <> */
+ { { deliver, noop }, synth_2_down_1 }, /* <-> */
+ { { noop, noop }, synth_2_down_1 }, /* k */
+ { { noop, noop }, synth_2_down_1 }, /* ... */
+ },
+};
+
+#define EMULATION_WINDOW 10
+#define EMULATION_TIMEOUT 100
+
+#define EventX(e) ((e)->u.keyButtonPointer.rootX)
+#define EventY(e) ((e)->u.keyButtonPointer.rootY)
+
+static int
+KdInsideEmulationWindow (KdMouseInfo *mi, xEvent *ev)
+{
+ if (ev->u.keyButtonPointer.pad1)
+ {
+ mi->emulationDx += EventX(ev);
+ mi->emulationDy += EventY(ev);
+ }
+ else
+ {
+ mi->emulationDx = EventX(&mi->heldEvent) - EventX(ev);
+ mi->emulationDy = EventY(&mi->heldEvent) - EventY(ev);
+ }
+ return (abs (mi->emulationDx) < EMULATION_WINDOW &&
+ abs (mi->emulationDy) < EMULATION_WINDOW);
+}
+
+static KdInputClass
+KdClassifyInput (KdMouseInfo *mi, xEvent *ev)
+{
+ switch (ev->u.u.type) {
+ case ButtonPress:
+ switch (ev->u.u.detail) {
+ case 1: return down_1;
+ case 2: return down_2;
+ case 3: return down_3;
+ default: return down_o;
+ }
+ break;
+ case ButtonRelease:
+ switch (ev->u.u.detail) {
+ case 1: return up_1;
+ case 2: return up_2;
+ case 3: return up_3;
+ default: return up_o;
+ }
+ break;
+ case MotionNotify:
+ if (mi->eventHeld && !KdInsideEmulationWindow(mi, ev))
+ return outside_box;
+ else
+ return motion;
+ default:
+ return keyboard;
+ }
+ return keyboard;
+}
+
+#ifndef NDEBUG
+char *kdStateNames[] = {
+ "start",
+ "button_1_pend",
+ "button_1_down",
+ "button_2_down",
+ "button_3_pend",
+ "button_3_down",
+ "synth_2_down_13",
+ "synth_2_down_3",
+ "synthetic_2_down_1",
+ "num_input_states"
+};
+
+char *kdClassNames[] = {
+ "down_1", "up_1",
+ "down_2", "up_2",
+ "down_3", "up_3",
+ "motion", "ouside_box",
+ "keyboard", "timeout",
+ "num_input_class"
+};
+
+char *kdActionNames[] = {
+ "noop",
+ "hold",
+ "setto",
+ "deliver",
+ "release",
+ "clearto",
+ "gen_down_2",
+ "gen_up_2",
+};
+#endif
+
+static void
+KdQueueEvent (xEvent *ev)
+{
+ KdAssertSigioBlocked ("KdQueueEvent");
+ if (ev->u.u.type == MotionNotify)
+ {
+ if (ev->u.keyButtonPointer.pad1)
+ {
+ ev->u.keyButtonPointer.pad1 = 0;
+ miPointerDeltaCursor (ev->u.keyButtonPointer.rootX,
+ ev->u.keyButtonPointer.rootY,
+ ev->u.keyButtonPointer.time);
+ }
+ else
+ {
+ miPointerAbsoluteCursor(ev->u.keyButtonPointer.rootX,
+ ev->u.keyButtonPointer.rootY,
+ ev->u.keyButtonPointer.time);
+ }
+ }
+ else
+ {
+ mieqEnqueue (ev);
+ }
+}
+
+static void
+KdRunMouseMachine (KdMouseInfo *mi, KdInputClass c, xEvent *ev)
+{
+ KdInputTransition *t;
+ int a;
+
+ t = &kdInputMachine[mi->mouseState][c];
+ for (a = 0; a < MAX_ACTIONS; a++)
+ {
+ switch (t->actions[a]) {
+ case noop:
+ break;
+ case hold:
+ mi->eventHeld = TRUE;
+ mi->emulationDx = 0;
+ mi->emulationDy = 0;
+ mi->heldEvent = *ev;
+ break;
+ case setto:
+ mi->emulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT;
+ mi->timeoutPending = TRUE;
+ break;
+ case deliver:
+ KdQueueEvent (ev);
+ break;
+ case release:
+ mi->eventHeld = FALSE;
+ mi->timeoutPending = FALSE;
+ KdQueueEvent (&mi->heldEvent);
+ break;
+ case clearto:
+ mi->timeoutPending = FALSE;
+ break;
+ case gen_down_2:
+ ev->u.u.detail = 2;
+ mi->eventHeld = FALSE;
+ KdQueueEvent (ev);
+ break;
+ case gen_up_2:
+ ev->u.u.detail = 2;
+ KdQueueEvent (ev);
+ break;
+ }
+ }
+ mi->mouseState = t->nextState;
+}
+
+void
+KdResetInputMachine (void)
+{
+ KdMouseInfo *mi;
+
+ for (mi = kdMouseInfo; mi; mi = mi->next)
+ {
+ mi->mouseState = start;
+ mi->eventHeld = FALSE;
+ }
+}
+
+static void
+KdHandleMouseEvent (KdMouseInfo *mi, xEvent *ev)
+{
+ if (mi->emulateMiddleButton)
+ KdRunMouseMachine (mi, KdClassifyInput (mi, ev), ev);
+ else
+ KdQueueEvent (ev);
+}
+
+static void
+KdReceiveTimeout (KdMouseInfo *mi)
+{
+ KdRunMouseMachine (mi, timeout, 0);
+}
+
+#define KILL_SEQUENCE ((1L << KK_CONTROL)|(1L << KK_ALT)|(1L << KK_F8)|(1L << KK_F10))
+#define SPECIAL_SEQUENCE ((1L << KK_CONTROL) | (1L << KK_ALT))
+#define SETKILLKEY(b) (KdSpecialKeys |= (1L << (b)))
+#define CLEARKILLKEY(b) (KdSpecialKeys &= ~(1L << (b)))
+#define KEYMAP (pKdKeyboard->key->curKeySyms)
+#define KEYCOL1(k) (KEYMAP.map[((k)-kdMinKeyCode)*KEYMAP.mapWidth])
+
+CARD32 KdSpecialKeys = 0;
+
+extern char dispatchException;
+
+/*
+ * kdCheckTermination
+ *
+ * This function checks for the key sequence that terminates the server. When
+ * detected, it sets the dispatchException flag and returns. The key sequence
+ * is:
+ * Control-Alt
+ * It's assumed that the server will be waken up by the caller when this
+ * function returns.
+ */
+
+extern int nClients;
+
+static void
+KdCheckSpecialKeys(xEvent *xE)
+{
+ KeySym sym = KEYCOL1(xE->u.u.detail);
+
+ if (!pKdKeyboard) return;
+
+ /*
+ * Ignore key releases
+ */
+
+ if (xE->u.u.type == KeyRelease) return;
+
+#ifdef XIPAQ
+ /*
+ * Check for buttons 1, 2 and 3 on the iPAQ
+ */
+ if (sym == XK_Pointer_Button1 && kdMouseInfo) {
+ KdEnqueueMouseEvent(kdMouseInfo, KD_MOUSE_DELTA | KD_BUTTON_1, 0, 0);
+ return;
+ }
+ if (sym == XK_Pointer_Button2 && kdMouseInfo) {
+ KdEnqueueMouseEvent(kdMouseInfo, KD_MOUSE_DELTA | KD_BUTTON_2, 0, 0);
+ return;
+ }
+ if (sym == XK_Pointer_Button3 && kdMouseInfo) {
+ KdEnqueueMouseEvent(kdMouseInfo, KD_MOUSE_DELTA | KD_BUTTON_3, 0, 0);
+ return;
+ }
+#endif
+
+ /*
+ * Check for control/alt pressed
+ */
+ if ((pKdKeyboard->key->state & (ControlMask|Mod1Mask)) !=
+ (ControlMask|Mod1Mask))
+ return;
+
+
+ /*
+ * Let OS function see keysym first
+ */
+
+ if (kdOsFuncs->SpecialKey)
+ if ((*kdOsFuncs->SpecialKey) (sym))
+ return;
+
+ /*
+ * Now check for backspace or delete; these signal the
+ * X server to terminate
+ */
+ switch (sym) {
+ case XK_BackSpace:
+ case XK_Delete:
+ case XK_KP_Delete:
+ /*
+ * Set the dispatch exception flag so the server will terminate the
+ * next time through the dispatch loop.
+ */
+ if (kdDontZap == FALSE)
+ dispatchException |= DE_TERMINATE;
+ break;
+ }
+}
+
+/*
+ * kdEnqueueKeyboardEvent
+ *
+ * This function converts hardware keyboard event information into an X event
+ * and enqueues it using MI. It wakes up the server before returning so that
+ * the event will be processed normally.
+ *
+ */
+
+static void
+KdHandleKeyboardEvent (xEvent *ev)
+{
+ int key = ev->u.u.detail;
+ int byte;
+ CARD8 bit;
+ KdMouseInfo *mi;
+
+ byte = key >> 3;
+ bit = 1 << (key & 7);
+ switch (ev->u.u.type) {
+ case KeyPress:
+ kdKeyState[byte] |= bit;
+ break;
+ case KeyRelease:
+ kdKeyState[byte] &= ~bit;
+ break;
+ }
+ for (mi = kdMouseInfo; mi; mi = mi->next)
+ KdRunMouseMachine (mi, keyboard, 0);
+ KdQueueEvent (ev);
+}
+
+static void
+KdReleaseAllKeys (void)
+{
+ xEvent xE;
+ int key;
+
+ KdBlockSigio ();
+ for (key = 0; key < KD_KEY_COUNT; key++)
+ if (IsKeyDown(key))
+ {
+ xE.u.keyButtonPointer.time = GetTimeInMillis();
+ xE.u.u.type = KeyRelease;
+ xE.u.u.detail = key;
+ KdHandleKeyboardEvent (&xE);
+ }
+ KdUnblockSigio ();
+}
+
+static void
+KdCheckLock (void)
+{
+ KeyClassPtr keyc = pKdKeyboard->key;
+ Bool isSet, shouldBeSet;
+
+ if (kdKeyboardFuncs->LockLed)
+ {
+ isSet = (kdLeds & (1 << (kdKeyboardFuncs->LockLed-1))) != 0;
+ shouldBeSet = (keyc->state & LockMask) != 0;
+ if (isSet != shouldBeSet)
+ {
+ KdSetLed (kdKeyboardFuncs->LockLed, shouldBeSet);
+ }
+ }
+}
+
+void
+KdEnqueueKeyboardEvent(unsigned char scan_code,
+ unsigned char is_up)
+{
+ unsigned char key_code;
+ xEvent xE;
+ KeyClassPtr keyc;
+
+ if (!pKdKeyboard)
+ return;
+ keyc = pKdKeyboard->key;
+
+ xE.u.keyButtonPointer.time = GetTimeInMillis();
+
+ if (kdMinScanCode <= scan_code && scan_code <= kdMaxScanCode)
+ {
+ key_code = scan_code + KD_MIN_KEYCODE - kdMinScanCode;
+
+ /*
+ * Set up this event -- the type may be modified below
+ */
+ if (is_up)
+ xE.u.u.type = KeyRelease;
+ else
+ xE.u.u.type = KeyPress;
+ xE.u.u.detail = key_code;
+
+ switch (KEYCOL1(key_code))
+ {
+ case XK_Num_Lock:
+ case XK_Scroll_Lock:
+ case XK_Shift_Lock:
+ case XK_Caps_Lock:
+ if (xE.u.u.type == KeyRelease)
+ return;
+ if (IsKeyDown (key_code))
+ xE.u.u.type = KeyRelease;
+ else
+ xE.u.u.type = KeyPress;
+ }
+
+ /*
+ * Check pressed keys which are already down
+ */
+ if (IsKeyDown (key_code) && xE.u.u.type == KeyPress)
+ {
+ KeybdCtrl *ctrl = &pKdKeyboard->kbdfeed->ctrl;
+
+ /*
+ * Check auto repeat
+ */
+ if (!ctrl->autoRepeat || keyc->modifierMap[key_code] ||
+ !(ctrl->autoRepeats[key_code >> 3] & (1 << (key_code & 7))))
+ {
+ return;
+ }
+ /*
+ * X delivers press/release even for autorepeat
+ */
+ xE.u.u.type = KeyRelease;
+ KdHandleKeyboardEvent (&xE);
+ xE.u.u.type = KeyPress;
+ }
+ /*
+ * Check released keys which are already up
+ */
+ else if (!IsKeyDown (key_code) && xE.u.u.type == KeyRelease)
+ {
+ return;
+ }
+ KdCheckSpecialKeys (&xE);
+ KdHandleKeyboardEvent (&xE);
+ }
+}
+
+#define SetButton(mi, b, v, s) \
+{\
+ xE.u.u.detail = mi->map[b]; \
+ xE.u.u.type = v; \
+ KdHandleMouseEvent (mi, &xE); \
+}
+
+#define Press(mi, b) SetButton(mi, b, ButtonPress, "Down")
+#define Release(mi, b) SetButton(mi, b, ButtonRelease, "Up")
+
+/*
+ * kdEnqueueMouseEvent
+ *
+ * This function converts hardware mouse event information into X event
+ * information. A mouse movement event is passed off to MI to generate
+ * a MotionNotify event, if appropriate. Button events are created and
+ * passed off to MI for enqueueing.
+ */
+
+static void
+KdMouseAccelerate (DeviceIntPtr device, int *dx, int *dy)
+{
+ PtrCtrl *pCtrl = &device->ptrfeed->ctrl;
+ double speed = sqrt (*dx * *dx + *dy * *dy);
+ double accel;
+ double m;
+
+ /*
+ * Ok, so we want it moving num/den times faster at threshold*2
+ *
+ * accel = m *threshold + b
+ * 1 = m * 0 + b -> b = 1
+ *
+ * num/den = m * (threshold * 2) + 1
+ *
+ * num / den - 1 = m * threshold * 2
+ * (num / den - 1) / threshold * 2 = m
+ */
+ m = (((double) pCtrl->num / (double) pCtrl->den - 1.0) /
+ ((double) pCtrl->threshold * 2.0));
+ accel = m * speed + 1;
+ *dx = accel * *dx;
+ *dy = accel * *dy;
+}
+
+void
+KdEnqueueMouseEvent(KdMouseInfo *mi, unsigned long flags, int rx, int ry)
+{
+ CARD32 ms;
+ xEvent xE;
+ unsigned char buttons;
+ int x, y;
+ int (*matrix)[3] = kdMouseMatrix.matrix;
+ unsigned long button;
+ int n;
+
+ if (!pKdPointer)
+ return;
+
+ ms = GetTimeInMillis();
+
+ if (flags & KD_MOUSE_DELTA)
+ {
+ if (mi->transformCoordinates)
+ {
+ x = matrix[0][0] * rx + matrix[0][1] * ry;
+ y = matrix[1][0] * rx + matrix[1][1] * ry;
+ }
+ else
+ {
+ x = rx;
+ y = ry;
+ }
+ KdMouseAccelerate (pKdPointer, &x, &y);
+ xE.u.keyButtonPointer.pad1 = 1;
+ }
+ else
+ {
+ if (mi->transformCoordinates)
+ {
+ x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2];
+ y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2];
+ }
+ else
+ {
+ x = rx;
+ y = ry;
+ }
+ xE.u.keyButtonPointer.pad1 = 0;
+ }
+ xE.u.keyButtonPointer.time = ms;
+ xE.u.keyButtonPointer.rootX = x;
+ xE.u.keyButtonPointer.rootY = y;
+
+ xE.u.u.type = MotionNotify;
+ xE.u.u.detail = 0;
+ KdHandleMouseEvent (mi, &xE);
+
+ buttons = flags;
+
+ for (button = KD_BUTTON_1, n = 0; button <= KD_BUTTON_5; button <<= 1, n++)
+ {
+ if ((mi->buttonState & button) ^ (buttons & button))
+ {
+ if (buttons & button)
+ {
+ Press(mi, n);
+ }
+ else
+ {
+ Release(mi, n);
+ }
+ }
+ }
+ mi->buttonState = buttons;
+}
+
+static void
+KdEnqueueMotionEvent (KdMouseInfo *mi, int x, int y)
+{
+ xEvent xE;
+ CARD32 ms;
+
+ ms = GetTimeInMillis();
+
+ xE.u.u.type = MotionNotify;
+ xE.u.keyButtonPointer.time = ms;
+ xE.u.keyButtonPointer.rootX = x;
+ xE.u.keyButtonPointer.rootY = y;
+
+ KdHandleMouseEvent (mi, &xE);
+}
+
+static void
+KdBlockHandler (int screen,
+ pointer blockData,
+ pointer timeout,
+ pointer readmask)
+{
+ KdMouseInfo *mi;
+ int myTimeout=0;
+
+ for (mi = kdMouseInfo; mi; mi = mi->next)
+ {
+ if (mi->timeoutPending)
+ {
+ int ms;
+
+ ms = mi->emulationTimeout - GetTimeInMillis ();
+ if (ms < 1)
+ ms = 1;
+ if(ms<myTimeout || myTimeout==0)
+ myTimeout=ms;
+ }
+ }
+ /* if we need to poll for events, do that */
+ if(kdOsFuncs->pollEvents)
+ {
+ (*kdOsFuncs->pollEvents)();
+ myTimeout=20;
+ }
+ if(myTimeout>0)
+ AdjustWaitForDelay (timeout, myTimeout);
+}
+
+void
+KdWakeupHandler (int screen,
+ pointer data,
+ unsigned long lresult,
+ pointer readmask)
+{
+ int result = (int) lresult;
+ fd_set *pReadmask = (fd_set *) readmask;
+ int i;
+ KdMouseInfo *mi;
+
+ if (kdInputEnabled && result > 0)
+ {
+ for (i = 0; i < kdNumInputFds; i++)
+ if (FD_ISSET (kdInputFds[i].fd, pReadmask))
+ {
+ KdBlockSigio ();
+ (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure);
+ KdUnblockSigio ();
+ }
+ }
+ for (mi = kdMouseInfo; mi; mi = mi->next)
+ {
+ if (mi->timeoutPending)
+ {
+ if ((long) (GetTimeInMillis () - mi->emulationTimeout) >= 0)
+ {
+ mi->timeoutPending = FALSE;
+ KdBlockSigio ();
+ KdReceiveTimeout (mi);
+ KdUnblockSigio ();
+ }
+ }
+ }
+// if (kdSwitchPending)
+// kdProcessSwitch ();
+}
+
+#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin))
+
+static Bool
+KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
+{
+ ScreenPtr pScreen = *ppScreen;
+ ScreenPtr pNewScreen;
+ int n;
+ int dx, dy;
+ int best_x, best_y;
+ int n_best_x, n_best_y;
+ CARD32 ms;
+
+ if (kdDisableZaphod || screenInfo.numScreens <= 1)
+ return FALSE;
+
+ if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height)
+ return FALSE;
+
+ ms = GetTimeInMillis ();
+ if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000)
+ return FALSE;
+ kdOffScreen = TRUE;
+ kdOffScreenTime = ms;
+ n_best_x = -1;
+ best_x = 32767;
+ n_best_y = -1;
+ best_y = 32767;
+ for (n = 0; n < screenInfo.numScreens; n++)
+ {
+ pNewScreen = screenInfo.screens[n];
+ if (pNewScreen == pScreen)
+ continue;
+ dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x;
+ dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y;
+ if (*x < 0)
+ {
+ if (dx <= 0 && -dx < best_x)
+ {
+ best_x = -dx;
+ n_best_x = n;
+ }
+ }
+ else if (*x >= pScreen->width)
+ {
+ if (dx >= 0 && dx < best_x)
+ {
+ best_x = dx;
+ n_best_x = n;
+ }
+ }
+ if (*y < 0)
+ {
+ if (dy <= 0 && -dy < best_y)
+ {
+ best_y = -dy;
+ n_best_y = n;
+ }
+ }
+ else if (*y >= pScreen->height)
+ {
+ if (dy >= 0 && dy < best_y)
+ {
+ best_y = dy;
+ n_best_y = n;
+ }
+ }
+ }
+ if (best_y < best_x)
+ n_best_x = n_best_y;
+ if (n_best_x == -1)
+ return FALSE;
+ pNewScreen = screenInfo.screens[n_best_x];
+
+ if (*x < 0)
+ *x += pNewScreen->width;
+ if (*y < 0)
+ *y += pNewScreen->height;
+
+ if (*x >= pScreen->width)
+ *x -= pScreen->width;
+ if (*y >= pScreen->height)
+ *y -= pScreen->height;
+
+ *ppScreen = pNewScreen;
+ return TRUE;
+}
+
+static void
+KdCrossScreen(ScreenPtr pScreen, Bool entering)
+{
+#ifndef XIPAQ
+// if (entering)
+// KdEnableScreen (pScreen);
+// else
+// KdDisableScreen (pScreen);
+#endif
+}
+
+int KdCurScreen; /* current event screen */
+
+static void
+KdWarpCursor (ScreenPtr pScreen, int x, int y)
+{
+ KdBlockSigio ();
+ KdCurScreen = pScreen->myNum;
+ miPointerWarpCursor (pScreen, x, y);
+ KdUnblockSigio ();
+}
+
+miPointerScreenFuncRec kdPointerScreenFuncs =
+{
+ KdCursorOffScreen,
+ KdCrossScreen,
+ KdWarpCursor
+};
+
+void
+ProcessInputEvents ()
+{
+ mieqProcessInputEvents();
+ miPointerUpdate();
+// if (kdSwitchPending)
+// KdProcessSwitch ();
+ KdCheckLock ();
+}
diff --git a/hw/xgl/egl/kkeymap.h b/hw/xgl/egl/kkeymap.h
new file mode 100644
index 000000000..9a21d3597
--- /dev/null
+++ b/hw/xgl/egl/kkeymap.h
@@ -0,0 +1,58 @@
+/*
+ * Id: kkeymap.h,v 1.1 1999/11/02 03:54:46 keithp Exp $
+ *
+ * Copyright 1999 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.
+ */
+/* $RCSId: xc/programs/Xserver/hw/kdrive/kkeymap.h,v 1.1 1999/11/19 13:53:50 hohndel Exp $ */
+/*
+ * All global variables and functions pertaining to keyboard key mapping
+ * live in this header file.
+ */
+
+#ifndef _KKEYMAP_H
+#define _KKEYMAP_H
+
+/* Offset of MIN_SCANCODE to 8 (X minimum scancode value) */
+#define KD_KEY_OFFSET (8 - kdMinScanCode)
+
+#define KD_MIN_KEYCODE 8
+#define KD_MAX_KEYCODE 254
+#define KD_MAX_WIDTH 4
+#define KD_MAX_LENGTH (KD_MAX_KEYCODE - KD_MIN_KEYCODE + 1)
+
+extern int kdMinScanCode;
+extern int kdMaxScanCode;
+extern int kdMinKeyCode;
+extern int kdMaxKeyCode;
+extern int kdKeymapWidth;
+
+extern KeySym kdKeymap[KD_MAX_LENGTH * KD_MAX_WIDTH];
+
+extern CARD8 kdModMap[MAP_LENGTH];
+
+extern KeySymsRec kdKeySyms;
+
+typedef struct {
+ KeySym modsym;
+ int modbit;
+} KdKeySymModsRec;
+
+#endif /* _KKEYMAP_H */
diff --git a/hw/xgl/egl/xegl.c b/hw/xgl/egl/xegl.c
new file mode 100644
index 000000000..93812ec67
--- /dev/null
+++ b/hw/xgl/egl/xegl.c
@@ -0,0 +1,798 @@
+/*
+ * Copyright © 2004 David Reveman
+ *
+ * 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
+ * David Reveman not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior permission.
+ * David Reveman makes no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL DAVID REVEMAN 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.
+ *
+ * Author: David Reveman <davidr@novell.com>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <math.h>
+
+#include <glitz-egl.h>
+
+#include "xgl.h"
+#include "inputstr.h"
+#include "cursorstr.h"
+#include "mipointer.h"
+
+#include "xegl.h"
+
+#define XEGL_DEFAULT_SCREEN_WIDTH 800
+#define XEGL_DEFAULT_SCREEN_HEIGHT 600
+
+int xeglScreenGeneration = -1;
+int xeglScreenPrivateIndex;
+
+#define XEGL_GET_SCREEN_PRIV(pScreen) \
+ ((xeglScreenPtr) (pScreen)->devPrivates[xeglScreenPrivateIndex].ptr)
+
+#define XEGL_SET_SCREEN_PRIV(pScreen, v) \
+ ((pScreen)->devPrivates[xeglScreenPrivateIndex].ptr = (pointer) v)
+
+#define XEGL_SCREEN_PRIV(pScreen) \
+ xeglScreenPtr pScreenPriv = XEGL_GET_SCREEN_PRIV (pScreen)
+
+typedef struct _xeglCursor {
+ Cursor cursor;
+} xeglCursorRec, *xeglCursorPtr;
+
+#define XEGL_GET_CURSOR_PRIV(pCursor, pScreen) \
+ ((xeglCursorPtr) (pCursor)->devPriv[(pScreen)->myNum])
+
+#define XEGL_SET_CURSOR_PRIV(pCursor, pScreen, v) \
+ ((pCursor)->devPriv[(pScreen)->myNum] = (pointer) v)
+
+#define XEGL_CURSOR_PRIV(pCursor, pScreen) \
+ xeglCursorPtr pCursorPriv = XEGL_GET_CURSOR_PRIV (pCursor, pScreen)
+
+char *xDisplayName = NULL;
+EGLDisplay xdisplay;
+EGLScreenMESA xscreen;
+glitz_format_t *xeglCurrentFormat;
+CARD32 lastEventTime = 0;
+ScreenPtr currentScreen = NULL;
+Bool softCursor = TRUE;
+xglScreenInfoRec xglScreenInfo = {
+ NULL, 0, 0, 0, 0, FALSE,
+ DEFAULT_GEOMETRY_DATA_TYPE,
+ DEFAULT_GEOMETRY_USAGE,
+ FALSE,
+ XGL_DEFAULT_PBO_MASK,
+ FALSE
+};
+
+extern miPointerScreenFuncRec kdPointerScreenFuncs;
+
+static Bool
+xeglAllocatePrivates (ScreenPtr pScreen)
+{
+ xeglScreenPtr pScreenPriv;
+
+ if (xeglScreenGeneration != serverGeneration)
+ {
+ xeglScreenPrivateIndex = AllocateScreenPrivateIndex ();
+ if (xeglScreenPrivateIndex < 0)
+ return FALSE;
+
+ xeglScreenGeneration = serverGeneration;
+ }
+
+ pScreenPriv = xalloc (sizeof (xeglScreenRec));
+ if (!pScreenPriv)
+ return FALSE;
+
+ XEGL_SET_SCREEN_PRIV (pScreen, pScreenPriv);
+
+ return TRUE;
+}
+
+static void
+xeglConstrainCursor (ScreenPtr pScreen,
+ BoxPtr pBox)
+{
+}
+
+static void
+xeglCursorLimits (ScreenPtr pScreen,
+ CursorPtr pCursor,
+ BoxPtr pHotBox,
+ BoxPtr pTopLeftBox)
+{
+ *pTopLeftBox = *pHotBox;
+}
+
+static Bool
+xeglDisplayCursor (ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+#if 0
+ XEGL_SCREEN_PRIV (pScreen);
+ XEGL_CURSOR_PRIV (pCursor, pScreen);
+
+ XDefineCursor (xdisplay, pScreenPriv->win, pCursorPriv->cursor);
+#endif
+ return TRUE;
+}
+
+#ifdef ARGB_CURSOR
+
+static Bool
+xeglARGBCursorSupport (void);
+
+static Cursor
+xeglCreateARGBCursor (ScreenPtr pScreen,
+ CursorPtr pCursor);
+
+#endif
+
+static Bool
+xeglRealizeCursor (ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+#if 0
+ xeglCursorPtr pCursorPriv;
+ XImage *ximage;
+ Pixmap source, mask;
+ XColor fgColor, bgColor;
+ GC xgc;
+ unsigned long valuemask;
+ XGCValues values;
+
+ XEGL_SCREEN_PRIV (pScreen);
+
+ valuemask = GCForeground | GCBackground;
+
+ values.foreground = 1L;
+ values.background = 0L;
+
+ pCursorPriv = xalloc (sizeof (xeglCursorRec));
+ if (!pCursorPriv)
+ return FALSE;
+
+ XEGL_SET_CURSOR_PRIV (pCursor, pScreen, pCursorPriv);
+
+#ifdef ARGB_CURSOR
+ if (pCursor->bits->argb)
+ {
+ pCursorPriv->cursor = xeglCreateARGBCursor (pScreen, pCursor);
+ if (pCursorPriv->cursor)
+ return TRUE;
+ }
+#endif
+
+ source = XCreatePixmap (xdisplay,
+ pScreenPriv->win,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 1);
+
+ mask = XCreatePixmap (xdisplay,
+ pScreenPriv->win,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 1);
+
+ xgc = XCreateGC (xdisplay, source, valuemask, &values);
+
+ ximage = XCreateImage (xdisplay,
+ DefaultVisual (xdisplay, xscreen),
+ 1, XYBitmap, 0,
+ (char *) pCursor->bits->source,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ BitmapPad (xdisplay), 0);
+
+ XPutImage (xdisplay, source, xgc, ximage,
+ 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+ XFree (ximage);
+
+ ximage = XCreateImage (xdisplay,
+ DefaultVisual (xdisplay, xscreen),
+ 1, XYBitmap, 0,
+ (char *) pCursor->bits->mask,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ BitmapPad (xdisplay), 0);
+
+ XPutImage (xdisplay, mask, xgc, ximage,
+ 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+ XFree (ximage);
+ XFreeGC (xdisplay, xgc);
+
+ fgColor.red = pCursor->foreRed;
+ fgColor.green = pCursor->foreGreen;
+ fgColor.blue = pCursor->foreBlue;
+
+ bgColor.red = pCursor->backRed;
+ bgColor.green = pCursor->backGreen;
+ bgColor.blue = pCursor->backBlue;
+
+ pCursorPriv->cursor =
+ XCreatePixmapCursor (xdisplay, source, mask, &fgColor, &bgColor,
+ pCursor->bits->xhot, pCursor->bits->yhot);
+
+ XFreePixmap (xdisplay, mask);
+ XFreePixmap (xdisplay, source);
+#endif
+ return TRUE;
+}
+
+static Bool
+xeglUnrealizeCursor (ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+#if 0
+ XEGL_CURSOR_PRIV (pCursor, pScreen);
+
+ XFreeCursor (xdisplay, pCursorPriv->cursor);
+ xfree (pCursorPriv);
+#endif
+ return TRUE;
+}
+
+static void
+xeglRecolorCursor (ScreenPtr pScreen,
+ CursorPtr pCursor,
+ Bool displayed)
+{
+#if 0
+ XColor fgColor, bgColor;
+
+ XEGL_CURSOR_PRIV (pCursor, pScreen);
+
+ fgColor.red = pCursor->foreRed;
+ fgColor.green = pCursor->foreGreen;
+ fgColor.blue = pCursor->foreBlue;
+
+ bgColor.red = pCursor->backRed;
+ bgColor.green = pCursor->backGreen;
+ bgColor.blue = pCursor->backBlue;
+
+ XRecolorCursor (xdisplay, pCursorPriv->cursor, &fgColor, &bgColor);
+#endif
+}
+
+static Bool
+xeglSetCursorPosition (ScreenPtr pScreen,
+ int x,
+ int y,
+ Bool generateEvent)
+{
+#if 0
+ XEGL_SCREEN_PRIV (pScreen);
+
+ XWarpPointer (xdisplay, pScreenPriv->win, pScreenPriv->win,
+ 0, 0, 0, 0, x, y);
+#endif
+ return TRUE;
+}
+
+static Bool
+xeglCloseScreen (int index,
+ ScreenPtr pScreen)
+{
+ glitz_drawable_t *drawable;
+
+ XEGL_SCREEN_PRIV (pScreen);
+
+ drawable = XGL_GET_SCREEN_PRIV (pScreen)->drawable;
+ if (drawable)
+ glitz_drawable_destroy (drawable);
+
+ xglClearVisualTypes ();
+#if 0
+ if (pScreenPriv->win)
+ XDestroyWindow (xdisplay, pScreenPriv->win);
+
+ if (pScreenPriv->colormap)
+ XFreeColormap (xdisplay, pScreenPriv->colormap);
+#endif
+ XGL_SCREEN_UNWRAP (CloseScreen);
+ xfree (pScreenPriv);
+
+ return (*pScreen->CloseScreen) (index, pScreen);
+}
+
+static Bool
+xeglCursorOffScreen (ScreenPtr *ppScreen, int *x, int *y)
+{
+ return FALSE;
+}
+
+static void
+xeglCrossScreen (ScreenPtr pScreen, Bool entering)
+{
+}
+
+static void
+xeglWarpCursor (ScreenPtr pScreen, int x, int y)
+{
+ miPointerWarpCursor (pScreen, x, y);
+}
+
+miPointerScreenFuncRec xeglPointerScreenFuncs = {
+ xeglCursorOffScreen,
+ xeglCrossScreen,
+ xeglWarpCursor
+};
+
+static void
+xeglMoveCursor(ScreenPtr pScreen, int x, int y)
+{
+}
+
+
+#define FB_CUR_SETIMAGE 0x01
+#define FB_CUR_SETPOS 0x02
+#define FB_CUR_SETHOT 0x04
+#define FB_CUR_SETCMAP 0x08
+#define FB_CUR_SETSHAPE 0x10
+#define FB_CUR_SETSIZE 0x20
+#define FB_CUR_SETALL 0xFF
+
+struct fbcurpos {
+ unsigned short x, y;
+};
+
+struct fb_cmap_user {
+ unsigned long start; /* First entry */
+ unsigned long len; /* Number of entries */
+ unsigned short *red; /* Red values */
+ unsigned short *green;
+ unsigned short *blue;
+ unsigned short *transp; /* transparency, can be NULL */
+};
+
+struct fb_image_user {
+ unsigned long dx; /* Where to place image */
+ unsigned long dy;
+ unsigned long width; /* Size of image */
+ unsigned long height;
+ unsigned long fg_color; /* Only used when a mono bitmap */
+ unsigned long bg_color;
+ unsigned char depth; /* Depth of the image */
+ const char *data; /* Pointer to image data */
+ struct fb_cmap_user cmap; /* color map info */
+};
+
+struct fb_cursor_user {
+ unsigned short set; /* what to set */
+ unsigned short enable; /* cursor on/off */
+ unsigned short rop; /* bitop operation */
+ const char *mask; /* cursor mask bits */
+ struct fbcurpos hot; /* cursor hot spot */
+ struct fb_image_user image; /* Cursor image */
+};
+#define FBIO_CURSOR _IOWR('F', 0x08, struct fb_cursor_user)
+
+
+static void
+xeglSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
+{
+#if 0
+ int fd, err;
+ struct fb_cursor_user cursor;
+
+ fd = open("/dev/fb0", O_RDWR);
+ memset(&cursor, 0, sizeof(cursor));
+ cursor.set = FB_CUR_SETPOS;
+ cursor.image.dx = 50;
+ cursor.image.dy = 50;
+ cursor.enable = 1;
+ err = ioctl(fd, FBIO_CURSOR, &cursor);
+ err = errno;
+ printf("errno %d\n", err);
+ close(fd);
+#endif
+}
+
+miPointerSpriteFuncRec eglPointerSpriteFuncs = {
+ xeglRealizeCursor,
+ xeglUnrealizeCursor,
+ xeglSetCursor,
+ xeglMoveCursor,
+};
+
+static Bool
+xeglScreenInit (int index,
+ ScreenPtr pScreen,
+ int argc,
+ char **argv)
+{
+ EGLSurface screen_surf;
+ EGLModeMESA mode;
+ int count;
+ xeglScreenPtr pScreenPriv;
+ glitz_drawable_format_t *format;
+ glitz_drawable_t *drawable;
+ const EGLint screenAttribs[] = {
+ EGL_WIDTH, 1024,
+ EGL_HEIGHT, 768,
+ EGL_NONE
+ };
+
+ xglScreenInfo.width = 1024;
+ xglScreenInfo.height = 768;
+
+ format = xglVisuals[0].format;
+
+ if (!xeglAllocatePrivates (pScreen))
+ return FALSE;
+
+ currentScreen = pScreen;
+
+ pScreenPriv = XEGL_GET_SCREEN_PRIV (pScreen);
+
+ if (xglScreenInfo.fullscreen)
+ {
+// xglScreenInfo.width = DisplayWidth (xdisplay, xscreen);
+// xglScreenInfo.height = DisplayHeight (xdisplay, xscreen);
+// xglScreenInfo.widthMm = DisplayWidthMM (xdisplay, xscreen);
+// xglScreenInfo.heightMm = DisplayHeightMM (xdisplay, xscreen);
+ }
+ else if (xglScreenInfo.width == 0 || xglScreenInfo.height == 0)
+ {
+ xglScreenInfo.width = XEGL_DEFAULT_SCREEN_WIDTH;
+ xglScreenInfo.height = XEGL_DEFAULT_SCREEN_HEIGHT;
+ }
+
+ eglGetModesMESA(xdisplay, xscreen, &mode, 1, &count);
+ screen_surf = eglCreateScreenSurfaceMESA(xdisplay, format->id, screenAttribs);
+ if (screen_surf == EGL_NO_SURFACE) {
+ printf("failed to create screen surface\n");
+ return FALSE;
+ }
+
+ eglShowSurfaceMESA(xdisplay, xscreen, screen_surf, mode);
+
+ drawable = glitz_egl_create_surface (xdisplay, xscreen, format, screen_surf,
+ xglScreenInfo.width, xglScreenInfo.height);
+ if (!drawable)
+ {
+ ErrorF ("[%d] couldn't create glitz drawable for window\n", index);
+ return FALSE;
+ }
+
+// XSelectInput (xdisplay, pScreenPriv->win, ExposureMask);
+// XMapWindow (xdisplay, pScreenPriv->win);
+
+ if (xglScreenInfo.fullscreen)
+ {
+#if 0
+ XClientMessageEvent xev;
+
+ memset (&xev, 0, sizeof (xev));
+
+ xev.type = ClientMessage;
+ xev.message_type = XInternAtom (xdisplay, "_NET_WM_STATE", FALSE);
+ xev.display = xdisplay;
+ xev.window = pScreenPriv->win;
+ xev.format = 32;
+ xev.data.l[0] = 1;
+ xev.data.l[1] =
+ XInternAtom (xdisplay, "_NET_WM_STATE_FULLSCREEN", FALSE);
+
+ XSendEvent (xdisplay, root, FALSE, SubstructureRedirectMask,
+ (XEvent *) &xev);
+#endif
+ }
+
+ xglScreenInfo.drawable = drawable;
+
+ if (!xglScreenInit (pScreen, &xglScreenInfo))
+ return FALSE;
+
+ XGL_SCREEN_WRAP (CloseScreen, xeglCloseScreen);
+
+#ifdef ARGB_CURSOR
+ if (!xeglARGBCursorSupport ())
+ softCursor = TRUE;
+#endif
+ miDCInitialize (pScreen, &xeglPointerScreenFuncs);
+
+// miPointerInitialize(pScreen, &eglPointerSpriteFuncs,
+// &kdPointerScreenFuncs, FALSE);
+
+ if (!xglFinishScreenInit (pScreen))
+ return FALSE;
+
+// while (XNextEvent (xdisplay, &xevent))
+// if (xevent.type == Expose)
+// break;
+
+// XSelectInput (xdisplay, pScreenPriv->win,
+// ButtonPressMask | ButtonReleaseMask |
+// KeyPressMask | KeyReleaseMask | EnterWindowMask |
+// PointerMotionMask);
+
+ return TRUE;
+}
+
+void
+InitOutput (ScreenInfo *pScreenInfo,
+ int argc,
+ char **argv)
+{
+ glitz_drawable_format_t *format, templ;
+ int i, maj, min, count;
+ unsigned long mask;
+ unsigned long extraMask[] = {
+ GLITZ_FORMAT_PBUFFER_MASK |
+ GLITZ_FORMAT_DOUBLEBUFFER_MASK,
+ 0
+ };
+
+ xglSetPixmapFormats (pScreenInfo);
+
+ if (!xdisplay)
+ {
+ xdisplay = eglGetDisplay("!fb_dri");
+ assert(xdisplay);
+
+ if (!eglInitialize(xdisplay, &maj, &min))
+ FatalError ("can't open display");
+
+ eglGetScreensMESA(xdisplay, &xscreen, 1, &count);
+
+ glitz_egl_init (NULL);
+ }
+
+ templ.types.window = 1;
+ templ.types.pbuffer = 1;
+ templ.samples = 1;
+ templ.doublebuffer = 1;
+ templ.color.alpha_size = 8;
+
+ mask =
+ GLITZ_FORMAT_WINDOW_MASK |
+ GLITZ_FORMAT_SAMPLES_MASK;
+
+ for (i = 0; i < sizeof (extraMask) / sizeof (extraMask[0]); i++)
+ {
+ format = glitz_egl_find_config (xdisplay, xscreen,
+ mask | extraMask[i],
+ &templ, 0);
+ if (format)
+ break;
+ }
+
+ if (!format)
+ FatalError ("no visual format found");
+
+ xglSetVisualTypesAndMasks (pScreenInfo, format, (1 << TrueColor));
+
+ xglInitVisuals (pScreenInfo);
+
+ AddScreen (xeglScreenInit, argc, argv);
+}
+
+static void
+xeglBlockHandler (pointer blockData,
+ OSTimePtr pTimeout,
+ pointer pReadMask)
+{
+ XGL_SCREEN_PRIV (currentScreen);
+
+ if (!xglSyncSurface (&pScreenPriv->pScreenPixmap->drawable))
+ FatalError (XGL_SW_FAILURE_STRING);
+
+ glitz_surface_flush (pScreenPriv->surface);
+ glitz_drawable_finish (pScreenPriv->drawable);
+
+// XSync (xdisplay, FALSE);
+}
+
+static void
+xeglWakeupHandler (pointer blockData,
+ int result,
+ pointer pReadMask)
+{
+#if 0
+ ScreenPtr pScreen = currentScreen;
+ XEvent X;
+ xEvent x;
+
+ while (XPending (xdisplay)) {
+ XNextEvent (xdisplay, &X);
+
+ switch (X.type) {
+ case KeyPress:
+ x.u.u.type = KeyPress;
+ x.u.u.detail = X.xkey.keycode;
+ x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
+ mieqEnqueue (&x);
+ break;
+ case KeyRelease:
+ x.u.u.type = KeyRelease;
+ x.u.u.detail = X.xkey.keycode;
+ x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
+ mieqEnqueue (&x);
+ break;
+ case ButtonPress:
+ x.u.u.type = ButtonPress;
+ x.u.u.detail = X.xbutton.button;
+ x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
+ mieqEnqueue (&x);
+ break;
+ case ButtonRelease:
+ x.u.u.type = ButtonRelease;
+ x.u.u.detail = X.xbutton.button;
+ x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
+ mieqEnqueue (&x);
+ break;
+ case MotionNotify:
+ x.u.u.type = MotionNotify;
+ x.u.keyButtonPointer.rootX = X.xmotion.x;
+ x.u.keyButtonPointer.rootY = X.xmotion.y;
+ x.u.keyButtonPointer.time = lastEventTime = GetTimeInMillis ();
+ miPointerAbsoluteCursor (X.xmotion.x, X.xmotion.y, lastEventTime);
+ mieqEnqueue (&x);
+ break;
+ case EnterNotify:
+ if (X.xcrossing.detail != NotifyInferior) {
+ if (pScreen) {
+ NewCurrentScreen (pScreen, X.xcrossing.x, X.xcrossing.y);
+ x.u.u.type = MotionNotify;
+ x.u.keyButtonPointer.rootX = X.xcrossing.x;
+ x.u.keyButtonPointer.rootY = X.xcrossing.y;
+ x.u.keyButtonPointer.time = lastEventTime =
+ GetTimeInMillis ();
+ mieqEnqueue (&x);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+#endif
+}
+
+void
+InitInput (int argc, char **argv)
+{
+ eglInitInput (&LinuxEvdevMouseFuncs, &LinuxEvdevKeyboardFuncs);
+ RegisterBlockAndWakeupHandlers (xeglBlockHandler,
+ KdWakeupHandler,
+ NULL);
+}
+
+void
+ddxUseMsg (void)
+{
+ ErrorF ("\nXegl usage:\n");
+ ErrorF ("-display string display name of the real server\n");
+ ErrorF ("-softcursor force software cursor\n");
+
+ xglUseMsg ();
+}
+
+int
+ddxProcessArgument (int argc, char **argv, int i)
+{
+ if (!strcmp (argv[i], "-display"))
+ {
+ if (++i < argc) {
+ xDisplayName = argv[i];
+ return 2;
+ }
+ return 0;
+ }
+ else if (!strcmp (argv[i], "-softcursor"))
+ {
+ softCursor = TRUE;
+ return 1;
+ }
+
+ return xglProcessArgument (&xglScreenInfo, argc, argv, i);
+}
+
+void
+AbortDDX (void)
+{
+}
+
+void
+ddxGiveUp ()
+{
+ AbortDDX ();
+}
+
+void
+OsVendorInit (void)
+{
+}
+
+#ifdef ARGB_CURSOR
+
+//#include <X11/extensions/Xrender.h>
+
+static Bool
+xeglARGBCursorSupport (void)
+{
+#if 0
+ int renderMajor, renderMinor;
+
+ if (!XRenderQueryVersion (xdisplay, &renderMajor, &renderMinor))
+ renderMajor = renderMinor = -1;
+
+ return (renderMajor > 0 || renderMinor > 4);
+#endif
+ return TRUE;
+}
+
+static Cursor
+xeglCreateARGBCursor (ScreenPtr pScreen,
+ CursorPtr pCursor)
+{
+ Cursor cursor;
+#if 0
+ Pixmap xpixmap;
+ GC xgc;
+ XImage *ximage;
+ XRenderPictFormat *xformat;
+ Picture xpicture;
+
+ XEGL_SCREEN_PRIV (pScreen);
+
+ xpixmap = XCreatePixmap (xdisplay,
+ pScreenPriv->win,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 32);
+
+ xgc = XCreateGC (xdisplay, xpixmap, 0, NULL);
+
+ ximage = XCreateImage (xdisplay,
+ DefaultVisual (xdisplay, xscreen),
+ 32, ZPixmap, 0,
+ (char *) pCursor->bits->argb,
+ pCursor->bits->width,
+ pCursor->bits->height,
+ 32, pCursor->bits->width * 4);
+
+ XPutImage (xdisplay, xpixmap, xgc, ximage,
+ 0, 0, 0, 0, pCursor->bits->width, pCursor->bits->height);
+
+ XFree (ximage);
+ XFreeGC (xdisplay, xgc);
+
+ xformat = XRenderFindStandardFormat (xdisplay, PictStandardARGB32);
+ xpicture = XRenderCreatePicture (xdisplay, xpixmap, xformat, 0, 0);
+
+ cursor = XRenderCreateCursor (xdisplay, xpicture,
+ pCursor->bits->xhot,
+ pCursor->bits->yhot);
+
+ XRenderFreePicture (xdisplay, xpicture);
+ XFreePixmap (xdisplay, xpixmap);
+#endif
+ return cursor;
+}
+
+#endif
diff --git a/hw/xgl/egl/xegl.h b/hw/xgl/egl/xegl.h
new file mode 100644
index 000000000..e75f233ad
--- /dev/null
+++ b/hw/xgl/egl/xegl.h
@@ -0,0 +1,131 @@
+#include "randrstr.h"
+
+#define KD_BUTTON_1 0x01
+#define KD_BUTTON_2 0x02
+#define KD_BUTTON_3 0x04
+#define KD_BUTTON_4 0x08
+#define KD_BUTTON_5 0x10
+#define KD_MOUSE_DELTA 0x80000000
+
+typedef struct _KdMouseFuncs {
+ Bool (*Init) (void);
+ void (*Fini) (void);
+} KdMouseFuncs;
+
+typedef struct _KdKeyboardFuncs {
+ void (*Load) (void);
+ int (*Init) (void);
+ void (*Leds) (int);
+ void (*Bell) (int, int, int);
+ void (*Fini) (void);
+ int LockLed;
+} KdKeyboardFuncs;
+
+typedef struct _KdOsFuncs {
+ int (*Init) (void);
+ void (*Enable) (void);
+ Bool (*SpecialKey) (KeySym);
+ void (*Disable) (void);
+ void (*Fini) (void);
+ void (*pollEvents) (void);
+} KdOsFuncs;
+
+typedef struct _KdMouseMatrix {
+ int matrix[2][3];
+} KdMouseMatrix;
+
+typedef enum _kdMouseState {
+ start,
+ button_1_pend,
+ button_1_down,
+ button_2_down,
+ button_3_pend,
+ button_3_down,
+ synth_2_down_13,
+ synth_2_down_3,
+ synth_2_down_1,
+ num_input_states
+} KdMouseState;
+
+#define KD_MAX_BUTTON 7
+
+typedef struct _KdMouseInfo {
+ struct _KdMouseInfo *next;
+ void *driver;
+ void *closure;
+ char *name;
+ char *prot;
+ char map[KD_MAX_BUTTON];
+ int nbutton;
+ Bool emulateMiddleButton;
+ unsigned long emulationTimeout;
+ Bool timeoutPending;
+ KdMouseState mouseState;
+ Bool eventHeld;
+ xEvent heldEvent;
+ unsigned char buttonState;
+ int emulationDx, emulationDy;
+ int inputType;
+ Bool transformCoordinates;
+} KdMouseInfo;
+
+typedef struct _KdScreenInfo {
+ struct _KdScreenInfo *next;
+ ScreenPtr pScreen;
+ void *driver;
+ Rotation randr; /* rotation and reflection */
+ int width;
+ int height;
+ int rate;
+ int width_mm;
+ int height_mm;
+ int subpixel_order;
+ Bool dumb;
+ Bool softCursor;
+ int mynum;
+ DDXPointRec origin;
+} KdScreenInfo;
+
+#define KD_MAX_FB 2
+#define KD_MAX_PSEUDO_DEPTH 8
+#define KD_MAX_PSEUDO_SIZE (1 << KD_MAX_PSEUDO_DEPTH)
+
+typedef struct _xeglScreen {
+ Window win;
+ Colormap colormap;
+ CloseScreenProcPtr CloseScreen;
+ KdScreenInfo *screen;
+ ColormapPtr pInstalledmap[KD_MAX_FB]; /* current colormap */
+} xeglScreenRec, *xeglScreenPtr;
+
+extern KdMouseInfo *kdMouseInfo;
+extern KdOsFuncs *kdOsFuncs;
+extern Bool kdDontZap;
+extern Bool kdDisableZaphod;
+extern int kdScreenPrivateIndex;
+extern KdMouseFuncs LinuxEvdevMouseFuncs;
+extern KdKeyboardFuncs LinuxEvdevKeyboardFuncs;
+
+#define RR_Rotate_All (RR_Rotate_0|RR_Rotate_90|RR_Rotate_180|RR_Rotate_270)
+#define RR_Reflect_All (RR_Reflect_X|RR_Reflect_Y)
+
+#define KdGetScreenPriv(pScreen) ((xeglScreenPtr) \
+ (pScreen)->devPrivates[kdScreenPrivateIndex].ptr)
+#define KdScreenPriv(pScreen) xeglScreenPtr pScreenPriv = KdGetScreenPriv(pScreen)
+
+extern void eglInitInput(KdMouseFuncs *pMouseFuncs, KdKeyboardFuncs *pKeyboardFuncs);
+extern void KdParseMouse(char *arg);
+extern KdMouseInfo *KdMouseInfoAdd(void);
+extern void KdMouseInfoDispose(KdMouseInfo *mi);
+extern int KdAllocInputType(void);
+extern char *KdSaveString (char *str);
+extern Bool KdRegisterFd(int type, int fd, void (*read) (int fd, void *closure), void *closure);
+extern void KdUnregisterFds(int type, Bool do_close);
+extern void KdEnqueueKeyboardEvent(unsigned char scan_code, unsigned char is_up);
+extern void KdEnqueueMouseEvent(KdMouseInfo *mi, unsigned long flags, int rx, int ry);
+extern void KdRegisterFdEnableDisable(int fd,
+ int (*enable)(int fd, void *closure),
+ void (*disable)(int fd, void *closure));
+extern void KdWakeupHandler(int screen, pointer data, unsigned long lresult, pointer readmask);
+
+
diff --git a/hw/xgl/egl/xeglinput.c b/hw/xgl/egl/xeglinput.c
new file mode 100644
index 000000000..8c50b7846
--- /dev/null
+++ b/hw/xgl/egl/xeglinput.c
@@ -0,0 +1,168 @@
+#include "xgl.h"
+#include "xegl.h"
+
+KdOsFuncs *kdOsFuncs;
+Bool kdEmulateMiddleButton;
+Bool kdRawPointerCoordinates;
+Bool kdDontZap;
+Bool kdDisableZaphod;
+int kdScreenPrivateIndex;
+
+static char *
+KdParseFindNext (char *cur, char *delim, char *save, char *last)
+{
+ while (*cur && !strchr (delim, *cur))
+ {
+ *save++ = *cur++;
+ }
+ *save = 0;
+ *last = *cur;
+ if (*cur)
+ cur++;
+ return cur;
+}
+
+/*
+ * Mouse argument syntax:
+ *
+ * device,protocol,options...
+ *
+ * Options are any of:
+ * 1-5 n button mouse
+ * 2button emulate middle button
+ * {NMO} Reorder buttons
+ */
+char *
+KdSaveString (char *str)
+{
+ char *n = (char *) xalloc (strlen (str) + 1);
+
+ if (!n)
+ return 0;
+ strcpy (n, str);
+ return n;
+}
+
+/*
+ * Parse mouse information. Syntax:
+ *
+ * <device>,<nbutton>,<protocol>{,<option>}...
+ *
+ * options: {nmo} pointer mapping (e.g. {321})
+ * 2button emulate middle button
+ * 3button dont emulate middle button
+ */
+void
+KdParseMouse (char *arg)
+{
+ char save[1024];
+ char delim;
+ KdMouseInfo *mi;
+ int i;
+
+ mi = KdMouseInfoAdd ();
+ if (!mi)
+ return;
+ mi->name = 0;
+ mi->prot = 0;
+ mi->emulateMiddleButton = kdEmulateMiddleButton;
+ mi->transformCoordinates = !kdRawPointerCoordinates;
+ mi->nbutton = 3;
+ for (i = 0; i < KD_MAX_BUTTON; i++)
+ mi->map[i] = i + 1;
+
+ if (!arg)
+ return;
+ if (strlen (arg) >= sizeof (save))
+ return;
+ arg = KdParseFindNext (arg, ",", save, &delim);
+ if (!save[0])
+ return;
+ mi->name = KdSaveString (save);
+ if (delim != ',')
+ return;
+
+ arg = KdParseFindNext (arg, ",", save, &delim);
+ if (!save[0])
+ return;
+
+ if ('1' <= save[0] && save[0] <= '0' + KD_MAX_BUTTON && save[1] == '\0')
+ {
+ mi->nbutton = save[0] - '0';
+ if (mi->nbutton > KD_MAX_BUTTON)
+ {
+ UseMsg ();
+ return;
+ }
+ }
+
+ if (!delim != ',')
+ return;
+
+ arg = KdParseFindNext (arg, ",", save, &delim);
+
+ if (save[0])
+ mi->prot = KdSaveString (save);
+
+ while (delim == ',')
+ {
+ arg = KdParseFindNext (arg, ",", save, &delim);
+ if (save[0] == '{')
+ {
+ char *s = save + 1;
+ i = 0;
+ while (*s && *s != '}')
+ {
+ if ('1' <= *s && *s <= '0' + mi->nbutton)
+ mi->map[i] = *s - '0';
+ else
+ UseMsg ();
+ s++;
+ }
+ }
+ else if (!strcmp (save, "2button"))
+ mi->emulateMiddleButton = TRUE;
+ else if (!strcmp (save, "3button"))
+ mi->emulateMiddleButton = FALSE;
+ else if (!strcmp (save, "rawcoord"))
+ mi->transformCoordinates = FALSE;
+ else if (!strcmp (save, "transform"))
+ mi->transformCoordinates = TRUE;
+ else
+ UseMsg ();
+ }
+}
+
+KdMouseInfo *kdMouseInfo;
+
+KdMouseInfo *
+KdMouseInfoAdd (void)
+{
+ KdMouseInfo *mi, **prev;
+
+ mi = (KdMouseInfo *) xalloc (sizeof (KdMouseInfo));
+ if (!mi)
+ return 0;
+ bzero (mi, sizeof (KdMouseInfo));
+ for (prev = &kdMouseInfo; *prev; prev = &(*prev)->next);
+ *prev = mi;
+ return mi;
+}
+
+void
+KdMouseInfoDispose (KdMouseInfo *mi)
+{
+ KdMouseInfo **prev;
+
+ for (prev = &kdMouseInfo; *prev; prev = &(*prev)->next)
+ if (*prev == mi)
+ {
+ *prev = mi->next;
+ if (mi->name)
+ xfree (mi->name);
+ if (mi->prot)
+ xfree (mi->prot);
+ xfree (mi);
+ break;
+ }
+}