static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void grabbuttons(Client *c, Bool focused);
static void grabkeys(void);
+static void grab_typing_keys(void);
static void incnmaster(const Arg *arg);
static void keypress(XEvent *e);
static void killclient(const Arg *arg);
static void run(void);
static void scan(void);
static Bool sendevent(Client *c, Atom proto);
+static void send_keycode(KeyCode key);
static void sendmon(Client *c, Monitor *m);
static void setclientstate(Client *c, long state);
static void setfocus(Client *c);
static void zoom(const Arg *arg);
/* variables */
+static KeyCode key_buffer[100];
+static int key_buffer_len = 0;
+static Bool key_buffering = False;
static const char broken[] = "broken";
static char stext[256];
static int screen;
for(j = 0; j < LENGTH(modifiers); j++)
XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
True, GrabModeAsync, GrabModeAsync);
+ if(key_buffering)
+ grab_typing_keys();
+ }
+}
+
+void
+grab_typing_keys(void) {
+ updatenumlockmask();
+ {
+ unsigned int i, j;
+ unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
+ KeySym typing_keys[] = {
+ XK_space, XK_Return, XK_period, XK_slash, XK_minus, XK_apostrophe,
+ XK_A, XK_B, XK_C, XK_D, XK_E, XK_F, XK_G, XK_H, XK_I, XK_J, XK_K,
+ XK_L, XK_M, XK_N, XK_O, XK_P, XK_Q, XK_R, XK_S, XK_T, XK_U, XK_V,
+ XK_W, XK_X, XK_Y, XK_Z, XK_0, XK_1, XK_2, XK_3, XK_4, XK_5, XK_6,
+ XK_7, XK_8, XK_9,
+ };
+
+ KeyCode code;
+
+ for(i = 0; i < LENGTH(typing_keys); i++)
+ if((code = XKeysymToKeycode(dpy, typing_keys[i])))
+ for(j = 0; j < LENGTH(modifiers); j++)
+ XGrabKey(dpy, code, modifiers[j], root,
+ True, GrabModeAsync, GrabModeAsync);
}
}
#endif /* XINERAMA */
void
+send_keycode(KeyCode key) {
+ XKeyEvent event;
+ if(!selmon->sel) {
+ return;
+ }
+ event.display = dpy;
+ event.root = root;
+ event.window = selmon->sel->win;
+ event.subwindow = None;
+ event.same_screen = True;
+ event.x = 1;
+ event.y = 1;
+ event.x_root = 1;
+ event.y_root = 1;
+ event.time = CurrentTime;
+ event.state = 0; // 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);
+}
+
+void
keypress(XEvent *e) {
unsigned int i;
KeySym keysym;
XKeyEvent *ev;
+ Bool called = False;
ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
for(i = 0; i < LENGTH(keys); i++)
if(keysym == keys[i].keysym
&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
- && keys[i].func)
+ && keys[i].func) {
keys[i].func(&(keys[i].arg));
+ called = True;
+ }
+ if(!called) {
+ if(key_buffering) {
+ if(key_buffer_len == LENGTH(key_buffer)) {
+ // buffer full, bail
+ key_buffer_len = 0;
+ key_buffering = False;
+ grabkeys(); // stop grabbing typing keys
+ } else {
+ key_buffer[key_buffer_len] = (KeyCode)ev->keycode;
+ key_buffer_len += 1;
+ }
+ } else {
+ send_keycode(ev->keycode);
+ }
+ }
}
void
Client *c, *t = NULL;
Window trans = None;
XWindowChanges wc;
+ int i;
if(!(c = calloc(1, sizeof(Client))))
die("fatal: could not malloc() %u bytes\n", sizeof(Client));
arrange(c->mon);
XMapWindow(dpy, c->win);
focus(c);
+ if(key_buffering) {
+ key_buffering = False;
+ grabkeys(); // stop grabbing typing keys
+ if(key_buffer_len > 0) {
+ for(i = 0; i < key_buffer_len; ++i) {
+ send_keycode(key_buffer[i]);
+ }
+ }
+ key_buffer_len = 0;
+ }
}
void
}
if(arg->v == dmenucmd)
dmenumon[0] = '0' + selmon->num;
+ key_buffering = True;
+ key_buffer_len = 0;
+ grab_typing_keys();
if(fork() == 0) {
if(dpy)
close(ConnectionNumber(dpy));