async key grabs to avoid race conditions with the sync stuff. there are still possible rases (yay X) but they will be much harder to hit, i expect noone will ever hit them more than once/often enuogh to realise.

This commit is contained in:
Dana Jansens 2003-05-22 18:14:22 +00:00
parent 64c9c16c3f
commit 1eef38ce75

View file

@ -5,6 +5,7 @@
#include "kernel/grab.h" #include "kernel/grab.h"
#include "kernel/action.h" #include "kernel/action.h"
#include "kernel/parse.h" #include "kernel/parse.h"
#include "kernel/timer.h"
#include "tree.h" #include "tree.h"
#include "keyboard.h" #include "keyboard.h"
#include "keyparse.h" #include "keyparse.h"
@ -20,30 +21,37 @@ KeyBindingTree *firstnode = NULL;
static KeyBindingTree *curpos; static KeyBindingTree *curpos;
static guint reset_key, reset_state, button_return, button_escape; static guint reset_key, reset_state, button_return, button_escape;
static gboolean grabbed; static Timer *chain_timer;
static void grab_keys(gboolean grab) static void grab_keys()
{ {
if (!grab) { KeyBindingTree *p;
ungrab_all_keys();
} else { ungrab_all_keys();
KeyBindingTree *p = firstnode;
while (p) { p = curpos ? curpos->first_child : firstnode;
grab_key(p->key, p->state, GrabModeSync); while (p) {
p = p->next_sibling; grab_key(p->key, p->state, GrabModeAsync);
} p = p->next_sibling;
} }
grab_key(reset_key, reset_state, GrabModeAsync);
} }
static void reset_chains() static void reset_chains()
{ {
/* XXX kill timer */ if (chain_timer) {
curpos = NULL; timer_stop(chain_timer);
if (grabbed) { chain_timer = NULL;
grabbed = FALSE; }
grab_keyboard(FALSE); if (curpos) {
} else curpos = NULL;
XAllowEvents(ob_display, AsyncKeyboard, event_lasttime); grab_keys();
}
}
static void chain_timeout(void *data)
{
reset_chains();
} }
gboolean kbind(GList *keylist, Action *action) gboolean kbind(GList *keylist, Action *action)
@ -71,19 +79,12 @@ gboolean kbind(GList *keylist, Action *action)
return FALSE; return FALSE;
} }
/* grab the server here to make sure no key presses go missed */
grab_server(TRUE);
grab_keys(FALSE);
/* set the action */ /* set the action */
t->actions = g_slist_append(t->actions, action); t->actions = g_slist_append(t->actions, action);
/* assimilate this built tree into the main tree. assimilation /* assimilate this built tree into the main tree. assimilation
destroys/uses the tree */ destroys/uses the tree */
if (tree) tree_assimilate(tree); if (tree) tree_assimilate(tree);
grab_keys(TRUE);
grab_server(FALSE);
return TRUE; return TRUE;
} }
@ -115,8 +116,8 @@ static void event(ObEvent *e, void *foo)
Action *act = it->data; Action *act = it->data;
act->data.cycle.final = TRUE; act->data.cycle.final = TRUE;
act->func(&act->data); act->func(&act->data);
grab_keyboard(FALSE);
grabbed_key = NULL; grabbed_key = NULL;
grab_keyboard(FALSE);
reset_chains(); reset_chains();
return; return;
} }
@ -140,14 +141,12 @@ static void event(ObEvent *e, void *foo)
if (p->key == e->data.x.e->xkey.keycode && if (p->key == e->data.x.e->xkey.keycode &&
p->state == e->data.x.e->xkey.state) { p->state == e->data.x.e->xkey.state) {
if (p->first_child != NULL) { /* part of a chain */ if (p->first_child != NULL) { /* part of a chain */
/* XXX TIMER */ if (chain_timer) timer_stop(chain_timer);
if (!grabbed) { /* 5 second timeout for chains */
grab_keyboard(TRUE); chain_timer = timer_start(5000*1000, chain_timeout,
grabbed = TRUE; NULL);
XAllowEvents(ob_display, AsyncKeyboard,
event_lasttime);
}
curpos = p; curpos = p;
grab_keys();
} else { } else {
GSList *it; GSList *it;
for (it = p->actions; it; it = it->next) { for (it = p->actions; it; it = it->next) {
@ -164,8 +163,9 @@ static void event(ObEvent *e, void *foo)
if (act->func == action_cycle_windows && if (act->func == action_cycle_windows &&
!grabbed_key) { !grabbed_key) {
grab_keyboard(TRUE);
grabbed_key = p; grabbed_key = p;
grab_keyboard(TRUE);
break;
} }
} }
} }
@ -184,22 +184,24 @@ void plugin_startup()
guint i; guint i;
curpos = NULL; curpos = NULL;
grabbed = FALSE; chain_timer = NULL;
dispatch_register(Event_X_KeyPress | Event_X_KeyRelease, (EventHandler)event, NULL); dispatch_register(Event_X_KeyPress | Event_X_KeyRelease,
(EventHandler)event, NULL);
translate_key("C-g", &reset_state, &reset_key); translate_key("C-g", &reset_state, &reset_key);
translate_key("Escape", &i, &button_escape); translate_key("Escape", &i, &button_escape);
translate_key("Return", &i, &button_return); translate_key("Return", &i, &button_return);
grab_keys();
} }
void plugin_shutdown() void plugin_shutdown()
{ {
dispatch_register(0, (EventHandler)event, NULL); dispatch_register(0, (EventHandler)event, NULL);
grab_keys(FALSE);
tree_destroy(firstnode); tree_destroy(firstnode);
firstnode = NULL; firstnode = NULL;
grab_keys(TRUE); ungrab_all_keys();
} }