all repos — openbox @ 7af1c6a9c3a57f3ded34fad3f9f4a30fe377a65e

openbox fork - make it a bit more like ryudo

menus grab the keyboard and pointer, thus making only one menu visible at a time, and making them act like gtk menus and * menus do, where you can click and drag and release to select something as well as click-release to elave it open while you search around the menu
Dana Jansens danakj@orodu.net
commit

7af1c6a9c3a57f3ded34fad3f9f4a30fe377a65e

parent

32c51bb4435f2f3c68616e26e7ee64dfcfb6a38d

4 files changed, 133 insertions(+), 47 deletions(-)

jump to
M openbox/event.copenbox/event.c

@@ -41,7 +41,7 @@ static void event_handle_root(XEvent *e);

static void event_handle_dock(Dock *s, XEvent *e); static void event_handle_dockapp(DockApp *app, XEvent *e); static void event_handle_client(Client *c, XEvent *e); -static void event_handle_menu(Menu *menu, Client *c, XEvent *e); +static void event_handle_menu(Client *c, XEvent *e); static void fd_event_handle(); #ifdef USE_SM static void ice_watch(IceConn conn, IcePointer data, Bool opening,

@@ -501,10 +501,7 @@ if (event_ignore(e, client))

return; /* deal with it in the kernel */ - if (menu) { - event_handle_menu(menu, client, e); - return; - } else if (client) + if (client) event_handle_client(client, e); else if (dockapp) event_handle_dockapp(dockapp, e);

@@ -535,6 +532,15 @@ e->xconfigurerequest.value_mask, &xwc);

