]> git.lizzy.rs Git - bspwm.git/blob - restore.c
Restore the tiled rectangles of nodes and clients
[bspwm.git] / restore.c
1 /* Copyright (c) 2012, Bastien Dejean
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this
8  *    list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
17  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include <ctype.h>
26 #include <string.h>
27 #include "bspwm.h"
28 #include "desktop.h"
29 #include "ewmh.h"
30 #include "history.h"
31 #include "monitor.h"
32 #include "query.h"
33 #include "stack.h"
34 #include "tree.h"
35 #include "settings.h"
36 #include "restore.h"
37
38 void restore_tree(char *file_path)
39 {
40         if (file_path == NULL)
41                 return;
42
43         FILE *snapshot = fopen(file_path, "r");
44         if (snapshot == NULL) {
45                 warn("Restore tree: can't open '%s'.\n", file_path);
46                 return;
47         }
48
49         PUTS("restore tree");
50
51         char line[MAXLEN];
52         char name[MAXLEN];
53         coordinates_t loc;
54         monitor_t *m = NULL;
55         desktop_t *d = NULL;
56         node_t *n = NULL;
57         unsigned int level, last_level = 0;
58
59         while (fgets(line, sizeof(line), snapshot) != NULL) {
60                 unsigned int len = strlen(line);
61                 level = 0;
62
63                 while (level < len && isspace(line[level]))
64                         level++;
65
66                 if (level == 0) {
67                         int x, y, top, right, bottom, left;
68                         unsigned int w, h;
69                         char end = 0;
70                         name[0] = '\0';
71                         sscanf(line + level, "%s %ux%u%i%i %i,%i,%i,%i %c", name, &w, &h, &x, &y,
72                                &top, &right, &bottom, &left, &end);
73                         m = find_monitor(name);
74                         if (m == NULL)
75                                 continue;
76                         m->rectangle = (xcb_rectangle_t) {x, y, w, h};
77                         m->top_padding = top;
78                         m->right_padding = right;
79                         m->bottom_padding = bottom;
80                         m->left_padding = left;
81                         if (end != 0)
82                                 mon = m;
83                 } else if (level == 1) {
84                         if (m == NULL)
85                                 continue;
86                         int wg, top, right, bottom, left;
87                         unsigned int bw;
88                         char floating, layout = 0, end = 0;
89                         name[0] = '\0';
90                         loc.desktop = NULL;
91                         sscanf(line + level, "%s %u %i %i,%i,%i,%i %c %c %c", name,
92                                &bw, &wg, &top, &right, &bottom, &left, &layout, &floating, &end);
93                         locate_desktop(name, &loc);
94                         d = loc.desktop;
95                         if (d == NULL) {
96                                 continue;
97                         }
98                         d->border_width = bw;
99                         d->window_gap = wg;
100                         d->top_padding = top;
101                         d->right_padding = right;
102                         d->bottom_padding = bottom;
103                         d->left_padding = left;
104                         if (layout == 'M') {
105                                 d->layout = LAYOUT_MONOCLE;
106                         } else if (layout == 'T') {
107                                 d->layout = LAYOUT_TILED;
108                         }
109                         if (end != 0) {
110                                 m->desk = d;
111                         }
112                 } else {
113                         if (m == NULL || d == NULL)
114                                 continue;
115                         node_t *birth = make_node();
116                         if (level == 2) {
117                                 empty_desktop(d);
118                                 d->root = birth;
119                         } else if (n != NULL) {
120                                 if (level > last_level) {
121                                         n->first_child = birth;
122                                 } else {
123                                         do {
124                                                 n = n->parent;
125                                         } while (n != NULL && n->second_child != NULL);
126                                         if (n == NULL)
127                                                 continue;
128                                         n->second_child = birth;
129                                 }
130                                 birth->parent = n;
131                         }
132                         n = birth;
133                         char birth_rotation;
134                         if (isupper(line[level])) {
135                                 char split_type;
136                                 sscanf(line + level, "%c %c %lf", &split_type, &birth_rotation, &n->split_ratio);
137                                 if (split_type == 'H') {
138                                         n->split_type = TYPE_HORIZONTAL;
139                                 } else if (split_type == 'V') {
140                                         n->split_type = TYPE_VERTICAL;
141                                 }
142                         } else {
143                                 client_t *c = make_client(XCB_NONE, d->border_width);
144                                 num_clients++;
145                                 char urgent, locked, sticky, private, split_dir, split_mode, state, layer, end = 0;
146                                 sscanf(line + level, "%c %s %s %X %u %hux%hu%hi%hi %c%c %c%c %c%c%c%c %c", &birth_rotation,
147                                        c->class_name, c->instance_name, &c->window, &c->border_width,
148                                        &c->floating_rectangle.width, &c->floating_rectangle.height,
149                                        &c->floating_rectangle.x, &c->floating_rectangle.y,
150                                        &split_dir, &split_mode, &state, &layer,
151                                        &urgent, &locked, &sticky, &private, &end);
152                                 n->split_mode = (split_mode == '-' ? MODE_AUTOMATIC : MODE_MANUAL);
153                                 if (split_dir == 'U') {
154                                         n->split_dir = DIR_UP;
155                                 } else if (split_dir == 'R') {
156                                         n->split_dir = DIR_RIGHT;
157                                 } else if (split_dir == 'D') {
158                                         n->split_dir = DIR_DOWN;
159                                 } else if (split_dir == 'L') {
160                                         n->split_dir = DIR_LEFT;
161                                 }
162                                 if (state == 'f') {
163                                         c->state = STATE_FLOATING;
164                                 } else if (state == 'F') {
165                                         c->state = STATE_FULLSCREEN;
166                                 } else if (state == 'p') {
167                                         c->state = STATE_PSEUDO_TILED;
168                                 }
169                                 if (layer == 'b') {
170                                         c->layer = LAYER_BELOW;
171                                 } else if (layer == 'a') {
172                                         c->layer = LAYER_ABOVE;
173                                 }
174                                 c->urgent = (urgent == '-' ? false : true);
175                                 c->locked = (locked == '-' ? false : true);
176                                 c->sticky = (sticky == '-' ? false : true);
177                                 c->private = (private == '-' ? false : true);
178                                 n->client = c;
179                                 if (end != 0) {
180                                         d->focus = n;
181                                 }
182                                 if (c->sticky) {
183                                         m->num_sticky++;
184                                 }
185                         }
186                         if (birth_rotation == 'a') {
187                                 n->birth_rotation = 90;
188                         } else if (birth_rotation == 'c') {
189                                 n->birth_rotation = 270;
190                         } else if (birth_rotation == 'm') {
191                                 n->birth_rotation = 0;
192                         }
193                 }
194                 last_level = level;
195         }
196
197         fclose(snapshot);
198
199         for (monitor_t *m = mon_head; m != NULL; m = m->next) {
200                 for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
201                         for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
202                                 uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
203                                 xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
204                                 if (!IS_TILED(n->client)) {
205                                         n->vacant = true;
206                                         update_vacant_state(n->parent);
207                                 }
208                                 if (n->client->private) {
209                                         update_privacy_level(n, true);
210                                 }
211                         }
212                         /* Has the side effect of restoring the node's rectangles and the client's tiled rectangles */
213                         arrange(m, d);
214                 }
215         }
216
217         ewmh_update_current_desktop();
218 }
219
220 void restore_history(char *file_path)
221 {
222         if (file_path == NULL)
223                 return;
224
225         FILE *snapshot = fopen(file_path, "r");
226         if (snapshot == NULL) {
227                 warn("Restore history: can't open '%s'.\n", file_path);
228                 return;
229         }
230
231         PUTS("restore history");
232
233         char line[MAXLEN];
234         char mnm[SMALEN];
235         char dnm[SMALEN];
236         xcb_window_t win;
237
238         while (fgets(line, sizeof(line), snapshot) != NULL) {
239                 if (sscanf(line, "%s %s %X", mnm, dnm, &win) == 3) {
240                         coordinates_t loc;
241                         if (win != XCB_NONE && !locate_window(win, &loc)) {
242                                 warn("Can't locate window 0x%X.\n", win);
243                                 continue;
244                         }
245                         node_t *n = (win == XCB_NONE ? NULL : loc.node);
246                         if (!locate_desktop(dnm, &loc)) {
247                                 warn("Can't locate desktop '%s'.\n", dnm);
248                                 continue;
249                         }
250                         desktop_t *d = loc.desktop;
251                         if (!locate_monitor(mnm, &loc)) {
252                                 warn("Can't locate monitor '%s'.\n", mnm);
253                                 continue;
254                         }
255                         monitor_t *m = loc.monitor;
256                         history_add(m, d, n);
257                 } else {
258                         warn("Can't parse history entry: '%s'\n", line);
259                 }
260         }
261
262         fclose(snapshot);
263 }
264
265 void restore_stack(char *file_path)
266 {
267         if (file_path == NULL)
268                 return;
269
270         FILE *snapshot = fopen(file_path, "r");
271         if (snapshot == NULL) {
272                 warn("Restore stack: can't open '%s'.\n", file_path);
273                 return;
274         }
275
276         PUTS("restore stack");
277
278         char line[MAXLEN];
279         xcb_window_t win;
280
281         while (fgets(line, sizeof(line), snapshot) != NULL) {
282                 if (sscanf(line, "%X", &win) == 1) {
283                         coordinates_t loc;
284                         if (locate_window(win, &loc))
285                                 stack_insert_after(stack_tail, loc.node);
286                         else
287                                 warn("Can't locate window 0x%X.\n", win);
288                 } else {
289                         warn("Can't parse stack entry: '%s'\n", line);
290                 }
291         }
292
293         fclose(snapshot);
294 }