From 780b2428a2463f164608c498f7d2e586016b8e11 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Mon, 19 Aug 2013 00:03:51 +0200 Subject: [PATCH] Add ForEach action which is like If but runs on all clients Also adds a Stop action that lets you stop running, in case you only want to run actions on the first match. --- openbox/actions.c | 26 +++++++++++++++++++++++--- openbox/actions.h | 2 ++ openbox/actions/if.c | 44 +++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/openbox/actions.c b/openbox/actions.c index ac849a9..bf00c6c 100644 --- a/openbox/actions.c +++ b/openbox/actions.c @@ -52,6 +52,7 @@ struct _ObActionsDefinition { ObActionsRunFunc run; ObActionsShutdownFunc shutdown; gboolean modifies_focused_window; + gboolean can_stop; }; struct _ObActionsAct { @@ -111,6 +112,7 @@ ObActionsDefinition* do_register(const gchar *name, def->run = run; def->shutdown = NULL; def->modifies_focused_window = TRUE; + def->can_stop = FALSE; registered = g_slist_prepend(registered, def); return def; @@ -174,6 +176,22 @@ gboolean actions_set_modifies_focused_window(const gchar *name, return FALSE; } +gboolean actions_set_can_stop(const gchar *name, + gboolean can_stop) +{ + GSList *it; + ObActionsDefinition *def; + + for (it = registered; it; it = g_slist_next(it)) { + def = it->data; + if (!g_ascii_strcasecmp(name, def->name)) { + def->can_stop = can_stop; + return TRUE; + } + } + return FALSE; +} + static void actions_definition_ref(ObActionsDefinition *def) { ++def->ref; @@ -356,16 +374,18 @@ void actions_run_acts(GSList *acts, /* fire the action's run function with this data */ if (ok) { if (!act->def->run(&data, act->options)) { - if (actions_act_is_interactive(act)) + if (actions_act_is_interactive(act)) { actions_interactive_end_act(); + } if (client && client == focus_client && act->def->modifies_focused_window) { update_user_time = TRUE; } } else { - /* make sure its interactive if it returned TRUE */ - g_assert(act->i_input); + /* make sure its interactive or allowed to stop + if it returned TRUE */ + g_assert(act->i_input || act->def->can_stop); /* no actions are run after the interactive one */ break; diff --git a/openbox/actions.h b/openbox/actions.h index f413ad8..f8e1ba8 100644 --- a/openbox/actions.h +++ b/openbox/actions.h @@ -84,6 +84,8 @@ gboolean actions_set_shutdown(const gchar *name, ObActionsShutdownFunc shutdown); gboolean actions_set_modifies_focused_window(const gchar *name, gboolean modifies); +gboolean actions_set_can_stop(const gchar *name, + gboolean modifies); ObActionsAct* actions_parse(xmlNodePtr node); ObActionsAct* actions_parse_string(const gchar *name); diff --git a/openbox/actions/if.c b/openbox/actions/if.c index 8a31c9a..1802c6a 100644 --- a/openbox/actions/if.c +++ b/openbox/actions/if.c @@ -64,15 +64,22 @@ typedef struct { GArray* queries; GSList *thenacts; GSList *elseacts; + gboolean stop; } Options; static gpointer setup_func(xmlNodePtr node); static void free_func(gpointer options); -static gboolean run_func(ObActionsData *data, gpointer options); +static gboolean run_func_if(ObActionsData *data, gpointer options); +static gboolean run_func_stop(ObActionsData *data, gpointer options); +static gboolean run_func_foreach(ObActionsData *data, gpointer options); void action_if_startup(void) { - actions_register("If", setup_func, free_func, run_func); + actions_register("If", setup_func, free_func, run_func_if); + actions_register("Stop", NULL, NULL, run_func_stop); + actions_register("ForEach", setup_func, free_func, run_func_foreach); + + actions_set_can_stop("Stop", TRUE); } static inline void set_bool(xmlNodePtr node, @@ -228,7 +235,7 @@ static void free_func(gpointer options) } /* Always return FALSE because its not interactive */ -static gboolean run_func(ObActionsData *data, gpointer options) +static gboolean run_func_if(ObActionsData *data, gpointer options) { Options *o = options; ObClient *action_target = data->client; @@ -351,3 +358,34 @@ static gboolean run_func(ObActionsData *data, gpointer options) return FALSE; } + +static gboolean run_func_foreach(ObActionsData *data, gpointer options) +{ + GList *it; + Options *o = options; + + o->stop = FALSE; + + for (it = client_list; it; it = g_list_next(it)) { + data->client = it->data; + run_func_if(data, options); + if (o->stop) { + break; + } + } + + return FALSE; +} + +static gboolean run_func_stop(ObActionsData *data, gpointer options) +{ + Options *o = options; + + /* This stops the loop above so we don't invoke actions on any more + clients */ + o->stop = TRUE; + + /* TRUE causes actions_run_acts to not run further actions on the current + client */ + return TRUE; +} -- 1.9.1