13 #include <yajl/yajl_common.h> 14 #include <yajl/yajl_gen.h> 15 #include <yajl/yajl_parse.h> 16 #include <yajl/yajl_version.h> 48 static
int json_start_map(
void *
ctx) {
51 LOG(
"creating new swallow\n");
54 current_swallow->
dock = M_DONTCHECK;
60 DLOG(
"New floating_node\n");
63 json_node->
name = NULL;
65 DLOG(
"Parent is workspace = %p\n", ws);
69 json_node->
name = NULL;
70 json_node->
parent = parent;
85 DLOG(
"Setting layout = L_SPLITH\n");
92 DLOG(
"sanity check: removing swallows specification from split container\n");
101 if (json_node->
type == CT_WORKSPACE) {
103 DLOG(
"Attaching workspace. name = %s\n", json_node->
name);
104 if (json_node->
name == NULL || strcmp(json_node->
name,
"") == 0) {
112 Con *workspace = NULL;
117 while (workspace != NULL) {
136 if (json_node->
type == CT_FLOATING_CON) {
143 const Rect zero = {0, 0, 0, 0};
144 if (memcmp(&(json_node->
rect), &zero,
sizeof(
Rect)) == 0) {
145 DLOG(
"Geometry not set, combining children\n");
170 LOG(
"Creating window\n");
172 json_node = json_node->
parent;
180 ELOG(
"Layout file is invalid: found an empty swallow definition.\n");
192 LOG(
"end of array\n");
207 LOG(
"focus (reverse) %d\n", mapping->
old_id);
212 LOG(
"got it! %p\n", con);
229 static int json_key(
void *
ctx,
const unsigned char *val,
size_t len) {
230 LOG(
"key: %.*s\n", (
int)len, val);
234 if (strcasecmp(
last_key,
"swallows") == 0)
237 if (strcasecmp(
last_key,
"rect") == 0)
240 if (strcasecmp(
last_key,
"deco_rect") == 0)
243 if (strcasecmp(
last_key,
"window_rect") == 0)
246 if (strcasecmp(
last_key,
"geometry") == 0)
249 if (strcasecmp(
last_key,
"focus") == 0)
252 if (strcasecmp(
last_key,
"marks") == 0) {
261 LOG(
"string: %.*s for key %s\n", (
int)len, val,
last_key);
265 if (strcasecmp(
last_key,
"class") == 0) {
268 }
else if (strcasecmp(
last_key,
"instance") == 0) {
271 }
else if (strcasecmp(
last_key,
"window_role") == 0) {
274 }
else if (strcasecmp(
last_key,
"title") == 0) {
288 if (strcasecmp(
last_key,
"name") == 0) {
290 memcpy(json_node->
name, val, len);
291 }
else if (strcasecmp(
last_key,
"title_format") == 0) {
294 }
else if (strcasecmp(
last_key,
"sticky_group") == 0) {
297 LOG(
"sticky_group of this container is %s\n", json_node->
sticky_group);
298 }
else if (strcasecmp(
last_key,
"orientation") == 0) {
307 if (strcasecmp(buf,
"none") == 0 ||
308 strcasecmp(buf,
"horizontal") == 0)
310 else if (strcasecmp(buf,
"vertical") == 0)
313 LOG(
"Unhandled orientation: %s\n", buf);
315 }
else if (strcasecmp(
last_key,
"border") == 0) {
318 if (strcasecmp(buf,
"none") == 0)
320 else if (strcasecmp(buf,
"1pixel") == 0) {
323 }
else if (strcasecmp(buf,
"pixel") == 0)
325 else if (strcasecmp(buf,
"normal") == 0)
328 LOG(
"Unhandled \"border\": %s\n", buf);
330 }
else if (strcasecmp(
last_key,
"type") == 0) {
333 if (strcasecmp(buf,
"root") == 0)
334 json_node->
type = CT_ROOT;
335 else if (strcasecmp(buf,
"output") == 0)
336 json_node->
type = CT_OUTPUT;
337 else if (strcasecmp(buf,
"con") == 0)
338 json_node->
type = CT_CON;
339 else if (strcasecmp(buf,
"floating_con") == 0)
340 json_node->
type = CT_FLOATING_CON;
341 else if (strcasecmp(buf,
"workspace") == 0)
342 json_node->
type = CT_WORKSPACE;
343 else if (strcasecmp(buf,
"dockarea") == 0)
344 json_node->
type = CT_DOCKAREA;
346 LOG(
"Unhandled \"type\": %s\n", buf);
348 }
else if (strcasecmp(
last_key,
"layout") == 0) {
351 if (strcasecmp(buf,
"default") == 0)
354 else if (strcasecmp(buf,
"stacked") == 0)
356 else if (strcasecmp(buf,
"tabbed") == 0)
358 else if (strcasecmp(buf,
"dockarea") == 0)
360 else if (strcasecmp(buf,
"output") == 0)
362 else if (strcasecmp(buf,
"splith") == 0)
364 else if (strcasecmp(buf,
"splitv") == 0)
367 LOG(
"Unhandled \"layout\": %s\n", buf);
369 }
else if (strcasecmp(
last_key,
"workspace_layout") == 0) {
372 if (strcasecmp(buf,
"default") == 0)
374 else if (strcasecmp(buf,
"stacked") == 0)
376 else if (strcasecmp(buf,
"tabbed") == 0)
379 LOG(
"Unhandled \"workspace_layout\": %s\n", buf);
381 }
else if (strcasecmp(
last_key,
"last_split_layout") == 0) {
384 if (strcasecmp(buf,
"splith") == 0)
386 else if (strcasecmp(buf,
"splitv") == 0)
389 LOG(
"Unhandled \"last_splitlayout\": %s\n", buf);
391 }
else if (strcasecmp(
last_key,
"mark") == 0) {
392 DLOG(
"Found deprecated key \"mark\".\n");
398 }
else if (strcasecmp(
last_key,
"floating") == 0) {
401 if (strcasecmp(buf,
"auto_off") == 0)
402 json_node->
floating = FLOATING_AUTO_OFF;
403 else if (strcasecmp(buf,
"auto_on") == 0)
404 json_node->
floating = FLOATING_AUTO_ON;
405 else if (strcasecmp(buf,
"user_off") == 0)
406 json_node->
floating = FLOATING_USER_OFF;
407 else if (strcasecmp(buf,
"user_on") == 0)
408 json_node->
floating = FLOATING_USER_ON;
410 }
else if (strcasecmp(
last_key,
"scratchpad_state") == 0) {
413 if (strcasecmp(buf,
"none") == 0)
415 else if (strcasecmp(buf,
"fresh") == 0)
417 else if (strcasecmp(buf,
"changed") == 0)
428 if (strcasecmp(
last_key,
"type") == 0)
429 json_node->
type = val;
431 if (strcasecmp(
last_key,
"fullscreen_mode") == 0)
434 if (strcasecmp(
last_key,
"num") == 0)
435 json_node->
num = val;
437 if (strcasecmp(
last_key,
"current_border_width") == 0)
440 if (strcasecmp(
last_key,
"depth") == 0)
441 json_node->
depth = val;
448 focus_mapping->
old_id = val;
455 r = &(json_node->
rect);
462 else if (strcasecmp(
last_key,
"y") == 0)
464 else if (strcasecmp(
last_key,
"width") == 0)
466 else if (strcasecmp(
last_key,
"height") == 0)
470 DLOG(
"rect now: (%d, %d, %d, %d)\n",
474 if (strcasecmp(
last_key,
"id") == 0) {
475 current_swallow->
id = val;
478 if (strcasecmp(
last_key,
"dock") == 0) {
479 current_swallow->
dock = val;
482 if (strcasecmp(
last_key,
"insert_where") == 0) {
493 if (strcasecmp(
last_key,
"focused") == 0 && val) {
497 if (strcasecmp(
last_key,
"sticky") == 0)
501 if (strcasecmp(
last_key,
"restart_mode") == 0) {
512 if (strcasecmp(
last_key,
"percent") == 0) {
532 if (strcasecmp(
last_key,
"type") != 0 || content_level > 1)
535 DLOG(
"string = %.*s, last_key = %s\n", (
int)len, val,
last_key);
536 if (strncasecmp((
const char *)val,
"workspace", len) == 0)
547 yajl_handle hand = yajl_alloc(NULL, NULL, NULL);
549 yajl_config(hand, yajl_allow_comments,
true);
551 yajl_config(hand, yajl_allow_multiple_values,
true);
553 setlocale(LC_NUMERIC,
"C");
554 if (yajl_parse(hand, (
const unsigned char *)buf, len) != yajl_status_ok) {
555 unsigned char *str = yajl_get_error(hand, 1, (
const unsigned char *)buf, len);
556 ELOG(
"JSON parsing error: %s\n", str);
557 yajl_free_error(hand, str);
560 setlocale(LC_NUMERIC,
"");
562 yajl_complete_parse(hand);
577 static yajl_callbacks callbacks = {
585 yajl_handle hand = yajl_alloc(&callbacks, NULL, NULL);
587 yajl_config(hand, yajl_allow_comments,
true);
589 yajl_config(hand, yajl_allow_multiple_values,
true);
590 setlocale(LC_NUMERIC,
"C");
591 const yajl_status stat = yajl_parse(hand, (
const unsigned char *)buf, len);
592 if (stat != yajl_status_ok && stat != yajl_status_client_canceled) {
593 unsigned char *str = yajl_get_error(hand, 1, (
const unsigned char *)buf, len);
594 ELOG(
"JSON parsing error: %s\n", str);
595 yajl_free_error(hand, str);
598 setlocale(LC_NUMERIC,
"");
599 yajl_complete_parse(hand);
606 static yajl_callbacks callbacks = {
611 .yajl_start_map = json_start_map,
616 yajl_handle hand = yajl_alloc(&callbacks, NULL, NULL);
618 yajl_config(hand, yajl_allow_comments,
true);
620 yajl_config(hand, yajl_allow_multiple_values,
true);
631 setlocale(LC_NUMERIC,
"C");
632 const yajl_status stat = yajl_parse(hand, (
const unsigned char *)buf, len);
633 if (stat != yajl_status_ok) {
634 unsigned char *str = yajl_get_error(hand, 1, (
const unsigned char *)buf, len);
635 ELOG(
"JSON parsing error: %s\n", str);
636 if (errormsg != NULL)
637 *errormsg =
sstrdup((
const char *)str);
638 yajl_free_error(hand, str);
641 DLOG(
"freeing incomplete container %p\n", json_node);
652 setlocale(LC_NUMERIC,
"");
653 yajl_complete_parse(hand);
void con_free(Con *con)
Frees the specified container.
void con_fix_percent(Con *con)
Updates the percent attribute of the children of the given container.
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
layout_t last_split_layout
#define TAILQ_INSERT_HEAD(head, elm, field)
#define TAILQ_HEAD_INITIALIZER(head)
char * title_format
The format with which the window's name should be displayed.
static bool parsing_focus
struct Match * current_swallow
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
#define TAILQ_EMPTY(head)
A 'Con' represents everything from the X11 root window down to a single X11 window.
bool json_validate(const char *buf, const size_t len)
Returns true if the provided JSON could be parsed by yajl.
static TAILQ_HEAD(focus_mappings_head, focus_mapping)
static int json_key(void *ctx, const unsigned char *val, size_t len)
static json_content_t content_result
Con * con_new_skeleton(Con *parent, i3Window *window)
Create a new container (and attach it to the given parent, if not NULL).
static bool parsing_swallows
void match_free(Match *match)
Frees the given match.
void con_focus(Con *con)
Sets input focus to the given container.
#define TAILQ_INSERT_TAIL(head, elm, field)
static bool parsing_geometry
static bool parsing_window_rect
static bool parsing_marks
static int json_string(void *ctx, const unsigned char *val, size_t len)
void con_mark(Con *con, const char *mark, mark_mode_t mode)
Assigns a mark to the container.
struct Rect geometry
the geometry this window requested when getting mapped
static int json_end_map(void *ctx)
static bool parsing_deco_rect
static int json_determine_content_shallower(void *ctx)
enum Con::@21 floating
floating? (= not in tiling layout) This cannot be simply a bool because we want to keep track of whet...
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
static bool swallow_is_empty
#define TAILQ_FOREACH(var, head, field)
#define TAILQ_FIRST(head)
static int json_determine_content_string(void *ctx, const unsigned char *val, size_t len)
fullscreen_mode_t fullscreen_mode
#define TAILQ_REMOVE(head, elm, field)
json_content_t json_determine_content(const char *buf, const size_t len)
bool con_is_split(Con *con)
Returns true if a container should be considered split.
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
Con * output_get_content(Con *output)
Returns the output container below the given output container.
void * scalloc(size_t num, size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
void floating_check_size(Con *floating_con)
Called when a floating window is created or resized.
struct regex * window_role
layout_t workspace_layout
void * srealloc(void *ptr, size_t size)
Safe-wrapper around realloc which exits if realloc returns NULL (meaning that there is no more memory...
enum Match::@17 insert_where
static int json_int(void *ctx, long long val)
void x_con_init(Con *con)
Initializes the X11 part for the given container.
static int json_determine_content_deeper(void *ctx)
A "match" is a data structure which acts like a mask or expression to match certain windows or not...
static int json_end_array(void *ctx)
long ws_name_to_number(const char *name)
Parses the workspace name as a number.
static int json_double(void *ctx, double val)
border_style_t border_style
int num
the workspace number, if this Con is of type CT_WORKSPACE and the workspace is not a named workspace ...
void con_attach(Con *con, Con *parent, bool ignore_focus)
Attaches the given container to the given parent.
#define TAILQ_ENTRY(type)
enum Con::@22 scratchpad_state
static int json_bool(void *ctx, int val)
void match_init(Match *match)
void tree_append_json(Con *con, const char *buf, const size_t len, char **errormsg)
#define GREP_FIRST(dest, head, condition)
Stores a rectangle, for example the size of a window, the child window etc.
struct regex * regex_new(const char *pattern)
Creates a new 'regex' struct containing the given pattern and a PCRE compiled regular expression...
static xcb_cursor_context_t * ctx
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)