void menu_button(WThing *thing, XButtonEvent *ev, WFunction *func, WFuncArg arg) { WMenu *menu; int x, y, entry; if(!WTHING_IS(thing, WTHING_MENU)) return; menu=(WMenu*)thing; x=ev->x_root-menu->x; y=ev->y_root-menu->y; entry=entry_at(menu, x, y); if(ev->type==ButtonPress){ /* press */ if(entry==menu->selected){ menu_set_selected(menu, NO_ENTRY); }else{ menu_set_selected(menu, entry); show_selected_submenu(menu); } return; } end_scroll(); /* release */ if(entry>=0){ if(menu->selected==entry) menu_execute_selected(menu); }else if(entry!=ENTRY_TITLE && !(menu->flags&WMENU_KEEP)){ finish_menu(menu, FALSE); } destroy_contextual_menus(); }
bool menu_select_at(WMenu *menu, int rx, int ry) { int x, y; int entry; x=rx-menu->x; y=ry-menu->y; entry=entry_at(menu, x, y); if(entry==NO_ENTRY){ if(MENU_SUBMENU(menu)==NULL) menu_set_selected(menu, NO_ENTRY); return FALSE; } if(entry!=menu->selected){ menu_set_selected(menu, entry); show_selected_submenu(menu); } return TRUE; }
static void keep(WMenu *menu) { WWinObj *tmp; if(menu->flags&(WMENU_KEEP|WMENU_CONTEXTUAL)) return; menu->flags|=WMENU_KEEP; tmp=menu->stack_above; if(tmp!=NULL){ restack_winobj((WWinObj*)menu, LVL_MENU, TRUE); menu_set_selected((WMenu*)tmp, NO_ENTRY); } draw_menu(menu, FALSE); }
/* Execute selected entry; either show submenu or * call given function. */ static bool menu_execute_selected(WMenu *menu) { WMenuEnt *entry; WMenuData *data; WThing *context; if(menu->selected<0) return TRUE; /* Submenu already visible? -> return */ if(MENU_SUBMENU(menu)!=NULL) return TRUE; data=menu->data; context=menu->context; entry=&(data->entries[menu->selected]); if(entry->flags&WMENUENT_SUBMENU){ do_show_selected_submenu(menu, entry); return TRUE; } data->nref++; if(menu->flags&WMENU_KEEP){ menu_set_selected(menu, NO_ENTRY); }else{ finish_menu(menu, FALSE); } finish_contextual_menus(); if(data->exec_func!=NULL) data->exec_func(entry, context); if(--data->nref==0 && data->deinit_func!=NULL) data->deinit_func(data); return FALSE; }
/* Destroy a menu and all its submenus. */ static void do_destroy_menu_tree(WMenu *menu, bool setsel, bool contextual_only) { WWinObj *tmpobj=NULL, *p, *next; WWinObj *parent=menu->stack_above; p=init_traverse_winobjs_b((WWinObj*)menu, &tmpobj); for(; p!=NULL; p=next){ next=traverse_winobjs_b(p, (WWinObj*)menu, &tmpobj); if(!WTHING_IS(p, WTHING_MENU)) continue; if(contextual_only && !(p->flags&WMENU_CONTEXTUAL)) continue; /* destroy the menu */ parent=p->stack_above; do_destroy_menu((WMenu*)p); if(setsel && parent!=NULL && WTHING_IS(parent, WTHING_MENU)) menu_set_selected((WMenu*)parent, NO_ENTRY); } }
void menu_command(WMenu *menu, int cmd) { WMenu *other; switch(cmd){ case MENU_CMD_PREV: if(menu->selected>0) menu_set_selected(menu, menu->selected-1); else menu_set_selected(menu, menu->data->nentries-1); vis_entry(menu, menu->selected); break; case MENU_CMD_NEXT: if(menu->selected<menu->data->nentries-1) menu_set_selected(menu, menu->selected+1); else menu_set_selected(menu, 0); vis_entry(menu, menu->selected); break; case MENU_CMD_ENTERSUB: case MENU_CMD_EXECUTE: if(menu->selected<0) break; if(MENU_SUBMENU(menu)==NULL){ if(menu->data->entries[menu->selected].flags&WMENUENT_SUBMENU) show_selected_submenu(menu); } other=MENU_SUBMENU(menu); if(other!=NULL){ set_active_menu(other); if(other->selected==NO_ENTRY) other->selected=0; vis_entry(other, other->selected); break; } if(cmd!=MENU_CMD_EXECUTE) break; menu_execute_selected(menu); break; case MENU_CMD_LEAVESUB: other=MENU_PARENT(menu); if(other!=NULL){ do_destroy_menu_tree(menu, FALSE, FALSE); /* set_active_menu is not used because unlink_winobj_d gives the * parent a focus if the destroyed menu is current. This should * not bee true in INPUT_CTXMENU mode. */ if(wglobal.input_mode==INPUT_CTXMENU) wglobal.grab_holder=(WThing*)other; vis_entry(other, other->selected); } break; case MENU_CMD_CLOSE: finish_menu(menu, TRUE); finish_contextual_menus(); break; case MENU_CMD_RAISEKEEP: raise_winobj((WWinObj*)menu); case MENU_CMD_KEEP: keep(menu); break; } }
void load_menu(){ window_stack_pop(true); window_stack_push(menu_window, true); current_screen=SCREEN_MENU_KEY; menu_set_selected(last_screen); }