From 111465b7373cdcdd791b603aefd882ae06d5bf0b Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 14 Dec 2009 16:08:30 -0500 Subject: Let menus place themselves on monitors where the mouse is not present This fixes a bug which forced menus to show up on the same monitor as the mouse pointer. --- openbox/menuframe.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'openbox/menuframe.c') diff --git a/openbox/menuframe.c b/openbox/menuframe.c index a9b54408..3b53a63e 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -192,6 +192,7 @@ static void menu_entry_frame_free(ObMenuEntryFrame *self) void menu_frame_move(ObMenuFrame *self, gint x, gint y) { RECT_SET_POINT(self->area, x, y); + self->monitor = screen_find_monitor_point(x, y); XMoveWindow(ob_display, self->window, self->area.x, self->area.y); } @@ -294,7 +295,7 @@ void menu_frame_move_on_screen(ObMenuFrame *self, gint x, gint y, *dx = *dy = 0; - a = screen_physical_area_monitor(self->monitor); + a = screen_physical_area_monitor(screen_find_monitor_point(x, y)); half = g_list_length(self->entries) / 2; pos = g_list_index(self->entries, self->selected); @@ -953,17 +954,6 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y, if (!menu_frame_show(self)) return FALSE; - /* find the monitor the menu is on */ - for (i = 0; i < screen_num_monitors; ++i) { - Rect *a = screen_physical_area_monitor(i); - gboolean contains = RECT_CONTAINS(*a, x, y); - g_free(a); - if (contains) { - self->monitor = i; - break; - } - } - if (self->menu->place_func) self->menu->place_func(self, &x, &y, mouse, self->menu->data); else -- cgit v1.2.3 From 828c095c8b5a2df96a38faaeb8a0df504e68e70f Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Mon, 14 Dec 2009 18:18:10 -0500 Subject: Don't hide submenus immediately when unselecting the parent's entry This allows users to move to the submenu across other menu items (the same as they already could across other menu items that were submenus). This uses the same config delay for hiding submenus as it does for showing new ones. Based off the ideas in bug #3762. --- openbox/menuframe.c | 76 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 12 deletions(-) (limited to 'openbox/menuframe.c') diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 3b53a63e..ad692d2e 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -48,7 +48,8 @@ static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry, ObMenuFrame *frame); static void menu_entry_frame_free(ObMenuEntryFrame *self); static void menu_frame_update(ObMenuFrame *self); -static gboolean menu_entry_frame_submenu_timeout(gpointer data); +static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data); +static gboolean menu_entry_frame_submenu_show_timeout(gpointer data); static void menu_frame_hide(ObMenuFrame *self); static Window createWindow(Window parent, gulong mask, @@ -94,6 +95,7 @@ ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client) self->type = Window_Menu; self->menu = menu; self->selected = NULL; + self->open_submenu = NULL; self->client = client; self->direction_right = TRUE; self->show_from = show_from; @@ -984,6 +986,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent, self->monitor = parent->monitor; self->parent = parent; self->parent_entry = parent_entry; + parent->open_submenu = parent_entry; /* set up parent's child to be us */ if (parent->child) @@ -1028,8 +1031,10 @@ static void menu_frame_hide(ObMenuFrame *self) if (self->child) menu_frame_hide(self->child); - if (self->parent) + if (self->parent && self->parent->child == self) { self->parent->child = NULL; + self->parent->open_submenu = NULL; + } self->parent = NULL; self->parent_entry = NULL; @@ -1053,7 +1058,10 @@ void menu_frame_hide_all(void) if (config_submenu_show_delay) { /* remove any submenu open requests */ ob_main_loop_timeout_remove(ob_main_loop, - menu_entry_frame_submenu_timeout); + menu_entry_frame_submenu_show_timeout); + /* remove any submenu close delays */ + ob_main_loop_timeout_remove(ob_main_loop, + menu_entry_frame_submenu_hide_timeout); } if ((it = g_list_last(menu_frame_visible))) menu_frame_hide(it->data); @@ -1067,8 +1075,13 @@ void menu_frame_hide_all_client(ObClient *client) if (f->client == client) { if (config_submenu_show_delay) { /* remove any submenu open requests */ - ob_main_loop_timeout_remove(ob_main_loop, - menu_entry_frame_submenu_timeout); + ob_main_loop_timeout_remove + (ob_main_loop, + menu_entry_frame_submenu_show_timeout); + /* remove any submenu close delays */ + ob_main_loop_timeout_remove + (ob_main_loop, + menu_entry_frame_submenu_hide_timeout); } menu_frame_hide(f); } @@ -1103,7 +1116,6 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y) for (it = frame->entries; it; it = g_list_next(it)) { ObMenuEntryFrame *e = it->data; - if (RECT_CONTAINS(e->area, x, y)) { ret = e; break; @@ -1113,7 +1125,15 @@ ObMenuEntryFrame* menu_entry_frame_under(gint x, gint y) return ret; } -static gboolean menu_entry_frame_submenu_timeout(gpointer data) +static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data) +{ + g_assert(menu_frame_visible); + g_assert(((ObMenuFrame*)data)->parent != NULL); + menu_frame_hide((ObMenuFrame*)data); + return FALSE; +} + +static gboolean menu_entry_frame_submenu_show_timeout(gpointer data) { g_assert(menu_frame_visible); menu_entry_frame_show_submenu((ObMenuEntryFrame*)data); @@ -1134,25 +1154,57 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, if (config_submenu_show_delay) { /* remove any submenu open requests */ ob_main_loop_timeout_remove(ob_main_loop, - menu_entry_frame_submenu_timeout); + menu_entry_frame_submenu_show_timeout); + } + + if (!entry && self->open_submenu) { + entry = self->open_submenu; + oldchild = NULL; + + /* remove any submenu close delays */ + ob_main_loop_timeout_remove(ob_main_loop, + menu_entry_frame_submenu_hide_timeout); } self->selected = entry; if (old) menu_entry_frame_render(old); - if (oldchild) - menu_frame_hide(oldchild); + + if (oldchild) { + /* there is an open submenu */ + + if (config_submenu_show_delay && !immediate) { + if (old == self->open_submenu) { + /* close the open submenu after a delay if we don't have + it selected */ + ob_main_loop_timeout_remove + (ob_main_loop, + menu_entry_frame_submenu_hide_timeout); + ob_main_loop_timeout_add(ob_main_loop, + config_submenu_show_delay * 1000, + menu_entry_frame_submenu_hide_timeout, + self->child, g_direct_equal, + NULL); + } + } + else + menu_frame_hide(oldchild); + } if (self->selected) { menu_entry_frame_render(self->selected); - if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) { + /* if we've selected a submenu and it wasn't always open, then + show it */ + if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU && + self->selected != self->open_submenu) + { if (config_submenu_show_delay && !immediate) { /* initiate a new submenu open request */ ob_main_loop_timeout_add(ob_main_loop, config_submenu_show_delay * 1000, - menu_entry_frame_submenu_timeout, + menu_entry_frame_submenu_show_timeout, self->selected, g_direct_equal, NULL); } else { -- cgit v1.2.3 From 811e3ddbc30d90283b532360ee8c39251fa54de8 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Dec 2009 10:43:22 -0500 Subject: Ignore enter events caused by closing openbox menus --- openbox/menuframe.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'openbox/menuframe.c') diff --git a/openbox/menuframe.c b/openbox/menuframe.c index ad692d2e..3d2bf829 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -23,6 +23,7 @@ #include "screen.h" #include "prop.h" #include "actions.h" +#include "event.h" #include "grab.h" #include "openbox.h" #include "mainloop.h" @@ -949,7 +950,6 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y, gboolean mouse) { gint px, py; - guint i; if (menu_frame_is_visible(self)) return TRUE; @@ -1021,6 +1021,7 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent, static void menu_frame_hide(ObMenuFrame *self) { GList *it = g_list_find(menu_frame_visible, self); + gulong ignore_start; if (!it) return; @@ -1046,7 +1047,9 @@ static void menu_frame_hide(ObMenuFrame *self) ungrab_keyboard(); } + ignore_start = event_start_ignore_all_enters(); XUnmapWindow(ob_display, self->window); + event_end_ignore_all_enters(ignore_start); menu_frame_free(self); } -- cgit v1.2.3 From 8ada991d829671ab5e6dd4c5526b6a0238ba6a16 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 16 Dec 2009 15:32:51 -0500 Subject: Fix the delayed hiding of submenus, so that they don't end up hidden while the entry is selected --- openbox/menuframe.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'openbox/menuframe.c') diff --git a/openbox/menuframe.c b/openbox/menuframe.c index 3d2bf829..8177f513 100644 --- a/openbox/menuframe.c +++ b/openbox/menuframe.c @@ -1161,6 +1161,8 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, } if (!entry && self->open_submenu) { + /* we moved out of the menu, so move the selection back to the open + submenu */ entry = self->open_submenu; oldchild = NULL; @@ -1178,12 +1180,16 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, /* there is an open submenu */ if (config_submenu_show_delay && !immediate) { - if (old == self->open_submenu) { - /* close the open submenu after a delay if we don't have - it selected */ + if (entry == self->open_submenu) { + /* we moved onto the entry that has an open submenu, so stop + trying to close the submenu */ ob_main_loop_timeout_remove (ob_main_loop, menu_entry_frame_submenu_hide_timeout); + } + else if (old == self->open_submenu) { + /* we just moved off the entry with an open submenu, so + close the open submenu after a delay */ ob_main_loop_timeout_add(ob_main_loop, config_submenu_show_delay * 1000, menu_entry_frame_submenu_hide_timeout, @@ -1198,7 +1204,7 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, if (self->selected) { menu_entry_frame_render(self->selected); - /* if we've selected a submenu and it wasn't always open, then + /* if we've selected a submenu and it wasn't already open, then show it */ if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU && self->selected != self->open_submenu) -- cgit v1.2.3