>From 0f3f6ca736fe43222298633eb618f8a50f92292f Mon Sep 17 00:00:00 2001
From: Carlos R. Mafra <[email protected]>
Date: Tue, 25 Aug 2009 21:15:35 +0200
Subject: [PATCH v2] Add config option to supress focus requests across 
workspaces

In commit d6c134f420bfa1cd6b6a9474d01548933b559901 ("Do not switch
workspace to follow new windows in others") the default behavior
was changed, and workspace switching to follow focus requests was
strictly forbidden.

Although that seems to be a sane thing to do by default, that raises
concerns about whether Window Maker could be more flexible in that
respect -- allowing the user to choose which applications are or
are not allowed to do that.

This patch adds such configuration, located in the "Advanced Options"
submenu of the top-level "Attributes" menu.
---

  Changes since v1:
  
          * Rename ignore_focus_across_wksp to dont_focus_across_wksp, as
            that makes more sense from the point of view of the _application_
            
          * Change option description to be congruent to the variable renaming
          
          * Add back Martin's check regarding the origin of the request, if it
            comes from a different workspace or not

 src/session.c    |    5 +++--
 src/wdefaults.c  |    5 +++++
 src/window.h     |    2 ++
 src/winspector.c |   36 +++++++++++++++++++++++++++---------
 src/wmspec.c     |   18 +++++++++++-------
 5 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/src/session.c b/src/session.c
index 90f5040..17a2d5a 100644
--- a/src/session.c
+++ b/src/session.c
@@ -803,7 +803,7 @@ static WMPropList *makeAttributeState(WWindow * wwin)
     ? (wwin)->user_flags.FLAG : -1)
 
        snprintf(buffer, sizeof(buffer),
-                "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i 
%i %i %i",
+                "%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i 
%i %i %i %i",
                 W_FLAG(no_titlebar),
                 W_FLAG(no_resizable),
                 W_FLAG(no_closable),
@@ -827,7 +827,8 @@ static WMPropList *makeAttributeState(WWindow * wwin)
                 W_FLAG(always_user_icon),
                 W_FLAG(start_miniaturized),
                 W_FLAG(start_hidden),
-                W_FLAG(start_maximized), W_FLAG(dont_save_session), 
W_FLAG(emulate_appicon));
+                W_FLAG(start_maximized),
+                W_FLAG(dont_save_session), W_FLAG(dont_focus_across_wksp), 
W_FLAG(emulate_appicon));
 
        return WMCreatePLString(buffer);
 }
diff --git a/src/wdefaults.c b/src/wdefaults.c
index d82bb49..5fec333 100644
--- a/src/wdefaults.c
+++ b/src/wdefaults.c
@@ -78,6 +78,7 @@ static WMPropList *AStartMaximized;
 static WMPropList *AStartHidden;       /* app */
 static WMPropList *ADontSaveSession;   /* app */
 static WMPropList *AEmulateAppIcon;
+static WMPropList *ADontFocusAcrossWorkspace;
 static WMPropList *AFullMaximize;
 static WMPropList *ASharedAppIcon;     /* app */
 #ifdef XKB_BUTTON_HINT
@@ -116,6 +117,7 @@ static void init_wdefaults(WScreen * scr)
        AStartMaximized = WMCreatePLString("StartMaximized");
        ADontSaveSession = WMCreatePLString("DontSaveSession");
        AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
+       ADontFocusAcrossWorkspace = 
WMCreatePLString("DontFocusAcrossWorkspace");
        AFullMaximize = WMCreatePLString("FullMaximize");
        ASharedAppIcon = WMCreatePLString("SharedAppIcon");
 #ifdef XKB_BUTTON_HINT
