static void grabkeys(void);
static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
+static void keyrelease(XEvent *e);
static void killclient(const Arg *arg);
static void manage(Window w, XWindowAttributes *wa);
static void mappingnotify(XEvent *e);
static void run(void);
static void scan(void);
static Bool sendevent(Client *c, Atom proto);
-static void send_keycode(KeyCode key, unsigned int state);
+static void send_key_event(int type, KeyCode key, unsigned int state);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
typedef struct {
KeyCode keycode;
unsigned int state;
+ int type;
} BufferedKey;
static BufferedKey key_buffer[200];
static int key_buffer_len = 0;
[Expose] = expose,
[FocusIn] = focusin,
[KeyPress] = keypress,
+ [KeyRelease] = keyrelease,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
[MotionNotify] = motionnotify,
grabkeys(void) {
updatenumlockmask();
//XUngrabKey(dpy, AnyKey, AnyModifier, root);
+ // FIXME key grabbing causes FocusOut events, which confuses programs (they only get keypresses when they don't have focus)
XGrabKey(dpy, AnyKey, AnyModifier, root, True, GrabModeAsync, GrabModeAsync);
}
#endif /* XINERAMA */
void
-send_keycode(KeyCode key, unsigned int state) {
+send_key_event(int type, KeyCode key, unsigned int state) {
+ int mask;
+ if (type == KeyPress) {
+ mask = KeyPressMask;
+ } else {
+ mask = KeyReleaseMask;
+ }
XKeyEvent event;
if(!selmon->sel) {
return;
}
+ event.type = type;
event.display = dpy;
event.root = root;
event.window = selmon->sel->win;
event.time = CurrentTime;
event.state = state; // modifiers
event.keycode = key;
- event.type = KeyPress;
- XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
- event.type = KeyRelease;
- XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
+ event.same_screen = True;
+ XSendEvent(event.display, event.window, True, mask, (XEvent *)&event);
}
void
Bool called = False;
ev = &e->xkey;
+ // fprintf(stderr, "key DOWN %i\n", ev->keycode);
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < LENGTH(keys); i++)
if(keysym == keys[i].keysym
key_buffering = False;
} else {
key_buffer[key_buffer_len].keycode = (KeyCode)ev->keycode;
- key_buffer[key_buffer_len].state = (KeyCode)ev->state;
+ key_buffer[key_buffer_len].state = ev->state;
+ key_buffer[key_buffer_len].type = KeyPress;
key_buffer_len += 1;
}
} else {
- send_keycode(ev->keycode, ev->state);
+ send_key_event(KeyPress, (KeyCode)ev->keycode, ev->state);
}
}
}
void
+keyrelease(XEvent *e) {
+ XKeyEvent *ev;
+ ev = &e->xkey;
+ // fprintf(stderr, "key UP %i\n", ev->keycode);
+ if(key_buffering) {
+ if(key_buffer_len == LENGTH(key_buffer)) {
+ // buffer full, bail
+ key_buffer_len = 0;
+ key_buffering = False;
+ } else {
+ key_buffer[key_buffer_len].keycode = (KeyCode)ev->keycode;
+ key_buffer[key_buffer_len].state = ev->state;
+ key_buffer[key_buffer_len].type = KeyRelease;
+ key_buffer_len += 1;
+ }
+ } else {
+ send_key_event(KeyRelease, (KeyCode)ev->keycode, ev->state);
+ }
+}
+
+void
killclient(const Arg *arg) {
if(!selmon->sel)
return;
XMapWindow(dpy, c->win);
focus(c);
if(key_buffering) {
- if(key_buffer_len > 0) {
- for(i = 0; i < key_buffer_len; ++i) {
- send_keycode(key_buffer[i].keycode, key_buffer[i].state);
- }
+ for(i = 0; i < key_buffer_len; ++i) {
+ send_key_event(key_buffer[i].type, key_buffer[i].keycode, key_buffer[i].state);
}
key_buffer_len = 0;
key_buffering = False;
void
mappingnotify(XEvent *e) {
XMappingEvent *ev = &e->xmapping;
+ // fprintf(stderr, "MapNotify\n");
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard)
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
+ // fprintf(stderr, "MapRequest\n");
if(!XGetWindowAttributes(dpy, ev->window, &wa))
return;
if(wa.override_redirect) {
XEvent ev;
/* main event loop */
XSync(dpy, False);
- while(running && !XNextEvent(dpy, &ev))
- if(handler[ev.type])
+ while(running && !XNextEvent(dpy, &ev)) {
+ if(handler[ev.type]) {
+ // fprintf(stderr, "handling event type %i\n", ev.type);
handler[ev.type](&ev); /* call handler */
+ } else {
+ // fprintf(stderr, "evt type %i\n", ev.type);
+ }
+ }
}
void