xerror_set_ignore(FALSE); } + if (menu_visible) + if (e->type == MotionNotify || e->type == ButtonRelease || + e->type == ButtonPress || + e->type == KeyPress || e->type == KeyRelease) { + event_handle_menu(client, e); + + return; /* no dispatch! */ + } + if (moveresize_in_progress) if (e->type == MotionNotify || e->type == ButtonRelease || e->type == ButtonPress ||

@@ -977,57 +983,110 @@ #endif

} } -static void event_handle_menu(Menu *menu, Client *client, XEvent *e) +static void event_handle_menu(Client *client, XEvent *e) { + static MenuEntry *over = NULL; MenuEntry *entry; + Menu *top; + GSList *it; + + top = g_slist_nth_data(menu_visible, 0); g_message("EVENT %d", e->type); switch (e->type) { + case KeyPress: + if (over) { + if (over->parent->mouseover) + over->parent->mouseover(over, FALSE); + else + menu_control_mouseover(over, FALSE); + menu_entry_render(over); + } +/* + if (top->hide) + top->hide(top); + else +*/ + menu_hide(top); + break; case ButtonPress: + if (e->xbutton.button > 3) break; + g_message("BUTTON PRESS"); - if (e->xbutton.button == 3) - menu_hide(menu); - else if (e->xbutton.button == 1) { - entry = menu_find_entry(menu, e->xbutton.window); - if (!entry) - stacking_raise(MENU_AS_WINDOW(menu)); - } break; case ButtonRelease: - g_message("BUTTON RELEASED"); - if (!menu->shown) break; + if (e->xbutton.button > 3) break; -/* grab_pointer_window(FALSE, None, menu->frame);*/ + g_message("BUTTON RELEASED"); - if (e->xbutton.button == 1) { - entry = menu_find_entry(menu, e->xbutton.window); - if (entry) { - int junk; - Window wjunk; - guint ujunk, b, w, h; - XGetGeometry(ob_display, e->xbutton.window, - &wjunk, &junk, &junk, &w, &h, &b, &ujunk); - if (e->xbutton.x >= (signed)-b && - e->xbutton.y >= (signed)-b && - e->xbutton.x < (signed)(w+b) && - e->xbutton.y < (signed)(h+b)) { + for (it = menu_visible; it; it = g_slist_next(it)) { + Menu *m = it->data; + if (e->xbutton.x_root >= m->location.x - ob_rr_theme->bwidth && + e->xbutton.y_root >= m->location.y - ob_rr_theme->bwidth && + e->xbutton.x_root < m->location.x + m->size.width + + ob_rr_theme->bwidth && + e->xbutton.y_root < m->location.y + m->size.height + + ob_rr_theme->bwidth) { + if ((entry = menu_find_entry_by_pos(it->data, + e->xbutton.x_root - + m->location.x, + e->xbutton.y_root - + m->location.y))) { menu_entry_fire(entry); } + break; } } + if (!it) { + if (over) { + if (over->parent->mouseover) + over->parent->mouseover(over, FALSE); + else + menu_control_mouseover(over, FALSE); + } + menu_entry_render(over); +/* + if (top->hide) + top->hide(top); + else +*/ + menu_hide(top); + } break; - case EnterNotify: - case LeaveNotify: - g_message("enter/leave"); - entry = menu_find_entry(menu, e->xcrossing.window); - if (entry) { - if (menu->mouseover) - menu->mouseover(entry, e->type == EnterNotify); + case MotionNotify: + g_message("motion"); + for (it = menu_visible; it; it = g_slist_next(it)) { + Menu *m = it->data; + if ((entry = menu_find_entry_by_pos(it->data, + e->xmotion.x_root - + m->location.x, + e->xmotion.y_root - + m->location.y))) { + if (over && entry != over) { + if (over->parent->mouseover) + over->parent->mouseover(over, FALSE); + else + menu_control_mouseover(over, FALSE); + menu_entry_render(over); + } + + over = entry; + if (over->parent->mouseover) + over->parent->mouseover(over, TRUE); + else + menu_control_mouseover(over, TRUE); + menu_entry_render(over); + break; + } + } + if (!it && over) { + if (over->parent->mouseover) + over->parent->mouseover(over, FALSE); else - menu_control_mouseover(entry, e->type == EnterNotify); - - menu_entry_render(entry); + menu_control_mouseover(over, FALSE); + menu_entry_render(over); + over = NULL; } break; }
M openbox/menu.copenbox/menu.c

@@ -2,12 +2,12 @@ #include "menu.h"

#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)

@@ -310,6 +310,16 @@ menu_render(self);

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 {

@@ -326,6 +336,11 @@ menu_hide(self->open_submenu);

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); } }

@@ -353,6 +368,18 @@ }

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;

@@ -375,12 +402,10 @@

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);

@@ -413,9 +438,9 @@

/* 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 - - ob_rr_theme->bevel; + ob_rr_theme->bwidth; menu_show_full(self->submenu, x, self->parent->location.y + self->y,
M openbox/menu.hopenbox/menu.h

@@ -16,6 +16,7 @@ typedef void(*menu_controller_mouseover)(struct MenuEntry *self,

gboolean enter); extern GHashTable *menu_hash; +extern GSList *menu_visible; typedef struct Menu { ObWindow obwin;

@@ -131,6 +132,7 @@

void menu_add_entry(Menu *menu, MenuEntry *entry); MenuEntry *menu_find_entry(Menu *menu, Window win); +MenuEntry *menu_find_entry_by_pos(Menu *menu, int x, int y); void menu_entry_render(MenuEntry *self);
M openbox/menu_render.copenbox/menu_render.c

@@ -79,8 +79,8 @@ self->size.width += 2 * self->bullet_w + 2 * ob_rr_theme->bevel;

self->item_h += ob_rr_theme->bevel * 2; items_h = self->item_h * MAX(nitems, 1); - XResizeWindow(ob_display, self->frame, self->size.width, - MAX(self->title_h + items_h + ob_rr_theme->bwidth, 1)); + self->size.height = MAX(self->title_h + items_h + ob_rr_theme->bwidth, 1); + XResizeWindow(ob_display, self->frame, self->size.width,self->size.height); if (self->label) XMoveResizeWindow(ob_display, self->title, -ob_rr_theme->bwidth, -ob_rr_theme->bwidth,

@@ -101,7 +101,6 @@ menu_entry_render(it->data);

item_y += self->item_h; } - self->size.height = item_y; self->invalid = FALSE; }

@@ -134,6 +133,7 @@ (self->action || self->render_type == MenuEntryRenderType_Submenu) ?

self->a_hilite : self->a_item); break; } + g_message ("%s %d", self->label, self->hilite); XMoveResizeWindow(ob_display, self->item, 0, self->y, menu->size.width, menu->item_h);