2 #define I3__FILE__ "tree.c"
28 __i3->
type = CT_OUTPUT;
31 x_set_name(__i3,
"[i3 con] pseudo-output __i3");
41 DLOG(
"adding main content container\n");
43 content->
type = CT_CON;
46 content->
layout = L_SPLITH;
53 ws->
type = CT_WORKSPACE;
58 x_set_name(ws,
"[i3 con] workspace __i3_scratch");
68 bool tree_restore(
const char *path, xcb_get_geometry_reply_t *geometry) {
72 LOG(
"%s does not exist, not restoring tree\n", globbed);
89 printf(
"appended tree, using new root\n");
91 printf(
"new root = %p\n", croot);
93 printf(
"out = %p\n", out);
95 printf(
"ws = %p\n", ws);
99 if (strcmp(out->
name,
"__i3") != 0) {
100 DLOG(
"Adding pseudo-output __i3 during inplace restart\n");
119 croot->
name =
"root";
120 croot->
type = CT_ROOT;
149 if (con->
type == CT_FLOATING_CON) {
151 if (con->
type != CT_WORKSPACE)
154 DLOG(
"con = %p\n", con);
161 new->layout = L_SPLITH;
193 bool was_mapped = con->
mapped;
212 DLOG(
"next = %p, focused = %p\n", next, focused);
214 DLOG(
"closing %p, kill_window = %d\n", con, kill_window);
215 Con *child, *nextchild;
216 bool abort_kill =
false;
219 for (child =
TAILQ_FIRST(&(con->nodes_head)); child; ) {
221 DLOG(
"killing child=%p\n", child);
222 if (!
tree_close(child, kill_window,
true,
false))
228 DLOG(
"One of the children could not be killed immediately (WM_DELETE sent), aborting.\n");
232 if (con->
window != NULL) {
237 xcb_void_cookie_t cookie;
248 cookie = xcb_change_property(
conn, XCB_PROP_MODE_REPLACE,
249 con->
window->
id, A_WM_STATE, A_WM_STATE, 32, 2, data);
265 if (con == focused) {
266 DLOG(
"This is the focused container, i need to find another one to focus. I start looking at ws = %p\n", ws);
269 dont_kill_parent =
true;
270 DLOG(
"Alright, focusing %p\n", next);
281 DLOG(
"Removing urgency timer of con %p\n", con);
287 if (con->
type != CT_FLOATING_CON) {
301 if (!dont_kill_parent)
308 DLOG(
"Container was floating, killing floating container\n");
310 DLOG(
"parent container killed\n");
321 DLOG(
"No next container, i will just exit now\n");
325 if (was_mapped || con == focused) {
326 if ((kill_window !=
DONT_KILL_WINDOW) || !dont_kill_parent || con == focused) {
327 DLOG(
"focusing %p / %s\n", next, next->
name);
328 if (next->
type == CT_DOCKAREA) {
332 if (!force_set_focus && con != focused)
333 DLOG(
"not changing focus, the container was not focused before\n");
338 DLOG(
"not focusing because we're not killing anybody\n");
341 DLOG(
"not focusing, was not mapped\n");
345 if (!dont_kill_parent)
346 CALL(parent, on_remove_child);
356 assert(focused != NULL);
357 if (focused->
type == CT_WORKSPACE) {
358 LOG(
"Cannot close workspace\n");
363 assert(focused->
type != CT_OUTPUT);
364 assert(focused->
type != CT_ROOT);
367 tree_close(focused, kill_window,
false,
false);
376 if (con->
type == CT_FLOATING_CON) {
377 DLOG(
"Floating containers can't be split.\n");
381 if (con->
type == CT_WORKSPACE) {
383 DLOG(
"Just changing orientation of workspace\n");
384 con->
layout = (orientation ==
HORIZ) ? L_SPLITH : L_SPLITV;
403 (parent->
layout == L_SPLITH ||
404 parent->
layout == L_SPLITV)) {
405 parent->
layout = (orientation ==
HORIZ) ? L_SPLITH : L_SPLITV;
406 DLOG(
"Just changing orientation of existing container\n");
410 DLOG(
"Splitting in orientation %d\n", orientation);
416 new->parent = parent;
417 new->
layout = (orientation ==
HORIZ) ? L_SPLITH : L_SPLITV;
434 if (focused->
parent->
type == CT_FLOATING_CON) {
442 focused->
type == CT_WORKSPACE) {
443 ELOG(
"'focus parent': Focus is already on the workspace, cannot go higher than that.\n");
457 if (next ==
TAILQ_END(&(focused->focus_head))) {
458 DLOG(
"cannot go down\n");
461 else if (next->
type == CT_FLOATING_CON) {
465 if (child ==
TAILQ_END(&(next->focus_head))) {
466 DLOG(
"cannot go down\n");
483 if (con->
type == CT_WORKSPACE) {
486 TAILQ_FOREACH(current, &(con->floating_head), floating_windows)
500 DLOG(
"-- BEGIN RENDERING --\n");
509 DLOG(
"-- END RENDERING --\n");
526 if (con->
type == CT_WORKSPACE) {
528 DLOG(
"Cannot change workspace while in global fullscreen mode.\n");
536 DLOG(
"Current output is %s\n", current_output->
name);
540 if (way ==
'n' && orientation ==
HORIZ)
542 else if (way ==
'p' && orientation ==
HORIZ)
544 else if (way ==
'n' && orientation ==
VERT)
546 else if (way ==
'p' && orientation ==
VERT)
554 DLOG(
"Next output is %s\n", next_output->
name);
557 Con *workspace = NULL;
582 if (con->
type == CT_FLOATING_CON) {
584 if (orientation ==
HORIZ) {
588 else next =
TAILQ_PREV(con, floating_head, floating_windows);
594 else next =
TAILQ_LAST(&(parent->floating_head), floating_head);
614 return _tree_next(parent, way, orientation, wrap);
620 DLOG(
"nothing to focus\n");
627 else next =
TAILQ_PREV(current, nodes_head, nodes);
634 if (
_tree_next(parent, way, orientation,
false))
643 else next =
TAILQ_LAST(&(parent->nodes_head), nodes_head);
680 Con *current, *child, *parent = con->
parent;
681 DLOG(
"Checking if I can flatten con = %p / %s\n", con, con->
name);
684 if (con->
type != CT_CON ||
685 parent->
layout == L_OUTPUT ||
691 if (child == NULL ||
TAILQ_NEXT(child, nodes) != NULL)
694 DLOG(
"child = %p, con = %p, parent = %p\n", child, con, parent);
704 DLOG(
"Alright, I have to flatten this situation now. Stay calm.\n");
708 DLOG(
"detaching...\n");
712 DLOG(
"detaching current=%p / %s\n", current, current->
name);
714 DLOG(
"re-attaching\n");
721 DLOG(
"attaching to focus list\n");
725 DLOG(
"re-attached all\n");
728 if (focus_next != NULL &&
730 DLOG(
"restoring focus to focus_next=%p\n", focus_next);
731 TAILQ_REMOVE(&(parent->focus_head), focus_next, focused);
733 DLOG(
"restored focus.\n");
737 DLOG(
"closing redundant cons\n");
751 while (current != NULL) {
758 while (current != NULL) {