Do not send WM_TAKE_FOCUS when InputHint is set
Patch status: needinfo
Patch by Tony Crisci
Long description:
Window managers do not conventionally send WM_TAKE_FOCUS when the WM_HINTS property of the client has the `input` flag set (which shall be "the client's input model") ''even when the window claims to support the protocol''. While the window manager may respond by both setting focus for the client and sending WM_TAKE_FOCUS, the latter will not fulfil its intended purpose and may complicate input event handling. Note that whenever the WM_HINTS property is missing from the window, i3 will treat this window as if the InputHint is set. The window manager is allowed by the spec to assume convenient values in this case. dwm seems to follow this convention: http://lists.suckless.org/dev/1104/7548.html#replies Here is a second-hand report that Compiz and Metacity follow this convention: www.winehq.org/pipermail/wine-devel/2007-July/058255.html The "models of input handling" can be found here: http://tronche.com/gui/x/icccm/sec-4.html#s-4.1.7 Future work should go towards improving support for the input handling models. i3 should implement support for the "no input" model, perhaps based on _NET_WM_TYPE. For possible implementation ideas see http://mail.gnome.org/archives/wm-spec-list/2007-March/msg00001.html fixes #1167
To apply this patch, use:
curl http://cr.i3wm.org/patch/408/raw.patch | git am
b/src/x.c
41 |
@@ -964,17 +964,13 @@ void x_push_changes(Con *con) { |
42 |
/* Invalidate focused_id to correctly focus new windows with the same ID */ |
43 |
focused_id = XCB_NONE; |
44 |
} else { |
45 |
- bool set_focus = true; |
46 |
if (focused->window != NULL && |
47 |
- focused->window->needs_take_focus) { |
48 |
+ focused->window->needs_take_focus && |
49 |
+ focused->window->doesnt_accept_focus) { |
50 |
DLOG("Updating focus by sending WM_TAKE_FOCUS to window 0x%08x (focused: %p / %s)\n", |
51 |
to_focus, focused, focused->name); |
52 |
send_take_focus(to_focus); |
53 |
- set_focus = !focused->window->doesnt_accept_focus; |
54 |
- DLOG("set_focus = %d\n", set_focus); |
55 |
- } |
56 |
- |
57 |
- if (set_focus) { |
58 |
+ } else { |
59 |
DLOG("Updating focus (focused: %p / %s) to X11 window 0x%08x\n", focused, focused->name, to_focus); |
60 |
/* We remove XCB_EVENT_MASK_FOCUS_CHANGE from the event mask to get |
61 |
* no focus change events for our own focus changes. We only want |
b/testcases/t/158-wm_take_focus.t
66 |
@@ -30,7 +30,32 @@ subtest 'Window without WM_TAKE_FOCUS', sub { |
67 |
done_testing; |
68 |
}; |
69 |
|
70 |
-subtest 'Window with WM_TAKE_FOCUS', sub { |
71 |
+# Window managers do not conventionally send WM_TAKE_FOCUS to clients with the |
72 |
+# InputHint set (see issue #1167). |
73 |
+subtest 'Window with WM_TAKE_FOCUS and with InputHint set', sub { |
74 |
+ # XXX: This test relies on the fact that whenever a window is opened |
75 |
+ # without setting the WM_HINTS property on the window at all, i3 will treat |
76 |
+ # this window as if the InputHint were set. |
77 |
+ |
78 |
+ fresh_workspace; |
79 |
+ |
80 |
+ my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS'); |
81 |
+ |
82 |
+ my $window = open_window({ |
83 |
+ dont_map => 1, |
84 |
+ protocols => [ $take_focus ], |
85 |
+ }); |
86 |
+ |
87 |
+ $window->map; |
88 |
+ # sync_with_i3 will send a ClientMessage to i3 and receive one targeted to |
89 |
+ # $window->id. If it receives WM_TAKE_FOCUS instead, it will return 0, thus |
90 |
+ # the test will fail. |
91 |
+ ok(sync_with_i3(window_id => $window->id), 'did not receive ClientMessage'); |
92 |
+ |
93 |
+ done_testing; |
94 |
+}; |
95 |
+ |
96 |
+subtest 'Window with WM_TAKE_FOCUS and without InputHint', sub { |
97 |
fresh_workspace; |
98 |
|
99 |
my $take_focus = $x->atom(name => 'WM_TAKE_FOCUS'); |
100 |
@@ -40,6 +65,9 @@ subtest 'Window with WM_TAKE_FOCUS', sub { |
101 |
protocols => [ $take_focus ], |
102 |
}); |
103 |
|
104 |
+ # add an empty WM_HINTS property (InputHint will be unset) |
105 |
+ $window->add_hint(''); |
106 |
+ |
107 |
$window->map; |
108 |
|
109 |
ok(wait_for_event(1, sub { |