Add support for _NET_WM_STATE_DEMANDS_ATTENTION.
Patch status: needinfo
Patch by oblique
Long description:
_NET_WM_STATE_DEMANDS_ATTENTION indicates that some action in or with the window happened. It's a weaker hint than urgency flag of WM_HINTS, but some applications and almost all Qt applications use it instead of WM_HINTS' urgency flag (one example is Skype).
To apply this patch, use:
curl http://cr.i3wm.org/patch/60/raw.patch | git am
b/docs/hacking-howto
19 |
@@ -28,7 +28,8 @@ In the case of i3, the tasks (and order of them) are the following: |
20 |
the first client of X) and manage them (reparent them, create window |
21 |
decorations, etc.) |
22 |
. When new windows are created, manage them |
23 |
-. Handle the client’s `_WM_STATE` property, but only the `_WM_STATE_FULLSCREEN` |
24 |
+. Handle the client’s `_WM_STATE` property, but only `_WM_STATE_FULLSCREEN` and |
25 |
+ `_NET_WM_STATE_DEMANDS_ATTENTION` |
26 |
. Handle the client’s `WM_NAME` property |
27 |
. Handle the client’s size hints to display them proportionally |
28 |
. Handle the client’s urgency hint |
b/include/atoms.xmacro
33 |
@@ -2,6 +2,7 @@ xmacro(_NET_SUPPORTED) |
34 |
xmacro(_NET_SUPPORTING_WM_CHECK) |
35 |
xmacro(_NET_WM_NAME) |
36 |
xmacro(_NET_WM_STATE_FULLSCREEN) |
37 |
+xmacro(_NET_WM_STATE_DEMANDS_ATTENTION) |
38 |
xmacro(_NET_WM_STATE) |
39 |
xmacro(_NET_WM_WINDOW_TYPE) |
40 |
xmacro(_NET_WM_WINDOW_TYPE_DOCK) |
b/src/handlers.c
45 |
@@ -619,10 +619,10 @@ static void handle_client_message(xcb_client_message_event_t *event) { |
46 |
|
47 |
LOG("ClientMessage for window 0x%08x\n", event->window); |
48 |
if (event->type == A__NET_WM_STATE) { |
49 |
- if (event->format != 32 || event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN) { |
50 |
- DLOG("atom in clientmessage is %d, fullscreen is %d\n", |
51 |
- event->data.data32[1], A__NET_WM_STATE_FULLSCREEN); |
52 |
- DLOG("not about fullscreen atom\n"); |
53 |
+ if (event->format != 32 || |
54 |
+ (event->data.data32[1] != A__NET_WM_STATE_FULLSCREEN && |
55 |
+ event->data.data32[1] != A__NET_WM_STATE_DEMANDS_ATTENTION)) { |
56 |
+ DLOG("Unknown atom in clientmessage of type %d\n", event->data.data32[1]); |
57 |
return; |
58 |
} |
59 |
|
60 |
@@ -632,15 +632,52 @@ static void handle_client_message(xcb_client_message_event_t *event) { |
61 |
return; |
62 |
} |
63 |
|
64 |
- /* Check if the fullscreen state should be toggled */ |
65 |
- if ((con->fullscreen_mode != CF_NONE && |
66 |
- (event->data.data32[0] == _NET_WM_STATE_REMOVE || |
67 |
- event->data.data32[0] == _NET_WM_STATE_TOGGLE)) || |
68 |
- (con->fullscreen_mode == CF_NONE && |
69 |
- (event->data.data32[0] == _NET_WM_STATE_ADD || |
70 |
- event->data.data32[0] == _NET_WM_STATE_TOGGLE))) { |
71 |
- DLOG("toggling fullscreen\n"); |
72 |
- con_toggle_fullscreen(con, CF_OUTPUT); |
73 |
+ if (event->data.data32[1] == A__NET_WM_STATE_FULLSCREEN) { |
74 |
+ /* Check if the fullscreen state should be toggled */ |
75 |
+ if ((con->fullscreen_mode != CF_NONE && |
76 |
+ (event->data.data32[0] == _NET_WM_STATE_REMOVE || |
77 |
+ event->data.data32[0] == _NET_WM_STATE_TOGGLE)) || |
78 |
+ (con->fullscreen_mode == CF_NONE && |
79 |
+ (event->data.data32[0] == _NET_WM_STATE_ADD || |
80 |
+ event->data.data32[0] == _NET_WM_STATE_TOGGLE))) { |
81 |
+ DLOG("toggling fullscreen\n"); |
82 |
+ con_toggle_fullscreen(con, CF_OUTPUT); |
83 |
+ } |
84 |
+ } else if (event->data.data32[1] == A__NET_WM_STATE_DEMANDS_ATTENTION) { |
85 |
+ bool urgent; |
86 |
+ |
87 |
+ /* Check if the urgent flag must be set */ |
88 |
+ if (event->data.data32[0] == _NET_WM_STATE_ADD) |
89 |
+ urgent = true; |
90 |
+ else if (event->data.data32[0] == _NET_WM_STATE_REMOVE) |
91 |
+ urgent = false; |
92 |
+ else if (event->data.data32[0] == _NET_WM_STATE_TOGGLE) |
93 |
+ urgent = !con->urgent; |
94 |
+ |
95 |
+ if (con->urgency_timer == NULL) { |
96 |
+ con->urgent = urgent; |
97 |
+ } else |
98 |
+ DLOG("Discarding urgency WM_HINT because timer is running\n"); |
99 |
+ |
100 |
+ //CLIENT_LOG(con); |
101 |
+ if (con->window) { |
102 |
+ if (con->urgent) { |
103 |
+ gettimeofday(&con->window->urgent, NULL); |
104 |
+ } else { |
105 |
+ con->window->urgent.tv_sec = 0; |
106 |
+ con->window->urgent.tv_usec = 0; |
107 |
+ } |
108 |
+ } |
109 |
+ |
110 |
+ con_update_parents_urgency(con); |
111 |
+ |
112 |
+ LOG("Urgency flag changed to %d\n", con->urgent); |
113 |
+ |
114 |
+ Con *ws; |
115 |
+ /* Set the urgency flag on the workspace, if a workspace could be found |
116 |
+ * (for dock clients, that is not the case). */ |
117 |
+ if ((ws = con_get_workspace(con)) != NULL) |
118 |
+ workspace_update_urgent_flag(ws); |
119 |
} |
120 |
|
121 |
tree_render(); |
122 |
@@ -1094,7 +1131,7 @@ void handle_event(int type, xcb_generic_event_t *event) { |
123 |
|
124 |
/* Client message are sent to the root window. The only interesting |
125 |
* client message for us is _NET_WM_STATE, we honour |
126 |
- * _NET_WM_STATE_FULLSCREEN */ |
127 |
+ * _NET_WM_STATE_FULLSCREEN and _NET_WM_STATE_DEMANDS_ATTENTION */ |
128 |
case XCB_CLIENT_MESSAGE: |
129 |
handle_client_message((xcb_client_message_event_t*)event); |
130 |
break; |