Hi Hotkeys for dock applications is a really cool feature. After upgrading to new windowmaker I was missing much for this feature.
Original patch did not applied successfully, so I updated patch to apply to HEAD. Please consider including it. Thanks! PS. I want to thank the author of original patch for adding this feature.
>From 56c8852a0f2ee753da79d4c04a785fa5d8e15953 Mon Sep 17 00:00:00 2001 From: Yuri Karaban <mli...@dev97.com> Date: Thu, 29 Mar 2012 20:39:40 +0300 Subject: [PATCH] applied to HEAD WindowMaker-0.91.0-alt-dockhotkeys.patch --- src/appicon.c | 2 + src/appicon.h | 4 ++ src/dock.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dockedapp.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/event.c | 2 +- src/screen.h | 1 + src/window.c | 1 + 7 files changed, 289 insertions(+), 2 deletions(-) diff --git a/src/appicon.c b/src/appicon.c index d05413b..6a2e2e9 100644 --- a/src/appicon.c +++ b/src/appicon.c @@ -169,6 +169,8 @@ void wAppIconDestroy(WAppIcon * aicon) if (aicon->dnd_command) wfree(aicon->dnd_command); #endif + if (aicon->keyboard_shortcut) + wfree(aicon->keyboard_shortcut); if (aicon->wm_instance) wfree(aicon->wm_instance); diff --git a/src/appicon.h b/src/appicon.h index f10f847..4e6b5ef 100644 --- a/src/appicon.h +++ b/src/appicon.h @@ -50,6 +50,10 @@ typedef struct WAppIcon { char *paste_command; /* command to run when something is pasted */ + char *keyboard_shortcut; /* keyboard shortcut to launch app */ + int modifier; + KeyCode keycode; + char *wm_class; char *wm_instance; pid_t pid; /* for apps launched from the dock */ diff --git a/src/dock.c b/src/dock.c index 71bef02..5cc8a5f 100644 --- a/src/dock.c +++ b/src/dock.c @@ -79,6 +79,7 @@ static WMPropList *dPasteCommand = NULL; #ifdef XDND /* XXX was OFFIX */ static WMPropList *dDropCommand = NULL; #endif +static WMPropList *dKeyboardShortcut = NULL; static WMPropList *dAutoLaunch, *dLock; static WMPropList *dName, *dForced, *dBuggyApplication, *dYes, *dNo; static WMPropList *dHost, *dDock, *dClip; @@ -131,6 +132,7 @@ static void make_keys(void) #ifdef XDND dDropCommand = WMRetainPropList(WMCreatePLString("DropCommand")); #endif + dKeyboardShortcut = WMRetainPropList(WMCreatePLString("Shortcut")); dLock = WMRetainPropList(WMCreatePLString("Lock")); dAutoLaunch = WMRetainPropList(WMCreatePLString("AutoLaunch")); dName = WMRetainPropList(WMCreatePLString("Name")); @@ -1241,6 +1243,12 @@ static WMPropList *make_icon_state(WAppIcon *btn) WMReleasePropList(command); } + if (btn->keyboard_shortcut) { + command = WMCreatePLString(btn->keyboard_shortcut); + WMPutInPLDictionary(node, dKeyboardShortcut, command); + WMReleasePropList(command); + } + if (btn->client_machine && btn->remote_start) { host = WMCreatePLString(btn->client_machine); WMPutInPLDictionary(node, dHost, host); @@ -1435,6 +1443,12 @@ static WAppIcon *restore_icon_state(WScreen *scr, WMPropList *info, int type, in aicon->dnd_command = wstrdup(WMGetFromPLString(cmd)); #endif + cmd = WMGetFromPLDictionary(info, dKeyboardShortcut); + if (cmd) { + if(addDockShortcut(WMGetFromPLString(cmd), aicon)) + aicon->keyboard_shortcut = wstrdup(WMGetFromPLString(cmd)); + } + cmd = WMGetFromPLDictionary(info, dPasteCommand); if (cmd) aicon->paste_command = wstrdup(WMGetFromPLString(cmd)); @@ -1704,6 +1718,8 @@ WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) if (type == WM_DOCK) dock->icon_count = 0; + dock->screen_ptr->flags.dock_changed_shortcuts = 0; + for (i = 0; i < count; i++) { if (dock->icon_count >= dock->max_icons) { wwarning(_("there are too many icons stored in dock. Ignoring what doesn't fit")); @@ -1736,6 +1752,12 @@ WDock *wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type) dock->icon_count++; } + if(dock->screen_ptr->flags.dock_changed_shortcuts) + { + rebind_key_grabs(dock->screen_ptr); + dock->screen_ptr->flags.dock_changed_shortcuts = 0; + } + /* if the first icon is not defined, use the default */ if (dock->icon_array[0] == NULL) { /* update default icon */ @@ -4031,3 +4053,125 @@ int wClipMakeIconOmnipresent(WAppIcon *aicon, int omnipresent) return status; } + +Bool +addDockShortcut(char *shortcutDefinition, WAppIcon *icon) +{ + int modifier = 0; + KeyCode keycode; + KeySym ksym; + char *k; + char buf[128], *b; + + strcpy(buf, shortcutDefinition); + b = (char*)buf; + + /* get modifiers */ + while((k = strchr(b, '+'))!=NULL) { + int mod; + + *k = 0; + mod = wXModifierFromKey(b); + if(mod < 0) { + wwarning(_("invalid key modifier \"%s\""), b); + return False; + } + modifier |= mod; + + b = k+1; + } + + /* get key */ + ksym = XStringToKeysym(b); + + if (ksym==NoSymbol) { + wwarning(_("invalid kbd shortcut specification \"%s\""), shortcutDefinition); + return False; + } + + keycode = XKeysymToKeycode(dpy, ksym); + if (keycode==0) { + wwarning(_("invalid key in shortcut \"%s\""), shortcutDefinition); + return False; + } + icon->modifier = modifier; + icon->keycode = keycode; + if(icon->dock && icon->dock->screen_ptr) + icon->dock->screen_ptr->flags.dock_changed_shortcuts = 1; + return True; +} + +static Bool +wDockPerformShortcut(WDock *dock, XEvent *event) +{ + int i; + int modifiers; + int done = 0; + + if(!dock) return done; + modifiers = event->xkey.state & ValidModMask; + for(i=(dock->type==WM_DOCK ? 0 : 1); i<dock->max_icons; i++) { + WAppIcon *btn = dock->icon_array[i]; + + if(!btn || btn->attracted) + continue; + + if(btn->keycode==event->xkey.keycode && (btn->modifier==modifiers)) { + launchDockedApplication(btn, False); + done = True; + break; + } + + } + return done; +} + +Bool +wDockAndClipPerformShortcut(WScreen *scr, XEvent *event) +{ + int done = 0; + int i; + if(!(done = wDockPerformShortcut(scr->dock, event))) { + for(i=0; i < scr->workspace_count; i++) { + if(done = wDockPerformShortcut(scr->workspaces[i]->clip, event)) break; + } + } + return done; +} + +static void +wDockBindShortcuts(Window window, WDock* dock) +{ + int i; + if(!dock) return; + for(i=(dock->type==WM_DOCK ? 0 : 1); i<dock->max_icons; i++) { + WAppIcon *btn = dock->icon_array[i]; + + if(!btn || btn->attracted) + continue; + + if(btn->keyboard_shortcut) + { + if(btn->keyboard_shortcut && btn->modifier!=AnyModifier) { + XGrabKey(dpy, btn->keycode, btn->modifier|LockMask, + window, True, GrabModeAsync, GrabModeAsync); +#ifdef NUMLOCK_HACK + wHackedGrabKey(btn->keycode, btn->modifier, + window, True, GrabModeAsync, GrabModeAsync); +#endif + } + XGrabKey(dpy, btn->keycode, btn->modifier, window, True, + GrabModeAsync, GrabModeAsync); + } + } +} + +void +wDockAndClipBindShortcuts(Window window, WScreen *scr) +{ + int i; + wDockBindShortcuts(window, scr->dock); + for(i=0; i < scr->workspace_count; i++ ) { + wDockBindShortcuts(window, scr->workspaces[i]->clip); + } +} diff --git a/src/dockedapp.c b/src/dockedapp.c index 944e025..b4a00c2 100644 --- a/src/dockedapp.c +++ b/src/dockedapp.c @@ -23,6 +23,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include <X11/keysym.h> #include <stdlib.h> #include <string.h> @@ -60,6 +61,10 @@ typedef struct _AppSettingsPanel { WMTextField *pasteCommandField; WMLabel *pasteCommandLabel; + WMFrame *keyboardShortcutFrame; + WMTextField *keyboardShortcutField; + WMButton *keyboardShortcutCaptureBtn; + WMFrame *iconFrame; WMTextField *iconField; WMButton *browseBtn; @@ -75,6 +80,7 @@ typedef struct _AppSettingsPanel { /* kluge */ unsigned int destroyed:1; unsigned int choosingIcon:1; + unsigned int capturing:1; } AppSettingsPanel; void DestroyDockAppSettingsPanel(AppSettingsPanel * panel); @@ -105,6 +111,43 @@ static void updatePasteCommand(WAppIcon * icon, char *command) icon->paste_command = command; } +static char* +trimstr(char *str) +{ + char *p = str; + int i; + + while (isspace(*p)) p++; + p = wstrdup(p); + i = strlen(p); + while (isspace(p[i]) && i>0) { + p[i]=0; + i--; + } + + return p; +} + +static void +updateKeyboardShortcut(WAppIcon *icon, char *shortcut) +{ + char *str = NULL; + if(icon->keyboard_shortcut) + wfree(icon->keyboard_shortcut); + if(shortcut) { + str = trimstr(shortcut); + if(!strlen(str)) { + wfree(str); + str = NULL; + } + } + icon->keyboard_shortcut = str; + icon->modifier = 0; + icon->keycode = 0; + if(str) addDockShortcut(str, icon); + rebind_key_grabs(icon->dock->screen_ptr); +} + #ifdef XDND static void updateDNDCommand(WAppIcon * icon, char *command) { @@ -242,6 +285,9 @@ static void panelBtnCallback(WMWidget * self, void *data) text = WMGetTextFieldText(panel->pasteCommandField); updatePasteCommand(panel->editedIcon, text); + text = WMGetTextFieldText(panel->keyboardShortcutField); + updateKeyboardShortcut(panel->editedIcon, text); + panel->editedIcon->auto_launch = WMGetButtonSelected(panel->autoLaunchBtn); panel->editedIcon->lock = WMGetButtonSelected(panel->lockBtn); @@ -251,8 +297,82 @@ static void panelBtnCallback(WMWidget * self, void *data) DestroyDockAppSettingsPanel(panel); } +static char* +captureShortcut(Display *dpy, AppSettingsPanel *panel) +{ + XEvent ev; + KeySym ksym, lksym, uksym; + char buffer[64]; + char *key = NULL; + + while (panel->capturing) { + XAllowEvents(dpy, AsyncKeyboard, CurrentTime); + WMNextEvent(dpy, &ev); + if (ev.type==KeyPress && ev.xkey.keycode!=0) { + ksym = XKeycodeToKeysym(dpy, ev.xkey.keycode, 0); + if (!IsModifierKey(ksym)) { + XConvertCase(ksym, &lksym, &uksym); + key=XKeysymToString(uksym); + panel->capturing = 0; + break; + } + } + WMHandleEvent(&ev); + } + if (!key) + return NULL; + + buffer[0] = 0; + if (ev.xkey.state & ControlMask) { + strcat(buffer, "Control+"); + } + if (ev.xkey.state & ShiftMask) { + strcat(buffer, "Shift+"); + } + if (ev.xkey.state & Mod1Mask) { + strcat(buffer, "Mod1+"); + } + if (ev.xkey.state & Mod2Mask) { + strcat(buffer, "Mod2+"); + } + if (ev.xkey.state & Mod3Mask) { + strcat(buffer, "Mod3+"); + } + if (ev.xkey.state & Mod4Mask) { + strcat(buffer, "Mod4+"); + } + if (ev.xkey.state & Mod5Mask) { + strcat(buffer, "Mod5+"); + } + strcat(buffer, key); + + return wstrdup(buffer); +} + +static void +captureClick(WMWidget *w, void *data) +{ + AppSettingsPanel *panel = (AppSettingsPanel*)data; + char *shortcut; + + if(!panel->capturing) { + panel->capturing = 1; + WMSetButtonText(w, _("Cancel")); + XGrabKeyboard(dpy, WMWidgetXID(panel->win), True, GrabModeAsync, + GrabModeAsync, CurrentTime); + shortcut = captureShortcut(dpy, panel); + if (shortcut) { + WMSetTextFieldText(panel->keyboardShortcutField, shortcut); + wfree(shortcut); + } + } + panel->capturing = 0; + WMSetButtonText(w, _("Capture")); + XUngrabKeyboard(dpy, CurrentTime); +} + #define PWIDTH 295 -#define PHEIGHT 430 +#define PHEIGHT 490 void ShowDockAppSettingsPanel(WAppIcon * aicon) { @@ -352,6 +472,21 @@ void ShowDockAppSettingsPanel(WAppIcon * aicon) #endif WMMapSubwidgets(panel->dndCommandFrame); + panel->keyboardShortcutFrame = WMCreateFrame(vbox); + WMSetFrameTitle(panel->keyboardShortcutFrame, _("Keyboard shortcut")); + WMAddBoxSubview(vbox, WMWidgetView(panel->keyboardShortcutFrame), False, True, + 50, 50, 10); + panel->keyboardShortcutField = WMCreateTextField(panel->keyboardShortcutFrame); + WMResizeWidget(panel->keyboardShortcutField, 176, 20); + WMMoveWidget(panel->keyboardShortcutField, 10, 20); + WMSetTextFieldText(panel->keyboardShortcutField, aicon->keyboard_shortcut); + panel->keyboardShortcutCaptureBtn = WMCreateCommandButton(panel->keyboardShortcutFrame); + WMSetButtonText(panel->keyboardShortcutCaptureBtn, _("Capture")); + WMResizeWidget(panel->keyboardShortcutCaptureBtn, 70, 24); + WMMoveWidget(panel->keyboardShortcutCaptureBtn, 195, 18); + WMSetButtonAction(panel->keyboardShortcutCaptureBtn, captureClick, panel); + WMMapSubwidgets(panel->keyboardShortcutFrame); + panel->iconFrame = WMCreateFrame(vbox); WMSetFrameTitle(panel->iconFrame, _("Icon Image")); WMAddBoxSubview(vbox, WMWidgetView(panel->iconFrame), False, True, 50, 50, 10); diff --git a/src/event.c b/src/event.c index 3bc3c40..98b2ff9 100644 --- a/src/event.c +++ b/src/event.c @@ -1363,7 +1363,7 @@ static void handleKeyPress(XEvent * event) if (command < 0) { - if (!wRootMenuPerformShortcut(event)) { + if (!wRootMenuPerformShortcut(event) && !wDockAndClipPerformShortcut(scr, event)) { static int dontLoop = 0; if (dontLoop > 10) { diff --git a/src/screen.h b/src/screen.h index af5a97b..a909bde 100644 --- a/src/screen.h +++ b/src/screen.h @@ -279,6 +279,7 @@ typedef struct _WScreen { unsigned int regenerate_icon_textures:1; unsigned int dnd_data_convertion_status:1; unsigned int root_menu_changed_shortcuts:1; + unsigned int dock_changed_shortcuts:1; unsigned int added_workspace_menu:1; unsigned int added_windows_menu:1; unsigned int startup2:1; /* startup phase 2 */ diff --git a/src/window.c b/src/window.c index d6a2a1b..e9f47a4 100644 --- a/src/window.c +++ b/src/window.c @@ -2478,6 +2478,7 @@ void wWindowSetKeyGrabs(WWindow * wwin) } wRootMenuBindShortcuts(wwin->frame->core->window); + wDockAndClipBindShortcuts(wwin->frame->core->window, wwin->screen_ptr); } void wWindowResetMouseGrabs(WWindow * wwin) -- 1.7.8.5
-- Deo Vindice.