*/
#include "actions.h"
+#include "gettext.h"
-static void actions_unregister(ObActionsDefinition *def);
+static void actions_definition_ref(ObActionsDefinition *def);
+static void actions_definition_unref(ObActionsDefinition *def);
struct _ObActionsDefinition {
+ guint ref;
+
gchar *name;
- gboolean interactive;
+ gboolean allow_interactive;
- ObActionsDataParseFunc parse;
+ ObActionsDataSetupFunc setup;
ObActionsDataFreeFunc free;
ObActionsRunFunc run;
+};
+
+struct _ObActionsAct {
+ guint ref;
+
+ ObActionsDefinition *def;
- gpointer action_data;
+ gpointer options;
};
static GSList *registered = NULL;
/* free all the registered actions */
while (registered) {
- actions_unregister(registered->data);
+ actions_definition_unref(registered->data);
registered = g_slist_delete_link(registered, registered);
}
}
gboolean actions_register(const gchar *name,
- gboolean interactive,
+ gboolean allow_interactive,
ObActionsDataSetupFunc setup,
- ObActionsDataParseFunc parse,
ObActionsDataFreeFunc free,
ObActionsRunFunc run)
{
}
def = g_new(ObActionsDefinition, 1);
+ def->ref = 1;
def->name = g_strdup(name);
- def->interactive = interactive;
- def->parse = parse;
+ def->allow_interactive = allow_interactive;
+ def->setup = setup;
def->free = free;
def->run = run;
- def->action_data = setup();
return TRUE;
}
-static void actions_unregister(ObActionsDefinition *def)
+static void actions_definition_ref(ObActionsDefinition *def)
+{
+ ++def->ref;
+}
+
+static void actions_definition_unref(ObActionsDefinition *def)
{
- if (def) {
- def->free(def->action_data);
+ if (def && --def->ref == 0) {
g_free(def->name);
g_free(def);
}
}
+
+ObActionsAct* actions_parse(ObParseInst *i,
+ xmlDocPtr doc,
+ xmlNodePtr node)
+{
+ GSList *it;
+ gchar *name;
+ ObActionsDefinition *def;
+ ObActionsAct *act = NULL;
+
+ if (!parse_attr_string("name", node, &name)) return NULL;
+
+ /* find the requested action */
+ for (it = registered; it; it = g_slist_next(it)) {
+ def = it->data;
+ if (!g_ascii_strcasecmp(name, def->name))
+ break;
+ }
+
+ /* if we found the action */
+ if (it != NULL) {
+ act = g_new(ObActionsAct, 1);
+ act->ref = 1;
+ act->def = def;
+ actions_definition_ref(act->def);
+ act->options = def->setup(i, doc, node->children);
+ } else
+ g_message(_("Invalid action '%s' requested. No such action exists."),
+ name);
+
+ g_free(name);
+
+ return act;
+}
+
+void actions_act_ref(ObActionsAct *act)
+{
+ ++act->ref;
+}
+
+void actions_act_unref(ObActionsAct *act)
+{
+ if (act && --act->ref == 0) {
+ /* free the action specific options */
+ act->def->free(act->options);
+ /* unref the definition */
+ actions_definition_unref(act->def);
+ g_free(act);
+ }
+}
#include <glib.h>
typedef struct _ObActionsDefinition ObActionsDefinition;
+typedef struct _ObActionsAct ObActionsAct;
+typedef struct _ObActionsData ObActionsData;
typedef struct _ObActionsAnyData ObActionsAnyData;
typedef struct _ObActionsGlobalData ObActionsGlobalData;
typedef struct _ObActionsClientData ObActionsClientData;
OB_NUM_ACTIONS_INTERACTIVE_STATES
} ObActionsInteractiveState;
-typedef gpointer (*ObActionsDataSetupFunc)();
-typedef void (*ObActionsDataParseFunc)(gpointer action_data,
- ObParseInst *i,
+typedef gpointer (*ObActionsDataSetupFunc)(ObParseInst *i,
xmlDocPtr doc, xmlNodePtr node);
-typedef void (*ObActionsDataFreeFunc)(gpointer action_data);
-typedef void (*ObActionsRunFunc)(ObActionsAnyData *data,
- gpointer action_data);
+typedef void (*ObActionsDataFreeFunc)(gpointer options);
+typedef void (*ObActionsRunFunc)(ObActionsData *data,
+ gpointer options);
/*
The theory goes:
06:11 (@dana) eg show menu/exit, raise/focus, and cycling/directional/expose
*/
+typedef enum {
+ OB_ACTION_TYPE_GLOBAL,
+ OB_ACTION_TYPE_CLIENT,
+ OB_ACTION_TYPE_SELECTOR
+} ObActionsType;
+
struct _ObActionsAnyData {
ObUserAction uact;
gint x;
GSList *actions;
};
+struct _ObActionsData {
+ ObActionsType type;
+
+ union {
+ ObActionsAnyData any;
+ ObActionsGlobalData global;
+ ObActionsClientData client;
+ ObActionsSelectorData selector;
+ };
+};
+
void actions_startup(gboolean reconfigure);
void actions_shutdown(gboolean reconfigure);
gboolean actions_register(const gchar *name,
- gboolean interactive,
+ gboolean allow_interactive,
ObActionsDataSetupFunc setup,
- ObActionsDataParseFunc parse,
ObActionsDataFreeFunc free,
ObActionsRunFunc run);
+
+ObActionsAct* actions_parse(ObParseInst *i,
+ xmlDocPtr doc,
+ xmlNodePtr node);
+
+void actions_act_ref(ObActionsAct *act);
+void actions_act_unref(ObActionsAct *act);
#include "prop.h"
#include "translate.h"
#include "client.h"
+#include "actions.h"
#include "screen.h"
#include "parser/parse.h"
#include "openbox.h"
}
else if ((n = parse_find_node("action", node->children))) {
while (n) {
- ObAction *action;
+ ObActionsDefinition *action;
- action = action_parse(i, doc, n, OB_USER_ACTION_KEYBOARD_KEY);
+ action = actions_parse(i, doc, n);
if (action)
keyboard_bind(keylist, action);
n = parse_find_node("action", n->next);