diff --git a/openbox/action.c b/openbox/action.c index a395af2d..f780ce88 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -28,11 +28,12 @@ #include "openbox.h" #include "grab.h" #include "keyboard.h" +#include "event.h" #include typedef struct ActionString { - char *name; + const gchar *name; void (*func)(union ActionData *); void (*setup)(ObAction **, ObUserAction uact); } ActionString; @@ -784,27 +785,51 @@ ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, return act; } -void action_run_full(ObAction *a, struct _ObClient *c, +void action_run_list(GSList *acts, struct _ObClient *c, guint state, guint button, gint x, gint y, gboolean cancel, gboolean done) { + GSList *it; + ObAction *a; + gboolean inter = FALSE; + if (x < 0 && y < 0) screen_pointer_pos(&x, &y); - a->data.any.c = c; - a->data.any.x = x; - a->data.any.y = y; - - a->data.any.button = button; - - if (a->data.any.interactive) { - a->data.inter.cancel = cancel; - a->data.inter.final = done; - if (!(cancel || done)) - keyboard_interactive_grab(state, c, a); + for (it = acts; it; it = g_slist_next(it)) { + a = it->data; + if (a->data.any.interactive) { + inter = TRUE; + break; + } } - a->func(&a->data); + if (!inter) { + /* sometimes when we execute another app as an action, + it won't work right unless we XUngrabKeyboard first, + even though we grabbed the key/button Asychronously. + e.g. "gnome-panel-control --main-menu" */ + XUngrabKeyboard(ob_display, event_lasttime); + } + + for (it = acts; it; it = g_slist_next(it)) { + a = it->data; + + a->data.any.c = c; + a->data.any.x = x; + a->data.any.y = y; + + a->data.any.button = button; + + if (a->data.any.interactive) { + a->data.inter.cancel = cancel; + a->data.inter.final = done; + if (!(cancel || done)) + keyboard_interactive_grab(state, c, a); + } + + a->func(&a->data); + } } void action_execute(union ActionData *data) diff --git a/openbox/action.h b/openbox/action.h index 68488731..c88ad85f 100644 --- a/openbox/action.h +++ b/openbox/action.h @@ -169,7 +169,7 @@ ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, ObUserAction uact); void action_free(ObAction *a); -/*! Executes an action. +/*! Executes a list of actions. @param c The client associated with the action. Can be NULL. @param state The keyboard modifiers state at the time the user action occured @param button The mouse button used to execute the action. @@ -180,21 +180,21 @@ void action_free(ObAction *a); @param done If the action is completing an interactive action. This only affects interactive actions, but should generally always be FALSE. */ -void action_run_full(ObAction *a, struct _ObClient *c, +void action_run_list(GSList *acts, struct _ObClient *c, guint state, guint button, gint x, gint y, gboolean cancel, gboolean done); #define action_run_mouse(a, c, s, b, x, y) \ - action_run_full(a, c, s, b, x, y, FALSE, FALSE) + action_run_list(a, c, s, b, x, y, FALSE, FALSE) #define action_run_interactive(a, c, s, n, d) \ - action_run_full(a, c, s, 0, -1, -1, n, d) + action_run_list(a, c, s, 0, -1, -1, n, d) #define action_run_key(a, c, s, x, y) \ - action_run_full(a, c, s, 0, x, y, FALSE,FALSE) + action_run_list(a, c, s, 0, x, y, FALSE,FALSE) #define action_run(a, c, s) \ - action_run_full(a, c, s, 0, -1, -1, FALSE,FALSE) + action_run_list(a, c, s, 0, -1, -1, FALSE,FALSE) /* Execute */ void action_execute(union ActionData *data);