diff options
author | Jon Smirl <jonsmirl@yahoo.com> | 2005-06-04 23:33:03 +0000 |
---|---|---|
committer | Jon Smirl <jonsmirl@yahoo.com> | 2005-06-04 23:33:03 +0000 |
commit | aa959672863aad71c807d6c09938bb296c347bcf (patch) | |
tree | 5e4c00379e3786054ded24a0d46e896f12690e97 /hw/xgl | |
parent | 88d49bed008264092245c4f6c53174f93f6ab387 (diff) | |
download | xserver-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.am | 16 | ||||
-rw-r--r-- | hw/xgl/egl/evdev.c | 643 | ||||
-rw-r--r-- | hw/xgl/egl/kinput.c | 1683 | ||||
-rw-r--r-- | hw/xgl/egl/kkeymap.h | 58 | ||||
-rw-r--r-- | hw/xgl/egl/xegl.c | 798 | ||||
-rw-r--r-- | hw/xgl/egl/xegl.h | 131 | ||||
-rw-r--r-- | hw/xgl/egl/xeglinput.c | 168 |
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; + } +} |