On Sat, 16 Apr 2011, Martin Dietze wrote:
> hack away :)
and here's an attempt.
(forgot to mention wmessage()ification in the changelog; writing to
buffered stdout highly sucks if you actually want to read debug
stuff...)
>From c5a22205ac33c49dbc8cedae4ab26b8967938e35 Mon Sep 17 00:00:00 2001
From: Tamas TEVESZ <[email protected]>
Date: Mon, 18 Apr 2011 21:00:49 +0200
Subject: [PATCH] Partial fix for focus stealing
By turning M'bert's d6c134 around a bit and adapting the surroundings,
allow _NET_ACTIVE_WINDOW only if fulfilling it doesn't cause annoying
unwanted changes in the workspace. This is now the default behaviour;
unconditional focus stealing can be enabled on a per-client basis in the
Advanced Options window menu ("Focus across workspaces").
---
src/wdefaults.c | 8 ++++----
src/window.h | 4 ++--
src/winspector.c | 19 +++++++++----------
src/wmspec.c | 36 +++++++++++++++++-------------------
4 files changed, 32 insertions(+), 35 deletions(-)
diff --git a/src/wdefaults.c b/src/wdefaults.c
index ffe3b20..94487d0 100644
--- a/src/wdefaults.c
+++ b/src/wdefaults.c
@@ -74,7 +74,7 @@ static WMPropList *AStartMaximized;
static WMPropList *AStartHidden; /* app */
static WMPropList *ADontSaveSession; /* app */
static WMPropList *AEmulateAppIcon;
-static WMPropList *ADontFocusAcrossWorkspace;
+static WMPropList *AFocusAcrossWorkspace;
static WMPropList *AFullMaximize;
static WMPropList *ASharedAppIcon; /* app */
#ifdef XKB_BUTTON_HINT
@@ -111,7 +111,7 @@ static void init_wdefaults(WScreen * scr)
AStartMaximized = WMCreatePLString("StartMaximized");
ADontSaveSession = WMCreatePLString("DontSaveSession");
AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
- ADontFocusAcrossWorkspace =
WMCreatePLString("DontFocusAcrossWorkspace");
+ AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
AFullMaximize = WMCreatePLString("FullMaximize");
ASharedAppIcon = WMCreatePLString("SharedAppIcon");
#ifdef XKB_BUTTON_HINT
@@ -303,8 +303,8 @@ 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, AFocusAcrossWorkspace, No,
useGlobalDefault);
+ APPLY_VAL(value, focus_across_wksp, AFocusAcrossWorkspace);
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 47c2506..edebe80 100644
--- a/src/window.h
+++ b/src/window.h
@@ -125,8 +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 focus_across_wksp:1; /* 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 8b14094..7efe99f 100644
--- a/src/winspector.c
+++ b/src/winspector.c
@@ -138,7 +138,7 @@ static WMPropList *ASkipWindowList;
static WMPropList *ASkipSwitchPanel;
static WMPropList *AKeepInsideScreen;
static WMPropList *AUnfocusable;
-static WMPropList *ADontFocusAcrossWorkspace;
+static WMPropList *AFocusAcrossWorkspace;
static WMPropList *AAlwaysUserIcon;
static WMPropList *AStartMiniaturized;
static WMPropList *AStartMaximized;
@@ -190,7 +190,7 @@ static void make_keys(void)
ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
AUnfocusable = WMCreatePLString("Unfocusable");
- ADontFocusAcrossWorkspace =
WMCreatePLString("DontFocusAcrossWorkspace");
+ AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
AStartMiniaturized = WMCreatePLString("StartMiniaturized");
AStartMaximized = WMCreatePLString("StartMaximized");
@@ -595,7 +595,7 @@ static void saveSettings(WMButton * button, InspectorPanel
* panel)
different |= insertAttribute(dict, winDic, AEmulateAppIcon, value,
flags);
value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
- different |= insertAttribute(dict, winDic, ADontFocusAcrossWorkspace,
value, flags);
+ different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace,
value, flags);
#ifdef XKB_BUTTON_HINT
value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
@@ -773,7 +773,7 @@ static void applySettings(WMButton * button, InspectorPanel
* panel)
WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
WSETUFLAG(wwin, dont_save_session,
WMGetButtonSelected(panel->moreChk[7]));
WSETUFLAG(wwin, emulate_appicon,
WMGetButtonSelected(panel->moreChk[8]));
- WSETUFLAG(wwin, dont_focus_across_wksp,
WMGetButtonSelected(panel->moreChk[9]));
+ WSETUFLAG(wwin, focus_across_wksp,
WMGetButtonSelected(panel->moreChk[9]));
#ifdef XKB_BUTTON_HINT
WSETUFLAG(wwin, no_language_button,
WMGetButtonSelected(panel->moreChk[10]));
#endif
@@ -951,7 +951,7 @@ static void revertSettings(WMButton * button,
InspectorPanel * panel)
flag = WFLAGP(wwin, emulate_appicon);
break;
case 9:
- flag = WFLAGP(wwin, dont_focus_across_wksp);
+ flag = WFLAGP(wwin, focus_across_wksp);
break;
#ifdef XKB_BUTTON_HINT
case 10:
@@ -1394,11 +1394,10 @@ static InspectorPanel *createInspectorForWindow(WWindow
* wwin, int xpos, int yp
"application icon to be created.");
break;
case 9:
- 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).");
+ caption = _("Focus across workspaces");
+ flag = WFLAGP(wwin, focus_across_wksp);
+ descr = _("Allow Window Maker to switch workspace to
satisfy\n"
+ "a focus request (annoying).");
break;
#ifdef XKB_BUTTON_HINT
case 10:
diff --git a/src/wmspec.c b/src/wmspec.c
index d3bce77..95985db 100644
--- a/src/wmspec.c
+++ b/src/wmspec.c
@@ -35,6 +35,7 @@
#include <X11/Xarch.h>
#include <string.h>
+#include <WINGs/WUtil.h>
#include "WindowMaker.h"
#include "window.h"
#include "screen.h"
@@ -49,10 +50,6 @@
#include "xinerama.h"
#include "properties.h"
-#ifdef DEBUG_WMSPEC
-#include <stdio.h>
-#endif
-
/* Global variables */
extern Atom _XA_WM_DELETE_WINDOW;
extern Time LastTimestamp;
@@ -519,7 +516,7 @@ void wNETWMInitStuff(WScreen * scr)
int i;
#ifdef DEBUG_WMSPEC
- printf("wNETWMInitStuff\n");
+ wmessage("enter");
#endif
#ifdef HAVE_XINTERNATOMS
@@ -1041,7 +1038,7 @@ static void doStateAtom(WWindow * wwin, Atom state, int
set, Bool init)
} else {
#ifdef DEBUG_WMSPEC
- printf("doStateAtom unknown atom %s set %d\n",
XGetAtomName(dpy, state), set);
+ wmessage("doStateAtom unknown atom %s set %d\n",
XGetAtomName(dpy, state), set);
#endif
}
}
@@ -1303,7 +1300,7 @@ Bool wNETWMCheckInitialClientState(WWindow * wwin)
Bool hasState = False;
#ifdef DEBUG_WMSPEC
- printf("CheckInitialClientState\n");
+ wmessage("enter");
#endif
wNETWMShowingDesktop(wwin->screen_ptr, False);
@@ -1354,7 +1351,7 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent *
event)
Bool done = True;
#ifdef DEBUG_WMSPEC
- printf("processClientMessage type %s\n", XGetAtomName(dpy,
event->message_type));
+ wmessage("processClientMessage type %s\n", XGetAtomName(dpy,
event->message_type));
#endif
scr = wScreenForWindow(event->window);
@@ -1403,16 +1400,17 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent *
event)
if (event->message_type == net_active_window) {
/*
- * Firefox sends aditional 'net_active_window' signals on
startup if
- * multiple tabs are open. That causes unnecessary workspace
switching if
- * those signals come from other workspaces. Therefore we also
check if
- * we should ignore these spurious focus across workspaces
requests (but
- * allow the switching if it comes from a pager).
+ * Satisfy a client's focus request only if
+ * - request comes from a pager, or
+ * - it's explicitly allowed in Advanced Options, or
+ * - giving the client the focus does not cause a change in
+ * the active workspace (XXX: or the active head if Xinerama)
*/
- if (wwin->frame->workspace ==
wwin->screen_ptr->current_workspace
- || !WFLAGP(wwin, dont_focus_across_wksp) ||
event->data.l[0] == 2) {
- wNETWMShowingDesktop(scr, False);
- wMakeWindowVisible(wwin);
+ if (wwin->frame->workspace ==
wwin->screen_ptr->current_workspace /* No workspace change */
+ || event->data.l[0] == 2 /* Requested by pager */
+ || WFLAGP(wwin, focus_across_wksp) /* Explicitly allowed
*/) {
+ wNETWMShowingDesktop(scr, False);
+ wMakeWindowVisible(wwin);
}
} else if (event->message_type == net_close_window) {
if (!WFLAGP(wwin, no_closable)) {
@@ -1424,7 +1422,7 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent *
event)
long set = event->data.l[0];
#ifdef DEBUG_WMSPEC
- printf("net_wm_state set %ld a1 %s a2 %s\n", set,
+ wmessage("net_wm_state set %ld a1 %s a2 %s\n", set,
XGetAtomName(dpy, event->data.l[1]), XGetAtomName(dpy,
event->data.l[2]));
#endif
@@ -1464,7 +1462,7 @@ Bool wNETWMCheckClientHintChange(WWindow * wwin,
XPropertyEvent * event)
Bool ret = True;
#ifdef DEBUG_WMSPEC
- printf("clientHintChange type %s\n", XGetAtomName(dpy, event->atom));
+ wmessage("clientHintChange type %s\n", XGetAtomName(dpy, event->atom));
#endif
if (event->atom == net_wm_strut) {
--
1.7.0.4
--
[-]
mkdir /nonexistentFrom c5a22205ac33c49dbc8cedae4ab26b8967938e35 Mon Sep 17 00:00:00 2001
From: Tamas TEVESZ <[email protected]>
Date: Mon, 18 Apr 2011 21:00:49 +0200
Subject: [PATCH] Partial fix for focus stealing
By turning M'bert's d6c134 around a bit and adapting the surroundings,
allow _NET_ACTIVE_WINDOW only if fulfilling it doesn't cause annoying
unwanted changes in the workspace. This is now the default behaviour;
unconditional focus stealing can be enabled on a per-client basis in the
Advanced Options window menu ("Focus across workspaces").
---
src/wdefaults.c | 8 ++++----
src/window.h | 4 ++--
src/winspector.c | 19 +++++++++----------
src/wmspec.c | 36 +++++++++++++++++-------------------
4 files changed, 32 insertions(+), 35 deletions(-)
diff --git a/src/wdefaults.c b/src/wdefaults.c
index ffe3b20..94487d0 100644
--- a/src/wdefaults.c
+++ b/src/wdefaults.c
@@ -74,7 +74,7 @@ static WMPropList *AStartMaximized;
static WMPropList *AStartHidden; /* app */
static WMPropList *ADontSaveSession; /* app */
static WMPropList *AEmulateAppIcon;
-static WMPropList *ADontFocusAcrossWorkspace;
+static WMPropList *AFocusAcrossWorkspace;
static WMPropList *AFullMaximize;
static WMPropList *ASharedAppIcon; /* app */
#ifdef XKB_BUTTON_HINT
@@ -111,7 +111,7 @@ static void init_wdefaults(WScreen * scr)
AStartMaximized = WMCreatePLString("StartMaximized");
ADontSaveSession = WMCreatePLString("DontSaveSession");
AEmulateAppIcon = WMCreatePLString("EmulateAppIcon");
- ADontFocusAcrossWorkspace = WMCreatePLString("DontFocusAcrossWorkspace");
+ AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
AFullMaximize = WMCreatePLString("FullMaximize");
ASharedAppIcon = WMCreatePLString("SharedAppIcon");
#ifdef XKB_BUTTON_HINT
@@ -303,8 +303,8 @@ 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, AFocusAcrossWorkspace, No, useGlobalDefault);
+ APPLY_VAL(value, focus_across_wksp, AFocusAcrossWorkspace);
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 47c2506..edebe80 100644
--- a/src/window.h
+++ b/src/window.h
@@ -125,8 +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 focus_across_wksp:1; /* 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 8b14094..7efe99f 100644
--- a/src/winspector.c
+++ b/src/winspector.c
@@ -138,7 +138,7 @@ static WMPropList *ASkipWindowList;
static WMPropList *ASkipSwitchPanel;
static WMPropList *AKeepInsideScreen;
static WMPropList *AUnfocusable;
-static WMPropList *ADontFocusAcrossWorkspace;
+static WMPropList *AFocusAcrossWorkspace;
static WMPropList *AAlwaysUserIcon;
static WMPropList *AStartMiniaturized;
static WMPropList *AStartMaximized;
@@ -190,7 +190,7 @@ static void make_keys(void)
ASkipSwitchPanel = WMCreatePLString("SkipSwitchPanel");
AKeepInsideScreen = WMCreatePLString("KeepInsideScreen");
AUnfocusable = WMCreatePLString("Unfocusable");
- ADontFocusAcrossWorkspace = WMCreatePLString("DontFocusAcrossWorkspace");
+ AFocusAcrossWorkspace = WMCreatePLString("FocusAcrossWorkspace");
AAlwaysUserIcon = WMCreatePLString("AlwaysUserIcon");
AStartMiniaturized = WMCreatePLString("StartMiniaturized");
AStartMaximized = WMCreatePLString("StartMaximized");
@@ -595,7 +595,7 @@ static void saveSettings(WMButton * button, InspectorPanel * panel)
different |= insertAttribute(dict, winDic, AEmulateAppIcon, value, flags);
value = (WMGetButtonSelected(panel->moreChk[9]) != 0) ? Yes : No;
- different |= insertAttribute(dict, winDic, ADontFocusAcrossWorkspace, value, flags);
+ different |= insertAttribute(dict, winDic, AFocusAcrossWorkspace, value, flags);
#ifdef XKB_BUTTON_HINT
value = (WMGetButtonSelected(panel->moreChk[10]) != 0) ? Yes : No;
@@ -773,7 +773,7 @@ static void applySettings(WMButton * button, InspectorPanel * panel)
WSETUFLAG(wwin, no_hide_others, WMGetButtonSelected(panel->moreChk[6]));
WSETUFLAG(wwin, dont_save_session, WMGetButtonSelected(panel->moreChk[7]));
WSETUFLAG(wwin, emulate_appicon, WMGetButtonSelected(panel->moreChk[8]));
- WSETUFLAG(wwin, dont_focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
+ WSETUFLAG(wwin, focus_across_wksp, WMGetButtonSelected(panel->moreChk[9]));
#ifdef XKB_BUTTON_HINT
WSETUFLAG(wwin, no_language_button, WMGetButtonSelected(panel->moreChk[10]));
#endif
@@ -951,7 +951,7 @@ static void revertSettings(WMButton * button, InspectorPanel * panel)
flag = WFLAGP(wwin, emulate_appicon);
break;
case 9:
- flag = WFLAGP(wwin, dont_focus_across_wksp);
+ flag = WFLAGP(wwin, focus_across_wksp);
break;
#ifdef XKB_BUTTON_HINT
case 10:
@@ -1394,11 +1394,10 @@ static InspectorPanel *createInspectorForWindow(WWindow * wwin, int xpos, int yp
"application icon to be created.");
break;
case 9:
- 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).");
+ caption = _("Focus across workspaces");
+ flag = WFLAGP(wwin, focus_across_wksp);
+ descr = _("Allow Window Maker to switch workspace to satisfy\n"
+ "a focus request (annoying).");
break;
#ifdef XKB_BUTTON_HINT
case 10:
diff --git a/src/wmspec.c b/src/wmspec.c
index d3bce77..95985db 100644
--- a/src/wmspec.c
+++ b/src/wmspec.c
@@ -35,6 +35,7 @@
#include <X11/Xarch.h>
#include <string.h>
+#include <WINGs/WUtil.h>
#include "WindowMaker.h"
#include "window.h"
#include "screen.h"
@@ -49,10 +50,6 @@
#include "xinerama.h"
#include "properties.h"
-#ifdef DEBUG_WMSPEC
-#include <stdio.h>
-#endif
-
/* Global variables */
extern Atom _XA_WM_DELETE_WINDOW;
extern Time LastTimestamp;
@@ -519,7 +516,7 @@ void wNETWMInitStuff(WScreen * scr)
int i;
#ifdef DEBUG_WMSPEC
- printf("wNETWMInitStuff\n");
+ wmessage("enter");
#endif
#ifdef HAVE_XINTERNATOMS
@@ -1041,7 +1038,7 @@ static void doStateAtom(WWindow * wwin, Atom state, int set, Bool init)
} else {
#ifdef DEBUG_WMSPEC
- printf("doStateAtom unknown atom %s set %d\n", XGetAtomName(dpy, state), set);
+ wmessage("doStateAtom unknown atom %s set %d\n", XGetAtomName(dpy, state), set);
#endif
}
}
@@ -1303,7 +1300,7 @@ Bool wNETWMCheckInitialClientState(WWindow * wwin)
Bool hasState = False;
#ifdef DEBUG_WMSPEC
- printf("CheckInitialClientState\n");
+ wmessage("enter");
#endif
wNETWMShowingDesktop(wwin->screen_ptr, False);
@@ -1354,7 +1351,7 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent * event)
Bool done = True;
#ifdef DEBUG_WMSPEC
- printf("processClientMessage type %s\n", XGetAtomName(dpy, event->message_type));
+ wmessage("processClientMessage type %s\n", XGetAtomName(dpy, event->message_type));
#endif
scr = wScreenForWindow(event->window);
@@ -1403,16 +1400,17 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent * event)
if (event->message_type == net_active_window) {
/*
- * Firefox sends aditional 'net_active_window' signals on startup if
- * multiple tabs are open. That causes unnecessary workspace switching if
- * those signals come from other workspaces. Therefore we also check if
- * we should ignore these spurious focus across workspaces requests (but
- * allow the switching if it comes from a pager).
+ * Satisfy a client's focus request only if
+ * - request comes from a pager, or
+ * - it's explicitly allowed in Advanced Options, or
+ * - giving the client the focus does not cause a change in
+ * the active workspace (XXX: or the active head if Xinerama)
*/
- if (wwin->frame->workspace == wwin->screen_ptr->current_workspace
- || !WFLAGP(wwin, dont_focus_across_wksp) || event->data.l[0] == 2) {
- wNETWMShowingDesktop(scr, False);
- wMakeWindowVisible(wwin);
+ if (wwin->frame->workspace == wwin->screen_ptr->current_workspace /* No workspace change */
+ || event->data.l[0] == 2 /* Requested by pager */
+ || WFLAGP(wwin, focus_across_wksp) /* Explicitly allowed */) {
+ wNETWMShowingDesktop(scr, False);
+ wMakeWindowVisible(wwin);
}
} else if (event->message_type == net_close_window) {
if (!WFLAGP(wwin, no_closable)) {
@@ -1424,7 +1422,7 @@ Bool wNETWMProcessClientMessage(XClientMessageEvent * event)
long set = event->data.l[0];
#ifdef DEBUG_WMSPEC
- printf("net_wm_state set %ld a1 %s a2 %s\n", set,
+ wmessage("net_wm_state set %ld a1 %s a2 %s\n", set,
XGetAtomName(dpy, event->data.l[1]), XGetAtomName(dpy, event->data.l[2]));
#endif
@@ -1464,7 +1462,7 @@ Bool wNETWMCheckClientHintChange(WWindow * wwin, XPropertyEvent * event)
Bool ret = True;
#ifdef DEBUG_WMSPEC
- printf("clientHintChange type %s\n", XGetAtomName(dpy, event->atom));
+ wmessage("clientHintChange type %s\n", XGetAtomName(dpy, event->atom));
#endif
if (event->atom == net_wm_strut) {
--
1.7.0.4