X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=openbox%2Fmenu.c;h=8f7c8b6cb301277a81c96e31806a67c3da57ca63;hb=7af1c6a9c3a57f3ded34fad3f9f4a30fe377a65e;hp=862917685a2d70eea83db54270e197dc265525ee;hpb=a4a0cb78294bb1809b836ea1e86e9d7294bb2929;p=chaz%2Fopenbox diff --git a/openbox/menu.c b/openbox/menu.c index 86291768..8f7c8b6c 100644 --- a/openbox/menu.c +++ b/openbox/menu.c @@ -2,12 +2,12 @@ #include "openbox.h" #include "stacking.h" #include "grab.h" -#include "render/theme.h" #include "screen.h" #include "geom.h" #include "plugin.h" GHashTable *menu_hash = NULL; +GSList *menu_visible = NULL; #define FRAME_EVENTMASK (ButtonPressMask |ButtonMotionMask | EnterWindowMask | \ LeaveWindowMask) @@ -15,6 +15,52 @@ GHashTable *menu_hash = NULL; #define ENTRY_EVENTMASK (EnterWindowMask | LeaveWindowMask | \ ButtonPressMask | ButtonReleaseMask) +static void parse_menu(xmlDocPtr doc, xmlNodePtr node, void *data) +{ + Action *act; + xmlNodePtr nact; + gchar *id = NULL, *title = NULL, *label = NULL; + Menu *menu, *parent; + + if (!parse_attr_string("id", node->parent, &id)) + goto parse_menu_fail; + if (!parse_attr_string("label", node->parent, &title)) + goto parse_menu_fail; + + g_message("menu label %s", title); + + menu = menu_new(title, id, data ? *((Menu**)data) : NULL); + if (data) + *((Menu**)data) = menu; + + while (node) { + if (!xmlStrcasecmp(node->name, (const xmlChar*) "menu")) { + parent = menu; + parse_menu(doc, node->xmlChildrenNode, &parent); + menu_add_entry(menu, menu_entry_new_submenu(parent->label, + parent)); + } + else if (!xmlStrcasecmp(node->name, (const xmlChar*) "item")) { + if (parse_attr_string("label", node, &label)) { + if ((nact = parse_find_node("action", node->xmlChildrenNode))) + act = action_parse(doc, nact); + else + act = NULL; + if (act) + menu_add_entry(menu, menu_entry_new(label, act)); + else + menu_add_entry(menu, menu_entry_new_separator(label)); + g_free(label); + } + } + node = node->next; + } + +parse_menu_fail: + g_free(id); + g_free(title); +} + void menu_control_show(Menu *self, int x, int y, Client *client); void menu_destroy_hash_key(Menu *menu) @@ -64,15 +110,20 @@ void menu_entry_free(MenuEntry *self) void menu_startup() { +/* Menu *m; Menu *s; Menu *t; Action *a; +*/ menu_hash = g_hash_table_new_full(g_str_hash, g_str_equal, - menu_destroy_hash_key, + (GDestroyNotify)menu_destroy_hash_key, (GDestroyNotify)menu_destroy_hash_value); + parse_register("menu", parse_menu, NULL); + +/* m = menu_new("sex menu", "root", NULL); a = action_from_string("execute"); @@ -83,6 +134,7 @@ void menu_startup() menu_add_entry(m, menu_entry_new_separator("--")); a = action_from_string("exit"); menu_add_entry(m, menu_entry_new("exit", a)); +*/ /* s = menu_new("subsex menu", "submenu", m); @@ -159,23 +211,17 @@ Menu *menu_new_full(char *label, char *name, Menu *parent, attrib.override_redirect = TRUE; attrib.event_mask = FRAME_EVENTMASK; - self->frame = createWindow(ob_root, CWOverrideRedirect|CWEventMask, &attrib); + 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); - XSetWindowBorderWidth(ob_display, self->frame, theme_bwidth); - XSetWindowBackground(ob_display, self->frame, theme_b_color->pixel); - XSetWindowBorderWidth(ob_display, self->title, theme_bwidth); - XSetWindowBorder(ob_display, self->frame, theme_b_color->pixel); - XSetWindowBorder(ob_display, self->title, theme_b_color->pixel); + self->a_title = self->a_items = NULL; XMapWindow(ob_display, self->title); XMapWindow(ob_display, self->items); - self->a_title = RrAppearanceCopy(theme_a_menu_title); - self->a_items = RrAppearanceCopy(theme_a_menu); - g_hash_table_insert(window_map, &self->frame, self); g_hash_table_insert(window_map, &self->title, self); g_hash_table_insert(window_map, &self->items, self); @@ -234,9 +280,8 @@ void menu_add_entry(Menu *menu, MenuEntry *entry) attrib.event_mask = ENTRY_EVENTMASK; entry->item = createWindow(menu->items, CWEventMask, &attrib); XMapWindow(ob_display, entry->item); - entry->a_item = RrAppearanceCopy(theme_a_menu_item); - entry->a_disabled = RrAppearanceCopy(theme_a_menu_disabled); - entry->a_hilite = RrAppearanceCopy(theme_a_menu_hilite); + + entry->a_item = entry->a_disabled = entry->a_hilite = NULL; menu->invalid = TRUE; @@ -253,7 +298,7 @@ void menu_show(char *name, int x, int y, Client *client) name); return; } - + menu_show_full(self, x, y, client); } @@ -265,6 +310,16 @@ void menu_show_full(Menu *self, int x, int y, Client *client) self->client = client; + if (!self->shown) { + GSList *it; + + if (!self->parent) { + grab_pointer(TRUE, None); + grab_keyboard(TRUE); + } + menu_visible = g_slist_append(menu_visible, self); + } + if (self->show) { self->show(self, x, y, client); } else { @@ -281,6 +336,11 @@ void menu_hide(Menu *self) { if (self->parent && self->parent->open_submenu == self) self->parent->open_submenu = NULL; + if (!self->parent) { + grab_keyboard(FALSE); + grab_pointer(FALSE, None); + } + menu_visible = g_slist_remove(menu_visible, self); } } @@ -308,6 +368,18 @@ MenuEntry *menu_find_entry(Menu *menu, Window win) return NULL; } +MenuEntry *menu_find_entry_by_pos(Menu *menu, int x, int y) +{ + if (x < 0 || x >= menu->size.width || y < 0 || y >= menu->size.height) + return NULL; + + y -= menu->title_h + ob_rr_theme->bwidth; + if (y < 0) return NULL; + + g_message ("%d %p", y/menu->item_h, g_list_nth_data(menu->entries, y / menu->item_h)); + return g_list_nth_data(menu->entries, y / menu->item_h); +} + void menu_entry_fire(MenuEntry *self) { Menu *m; @@ -330,12 +402,10 @@ void menu_entry_fire(MenuEntry *self) void menu_control_show(Menu *self, int x, int y, Client *client) { g_assert(!self->invalid); - XMoveWindow(ob_display, self->frame, - MIN(x, screen_physical_size.width - self->size.width), - MIN(y, screen_physical_size.height - self->size.height)); POINT_SET(self->location, MIN(x, screen_physical_size.width - self->size.width), MIN(y, screen_physical_size.height - self->size.height)); + XMoveWindow(ob_display, self->frame, self->location.x, self->location.y); if (!self->shown) { XMapWindow(ob_display, self->frame); @@ -363,14 +433,14 @@ void menu_control_mouseover(MenuEntry *self, gboolean enter) { /* TODO: I don't understand why these bevels should be here. Something must be wrong in the width calculation */ x = self->parent->location.x + self->parent->size.width + - theme_bevel; + ob_rr_theme->bwidth; /* need to get the width. is this bad?*/ menu_render(self->submenu); - if (self->submenu->size.width + x > screen_physical_size.width) + if (self->submenu->size.width + x >= screen_physical_size.width) x = self->parent->location.x - self->submenu->size.width - - theme_bevel; + ob_rr_theme->bwidth; menu_show_full(self->submenu, x, self->parent->location.y + self->y,