void menu_show(gchar *name, gint x, gint y, gboolean mouse, ObClient *client) { ObMenu *self; ObMenuFrame *frame; if (!(self = menu_from_name(name)) || grab_on_keyboard() || grab_on_pointer()) return; /* if the requested menu is already the top visible menu, then don't bother */ if (menu_frame_visible) { frame = menu_frame_visible->data; if (frame->menu == self) return; } menu_frame_hide_all(); /* clear the pipe menus when showing a new menu */ menu_clear_pipe_caches(); frame = menu_frame_new(self, 0, client); if (!menu_frame_show_topmenu(frame, x, y, mouse)) menu_frame_free(frame); else { if (!mouse) { /* select the first entry if it's not a submenu and we opened * the menu with the keyboard, and skip all headers */ GList *it = frame->entries; while (it) { ObMenuEntryFrame *e = it->data; if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) { menu_frame_select(frame, e, FALSE); break; } else if (e->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR) it = g_list_next(it); else break; } } /* reset the hide timer */ if (!mouse) menu_can_hide = TRUE; else { menu_can_hide = FALSE; obt_main_loop_timeout_add(ob_main_loop, config_menu_hide_delay * 1000, menu_hide_delay_func, NULL, g_direct_equal, NULL); } } }
void menu_frame_select_last(ObMenuFrame *self) { GList *it = NULL; if (self->entries) { for (it = g_list_last(self->entries); it; it = g_list_previous(it)) { ObMenuEntryFrame *e = it->data; if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) break; if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) break; } } menu_frame_select(self, it ? it->data : NULL, FALSE); }
void menu_frame_select_next(ObMenuFrame *self) { GList *it = NULL, *start; if (self->entries) { start = it = g_list_find(self->entries, self->selected); while (TRUE) { ObMenuEntryFrame *e; it = it ? g_list_next(it) : self->entries; if (it == start) break; if (it) { e = it->data; if (e->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) break; if (e->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) break; } } } menu_frame_select(self, it ? it->data : NULL, FALSE); }
void menu_frame_select(ObMenuFrame *self, ObMenuEntryFrame *entry, gboolean immediate) { ObMenuEntryFrame *old = self->selected; ObMenuFrame *oldchild = self->child; ObMenuEntryFrame *oldchild_entry = self->child_entry; /* if the user selected a separator, ignore it and reselect what we had selected before */ if (entry && entry->entry->type == OB_MENU_ENTRY_TYPE_SEPARATOR) entry = old; if (old == entry && (!old || old->entry->type != OB_MENU_ENTRY_TYPE_SUBMENU)) return; /* if the user left this menu but we have a submenu open, move the selection back to that submenu */ if (!entry && oldchild_entry) entry = oldchild_entry; if (config_submenu_show_delay && submenu_show_timer) /* remove any submenu open requests */ g_source_remove(submenu_show_timer); self->selected = entry; if (old) menu_entry_frame_render(old); if (oldchild_entry) { /* There is an open submenu */ if (oldchild_entry == self->selected) { /* The open submenu has been reselected, so stop hiding the submenu */ remove_submenu_hide_timeout(oldchild); } else if (oldchild_entry == old) { /* The open submenu was selected and is no longer, so hide the submenu */ if (immediate || config_submenu_hide_delay == 0) menu_frame_hide(oldchild); else if (config_submenu_hide_delay > 0) { if (submenu_hide_timer) g_source_remove(submenu_hide_timer); submenu_hide_timer = g_timeout_add_full(G_PRIORITY_DEFAULT, config_submenu_hide_delay, submenu_hide_timeout, oldchild, submenu_hide_dest); } } } if (self->selected) { menu_entry_frame_render(self->selected); if (self->selected->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) { /* only show if the submenu isn't already showing */ if (oldchild_entry != self->selected) { if (immediate || config_submenu_show_delay == 0) menu_entry_frame_show_submenu(self->selected); else if (config_submenu_show_delay > 0) { if (submenu_show_timer) g_source_remove(submenu_show_timer); submenu_show_timer = g_timeout_add_full(G_PRIORITY_DEFAULT, config_submenu_show_delay, submenu_show_timeout, self->selected, submenu_show_dest); } } /* hide the grandchildren of this menu. and move the cursor to the current menu */ else if (immediate && self->child && self->child->child) { menu_frame_hide(self->child->child); menu_frame_select(self->child, NULL, TRUE); } } } }