* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <fcntl.h>
#include "bspwm.h"
#include "desktop.h"
#include "ewmh.h"
#include "tree.h"
#include "settings.h"
#include "restore.h"
-#include "helpers.h"
-#include "common.h"
+#include "window.h"
#include "parse.h"
-#include "jsmn.h"
bool restore_tree(const char *file_path)
{
return false;
}
+ int num = tokens[0].size;
+
+ if (num < 1) {
+ free(tokens);
+ free(json);
+
+ return false;
+ }
+
+ mon = NULL;
while (mon_head != NULL) {
remove_monitor(mon_head);
}
- int num = tokens[0].size;
jsmntok_t *t = tokens + 1;
- char *focusedMonitorName = NULL;
+ char *focusedMonitorName = NULL, *primaryMonitorName = NULL;
for (int i = 0; i < num; i++) {
if (keyeq("focusedMonitorName", t, json)) {
- focusedMonitorName = copy_string(t+1, json);
+ free(focusedMonitorName);
t++;
- } else if (keyeq("numClients", t, json)) {
+ focusedMonitorName = copy_string(json + t->start, t->end - t->start);
+ } else if (keyeq("primaryMonitorName", t, json)) {
+ free(primaryMonitorName);
t++;
- sscanf(json + t->start, "%u", &num_clients);
+ primaryMonitorName = copy_string(json + t->start, t->end - t->start);
+ } else if (keyeq("clientsCount", t, json)) {
+ t++;
+ sscanf(json + t->start, "%u", &clients_count);
} else if (keyeq("monitors", t, json)) {
t++;
int s = t->size;
t++;
for (int j = 0; j < s; j++) {
monitor_t *m = restore_monitor(&t, json);
+ if (m->desk == NULL) {
+ add_desktop(m, make_desktop(NULL, XCB_NONE));
+ }
add_monitor(m);
- t++;
}
+ continue;
+ } else if (keyeq("focusHistory", t, json)) {
+ t++;
+ restore_history(&t, json);
+ continue;
+ } else if (keyeq("stackingList", t, json)) {
+ t++;
+ restore_stack(&t, json);
+ continue;
}
t++;
}
}
}
+ if (primaryMonitorName != NULL) {
+ coordinates_t loc;
+ if (locate_monitor(primaryMonitorName, &loc)) {
+ pri_mon = loc.monitor;
+ }
+ }
+
free(focusedMonitorName);
+ free(primaryMonitorName);
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ refresh_presel_feebacks_in(d->root, d, m);
+ restack_presel_feedback(d);
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
+ if (n->client == NULL) {
+ continue;
+ }
uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
- xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
+ xcb_change_window_attributes(dpy, n->id, XCB_CW_EVENT_MASK, values);
}
}
}
- ewmh_update_client_list();
+ ewmh_update_client_list(false);
+ ewmh_update_client_list(true);
+ ewmh_update_active_window();
ewmh_update_number_of_desktops();
ewmh_update_current_desktop();
ewmh_update_desktop_names();
return true;
}
-#define RESTORE_INT(o, k, p) \
+#define RESTORE_INT(k, p) \
} else if (keyeq(#k, *t, json)) { \
(*t)++; \
- sscanf(json + (*t)->start, "%i", &o->p);
+ sscanf(json + (*t)->start, "%i", p);
-#define RESTORE_UINT(o, k, p) \
+#define RESTORE_UINT(k, p) \
} else if (keyeq(#k, *t, json)) { \
(*t)++; \
- sscanf(json + (*t)->start, "%u", &o->p);
+ sscanf(json + (*t)->start, "%u", p);
-#define RESTORE_USINT(o, k, p) \
+#define RESTORE_USINT(k, p) \
} else if (keyeq(#k, *t, json)) { \
(*t)++; \
- sscanf(json + (*t)->start, "%hu", &o->p);
+ sscanf(json + (*t)->start, "%hu", p);
-#define RESTORE_DOUBLE(o, k, p) \
+#define RESTORE_DOUBLE(k, p) \
} else if (keyeq(#k, *t, json)) { \
(*t)++; \
- sscanf(json + (*t)->start, "%lf", &o->p);
+ sscanf(json + (*t)->start, "%lf", p);
-#define RESTORE_ANY(o, k, p, f) \
+#define RESTORE_ANY(k, p, f) \
} else if (keyeq(#k, *t, json)) { \
(*t)++; \
- char *val = copy_string(*t, json); \
- f(val, &o->p); \
+ char *val = copy_string(json + (*t)->start, (*t)->end - (*t)->start); \
+ f(val, p); \
free(val);
-#define RESTORE_BOOL(o, k, p) RESTORE_ANY(o, k, p, parse_bool)
+#define RESTORE_BOOL(k, p) RESTORE_ANY(k, p, parse_bool)
monitor_t *restore_monitor(jsmntok_t **t, char *json)
{
int num = (*t)->size;
(*t)++;
- monitor_t *m = make_monitor(NULL);
+ monitor_t *m = make_monitor(NULL, UINT32_MAX);
char *focusedDesktopName = NULL;
for (int i = 0; i < num; i++) {
if (keyeq("name", *t, json)) {
(*t)++;
snprintf(m->name, (*t)->end - (*t)->start + 1, "%s", json + (*t)->start);
- RESTORE_UINT(m, id, id)
- RESTORE_BOOL(m, wired, wired)
- RESTORE_INT(m, topPadding, top_padding)
- RESTORE_INT(m, rightPadding, right_padding)
- RESTORE_INT(m, bottomPadding, bottom_padding)
- RESTORE_INT(m, leftPadding, left_padding)
- RESTORE_INT(m, numSticky, num_sticky)
+ RESTORE_UINT(id, &m->id)
+ RESTORE_UINT(randrId, &m->randr_id)
+ RESTORE_BOOL(wired, &m->wired)
+ RESTORE_UINT(stickyCount, &m->sticky_count)
+ RESTORE_INT(windowGap, &m->window_gap)
+ RESTORE_UINT(borderWidth, &m->border_width)
+ } else if (keyeq("padding", *t, json)) {
+ (*t)++;
+ restore_padding(&m->padding, t, json);
+ continue;
} else if (keyeq("rectangle", *t, json)) {
(*t)++;
restore_rectangle(&m->rectangle, t, json);
update_root(m, &m->rectangle);
continue;
} else if (keyeq("focusedDesktopName", *t, json)) {
+ free(focusedDesktopName);
(*t)++;
- focusedDesktopName = copy_string(*t, json);
+ focusedDesktopName = copy_string(json + (*t)->start, (*t)->end - (*t)->start);
} else if (keyeq("desktops", *t, json)) {
(*t)++;
int s = (*t)->size;
{
int s = (*t)->size;
(*t)++;
- desktop_t *d = make_desktop(NULL);
- xcb_window_t focusedWindow = XCB_NONE;
+ desktop_t *d = make_desktop(NULL, UINT32_MAX);
+ xcb_window_t focusedNodeId = XCB_NONE;
for (int i = 0; i < s; i++) {
if (keyeq("name", *t, json)) {
(*t)++;
snprintf(d->name, (*t)->end - (*t)->start + 1, "%s", json + (*t)->start);
- } else if (keyeq("layout", *t, json)) {
+ RESTORE_UINT(id, &d->id)
+ RESTORE_ANY(layout, &d->layout, parse_layout)
+ RESTORE_INT(windowGap, &d->window_gap)
+ RESTORE_UINT(borderWidth, &d->border_width)
+ } else if (keyeq("focusedNodeId", *t, json)) {
(*t)++;
- char *val = copy_string(*t, json);
- layout_t lyt;
- if (parse_layout(val, &lyt)) {
- d->layout = lyt;
- }
- free(val);
- RESTORE_INT(d, topPadding, top_padding)
- RESTORE_INT(d, rightPadding, right_padding)
- RESTORE_INT(d, bottomPadding, bottom_padding)
- RESTORE_INT(d, leftPadding, left_padding)
- RESTORE_INT(d, windowGap, window_gap)
- RESTORE_UINT(d, borderWidth, border_width)
- } else if (keyeq("focusedWindow", *t, json)) {
+ sscanf(json + (*t)->start, "%u", &focusedNodeId);
+ } else if (keyeq("padding", *t, json)) {
(*t)++;
- sscanf(json + (*t)->start, "%u", &focusedWindow);
+ restore_padding(&d->padding, t, json);
+ continue;
} else if (keyeq("root", *t, json)) {
(*t)++;
d->root = restore_node(t, json);
(*t)++;
}
- if (focusedWindow != XCB_NONE) {
- for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root)) {
- if (f->client->window == focusedWindow) {
- d->focus = f;
- break;
- }
- }
+ if (focusedNodeId != XCB_NONE) {
+ d->focus = find_by_id_in(d->root, focusedNodeId);
}
return d;
} else {
int s = (*t)->size;
(*t)++;
- node_t *n = make_node();
+ /* hack to prevent a new ID from being generated */
+ node_t *n = make_node(UINT32_MAX);
for (int i = 0; i < s; i++) {
- if (keyeq("splitType", *t, json)) {
+ if (keyeq("id", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%u", &n->id);
+ RESTORE_ANY(splitType, &n->split_type, parse_split_type)
+ RESTORE_DOUBLE(splitRatio, &n->split_ratio)
+ RESTORE_INT(birthRotation, &n->birth_rotation)
+ RESTORE_BOOL(vacant, &n->vacant)
+ RESTORE_BOOL(sticky, &n->sticky)
+ RESTORE_BOOL(private, &n->private)
+ RESTORE_BOOL(locked, &n->locked)
+ } else if (keyeq("presel", *t, json)) {
(*t)++;
- char *val = copy_string(*t, json);
- parse_split_type(val, &n->split_type);
- free(val);
- RESTORE_DOUBLE(n, splitRatio, split_ratio)
- RESTORE_ANY(n, splitMode, split_mode, parse_split_mode)
- RESTORE_ANY(n, splitDir, split_dir, parse_direction)
- RESTORE_INT(n, birthRotation, birth_rotation)
- RESTORE_INT(n, privacyLevel, privacy_level)
- RESTORE_ANY(n, vacant, vacant, parse_bool)
+ n->presel = restore_presel(t, json);
+ continue;
} else if (keyeq("rectangle", *t, json)) {
(*t)++;
restore_rectangle(&n->rectangle, t, json);
(*t)++;
n->client = restore_client(t, json);
continue;
+ } else {
+ warn("Restore node: unknown key: '%.*s'.\n", (*t)->end - (*t)->start, json + (*t)->start);
+ (*t)++;
}
(*t)++;
}
}
}
-client_t *restore_client(jsmntok_t **t, char *json)
+presel_t *restore_presel(jsmntok_t **t, char *json)
{
if ((*t)->type == JSMN_PRIMITIVE) {
(*t)++;
} else {
int s = (*t)->size;
(*t)++;
- client_t *c = make_client(XCB_NONE, 0);
+ presel_t *p = make_presel();
for (int i = 0; i < s; i++) {
- if (keyeq("window", *t, json)) {
+ if (keyeq("splitRatio", *t, json)) {
(*t)++;
- sscanf(json + (*t)->start, "%u", &c->window);
- } else if (keyeq("className", *t, json)) {
+ sscanf(json + (*t)->start, "%lf", &p->split_ratio);
+ RESTORE_ANY(splitDir, &p->split_dir, parse_direction)
+ }
+
+ (*t)++;
+ }
+
+ return p;
+ }
+}
+
+
+client_t *restore_client(jsmntok_t **t, char *json)
+{
+ if ((*t)->type == JSMN_PRIMITIVE) {
+ (*t)++;
+ return NULL;
+ } else {
+ int s = (*t)->size;
+ (*t)++;
+ client_t *c = make_client();
+
+ for (int i = 0; i < s; i++) {
+ if (keyeq("className", *t, json)) {
(*t)++;
snprintf(c->class_name, (*t)->end - (*t)->start + 1, "%s", json + (*t)->start);
} else if (keyeq("instanceName", *t, json)) {
(*t)++;
snprintf(c->instance_name, (*t)->end - (*t)->start + 1, "%s", json + (*t)->start);
- RESTORE_ANY(c, state, state, parse_client_state)
- RESTORE_ANY(c, lastState, last_state, parse_client_state)
- RESTORE_ANY(c, layer, layer, parse_stack_layer)
- RESTORE_ANY(c, lastLayer, last_layer, parse_stack_layer)
- RESTORE_UINT(c, borderWidth, border_width)
- RESTORE_BOOL(c, locked, locked)
- RESTORE_BOOL(c, sticky, sticky)
- RESTORE_BOOL(c, urgent, urgent)
- RESTORE_BOOL(c, private, private)
- RESTORE_BOOL(c, icccmFocus, icccm_focus)
- RESTORE_BOOL(c, icccmInput, icccm_input)
- RESTORE_USINT(c, minWidth, min_width)
- RESTORE_USINT(c, maxWidth, max_width)
- RESTORE_USINT(c, minHeight, min_height)
- RESTORE_USINT(c, maxHeight, max_height)
- RESTORE_INT(c, numStates, num_states)
+ RESTORE_ANY(state, &c->state, parse_client_state)
+ RESTORE_ANY(lastState, &c->last_state, parse_client_state)
+ RESTORE_ANY(layer, &c->layer, parse_stack_layer)
+ RESTORE_ANY(lastLayer, &c->last_layer, parse_stack_layer)
+ RESTORE_UINT(borderWidth, &c->border_width)
+ RESTORE_BOOL(urgent, &c->urgent)
+ RESTORE_BOOL(visible, &c->visible)
+ RESTORE_BOOL(icccmFocus, &c->icccm_focus)
+ RESTORE_BOOL(icccmInput, &c->icccm_input)
+ RESTORE_USINT(minWidth, &c->min_width)
+ RESTORE_USINT(maxWidth, &c->max_width)
+ RESTORE_USINT(minHeight, &c->min_height)
+ RESTORE_USINT(maxHeight, &c->max_height)
+ RESTORE_INT(wmStatesCount, &c->wm_states_count)
} else if (keyeq("wmState", *t, json)) {
(*t)++;
restore_wm_state(c->wm_state, t, json);
(*t)++;
restore_rectangle(&c->floating_rectangle, t, json);
continue;
+ } else {
+ warn("Restore client: unknown key: '%.*s'.\n", (*t)->end - (*t)->start, json + (*t)->start);
+ (*t)++;
}
(*t)++;
}
}
-void restore_wm_state(xcb_atom_t *w, jsmntok_t **t, char *json)
+void restore_padding(padding_t *p, jsmntok_t **t, char *json)
{
int s = (*t)->size;
(*t)++;
for (int i = 0; i < s; i++) {
- sscanf(json + (*t)->start, "%u", &w[i]);
+ if (keyeq("top", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%i", &p->top);
+ } else if (keyeq("right", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%i", &p->right);
+ } else if (keyeq("bottom", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%i", &p->bottom);
+ } else if (keyeq("left", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%i", &p->left);
+ }
(*t)++;
}
}
-#undef RESTORE_INT
-#undef RESTORE_UINT
-#undef RESTORE_USINT
-#undef RESTORE_DOUBLE
-#undef RESTORE_ANY
-#undef RESTORE_BOOL
-
-bool keyeq(char *s, jsmntok_t *key, char *json)
+void restore_history(jsmntok_t **t, char *json)
{
- return (strncmp(s, json + key->start, key->end - key->start) == 0);
-}
+ int s = (*t)->size;
+ (*t)++;
-char *copy_string(jsmntok_t *tok, char *json)
-{
- size_t len = tok->end - tok->start + 1;
- char *res = malloc(len * sizeof(char));
- if (res == NULL) {
- perror("Copy string: malloc");
- return NULL;
+ for (int i = 0; i < s; i++) {
+ coordinates_t loc = {NULL, NULL, NULL};
+ restore_coordinates(&loc, t, json);
+ if (loc.monitor != NULL && loc.desktop != NULL) {
+ history_add(loc.monitor, loc.desktop, loc.node);
+ }
}
- strncpy(res, json+tok->start, len-1);
- res[len-1] = '\0';
- return res;
}
-bool restore_history(const char *file_path)
+void restore_coordinates(coordinates_t *loc, jsmntok_t **t, char *json)
{
- if (file_path == NULL) {
- return false;
- }
-
- FILE *snapshot = fopen(file_path, "r");
- if (snapshot == NULL) {
- perror("Restore history: fopen");
- return false;
- }
-
- char line[MAXLEN];
- char mnm[SMALEN];
- char dnm[SMALEN];
- xcb_window_t win;
-
- empty_history();
+ int s = (*t)->size;
+ (*t)++;
- while (fgets(line, sizeof(line), snapshot) != NULL) {
- if (sscanf(line, "%s %s %X", mnm, dnm, &win) == 3) {
- coordinates_t loc;
- if (win != XCB_NONE && !locate_window(win, &loc)) {
- warn("Can't locate window 0x%X.\n", win);
- continue;
- }
- node_t *n = (win == XCB_NONE ? NULL : loc.node);
- if (!locate_desktop(dnm, &loc)) {
- warn("Can't locate desktop '%s'.\n", dnm);
- continue;
- }
- desktop_t *d = loc.desktop;
- if (!locate_monitor(mnm, &loc)) {
- warn("Can't locate monitor '%s'.\n", mnm);
- continue;
- }
- monitor_t *m = loc.monitor;
- history_add(m, d, n);
- } else {
- warn("Can't parse history entry: '%s'\n", line);
+ for (int i = 0; i < s; i++) {
+ if (keyeq("monitorName", *t, json)) {
+ (*t)++;
+ char *name = copy_string(json + (*t)->start, (*t)->end - (*t)->start);
+ loc->monitor = find_monitor(name);
+ free(name);
+ } else if (keyeq("desktopName", *t, json)) {
+ (*t)++;
+ char *name = copy_string(json + (*t)->start, (*t)->end - (*t)->start);
+ loc->desktop = find_desktop_in(name, loc->monitor);
+ free(name);
+ } else if (keyeq("nodeId", *t, json)) {
+ (*t)++;
+ uint32_t id;
+ sscanf(json + (*t)->start, "%u", &id);
+ loc->node = find_by_id_in(loc->desktop!=NULL?loc->desktop->root:NULL, id);
}
+ (*t)++;
}
-
- fclose(snapshot);
- return true;
}
-bool restore_stack(const char *file_path)
+void restore_stack(jsmntok_t **t, char *json)
{
- if (file_path == NULL) {
- return false;
- }
+ int s = (*t)->size;
+ (*t)++;
- FILE *snapshot = fopen(file_path, "r");
- if (snapshot == NULL) {
- perror("Restore stack: fopen");
- return false;
+ for (int i = 0; i < s; i++) {
+ uint32_t id;
+ sscanf(json + (*t)->start, "%u", &id);
+ coordinates_t loc;
+ if (locate_window(id, &loc)) {
+ stack_insert_after(stack_tail, loc.node);
+ }
+ (*t)++;
}
+}
- char line[MAXLEN];
- xcb_window_t win;
+void restore_wm_state(xcb_atom_t *w, jsmntok_t **t, char *json)
+{
+ int s = (*t)->size;
+ (*t)++;
- while (stack_head != NULL) {
- remove_stack(stack_head);
+ for (int i = 0; i < s; i++) {
+ sscanf(json + (*t)->start, "%u", &w[i]);
+ (*t)++;
}
+}
- while (fgets(line, sizeof(line), snapshot) != NULL) {
- if (sscanf(line, "%X", &win) == 1) {
- coordinates_t loc;
- if (locate_window(win, &loc)) {
- stack_insert_after(stack_tail, loc.node);
- } else {
- warn("Can't locate window 0x%X.\n", win);
- }
- } else {
- warn("Can't parse stack entry: '%s'\n", line);
- }
- }
+#undef RESTORE_INT
+#undef RESTORE_UINT
+#undef RESTORE_USINT
+#undef RESTORE_DOUBLE
+#undef RESTORE_ANY
+#undef RESTORE_BOOL
- fclose(snapshot);
- return true;
+bool keyeq(char *s, jsmntok_t *key, char *json)
+{
+ size_t n = key->end - key->start;
+ return (strlen(s) == n && strncmp(s, json + key->start, n) == 0);
}