/* usermenu.c- user defined menu * * Window Maker window manager * * Copyright (c) hmmm... Should I put everybody's name here? * Where's my lawyer?? -- ]d :D * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. * * * * * * * * * * * User defined menu is good, but beer's always better * if someone wanna start hacking something, He heard... * TODO * - enhance commands. (eg, exit, hide, list all app's member * window and etc) * - cache menu... dunno.. if people really use this feature :P * - Violins, senseless violins! * that's all, right now :P * - external! WINGs menu editor. * TODONOT * - allow applications to share their menu. ] think it * looks wierd since there still are more than 1 appicon. * * Syntax... * ( * "Program Name", * ("Command 1", SHORTCUT, 1), * ("Command 2", SHORTCUT, 2, ("Allowed_instant_1", "Allowed_instant_2")), * ("Command 3", SHORTCUT, (3,4,5), ("Allowed_instant_1")), * ( * "Submenu", * ("Kill Command", KILL), * ("Hide Command", HIDE), * ("Hide Others Command", HIDE_OTHERS), * ("Members", MEMBERS), * ("Exit Command", EXIT) * ) * ) * * Tips: * - If you don't want short cut keys to be listed * in the right side of entries, you can just put them * in array instead of using the string directly. * */ #include "wconfig.h" #ifdef USER_MENU #include #include #include #include #include #include #include #include #include "WindowMaker.h" #include "wcore.h" #include "menu.h" #include "actions.h" #include "funcs.h" #include "keybind.h" #include "framewin.h" /*** var ***/ extern WPreferences wPreferences; typedef struct { WScreen *screen; WShortKey *key; int key_no; } WUserMenuData; static void notifyClient(WMenu *menu, WMenuEntry *entry) { XEvent event; WUserMenuData *data = entry->clientdata; WScreen *scr = data->screen; Window window; int i; window=scr->focused_window->client_win; for(i=0;ikey_no;i++) { event.xkey.type = KeyPress; event.xkey.display = dpy; event.xkey.window = window; event.xkey.root = DefaultRootWindow(dpy); event.xkey.subwindow = (Window)None; event.xkey.x = 0x0; event.xkey.y = 0x0; event.xkey.x_root = 0x0; event.xkey.y_root = 0x0; event.xkey.keycode = data->key[i].keycode; event.xkey.state = data->key[i].modifier; event.xkey.same_screen = True; event.xkey.time = CurrentTime; if (XSendEvent(dpy, window, False, KeyPressMask, &event)) { event.xkey.type = KeyRelease; event.xkey.time = CurrentTime; XSendEvent(dpy, window, True, KeyReleaseMask, &event); } } } static void removeUserMenudata(void *menudata) { WUserMenuData *data = menudata; if(data->key) wfree(data->key); wfree(data); } static WUserMenuData* convertShortcuts(WScreen *scr, WMPropList *shortcut) { WUserMenuData *data; KeySym ksym; char *k; char *buffer; char buf[128], *b; int keycount,i,j,mod; if (WMIsPLString(shortcut)) { keycount = 1; } else if (WMIsPLArray(shortcut)) { keycount = WMGetPropListItemCount(shortcut); } else return NULL; /*for (i=0;ikey = wmalloc(sizeof(WShortKey)*keycount); if (!data->key) { wfree(data); return NULL; } for (i=0,j=0;ikey[j].modifier = 0; if (WMIsPLArray(shortcut)) { strcpy(buf, WMGetFromPLString(WMGetFromPLArray(shortcut, i))); } else { strcpy(buf, WMGetFromPLString(shortcut)); } b = (char*)buf; while ((k = strchr(b, '+'))!=NULL) { *k = 0; mod = wXModifierFromKey(b); if (mod<0) { break; } data->key[j].modifier |= mod; b = k+1; } ksym = XStringToKeysym(b); if (ksym==NoSymbol) { continue; } data->key[j].keycode = XKeysymToKeycode(dpy, ksym); if (data->key[j].keycode) { j++; } } keyover: /* get key */ if (!j) { puts("fatal j"); wfree(data->key); wfree(data); return NULL; } data->key_no = j; data->screen = scr; return data; } static WMenu* configureUserMenu(WScreen *scr, WMPropList *plum) { char *mtitle; WMenu *menu=NULL; WMPropList *elem, *title, *command, *params; int count,i; WUserMenuData *data; if (!plum) return NULL; if (!WMIsPLArray(plum)) { return NULL; } count = WMGetPropListItemCount(plum); if (!count) return NULL; elem = WMGetFromPLArray(plum, 0); if (!WMIsPLString(elem)) { return NULL; } mtitle = WMGetFromPLString(elem); menu=wMenuCreateForApp(scr, mtitle, True); for(i=1; iframe->title, NULL, NULL); wMenuEntrySetCascade(menu, mentry, submenu); } else { int idx = 0; WMPropList *instances=0; title = WMGetFromPLArray(elem,idx++); command = WMGetFromPLArray(elem,idx++); if (WMGetPropListItemCount(elem) >= 3) params = WMGetFromPLArray(elem,idx++); if (!title || !command) return menu; if (!strcmp("SHORTCUT",WMGetFromPLString(command))) { WMenuEntry *entry; data = convertShortcuts(scr, params); if (data){ entry = wMenuAddCallback(menu, WMGetFromPLString(title), notifyClient, data); if (entry) { if (WMIsPLString(params)) { entry->rtext = GetShortcutString(WMGetFromPLString(params)); } entry->free_cdata = removeUserMenudata; if (WMGetPropListItemCount(elem) >= 4) { instances = WMGetFromPLArray(elem,idx++); if(WMIsPLArray(instances)) if (instances && WMGetPropListItemCount(instances) && WMIsPLArray(instances)){ entry->instances = WMRetainPropList(instances); } } } } } } } return menu; } void wUserMenuRefreshInstances(WMenu *menu, WWindow *wwin) { WMenuEntry* entry; int i,j,count,paintflag; paintflag=0; if(!menu) return; for (i=0; ientry_no; i++) { if (menu->entries[i]->instances){ WMPropList *ins; int oldflag; count = WMGetPropListItemCount(menu->entries[i]->instances); oldflag = menu->entries[i]->flags.enabled; menu->entries[i]->flags.enabled = 0; for (j=0; jentries[i]->instances,j); if (!strcmp(wwin->wm_instance,WMGetFromPLString(ins))) { menu->entries[i]->flags.enabled = 1; break; } } if (oldflag != menu->entries[i]->flags.enabled) paintflag=1; } } for (i=0; i < menu->cascade_no; i++) { if (!menu->cascades[i]->flags.brother) wUserMenuRefreshInstances(menu->cascades[i], wwin); else wUserMenuRefreshInstances(menu->cascades[i]->brother, wwin); } if (paintflag) wMenuPaint(menu); } static WMenu* readUserMenuFile(WScreen *scr, char *file_name) { WMenu *menu; char *mtitle; WMPropList *plum, *elem, *title, *command, *params; int count,i; menu=NULL; plum = WMReadPropListFromFile(file_name); /**/ if(plum){ menu = configureUserMenu(scr, plum); WMReleasePropList(plum); } return menu; } WMenu* wUserMenuGet(WScreen *scr, WWindow *wwin) { WMenu *menu = NULL; char buffer[100]; char *path = NULL; char *tmp; if (wwin->wm_instance && wwin->wm_class) { int len = strlen(wwin->wm_instance)+strlen(wwin->wm_class)+7; tmp=wmalloc(len); snprintf(tmp,len,"%s.%s.menu",wwin->wm_instance,wwin->wm_class); path = wfindfile(DEF_USER_MENU_PATHS,tmp); wfree(tmp); if (!path) return NULL; if (wwin) { menu = readUserMenuFile(scr, path); } wfree(path); } return menu; } #endif /* USER_MENU */