i3 - improved tiling WM


Fix problem when moving fullscreen window to scratchpad

Patch status: needinfo

Patch by jj

Long description:

When moving a fullscreen window to scratchpad with 'move scratchpad', the
focused window would stay fullscreen.

Also, when having a container in fullscreen mode and then focusing a child of
this container and moving it to scratchpad, it would enable fullscreen for
the child window.

This patch fixes both problems, so the scratchpad window is always floating.

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

b/src/scratchpad.c

23
@@ -39,6 +39,12 @@ void scratchpad_move(Con *con) {
24
         return;
25
     }
26
 
27
+    /* If the current con is in fullscreen mode, we need to disable that,
28
+     *  as a scratchpad window should never be in fullscreen mode */
29
+    if (focused && focused->type != CT_WORKSPACE && focused->fullscreen_mode != CF_NONE) {
30
+        con_toggle_fullscreen(focused, CF_OUTPUT);
31
+    }
32
+
33
     /* 1: Ensure the window or any parent is floating. From now on, we deal
34
      * with the CT_FLOATING_CON. We use automatic == false because the user
35
      * made the choice that this window should be a scratchpad (and floating).
36
@@ -78,16 +84,6 @@ void scratchpad_show(Con *con) {
37
     Con *__i3_scratch = workspace_get("__i3_scratch", NULL);
38
     Con *floating;
39
 
40
-    /* If the current con or any of its parents are in fullscreen mode, we
41
-     * first need to disable it before showing the scratchpad con. */
42
-    Con *fs = focused;
43
-    while (fs && fs->fullscreen_mode == CF_NONE)
44
-        fs = fs->parent;
45
-
46
-    if (fs->type != CT_WORKSPACE) {
47
-        con_toggle_fullscreen(focused, CF_OUTPUT);
48
-    }
49
-
50
     /* If this was 'scratchpad show' without criteria, we check if the
51
      * currently focused window is a scratchpad window and should be hidden
52
      * again. */
53
@@ -99,6 +95,16 @@ void scratchpad_show(Con *con) {
54
         return;
55
     }
56
 
57
+    /* If the current con or any of its parents are in fullscreen mode, we
58
+     * first need to disable it before showing the scratchpad con. */
59
+    Con *fs = focused;
60
+    while (fs && fs->fullscreen_mode == CF_NONE)
61
+        fs = fs->parent;
62
+
63
+    if (fs && fs->type != CT_WORKSPACE) {
64
+        con_toggle_fullscreen(fs, CF_OUTPUT);
65
+    }
66
+
67
     /* If this was 'scratchpad show' without criteria, we check if there is a
68
      * unfocused scratchpad on the current workspace and focus it */
69
     Con *walk_con;

b/testcases/t/206-fullscreen-scratchpad.t

75
@@ -0,0 +1,100 @@
76
+#!perl
77
+# vim:ts=4:sw=4:expandtab
78
+#
79
+# Please read the following documents before working on tests:
80
+# • http://build.i3wm.org/docs/testsuite.html
81
+#   (or docs/testsuite)
82
+#
83
+# • http://build.i3wm.org/docs/lib-i3test.html
84
+#   (alternatively: perldoc ./testcases/lib/i3test.pm)
85
+#
86
+# • http://build.i3wm.org/docs/ipc.html
87
+#   (or docs/ipc)
88
+#
89
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
90
+#   (unless you are already familiar with Perl)
91
+#
92
+#   Assure that no window is in fullscreen mode after showing a scratchpad window
93
+# Bug still in: 4.5.1-54-g0f6b5fe
94
+
95
+use i3test i3_autostart => 0;
96
+use List::Util qw(first);
97
+
98
+my $config = <<EOT;
99
+# i3 config file (v4)
100
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
101
+workspace_layout stacked
102
+EOT
103
+
104
+my $pid = launch_with_config($config);
105
+
106
+my $tmp = fresh_workspace;
107
+
108
+sub fullscreen_windows {
109
+    my $ws = $tmp;
110
+    $ws = shift if @_;
111
+
112
+    my $nodes = scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($ws)->[0]->{nodes}};
113
+    my $cons = scalar grep { $_->{fullscreen_mode} != 0 } @{get_ws_content($ws)};
114
+    return $nodes + $cons;
115
+}
116
+
117
+##########################################################################################
118
+# map two windows in one container, fullscreen one of them and then move it to scratchpad
119
+##########################################################################################
120
+
121
+my $first_win = open_window;
122
+my $second_win = open_window;
123
+
124
+# fullscreen the focused window
125
+cmd 'fullscreen';
126
+
127
+# see if the window really is in fullscreen mode
128
+is(fullscreen_windows(), 1, 'amount of fullscreen windows after enabling fullscreen');
129
+
130
+# move window to scratchpad
131
+cmd 'move scratchpad';
132
+
133
+###############################################################################
134
+# show the scratchpad window again; it should not be in fullscreen mode anymore
135
+###############################################################################
136
+
137
+# show window from scratchpad
138
+cmd 'scratchpad show';
139
+
140
+# switch window back to tiling mode
141
+cmd 'floating toggle';
142
+
143
+# see if no window is in fullscreen mode
144
+is(fullscreen_windows(), 0, 'amount of fullscreen windows after showing previously fullscreened scratchpad window');
145
+
146
+########################################################################################
147
+# move a window to scratchpad, focus parent container, make it fullscreen, focus a child
148
+########################################################################################
149
+
150
+# move one window to scratchpad
151
+cmd 'move scratchpad';
152
+
153
+# focus parent
154
+cmd 'focus parent';
155
+
156
+# fullscreen the container
157
+cmd 'fullscreen';
158
+
159
+# focus child
160
+cmd 'focus child';
161
+
162
+# see if the window really is in fullscreen mode
163
+is(fullscreen_windows(), 1, 'amount of fullscreen windows after enabling fullscreen on parent');
164
+
165
+##########################################################################
166
+# show a scratchpad window; no window should be in fullscreen mode anymore
167
+##########################################################################
168
+
169
+# show the scratchpad window
170
+cmd 'scratchpad show';
171
+
172
+# see if no window is in fullscreen mode
173
+is(fullscreen_windows(), 0, 'amount of fullscreen windows after showing a scratchpad window while a parent container was in fullscreen mode');
174
+
175
+done_testing;