2 * Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com>
3 * Author: Tony Rogvall <tony@bluetail.com>
5 * Converted to scancode mode by Greg Haerr
13 #include <X11/Xutil.h>
14 #include <X11/keysym.h>
15 #include <X11/XKBlib.h>
18 static int X11_Open(KBDDEVICE *pkd);
19 static void X11_Close(void);
20 static void X11_GetModifierInfo(MWKEYMOD *modifiers, MWKEYMOD *curmodifiers);
21 static int X11_Read(MWKEY *kbuf, MWKEYMOD *modifiers, MWSCANCODE *scancode);
23 static int init_modstate();
25 static MWKEYMOD key_modstate;
26 extern int escape_quits;
28 extern Display* x11_dpy;
30 extern Visual* x11_vis;
31 extern Window x11_win;
33 extern int x11_setup_display();
35 #define X_SCR_MASK 0x80
36 #define X_CAP_MASK 0x2
37 #define X_NUM_MASK 0x10
49 * This is real simple, we just use a special file handle
50 * that allows non-blocking I/O, and put the terminal into
54 X11_Open(KBDDEVICE *pkd)
56 if (x11_setup_display() < 0)
59 if(init_modstate() < 0)
62 /* return the x11 file descriptor for select */
63 return ConnectionNumber(x11_dpy);
68 * This resets the terminal modes.
77 * Return the possible modifiers for the keyboard.
80 X11_GetModifierInfo(MWKEYMOD *modifiers, MWKEYMOD *curmodifiers)
83 *modifiers = MWKMOD_SHIFT | MWKMOD_CTRL | MWKMOD_ALT;
85 *curmodifiers = key_modstate;
89 * This reads one keystroke from the keyboard, and the current state of
90 * the modifier keys (ALT, SHIFT, etc). Returns -1 on error, 0 if no data
91 * is ready, 1 on a keypress, and 2 on keyrelease.
92 * This is a non-blocking call.
95 X11_Read(MWKEY *kbuf, MWKEYMOD *modifiers, MWSCANCODE *scancode)
100 static int grabbed = 0;
101 static int x11_accel_num;
102 static int x11_accel_den;
103 static int x11_thres;
105 /* check if we have a KeyPressedEvent */
106 if (XCheckMaskEvent(x11_dpy, KeyPressMask|KeyReleaseMask, &ev)) {
107 KeySym sym = XKeycodeToKeysym(x11_dpy, ev.xkey.keycode, 0);
112 /* calculate kbd modifiers*/
113 key_modstate &= (MWKMOD_NUM|MWKMOD_CAPS|MWKMOD_SCR);
114 if (ev.xkey.state & ControlMask)
115 key_modstate |= MWKMOD_CTRL;
116 if (ev.xkey.state & ShiftMask)
117 key_modstate |= MWKMOD_SHIFT;
118 if (ev.xkey.state & Mod1Mask)
119 key_modstate |= MWKMOD_ALT;
120 if (ev.xkey.state & X_CAP_MASK)
121 key_modstate |= MWKMOD_CAPS;
122 if (ev.xkey.state & X_SCR_MASK)
123 key_modstate |= MWKMOD_SCR;
124 if (ev.xkey.state & X_NUM_MASK)
125 key_modstate |= MWKMOD_NUM;
127 if (sym == XK_Escape) {
128 mwkey = MWKEY_ESCAPE;
130 if (ev.xkey.state & ControlMask) {
131 /* toggle grab control */
133 XUngrabPointer(x11_dpy, CurrentTime);
134 XUngrabKeyboard(x11_dpy, CurrentTime);
135 XChangePointerControl(x11_dpy, True, False, x11_accel_num,
140 /* save pointer config */
141 XGetPointerControl(x11_dpy, &x11_accel_num, &x11_accel_den,
143 XChangePointerControl(x11_dpy, True, False, 1, 1, 0);
144 XGrabKeyboard(x11_dpy, x11_win,
145 True, /* only to this window */
146 GrabModeAsync, GrabModeAsync, CurrentTime);
147 XGrabPointer(x11_dpy, x11_win, False,
148 PointerMotionMask | ButtonPressMask,
149 GrabModeAsync, GrabModeAsync, None, None,
155 XChangePointerControl(x11_dpy, True, False, x11_accel_num,
158 *modifiers = key_modstate;
159 *scancode = ev.xkey.keycode;
160 return (ev.xkey.type == KeyPress)? 1: 2;
164 mwkey = MWKEY_DELETE;
182 mwkey = MWKEY_PAGEUP;
185 mwkey = MWKEY_PAGEDOWN;
191 mwkey = MWKEY_INSERT;
205 mwkey = MWKEY_CANCEL;
208 mwkey = MWKEY_KP_ENTER;
228 case XK_KP_Page_Down:
238 mwkey = MWKEY_KP_PERIOD;
241 mwkey = MWKEY_KP_EQUALS;
244 mwkey = MWKEY_KP_MULTIPLY;
247 mwkey = MWKEY_KP_PLUS;
250 mwkey = MWKEY_KP_MINUS;
253 mwkey = MWKEY_KP_PERIOD;
256 mwkey = MWKEY_KP_DIVIDE;
301 /* not sent, used only for state*/
302 if (ev.xkey.type == KeyRelease)
303 key_modstate ^= MWKMOD_NUM;
307 /* not sent, used only for state*/
308 if (ev.xkey.type == KeyRelease)
309 key_modstate ^= MWKMOD_CAPS;
312 /* not sent, used only for state*/
313 if (ev.xkey.type == KeyRelease)
314 key_modstate ^= MWKMOD_SCR;
318 mwkey = MWKEY_LSHIFT;
321 mwkey = MWKEY_RSHIFT;
353 fprintf(stderr, "Unhandled X11 keysym: %04x\n", (int)sym);
356 XLookupString(&ev.xkey, &mwkey, 1, &sym, NULL );
358 if (key_modstate & MWKMOD_CTRL)
359 mwkey = sym & 0x1f; /* Control code */
361 mwkey = sym & 0xff; /* ASCII*/
366 if (key_modstate & MWKMOD_NUM) {
378 mwkey = mwkey - MWKEY_KP0 + '0';
380 case MWKEY_KP_PERIOD:
383 case MWKEY_KP_DIVIDE:
386 case MWKEY_KP_MULTIPLY:
398 case MWKEY_KP_EQUALS:
403 *modifiers = key_modstate;
404 *scancode = ev.xkey.keycode;
407 //printf("mods: 0x%x scan: 0x%x key: 0x%x\n",*modifiers
410 return (ev.xkey.type == KeyPress)? 1 : 2;
416 #define NUM_LOCK_MASK 0x00000002
417 #define CAPS_LOCK_MASK 0x00000001
418 #define SCROLL_LOCK_MASK 0x00000004
420 /* initialise key_modstate */
421 static int init_modstate ()
424 int capsl, numl, scrolll;
426 if(XkbGetIndicatorState (x11_dpy, XkbUseCoreKbd, &state) != Success) {
427 fprintf(stderr, "Error reading Indicator status\n");
430 capsl = state & CAPS_LOCK_MASK;
431 numl = state & NUM_LOCK_MASK;
432 scrolll = state & SCROLL_LOCK_MASK;
435 key_modstate |= MWKMOD_NUM;
438 key_modstate |= MWKMOD_CAPS;
441 key_modstate |= MWKMOD_SCR;