X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fmenu.c;h=42a183aba775a3eb393d1fd3256f014b6c337dfa;hb=92d3f2342db3d3bfd5d41a6c3dc165efa7766ffa;hp=4a37d2c60849a709dc722d81f538eac43cfe66fb;hpb=79a352a40bd16924b1ca3df49f6c82d77e956a0e;p=chaz%2Fopenbox diff --git a/openbox/menu.c b/openbox/menu.c index 4a37d2c6..42a183ab 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -1,15 +1,19 @@ #include "menu.h" #include "openbox.h" #include "stacking.h" +#include "grab.h" #include "render/theme.h" static GHashTable *menu_hash = NULL; GHashTable *menu_map = NULL; +#define FRAME_EVENTMASK (ButtonMotionMask | EnterWindowMask | LeaveWindowMask) #define TITLE_EVENTMASK (ButtonPressMask | ButtonMotionMask) #define ENTRY_EVENTMASK (EnterWindowMask | LeaveWindowMask | \ ButtonPressMask | ButtonReleaseMask) +void menu_control_show(Menu *self, int x, int y, Client *client); + void menu_destroy_hash_key(gpointer data) { g_free(data); @@ -56,6 +60,7 @@ void menu_entry_free(MenuEntry *self) void menu_startup() { Menu *m; + Action *a; menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal, menu_destroy_hash_key, @@ -63,14 +68,14 @@ void menu_startup() menu_map = g_hash_table_new(g_int_hash, g_int_equal); m = menu_new("sex menu", "root", NULL); - menu_add_entry(m, menu_entry_new("foo shit etc bleh", - action_from_string("restart"))); - menu_add_entry(m, menu_entry_new("more shit", - action_from_string("restart"))); - menu_add_entry(m, menu_entry_new("", - action_from_string("restart"))); - menu_add_entry(m, menu_entry_new("and yet more", - action_from_string("restart"))); + a = action_from_string("execute"); + a->data.execute.path = g_strdup("xterm"); + menu_add_entry(m, menu_entry_new("xterm", a)); + a = action_from_string("restart"); + menu_add_entry(m, menu_entry_new("restart", a)); + menu_add_entry(m, menu_entry_new("--", NULL)); + a = action_from_string("exit"); + menu_add_entry(m, menu_entry_new("exit", a)); } void menu_shutdown() @@ -88,7 +93,8 @@ static Window createWindow(Window parent, unsigned long mask, } -Menu *menu_new(char *label, char *name, Menu *parent) +Menu *menu_new_full(char *label, char *name, Menu *parent, + menu_controller_show show, menu_controller_update update) { XSetWindowAttributes attrib; Menu *self; @@ -102,9 +108,16 @@ Menu *menu_new(char *label, char *name, Menu *parent) self->shown = FALSE; self->invalid = FALSE; /* default controllers? */ + + self->show = show; + self->hide = NULL; + self->update = update; + self->mouseover = NULL; + self->selected = NULL; attrib.override_redirect = TRUE; - self->frame = createWindow(ob_root, CWOverrideRedirect, &attrib); + attrib.event_mask = FRAME_EVENTMASK; + self->frame = createWindow(ob_root, CWOverrideRedirect|CWEventMask, &attrib); attrib.event_mask = TITLE_EVENTMASK; self->title = createWindow(self->frame, CWEventMask, &attrib); self->items = createWindow(self->frame, 0, &attrib); @@ -184,10 +197,6 @@ void menu_add_entry(Menu *menu, MenuEntry *entry) void menu_show(char *name, int x, int y, Client *client) { Menu *self; - GList *it; - int items_h; - int nitems = 0; /* each item, only one is used */ - int item_y; self = g_hash_table_lookup(menu_hash, name); if (!self) { @@ -196,66 +205,28 @@ void menu_show(char *name, int x, int y, Client *client) return; } - self->width = 1; - self->item_h = 0; - - /* set texture data and size them mofos out */ - self->a_title->texture[0].data.text.string = self->label; - appearance_minsize(self->a_title, &self->title_min_w, &self->title_h); - self->title_min_w += theme_bevel * 2; - self->title_h += theme_bevel * 2; - self->width = MAX(self->width, self->title_min_w); - - for (it = self->entries; it; it = it->next) { - MenuEntry *e = it->data; - int h; - - e->a_item->texture[0].data.text.string = e->label; - appearance_minsize(e->a_item, &e->min_w, &self->item_h); - self->width = MAX(self->width, e->min_w); - - e->a_disabled->texture[0].data.text.string = e->label; - appearance_minsize(e->a_disabled, &e->min_w, &h); - self->item_h = MAX(self->item_h, h); - self->width = MAX(self->width, e->min_w); - - e->a_hilite->texture[0].data.text.string = e->label; - appearance_minsize(e->a_hilite, &e->min_w, &h); - self->item_h = MAX(self->item_h, h); - self->width = MAX(self->width, e->min_w); - - e->min_w += theme_bevel * 2; - ++nitems; + if (self->invalid) { + if (self->update) { + self->update(self); + } else { + menu_render(self); + } } - self->bullet_w = self->item_h + theme_bevel; - self->width += 2 * self->bullet_w; - self->item_h += theme_bevel * 2; - items_h = self->item_h * nitems; - - RECT_SET(self->a_title->area, 0, 0, self->width, self->title_h); - RECT_SET(self->a_title->texture[0].position, 0, 0, self->width, - self->title_h); - RECT_SET(self->a_items->area, 0, 0, self->width, items_h); - - XMoveResizeWindow(ob_display, self->frame, x, y, self->width, - self->title_h + items_h); - XMoveResizeWindow(ob_display, self->title, -theme_bwidth, -theme_bwidth, - self->width, self->title_h); - XMoveResizeWindow(ob_display, self->items, 0, self->title_h + theme_bwidth, - self->width, items_h); - - paint(self->title, self->a_title); - paint(self->items, self->a_items); - - item_y = 0; - for (it = self->entries; it; it = it->next) { - ((MenuEntry*)it->data)->y = item_y; - menu_entry_render(it->data); - item_y += self->item_h; + + self->client = client; + + if (self->show) { + self->show(self, x, y, client); + } else { + menu_control_show(self, x, y, client); } +} - stacking_raise_internal(self->frame); - XMapWindow(ob_display, self->frame); +void menu_hide(Menu *self) { + if (self->shown) { + XUnmapWindow(ob_display, self->frame); + self->shown = FALSE; + } } MenuEntry *menu_find_entry(Menu *menu, Window win) @@ -276,7 +247,7 @@ void menu_entry_render(MenuEntry *self) Appearance *a; a = !self->enabled ? self->a_disabled : - (self->hilite ? self->a_hilite : self->a_item); + (self->hilite && self->action ? self->a_hilite : self->a_item); RECT_SET(a->area, 0, 0, menu->width, menu->item_h); @@ -292,3 +263,32 @@ void menu_entry_render(MenuEntry *self) paint(self->item, a); } + +void menu_entry_fire(MenuEntry *self) +{ + Menu *m; + + if (self->action) { + self->action->data.any.c = self->parent->client; + self->action->func(&self->action->data); + + /* hide the whole thing */ + m = self->parent; + while (m->parent) m = m->parent; + menu_hide(m); + } +} + +/* + Default menu controller action for showing. +*/ + +void menu_control_show(Menu *self, int x, int y, Client *client) { + XMoveWindow(ob_display, self->frame, x, y); + + if (!self->shown) { + stacking_raise_internal(self->frame); + XMapWindow(ob_display, self->frame); + self->shown = TRUE; + } +}