i3 - improved tiling WM


Fix scratchpad_show Test if window is in scratchpad Test if function is called without criteria Updated testcase

Patch status: superseded

Patch by Philippe Virouleau

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

b/src/scratchpad.c

16
@@ -88,12 +88,23 @@ void scratchpad_show(Con *con) {
17
         con_toggle_fullscreen(focused, CF_OUTPUT);
18
     }
19
 
20
+    /* If this was 'scratchpad show' without criteria, we check if the
21
+     * currently focused window is a scratchpad window and should be hidden
22
+     * again. */
23
+    if (!con &&
24
+        (floating = con_inside_floating(focused)) &&
25
+        floating->scratchpad_state != SCRATCHPAD_NONE) {
26
+        DLOG("Focused window is a scratchpad window, hiding it.\n");
27
+        scratchpad_move(focused);
28
+        return;
29
+    }
30
+
31
     /* If this was 'scratchpad show' without criteria, we check if there is a
32
      * unfocused scratchpad on the current workspace and focus it */
33
     Con *walk_con;
34
     Con *focused_ws = con_get_workspace(focused);
35
     TAILQ_FOREACH(walk_con, &(focused_ws->floating_head), floating_windows) {
36
-        if ((floating = con_inside_floating(walk_con)) &&
37
+        if (!con && (floating = con_inside_floating(walk_con)) &&
38
             floating->scratchpad_state != SCRATCHPAD_NONE &&
39
             floating != con_inside_floating(focused)) {
40
                 DLOG("Found an unfocused scratchpad window on this workspace\n");
41
@@ -112,7 +123,7 @@ void scratchpad_show(Con *con) {
42
     focused_ws = con_get_workspace(focused);
43
     TAILQ_FOREACH(walk_con, &all_cons, all_cons) {
44
         Con *walk_ws = con_get_workspace(walk_con);
45
-        if (walk_ws &&
46
+        if (!con && walk_ws &&
47
             !con_is_internal(walk_ws) && focused_ws != walk_ws &&
48
             (floating = con_inside_floating(walk_con)) &&
49
             floating->scratchpad_state != SCRATCHPAD_NONE) {
50
@@ -123,14 +134,10 @@ void scratchpad_show(Con *con) {
51
         }
52
     }
53
 
54
-    /* If this was 'scratchpad show' without criteria, we check if the
55
-     * currently focused window is a scratchpad window and should be hidden
56
-     * again. */
57
-    if (!con &&
58
-        (floating = con_inside_floating(focused)) &&
59
-        floating->scratchpad_state != SCRATCHPAD_NONE) {
60
-        DLOG("Focused window is a scratchpad window, hiding it.\n");
61
-        scratchpad_move(focused);
62
+    /* If this was 'scratchpad show' with criteria, we check if the window
63
+     * is actually in the scratchpad */
64
+    if (con && con->parent->scratchpad_state == SCRATCHPAD_NONE) {
65
+        DLOG("Window is not in the scratchpad, doing nothing.\n");
66
         return;
67
     }
68
 

b/testcases/t/202-scratchpad-criteria.t

73
@@ -17,26 +17,35 @@
74
 # Verifies that using criteria to address scratchpad windows works.
75
 use i3test;
76
 
77
-################################################################################
78
+#####################################################################
79
 # Verify that using scratchpad show with criteria works as expected:
80
-# When matching a scratchpad window which is visible, it should hide it.
81
-# When matching a scratchpad window which is on __i3_scratch, it should show it.
82
-# When matching a non-scratchpad window, it should be a no-op.
83
-################################################################################
84
+# - When matching a scratchpad window which is visible,
85
+#   it should hide it.
86
+# - When matching a scratchpad window which is on __i3_scratch,
87
+#   it should show it.
88
+# - When matching a non-scratchpad window, it should be a no-op.
89
+# - When matching a scratchpad window,
90
+#   non-matching windows shouldn't appear
91
+######################################################################
92
 
93
 my $tmp = fresh_workspace;
94
 
95
 my $third_window = open_window(name => 'scratch-match');
96
 cmd 'move scratchpad';
97
 
98
-# Verify that using 'scratchpad show' without any matching windows is a no-op.
99
+#####################################################################
100
+# Verify that using 'scratchpad show' without any matching windows is
101
+# a no-op.
102
+#####################################################################
103
 my $old_focus = get_focused($tmp);
104
 
105
 cmd '[title="nomatch"] scratchpad show';
106
 
107
 is(get_focused($tmp), $old_focus, 'non-matching criteria have no effect');
108
 
109
+#####################################################################
110
 # Verify that we can use criteria to show a scratchpad window.
111
+#####################################################################
112
 cmd '[title="scratch-match"] scratchpad show';
113
 
114
 my $scratch_focus = get_focused($tmp);
115
@@ -47,12 +56,102 @@ cmd '[title="scratch-match"] scratchpad show';
116
 isnt(get_focused($tmp), $scratch_focus, 'matching criteria works');
117
 is(get_focused($tmp), $old_focus, 'focus restored');
118
 
119
+
120
+#####################################################################
121
 # Verify that we cannot use criteria to show a non-scratchpad window.
122
+#####################################################################
123
 my $tmp2 = fresh_workspace;
124
 my $non_scratch_window = open_window(name => 'non-scratch');
125
 cmd "workspace $tmp";
126
 is(get_focused($tmp), $old_focus, 'focus still ok');
127
-cmd '[title="non-match"] scratchpad show';
128
+cmd '[title="non-scratch"] scratchpad show';
129
 is(get_focused($tmp), $old_focus, 'focus unchanged');
130
 
131
+#####################################################################
132
+# Verify that non-matching windows doesn't appear
133
+#####################################################################
134
+# Subroutine to clear scratchpad
135
+sub clear_scratchpad {
136
+    while (scalar @{get_ws('__i3_scratch')->{floating_nodes}}) {
137
+        cmd 'scratchpad show';
138
+        cmd 'kill';
139
+    }
140
+}
141
+
142
+#Start from an empty fresh workspace
143
+my $empty_ws = fresh_workspace;
144
+cmd "workspace $empty_ws";
145
+
146
+my $no_focused = get_focused($empty_ws);
147
+cmd '[title="nothingmatchthistitle"] scratchpad show';
148
+#Check nothing match
149
+is(get_focused($empty_ws), $no_focused, "no window to focus on");
150
+
151
+clear_scratchpad;
152
+
153
+open_window(name => "my-scratch-window");
154
+my $w1_focus = get_focused($empty_ws);
155
+cmd 'move scratchpad';
156
+cmd '[title="my-scratch-window"] scratchpad show';
157
+#Check we created and shown a scratchpad window
158
+is(get_focused($empty_ws), $w1_focus, "focus on scratchpad window");
159
+
160
+#Switching workspace
161
+my $empty_ws2 = fresh_workspace;
162
+cmd "workspace $empty_ws2";
163
+open_window(name => "my-second-scratch-window");
164
+
165
+my $w2_focus = get_focused($empty_ws2);
166
+cmd 'move scratchpad';
167
+cmd '[title="my-second-scratch-window"] scratchpad show';
168
+
169
+#Check we got the correct window
170
+is(get_focused($empty_ws2), $w2_focus, "focus is on second window");
171
+
172
+#####################################################################
173
+# Verify that 'scratchpad show' correctly hide multiple scratchpad
174
+# windows
175
+#####################################################################
176
+clear_scratchpad;
177
+
178
+sub check_floating {
179
+    my($rws, $n) = @_;
180
+    my $ws = get_ws($rws);
181
+    is(scalar @{$ws->{nodes}}, 0, 'no windows on ws');
182
+    is(scalar @{$ws->{floating_nodes}}, $n, "$n floating windows on ws");
183
+}
184
+
185
+my $empty_ws3 = fresh_workspace;
186
+cmd "workspace $empty_ws3";
187
+
188
+check_floating($empty_ws3, 0);
189
+
190
+#Creating two scratchpad windows
191
+open_window(name => "toggle-1");
192
+cmd 'move scratchpad';
193
+open_window(name => "toggle-2");
194
+cmd 'move scratchpad';
195
+check_floating($empty_ws3, 0);
196
+#Showing both
197
+cmd '[title="toggle-"] scratchpad show';
198
+
199
+check_floating($empty_ws3, 2);
200
+
201
+#Hiding both
202
+cmd '[title="toggle-"] scratchpad show';
203
+check_floating($empty_ws3, 0);
204
+
205
+#Showing both again
206
+cmd '[title="toggle-"] scratchpad show';
207
+check_floating($empty_ws3, 2);
208
+
209
+
210
+#Hiding one
211
+cmd 'scratchpad show';
212
+check_floating($empty_ws3, 1);
213
+
214
+#Hiding the last
215
+cmd 'scratchpad show';
216
+check_floating($empty_ws3, 0);
217
+
218
 done_testing;