diff --git a/src/WindowMaker.h b/src/WindowMaker.h index 358a7b21..82939858 100644 --- a/src/WindowMaker.h +++ b/src/WindowMaker.h @@ -370,6 +370,7 @@ typedef struct WPreferences { signed char menu_style; /* menu decoration style */ signed char workspace_name_display_position; unsigned int modifier_mask; /* mask to use as kbd modifier */ + char *modifier_labels[7]; /* Names of the modifiers */ char ws_advance; /* Create new workspace and advance */ diff --git a/src/defaults.c b/src/defaults.c index 89b315ea..9f953b1f 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -147,6 +147,8 @@ static int setMenuStyle(); static int setSwPOptions(); static int updateUsableArea(); +static int setModifierKeyLabels(); + extern Cursor wCursor[WCUR_LAST]; static int getCursor(); static int setCursor(); @@ -511,6 +513,8 @@ WDefaultEntry optionList[] = { NULL, getColor, setIconTitleBack, NULL, NULL}, {"SwitchPanelImages", "(swtile.png, swback.png, 30, 40)", &wPreferences, NULL, getPropList, setSwPOptions, NULL, NULL}, + {"ModifierKeyLabels", "(\"Shift+\", \"Ctrl+\", \"Mod1+\", \"Mod2+\", \"Mod3+\", \"Mod4+\", \"Mod5+\")", &wPreferences, + NULL, getPropList, setModifierKeyLabels, NULL, NULL}, /* keybindings */ @@ -2998,6 +3002,36 @@ static int setSwPOptions(WScreen * scr, WDefaultEntry * entry, WMPropList * arra return 0; } +static int setModifierKeyLabels(WScreen * scr, WDefaultEntry * entry, WMPropList * array, void *foo) +{ + int i; + WPreferences *prefs = (WPreferences *) foo; + + if (!WMIsPLArray(array) || WMGetPropListItemCount(array) != 7) { + wwarning(_("Value for option \"%s\" must be an array of 7 strings"), entry->key); + WMReleasePropList(array); + return 0; + } + + DestroyWindowMenu(scr); + + for (i = 0; i < 7; i++) { + if (prefs->modifier_labels[i]) + wfree(prefs->modifier_labels[i]); + + if (WMIsPLString(WMGetFromPLArray(array, i))) { + prefs->modifier_labels[i] = wstrdup(WMGetFromPLString(WMGetFromPLArray(array, i))); + } else { + wwarning(_("Invalid argument for option \"%s\" item %d"), entry->key, i); + prefs->modifier_labels[i] = NULL; + } + } + + WMReleasePropList(array); + + return 0; +} + /* * Very ugly kluge. * Need access to the double click variables, so that all widgets in diff --git a/src/funcs.h b/src/funcs.h index 8b2b0502..5d813ea6 100644 --- a/src/funcs.h +++ b/src/funcs.h @@ -65,6 +65,8 @@ void OpenWorkspaceMenu(WScreen *scr, int x, int y); void CloseWindowMenu(WScreen *scr); +void DestroyWindowMenu(WScreen *scr); + WMagicNumber wAddDeathHandler(pid_t pid, WDeathHandler *callback, void *cdata); void wColormapInstallForWindow(WScreen *scr, WWindow *wwin); diff --git a/src/winmenu.c b/src/winmenu.c index 3598d5a3..8e657e60 100644 --- a/src/winmenu.c +++ b/src/winmenu.c @@ -238,6 +238,25 @@ static void updateWorkspaceMenu(WMenu * menu) wMenuRealize(menu); } +static char *getShortcutString(WShortKey key) +{ + char *tmp = NULL; + char *k = XKeysymToString(XKeycodeToKeysym(dpy, key.keycode, 0)); + if (!k) return NULL; + + char **m = wPreferences.modifier_labels; + if (key.modifier & ControlMask) tmp = wstrappend(tmp, m[1] ? m[1] : "Ctrl+"); + if (key.modifier & ShiftMask) tmp = wstrappend(tmp, m[0] ? m[0] : "Shift+"); + if (key.modifier & Mod1Mask) tmp = wstrappend(tmp, m[2] ? m[2] : "Mod1+"); + if (key.modifier & Mod2Mask) tmp = wstrappend(tmp, m[3] ? m[3] : "Mod2+"); + if (key.modifier & Mod3Mask) tmp = wstrappend(tmp, m[4] ? m[4] : "Mod3+"); + if (key.modifier & Mod4Mask) tmp = wstrappend(tmp, m[5] ? m[5] : "Mod4+"); + if (key.modifier & Mod5Mask) tmp = wstrappend(tmp, m[6] ? m[6] : "Mod5+"); + tmp = wstrappend(tmp, k); + + return tmp; +} + static void updateMakeShortcutMenu(WMenu * menu, WWindow * wwin) { WMenu *smenu = menu->cascades[menu->entries[MC_SHORTCUT]->cascade]; @@ -279,11 +298,11 @@ static void updateMakeShortcutMenu(WMenu * menu, WWindow * wwin) kcode = wKeyBindings[WKBD_WINDOW1 + shortcutNo].keycode; if (kcode) { - if ((tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0))) + if ((tmp = getShortcutString(wKeyBindings[WKBD_WINDOW1 + shortcutNo])) && (!entry->rtext || strcmp(tmp, entry->rtext) != 0)) { if (entry->rtext) wfree(entry->rtext); - entry->rtext = wstrdup(tmp); + entry->rtext = tmp; smenu->flags.realized = 0; } wMenuSetEnabled(smenu, i, True); @@ -394,9 +413,7 @@ static WMenu *makeOptionsMenu(WScreen * scr) static WMenu *createWindowMenu(WScreen * scr) { WMenu *menu; - KeyCode kcode; WMenuEntry *entry; - char *tmp; menu = wMenuCreate(scr, NULL, False); /* @@ -405,52 +422,22 @@ static WMenu *createWindowMenu(WScreen * scr) * this file. */ entry = wMenuAddCallback(menu, _("Maximize"), execMenuCommand, NULL); - if (wKeyBindings[WKBD_MAXIMIZE].keycode != 0) { - kcode = wKeyBindings[WKBD_MAXIMIZE].keycode; - - if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)))) - entry->rtext = wstrdup(tmp); - } + entry->rtext = getShortcutString(wKeyBindings[WKBD_MAXIMIZE]); entry = wMenuAddCallback(menu, _("Miniaturize"), execMenuCommand, NULL); - if (wKeyBindings[WKBD_MINIATURIZE].keycode != 0) { - kcode = wKeyBindings[WKBD_MINIATURIZE].keycode; - - if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)))) - entry->rtext = wstrdup(tmp); - } + entry->rtext = getShortcutString(wKeyBindings[WKBD_MINIATURIZE]); entry = wMenuAddCallback(menu, _("Shade"), execMenuCommand, NULL); - if (wKeyBindings[WKBD_SHADE].keycode != 0) { - kcode = wKeyBindings[WKBD_SHADE].keycode; - - if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)))) - entry->rtext = wstrdup(tmp); - } + entry->rtext = getShortcutString(wKeyBindings[WKBD_SHADE]); entry = wMenuAddCallback(menu, _("Hide"), execMenuCommand, NULL); - if (wKeyBindings[WKBD_HIDE].keycode != 0) { - kcode = wKeyBindings[WKBD_HIDE].keycode; - - if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)))) - entry->rtext = wstrdup(tmp); - } + entry->rtext = getShortcutString(wKeyBindings[WKBD_HIDE]); entry = wMenuAddCallback(menu, _("Resize/Move"), execMenuCommand, NULL); - if (wKeyBindings[WKBD_MOVERESIZE].keycode != 0) { - kcode = wKeyBindings[WKBD_MOVERESIZE].keycode; - - if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)))) - entry->rtext = wstrdup(tmp); - } + entry->rtext = getShortcutString(wKeyBindings[WKBD_MOVERESIZE]); entry = wMenuAddCallback(menu, _("Select"), execMenuCommand, NULL); - if (wKeyBindings[WKBD_SELECT].keycode != 0) { - kcode = wKeyBindings[WKBD_SELECT].keycode; - - if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)))) - entry->rtext = wstrdup(tmp); - } + entry->rtext = getShortcutString(wKeyBindings[WKBD_SELECT]); entry = wMenuAddCallback(menu, _("Move To"), NULL, NULL); scr->workspace_submenu = makeWorkspaceMenu(scr); @@ -468,11 +455,7 @@ static WMenu *createWindowMenu(WScreen * scr) */ entry = wMenuAddCallback(menu, _("Close"), execMenuCommand, NULL); - if (wKeyBindings[WKBD_CLOSE].keycode != 0) { - kcode = wKeyBindings[WKBD_CLOSE].keycode; - if (kcode && (tmp = XKeysymToString(XKeycodeToKeysym(dpy, kcode, 0)))) - entry->rtext = wstrdup(tmp); - } + entry->rtext = getShortcutString(wKeyBindings[WKBD_CLOSE]); entry = wMenuAddCallback(menu, _("Kill"), execMenuCommand, NULL); @@ -711,3 +694,14 @@ void OpenMiniwindowMenu(WWindow * wwin, int x, int y) wMenuMapAt(menu, x, y, False); } + +void DestroyWindowMenu(WScreen *scr) +{ + if (scr->window_menu) { + scr->window_menu->entries[MC_MINIATURIZE]->text = NULL; + scr->window_menu->entries[MC_MAXIMIZE]->text = NULL; + scr->window_menu->entries[MC_SHADE]->text = NULL; + wMenuDestroy(scr->window_menu, True); + scr->window_menu = NULL; + } +}