#include "misc.h"
#include "parser/parse.h"
-GHashTable *menu_hash = NULL;
+static GHashTable *menu_hash = NULL;
+
+ObParseInst *menu_parse_inst;
typedef struct _ObMenuParseState ObMenuParseState;
for (node = node->xmlChildrenNode; node; node = node->next)
if (!xmlStrcasecmp(node->name, (const xmlChar*) "action"))
- acts = g_slist_append(acts, action_parse(doc, node));
+ acts = g_slist_append(acts, action_parse(i, doc, node));
menu_add_normal(state->menus->data, 0, label, acts);
g_free(label);
}
menu_add_separator(state->menus->data, 0);
}
+gboolean menu_open_plugin(ObParseInst *i, gchar *name, gchar *plugin)
+{
+ gboolean ret = FALSE;
+
+ if (plugin_open(plugin, i)) {
+ plugin_start(plugin);
+ if (g_hash_table_lookup(menu_hash, name))
+ ret = TRUE;
+ else
+ g_warning("Specified plugin '%s' did not provide the "
+ "menu '%s'", plugin, name);
+ }
+ return ret;
+}
+
static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
gpointer data)
{
if (!g_hash_table_lookup(menu_hash, name)) {
if (parse_attr_string("plugin", node, &plugin)) {
- if (!plugin_open(plugin, i))
- goto parse_menu_fail;
- plugin_start(plugin);
- if (!g_hash_table_lookup(menu_hash, name))
- g_warning("Specified plugin '%s' did not provide the "
- "menu '%s'", plugin, name);
- goto parse_menu_fail;
+ menu_open_plugin(i, name, plugin);
} else {
if (!parse_attr_string("label", node, &title))
goto parse_menu_fail;
void menu_destroy_hash_value(ObMenu *self)
{
/* XXX make sure its not visible */
+
+ if (self->destroy_func)
+ self->destroy_func(self, self->data);
+
menu_clear_entries_internal(self);
g_free(self->name);
g_free(self->title);
{
menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
(GDestroyNotify)menu_destroy_hash_value);
+ menu_parse_inst = parse_startup();
}
void menu_shutdown()
{
+ parse_shutdown(menu_parse_inst);
+ menu_parse_inst = NULL;
+
menu_frame_hide_all();
g_hash_table_destroy(menu_hash);
menu_hash = NULL;
}
+gboolean menu_open(gchar *file, xmlDocPtr *doc, xmlNodePtr *node)
+{
+ gboolean loaded = TRUE;
+ gchar *p;
+
+ p = g_build_filename(g_get_home_dir(), ".openbox", file, NULL);
+ if (!parse_load(p, "openbox_menu", doc, node)) {
+ g_free(p);
+ p = g_build_filename(RCDIR, file, NULL);
+ if (!parse_load(p, "openbox_menu", doc, node)) {
+ g_free(p);
+ p = g_strdup(file);
+ if (!parse_load(p, "openbox_menu", doc, node)) {
+ g_warning("Failed to load menu from '%s'", file);
+ loaded = FALSE;
+ }
+ }
+ }
+ g_free(p);
+ return loaded;
+}
+
void menu_parse()
{
- ObParseInst *i;
ObMenuParseState parse_state;
xmlDocPtr doc;
xmlNodePtr node;
- gchar *p;
gboolean loaded = FALSE;
+ GSList *it;
+
+ for (it = config_menu_files; it; it = g_slist_next(it)) {
+ if (menu_open(it->data, &doc, &node))
+ loaded = TRUE;
- i = parse_startup();
-
- if (config_menu_path)
- if (!(loaded =
- parse_load(config_menu_path, "openbox_menu", &doc, &node)))
- g_warning("Failed to load menu from '%s'", config_menu_path);
- if (!loaded) {
- p = g_build_filename(g_get_home_dir(), ".openbox", "menu", NULL);
- if (!(loaded =
- parse_load(p, "openbox_menu", &doc, &node)))
- g_warning("Failed to load menu from '%s'", p);
- g_free(p);
- }
- if (!loaded) {
- p = g_build_filename(RCDIR, "menu", NULL);
- if (!(loaded =
- parse_load(p, "openbox_menu", &doc, &node)))
- g_warning("Failed to load menu from '%s'", p);
- g_free(p);
}
+ if (!loaded)
+ loaded = menu_open("menu", &doc, &node);
if (loaded) {
parse_state.menus = NULL;
- parse_register(i, "menu", parse_menu, &parse_state);
- parse_register(i, "item", parse_menu_item, &parse_state);
- parse_register(i, "separator", parse_menu_separator, &parse_state);
- parse_tree(i, doc, node->xmlChildrenNode);
+ parse_register(menu_parse_inst, "menu", parse_menu, &parse_state);
+ parse_register(menu_parse_inst, "item", parse_menu_item, &parse_state);
+ parse_register(menu_parse_inst, "separator",
+ parse_menu_separator, &parse_state);
+ parse_tree(menu_parse_inst, doc, node->xmlChildrenNode);
}
-
- parse_shutdown(i);
}
-gboolean menu_new(gchar *name, gchar *title, gpointer data)
+ObMenu* menu_new(gchar *name, gchar *title, gpointer data)
{
ObMenu *self;
- if (g_hash_table_lookup(menu_hash, name)) return FALSE;
+ /*if (g_hash_table_lookup(menu_hash, name)) return FALSE;*/
self = g_new0(ObMenu, 1);
self->name = g_strdup(name);
self->title = g_strdup(title);
self->data = data;
- g_hash_table_insert(menu_hash, self->name, self);
+ g_hash_table_replace(menu_hash, self->name, self);
- return TRUE;
+ return self;
}
void menu_free(gchar *name)
}
break;
case OB_MENU_ENTRY_TYPE_SUBMENU:
+ g_free(self->data.submenu.name);
+ break;
case OB_MENU_ENTRY_TYPE_SEPARATOR:
break;
}
}
}
-void menu_add_normal(gchar *name, gint id, gchar *label, GSList *actions)
+ObMenuEntry* menu_add_normal(gchar *name, gint id, gchar *label,
+ GSList *actions)
{
ObMenu *self;
ObMenuEntry *e;
e->data.normal.actions = actions;
self->entries = g_list_append(self->entries, e);
+ return e;
}
-void menu_add_submenu(gchar *name, gint id, gchar *submenu)
+ObMenuEntry* menu_add_submenu(gchar *name, gint id, gchar *submenu)
{
- ObMenu *self, *sub;
+ ObMenu *self;
ObMenuEntry *e;
if (!(self = menu_from_name(name))) return;
- if (!(sub = menu_from_name(submenu))) return;
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SUBMENU, id);
- e->data.submenu.submenu = sub;
+ e->data.submenu.name = g_strdup(submenu);
self->entries = g_list_append(self->entries, e);
+ return e;
}
-void menu_add_separator(gchar *name, gint id)
+ObMenuEntry* menu_add_separator(gchar *name, gint id)
{
ObMenu *self;
ObMenuEntry *e;
e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SEPARATOR, id);
self->entries = g_list_append(self->entries, e);
+ return e;
}
void menu_set_update_func(gchar *name, ObMenuUpdateFunc func)
self->update_func = func;
}
+void menu_set_execute_func(gchar *name, ObMenuExecuteFunc func)
+{
+ ObMenu *self;
+
+ if (!(self = menu_from_name(name))) return;
+ self->execute_func = func;
+}
+
+void menu_set_destroy_func(gchar *name, ObMenuDestroyFunc func)
+{
+ ObMenu *self;
+
+ if (!(self = menu_from_name(name))) return;
+ self->destroy_func = func;
+}
+
ObMenuEntry* menu_find_entry_id(ObMenu *self, gint id)
{
ObMenuEntry *ret = NULL;
}
return ret;
}
+
+void menu_find_submenus(ObMenu *self)
+{
+ GList *it;
+
+ for (it = self->entries; it; it = g_list_next(it)) {
+ ObMenuEntry *e = it->data;
+
+ if (e->type == OB_MENU_ENTRY_TYPE_SUBMENU)
+ e->data.submenu.submenu = menu_from_name(e->data.submenu.name);
+ }
+}