i3 - improved tiling WM


Fix scratchpad_show

Patch status: merged

Patch by Philippe Virouleau

Long description:

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

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

b/src/scratchpad.c

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

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

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