i3 - improved tiling WM


adjust window in scratchpad at move time

Patch status: needinfo

Patch by Vivien Didelot

Long description:

The first aim of this patch was to prevent i3 from resizing an already
floating window when moved to the scratchpad workspace.
Indeed, an user may adjust a small media player to his/her liking, move
it to scratchpad, then doesn't want i3 to readjust it.

Currently, the resizing of (every) scratchpad windows is done at show
time (in the scratchpad_show() function).
To be able to check if the window was not already floating and readjust
it accordingly, this patch moves the readjusting code from the show
function to the move function (scratchpad_move()).

This has the side-effect to make the SCRATCHPAD_FRESH state obsolete.
Consequently, this patch removes this fresh state and renames the state
SCRATCHPAD_CHANGED to SCRATCHPAD_ENABLED for relevance.

Reported-by: Julien Bonjean <julien.bonjean@savoirfairelinux.com>

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

b/include/data.h

33
@@ -571,8 +571,7 @@ struct Con {
34
 
35
     enum {
36
         SCRATCHPAD_NONE = 0,
37
-        SCRATCHPAD_FRESH = 1,
38
-        SCRATCHPAD_CHANGED = 2
39
+        SCRATCHPAD_ENABLED = 1
40
     } scratchpad_state;
41
 
42
     /* The ID of this container before restarting. Necessary to correctly

b/src/ipc.c

47
@@ -170,11 +170,8 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
48
         case SCRATCHPAD_NONE:
49
             ystr("none");
50
             break;
51
-        case SCRATCHPAD_FRESH:
52
-            ystr("fresh");
53
-            break;
54
-        case SCRATCHPAD_CHANGED:
55
-            ystr("changed");
56
+        case SCRATCHPAD_ENABLED:
57
+            ystr("enabled");
58
             break;
59
     }
60
 

b/src/load_layout.c

65
@@ -248,10 +248,8 @@ static int json_string(void *ctx, const unsigned char *val, unsigned int len) {
66
             sasprintf(&buf, "%.*s", (int)len, val);
67
             if (strcasecmp(buf, "none") == 0)
68
                 json_node->scratchpad_state = SCRATCHPAD_NONE;
69
-            else if (strcasecmp(buf, "fresh") == 0)
70
-                json_node->scratchpad_state = SCRATCHPAD_FRESH;
71
-            else if (strcasecmp(buf, "changed") == 0)
72
-                json_node->scratchpad_state = SCRATCHPAD_CHANGED;
73
+            else if (strcasecmp(buf, "enabled") == 0)
74
+                json_node->scratchpad_state = SCRATCHPAD_ENABLED;
75
             free(buf);
76
         }
77
     }

b/src/scratchpad.c

82
@@ -57,11 +57,22 @@ void scratchpad_move(Con *con) {
83
     con_move_to_workspace(con, __i3_scratch, true, true);
84
 
85
     /* 3: If this is the first time this window is used as a scratchpad, we set
86
-     * the scratchpad_state to SCRATCHPAD_FRESH. The window will then be
87
-     * adjusted in size according to what the user specifies. */
88
+     * the scratchpad_state to SCRATCHPAD_ENABLED. If it was not already
89
+     * floating, we adjust its size according to what the user specifies. */
90
     if (con->scratchpad_state == SCRATCHPAD_NONE) {
91
         DLOG("This window was never used as a scratchpad before.\n");
92
-        con->scratchpad_state = SCRATCHPAD_FRESH;
93
+        con->scratchpad_state = SCRATCHPAD_ENABLED;
94
+
95
+        if (!maybe_floating_con) {
96
+            DLOG("Adjusting size of this window.\n");
97
+            Con *output = con_get_output(con);
98
+            con->rect.width = output->rect.width * 0.5;
99
+            con->rect.height = output->rect.height * 0.75;
100
+            con->rect.x = output->rect.x +
101
+                ((output->rect.width / 2.0) - (con->rect.width / 2.0));
102
+            con->rect.y = output->rect.y +
103
+                ((output->rect.height / 2.0) - (con->rect.height / 2.0));
104
+        }
105
     }
106
 
107
     /* 4: Fix focus. Normally, when moving a window to a different output, the
108
@@ -153,22 +164,9 @@ void scratchpad_show(Con *con) {
109
         }
110
     }
111
 
112
-    /* 1: Move the window from __i3_scratch to the current workspace. */
113
+    /* Move the window from __i3_scratch to the current workspace. */
114
     con_move_to_workspace(con, active, true, false);
115
 
116
-    /* 2: Adjust the size if this window was not adjusted yet. */
117
-    if (con->scratchpad_state == SCRATCHPAD_FRESH) {
118
-        DLOG("Adjusting size of this window.\n");
119
-        Con *output = con_get_output(con);
120
-        con->rect.width = output->rect.width * 0.5;
121
-        con->rect.height = output->rect.height * 0.75;
122
-        con->rect.x = output->rect.x +
123
-                      ((output->rect.width / 2.0) - (con->rect.width / 2.0));
124
-        con->rect.y = output->rect.y +
125
-                      ((output->rect.height / 2.0) - (con->rect.height / 2.0));
126
-        con->scratchpad_state = SCRATCHPAD_CHANGED;
127
-    }
128
-
129
     /* Activate active workspace if window is from another workspace to ensure
130
      * proper focus. */
131
     if (current != active) {

b/testcases/t/185-scratchpad.t

136
@@ -109,7 +109,7 @@ is(scalar @scratch_nodes, 1, '__i3_scratch contains our window');
137
 ($nodes, $focus) = get_ws_content($tmp);
138
 is(scalar @$nodes, 0, 'no window on current ws anymore');
139
 
140
-is($scratch_nodes[0]->{scratchpad_state}, 'fresh', 'scratchpad_state fresh');
141
+is($scratch_nodes[0]->{scratchpad_state}, 'enabled', 'scratchpad_state enabled');
142
 
143
 $tree = $i3->get_tree->recv;
144
 my $__i3 = first { $_->{name} eq '__i3' } @{$tree->{nodes}};
145
@@ -165,7 +165,7 @@ $__i3_scratch = get_ws('__i3_scratch');
146
 @scratch_nodes = @{$__i3_scratch->{floating_nodes}};
147
 is(scalar @scratch_nodes, 1, '__i3_scratch contains our window');
148
 
149
-is($scratch_nodes[0]->{scratchpad_state}, 'changed', 'scratchpad_state changed');
150
+is($scratch_nodes[0]->{scratchpad_state}, 'enabled', 'scratchpad_state enabled');
151
 
152
 ################################################################################
153
 # 6: Verify that repeated 'scratchpad show' cycle through the stack, that is,
154
@@ -180,18 +180,13 @@ $__i3_scratch = get_ws('__i3_scratch');
155
 @scratch_nodes = @{$__i3_scratch->{floating_nodes}};
156
 is(scalar @scratch_nodes, 2, '__i3_scratch contains both windows');
157
 
158
-is($scratch_nodes[0]->{scratchpad_state}, 'changed', 'changed window first');
159
-is($scratch_nodes[1]->{scratchpad_state}, 'fresh', 'fresh window is second');
160
-
161
-my $changed_id = $scratch_nodes[0]->{nodes}->[0]->{id};
162
-my $fresh_id = $scratch_nodes[1]->{nodes}->[0]->{id};
163
-is($scratch_nodes[0]->{id}, $__i3_scratch->{focus}->[0], 'changed window first');
164
-is($scratch_nodes[1]->{id}, $__i3_scratch->{focus}->[1], 'fresh window second');
165
+my $first_id = $scratch_nodes[0]->{nodes}->[0]->{id};
166
+my $second_id = $scratch_nodes[1]->{nodes}->[0]->{id};
167
 
168
 # Repeatedly use 'scratchpad show' and check that the windows are different.
169
 cmd 'scratchpad show';
170
 
171
-is(get_focused($tmp), $changed_id, 'focus changed');
172
+is(get_focused($tmp), $first_id, 'focus changed');
173
 
174
 $ws = get_ws($tmp);
175
 $scratchrect = $ws->{floating_nodes}->[0]->{rect};
176
@@ -206,15 +201,15 @@ is($scratchrect->{y},
177
 
178
 cmd 'scratchpad show';
179
 
180
-isnt(get_focused($tmp), $changed_id, 'focus changed');
181
+isnt(get_focused($tmp), $first_id, 'focus changed');
182
 
183
 cmd 'scratchpad show';
184
 
185
-is(get_focused($tmp), $fresh_id, 'focus changed');
186
+is(get_focused($tmp), $second_id, 'focus changed');
187
 
188
 cmd 'scratchpad show';
189
 
190
-isnt(get_focused($tmp), $fresh_id, 'focus changed');
191
+isnt(get_focused($tmp), $second_id, 'focus changed');
192
 
193
 ################################################################################
194
 # 8: Show it, move it around, hide it. Verify that the position is retained
195
@@ -274,7 +269,7 @@ cmd '[title="scratch-match"] scratchpad show';
196
 $ws = get_ws($tmp);
197
 is(scalar @{$ws->{nodes}}, 1, 'still precisely one window on current ws');
198
 is(scalar @{$ws->{floating_nodes}}, 1, 'precisely one floating windows on current ws');
199
-is($ws->{floating_nodes}->[0]->{scratchpad_state}, 'changed', 'scratchpad_state is "changed"');
200
+is($ws->{floating_nodes}->[0]->{scratchpad_state}, 'enabled', 'scratchpad_state is "enabled"');
201
 
202
 ################################################################################
203
 # 10: on an empty workspace, ensure the 'move scratchpad' command does nothing