X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fmenu.c;h=2847b508a48fb303e8292e53da29fbbea91208a1;hb=5e06be6abb68a95aa9cafc5a6f0c5e295ebe9bee;hp=7e8685f09ea087282b8fd2066d392fb6f9010789;hpb=c34ef4028e504b8ce862b9c2e47b284ab66717dd;p=chaz%2Fopenbox diff --git a/openbox/menu.c b/openbox/menu.c index 7e8685f0..2847b508 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -12,7 +12,9 @@ #include "misc.h" #include "parser/parse.h" -GHashTable *menu_hash = NULL; +static GHashTable *menu_hash = NULL; + +ObParseInst *menu_parse_inst; typedef struct _ObMenuParseState ObMenuParseState; @@ -44,11 +46,11 @@ static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, if (state->menus) { if (parse_attr_string("label", node, &label)) { GSList *acts = NULL; - + for (node = node->xmlChildrenNode; node; node = node->next) if (!xmlStrcasecmp(node->name, (const xmlChar*) "action")) - acts = g_slist_append(acts, action_parse(doc, node)); - menu_add_normal(state->menus->data, label, acts); + acts = g_slist_append(acts, action_parse(i, doc, node)); + menu_add_normal(state->menus->data, 0, label, acts); g_free(label); } } @@ -59,42 +61,67 @@ static void parse_menu_separator(ObParseInst *i, gpointer data) { ObMenuParseState *state = data; - + if (state->menus) - menu_add_separator(state->menus->data); + 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) { ObMenuParseState *state = data; - gchar *name = NULL, *title = NULL; + gchar *name = NULL, *title = NULL, *plugin = NULL; if (!parse_attr_string("id", node, &name)) goto parse_menu_fail; if (!g_hash_table_lookup(menu_hash, name)) { - if (!parse_attr_string("label", node, &title)) - goto parse_menu_fail; - - if (menu_new(name, title, NULL)) { - state->menus = g_slist_prepend(state->menus, name); - parse_tree(i, doc, node->xmlChildrenNode); - state->menus = g_slist_delete_link(state->menus, state->menus); + if (parse_attr_string("plugin", node, &plugin)) { + menu_open_plugin(i, name, plugin); + } else { + if (!parse_attr_string("label", node, &title)) + goto parse_menu_fail; + + if (menu_new(name, title, NULL)) { + state->menus = g_slist_prepend(state->menus, name); + parse_tree(i, doc, node->xmlChildrenNode); + state->menus = g_slist_delete_link(state->menus, state->menus); + } } } if (state->menus) - menu_add_submenu(state->menus->data, name); + menu_add_submenu(state->menus->data, 0, name); parse_menu_fail: g_free(name); g_free(title); + g_free(plugin); } 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); @@ -104,70 +131,91 @@ void menu_startup(ObParseInst *i) { 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); + xmlFreeDoc(doc); } - - 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) +{ + ObMenu *self; + + if (!(self = menu_from_name(name))) return; + g_hash_table_remove(menu_hash, self->name); } void menu_show(gchar *name, gint x, gint y, ObClient *client) @@ -177,14 +225,12 @@ void menu_show(gchar *name, gint x, gint y, ObClient *client) if (!(self = menu_from_name(name))) return; - /* XXX update entries */ - frame = menu_frame_new(self, client); menu_frame_move(frame, x, y); menu_frame_show(frame, NULL); } -static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type) +static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type, gint id) { ObMenuEntry *self; @@ -193,7 +239,17 @@ static ObMenuEntry* menu_entry_new(ObMenu *menu, ObMenuEntryType type) self = g_new0(ObMenuEntry, 1); self->type = type; self->menu = menu; - self->enabled = TRUE; + self->id = id; + + switch (type) { + case OB_MENU_ENTRY_TYPE_NORMAL: + self->data.normal.enabled = TRUE; + break; + case OB_MENU_ENTRY_TYPE_SUBMENU: + case OB_MENU_ENTRY_TYPE_SEPARATOR: + break; + } + return self; } @@ -211,6 +267,8 @@ static void menu_entry_free(ObMenuEntry *self) } break; case OB_MENU_ENTRY_TYPE_SUBMENU: + g_free(self->data.submenu.name); + break; case OB_MENU_ENTRY_TYPE_SEPARATOR: break; } @@ -238,42 +296,97 @@ static void menu_clear_entries_internal(ObMenu *self) } } -void menu_add_normal(gchar *name, gchar *label, GSList *actions) +ObMenuEntry* menu_add_normal(gchar *name, gint id, gchar *label, + GSList *actions) { ObMenu *self; ObMenuEntry *e; if (!(self = menu_from_name(name))) return; - e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_NORMAL); + e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_NORMAL, id); e->data.normal.label = g_strdup(label); e->data.normal.actions = actions; self->entries = g_list_append(self->entries, e); + return e; } -void menu_add_submenu(gchar *name, 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); - e->data.submenu.submenu = sub; + e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SUBMENU, id); + e->data.submenu.name = g_strdup(submenu); self->entries = g_list_append(self->entries, e); + return e; } -void menu_add_separator(gchar *name) +ObMenuEntry* menu_add_separator(gchar *name, gint id) { ObMenu *self; ObMenuEntry *e; if (!(self = menu_from_name(name))) return; - e = menu_entry_new(self, OB_MENU_ENTRY_TYPE_SEPARATOR); + 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) +{ + ObMenu *self; + + if (!(self = menu_from_name(name))) return; + 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; + GList *it; + + for (it = self->entries; it; it = g_list_next(it)) { + ObMenuEntry *e = it->data; + + if (e->id == id) { + ret = e; + break; + } + } + 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); + } }