i3 - improved tiling WM


Implement the window::urgent event

Patch status: needinfo

Patch by Tony Crisci

Long description:

The window::urgent event is emitted when a container becomes urgent or
loses its urgent status.

To apply this patch, use:
curl http://cr.i3wm.org/patch/589/raw.patch | git am

b/src/con.c

18
@@ -231,6 +231,7 @@ void con_focus(Con *con) {
19
         con->urgent = false;
20
         con_update_parents_urgency(con);
21
         workspace_update_urgent_flag(con_get_workspace(con));
22
+        ipc_send_window_event("urgent", con);
23
     }
24
 }
25
 
26
@@ -1580,6 +1581,9 @@ void con_set_urgency(Con *con, bool urgent) {
27
         return;
28
     }
29
 
30
+    if (con->urgent == urgent)
31
+        return;
32
+
33
     if (con->urgency_timer == NULL) {
34
         con->urgent = urgent;
35
     } else
36
@@ -1597,14 +1601,16 @@ void con_set_urgency(Con *con, bool urgent) {
37
 
38
     con_update_parents_urgency(con);
39
 
40
-    if (con->urgent == urgent)
41
-        LOG("Urgency flag changed to %d\n", con->urgent);
42
-
43
     Con *ws;
44
     /* Set the urgency flag on the workspace, if a workspace could be found
45
      * (for dock clients, that is not the case). */
46
     if ((ws = con_get_workspace(con)) != NULL)
47
         workspace_update_urgent_flag(ws);
48
+
49
+    if (con->urgent == urgent) {
50
+        LOG("Urgency flag changed to %d\n", con->urgent);
51
+        ipc_send_window_event("urgent", con);
52
+    }
53
 }
54
 
55
 /*

b/src/workspace.c

60
@@ -325,11 +325,14 @@ static void workspace_reassign_sticky(Con *con) {
61
 static void workspace_defer_update_urgent_hint_cb(EV_P_ ev_timer *w, int revents) {
62
     Con *con = w->data;
63
 
64
-    DLOG("Resetting urgency flag of con %p by timer\n", con);
65
-    con->urgent = false;
66
-    con_update_parents_urgency(con);
67
-    workspace_update_urgent_flag(con_get_workspace(con));
68
-    tree_render();
69
+    if (con->urgent) {
70
+        DLOG("Resetting urgency flag of con %p by timer\n", con);
71
+        con->urgent = false;
72
+        con_update_parents_urgency(con);
73
+        workspace_update_urgent_flag(con_get_workspace(con));
74
+        ipc_send_window_event("urgent", con);
75
+        tree_render();
76
+    }
77
 
78
     ev_timer_stop(main_loop, con->urgency_timer);
79
     FREE(con->urgency_timer);
80
@@ -385,6 +388,7 @@ static void _workspace_show(Con *workspace) {
81
      * focus and thereby immediately destroy it */
82
     if (next->urgent && (int)(config.workspace_urgency_timer * 1000) > 0) {
83
         /* focus for now… */
84
+        next->urgent = false;
85
         con_focus(next);
86
 
87
         /* … but immediately reset urgency flags; they will be set to false by

b/testcases/t/231-ipc-window-urgent.t

93
@@ -0,0 +1,67 @@
94
+#!perl
95
+# vim:ts=4:sw=4:expandtab
96
+#
97
+# Please read the following documents before working on tests:
98
+# • http://build.i3wm.org/docs/testsuite.html
99
+#   (or docs/testsuite)
100
+#
101
+# • http://build.i3wm.org/docs/lib-i3test.html
102
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
103
+#
104
+# • http://build.i3wm.org/docs/ipc.html
105
+#   (or docs/ipc)
106
+#
107
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
108
+#   (unless you are already familiar with Perl)
109
+#
110
+# Test that the window::urgent event works correctly
111
+# Bug still in: 4.8-8-g20f1c92
112
+use i3test;
113
+
114
+my $config = <<EOT;
115
+# i3 config file (v4)
116
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
117
+
118
+force_display_urgency_hint 0ms
119
+EOT
120
+
121
+my $i3 = i3(get_socket_path());
122
+$i3->connect()->recv;
123
+
124
+my $cv;
125
+$i3->subscribe({
126
+    window => sub {
127
+        my ($event) = @_;
128
+        $cv->send($event) if $event->{change} eq 'urgent';
129
+    }
130
+})->recv;
131
+
132
+my $t;
133
+$t = AnyEvent->timer(
134
+    after => 0.5,
135
+    cb => sub {
136
+        $cv->send(0);
137
+    }
138
+);
139
+
140
+$cv = AnyEvent->condvar;
141
+fresh_workspace;
142
+my $win = open_window;
143
+my $dummy_win = open_window;
144
+
145
+$win->add_hint('urgency');
146
+my $event = $cv->recv;
147
+
148
+isnt($event, 0, 'an urgent con should emit the window::urgent event');
149
+is($event->{container}->{window}, $win->{id}, 'the event should contain information about the window');
150
+is($event->{container}->{urgent}, 1, 'the container should be urgent');
151
+
152
+$cv = AnyEvent->condvar;
153
+$win->delete_hint('urgency');
154
+my $event = $cv->recv;
155
+
156
+isnt($event, 0, 'an urgent con should emit the window::urgent event');
157
+is($event->{container}->{window}, $win->{id}, 'the event should contain information about the window');
158
+is($event->{container}->{urgent}, 0, 'the container should not be urgent');
159
+
160
+done_testing;