2 #define I3__FILE__ "load_layout.c"
15 #include <yajl/yajl_common.h>
16 #include <yajl/yajl_gen.h>
17 #include <yajl/yajl_parse.h>
18 #include <yajl/yajl_version.h>
42 static
int json_start_map(
void *
ctx) {
45 LOG(
"creating new swallow\n");
52 DLOG(
"New floating_node\n");
56 DLOG(
"Parent is workspace = %p\n", ws);
60 json_node->
parent = parent;
72 DLOG(
"Setting layout = L_SPLITH\n");
79 DLOG(
"sanity check: removing swallows specification from split container\n");
82 TAILQ_REMOVE(&(json_node->swallow_head), match, matches);
89 LOG(
"Creating window\n");
91 json_node = json_node->
parent;
103 LOG(
"end of array\n");
114 LOG(
"focus (reverse) %d\n", mapping->
old_id);
119 LOG(
"got it! %p\n", con);
136 static int json_key(
void *
ctx,
const unsigned char *val,
size_t len) {
137 LOG(
"key: %.*s\n", (
int)len, val);
141 if (strcasecmp(
last_key,
"swallows") == 0)
144 if (strcasecmp(
last_key,
"rect") == 0)
147 if (strcasecmp(
last_key,
"window_rect") == 0)
150 if (strcasecmp(
last_key,
"geometry") == 0)
153 if (strcasecmp(
last_key,
"focus") == 0)
160 LOG(
"string: %.*s for key %s\n", (
int)len, val,
last_key);
164 if (strcasecmp(
last_key,
"class") == 0) {
166 }
else if (strcasecmp(
last_key,
"instance") == 0) {
168 }
else if (strcasecmp(
last_key,
"window_role") == 0) {
170 }
else if (strcasecmp(
last_key,
"title") == 0) {
177 if (strcasecmp(
last_key,
"name") == 0) {
178 json_node->
name =
scalloc((len + 1) *
sizeof(
char));
179 memcpy(json_node->
name, val, len);
180 }
else if (strcasecmp(
last_key,
"sticky_group") == 0) {
183 LOG(
"sticky_group of this container is %s\n", json_node->
sticky_group);
184 }
else if (strcasecmp(
last_key,
"orientation") == 0) {
193 if (strcasecmp(buf,
"none") == 0 ||
194 strcasecmp(buf,
"horizontal") == 0)
196 else if (strcasecmp(buf,
"vertical") == 0)
199 LOG(
"Unhandled orientation: %s\n", buf);
201 }
else if (strcasecmp(
last_key,
"border") == 0) {
204 if (strcasecmp(buf,
"none") == 0)
206 else if (strcasecmp(buf,
"1pixel") == 0) {
209 }
else if (strcasecmp(buf,
"pixel") == 0)
211 else if (strcasecmp(buf,
"normal") == 0)
214 LOG(
"Unhandled \"border\": %s\n", buf);
216 }
else if (strcasecmp(
last_key,
"type") == 0) {
219 if (strcasecmp(buf,
"root") == 0)
220 json_node->
type = CT_ROOT;
221 else if (strcasecmp(buf,
"output") == 0)
222 json_node->
type = CT_OUTPUT;
223 else if (strcasecmp(buf,
"con") == 0)
224 json_node->
type = CT_CON;
225 else if (strcasecmp(buf,
"floating_con") == 0)
226 json_node->
type = CT_FLOATING_CON;
227 else if (strcasecmp(buf,
"workspace") == 0)
228 json_node->
type = CT_WORKSPACE;
229 else if (strcasecmp(buf,
"dockarea") == 0)
230 json_node->
type = CT_DOCKAREA;
232 LOG(
"Unhandled \"type\": %s\n", buf);
234 }
else if (strcasecmp(
last_key,
"layout") == 0) {
237 if (strcasecmp(buf,
"default") == 0)
240 else if (strcasecmp(buf,
"stacked") == 0)
242 else if (strcasecmp(buf,
"tabbed") == 0)
244 else if (strcasecmp(buf,
"dockarea") == 0)
246 else if (strcasecmp(buf,
"output") == 0)
248 else if (strcasecmp(buf,
"splith") == 0)
250 else if (strcasecmp(buf,
"splitv") == 0)
253 LOG(
"Unhandled \"layout\": %s\n", buf);
255 }
else if (strcasecmp(
last_key,
"workspace_layout") == 0) {
258 if (strcasecmp(buf,
"default") == 0)
260 else if (strcasecmp(buf,
"stacked") == 0)
262 else if (strcasecmp(buf,
"tabbed") == 0)
265 LOG(
"Unhandled \"workspace_layout\": %s\n", buf);
267 }
else if (strcasecmp(
last_key,
"last_split_layout") == 0) {
270 if (strcasecmp(buf,
"splith") == 0)
272 else if (strcasecmp(buf,
"splitv") == 0)
275 LOG(
"Unhandled \"last_splitlayout\": %s\n", buf);
277 }
else if (strcasecmp(
last_key,
"mark") == 0) {
280 json_node->
mark = buf;
281 }
else if (strcasecmp(
last_key,
"floating") == 0) {
284 if (strcasecmp(buf,
"auto_off") == 0)
285 json_node->
floating = FLOATING_AUTO_OFF;
286 else if (strcasecmp(buf,
"auto_on") == 0)
287 json_node->
floating = FLOATING_AUTO_ON;
288 else if (strcasecmp(buf,
"user_off") == 0)
289 json_node->
floating = FLOATING_USER_OFF;
290 else if (strcasecmp(buf,
"user_on") == 0)
291 json_node->
floating = FLOATING_USER_ON;
293 }
else if (strcasecmp(
last_key,
"scratchpad_state") == 0) {
296 if (strcasecmp(buf,
"none") == 0)
298 else if (strcasecmp(buf,
"fresh") == 0)
300 else if (strcasecmp(buf,
"changed") == 0)
311 if (strcasecmp(
last_key,
"type") == 0)
312 json_node->
type = val;
314 if (strcasecmp(
last_key,
"fullscreen_mode") == 0)
317 if (strcasecmp(
last_key,
"num") == 0)
318 json_node->
num = val;
320 if (strcasecmp(
last_key,
"current_border_width") == 0)
323 if (strcasecmp(
last_key,
"depth") == 0)
324 json_node->
depth = val;
331 focus_mapping->
old_id = val;
338 r = &(json_node->
rect);
345 else if (strcasecmp(
last_key,
"y") == 0)
347 else if (strcasecmp(
last_key,
"width") == 0)
349 else if (strcasecmp(
last_key,
"height") == 0)
353 DLOG(
"rect now: (%d, %d, %d, %d)\n",
357 if (strcasecmp(
last_key,
"id") == 0) {
358 current_swallow->
id = val;
360 if (strcasecmp(
last_key,
"dock") == 0) {
361 current_swallow->
dock = val;
363 if (strcasecmp(
last_key,
"insert_where") == 0) {
373 if (strcasecmp(
last_key,
"focused") == 0 && val) {
378 if (strcasecmp(
last_key,
"restart_mode") == 0)
387 if (strcasecmp(
last_key,
"percent") == 0) {
395 if ((f = fopen(filename,
"r")) == NULL) {
396 LOG(
"Cannot open file \"%s\"\n", filename);
400 if (fstat(fileno(f), &stbuf) != 0) {
401 LOG(
"Cannot fstat() the file\n");
405 char *buf =
smalloc(stbuf.st_size);
406 int n = fread(buf, 1, stbuf.st_size, f);
407 if (n != stbuf.st_size) {
408 LOG(
"File \"%s\" could not be read entirely, not loading.\n", filename);
412 LOG(
"read %d bytes\n", n);
415 static yajl_callbacks callbacks = {
420 .yajl_start_map = json_start_map,
425 g = yajl_gen_alloc(NULL);
426 hand = yajl_alloc(&callbacks, NULL, (
void *)g);
428 yajl_config(hand, yajl_allow_comments,
true);
430 yajl_config(hand, yajl_allow_multiple_values,
true);
439 setlocale(LC_NUMERIC,
"C");
440 stat = yajl_parse(hand, (
const unsigned char *)buf, n);
441 if (stat != yajl_status_ok) {
442 unsigned char *str = yajl_get_error(hand, 1, (
const unsigned char *)buf, n);
443 ELOG(
"JSON parsing error: %s\n", str);
444 if (errormsg != NULL)
445 *errormsg =
sstrdup((
const char *)str);
446 yajl_free_error(hand, str);
454 setlocale(LC_NUMERIC,
"");
455 yajl_complete_parse(hand);
enum Con::@20 scratchpad_state
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_REMOVE(head, elm, field)
void con_attach(Con *con, Con *parent, bool ignore_focus)
Attaches the given container to the given parent.
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
Stores a rectangle, for example the size of a window, the child window etc.
struct Match * current_swallow
static int json_bool(void *ctx, int val)
struct regex * window_role
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)
#define TAILQ_FIRST(head)
static int json_double(void *ctx, double val)
enum Con::@19 floating
floating? (= not in tiling layout) This cannot be simply a bool because we want to keep track of whet...
void tree_append_json(Con *con, const char *filename, char **errormsg)
border_style_t border_style
static bool parsing_focus
struct regex * regex_new(const char *pattern)
Creates a new 'regex' struct containing the given pattern and a PCRE compiled regular expression...
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...
static int json_key(void *ctx, const unsigned char *val, size_t len)
static int json_end_array(void *ctx)
#define TAILQ_INSERT_HEAD(head, elm, field)
struct Rect geometry
the geometry this window requested when getting mapped
int num
the workspace number, if this Con is of type CT_WORKSPACE and the workspace is not a named workspace ...
fullscreen_mode_t fullscreen_mode
void con_focus(Con *con)
Sets input focus to the given container.
#define TAILQ_EMPTY(head)
static int json_int(void *ctx, long long val)
bool con_is_split(Con *con)
#define TAILQ_ENTRY(type)
A "match" is a data structure which acts like a mask or expression to match certain windows or not...
static xcb_cursor_context_t * ctx
A 'Con' represents everything from the X11 root window down to a single X11 window.
void * scalloc(size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
layout_t last_split_layout
layout_t workspace_layout
enum Match::@15 insert_where
#define TAILQ_INSERT_TAIL(head, elm, field)
#define TAILQ_HEAD_INITIALIZER(head)
static bool parsing_swallows
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
#define TAILQ_FOREACH(var, head, field)
void con_fix_percent(Con *con)
Updates the percent attribute of the children of the given container.
static bool parsing_window_rect
static bool parsing_geometry
static int json_end_map(void *ctx)
static int json_string(void *ctx, const unsigned char *val, size_t len)
void match_init(Match *match)
Con * con_new_skeleton(Con *parent, i3Window *window)
Create a new container (and attach it to the given parent, if not NULL).
static TAILQ_HEAD(focus_mappings_head, focus_mapping)
void match_free(Match *match)
Frees the given match.
void x_con_init(Con *con, uint16_t depth)
Initializes the X11 part for the given container.