2 #define I3__FILE__ "con.c"
45 DLOG(
"opening window %d\n", cnt);
49 new->name = strdup(
colors[cnt]);
52 if ((cnt % (
sizeof(
colors) /
sizeof(
char*))) == 0)
84 struct nodes_head *nodes_head = &(parent->nodes_head);
85 struct focus_head *focus_head = &(parent->focus_head);
89 if (con->
type == CT_WORKSPACE) {
90 DLOG(
"it's a workspace. num = %d\n", con->
num);
95 if (con->
num < current->
num) {
99 while (current->
num != -1 && con->
num > current->
num) {
112 goto add_to_focus_head;
115 if (con->
type == CT_FLOATING_CON) {
116 DLOG(
"Inserting into floating containers\n");
122 if (loop->
type == CT_FLOATING_CON)
136 if (con->
window != NULL &&
137 parent->
type == CT_WORKSPACE &&
139 DLOG(
"Parent is a workspace. Applying default layout...\n");
143 nodes_head = &(target->nodes_head);
144 focus_head = &(target->focus_head);
153 if (current && parent->
type != CT_OUTPUT) {
154 DLOG(
"Inserting con = %p after last focused tiling con %p\n",
172 if (con->
type == CT_FLOATING_CON) {
188 DLOG(
"con_focus = %p\n", con);
219 if (con->
type == CT_WORKSPACE)
223 DLOG(
"container %p does not accept windows, it is a split container.\n", con);
228 return (con->
window == NULL);
238 while (result != NULL && result->
type != CT_OUTPUT)
242 assert(result != NULL);
252 while (result != NULL && result->
type != CT_WORKSPACE)
263 DLOG(
"Searching for parent of Con %p with orientation %d\n", con, orientation);
265 if (parent->
type == CT_FLOATING_CON)
268 DLOG(
"Need to go one level further up\n");
272 (parent->
type == CT_FLOATING_CON ||
273 parent->
type == CT_OUTPUT ||
279 DLOG(
"Result: %p\n", parent);
299 Con *current, *child;
310 current = entry->
con;
330 TAILQ_FOREACH(child, &(current->floating_head), floating_windows) {
346 DLOG(
"checking if con %p is floating\n", con);
347 return (con->
floating >= FLOATING_AUTO_ON);
357 if (con->
type == CT_FLOATING_CON)
360 if (con->
floating >= FLOATING_AUTO_ON)
363 if (con->
type == CT_WORKSPACE || con->
type == CT_OUTPUT)
402 if (con->
frame == frame)
422 if (store_match != NULL)
423 *store_match = match;
431 TAILQ_FOREACH(child, &(con->floating_head), floating_windows) {
435 if (store_match != NULL)
436 *store_match = match;
474 int children_with_percent = 0;
478 ++children_with_percent;
484 if (children_with_percent != children) {
487 if (children_with_percent == 0)
488 total += (child->
percent = 1.0);
489 else total += (child->
percent = total / children_with_percent);
498 child->
percent = 1.0 / children;
499 }
else if (total != 1.0) {
511 Con *workspace, *fullscreen;
513 if (con->
type == CT_WORKSPACE) {
514 DLOG(
"You cannot make a workspace fullscreen.\n");
518 DLOG(
"toggling fullscreen for %p / %s\n", con, con->
name);
521 if (fullscreen_mode == CF_GLOBAL)
527 if (fullscreen != NULL) {
531 LOG(
"Disabling fullscreen for (%p/%s) upon user request\n",
532 fullscreen, fullscreen->
name);
552 unsigned int num = 0;
555 values[num++] = A__NET_WM_STATE_FULLSCREEN;
557 xcb_change_property(
conn, XCB_PROP_MODE_REPLACE, con->
window->
id,
579 if (con->
type == CT_WORKSPACE) {
580 DLOG(
"Moving workspaces is not yet implemented.\n");
586 LOG(
"Cannot move out of a fullscreen container");
591 DLOG(
"Using FLOATINGCON instead\n");
596 if (workspace == source_ws) {
597 DLOG(
"Not moving, already there\n");
616 if (next->
type != CT_WORKSPACE) {
617 DLOG(
"next originally = %p / %s / type %d\n", next, next->
name, next->
type);
625 if (floatingcon != NULL) {
626 DLOG(
"floatingcon, going up even further\n");
627 next = floatingcon->
parent;
630 if (con->
type == CT_FLOATING_CON) {
632 DLOG(
"This is a floating window, using workspace %p / %s\n", ws, ws->
name);
636 if (source_output != dest_output) {
639 if (fix_coordinates && con->
type == CT_FLOATING_CON) {
641 }
else DLOG(
"Not fixing coordinates, fix_coordinates flag = %d\n", fix_coordinates);
658 DLOG(
"Re-attaching container to %p / %s\n", next, next->
name);
673 if ((workspace->
name[0] !=
'_' || workspace->
name[1] !=
'_') &&
680 if (source_output != dest_output &&
682 workspace->
name[0] !=
'_' &&
683 workspace->
name[1] !=
'_') {
684 DLOG(
"Moved to a different output, focusing target\n");
693 if (source_ws == current_ws)
697 CALL(parent, on_remove_child);
719 DLOG(
"Someone called con_orientation() on a con with L_DEFAULT, this is a bug in the code.\n");
725 DLOG(
"con_orientation() called on dockarea/output (%d) container %p\n", con->
layout, con);
730 DLOG(
"con_orientation() ran into default\n");
745 if (con->
type == CT_FLOATING_CON) {
746 DLOG(
"selecting next for CT_FLOATING_CON\n");
748 DLOG(
"next = %p\n", next);
750 next =
TAILQ_PREV(con, floating_head, floating_windows);
751 DLOG(
"using prev, next = %p\n", next);
756 DLOG(
"no more floating containers for next = %p, restoring workspace focus\n", next);
760 DLOG(
"skipping container itself, we want the next client\n");
764 if (next ==
TAILQ_END(&(ws->focus_head))) {
765 DLOG(
"Focus list empty, returning ws\n");
778 DLOG(
"selecting workspace for dock client\n");
786 DLOG(
"Using first entry %p\n", first);
810 DLOG(
"con_get_next(way=%c, orientation=%d)\n", way, orientation);
814 DLOG(
"need to go one level further up\n");
816 LOG(
"that's a workspace, we can't go further up\n");
827 if (next ==
TAILQ_END(&(parent->nodes_head)))
832 if (next ==
TAILQ_END(&(cur->nodes_head)))
835 DLOG(
"next = %p\n", next);
870 if (child->
type == CT_FLOATING_CON)
876 }
while (before != next && next !=
focused);
890 DLOG(
"con_descend_direction(%p, orientation %d, direction %d)\n", con, orientation, direction);
892 if (orientation ==
HORIZ) {
897 else most =
TAILQ_LAST(&(con->nodes_head), nodes_head);
898 }
else if (orientation ==
VERT) {
910 if (direction ==
D_UP || direction ==
D_DOWN) {
911 if (orientation ==
VERT) {
914 if (direction ==
D_UP)
915 most =
TAILQ_LAST(&(con->nodes_head), nodes_head);
917 }
else if (orientation ==
HORIZ) {
946 return (
Rect){ 0, 0, 0, 0 };
948 switch (border_style) {
950 result = (
Rect){2, 0, -(2 * 2), -2};
965 result = (
Rect){1, 1, -2, -2};
966 if (borders_to_hide & ADJ_LEFT_SCREEN_EDGE) {
970 if (borders_to_hide & ADJ_RIGHT_SCREEN_EDGE) {
977 if (borders_to_hide & ADJ_LOWER_SCREEN_EDGE) {
983 return (
Rect){0, 0, 0, 0};
1021 DLOG(
"this one is fullscreen! overriding BS_NONE\n");
1054 DLOG(
"This is a floating container\n");
1087 DLOG(
"con_set_layout(%p, %d), con->type = %d\n",
1088 con, layout, con->
type);
1093 if (con->
type != CT_WORKSPACE)
1099 if (con->
layout == L_SPLITH || con->
layout == L_SPLITV)
1106 if (con->
type == CT_WORKSPACE &&
1107 (layout == L_STACKED || layout == L_TABBED)) {
1109 DLOG(
"Setting workspace_layout to %d\n", layout);
1112 DLOG(
"Creating new split container\n");
1124 if (old_focused ==
TAILQ_END(&(con->focus_head)))
1128 DLOG(
"Moving cons\n");
1137 DLOG(
"Attaching new split to ws\n");
1148 if (layout == L_DEFAULT) {
1160 if (con->
layout == L_DEFAULT)
1179 if (con->
type != CT_WORKSPACE)
1181 DLOG(
"con_toggle_layout(%p, %s), parent = %p\n", con, toggle_mode, parent);
1183 if (strcmp(toggle_mode,
"split") == 0) {
1187 if (parent->
layout != L_SPLITH && parent->
layout != L_SPLITV)
1190 if (parent->
layout == L_SPLITH)
1195 if (parent->
layout == L_STACKED)
1197 else if (parent->
layout == L_TABBED) {
1198 if (strcmp(toggle_mode,
"all") == 0)
1201 }
else if (parent->
layout == L_SPLITH || parent->
layout == L_SPLITV) {
1202 if (strcmp(toggle_mode,
"all") == 0) {
1206 if (parent->
layout == L_SPLITH)
1223 DLOG(
"on_remove_child\n");
1227 if (con->
type == CT_OUTPUT ||
1228 con->
type == CT_ROOT ||
1229 con->
type == CT_DOCKAREA) {
1230 DLOG(
"not handling, type = %d\n", con->
type);
1235 if (con->
type == CT_WORKSPACE) {
1237 LOG(
"Closing old workspace (%p / %s), it is empty\n", con, con->
name);
1239 ipc_send_event(
"workspace", I3_IPC_EVENT_WORKSPACE,
"{\"change\":\"empty\"}");
1247 if (children == 0) {
1248 DLOG(
"Container empty, closing\n");
1260 DLOG(
"Determining minimum size for con %p\n", con);
1263 DLOG(
"leaf node, returning 75x50\n");
1264 return (
Rect){ 0, 0, 75, 50 };
1267 if (con->
type == CT_FLOATING_CON) {
1268 DLOG(
"floating con\n");
1273 if (con->
layout == L_STACKED || con->
layout == L_TABBED) {
1274 uint32_t max_width = 0, max_height = 0, deco_height = 0;
1279 max_width =
max(max_width, min.
width);
1280 max_height =
max(max_height, min.
height);
1282 DLOG(
"stacked/tabbed now, returning %d x %d + deco_rect = %d\n",
1283 max_width, max_height, deco_height);
1284 return (
Rect){ 0, 0, max_width, max_height + deco_height };
1295 if (con->
layout == L_SPLITH) {
1303 DLOG(
"split container, returning width = %d x height = %d\n", width,
height);
1307 ELOG(
"Unhandled case, type = %d, layout = %d, split = %d\n",
1349 if (fs->
type == CT_WORKSPACE)