improve submenu hide delay

This commit is contained in:
Alexey Korop 2010-01-04 13:21:12 -05:00 committed by Dana Jansens
parent e045227726
commit 8968b38338
5 changed files with 100 additions and 6 deletions

View file

@ -635,6 +635,9 @@
<submenuShowDelay>100</submenuShowDelay>
<!-- this one is easy, time to delay before showing a submenu after hovering
over the parent entry -->
<submenuHideDelay>400</submenuHideDelay>
<!-- time to delay before hiding a submenu when selecting another
entry in parent menu -->
<applicationIcons>yes</applicationIcons>
<!-- controls if icons appear in the client-list-(combined-)menu -->
<manageDesktops>yes</manageDesktops>

View file

@ -91,6 +91,7 @@ gint config_mouse_screenedgetime;
guint config_menu_hide_delay;
gboolean config_menu_middle;
guint config_submenu_show_delay;
guint config_submenu_hide_delay;
gboolean config_menu_client_list_icons;
gboolean config_menu_manage_desktops;
@ -812,6 +813,8 @@ static void parse_menu(ObParseInst *i, xmlDocPtr doc, xmlNodePtr node,
config_menu_middle = parse_bool(doc, n);
if ((n = parse_find_node("submenuShowDelay", node)))
config_submenu_show_delay = parse_int(doc, n);
if ((n = parse_find_node("submenuHideDelay", node)))
config_submenu_hide_delay = parse_int(doc, n);
if ((n = parse_find_node("applicationIcons", node)))
config_menu_client_list_icons = parse_bool(doc, n);
if ((n = parse_find_node("manageDesktops", node)))
@ -1016,6 +1019,7 @@ void config_startup(ObParseInst *i)
config_menu_hide_delay = 250;
config_menu_middle = FALSE;
config_submenu_show_delay = 0;
config_submenu_hide_delay = 750;
config_menu_client_list_icons = TRUE;
config_menu_manage_desktops = TRUE;
config_menu_files = NULL;

View file

@ -185,6 +185,8 @@ extern guint config_menu_hide_delay;
extern gboolean config_menu_middle;
/*! Delay before opening a submenu in milliseconds */
extern guint config_submenu_show_delay;
/*! Delay before closing a submenu in milliseconds */
extern guint config_submenu_hide_delay;
/*! Show icons in client_list_menu */
extern gboolean config_menu_client_list_icons;
/*! Show manage desktops in client_list_menu */

View file

@ -52,6 +52,8 @@ static void menu_frame_update(ObMenuFrame *self);
static gboolean menu_entry_frame_submenu_timeout(gpointer data);
static void menu_frame_hide(ObMenuFrame *self);
static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data);
static Window createWindow(Window parent, gulong mask,
XSetWindowAttributes *attrib)
{
@ -972,6 +974,14 @@ gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
return TRUE;
}
static void remove_submenu_hide_timeout(ObMenuFrame *self /* parent of submenu to hide */)
{
ob_main_loop_timeout_remove(ob_main_loop,
menu_entry_frame_submenu_hide_timeout);
if (self)
self->submenu_to_hide = NULL;
}
gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
ObMenuEntryFrame *parent_entry)
{
@ -985,10 +995,14 @@ gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
self->parent = parent;
self->parent_entry = parent_entry;
remove_submenu_hide_timeout(parent);
/* set up parent's child to be us */
if (parent->child)
menu_frame_hide(parent->child);
parent->child = self;
if ((parent->child) != self) {
if (parent->child)
menu_frame_hide(parent->child);
parent->child = self;
}
if (!menu_frame_show(self))
return FALSE;
@ -1020,6 +1034,8 @@ static void menu_frame_hide(ObMenuFrame *self)
GList *it = g_list_find(menu_frame_visible, self);
gulong ignore_start;
remove_submenu_hide_timeout(self->parent);
if (!it)
return;
@ -1123,11 +1139,50 @@ static gboolean menu_entry_frame_submenu_timeout(gpointer data)
return FALSE;
}
static gboolean menu_entry_frame_submenu_hide_timeout(gpointer data)
{
menu_frame_hide((ObMenuFrame*)data);
return FALSE;
}
void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
gboolean immediate)
{
ObMenuEntryFrame *old = self->selected;
ObMenuFrame *oldchild = self->child;
ObMenuEntryFrame *temp;
gboolean reselection;
if (!oldchild) {
/* self is the last visible (sub)menu */
if (self->parent && self->parent_entry != self->parent->selected) {
/* Legend:
(config_submenu_hide_delay != 0)
In the parent menu corresponding entry "A" selected,
this submenu ('self') shown, cursor moved in the parent
menu to another entry "B", then cursor moved for the
first time into this submenu.
Results:
parent menu selection is "B" instead of "A",
*/
temp = self->parent->selected;
self->parent->selected = self->parent_entry;
if (temp)
menu_entry_frame_render(temp);
menu_entry_frame_render(self->parent_entry);
}
remove_submenu_hide_timeout(self->parent);
}
else if (oldchild->child) {
/* self is the (at least) grandparent of the last visible submenu */
menu_frame_hide(oldchild->child);
if (temp = oldchild->selected) {
oldchild->selected = NULL;
menu_entry_frame_render(temp);
}
}
if (entry && entry->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR)
entry = old;
@ -1144,13 +1199,40 @@ void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry,
if (old)
menu_entry_frame_render(old);
if (oldchild)
menu_frame_hide(oldchild);
reselection = FALSE;
if (oldchild) {
if (self->submenu_to_hide == entry) {
/* Legend:
(config_submenu_hide_delay != 0)
Some entry "A" selected; corresponding submenu shown;
cursor moved to another entry "B" and moved back
to the entry "A", when submenu hide request added,
but submenu not hided.
*/
reselection = TRUE;
remove_submenu_hide_timeout(self);
}
else if (!immediate && config_submenu_hide_delay) {
if (self->submenu_to_hide == NULL) {
ob_main_loop_timeout_add(ob_main_loop,
config_submenu_hide_delay * 1000,
menu_entry_frame_submenu_hide_timeout,
oldchild, g_direct_equal,
NULL);
self->submenu_to_hide = old;
}
}
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 (!reselection &&
(self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU))
{
if (config_submenu_show_delay && !immediate) {
/* initiate a new submenu open request */
ob_main_loop_timeout_add(ob_main_loop,

View file

@ -80,6 +80,9 @@ struct _ObMenuFrame
menu until it has seen a KeyPress. this is to
avoid having the keybinding used to show the menu
end up running something inside the menu */
ObMenuEntryFrame * submenu_to_hide; /* if exist (single!) submenu hide request
then this variable hold a copy of 'selected' field of the parent menu,
otherwice NULL */
};
struct _ObMenuEntryFrame