From f7eb47dba4b091b67a28404ce461b15dffcb4298 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Thu, 28 Aug 2003 07:34:03 +0000 Subject: [PATCH] make client-list-menu work too more menu cleanups --- Makefile.am | 4 +- data/menu | 3 + openbox/action.c | 9 +- openbox/action.h | 2 +- openbox/config.c | 4 +- openbox/event.c | 11 +- openbox/menu.c | 45 +++++++-- openbox/menu.h | 13 ++- openbox/menuframe.c | 28 ++++-- openbox/menuframe.h | 2 +- plugins/menu/client_list_menu.c | 171 ++++++++++++++------------------ plugins/menu/client_menu.c | 9 ++ 12 files changed, 173 insertions(+), 128 deletions(-) diff --git a/Makefile.am b/Makefile.am index c056e25f..4b162ed4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,11 +27,11 @@ bin_PROGRAMS = \ plugin_LTLIBRARIES = \ plugins/placement/placement.la \ - plugins/menu/client_menu.la + plugins/menu/client_menu.la \ + plugins/menu/client_list_menu.la # plugins/menu/timed_menu.la \ # plugins/menu/fifo_menu.la \ # plugins/menu/include_menu.la \ -# plugins/menu/client_list_menu.la if OBCONF bin_PROGRAMS += \ diff --git a/data/menu b/data/menu index ef8b3145..230a3346 100644 --- a/data/menu +++ b/data/menu @@ -28,6 +28,7 @@ + @@ -35,6 +36,8 @@ + + diff --git a/openbox/action.c b/openbox/action.c index 0025187b..2f7c5c7d 100644 --- a/openbox/action.c +++ b/openbox/action.c @@ -693,7 +693,7 @@ ObAction *action_from_string(char *name) return a; } -ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node) +ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node) { char *actname; ObAction *act = NULL; @@ -705,8 +705,13 @@ ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node) if ((n = parse_find_node("execute", node->xmlChildrenNode))) act->data.execute.path = parse_string(doc, n); } else if (act->func == action_showmenu) { - if ((n = parse_find_node("menu", node->xmlChildrenNode))) + if ((n = parse_find_node("menu", node->xmlChildrenNode))) { + gchar *plugin; + act->data.showmenu.name = parse_string(doc, n); + if (parse_attr_string("plugin", n, &plugin)) + menu_open_plugin(i, act->data.showmenu.name, plugin); + } } else if (act->func == action_desktop) { if ((n = parse_find_node("desktop", node->xmlChildrenNode))) act->data.desktop.desk = parse_int(doc, n); diff --git a/openbox/action.h b/openbox/action.h index 2f57cb87..bacd4b5c 100644 --- a/openbox/action.h +++ b/openbox/action.h @@ -137,7 +137,7 @@ ObAction *action_new(void (*func)(union ActionData *data)); */ ObAction *action_from_string(char *name); -ObAction *action_parse(xmlDocPtr doc, xmlNodePtr node); +ObAction *action_parse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node); void action_free(ObAction *a); /* Execute */ diff --git a/openbox/config.c b/openbox/config.c index d03ba031..f0b78d7d 100644 --- a/openbox/config.c +++ b/openbox/config.c @@ -92,7 +92,7 @@ static void parse_key(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, if (keylist) { nact = parse_find_node("action", node); while (nact) { - if ((action = action_parse(doc, nact))) { + if ((action = action_parse(i, doc, nact))) { /* validate that its okay for a key binding */ if (action->func == action_moveresize && action->data.moveresize.corner != @@ -165,7 +165,7 @@ static void parse_mouse(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, goto next_nbut; nact = parse_find_node("action", nbut->xmlChildrenNode); while (nact) { - if ((action = action_parse(doc, nact))) { + if ((action = action_parse(i, doc, nact))) { /* validate that its okay for a mouse binding*/ if (mact == OB_MOUSE_ACTION_MOTION) { if (action->func != action_moveresize || diff --git a/openbox/event.c b/openbox/event.c index fc45060c..bbde397e 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -1170,13 +1170,14 @@ static void event_handle_menu(XEvent *ev) switch (ev->type) { case ButtonRelease: - if (!(f = menu_frame_under(ev->xmotion.x_root, - ev->xmotion.y_root))) + if (!(f = menu_frame_under(ev->xbutton.x_root, + ev->xbutton.y_root))) menu_frame_hide_all(); else { - if ((e = menu_entry_frame_under(ev->xmotion.x_root, - ev->xmotion.y_root))) - menu_entry_frame_execute(e); + if ((e = menu_entry_frame_under(ev->xbutton.x_root, + ev->xbutton.y_root))) + menu_entry_frame_execute(e, + !(ev->xbutton.state & ControlMask)); } break; case MotionNotify: diff --git a/openbox/menu.c b/openbox/menu.c index 5efb0c35..324b3629 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -47,7 +47,7 @@ static void parse_menu_item(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, 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); } @@ -64,6 +64,21 @@ static void parse_menu_separator(ObParseInst *i, 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) { @@ -75,13 +90,7 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node, 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; @@ -107,6 +116,10 @@ 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); @@ -315,6 +328,22 @@ 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; diff --git a/openbox/menu.h b/openbox/menu.h index a3332280..c4c9deea 100644 --- a/openbox/menu.h +++ b/openbox/menu.h @@ -3,13 +3,15 @@ #include "action.h" #include "window.h" -#include "render/render.h" #include "geom.h" +#include "render/render.h" +#include "parser/parse.h" #include struct _ObClient; struct _ObMenuFrame; +struct _ObMenuEntryFrame; typedef struct _ObMenu ObMenu; typedef struct _ObMenuEntry ObMenuEntry; @@ -18,6 +20,9 @@ typedef struct _ObSubmenuMenuEntry ObSubmenuMenuEntry; typedef struct _ObSeparatorMenuEntry ObSeparatorMenuEntry; typedef void (*ObMenuUpdateFunc)(struct _ObMenuFrame *frame, gpointer data); +typedef void (*ObMenuExecuteFunc)(struct _ObMenuEntryFrame *frame, + gpointer data); +typedef void (*ObMenuDestroyFunc)(struct _ObMenu *menu, gpointer data); extern GList *menu_visible; @@ -35,6 +40,8 @@ struct _ObMenu gpointer data; ObMenuUpdateFunc update_func; + ObMenuExecuteFunc execute_func; + ObMenuDestroyFunc destroy_func; }; typedef enum @@ -84,7 +91,11 @@ void menu_parse(); gboolean menu_new(gchar *name, gchar *title, gpointer data); void menu_free(gchar *name); +gboolean menu_open_plugin(ObParseInst *i, gchar *name, gchar *plugin); + void menu_set_update_func(gchar *name, ObMenuUpdateFunc func); +void menu_set_execute_func(gchar *name, ObMenuExecuteFunc func); +void menu_set_destroy_func(gchar *name, ObMenuDestroyFunc func); void menu_show(gchar *name, gint x, gint y, struct _ObClient *client); diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 832f49af..ea7f254c 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -344,8 +344,10 @@ static void menu_frame_render(ObMenuFrame *self) } if (!w) w = 10; - if (!allitems_h) allitems_h = 3; - if (!h) h = 3; + if (!allitems_h) { + allitems_h = 3; + h += 3; + } XResizeWindow(ob_display, self->window, w, h); XResizeWindow(ob_display, self->items, w, allitems_h); @@ -546,20 +548,24 @@ void menu_entry_frame_show_submenu(ObMenuEntryFrame *self) menu_frame_show(f, self->frame); } -void menu_entry_frame_execute(ObMenuEntryFrame *self) +void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide) { if (self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) { - GSList *it; - /* release grabs before executing the shit */ menu_frame_hide_all(); - for (it = self->entry->data.normal.actions; it; - it = g_slist_next(it)) - { - ObAction *act = it->data; - act->data.any.c = self->frame->client; - act->func(&act->data); + if (self->frame->menu->execute_func) + self->frame->menu->execute_func(self, self->frame->menu->data); + else { + GSList *it; + + for (it = self->entry->data.normal.actions; it; + it = g_slist_next(it)) + { + ObAction *act = it->data; + act->data.any.c = self->frame->client; + act->func(&act->data); + } } } } diff --git a/openbox/menuframe.h b/openbox/menuframe.h index 8cfc837b..7c744fee 100644 --- a/openbox/menuframe.h +++ b/openbox/menuframe.h @@ -94,6 +94,6 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y); void menu_entry_frame_show_submenu(ObMenuEntryFrame *self); -void menu_entry_frame_execute(ObMenuEntryFrame *self); +void menu_entry_frame_execute(ObMenuEntryFrame *self, gboolean hide); #endif diff --git a/plugins/menu/client_list_menu.c b/plugins/menu/client_list_menu.c index 166ac71d..2f5c5f9f 100644 --- a/plugins/menu/client_list_menu.c +++ b/plugins/menu/client_list_menu.c @@ -1,142 +1,123 @@ #include "kernel/openbox.h" #include "kernel/menu.h" +#include "kernel/menuframe.h" #include "kernel/action.h" #include "kernel/screen.h" #include "kernel/client.h" #include "kernel/focus.h" +#include "gettext.h" #include "render/theme.h" #include -static char *PLUGIN_NAME = "client_list_menu"; +#define MENU_NAME "client-list-menu" typedef struct { - GSList *submenus; -} Client_List_Menu_Data; + /* how many desktop menus we've made */ + guint desktops; +} MenuData; typedef struct { guint desktop; -} Client_List_Desktop_Menu_Data; - -#define CLIENT_LIST_MENU(m) ((ObMenu *)m) -#define CLIENT_LIST_MENU_DATA(m) ((Client_List_Menu_Data *)((ObMenu *)m)->plugin_data) - -#define CLIENT_LIST_DESKTOP_MENU(m) ((ObMenu *)m) -#define CLIENT_LIST_DESKTOP_MENU_DATA(m) ((Client_List_Desktop_Menu_Data *)((ObMenu *)m)->plugin_data) - -static void self_update(ObMenu *self); -static void self_destroy(ObMenu *self); +} DesktopData; void plugin_setup_config() { } -void plugin_shutdown() { } -void plugin_destroy (ObMenu *m) { } -void *plugin_create() -{ - ObMenu *menu = menu_new_full("Desktops", "client-list-menu", NULL, - NULL, self_update, NULL, - NULL, NULL, self_destroy); - - menu->plugin = PLUGIN_NAME; - menu->plugin_data = g_new(Client_List_Menu_Data, 1); - CLIENT_LIST_MENU_DATA(menu)->submenus = NULL; - - return (void *)menu; -} - -void plugin_startup() -{ - plugin_create("client_list_menu"); -} - - -static void desk_update(ObMenu *self) +static void desk_menu_update(ObMenuFrame *frame, gpointer data) { + ObMenu *menu = frame->menu; + DesktopData *d = data; GList *it; - guint desk; - - menu_clear(self); - desk = CLIENT_LIST_DESKTOP_MENU_DATA(self)->desktop; + menu_clear_entries(menu->name); - for (it = focus_order[desk]; it; it = g_list_next(it)) { - ObClient *c = (ObClient *)it->data; + for (it = focus_order[d->desktop]; it; it = g_list_next(it)) { + ObClient *c = it->data; if (client_normal(c)) { - ObAction* a = action_from_string("activate"); - a->data.activate.c = c; - menu_add_entry(self, menu_entry_new((c->iconic ? - c->icon_title : - c->title), a)); + GSList *acts; + ObAction* act; + + act = action_from_string("activate"); + act->data.activate.c = c; + acts = g_slist_prepend(NULL, act); + menu_add_normal(menu->name, 0, + (c->iconic ? c->icon_title : c->title), acts); } } - - menu_render(self); + } -static void desk_selected(ObMenuEntry *entry, - unsigned int button, unsigned int x, unsigned int y) +/* executes it without changing the client in the actions, since we set that + when we make the actions! */ +static void desk_menu_execute(ObMenuEntryFrame *self, gpointer data) { - entry->action->data.activate.here = (button == 2); - entry->parent->client = entry->action->data.activate.c; - menu_entry_fire(entry, button, x, y); + GSList *it; + + for (it = self->entry->data.normal.actions; it; it = g_slist_next(it)) + { + ObAction *act = it->data; + act->func(&act->data); + } } -static void desk_destroy(ObMenu *self) +static void desk_menu_destroy(ObMenu *menu, gpointer data) { - g_free(self->plugin_data); + DesktopData *d = data; + + g_free(d); } -static void self_update(ObMenu *self) +static void self_update(ObMenuFrame *frame, gpointer data) { - guint i, n; - ObMenu *deskmenu; - gchar *s; - GList *eit, *enext; - GSList *sit, *snext; - - n = g_slist_length(CLIENT_LIST_MENU_DATA(self)->submenus); + guint i; + MenuData *d = data; + + menu_clear_entries(MENU_NAME); for (i = 0; i < screen_num_desktops; ++i) { - if (i >= n) { - s = g_strdup_printf("client-list-menu-desktop-%d", i); - deskmenu = menu_new_full(screen_desktop_names[i], s, self, - NULL, - desk_update, desk_selected, NULL, NULL, - desk_destroy); - g_free(s); - - deskmenu->plugin = PLUGIN_NAME; - deskmenu->plugin_data = g_new(Client_List_Desktop_Menu_Data, 1); - CLIENT_LIST_DESKTOP_MENU_DATA(deskmenu)->desktop = i; - - CLIENT_LIST_MENU_DATA(self)->submenus = - g_slist_append(CLIENT_LIST_MENU_DATA(self)->submenus, - deskmenu); - } + gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i); + DesktopData *data = g_new(DesktopData, 1); - menu_add_entry(self, menu_entry_new_submenu(screen_desktop_names[i], - deskmenu)); - } + data->desktop = i; + menu_new(name, screen_desktop_names[i], data); + menu_set_update_func(name, desk_menu_update); + menu_set_execute_func(name, desk_menu_execute); + menu_set_destroy_func(name, desk_menu_destroy); - for (eit = g_list_nth(self->entries, i); eit; eit = enext) { - enext = g_list_next(eit); - menu_entry_free(eit->data); - self->entries = g_list_delete_link(self->entries, eit); + menu_add_submenu(MENU_NAME, 0, name); + + g_free(name); } - for (sit = g_slist_nth(CLIENT_LIST_MENU_DATA(self)->submenus, i); - sit; sit = snext) { - snext = g_slist_next(sit); - menu_free(sit->data); - CLIENT_LIST_MENU_DATA(self)->submenus = - g_slist_delete_link(CLIENT_LIST_MENU_DATA(self)->submenus, sit); + d->desktops = MAX(d->desktops, screen_num_desktops); +} + +static void self_destroy(ObMenu *menu, gpointer data) +{ + MenuData *d = data; + guint i; + + for (i = 0; i < d->desktops; ++i) { + gchar *name = g_strdup_printf("%s-%u", MENU_NAME, i); + menu_free(name); + g_free(name); } + g_free(d); +} + +void plugin_startup() +{ + MenuData *data; - menu_render(self); + data = g_new(MenuData, 1); + data->desktops = 0; + menu_new(MENU_NAME, _("Desktops"), data); + menu_set_update_func(MENU_NAME, self_update); + menu_set_destroy_func(MENU_NAME, self_destroy); } -static void self_destroy(ObMenu *self) +void plugin_shutdown() { - g_free(self->plugin_data); + menu_free(MENU_NAME); } diff --git a/plugins/menu/client_menu.c b/plugins/menu/client_menu.c index c9ec5916..32277047 100644 --- a/plugins/menu/client_menu.c +++ b/plugins/menu/client_menu.c @@ -82,6 +82,15 @@ static void layer_update(ObMenuFrame *frame, gpointer data) if (e->type == OB_MENU_ENTRY_TYPE_NORMAL) e->data.normal.enabled = !!frame->client; } + + e = menu_find_entry_id(menu, LAYER_TOP); + e->data.normal.enabled = !frame->client->above; + + e = menu_find_entry_id(menu, LAYER_NORMAL); + e->data.normal.enabled = !(frame->client->above || frame->client->below); + + e = menu_find_entry_id(menu, LAYER_BOTTOM); + e->data.normal.enabled = !frame->client->below; } static void send_to_update(ObMenuFrame *frame, gpointer data) -- 2.39.2