@@ -304,6 +306,9 @@ wDefaultFillAttributes(WScreen * scr, char *instance, char 
*class,
        value = get_value(dw, dc, dn, da, AEmulateAppIcon, No, 
useGlobalDefault);
        APPLY_VAL(value, emulate_appicon, AEmulateAppIcon);
 
+       value = get_value(dw, dc, dn, da, ADontFocusAcrossWorkspace, No, 
useGlobalDefault);
+       APPLY_VAL(value, dont_focus_across_wksp, ADontFocusAcrossWorkspace);
+
        value = get_value(dw, dc, dn, da, AFullMaximize, No, useGlobalDefault);
        APPLY_VAL(value, full_maximize, AFullMaximize);
 
diff --git a/src/window.h b/src/window.h
index e8275e2..f729fd9 100644
--- a/src/window.h
+++ b/src/window.h
@@ -125,6 +125,8 @@ typedef struct {
     unsigned int dont_move_off:1;
 
     unsigned int no_focusable:1;
+    unsigned int dont_focus_across_wksp:1; /* don't let wmaker switch 
workspace to follow
+                                           * a focus request */
 
     unsigned int always_user_icon:1;   /* ignore client IconPixmap or
                                         * IconWindow */
diff --git a/src/winspector.c b/src/winspector.c
index 4609a7e..fe473c2 100644
--- a/src/winspector.c
+++ b/src/winspector.c
@@ -93,9 +93,9 @@ typedef struct InspectorPanel {
        /* 3rd page. more attributes */
        WMFrame *moreFrm;
 #ifdef XKB_BUTTON_HINT
-       WMButton *moreChk[9];
+       WMButton *moreChk[10];
 #else
-       WMButton *moreChk[8];
+       WMButton *moreChk[9];
 #endif
 
        /* 4th page. icon and workspace */
@@ -144,6 +144,7 @@ static WMPropList *AOmnipresent;
 static WMPropList *ASkipWindowList;
 static WMPropList *AKeepInsideScreen;
 static WMPropList *AUnfocusable;
+static WMPropList *ADontFocusAcrossWorkspace;
 static WMPropList *AAlwaysUserIcon;
 static WMPropList *AStartMiniaturized;
 static WMPropList *AStartMaximized;
@@ -198,6 +199,7 @@ static void make_keys()
        ASkipWindowList = WMCreatePLString("SkipWindowList");
        AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
        AUnfocusable = WMCreatePLString("Unfocusable");
+       ADontFocusAcrossWorkspace = 
WMCreatePLString("DontFocusAcrossWorkspace");
        AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
        AStartMiniaturized = WMCreatePLString("StartMiniaturized");
        AStartMaximized = WMCreatePLString("StartMaximized");
@@ -598,8 +600,11 @@ static void saveSettings(WMButton * button, InspectorPanel 
* panel)
        value = (WMGetButtonSelected(panel->moreChk[7]) != 0) ? Yes : No;
        different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, 
flags);
 
-#ifdef XKB_BUTTON_HINT
        value = (WMGetButtonSelected(panel->moreChk[8]) != 0) ? Yes : No;
+       different |= insertAttribute(dict, winDic, ADontFocusAcrossWorkspace, 
value, flags);
+
+#ifdef XKB_BUTTON_HINT
+       value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
        different |= insertAttribute(dict, winDic, ANoLanguageButton, value, 
flags);
 #endif
 
@@ -751,6 +756,7 @@ static void applySettings(WMButton * button, InspectorPanel 
* panel)
 
        showIconFor(WMWidgetScreen(button), panel, NULL, NULL, USE_TEXT_FIELD);
 
+       /* Attributes... --> Window Attributes */
        WSETUFLAG(wwin, no_titlebar, WMGetButtonSelected(panel->attrChk[0]));
        WSETUFLAG(wwin, no_resizebar, WMGetButtonSelected(panel->attrChk[1]));
        WSETUFLAG(wwin, no_close_button, 
WMGetButtonSelected(panel->attrChk[2]));
@@ -763,6 +769,7 @@ static void applySettings(WMButton * button, InspectorPanel 
* panel)
        WSETUFLAG(wwin, start_maximized, 
WMGetButtonSelected(panel->attrChk[9]));
        WSETUFLAG(wwin, full_maximize, WMGetButtonSelected(panel->attrChk[10]));
 
+       /* Attributes... --> Advanced Options */
        WSETUFLAG(wwin, no_bind_keys, WMGetButtonSelected(panel->moreChk[0]));
        WSETUFLAG(wwin, no_bind_mouse, WMGetButtonSelected(panel->moreChk[1]));
        skip_window_list = WMGetButtonSelected(panel->moreChk[2]);
@@ -771,8 +778,9 @@ static void applySettings(WMButton * button, InspectorPanel 
* panel)
        WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[5]));
        WSETUFLAG(wwin, dont_save_session, 
WMGetButtonSelected(panel->moreChk[6]));
        WSETUFLAG(wwin, emulate_appicon, 
WMGetButtonSelected(panel->moreChk[7]));
+       WSETUFLAG(wwin, dont_focus_across_wksp, 
WMGetButtonSelected(panel->moreChk[8]));
 #ifdef XKB_BUTTON_HINT
