Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37528050
en ru br
Репозитории ALT
S:0.96.0-alt1
5.1: 0.92.0-alt6
4.1: 0.92.0-alt2
4.0: 0.92.0-alt2
3.0: 0.91.0-alt1
+backports:0.92.0-alt0.M30.1
www.altlinux.org/Changes

Группа :: Графические оболочки/Window Maker
Пакет: WindowMaker

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: WindowMaker-0.92.0-alt-dockhotkeys.patch
Скачать


 src/appicon.c   |    2 +
 src/appicon.h   |    4 ++
 src/dock.c      |  143 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/dockedapp.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/event.c     |    2 +-
 src/rootmenu.c  |    2 +-
 src/screen.h    |    1 +
 src/window.c    |    1 +
 8 files changed, 288 insertions(+), 3 deletions(-)
diff --git a/src/appicon.c b/src/appicon.c
index e05897b..22f2693 100644
--- a/src/appicon.c
+++ b/src/appicon.c
@@ -197,6 +197,8 @@ 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);
     if (aicon->wm_class)
diff --git a/src/appicon.h b/src/appicon.h
index 1115490..60adeee 100644
--- a/src/appicon.h
+++ b/src/appicon.h
@@ -52,6 +52,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 04cd32c..8e1882d 100644
--- a/src/dock.c
+++ b/src/dock.c
@@ -96,6 +96,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;
@@ -151,6 +152,7 @@ make_keys()
 #ifdef XDND
     dDropCommand = WMRetainPropList(WMCreatePLString("DropCommand"));
 #endif
+    dKeyboardShortcut = WMRetainPropList(WMCreatePLString("Shortcut"));
     dLock = WMRetainPropList(WMCreatePLString("Lock"));
     dAutoLaunch = WMRetainPropList(WMCreatePLString("AutoLaunch"));
     dName = WMRetainPropList(WMCreatePLString("Name"));
@@ -1398,6 +1400,12 @@ 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);
@@ -1613,6 +1621,12 @@ restore_icon_state(WScreen *scr, WMPropList *info, int type, int index)
         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));
@@ -1918,6 +1932,8 @@ 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"));
@@ -1950,6 +1966,11 @@ wDockRestoreState(WScreen *scr, WMPropList *dock_state, int type)
         } else if (dock->icon_count==0 && type==WM_DOCK)
             dock->icon_count++;
     }
+    if(dock->screen_ptr->flags.dock_changed_shortcuts)
+    {
+        rebindKeygrabs(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) {
@@ -4479,3 +4500,125 @@ 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 b02f140..ac49d9c 100644
--- a/src/dockedapp.c
+++ b/src/dockedapp.c
@@ -25,6 +25,7 @@
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
+#include <X11/keysym.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -66,6 +67,10 @@ typedef struct _AppSettingsPanel {
     WMTextField *pasteCommandField;
     WMLabel *pasteCommandLabel;
 
+    WMFrame *keyboardShortcutFrame;
+    WMTextField *keyboardShortcutField;
+    WMButton *keyboardShortcutCaptureBtn;
+
     WMFrame *iconFrame;
     WMTextField *iconField;
     WMButton *browseBtn;
@@ -81,6 +86,7 @@ typedef struct _AppSettingsPanel {
     /* kluge */
     unsigned int destroyed:1;
     unsigned int choosingIcon:1;
+    unsigned int capturing:1;
 } AppSettingsPanel;
 
 
@@ -117,6 +123,43 @@ 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);
+    	rebindKeygrabs(icon->dock->screen_ptr);
+}
+
 
 
 #ifdef XDND
@@ -267,6 +310,8 @@ 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);
@@ -279,9 +324,83 @@ 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
@@ -396,6 +515,21 @@ 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,
diff --git a/src/event.c b/src/event.c
index 85046d4..3afa95f 100644
--- a/src/event.c
+++ b/src/event.c
@@ -1368,7 +1368,7 @@ handleKeyPress(XEvent *event)
         }
 #endif
 #else
-        if (!wRootMenuPerformShortcut(event)) {
+	if (!wRootMenuPerformShortcut(event) && !wDockAndClipPerformShortcut(scr, event)) {
 #endif
             static int dontLoop = 0;
 
diff --git a/src/rootmenu.c b/src/rootmenu.c
index 58eedb2..01a5851 100644
--- a/src/rootmenu.c
+++ b/src/rootmenu.c
@@ -466,7 +466,7 @@ wRootMenuBindShortcuts(Window window)
 }
 
 
-static void
+void
 rebindKeygrabs(WScreen *scr)
 {
     WWindow *wwin;
diff --git a/src/screen.h b/src/screen.h
index 03f74f4..e58fa57 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -307,6 +307,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 0b6a39a..39eba85 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2809,6 +2809,7 @@ wWindowSetKeyGrabs(WWindow *wwin)
 
 #ifndef LITE
     wRootMenuBindShortcuts(wwin->frame->core->window);
+    wDockAndClipBindShortcuts(wwin->frame->core->window, wwin->screen_ptr);
 #endif
 }
 
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin