X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;ds=sidebyside;f=openbox%2Factions.c;h=7087f37d71557e196608308be4a2454ded875cd8;hb=ae624a1487fd7db9291c4de1a3b2c34fcab89ef9;hp=dff78f5033b6e603300d194d976b8aea78054ec5;hpb=314c0566371d83305d723c883884555a24cc0ad8;p=chaz%2Fopenbox diff --git a/openbox/actions.c b/openbox/actions.c index dff78f50..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; @@ -31,6 +37,8 @@ struct _ObActionsDefinition { ObActionsDataSetupFunc setup; ObActionsDataFreeFunc free; ObActionsRunFunc run; + ObActionsInteractiveInputFunc i_input; + ObActionsInteractiveCancelFunc i_cancel; }; struct _ObActionsAct { @@ -65,7 +73,9 @@ gboolean actions_register(const gchar *name, ObActionsType type, ObActionsDataSetupFunc setup, ObActionsDataFreeFunc free, - ObActionsRunFunc run) + ObActionsRunFunc run, + ObActionsInteractiveInputFunc i_input, + ObActionsInteractiveCancelFunc i_cancel) { GSList *it; ObActionsDefinition *def; @@ -76,6 +86,8 @@ gboolean actions_register(const gchar *name, return FALSE; } + g_assert((i_input == NULL) == (i_cancel == NULL)); + def = g_new(ObActionsDefinition, 1); def->ref = 1; def->name = g_strdup(name); @@ -83,6 +95,8 @@ gboolean actions_register(const gchar *name, def->setup = setup; def->free = free; def->run = run; + def->i_input = i_input; + def->i_cancel = i_cancel; return TRUE; } @@ -145,6 +159,11 @@ ObActionsAct* actions_parse(ObParseInst *i, return act; } +gboolean actions_act_is_interactive(ObActionsAct *act) +{ + return act->def->i_cancel != NULL; +} + void actions_act_ref(ObActionsAct *act) { ++act->ref; @@ -165,14 +184,12 @@ static void actions_setup_data(ObActionsData *data, ObUserAction uact, Time time, guint state, - guint button, gint x, gint y) { data->any.uact = uact; data->any.time = time; data->any.state = state; - data->any.button = button; data->any.x = x; data->any.y = y; } @@ -181,21 +198,20 @@ void actions_run_acts(GSList *acts, ObUserAction uact, Time time, guint state, - guint button, gint x, gint y, ObFrameContext con, - struct _ObClient *client, - ObActionsInteractiveState interactive) + struct _ObClient *client) { GSList *it; 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, button, x, y); + actions_setup_data(&data, uact, time, state, x, y); switch (data.type) { case OB_ACTION_TYPE_GLOBAL: break; @@ -203,14 +219,77 @@ void actions_run_acts(GSList *acts, data.client.context = con; data.client.c = client; break; - case OB_ACTION_TYPE_SELECTOR: - data.selector.interactive = interactive; - break; default: 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; }