-       WSETUFLAG(wwin, no_language_button, 
WMGetButtonSelected(panel->moreChk[8]));
+       WSETUFLAG(wwin, no_language_button, 
WMGetButtonSelected(panel->moreChk[9]));
 #endif
        WSETUFLAG(wwin, always_user_icon, WMGetButtonSelected(panel->alwChk));
 
@@ -919,7 +927,7 @@ static void revertSettings(WMButton * button, 
InspectorPanel * panel)
                }
                WMSetButtonSelected(panel->attrChk[i], flag);
        }
-       for (i = 0; i < 8; i++) {
+       for (i = 0; i < 9; i++) {
                int flag = 0;
 
                switch (i) {
@@ -947,8 +955,11 @@ static void revertSettings(WMButton * button, 
InspectorPanel * panel)
                case 7:
                        flag = WFLAGP(wwin, emulate_appicon);
                        break;
-#ifdef XKB_BUTTON_HINT
                case 8:
+                       flag = WFLAGP(wwin, dont_focus_across_wksp);
+                       break;
+#ifdef XKB_BUTTON_HINT
+               case 9:
                        flag = WFLAGP(wwin, no_language_button);
                        break;
 #endif
@@ -1323,9 +1334,9 @@ static InspectorPanel *createInspectorForWindow(WWindow * 
wwin, int xpos, int yp
 
        for (i = 0;
 #ifdef XKB_BUTTON_HINT
-            i < 9;
+            i < 10;
 #else
-            i < 8;
+            i < 9;
 #endif
             i++) {
                char *caption = NULL;
@@ -1382,8 +1393,15 @@ static InspectorPanel *createInspectorForWindow(WWindow 
* wwin, int xpos, int yp
                                  "enough information to Window Maker for a 
dockable\n"
                                  "application icon to be created.");
                        break;
-#ifdef XKB_BUTTON_HINT
                case 8:
+                       caption = _("Don't focus across workspaces");
+                       flag = WFLAGP(wwin, dont_focus_across_wksp);
+                       descr = _("Do not allow Window Maker to switch 
workspace to satisfy\n"
+                                 "a focus request (useful e.g. in the case of 
a multiple-tab\n"
+                                 "firefox opening in a different workspace).");
+                       break;
+#ifdef XKB_BUTTON_HINT
+               case 9:
                        caption = _("Disable language button");
                        flag = WFLAGP(wwin, no_language_button);
                        descr = _("Remove the `toggle language' button of the 
window.");
diff --git a/src/wmspec.c b/src/wmspec.c
index ab4ddcf..e1ff9ff 100644
--- a/src/wmspec.c
+++ b/src/wmspec.c
@@ -1449,14 +1449,18 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent * 
event)
                return False;
 
        /*
-        * Firefox with multiple tabs sends aditional 'net_active_window'
-        * signals on startup, which causes unnecessary workspace switching
-        * if its initial workspace is different from the current
+        * Firefox sends aditional 'net_active_window' signals on startup if
+        * multiple tabs are open. That causes unnecessary workspace switching 
if
+        * those signals come from across workspaces, i.e. from a different one 
than
+        * the current. Therefore we also check if we should ignore these 
spurious
+        * focus across workspaces requests.
         */
-       if (event->message_type == net_active_window &&
-           wwin->frame->workspace == wwin->screen_ptr->current_workspace) {
-               wNETWMShowingDesktop(scr, False);
-               wMakeWindowVisible(wwin);
+       if (event->message_type == net_active_window) {
+               if (wwin->frame->workspace == 
wwin->screen_ptr->current_workspace
+                   || !WFLAGP(wwin, dont_focus_across_wksp)) {
+                       wNETWMShowingDesktop(scr, False);
+                       wMakeWindowVisible(wwin);
+               }
        } else if (event->message_type == net_close_window) {
                if (!WFLAGP(wwin, no_closable)) {
                        if (wwin->protocols.DELETE_WINDOW)
-- 
1.6.4.183.g04423


-- 
To unsubscribe, send mail to [email protected].

Reply via email to