MD_DOCS = README.md doc/CONTRIBUTING.md doc/INSTALL.md doc/MISC.md doc/TODO.md
XSESSIONS = $(PREFIX)/share/xsessions
-WM_SRC = bspwm.c helpers.c settings.c monitor.c desktop.c tree.c stack.c history.c \
- events.c pointer.c window.c messages.c query.c restore.c rule.c ewmh.c subscribe.c
+WM_SRC = bspwm.c helpers.c jsmn.c settings.c monitor.c desktop.c tree.c stack.c history.c \
+ events.c pointer.c window.c messages.c parse.c query.c restore.c rule.c ewmh.c subscribe.c
WM_OBJ = $(WM_SRC:.c=.o)
CL_SRC = bspc.c helpers.c
CL_OBJ = $(CL_SRC:.c=.o)
ewmh.o: ewmh.c bspwm.h ewmh.h helpers.h settings.h tree.h types.h
helpers.o: helpers.c bspwm.h helpers.h types.h
history.o: history.c bspwm.h helpers.h query.h types.h
-messages.o: messages.c bspwm.h common.h desktop.h ewmh.h helpers.h history.h messages.h monitor.h pointer.h query.h restore.h rule.h settings.h subscribe.h tree.h types.h window.h
+jsmn.o: jsmn.c jsmn.h
+messages.o: messages.c bspwm.h common.h desktop.h ewmh.h helpers.h history.h jsmn.h messages.h monitor.h parse.h pointer.h query.h restore.h rule.h settings.h subscribe.h tree.h types.h window.h
monitor.o: monitor.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h subscribe.h tree.h types.h window.h
+parse.o: parse.c helpers.h parse.h types.h
pointer.o: pointer.c bspwm.h helpers.h monitor.h pointer.h query.h settings.h stack.h subscribe.h tree.h types.h window.h
-query.o: query.c bspwm.h desktop.h helpers.h history.h messages.h monitor.h query.h subscribe.h tree.h types.h
-restore.o: restore.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h restore.h settings.h stack.h tree.h types.h
-rule.o: rule.c bspwm.h ewmh.h helpers.h messages.h rule.h settings.h subscribe.h types.h window.h
+query.o: query.c bspwm.h desktop.h helpers.h history.h jsmn.h monitor.h parse.h query.h tree.h types.h
+restore.o: restore.c bspwm.h common.h desktop.h ewmh.h helpers.h history.h jsmn.h monitor.h parse.h query.h restore.h settings.h stack.h tree.h types.h
+rule.o: rule.c bspwm.h ewmh.h helpers.h parse.h rule.h settings.h types.h window.h
settings.o: settings.c bspwm.h helpers.h settings.h types.h
stack.o: stack.c bspwm.h helpers.h stack.h types.h window.h
subscribe.o: subscribe.c bspwm.h helpers.h settings.h subscribe.h tree.h types.h
tree.o: tree.c bspwm.h desktop.h ewmh.h helpers.h history.h monitor.h query.h settings.h stack.h subscribe.h tree.h types.h window.h
-window.o: window.c bspwm.h ewmh.h helpers.h messages.h monitor.h query.h rule.h settings.h stack.h subscribe.h tree.h types.h window.h
+window.o: window.c bspwm.h ewmh.h helpers.h monitor.h parse.h query.h rule.h settings.h stack.h subscribe.h tree.h types.h window.h
void init(void)
{
- num_monitors = num_desktops = num_clients = 0;
+ num_clients = 0;
monitor_uid = desktop_uid = 0;
mon = mon_head = mon_tail = pri_mon = NULL;
history_head = history_tail = history_needle = NULL;
for (int i = 0; i < n; i++) {
xcb_xinerama_screen_info_t info = xsi[i];
xcb_rectangle_t rect = (xcb_rectangle_t) {info.x_org, info.y_org, info.width, info.height};
- monitor_t *m = make_monitor(rect);
+ monitor_t *m = make_monitor(&rect);
add_monitor(m);
add_desktop(m, make_desktop(NULL));
}
} else {
warn("Xinerama is inactive.\n");
xcb_rectangle_t rect = (xcb_rectangle_t) {0, 0, screen_width, screen_height};
- monitor_t *m = make_monitor(rect);
+ monitor_t *m = make_monitor(&rect);
add_monitor(m);
add_desktop(m, make_desktop(NULL));
}
void cleanup(void)
{
- while (mon_head != NULL)
+ while (mon_head != NULL) {
remove_monitor(mon_head);
- while (rule_head != NULL)
+ }
+ while (rule_head != NULL) {
remove_rule(rule_head);
- while (stack_head != NULL)
- remove_stack(stack_head);
- while (subscribe_head != NULL)
+ }
+ while (subscribe_head != NULL) {
remove_subscriber(subscribe_head);
- while (pending_rule_head != NULL)
+ }
+ while (pending_rule_head != NULL) {
remove_pending_rule(pending_rule_head);
+ }
empty_history();
free(frozen_pointer);
}
xcb_connection_t *dpy;
int default_screen, screen_width, screen_height;
uint32_t num_clients;
-uint32_t num_desktops;
unsigned int num_monitors;
unsigned int monitor_uid;
unsigned int desktop_uid;
desktop_t *make_desktop(const char *name)
{
desktop_t *d = malloc(sizeof(desktop_t));
- if (name == NULL)
+ if (name == NULL) {
snprintf(d->name, sizeof(d->name), "%s%d", DEFAULT_DESK_NAME, ++desktop_uid);
- else
+ } else {
snprintf(d->name, sizeof(d->name), "%s", name);
+ }
d->prev = d->next = NULL;
d->root = d->focus = NULL;
initialize_desktop(d);
put_status(SBSC_MASK_DESKTOP_ADD, "desktop_add %s %s\n", m->name, d->name);
insert_desktop(m, d);
- num_desktops++;
ewmh_update_number_of_desktops();
ewmh_update_desktop_names();
ewmh_update_wm_desktops();
empty_desktop(d);
free(d);
- num_desktops--;
-
ewmh_update_current_desktop();
ewmh_update_number_of_desktops();
ewmh_update_desktop_names();
void ewmh_update_number_of_desktops(void)
{
+ uint32_t num_desktops = 0;
+
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ num_desktops++;
+ }
+ }
+
xcb_ewmh_set_number_of_desktops(ewmh, default_screen, num_desktops);
}
uint32_t ewmh_get_desktop_index(desktop_t *d)
{
uint32_t i = 0;
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next, i++)
- if (d == cd)
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *cd = m->desk_head; cd != NULL; cd = cd->next, i++) {
+ if (d == cd) {
return i;
+ }
+ }
+ }
return 0;
}
void ewmh_update_wm_desktops(void)
{
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
uint32_t i = ewmh_get_desktop_index(d);
- for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
+ for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
xcb_ewmh_set_wm_desktop(ewmh, n->client->window, i);
+ }
}
+ }
}
void ewmh_update_desktop_names(void)
uint32_t names_len;
i = 0;
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
- for (j = 0; d->name[j] != '\0' && (i + j) < sizeof(names); j++)
+ for (j = 0; d->name[j] != '\0' && (i + j) < sizeof(names); j++) {
names[i + j] = d->name[j];
+ }
i += j;
- if (i < sizeof(names))
+ if (i < sizeof(names)) {
names[i++] = '\0';
+ }
}
+ }
- if (i < 1)
+ if (i < 1) {
+ xcb_ewmh_set_desktop_names(ewmh, default_screen, 0, NULL);
return;
+ }
names_len = i - 1;
xcb_ewmh_set_desktop_names(ewmh, default_screen, names_len, names);
xcb_window_t wins[num_clients];
unsigned int i = 0;
- for (monitor_t *m = mon_head; m != NULL; m = m->next)
- for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
- for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
wins[i++] = n->client->window;
+ }
+ }
+ }
xcb_ewmh_set_client_list(ewmh, default_screen, num_clients, wins);
xcb_ewmh_set_client_list_stacking(ewmh, default_screen, num_clients, wins);
bool ewmh_wm_state_add(client_t *c, xcb_atom_t state)
{
- if (c->num_states >= MAX_STATE)
+ if (c->num_states >= MAX_STATE) {
return false;
- for (int i = 0; i < c->num_states; i++)
- if (c->wm_state[i] == state)
+ }
+ for (int i = 0; i < c->num_states; i++) {
+ if (c->wm_state[i] == state) {
return false;
+ }
+ }
c->wm_state[c->num_states] = state;
c->num_states++;
xcb_ewmh_set_wm_state(ewmh, c->window, c->num_states, c->wm_state);
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
#include <math.h>
#include "bspwm.h"
exit(EXIT_FAILURE);
}
+char *read_string(const char *file_path, size_t *tlen)
+{
+ if (file_path == NULL) {
+ return NULL;
+ }
+
+ int fd = open(file_path, O_RDONLY);
+
+ if (fd == -1) {
+ perror("Read file: open");
+ return NULL;
+ }
+
+ char buf[BUFSIZ], *content;
+ size_t len = sizeof(buf);
+
+ if ((content = malloc(len * sizeof(char))) == NULL) {
+ perror("Read file: malloc");
+ return NULL;
+ }
+
+ int nb;
+ *tlen = 0;
+
+ while (true) {
+ nb = read(fd, buf, sizeof(buf));
+ if (nb < 0) {
+ perror("Restore tree: read");
+ free(content);
+ return NULL;
+ } else if (nb == 0) {
+ break;
+ } else {
+ *tlen += nb;
+ if (*tlen > len) {
+ len *= 2;
+ char *rcontent = realloc(content, len * sizeof(char));
+ if (rcontent == NULL) {
+ perror("Read file: realloc");
+ free(content);
+ return NULL;
+ } else {
+ content = rcontent;
+ }
+ }
+ strncpy(content + (*tlen - nb), buf, nb);
+ }
+ }
+
+ return content;
+}
+
bool get_color(char *col, xcb_window_t win, uint32_t *pxl)
{
xcb_colormap_t map = screen->default_colormap;
#define LENGTH(x) (sizeof(x) / sizeof(*x))
#define MAX(A, B) ((A) > (B) ? (A) : (B))
#define MIN(A, B) ((A) < (B) ? (A) : (B))
-#define BOOLSTR(A) ((A) ? "true" : "false")
-#define ONOFFSTR(A) ((A) ? "on" : "off")
-#define LAYERSTR(A) ((A) == LAYER_BELOW ? "below" : ((A) == LAYER_NORMAL ? "normal" : "above"))
-#define STATESTR(A) ((A) == STATE_TILED ? "tiled" : ((A) == STATE_FLOATING ? "floating" : ((A) == STATE_FULLSCREEN ? "fullscreen" : "pseudo_tiled")))
+
#define IS_TILED(c) (c->state == STATE_TILED || c->state == STATE_PSEUDO_TILED)
#define IS_FLOATING(c) (c->state == STATE_FLOATING)
#define IS_FULLSCREEN(c) (c->state == STATE_FULLSCREEN)
+#define BOOL_STR(A) ((A) ? "true" : "false")
+#define ON_OFF_STR(A) ((A) ? "on" : "off")
+#define LAYOUT_STR(A) ((A) == LAYOUT_TILED ? "tiled" : "monocle")
+#define SPLIT_TYPE_STR(A) ((A) == TYPE_HORIZONTAL ? "horizontal" : "vertical")
+#define SPLIT_MODE_STR(A) ((A) == MODE_AUTOMATIC ? "automatic" : "manual")
+#define SPLIT_DIR_STR(A) ((A) == DIR_RIGHT ? "right" : ((A) == DIR_UP ? "up" : ((A) == DIR_LEFT ? "left" : "down")))
+#define STATE_STR(A) ((A) == STATE_TILED ? "tiled" : ((A) == STATE_FLOATING ? "floating" : ((A) == STATE_FULLSCREEN ? "fullscreen" : "pseudo_tiled")))
+#define LAYER_STR(A) ((A) == LAYER_BELOW ? "below" : ((A) == LAYER_NORMAL ? "normal" : "above"))
+
#define XCB_CONFIG_WINDOW_X_Y (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y)
#define XCB_CONFIG_WINDOW_WIDTH_HEIGHT (XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT)
#define XCB_CONFIG_WINDOW_X_Y_WIDTH_HEIGHT (XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT)
void warn(char *fmt, ...);
void err(char *fmt, ...);
+char *read_string(const char *file_path, size_t *tlen);
bool get_color(char *col, xcb_window_t win, uint32_t *pxl);
double distance(xcb_point_t a, xcb_point_t b);
/* remove duplicate entries */
while (c != NULL && ((a->loc.node != NULL && a->loc.node == c->loc.node) ||
(a->loc.node == NULL && a->loc.desktop == c->loc.desktop))) {
- history_t *d = c->prev;
+ history_t *p = c->prev;
if (history_head == c)
history_head = history_tail;
if (history_needle == c)
history_needle = history_tail;
free(c);
- c = d;
+ c = p;
}
a->prev = c;
}
--- /dev/null
+#include <stdlib.h>
+
+#include "jsmn.h"
+
+/**
+ * Allocates a fresh unused token from the token pull.
+ */
+static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
+ jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *tok;
+ if (parser->toknext >= num_tokens) {
+ return NULL;
+ }
+ tok = &tokens[parser->toknext++];
+ tok->start = tok->end = -1;
+ tok->size = 0;
+#ifdef JSMN_PARENT_LINKS
+ tok->parent = -1;
+#endif
+ return tok;
+}
+
+/**
+ * Fills token type and boundaries.
+ */
+static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
+ int start, int end) {
+ token->type = type;
+ token->start = start;
+ token->end = end;
+ token->size = 0;
+}
+
+/**
+ * Fills next available token with JSON primitive.
+ */
+static int jsmn_parse_primitive(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+ int start;
+
+ start = parser->pos;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ switch (js[parser->pos]) {
+#ifndef JSMN_STRICT
+ /* In strict mode primitive must be followed by "," or "}" or "]" */
+ case ':':
+#endif
+ case '\t' : case '\r' : case '\n' : case ' ' :
+ case ',' : case ']' : case '}' :
+ goto found;
+ }
+ if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#ifdef JSMN_STRICT
+ /* In strict mode primitive must be followed by a comma/object/array */
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+#endif
+
+found:
+ if (tokens == NULL) {
+ parser->pos--;
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ parser->pos--;
+ return 0;
+}
+
+/**
+ * Filsl next token with JSON string.
+ */
+static int jsmn_parse_string(jsmn_parser *parser, const char *js,
+ size_t len, jsmntok_t *tokens, size_t num_tokens) {
+ jsmntok_t *token;
+
+ int start = parser->pos;
+
+ parser->pos++;
+
+ /* Skip starting quote */
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c = js[parser->pos];
+
+ /* Quote: end of string */
+ if (c == '\"') {
+ if (tokens == NULL) {
+ return 0;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL) {
+ parser->pos = start;
+ return JSMN_ERROR_NOMEM;
+ }
+ jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ return 0;
+ }
+
+ /* Backslash: Quoted symbol expected */
+ if (c == '\\' && parser->pos + 1 < len) {
+ int i;
+ parser->pos++;
+ switch (js[parser->pos]) {
+ /* Allowed escaped symbols */
+ case '\"': case '/' : case '\\' : case 'b' :
+ case 'f' : case 'r' : case 'n' : case 't' :
+ break;
+ /* Allows escaped symbol \uXXXX */
+ case 'u':
+ parser->pos++;
+ for(i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; i++) {
+ /* If it isn't a hex character we have an error */
+ if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
+ (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
+ (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ parser->pos++;
+ }
+ parser->pos--;
+ break;
+ /* Unexpected symbol */
+ default:
+ parser->pos = start;
+ return JSMN_ERROR_INVAL;
+ }
+ }
+ }
+ parser->pos = start;
+ return JSMN_ERROR_PART;
+}
+
+/**
+ * Parse JSON string and fill tokens.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+ jsmntok_t *tokens, unsigned int num_tokens) {
+ int r;
+ int i;
+ jsmntok_t *token;
+ int count = parser->toknext;
+
+ for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
+ char c;
+ jsmntype_t type;
+
+ c = js[parser->pos];
+ switch (c) {
+ case '{': case '[':
+ count++;
+ if (tokens == NULL) {
+ break;
+ }
+ token = jsmn_alloc_token(parser, tokens, num_tokens);
+ if (token == NULL)
+ return JSMN_ERROR_NOMEM;
+ if (parser->toksuper != -1) {
+ tokens[parser->toksuper].size++;
+#ifdef JSMN_PARENT_LINKS
+ token->parent = parser->toksuper;
+#endif
+ }
+ token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
+ token->start = parser->pos;
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case '}': case ']':
+ if (tokens == NULL)
+ break;
+ type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
+#ifdef JSMN_PARENT_LINKS
+ if (parser->toknext < 1) {
+ return JSMN_ERROR_INVAL;
+ }
+ token = &tokens[parser->toknext - 1];
+ for (;;) {
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ token->end = parser->pos + 1;
+ parser->toksuper = token->parent;
+ break;
+ }
+ if (token->parent == -1) {
+ break;
+ }
+ token = &tokens[token->parent];
+ }
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ if (token->type != type) {
+ return JSMN_ERROR_INVAL;
+ }
+ parser->toksuper = -1;
+ token->end = parser->pos + 1;
+ break;
+ }
+ }
+ /* Error if unmatched closing bracket */
+ if (i == -1) return JSMN_ERROR_INVAL;
+ for (; i >= 0; i--) {
+ token = &tokens[i];
+ if (token->start != -1 && token->end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+#endif
+ break;
+ case '\"':
+ r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+ case '\t' : case '\r' : case '\n' : case ' ':
+ break;
+ case ':':
+ parser->toksuper = parser->toknext - 1;
+ break;
+ case ',':
+ if (tokens != NULL && parser->toksuper != -1 &&
+ tokens[parser->toksuper].type != JSMN_ARRAY &&
+ tokens[parser->toksuper].type != JSMN_OBJECT) {
+#ifdef JSMN_PARENT_LINKS
+ parser->toksuper = tokens[parser->toksuper].parent;
+#else
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) {
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ parser->toksuper = i;
+ break;
+ }
+ }
+ }
+#endif
+ }
+ break;
+#ifdef JSMN_STRICT
+ /* In strict mode primitives are: numbers and booleans */
+ case '-': case '0': case '1' : case '2': case '3' : case '4':
+ case '5': case '6': case '7' : case '8': case '9':
+ case 't': case 'f': case 'n' :
+ /* And they must not be keys of the object */
+ if (tokens != NULL && parser->toksuper != -1) {
+ jsmntok_t *t = &tokens[parser->toksuper];
+ if (t->type == JSMN_OBJECT ||
+ (t->type == JSMN_STRING && t->size != 0)) {
+ return JSMN_ERROR_INVAL;
+ }
+ }
+#else
+ /* In non-strict mode every unquoted value is a primitive */
+ default:
+#endif
+ r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
+ if (r < 0) return r;
+ count++;
+ if (parser->toksuper != -1 && tokens != NULL)
+ tokens[parser->toksuper].size++;
+ break;
+
+#ifdef JSMN_STRICT
+ /* Unexpected char in strict mode */
+ default:
+ return JSMN_ERROR_INVAL;
+#endif
+ }
+ }
+
+ if (tokens != NULL) {
+ for (i = parser->toknext - 1; i >= 0; i--) {
+ /* Unmatched opened object or array */
+ if (tokens[i].start != -1 && tokens[i].end == -1) {
+ return JSMN_ERROR_PART;
+ }
+ }
+ }
+
+ return count;
+}
+
+/**
+ * Creates a new parser based over a given buffer with an array of tokens
+ * available.
+ */
+void jsmn_init(jsmn_parser *parser) {
+ parser->pos = 0;
+ parser->toknext = 0;
+ parser->toksuper = -1;
+}
+
--- /dev/null
+#ifndef __JSMN_H_
+#define __JSMN_H_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * JSON type identifier. Basic types are:
+ * o Object
+ * o Array
+ * o String
+ * o Other primitive: number, boolean (true/false) or null
+ */
+typedef enum {
+ JSMN_UNDEFINED = 0,
+ JSMN_OBJECT = 1,
+ JSMN_ARRAY = 2,
+ JSMN_STRING = 3,
+ JSMN_PRIMITIVE = 4
+} jsmntype_t;
+
+enum jsmnerr {
+ /* Not enough tokens were provided */
+ JSMN_ERROR_NOMEM = -1,
+ /* Invalid character inside JSON string */
+ JSMN_ERROR_INVAL = -2,
+ /* The string is not a full JSON packet, more bytes expected */
+ JSMN_ERROR_PART = -3
+};
+
+/**
+ * JSON token description.
+ * @param type type (object, array, string etc.)
+ * @param start start position in JSON data string
+ * @param end end position in JSON data string
+ */
+typedef struct {
+ jsmntype_t type;
+ int start;
+ int end;
+ int size;
+#ifdef JSMN_PARENT_LINKS
+ int parent;
+#endif
+} jsmntok_t;
+
+/**
+ * JSON parser. Contains an array of token blocks available. Also stores
+ * the string being parsed now and current position in that string
+ */
+typedef struct {
+ unsigned int pos; /* offset in the JSON string */
+ unsigned int toknext; /* next token to allocate */
+ int toksuper; /* superior token node, e.g parent object or array */
+} jsmn_parser;
+
+/**
+ * Create JSON parser over an array of tokens
+ */
+void jsmn_init(jsmn_parser *parser);
+
+/**
+ * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
+ * a single JSON object.
+ */
+int jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
+ jsmntok_t *tokens, unsigned int num_tokens);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __JSMN_H_ */
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "window.h"
#include "common.h"
#include "subscribe.h"
+#include "parse.h"
#include "messages.h"
int handle_message(char *msg, int msg_len, FILE *rsp)
num--, args++;
}
- if (d != 1 || t > 1)
+ if (d != 1 || t > 1) {
return MSG_SYNTAX;
+ }
- if (dom == DOMAIN_HISTORY)
+ if (dom == DOMAIN_HISTORY) {
query_history(trg, rsp);
- else if (dom == DOMAIN_STACK)
+ } else if (dom == DOMAIN_STACK) {
query_stack(rsp);
- else if (dom == DOMAIN_WINDOW)
+ } else if (dom == DOMAIN_WINDOW) {
query_windows(trg, rsp);
- else
- query_monitors(trg, dom, rsp);
+ } else if (dom == DOMAIN_DESKTOP || dom == DOMAIN_MONITOR) {
+ query_names(dom, trg, rsp);
+ } else {
+ if (trg.node != NULL) {
+ query_node(trg.node, rsp);
+ } else if (trg.desktop != NULL) {
+ query_desktop(trg.desktop, rsp);
+ } else if (trg.monitor != NULL) {
+ query_monitor(trg.monitor, rsp);
+ } else {
+ query_tree(rsp);
+ }
+ fprintf(rsp, "\n");
+ }
return MSG_SUCCESS;
}
int cmd_restore(char **args, int num)
{
- if (num < 1)
+ if (num < 1) {
return MSG_SYNTAX;
+ }
while (num > 0) {
if (streq("-T", *args) || streq("--tree", *args)) {
num--, args++;
- if (num < 1)
+ if (num < 1) {
return MSG_SYNTAX;
- restore_tree(*args);
+ }
+ if (!restore_tree(*args)) {
+ return MSG_FAILURE;
+ }
} else if (streq("-H", *args) || streq("--history", *args)) {
num--, args++;
- if (num < 1)
+ if (num < 1) {
return MSG_SYNTAX;
- restore_history(*args);
+ }
+ if (!restore_history(*args)) {
+ return MSG_FAILURE;
+ }
} else if (streq("-S", *args) || streq("--stack", *args)) {
num--, args++;
- if (num < 1)
+ if (num < 1) {
return MSG_SYNTAX;
- restore_stack(*args);
+ }
+ if (!restore_stack(*args)) {
+ return MSG_FAILURE;
+ }
} else {
return MSG_SYNTAX;
}
int set_setting(coordinates_t loc, char *name, char *value)
{
-#define DESKWINDEFSET(k, v) \
+#define DESK_WIN_DEF_SET(k, v) \
if (loc.node != NULL) \
loc.node->client->k = v; \
else if (loc.desktop != NULL) \
unsigned int bw;
if (sscanf(value, "%u", &bw) != 1)
return MSG_FAILURE;
- DESKWINDEFSET(border_width, bw)
-#undef DESKWINDEFSET
-#define DESKDEFSET(k, v) \
+ DESK_WIN_DEF_SET(border_width, bw)
+#undef DESK_WIN_DEF_SET
+#define DESK_DEF_SET(k, v) \
if (loc.desktop != NULL) \
loc.desktop->k = v; \
else if (loc.monitor != NULL) \
int wg;
if (sscanf(value, "%i", &wg) != 1)
return MSG_FAILURE;
- DESKDEFSET(window_gap, wg)
-#undef DESKDEFSET
-#define MONDESKSET(k, v) \
+ DESK_DEF_SET(window_gap, wg)
+#undef DESK_DEF_SET
+#define MON_DESK_SET(k, v) \
if (loc.desktop != NULL) \
loc.desktop->k = v; \
else if (loc.monitor != NULL) \
int tp;
if (sscanf(value, "%i", &tp) != 1)
return MSG_FAILURE;
- MONDESKSET(top_padding, tp)
+ MON_DESK_SET(top_padding, tp)
} else if (streq("right_padding", name)) {
int rp;
if (sscanf(value, "%i", &rp) != 1)
return MSG_FAILURE;
- MONDESKSET(right_padding, rp)
+ MON_DESK_SET(right_padding, rp)
} else if (streq("bottom_padding", name)) {
int bp;
if (sscanf(value, "%i", &bp) != 1)
return MSG_FAILURE;
- MONDESKSET(bottom_padding, bp)
+ MON_DESK_SET(bottom_padding, bp)
} else if (streq("left_padding", name)) {
int lp;
if (sscanf(value, "%i", &lp) != 1)
return MSG_FAILURE;
- MONDESKSET(left_padding, lp)
-#undef MONDESKSET
-#define SETSTR(s) \
+ MON_DESK_SET(left_padding, lp)
+#undef MON_DESK_SET
+#define SET_STR(s) \
} else if (streq(#s, name)) { \
if (snprintf(s, sizeof(s), "%s", value) < 0) \
return MSG_FAILURE;
- SETSTR(external_rules_command)
- SETSTR(status_prefix)
-#undef SETSTR
+ SET_STR(external_rules_command)
+ SET_STR(status_prefix)
+#undef SET_STR
} else if (streq("split_ratio", name)) {
double r;
if (sscanf(value, "%lf", &r) == 1 && r > 0 && r < 1)
else
return MSG_FAILURE;
return MSG_SUCCESS;
-#define SETCOLOR(s) \
+#define SET_COLOR(s) \
} else if (streq(#s, name)) { \
snprintf(s, sizeof(s), "%s", value);
- SETCOLOR(focused_border_color)
- SETCOLOR(active_border_color)
- SETCOLOR(normal_border_color)
- SETCOLOR(presel_border_color)
- SETCOLOR(focused_locked_border_color)
- SETCOLOR(active_locked_border_color)
- SETCOLOR(normal_locked_border_color)
- SETCOLOR(focused_sticky_border_color)
- SETCOLOR(active_sticky_border_color)
- SETCOLOR(normal_sticky_border_color)
- SETCOLOR(focused_private_border_color)
- SETCOLOR(active_private_border_color)
- SETCOLOR(normal_private_border_color)
- SETCOLOR(urgent_border_color)
-#undef SETCOLOR
+ SET_COLOR(focused_border_color)
+ SET_COLOR(active_border_color)
+ SET_COLOR(normal_border_color)
+ SET_COLOR(presel_border_color)
+ SET_COLOR(focused_locked_border_color)
+ SET_COLOR(active_locked_border_color)
+ SET_COLOR(normal_locked_border_color)
+ SET_COLOR(focused_sticky_border_color)
+ SET_COLOR(active_sticky_border_color)
+ SET_COLOR(normal_sticky_border_color)
+ SET_COLOR(focused_private_border_color)
+ SET_COLOR(active_private_border_color)
+ SET_COLOR(normal_private_border_color)
+ SET_COLOR(urgent_border_color)
+#undef SET_COLOR
} else if (streq("initial_polarity", name)) {
child_polarity_t p;
if (parse_child_polarity(value, &p)) {
} else {
return MSG_FAILURE;
}
-#define SETBOOL(s) \
+#define SET_BOOL(s) \
} else if (streq(#s, name)) { \
if (!parse_bool(value, &s)) \
return MSG_FAILURE;
- SETBOOL(borderless_monocle)
- SETBOOL(gapless_monocle)
- SETBOOL(leaf_monocle)
- SETBOOL(pointer_follows_focus)
- SETBOOL(pointer_follows_monitor)
- SETBOOL(auto_alternate)
- SETBOOL(auto_cancel)
- SETBOOL(history_aware_focus)
- SETBOOL(focus_by_distance)
- SETBOOL(ignore_ewmh_focus)
- SETBOOL(center_pseudo_tiled)
-#undef SETBOOL
-#define SETMONBOOL(s) \
+ SET_BOOL(borderless_monocle)
+ SET_BOOL(gapless_monocle)
+ SET_BOOL(leaf_monocle)
+ SET_BOOL(pointer_follows_focus)
+ SET_BOOL(pointer_follows_monitor)
+ SET_BOOL(auto_alternate)
+ SET_BOOL(auto_cancel)
+ SET_BOOL(history_aware_focus)
+ SET_BOOL(focus_by_distance)
+ SET_BOOL(ignore_ewmh_focus)
+ SET_BOOL(center_pseudo_tiled)
+#undef SET_BOOL
+#define SET_MON_BOOL(s) \
} else if (streq(#s, name)) { \
if (!parse_bool(value, &s)) \
return MSG_FAILURE; \
if (s) \
update_monitors();
- SETMONBOOL(remove_disabled_monitors)
- SETMONBOOL(remove_unplugged_monitors)
- SETMONBOOL(merge_overlapping_monitors)
-#undef SETMONBOOL
+ SET_MON_BOOL(remove_disabled_monitors)
+ SET_MON_BOOL(remove_unplugged_monitors)
+ SET_MON_BOOL(merge_overlapping_monitors)
+#undef SET_MON_BOOL
} else {
return MSG_FAILURE;
}
fprintf(rsp, "%s", status_prefix);
else if (streq("initial_polarity", name))
fprintf(rsp, "%s", initial_polarity == FIRST_CHILD ? "first_child" : "second_child");
-#define MONDESKGET(k) \
+#define MON_DESK_GET(k) \
else if (streq(#k, name)) \
if (loc.desktop != NULL) \
fprintf(rsp, "%i", loc.desktop->k); \
fprintf(rsp, "%i", loc.monitor->k); \
else \
return MSG_FAILURE;
- MONDESKGET(top_padding)
- MONDESKGET(right_padding)
- MONDESKGET(bottom_padding)
- MONDESKGET(left_padding)
+ MON_DESK_GET(top_padding)
+ MON_DESK_GET(right_padding)
+ MON_DESK_GET(bottom_padding)
+ MON_DESK_GET(left_padding)
#undef DESKGET
-#define GETCOLOR(s) \
+#define GET_COLOR(s) \
else if (streq(#s, name)) \
fprintf(rsp, "%s", s);
- GETCOLOR(focused_border_color)
- GETCOLOR(active_border_color)
- GETCOLOR(normal_border_color)
- GETCOLOR(presel_border_color)
- GETCOLOR(focused_locked_border_color)
- GETCOLOR(active_locked_border_color)
- GETCOLOR(normal_locked_border_color)
- GETCOLOR(focused_sticky_border_color)
- GETCOLOR(active_sticky_border_color)
- GETCOLOR(normal_sticky_border_color)
- GETCOLOR(urgent_border_color)
-#undef GETCOLOR
-#define GETBOOL(s) \
+ GET_COLOR(focused_border_color)
+ GET_COLOR(active_border_color)
+ GET_COLOR(normal_border_color)
+ GET_COLOR(presel_border_color)
+ GET_COLOR(focused_locked_border_color)
+ GET_COLOR(active_locked_border_color)
+ GET_COLOR(normal_locked_border_color)
+ GET_COLOR(focused_sticky_border_color)
+ GET_COLOR(active_sticky_border_color)
+ GET_COLOR(normal_sticky_border_color)
+ GET_COLOR(urgent_border_color)
+#undef GET_COLOR
+#define GET_BOOL(s) \
else if (streq(#s, name)) \
- fprintf(rsp, "%s", BOOLSTR(s));
- GETBOOL(borderless_monocle)
- GETBOOL(gapless_monocle)
- GETBOOL(leaf_monocle)
- GETBOOL(focus_follows_pointer)
- GETBOOL(pointer_follows_focus)
- GETBOOL(pointer_follows_monitor)
- GETBOOL(auto_alternate)
- GETBOOL(auto_cancel)
- GETBOOL(history_aware_focus)
- GETBOOL(focus_by_distance)
- GETBOOL(ignore_ewmh_focus)
- GETBOOL(center_pseudo_tiled)
- GETBOOL(remove_disabled_monitors)
- GETBOOL(remove_unplugged_monitors)
- GETBOOL(merge_overlapping_monitors)
-#undef GETBOOL
+ fprintf(rsp, "%s", BOOL_STR(s));
+ GET_BOOL(borderless_monocle)
+ GET_BOOL(gapless_monocle)
+ GET_BOOL(leaf_monocle)
+ GET_BOOL(focus_follows_pointer)
+ GET_BOOL(pointer_follows_focus)
+ GET_BOOL(pointer_follows_monitor)
+ GET_BOOL(auto_alternate)
+ GET_BOOL(auto_cancel)
+ GET_BOOL(history_aware_focus)
+ GET_BOOL(focus_by_distance)
+ GET_BOOL(ignore_ewmh_focus)
+ GET_BOOL(center_pseudo_tiled)
+ GET_BOOL(remove_disabled_monitors)
+ GET_BOOL(remove_unplugged_monitors)
+ GET_BOOL(merge_overlapping_monitors)
+#undef GET_BOOL
else
return MSG_FAILURE;
fprintf(rsp, "\n");
}
return true;
}
-
-bool parse_bool(char *value, bool *b)
-{
- if (streq("true", value) || streq("on", value)) {
- *b = true;
- return true;
- } else if (streq("false", value) || streq("off", value)) {
- *b = false;
- return true;
- }
- return false;
-}
-
-bool parse_layout(char *s, layout_t *l)
-{
- if (streq("monocle", s)) {
- *l = LAYOUT_MONOCLE;
- return true;
- } else if (streq("tiled", s)) {
- *l = LAYOUT_TILED;
- return true;
- }
- return false;
-}
-
-bool parse_client_state(char *s, client_state_t *t)
-{
- if (streq("tiled", s)) {
- *t = STATE_TILED;
- return true;
- } else if (streq("pseudo_tiled", s)) {
- *t = STATE_PSEUDO_TILED;
- return true;
- } else if (streq("floating", s)) {
- *t = STATE_FLOATING;
- return true;
- } else if (streq("fullscreen", s)) {
- *t = STATE_FULLSCREEN;
- return true;
- }
- return false;
-}
-
-bool parse_stack_layer(char *s, stack_layer_t *l)
-{
- if (streq("below", s)) {
- *l = LAYER_BELOW;
- return true;
- } else if (streq("normal", s)) {
- *l = LAYER_NORMAL;
- return true;
- } else if (streq("above", s)) {
- *l = LAYER_ABOVE;
- return true;
- }
- return false;
-}
-
-bool parse_direction(char *s, direction_t *d)
-{
- if (streq("right", s)) {
- *d = DIR_RIGHT;
- return true;
- } else if (streq("down", s)) {
- *d = DIR_DOWN;
- return true;
- } else if (streq("left", s)) {
- *d = DIR_LEFT;
- return true;
- } else if (streq("up", s)) {
- *d = DIR_UP;
- return true;
- }
- return false;
-}
-
-bool parse_cycle_direction(char *s, cycle_dir_t *d)
-{
- if (streq("next", s)) {
- *d = CYCLE_NEXT;
- return true;
- } else if (streq("prev", s)) {
- *d = CYCLE_PREV;
- return true;
- }
- return false;
-}
-
-bool parse_circulate_direction(char *s, circulate_dir_t *d)
-{
- if (streq("forward", s)) {
- *d = CIRCULATE_FORWARD;
- return true;
- } else if (streq("backward", s)) {
- *d = CIRCULATE_BACKWARD;
- return true;
- }
- return false;
-}
-
-bool parse_history_direction(char *s, history_dir_t *d)
-{
- if (streq("older", s)) {
- *d = HISTORY_OLDER;
- return true;
- } else if (streq("newer", s)) {
- *d = HISTORY_NEWER;
- return true;
- }
- return false;
-}
-
-
-bool parse_flip(char *s, flip_t *f)
-{
- if (streq("horizontal", s)) {
- *f = FLIP_HORIZONTAL;
- return true;
- } else if (streq("vertical", s)) {
- *f = FLIP_VERTICAL;
- return true;
- }
- return false;
-}
-
-bool parse_pointer_action(char *s, pointer_action_t *a)
-{
- if (streq("move", s)) {
- *a = ACTION_MOVE;
- return true;
- } else if (streq("resize_corner", s)) {
- *a = ACTION_RESIZE_CORNER;
- return true;
- } else if (streq("resize_side", s)) {
- *a = ACTION_RESIZE_SIDE;
- return true;
- } else if (streq("focus", s)) {
- *a = ACTION_FOCUS;
- return true;
- }
- return false;
-}
-
-bool parse_child_polarity(char *s, child_polarity_t *p)
-{
- if (streq("first_child", s)) {
- *p = FIRST_CHILD;
- return true;
- } else if (streq("second_child", s)) {
- *p = SECOND_CHILD;
- return true;
- }
- return false;
-}
-
-bool parse_degree(char *s, int *d)
-{
- int i = atoi(s);
- while (i < 0)
- i += 360;
- while (i > 359)
- i -= 360;
- if ((i % 90) != 0) {
- return false;
- } else {
- *d = i;
- return true;
- }
-}
-
-bool parse_window_id(char *s, long int *i)
-{
- char *end;
- errno = 0;
- long int ret = strtol(s, &end, 0);
- if (errno != 0 || *end != '\0')
- return false;
- else
- *i = ret;
- return true;
-}
-
-bool parse_bool_declaration(char *s, char **key, bool *value, alter_state_t *state)
-{
- *key = strtok(s, EQL_TOK);
- char *v = strtok(NULL, EQL_TOK);
- if (v == NULL) {
- *state = ALTER_TOGGLE;
- return true;
- } else {
- if (parse_bool(v, value)) {
- *state = ALTER_SET;
- return true;
- } else {
- return false;
- }
- }
- return false;
-}
-
-bool parse_index(char *s, int *i)
-{
- int idx;
- if (sscanf(s, "^%i", &idx) != 1 || idx < 1)
- return false;
- *i = idx;
- return true;
-}
#include "types.h"
#include "subscribe.h"
-#define OPT_CHR '-'
-#define CAT_CHR '.'
-#define EQL_TOK "="
-
int handle_message(char *msg, int msg_len, FILE *rsp);
int process_message(char **args, int num, FILE *rsp);
int cmd_window(char **args, int num);
#include "window.h"
#include "monitor.h"
-monitor_t *make_monitor(xcb_rectangle_t rect)
+monitor_t *make_monitor(xcb_rectangle_t *rect)
{
monitor_t *m = malloc(sizeof(monitor_t));
snprintf(m->name, sizeof(m->name), "%s%02d", DEFAULT_MON_NAME, ++monitor_uid);
m->prev = m->next = NULL;
m->desk = m->desk_head = m->desk_tail = NULL;
- m->rectangle = rect;
m->top_padding = m->right_padding = m->bottom_padding = m->left_padding = 0;
m->wired = true;
m->num_sticky = 0;
- uint32_t values[] = {XCB_EVENT_MASK_ENTER_WINDOW};
- m->root = xcb_generate_id(dpy);
- xcb_create_window(dpy, XCB_COPY_FROM_PARENT, m->root, root, rect.x, rect.y, rect.width, rect.height, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, XCB_CW_EVENT_MASK, values);
- xcb_icccm_set_wm_class(dpy, m->root, sizeof(ROOT_WINDOW_IC), ROOT_WINDOW_IC);
- window_lower(m->root);
- if (focus_follows_pointer) {
- window_show(m->root);
+ if (rect != NULL) {
+ update_root(m, rect);
+ } else {
+ m->root = XCB_NONE;
+ m->rectangle = (xcb_rectangle_t) {0, 0, screen_width, screen_height};
}
return m;
}
+void update_root(monitor_t *m, xcb_rectangle_t *r)
+{
+ m->rectangle = *r;
+ if (m->root == XCB_NONE) {
+ uint32_t values[] = {XCB_EVENT_MASK_ENTER_WINDOW};
+ m->root = xcb_generate_id(dpy);
+ xcb_create_window(dpy, XCB_COPY_FROM_PARENT, m->root, root, r->x, r->y, r->width, r->height, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, XCB_CW_EVENT_MASK, values);
+ xcb_icccm_set_wm_class(dpy, m->root, sizeof(ROOT_WINDOW_IC), ROOT_WINDOW_IC);
+ window_lower(m->root);
+ if (focus_follows_pointer) {
+ window_show(m->root);
+ }
+ } else {
+ window_move_resize(m->root, r->x, r->y, r->width, r->height);
+ put_status(SBSC_MASK_MONITOR_GEOMETRY, "monitor_geometry %s %ux%u+%i+%i\n", m->name, r->width, r->height, r->x, r->y);
+ }
+}
+
void rename_monitor(monitor_t *m, const char *name)
{
put_status(SBSC_MASK_MONITOR_RENAME, "monitor_rename %s %s\n", m->name, name);
c->floating_rectangle.y = md->rectangle.y + dy_d - top_adjust;
}
-void update_root(monitor_t *m)
-{
- xcb_rectangle_t r = m->rectangle;
- window_move_resize(m->root, r.x, r.y, r.width, r.height);
- put_status(SBSC_MASK_MONITOR_GEOMETRY, "monitor_geometry %s %ux%u+%i+%i\n", m->name, r.width, r.height, r.x, r.y);
-}
-
void focus_monitor(monitor_t *m)
{
if (mon == m)
m->prev = mon_tail;
mon_tail = m;
}
-
- num_monitors++;
}
void remove_monitor(monitor_t *m)
xcb_destroy_window(dpy, m->root);
free(m);
- num_monitors--;
put_status(SBSC_MASK_REPORT);
}
xcb_rectangle_t rect = (xcb_rectangle_t) {cir->x, cir->y, cir->width, cir->height};
mm = get_monitor_by_id(outputs[i]);
if (mm != NULL) {
- mm->rectangle = rect;
- update_root(mm);
+ update_root(mm, &rect);
for (desktop_t *d = mm->desk_head; d != NULL; d = d->next) {
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
translate_client(mm, mm, n->client);
arrange(mm, mm->desk);
mm->wired = true;
} else {
- mm = make_monitor(rect);
+ mm = make_monitor(&rect);
char *name = (char *)xcb_randr_get_output_info_name(info);
size_t name_len = MIN(sizeof(mm->name), (size_t)xcb_randr_get_output_info_name_length(info) + 1);
snprintf(mm->name, name_len, "%s", name);
free(sres);
update_motion_recorder();
- return (num_monitors > 0);
+ return (mon_head != NULL);
}
#define DEFAULT_MON_NAME "MONITOR"
-monitor_t *make_monitor(xcb_rectangle_t rect);
+monitor_t *make_monitor(xcb_rectangle_t *rect);
+void update_root(monitor_t *m, xcb_rectangle_t *r);
void rename_monitor(monitor_t *m, const char *name);
monitor_t *find_monitor(char *name);
monitor_t *get_monitor_by_id(xcb_randr_output_t id);
void embrace_client(monitor_t *m, client_t *c);
void translate_client(monitor_t *ms, monitor_t *md, client_t *c);
-void update_root(monitor_t *m);
void focus_monitor(monitor_t *m);
void add_monitor(monitor_t *m);
void remove_monitor(monitor_t *m);
--- /dev/null
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "helpers.h"
+#include "parse.h"
+
+bool parse_bool(char *value, bool *b)
+{
+ if (streq("true", value) || streq("on", value)) {
+ *b = true;
+ return true;
+ } else if (streq("false", value) || streq("off", value)) {
+ *b = false;
+ return true;
+ }
+ return false;
+}
+
+bool parse_split_type(char *s, split_type_t *t)
+{
+ if (streq("horizontal", s)) {
+ *t = TYPE_HORIZONTAL;
+ return true;
+ } else if (streq("vertical", s)) {
+ *t = TYPE_VERTICAL;
+ return true;
+ }
+ return false;
+}
+
+bool parse_split_mode(char *s, split_mode_t *m)
+{
+ if (streq("automatic", s)) {
+ *m = MODE_AUTOMATIC;
+ return true;
+ } else if (streq("vertical", s)) {
+ *m = MODE_MANUAL;
+ return true;
+ }
+ return false;
+}
+
+bool parse_layout(char *s, layout_t *l)
+{
+ if (streq("monocle", s)) {
+ *l = LAYOUT_MONOCLE;
+ return true;
+ } else if (streq("tiled", s)) {
+ *l = LAYOUT_TILED;
+ return true;
+ }
+ return false;
+}
+
+bool parse_client_state(char *s, client_state_t *t)
+{
+ if (streq("tiled", s)) {
+ *t = STATE_TILED;
+ return true;
+ } else if (streq("pseudo_tiled", s)) {
+ *t = STATE_PSEUDO_TILED;
+ return true;
+ } else if (streq("floating", s)) {
+ *t = STATE_FLOATING;
+ return true;
+ } else if (streq("fullscreen", s)) {
+ *t = STATE_FULLSCREEN;
+ return true;
+ }
+ return false;
+}
+
+bool parse_stack_layer(char *s, stack_layer_t *l)
+{
+ if (streq("below", s)) {
+ *l = LAYER_BELOW;
+ return true;
+ } else if (streq("normal", s)) {
+ *l = LAYER_NORMAL;
+ return true;
+ } else if (streq("above", s)) {
+ *l = LAYER_ABOVE;
+ return true;
+ }
+ return false;
+}
+
+bool parse_direction(char *s, direction_t *d)
+{
+ if (streq("right", s)) {
+ *d = DIR_RIGHT;
+ return true;
+ } else if (streq("down", s)) {
+ *d = DIR_DOWN;
+ return true;
+ } else if (streq("left", s)) {
+ *d = DIR_LEFT;
+ return true;
+ } else if (streq("up", s)) {
+ *d = DIR_UP;
+ return true;
+ }
+ return false;
+}
+
+bool parse_cycle_direction(char *s, cycle_dir_t *d)
+{
+ if (streq("next", s)) {
+ *d = CYCLE_NEXT;
+ return true;
+ } else if (streq("prev", s)) {
+ *d = CYCLE_PREV;
+ return true;
+ }
+ return false;
+}
+
+bool parse_circulate_direction(char *s, circulate_dir_t *d)
+{
+ if (streq("forward", s)) {
+ *d = CIRCULATE_FORWARD;
+ return true;
+ } else if (streq("backward", s)) {
+ *d = CIRCULATE_BACKWARD;
+ return true;
+ }
+ return false;
+}
+
+bool parse_history_direction(char *s, history_dir_t *d)
+{
+ if (streq("older", s)) {
+ *d = HISTORY_OLDER;
+ return true;
+ } else if (streq("newer", s)) {
+ *d = HISTORY_NEWER;
+ return true;
+ }
+ return false;
+}
+
+
+bool parse_flip(char *s, flip_t *f)
+{
+ if (streq("horizontal", s)) {
+ *f = FLIP_HORIZONTAL;
+ return true;
+ } else if (streq("vertical", s)) {
+ *f = FLIP_VERTICAL;
+ return true;
+ }
+ return false;
+}
+
+bool parse_pointer_action(char *s, pointer_action_t *a)
+{
+ if (streq("move", s)) {
+ *a = ACTION_MOVE;
+ return true;
+ } else if (streq("resize_corner", s)) {
+ *a = ACTION_RESIZE_CORNER;
+ return true;
+ } else if (streq("resize_side", s)) {
+ *a = ACTION_RESIZE_SIDE;
+ return true;
+ } else if (streq("focus", s)) {
+ *a = ACTION_FOCUS;
+ return true;
+ }
+ return false;
+}
+
+bool parse_child_polarity(char *s, child_polarity_t *p)
+{
+ if (streq("first_child", s)) {
+ *p = FIRST_CHILD;
+ return true;
+ } else if (streq("second_child", s)) {
+ *p = SECOND_CHILD;
+ return true;
+ }
+ return false;
+}
+
+bool parse_degree(char *s, int *d)
+{
+ int i = atoi(s);
+ while (i < 0)
+ i += 360;
+ while (i > 359)
+ i -= 360;
+ if ((i % 90) != 0) {
+ return false;
+ } else {
+ *d = i;
+ return true;
+ }
+}
+
+bool parse_window_id(char *s, long int *i)
+{
+ char *end;
+ errno = 0;
+ long int ret = strtol(s, &end, 0);
+ if (errno != 0 || *end != '\0')
+ return false;
+ else
+ *i = ret;
+ return true;
+}
+
+bool parse_bool_declaration(char *s, char **key, bool *value, alter_state_t *state)
+{
+ *key = strtok(s, EQL_TOK);
+ char *v = strtok(NULL, EQL_TOK);
+ if (v == NULL) {
+ *state = ALTER_TOGGLE;
+ return true;
+ } else {
+ if (parse_bool(v, value)) {
+ *state = ALTER_SET;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
+bool parse_index(char *s, int *i)
+{
+ int idx;
+ if (sscanf(s, "^%i", &idx) != 1 || idx < 1)
+ return false;
+ *i = idx;
+ return true;
+}
--- /dev/null
+#ifndef BSPWM_PARSE_H
+#define BSPWM_PARSE_H
+
+#include "types.h"
+
+#define OPT_CHR '-'
+#define CAT_CHR '.'
+#define EQL_TOK "="
+
+bool parse_bool(char *value, bool *b);
+bool parse_split_type(char *s, split_type_t *t);
+bool parse_split_mode(char *s, split_mode_t *m);
+bool parse_layout(char *s, layout_t *l);
+bool parse_client_state(char *s, client_state_t *t);
+bool parse_stack_layer(char *s, stack_layer_t *l);
+bool parse_direction(char *s, direction_t *d);
+bool parse_cycle_direction(char *s, cycle_dir_t *d);
+bool parse_circulate_direction(char *s, circulate_dir_t *d);
+bool parse_history_direction(char *s, history_dir_t *d);
+bool parse_flip(char *s, flip_t *f);
+bool parse_pointer_action(char *s, pointer_action_t *a);
+bool parse_child_polarity(char *s, child_polarity_t *p);
+bool parse_degree(char *s, int *d);
+bool parse_window_id(char *s, long int *i);
+bool parse_bool_declaration(char *s, char **key, bool *value, alter_state_t *state);
+bool parse_index(char *s, int *i);
+
+#endif
#include "bspwm.h"
#include "desktop.h"
#include "history.h"
-#include "messages.h"
+#include "parse.h"
#include "monitor.h"
#include "tree.h"
#include "query.h"
+#include "jsmn.h"
-void query_monitors(coordinates_t loc, domain_t dom, FILE *rsp)
+void query_tree(FILE *rsp)
{
+ fprintf(rsp, "{");
+ fprintf(rsp, "\"focusedMonitorName\": \"%s\", ", mon->name);
+ fprintf(rsp, "\"numClients\": %i, ", num_clients);
+ fprintf(rsp, "\"monitors\": ");
+ fprintf(rsp, "[");
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
- if (loc.monitor != NULL && m != loc.monitor)
- continue;
- if (dom != DOMAIN_DESKTOP) {
- if (dom == DOMAIN_MONITOR) {
- fprintf(rsp, "%s\n", m->name);
- continue;
- } else {
- fprintf(rsp, "%s %ux%u%+i%+i %i,%i,%i,%i%s\n", m->name,
- m->rectangle.width,m->rectangle.height, m->rectangle.x, m->rectangle.y,
- m->top_padding, m->right_padding, m->bottom_padding, m->left_padding,
- (m == mon ? " *" : ""));
- }
+ query_monitor(m, rsp);
+ if (m->next != NULL) {
+ fprintf(rsp, ", ");
}
- query_desktops(m, dom, loc, (dom == DOMAIN_DESKTOP ? 0 : 1), rsp);
}
+ fprintf(rsp, "]");
+ fprintf(rsp, "}");
+
}
-void query_desktops(monitor_t *m, domain_t dom, coordinates_t loc, unsigned int depth, FILE *rsp)
+void query_monitor(monitor_t *m, FILE *rsp)
{
+ fprintf(rsp, "{");
+ fprintf(rsp, "\"name\": \"%s\", ", m->name);
+ fprintf(rsp, "\"id\": %u, ", m->id);
+ fprintf(rsp, "\"wired\": %s, ", BOOL_STR(m->wired));
+ fprintf(rsp, "\"topPadding\": %i, ", m->top_padding);
+ fprintf(rsp, "\"rightPadding\": %i, ", m->right_padding);
+ fprintf(rsp, "\"bottomPadding\": %i, ", m->bottom_padding);
+ fprintf(rsp, "\"leftPadding\": %i, ", m->left_padding);
+ fprintf(rsp, "\"numSticky\": %i, ", m->num_sticky);
+ fprintf(rsp, "\"rectangle\": ");
+ query_rectangle(m->rectangle, rsp);
+ fprintf(rsp, ", ");
+ fprintf(rsp, "\"focusedDesktopName\": \"%s\", ", m->desk->name);
+ fprintf(rsp, "\"desktops\": ");
+ fprintf(rsp, "[");
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
- if (loc.desktop != NULL && d != loc.desktop)
- continue;
- for (unsigned int i = 0; i < depth; i++)
- fprintf(rsp, "\t");
- if (dom == DOMAIN_DESKTOP) {
- fprintf(rsp, "%s\n", d->name);
- continue;
- } else {
- fprintf(rsp, "%s %u %i %i,%i,%i,%i %c%s\n", d->name, d->border_width,
- d->window_gap,
- d->top_padding, d->right_padding, d->bottom_padding, d->left_padding,
- (d->layout == LAYOUT_TILED ? 'T' : 'M'),
- (d == m->desk ? " *" : ""));
+ query_desktop(d, rsp);
+ if (d->next != NULL) {
+ fprintf(rsp, ", ");
}
- query_tree(d, d->root, rsp, depth + 1);
}
+ fprintf(rsp, "]");
+ fprintf(rsp, "}");
+}
+
+void query_desktop(desktop_t *d, FILE *rsp)
+{
+ fprintf(rsp, "{");
+ fprintf(rsp, "\"name\": \"%s\", ", d->name);
+ fprintf(rsp, "\"layout\": \"%s\", ", LAYOUT_STR(d->layout));
+ fprintf(rsp, "\"topPadding\": %i, ", d->top_padding);
+ fprintf(rsp, "\"rightPadding\": %i, ", d->right_padding);
+ fprintf(rsp, "\"bottomPadding\": %i, ", d->bottom_padding);
+ fprintf(rsp, "\"leftPadding\": %i, ", d->left_padding);
+ fprintf(rsp, "\"windowGap\": %i, ", d->window_gap);
+ fprintf(rsp, "\"borderWidth\": %u, ", d->border_width);
+ fprintf(rsp, "\"focusedWindow\": %u, ", d->focus != NULL ? d->focus->client->window : 0);
+ fprintf(rsp, "\"root\": ");
+ query_node(d->root, rsp);
+ fprintf(rsp, "}");
}
-void query_tree(desktop_t *d, node_t *n, FILE *rsp, unsigned int depth)
+void query_node(node_t *n, FILE *rsp)
{
- if (n == NULL)
- return;
-
- for (unsigned int i = 0; i < depth; i++)
- fprintf(rsp, "\t");
-
- if (is_leaf(n)) {
- client_t *c = n->client;
- fprintf(rsp, "%c %s %s 0x%X %u %ux%u%+i%+i %c%c %c%c %c%c%c%c%s\n",
- (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')),
- c->class_name, c->instance_name, c->window, c->border_width,
- c->floating_rectangle.width, c->floating_rectangle.height,
- c->floating_rectangle.x, c->floating_rectangle.y,
- (n->split_dir == DIR_UP ? 'U' : (n->split_dir == DIR_RIGHT ? 'R' : (n->split_dir == DIR_DOWN ? 'D' : 'L'))),
- (n->split_mode == MODE_AUTOMATIC ? '-' : 'p'),
- (c->state == STATE_TILED ? '-' : (c->state == STATE_FLOATING ? 'f' : (c->state == STATE_FULLSCREEN ? 'F' : 'p'))),
- (c->layer == LAYER_NORMAL ? '-' : (c->layer == LAYER_ABOVE ? 'a' : 'b')),
- (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (c->private ? 'i' : '-'),
- (n == d->focus ? " *" : ""));
+ if (n == NULL) {
+ fprintf(rsp, "null");
} else {
- fprintf(rsp, "%c %c %lf\n", (n->split_type == TYPE_HORIZONTAL ? 'H' : 'V'),
- (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), n->split_ratio);
+ fprintf(rsp, "{");
+ fprintf(rsp, "\"splitType\": \"%s\", ", SPLIT_TYPE_STR(n->split_type));
+ fprintf(rsp, "\"splitRatio\": %lf, ", n->split_ratio);
+ fprintf(rsp, "\"splitMode\": \"%s\", ", SPLIT_MODE_STR(n->split_mode));
+ fprintf(rsp, "\"splitDir\": \"%s\", ", SPLIT_DIR_STR(n->split_dir));
+ fprintf(rsp, "\"birthRotation\": %i, ", n->birth_rotation);
+ fprintf(rsp, "\"privacyLevel\": %i, ", n->privacy_level);
+ fprintf(rsp, "\"vacant\": %s, ", BOOL_STR(n->vacant));
+ fprintf(rsp, "\"rectangle\": ");
+ query_rectangle(n->rectangle, rsp);
+ fprintf(rsp, ", ");
+ fprintf(rsp, "\"firstChild\": ");
+ query_node(n->first_child, rsp);
+ fprintf(rsp, ", ");
+ fprintf(rsp, "\"secondChild\": ");
+ query_node(n->second_child, rsp);
+ fprintf(rsp, ", ");
+ fprintf(rsp, "\"client\": ");
+ query_client(n->client, rsp);
+ fprintf(rsp, "}");
}
+}
+
+void query_client(client_t *c, FILE *rsp)
+{
+ if (c == NULL) {
+ fprintf(rsp, "null");
+ } else {
+ fprintf(rsp, "{");
+ fprintf(rsp, "\"window\": %u, ", c->window);
+ fprintf(rsp, "\"className\": \"%s\", ", c->class_name);
+ fprintf(rsp, "\"instanceName\": \"%s\", ", c->instance_name);
+ fprintf(rsp, "\"borderWidth\": %u, ", c->border_width);
+ fprintf(rsp, "\"state\": \"%s\", ", STATE_STR(c->state));
+ fprintf(rsp, "\"lastState\": \"%s\", ", STATE_STR(c->last_state));
+ fprintf(rsp, "\"layer\": \"%s\", ", LAYER_STR(c->layer));
+ fprintf(rsp, "\"lastLayer\": \"%s\", ", LAYER_STR(c->last_layer));
+ fprintf(rsp, "\"locked\": %s, ", BOOL_STR(c->locked));
+ fprintf(rsp, "\"sticky\": %s, ", BOOL_STR(c->sticky));
+ fprintf(rsp, "\"urgent\": %s, ", BOOL_STR(c->urgent));
+ fprintf(rsp, "\"private\": %s, ", BOOL_STR(c->private));
+ fprintf(rsp, "\"icccmFocus\": %s, ", BOOL_STR(c->icccm_focus));
+ fprintf(rsp, "\"icccmInput\": %s, ", BOOL_STR(c->icccm_input));
+ fprintf(rsp, "\"minWidth\": %u, ", c->min_width);
+ fprintf(rsp, "\"maxWidth\": %u, ", c->max_width);
+ fprintf(rsp, "\"minHeight\": %u, ", c->min_height);
+ fprintf(rsp, "\"maxHeight\": %u, ", c->max_height);
+ fprintf(rsp, "\"numStates\": %i, ", c->num_states);
+ fprintf(rsp, "\"wmState\": ");
+ query_wm_state(c->wm_state, c->num_states, rsp);
+ fprintf(rsp, ", ");
+ fprintf(rsp, "\"tiledRectangle\": ");
+ query_rectangle(c->tiled_rectangle, rsp);
+ fprintf(rsp, ", ");
+ fprintf(rsp, "\"floatingRectangle\": ");
+ query_rectangle(c->floating_rectangle, rsp);
+ fprintf(rsp, "}");
+ }
+}
+
+void query_rectangle(xcb_rectangle_t r, FILE *rsp)
+{
+ fprintf(rsp, "{\"x\": %i, \"y\": %i, \"width\": %u, \"height\": %u}", r.x, r.y, r.width, r.height);
+}
- query_tree(d, n->first_child, rsp, depth + 1);
- query_tree(d, n->second_child, rsp, depth + 1);
+void query_wm_state(xcb_atom_t *wm_state, int num_states, FILE *rsp)
+{
+ fprintf(rsp, "[");
+ for (int i = 0; i < num_states; i++) {
+ fprintf(rsp, "%u", wm_state[i]);
+ if (i < num_states - 1) {
+ fprintf(rsp, ", ");
+ }
+ }
+ fprintf(rsp, "]");
}
void query_history(coordinates_t loc, FILE *rsp)
{
for (history_t *h = history_head; h != NULL; h = h->next) {
if ((loc.monitor != NULL && h->loc.monitor != loc.monitor)
- || (loc.desktop != NULL && h->loc.desktop != loc.desktop))
+ || (loc.desktop != NULL && h->loc.desktop != loc.desktop)) {
continue;
+ }
xcb_window_t win = XCB_NONE;
- if (h->loc.node != NULL)
+ if (h->loc.node != NULL) {
win = h->loc.node->client->window;
+ }
fprintf(rsp, "%s %s 0x%X\n", h->loc.monitor->name, h->loc.desktop->name, win);
}
}
void query_stack(FILE *rsp)
{
- for (stacking_list_t *s = stack_head; s != NULL; s = s->next)
+ for (stacking_list_t *s = stack_head; s != NULL; s = s->next) {
fprintf(rsp, "0x%X\n", s->node->client->window);
+ }
}
void query_windows(coordinates_t loc, FILE *rsp)
}
}
+void query_names(domain_t dom, coordinates_t loc, FILE *rsp)
+{
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ if (loc.monitor != NULL && m != loc.monitor) {
+ continue;
+ }
+ if (dom == DOMAIN_MONITOR) {
+ fprintf(rsp, "%s\n", m->name);
+ }
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ if (loc.desktop != NULL && d != loc.desktop) {
+ continue;
+ }
+ if (dom == DOMAIN_DESKTOP) {
+ fprintf(rsp, "%s\n", d->name);
+ }
+ }
+ }
+}
+
client_select_t make_client_select(void)
{
client_select_t sel = {
history_dir_t hdi;
if (parse_direction(desc, &dir)) {
dst->node = nearest_neighbor(ref->monitor, ref->desktop, ref->node, dir, sel);
- if (dst->node == NULL && num_monitors > 1) {
+ if (dst->node == NULL && mon_head != mon_tail) {
monitor_t *m = nearest_monitor(ref->monitor, dir, make_desktop_select());
if (m != NULL) {
coordinates_t loc = {m, m->desk, m->desk->focus};
DOMAIN_STACK
} domain_t;
-void query_monitors(coordinates_t loc, domain_t dom, FILE *rsp);
-void query_desktops(monitor_t *m, domain_t dom, coordinates_t loc, unsigned int depth, FILE *rsp);
-void query_tree(desktop_t *d, node_t *n, FILE *rsp, unsigned int depth);
+void query_tree(FILE *rsp);
+void query_monitor(monitor_t *m, FILE *rsp);
+void query_desktop(desktop_t *d, FILE *rsp);
+void query_node(node_t *n, FILE *rsp);
+void query_client(client_t *c, FILE *rsp);
+void query_rectangle(xcb_rectangle_t r, FILE *rsp);
+void query_wm_state(xcb_atom_t *wm_state, int num_states, FILE *rsp);
void query_history(coordinates_t loc, FILE *rsp);
void query_stack(FILE *rsp);
void query_windows(coordinates_t loc, FILE *rsp);
+void query_names(domain_t dom, coordinates_t loc, FILE *rsp);
client_select_t make_client_select(void);
desktop_select_t make_desktop_select(void);
void cleanup_client_select(client_select_t *sel);
#include <ctype.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 "parse.h"
+#include "jsmn.h"
-void restore_tree(char *file_path)
+bool restore_tree(const char *file_path)
{
- if (file_path == NULL)
- return;
+ size_t jslen;
+ char *json = read_string(file_path, &jslen);
- FILE *snapshot = fopen(file_path, "r");
- if (snapshot == NULL) {
- warn("Restore tree: can't open '%s'.\n", file_path);
- return;
+ if (json == NULL) {
+ return false;
}
- char line[MAXLEN];
- char name[MAXLEN];
- coordinates_t loc;
- monitor_t *m = NULL;
- desktop_t *d = NULL;
- node_t *n = NULL;
- unsigned int level, last_level = 0;
+ int nbtok = 256;
+ jsmn_parser parser;
+ jsmntok_t *tokens = malloc(nbtok * sizeof(jsmntok_t));
- while (fgets(line, sizeof(line), snapshot) != NULL) {
- unsigned int len = strlen(line);
- level = 0;
-
- while (level < len && isspace(line[level]))
- level++;
-
- if (level == 0) {
- int x, y, top, right, bottom, left;
- unsigned int w, h;
- char end = 0;
- name[0] = '\0';
- sscanf(line + level, "%s %ux%u%i%i %i,%i,%i,%i %c", name, &w, &h, &x, &y,
- &top, &right, &bottom, &left, &end);
- m = find_monitor(name);
- if (m == NULL)
- continue;
- m->rectangle = (xcb_rectangle_t) {x, y, w, h};
- m->top_padding = top;
- m->right_padding = right;
- m->bottom_padding = bottom;
- m->left_padding = left;
- if (end != 0)
- mon = m;
- } else if (level == 1) {
- if (m == NULL)
- continue;
- int wg, top, right, bottom, left;
- unsigned int bw;
- char layout = 0, end = 0;
- name[0] = '\0';
- loc.desktop = NULL;
- sscanf(line + level, "%s %u %i %i,%i,%i,%i %c %c", name,
- &bw, &wg, &top, &right, &bottom, &left, &layout, &end);
- locate_desktop(name, &loc);
- d = loc.desktop;
- if (d == NULL) {
- continue;
- }
- d->border_width = bw;
- d->window_gap = wg;
- d->top_padding = top;
- d->right_padding = right;
- d->bottom_padding = bottom;
- d->left_padding = left;
- if (layout == 'M') {
- d->layout = LAYOUT_MONOCLE;
- } else if (layout == 'T') {
- d->layout = LAYOUT_TILED;
- }
- if (end != 0) {
- m->desk = d;
- }
+ if (tokens == NULL) {
+ perror("Restore tree: malloc");
+ free(json);
+ return false;
+ }
+
+ jsmn_init(&parser);
+ int ret;
+
+ while ((ret = jsmn_parse(&parser, json, jslen, tokens, nbtok)) == JSMN_ERROR_NOMEM) {
+ nbtok *= 2;
+ jsmntok_t *rtokens = realloc(tokens, nbtok * sizeof(jsmntok_t));
+ if (rtokens == NULL) {
+ perror("Restore tree: realloc");
+ free(tokens);
+ free(json);
+ return false;
} else {
- if (m == NULL || d == NULL)
- continue;
- node_t *birth = make_node();
- if (level == 2) {
- empty_desktop(d);
- d->root = birth;
- } else if (n != NULL) {
- if (level > last_level) {
- n->first_child = birth;
- } else {
- do {
- n = n->parent;
- } while (n != NULL && n->second_child != NULL);
- if (n == NULL)
- continue;
- n->second_child = birth;
- }
- birth->parent = n;
- }
- n = birth;
- char birth_rotation;
- if (isupper(line[level])) {
- char split_type;
- sscanf(line + level, "%c %c %lf", &split_type, &birth_rotation, &n->split_ratio);
- if (split_type == 'H') {
- n->split_type = TYPE_HORIZONTAL;
- } else if (split_type == 'V') {
- n->split_type = TYPE_VERTICAL;
- }
- } else {
- client_t *c = make_client(XCB_NONE, d->border_width);
- num_clients++;
- char urgent, locked, sticky, private, split_dir, split_mode, state, layer, end = 0;
- sscanf(line + level, "%c %s %s %X %u %hux%hu%hi%hi %c%c %c%c %c%c%c%c %c", &birth_rotation,
- c->class_name, c->instance_name, &c->window, &c->border_width,
- &c->floating_rectangle.width, &c->floating_rectangle.height,
- &c->floating_rectangle.x, &c->floating_rectangle.y,
- &split_dir, &split_mode, &state, &layer,
- &urgent, &locked, &sticky, &private, &end);
- n->split_mode = (split_mode == '-' ? MODE_AUTOMATIC : MODE_MANUAL);
- if (split_dir == 'U') {
- n->split_dir = DIR_UP;
- } else if (split_dir == 'R') {
- n->split_dir = DIR_RIGHT;
- } else if (split_dir == 'D') {
- n->split_dir = DIR_DOWN;
- } else if (split_dir == 'L') {
- n->split_dir = DIR_LEFT;
- }
- if (state == 'f') {
- c->state = STATE_FLOATING;
- } else if (state == 'F') {
- c->state = STATE_FULLSCREEN;
- } else if (state == 'p') {
- c->state = STATE_PSEUDO_TILED;
- }
- if (layer == 'b') {
- c->layer = LAYER_BELOW;
- } else if (layer == 'a') {
- c->layer = LAYER_ABOVE;
- }
- c->urgent = (urgent == '-' ? false : true);
- c->locked = (locked == '-' ? false : true);
- c->sticky = (sticky == '-' ? false : true);
- c->private = (private == '-' ? false : true);
- n->client = c;
- if (end != 0) {
- d->focus = n;
- }
- if (c->sticky) {
- m->num_sticky++;
- }
- }
- if (birth_rotation == 'a') {
- n->birth_rotation = 90;
- } else if (birth_rotation == 'c') {
- n->birth_rotation = 270;
- } else if (birth_rotation == 'm') {
- n->birth_rotation = 0;
+ tokens = rtokens;
+ }
+ }
+
+ if (ret < 0) {
+ warn("Restore tree: jsmn_parse: ");
+ switch (ret) {
+ case JSMN_ERROR_NOMEM:
+ warn("not enough memory.\n");
+ break;
+ case JSMN_ERROR_INVAL:
+ warn("found invalid character inside JSON string.\n");
+ break;
+ case JSMN_ERROR_PART:
+ warn("not a full JSON packet.\n");
+ break;
+ default:
+ warn("unknown error.\n");
+ break;
+ }
+
+ free(tokens);
+ free(json);
+
+ return false;
+ }
+
+ while (mon_head != NULL) {
+ remove_monitor(mon_head);
+ }
+
+ int num = tokens[0].size;
+ jsmntok_t *t = tokens + 1;
+ char *focusedMonitorName = NULL;
+
+ for (int i = 0; i < num; i++) {
+ if (keyeq("focusedMonitorName", t, json)) {
+ focusedMonitorName = copy_string(t+1, json);
+ t++;
+ } else if (keyeq("numClients", t, json)) {
+ t++;
+ sscanf(json + t->start, "%i", &num_clients);
+ } 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);
+ add_monitor(m);
+ t++;
}
}
- last_level = level;
+ t++;
}
- fclose(snapshot);
+ if (focusedMonitorName != NULL) {
+ coordinates_t loc;
+ if (locate_monitor(focusedMonitorName, &loc)) {
+ mon = loc.monitor;
+ }
+ }
+
+ free(focusedMonitorName);
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
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);
- if (!IS_TILED(n->client)) {
- n->vacant = true;
- propagate_vacant_state(n);
+ }
+ }
+ }
+
+ ewmh_update_client_list();
+ ewmh_update_number_of_desktops();
+ ewmh_update_current_desktop();
+ ewmh_update_desktop_names();
+
+ free(tokens);
+ free(json);
+
+ return true;
+}
+
+#define RESTORE_INT(o, k, p) \
+ } else if (keyeq(#k, *t, json)) { \
+ (*t)++; \
+ sscanf(json + (*t)->start, "%i", &o->p);
+
+#define RESTORE_UINT(o, k, p) \
+ } else if (keyeq(#k, *t, json)) { \
+ (*t)++; \
+ sscanf(json + (*t)->start, "%u", &o->p);
+
+#define RESTORE_USINT(o, k, p) \
+ } else if (keyeq(#k, *t, json)) { \
+ (*t)++; \
+ sscanf(json + (*t)->start, "%hu", &o->p);
+
+#define RESTORE_DOUBLE(o, k, p) \
+ } else if (keyeq(#k, *t, json)) { \
+ (*t)++; \
+ sscanf(json + (*t)->start, "%lf", &o->p);
+
+#define RESTORE_ANY(o, k, p, f) \
+ } else if (keyeq(#k, *t, json)) { \
+ (*t)++; \
+ char *val = copy_string(*t, json); \
+ f(val, &o->p); \
+ free(val);
+
+#define RESTORE_BOOL(o, k, p) RESTORE_ANY(o, k, p, parse_bool)
+
+monitor_t *restore_monitor(jsmntok_t **t, char *json)
+{
+ int num = (*t)->size;
+ (*t)++;
+ monitor_t *m = make_monitor(NULL);
+ 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)
+ } 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)) {
+ (*t)++;
+ focusedDesktopName = copy_string(*t, json);
+ } else if (keyeq("desktops", *t, json)) {
+ (*t)++;
+ int s = (*t)->size;
+ (*t)++;
+ for (int j = 0; j < s; j++) {
+ desktop_t *d = restore_desktop(t, json);
+ add_desktop(m, d);
+ }
+ continue;
+ } else {
+ warn("Restore monitor: unknown key: '%.*s'.\n", (*t)->end - (*t)->start, json + (*t)->start);
+ (*t)++;
+ }
+ (*t)++;
+ }
+
+ if (focusedDesktopName != NULL) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ if (streq(focusedDesktopName, d->name)) {
+ m->desk = d;
+ break;
+ }
+ }
+ }
+
+ free(focusedDesktopName);
+
+ return m;
+}
+
+desktop_t *restore_desktop(jsmntok_t **t, char *json)
+{
+ int s = (*t)->size;
+ (*t)++;
+ desktop_t *d = make_desktop(NULL);
+ xcb_window_t focusedWindow = 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)) {
+ (*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)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%u", &focusedWindow);
+ } else if (keyeq("root", *t, json)) {
+ (*t)++;
+ d->root = restore_node(t, json);
+ continue;
+ } else {
+ warn("Restore desktop: unknown key: '%.*s'.\n", (*t)->end - (*t)->start, json + (*t)->start);
+ (*t)++;
+ }
+ (*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;
+ }
+ }
+ }
+
+ return d;
+}
+
+node_t *restore_node(jsmntok_t **t, char *json)
+{
+ if ((*t)->type == JSMN_PRIMITIVE) {
+ (*t)++;
+ return NULL;
+ } else {
+ int s = (*t)->size;
+ (*t)++;
+ node_t *n = make_node();
+
+ for (int i = 0; i < s; i++) {
+ if (keyeq("splitType", *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)
+ } else if (keyeq("rectangle", *t, json)) {
+ (*t)++;
+ restore_rectangle(&n->rectangle, t, json);
+ continue;
+ } else if (keyeq("firstChild", *t, json)) {
+ (*t)++;
+ node_t *fc = restore_node(t, json);
+ n->first_child = fc;
+ if (fc != NULL) {
+ fc->parent = n;
}
- if (n->client->private) {
- update_privacy_level(n, true);
+ continue;
+ } else if (keyeq("secondChild", *t, json)) {
+ (*t)++;
+ node_t *sc = restore_node(t, json);
+ n->second_child = sc;
+ if (sc != NULL) {
+ sc->parent = n;
}
+ continue;
+ } else if (keyeq("client", *t, json)) {
+ (*t)++;
+ n->client = restore_client(t, json);
+ continue;
}
- /* Has the side effect of restoring the node's rectangles and the client's tiled rectangles */
- arrange(m, d);
+ (*t)++;
}
+
+ return n;
}
+}
- ewmh_update_current_desktop();
+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(XCB_NONE, 0);
+
+ for (int i = 0; i < s; i++) {
+ if (keyeq("window", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%u", &c->window);
+ } else 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)
+ } else if (keyeq("wmState", *t, json)) {
+ (*t)++;
+ restore_wm_state(c->wm_state, t, json);
+ continue;
+ } else if (keyeq("tiledRectangle", *t, json)) {
+ (*t)++;
+ restore_rectangle(&c->tiled_rectangle, t, json);
+ continue;
+ } else if (keyeq("floatingRectangle", *t, json)) {
+ (*t)++;
+ restore_rectangle(&c->floating_rectangle, t, json);
+ continue;
+ }
+
+ (*t)++;
+ }
+
+ return c;
+ }
+}
+
+void restore_rectangle(xcb_rectangle_t *r, jsmntok_t **t, char *json)
+{
+ int s = (*t)->size;
+ (*t)++;
+
+ for (int i = 0; i < s; i++) {
+ if (keyeq("x", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%hi", &r->x);
+ } else if (keyeq("y", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%hi", &r->y);
+ } else if (keyeq("width", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%hu", &r->width);
+ } else if (keyeq("height", *t, json)) {
+ (*t)++;
+ sscanf(json + (*t)->start, "%hu", &r->height);
+ }
+ (*t)++;
+ }
+}
+
+void restore_wm_state(xcb_atom_t *w, jsmntok_t **t, char *json)
+{
+ int s = (*t)->size;
+ (*t)++;
+
+ for (int i = 0; i < s; i++) {
+ sscanf(json + (*t)->start, "%u", &w[i]);
+ (*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)
+{
+ return (strncmp(s, json + key->start, key->end - key->start) == 0);
+}
+
+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;
+ }
+ strncpy(res, json+tok->start, len-1);
+ res[len-1] = '\0';
+ return res;
}
-void restore_history(char *file_path)
+bool restore_history(const char *file_path)
{
- if (file_path == NULL)
- return;
+ if (file_path == NULL) {
+ return false;
+ }
FILE *snapshot = fopen(file_path, "r");
if (snapshot == NULL) {
- warn("Restore history: can't open '%s'.\n", file_path);
- return;
+ perror("Restore history: fopen");
+ return false;
}
char line[MAXLEN];
char dnm[SMALEN];
xcb_window_t win;
+ empty_history();
+
while (fgets(line, sizeof(line), snapshot) != NULL) {
if (sscanf(line, "%s %s %X", mnm, dnm, &win) == 3) {
coordinates_t loc;
}
fclose(snapshot);
+ return true;
}
-void restore_stack(char *file_path)
+bool restore_stack(const char *file_path)
{
- if (file_path == NULL)
- return;
+ if (file_path == NULL) {
+ return false;
+ }
FILE *snapshot = fopen(file_path, "r");
if (snapshot == NULL) {
- warn("Restore stack: can't open '%s'.\n", file_path);
- return;
+ perror("Restore stack: fopen");
+ return false;
}
char line[MAXLEN];
xcb_window_t win;
+ while (stack_head != NULL) {
+ remove_stack(stack_head);
+ }
+
while (fgets(line, sizeof(line), snapshot) != NULL) {
if (sscanf(line, "%X", &win) == 1) {
coordinates_t loc;
- if (locate_window(win, &loc))
+ if (locate_window(win, &loc)) {
stack_insert_after(stack_tail, loc.node);
- else
+ } else {
warn("Can't locate window 0x%X.\n", win);
+ }
} else {
warn("Can't parse stack entry: '%s'\n", line);
}
}
fclose(snapshot);
+ return true;
}
#ifndef BSPWM_RESTORE_H
#define BSPWM_RESTORE_H
-void restore_tree(char *file_path);
-void restore_history(char *file_path);
-void restore_stack(char *file_path);
+#include "jsmn.h"
+
+bool restore_tree(const char *file_path);
+monitor_t *restore_monitor(jsmntok_t **t, char *json);
+desktop_t *restore_desktop(jsmntok_t **t, char *json);
+node_t *restore_node(jsmntok_t **t, char *json);
+client_t *restore_client(jsmntok_t **t, char *json);
+void restore_rectangle(xcb_rectangle_t *r, jsmntok_t **t, char *json);
+void restore_wm_state(xcb_atom_t *w, jsmntok_t **t, char *json);
+bool keyeq(char *s, jsmntok_t *key, char *json);
+char *copy_string(jsmntok_t *tok, char *json);
+bool restore_history(const char *file_path);
+bool restore_stack(const char *file_path);
#endif
#include "bspwm.h"
#include "ewmh.h"
#include "window.h"
-#include "messages.h"
+#include "parse.h"
#include "settings.h"
#include "rule.h"
}
}
d->focus = n;
- put_status(SBSC_MASK_WINDOW_ACTIVATE, "window_activate %s %s 0x%X\n", m->name, d->name, n->client->window);
+ put_status(SBSC_MASK_WINDOW_ACTIVATE, "window_activate %s %s 0x%X\n", m->name, d->name, n!=NULL?n->client->window:0);
}
void focus_node(monitor_t *m, desktop_t *d, node_t *n)
c->border_width = border_width;
c->locked = c->sticky = c->urgent = c->private = c->icccm_focus = false;
c->icccm_input = true;
- xcb_icccm_get_wm_protocols_reply_t protocols;
- if (xcb_icccm_get_wm_protocols_reply(dpy, xcb_icccm_get_wm_protocols(dpy, win, ewmh->WM_PROTOCOLS), &protocols, NULL) == 1) {
- if (has_proto(WM_TAKE_FOCUS, &protocols)) {
- c->icccm_focus = true;
- }
- xcb_icccm_get_wm_protocols_reply_wipe(&protocols);
- }
c->num_states = 0;
- xcb_ewmh_get_atoms_reply_t wm_state;
- if (xcb_ewmh_get_wm_state_reply(ewmh, xcb_ewmh_get_wm_state(ewmh, win), &wm_state, NULL) == 1) {
- for (unsigned int i = 0; i < wm_state.atoms_len && i < MAX_STATE; i++) {
- ewmh_wm_state_add(c, wm_state.atoms[i]);
+ if (win != XCB_NONE) {
+ xcb_icccm_get_wm_protocols_reply_t protocols;
+ if (xcb_icccm_get_wm_protocols_reply(dpy, xcb_icccm_get_wm_protocols(dpy, win, ewmh->WM_PROTOCOLS), &protocols, NULL) == 1) {
+ if (has_proto(WM_TAKE_FOCUS, &protocols)) {
+ c->icccm_focus = true;
+ }
+ xcb_icccm_get_wm_protocols_reply_wipe(&protocols);
+ }
+ xcb_ewmh_get_atoms_reply_t wm_state;
+ if (xcb_ewmh_get_wm_state_reply(ewmh, xcb_ewmh_get_wm_state(ewmh, win), &wm_state, NULL) == 1) {
+ for (unsigned int i = 0; i < wm_state.atoms_len && i < MAX_STATE; i++) {
+ ewmh_wm_state_add(c, wm_state.atoms[i]);
+ }
+ xcb_ewmh_get_atoms_reply_wipe(&wm_state);
+ }
+ xcb_icccm_wm_hints_t hints;
+ if (xcb_icccm_get_wm_hints_reply(dpy, xcb_icccm_get_wm_hints(dpy, win), &hints, NULL) == 1
+ && (hints.flags & XCB_ICCCM_WM_HINT_INPUT)) {
+ c->icccm_input = hints.input;
}
- xcb_ewmh_get_atoms_reply_wipe(&wm_state);
- }
- xcb_icccm_wm_hints_t hints;
- if (xcb_icccm_get_wm_hints_reply(dpy, xcb_icccm_get_wm_hints(dpy, win), &hints, NULL) == 1
- && (hints.flags & XCB_ICCCM_WM_HINT_INPUT)) {
- c->icccm_input = hints.input;
}
return c;
}
node_t *next_leaf(node_t *n, node_t *r)
{
- if (n == NULL)
+ if (n == NULL) {
return NULL;
+ }
node_t *p = n;
- while (is_second_child(p) && p != r)
+ while (is_second_child(p) && p != r) {
p = p->parent;
- if (p == r)
+ }
+ if (p == r) {
return NULL;
+ }
return first_extrema(p->parent->second_child);
}
d->focus = first_extrema(d->root);
}
}
- if (n->client->sticky)
+
+ if (n->client->sticky) {
m->num_sticky--;
+ }
+
put_status(SBSC_MASK_REPORT);
}
num_clients--;
ewmh_update_client_list();
- if (focused)
+ if (focused) {
update_current();
+ }
}
void destroy_tree(node_t *n)
{
- if (n == NULL)
+ if (n == NULL) {
return;
+ }
node_t *first_tree = n->first_child;
node_t *second_tree = n->second_child;
if (n->client != NULL) {
+ remove_stack_node(n);
free(n->client);
num_clients--;
}
bool sticky;
bool urgent;
bool private;
- bool icccm_focus;
- bool icccm_input;
client_state_t state;
client_state_t last_state;
stack_layer_t layer;
stack_layer_t last_layer;
xcb_rectangle_t floating_rectangle;
xcb_rectangle_t tiled_rectangle;
+ bool icccm_focus;
+ bool icccm_input;
uint16_t min_width;
uint16_t max_width;
uint16_t min_height;
struct monitor_t {
char name[SMALEN];
xcb_randr_output_t id;
- xcb_rectangle_t rectangle;
xcb_window_t root;
bool wired;
int top_padding;
int right_padding;
int bottom_padding;
int left_padding;
+ int num_sticky;
+ xcb_rectangle_t rectangle;
desktop_t *desk;
desktop_t *desk_head;
desktop_t *desk_tail;
monitor_t *prev;
monitor_t *next;
- int num_sticky;
};
typedef struct {
#include "stack.h"
#include "tree.h"
#include "subscribe.h"
-#include "messages.h"
+#include "parse.h"
#include "window.h"
void schedule_window(xcb_window_t win)
break;
case STATE_FULLSCREEN:
default:
- return m->rectangle;
+ return m != NULL ? m->rectangle : (xcb_rectangle_t) {0, 0, screen_width, screen_height};
break;
}
}
c->layer = l;
- put_status(SBSC_MASK_WINDOW_LAYER, "window_layer %s %s 0x%X %s\n", m->name, d->name, c->window, LAYERSTR(l));
+ put_status(SBSC_MASK_WINDOW_LAYER, "window_layer %s %s 0x%X %s\n", m->name, d->name, c->window, LAYER_STR(l));
if (d->focus == n) {
neutralize_obscuring_windows(m, d, n);
break;
}
- put_status(SBSC_MASK_WINDOW_STATE, "window_state %s %s 0x%X %s off\n", m->name, d->name, c->window, STATESTR(c->last_state));
+ put_status(SBSC_MASK_WINDOW_STATE, "window_state %s %s 0x%X %s off\n", m->name, d->name, c->window, STATE_STR(c->last_state));
switch (c->state) {
case STATE_TILED:
break;
}
- put_status(SBSC_MASK_WINDOW_STATE, "window_state %s %s 0x%X %s on\n", m->name, d->name, c->window, STATESTR(c->state));
+ put_status(SBSC_MASK_WINDOW_STATE, "window_state %s %s 0x%X %s on\n", m->name, d->name, c->window, STATE_STR(c->state));
}
void set_floating(monitor_t *m, desktop_t *d, node_t *n, bool value)
client_t *c = n->client;
- put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X locked %s\n", m->name, d->name, c->window, ONOFFSTR(value));
+ put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X locked %s\n", m->name, d->name, c->window, ON_OFF_STR(value));
c->locked = value;
window_draw_border(n, d->focus == n, m == mon);
client_t *c = n->client;
- put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X sticky %s\n", m->name, d->name, c->window, ONOFFSTR(value));
+ put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X sticky %s\n", m->name, d->name, c->window, ON_OFF_STR(value));
if (d != m->desk)
transfer_node(m, d, n, m, m->desk, m->desk->focus);
client_t *c = n->client;
- put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X private %s\n", m->name, d->name, c->window, ONOFFSTR(value));
+ put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X private %s\n", m->name, d->name, c->window, ON_OFF_STR(value));
c->private = value;
update_privacy_level(n, value);
n->client->urgent = value;
window_draw_border(n, d->focus == n, m == mon);
- put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X urgent %s\n", m->name, d->name, n->client->window, ONOFFSTR(value));
+ put_status(SBSC_MASK_WINDOW_FLAG, "window_flag %s %s 0x%X urgent %s\n", m->name, d->name, n->client->window, ON_OFF_STR(value));
put_status(SBSC_MASK_REPORT);
}