void menu_clear_entries(ObMenu *self) { #ifdef DEBUG /* assert that the menu isn't visible */ { GList *it; ObMenuFrame *f; for (it = menu_frame_visible; it; it = g_list_next(it)) { f = it->data; g_assert(f->menu != self); } } #endif while (self->entries) { menu_entry_unref(self->entries->data); self->entries = g_list_delete_link(self->entries, self->entries); } self->more_menu->entries = self->entries; /* keep it in sync */ }
static void menu_entry_frame_free(ObMenuEntryFrame *self) { if (self) { window_remove(self->window); XDestroyWindow(obt_display, self->text); XDestroyWindow(obt_display, self->window); g_hash_table_remove(menu_frame_map, &self->text); g_hash_table_remove(menu_frame_map, &self->window); if ((self->entry->type == OB_MENU_ENTRY_TYPE_NORMAL) || (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)) { XDestroyWindow(obt_display, self->icon); g_hash_table_remove(menu_frame_map, &self->icon); } if (self->entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) { XDestroyWindow(obt_display, self->bullet); g_hash_table_remove(menu_frame_map, &self->bullet); } menu_entry_unref(self->entry); g_slice_free(ObMenuEntryFrame, self); } }
static void menu_frame_update(ObMenuFrame *self) { GList *mit, *fit; const Rect *a; gint h; menu_pipe_execute(self->menu); menu_find_submenus(self->menu); self->selected = NULL; /* start at show_from */ mit = g_list_nth(self->menu->entries, self->show_from); /* go through the menu's and frame's entries and connect the frame entries to the menu entries */ for (fit = self->entries; mit && fit; mit = g_list_next(mit), fit = g_list_next(fit)) { ObMenuEntryFrame *f = fit->data; f->entry = mit->data; } /* if there are more menu entries than in the frame, add them */ while (mit) { ObMenuEntryFrame *e = menu_entry_frame_new(mit->data, self); self->entries = g_list_append(self->entries, e); mit = g_list_next(mit); } /* if there are more frame entries than menu entries then get rid of them */ while (fit) { GList *n = g_list_next(fit); menu_entry_frame_free(fit->data); self->entries = g_list_delete_link(self->entries, fit); fit = n; } /* * make the menu fit on the screen */ /* calculate the height of the menu */ h = 0; for (fit = self->entries; fit; fit = g_list_next(fit)) h += menu_entry_frame_get_height(fit->data, fit == self->entries, g_list_next(fit) == NULL); /* add the border at the top and bottom */ h += ob_rr_theme->mbwidth * 2; a = screen_physical_area_monitor(self->monitor); if (h > a->height) { GList *flast, *tmp; gboolean last_entry = TRUE; /* take the height of our More... entry into account */ h += menu_entry_frame_get_height(NULL, FALSE, TRUE); /* start at the end of the entries */ flast = g_list_last(self->entries); /* pull out all the entries from the frame that don't fit on the screen, leaving at least 1 though */ while (h > a->height && g_list_previous(flast) != NULL) { /* update the height, without this entry */ h -= menu_entry_frame_get_height(flast->data, FALSE, last_entry); /* destroy the entry we're not displaying */ tmp = flast; flast = g_list_previous(flast); menu_entry_frame_free(tmp->data); self->entries = g_list_delete_link(self->entries, tmp); /* only the first one that we see is the last entry in the menu */ last_entry = FALSE; }; { ObMenuEntry *more_entry; ObMenuEntryFrame *more_frame; /* make the More... menu entry frame which will display in this frame. if self->menu->more_menu is NULL that means that this is already More... menu, so just use ourself. */ more_entry = menu_get_more((self->menu->more_menu ? self->menu->more_menu : self->menu), /* continue where we left off */ self->show_from + g_list_length(self->entries)); more_frame = menu_entry_frame_new(more_entry, self); /* make it get deleted when the menu frame goes away */ menu_entry_unref(more_entry); /* add our More... entry to the frame */ self->entries = g_list_append(self->entries, more_frame); } } menu_frame_render(self); }
void menu_entry_remove(ObMenuEntry *self) { self->menu->entries = g_list_remove(self->menu->entries, self); menu_entry_unref(self); }