From ae624a1487fd7db9291c4de1a3b2c34fcab89ef9 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Fri, 22 Jun 2007 02:30:13 +0000 Subject: [PATCH] add code for interactive actions --- openbox/actions.c | 79 ++++++++++++++++++++++++++++++++++++++++++-- openbox/actions.h | 8 ++++- openbox/event.c | 17 ++++------ openbox/moveresize.c | 2 +- 4 files changed, 91 insertions(+), 15 deletions(-) diff --git a/openbox/actions.c b/openbox/actions.c index c516969e..7087f37d 100644 --- a/openbox/actions.c +++ b/openbox/actions.c @@ -18,9 +18,15 @@ #include "actions.h" #include "gettext.h" +#include "grab.h" -static void actions_definition_ref(ObActionsDefinition *def); -static void actions_definition_unref(ObActionsDefinition *def); +static void actions_definition_ref(ObActionsDefinition *def); +static void actions_definition_unref(ObActionsDefinition *def); +static gboolean actions_interactive_begin_act(ObActionsAct *act, guint state); +static void actions_interactive_end_act(); + +static ObActionsAct *interactive_act = NULL; +static guint interactive_initial_state = 0; struct _ObActionsDefinition { guint ref; @@ -202,6 +208,7 @@ void actions_run_acts(GSList *acts, for (it = acts; it; it = g_slist_next(it)) { ObActionsData data; ObActionsAct *act = it->data; + gboolean ok = TRUE; data.type = act->def->type; actions_setup_data(&data, uact, time, state, x, y); @@ -216,7 +223,73 @@ void actions_run_acts(GSList *acts, g_assert_not_reached(); } + if (actions_act_is_interactive(act) && + (!interactive_act || interactive_act->def != act->def)) + { + ok = actions_interactive_begin_act(act, state); + } + /* fire the action's run function with this data */ - act->def->run(&data, act->options); + if (ok) { + if (!act->def->run(&data, act->options)) + actions_interactive_end_act(); + else + break; /* no actions are run after the interactive one */ + } + } +} + +gboolean actions_interactive_act_running() +{ + return interactive_act != NULL; +} + +void actions_interactive_cancel_act() +{ + if (interactive_act) { + interactive_act->def->i_cancel(interactive_act->options); + actions_interactive_end_act(); + } +} + +static gboolean actions_interactive_begin_act(ObActionsAct *act, guint state) +{ + /* cancel the old one */ + if (interactive_act) + actions_interactive_cancel_act(); + + if (grab_keyboard()) { + interactive_act = act; + actions_act_ref(interactive_act); + + interactive_initial_state = state; + return TRUE; + } + else + return FALSE; +} + +static void actions_interactive_end_act() +{ + if (interactive_act) { + ungrab_keyboard(); + + actions_act_unref(interactive_act); + interactive_act = NULL; + } +} + +gboolean actions_interactive_input_event(XEvent *e) +{ + gboolean used = FALSE; + if (interactive_act) { + if (!interactive_act->def->i_input(interactive_initial_state, e, + interactive_act->options, &used)) + { + used = TRUE; /* if it cancelled the action then it has to of + been used */ + actions_interactive_end_act(); + } } + return used; } diff --git a/openbox/actions.h b/openbox/actions.h index b55a7f07..df304130 100644 --- a/openbox/actions.h +++ b/openbox/actions.h @@ -37,7 +37,8 @@ typedef gboolean (*ObActionsRunFunc)(ObActionsData *data, gpointer options); typedef gboolean (*ObActionsInteractiveInputFunc)(guint initial_state, XEvent *e, - gpointer options); + gpointer options, + gboolean *used); typedef void (*ObActionsInteractiveCancelFunc)(gpointer options); typedef enum { @@ -112,3 +113,8 @@ void actions_run_acts(GSList *acts, gint y, ObFrameContext con, struct _ObClient *client); + +gboolean actions_interactive_act_running(); +void actions_interactive_cancel_act(); + +gboolean actions_interactive_input_event(XEvent *e); diff --git a/openbox/event.c b/openbox/event.c index a75d264a..6d53de21 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -808,8 +808,7 @@ static void event_handle_client(ObClient *client, XEvent *e) want to deal with them */ if (!(e->xbutton.button == 4 || e->xbutton.button == 5) && - !keyboard_interactively_grabbed() && - !menu_frame_visible) + !grab_on_keyboard()) { /* use where the press occured */ con = frame_context(client, e->xbutton.window, px, py); @@ -956,7 +955,7 @@ static void event_handle_client(ObClient *client, XEvent *e) (e->type == EnterNotify ? "Enter" : "Leave"), e->xcrossing.mode, e->xcrossing.detail, (client?client->window:0)); - if (keyboard_interactively_grabbed()) + if (grab_on_keyboard()) break; if (config_focus_follow && config_focus_delay && /* leave inferior events can happen when the mouse goes onto @@ -999,7 +998,7 @@ static void event_handle_client(ObClient *client, XEvent *e) frame_adjust_state(client->frame); break; case OB_FRAME_CONTEXT_FRAME: - if (keyboard_interactively_grabbed()) + if (grab_on_keyboard()) break; if (e->xcrossing.mode == NotifyGrab || e->xcrossing.mode == NotifyUngrab || @@ -1792,9 +1791,7 @@ static void event_handle_user_input(ObClient *client, XEvent *e) /* if the keyboard interactive action uses the event then dont use it for bindings. likewise is moveresize uses the event. */ - if (!keyboard_process_interactive_grab(e, &client) && - !(moveresize_in_progress && moveresize_event(e))) - { + if (!actions_interactive_input_event(e) && !moveresize_event(e)) { if (moveresize_in_progress) /* make further actions work on the client being moved/resized */ @@ -1899,9 +1896,9 @@ static gboolean is_enter_focus_event_ignored(XEvent *e) void event_cancel_all_key_grabs() { - if (keyboard_interactively_grabbed()) { - keyboard_interactive_cancel(); - ob_debug("KILLED interactive event\n"); + if (actions_interactive_act_running()) { + actions_interactive_cancel_act(); + ob_debug("KILLED interactive action\n"); } else if (menu_frame_visible) { menu_frame_hide_all(); diff --git a/openbox/moveresize.c b/openbox/moveresize.c index 534cd011..69dc18ba 100644 --- a/openbox/moveresize.c +++ b/openbox/moveresize.c @@ -416,7 +416,7 @@ gboolean moveresize_event(XEvent *e) { gboolean used = FALSE; - g_assert(moveresize_in_progress); + if (!moveresize_in_progress) return FALSE; if (e->type == ButtonPress) { if (!button) { -- 2.39.2