+ return !!(g_list_find(menu_frame_visible, self));
+}
+
+static gboolean menu_frame_show(ObMenuFrame *self)
+{
+ GList *it;
+
+ /* determine if the underlying menu is already visible */
+ for (it = menu_frame_visible; it; it = g_list_next(it)) {
+ ObMenuFrame *f = it->data;
+ if (f->menu == self->menu)
+ break;
+ }
+ if (!it) {
+ if (self->menu->update_func)
+ if (!self->menu->update_func(self, self->menu->data))
+ return FALSE;
+ }
+
+ if (menu_frame_visible == NULL) {
+ /* no menus shown yet */
+
+ /* grab the pointer in such a way as to pass through "owner events"
+ so that we can get enter/leave notifies in the menu. */
+ if (!grab_pointer(TRUE, FALSE, OB_CURSOR_POINTER))
+ return FALSE;
+ if (!grab_keyboard()) {
+ ungrab_pointer();
+ return FALSE;
+ }
+ }
+
+ menu_frame_update(self);
+
+ menu_frame_visible = g_list_prepend(menu_frame_visible, self);
+
+ if (self->menu->show_func)
+ self->menu->show_func(self, self->menu->data);
+
+ return TRUE;
+}
+
+gboolean menu_frame_show_topmenu(ObMenuFrame *self, gint x, gint y,
+ gboolean mouse)
+{
+ gint px, py;
+
+ if (menu_frame_is_visible(self))
+ return TRUE;
+ if (!menu_frame_show(self))
+ return FALSE;
+
+ if (self->menu->place_func)
+ self->menu->place_func(self, &x, &y, mouse, self->menu->data);
+ else
+ menu_frame_place_topmenu(self, &x, &y);
+
+ menu_frame_move(self, x, y);
+
+ XMapWindow(obt_display, self->window);
+
+ if (screen_pointer_pos(&px, &py)) {
+ ObMenuEntryFrame *e = menu_entry_frame_under(px, py);
+ if (e && e->frame == self)
+ e->ignore_enters++;
+ }
+
+ return TRUE;
+}
+
+/*! Stop hiding an open submenu.
+ @child The OnMenuFrame of the submenu to be hidden
+*/
+static void remove_submenu_hide_timeout(ObMenuFrame *child)
+{
+ if (submenu_hide_timer) g_source_remove(submenu_hide_timer);
+ submenu_hide_timer = 0;
+}
+
+gboolean menu_frame_show_submenu(ObMenuFrame *self, ObMenuFrame *parent,
+ ObMenuEntryFrame *parent_entry)
+{
+ gint x, y, dx, dy;
+ gint px, py;
+
+ if (menu_frame_is_visible(self))
+ return TRUE;
+
+ self->monitor = parent->monitor;
+ self->parent = parent;
+ self->parent_entry = parent_entry;
+
+ /* set up parent's child to be us */
+ if ((parent->child) != self) {