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; |