Go to the documentation of this file.
26 __i3->
type = CT_OUTPUT;
29 x_set_name(__i3,
"[i3 con] pseudo-output __i3");
39 DLOG(
"adding main content container\n");
41 content->
type = CT_CON;
51 ws->
type = CT_WORKSPACE;
56 x_set_name(ws,
"[i3 con] workspace __i3_scratch");
66 bool tree_restore(
const char *path, xcb_get_geometry_reply_t *geometry) {
72 LOG(
"%s does not exist, not restoring tree\n", globbed);
77 if ((len =
slurp(globbed, &buf)) < 0) {
93 DLOG(
"appended tree, using new root\n");
101 DLOG(
"out = %p\n", out);
103 DLOG(
"ws = %p\n", ws);
107 if (strcmp(out->
name,
"__i3") != 0) {
108 DLOG(
"Adding pseudo-output __i3 during inplace restart\n");
162 if (con->
type == CT_FLOATING_CON) {
164 if (con->
type != CT_WORKSPACE)
167 DLOG(
"con = %p\n", con);
201 DLOG(
"closing %p, kill_window = %d\n", con, kill_window);
202 Con *child, *nextchild;
203 bool abort_kill =
false;
206 for (child =
TAILQ_FIRST(&(con->nodes_head)); child;) {
208 DLOG(
"killing child=%p\n", child);
216 DLOG(
"One of the children could not be killed immediately (WM_DELETE sent), aborting.\n");
220 if (con->
window != NULL) {
225 xcb_void_cookie_t cookie;
230 XCB_CW_EVENT_MASK, (uint32_t[]){XCB_NONE});
240 long data[] = {XCB_ICCCM_WM_STATE_WITHDRAWN, XCB_NONE};
241 cookie = xcb_change_property(
conn, XCB_PROP_MODE_REPLACE,
242 con->
window->
id, A_WM_STATE, A_WM_STATE, 32, 2, data);
249 xcb_change_save_set(
conn, XCB_SET_MODE_DELETE, con->
window->
id);
276 DLOG(
"Removing urgency timer of con %p\n", con);
282 if (con->
type != CT_FLOATING_CON) {
296 if (!dont_kill_parent)
303 DLOG(
"Closing workspace container %s, updating EWMH atoms\n", ws->
name);
312 DLOG(
"not changing focus, the container was not focused before\n");
316 if (!dont_kill_parent)
317 CALL(parent, on_remove_child);
329 DLOG(
"Floating containers can't be split.\n");
333 if (con->
type == CT_WORKSPACE) {
336 DLOG(
"Changing workspace_layout to L_DEFAULT\n");
339 DLOG(
"Changing orientation of workspace\n");
361 DLOG(
"Just changing orientation of existing container\n");
365 DLOG(
"Splitting in orientation %d\n", orientation);
371 new->parent = parent;
398 ELOG(
"'focus parent': Focus is already on the workspace, cannot go higher than that.\n");
413 DLOG(
"cannot go down\n");
415 }
else if (next->
type == CT_FLOATING_CON) {
419 if (child ==
TAILQ_END(&(next->focus_head))) {
420 DLOG(
"cannot go down\n");
437 if (con->
type == CT_WORKSPACE) {
440 TAILQ_FOREACH (current, &(con->floating_head), floating_windows) {
455 DLOG(
"-- BEGIN RENDERING --\n");
464 DLOG(
"-- END RENDERING --\n");
469 DLOG(
"Cannot change workspace while in global fullscreen mode.\n");
474 if (!current_output) {
486 Con *workspace = NULL;
501 Con *first_wrap = NULL;
503 if (con->
type == CT_WORKSPACE) {
506 goto handle_workspace;
509 while (con->
type != CT_WORKSPACE) {
522 if (con->
type == CT_FLOATING_CON) {
523 if (orientation !=
HORIZ) {
529 Con *next = previous ?
TAILQ_PREV(con, floating_head, floating_windows)
533 next = previous ?
TAILQ_LAST(&(parent->floating_head), floating_head)
543 Con *
const next = previous ?
TAILQ_PREV(con, nodes_head, nodes)
549 Con *
const wrap = previous ?
TAILQ_LAST(&(parent->nodes_head), nodes_head)
573 assert(con->
type == CT_WORKSPACE);
580 return workspace ? workspace : first_wrap;
592 if (next->
type == CT_WORKSPACE) {
601 if (focus_tiling != next) {
602 focus = focus_tiling;
610 }
else if (next->
type == CT_FLOATING_CON) {
614 while (
TAILQ_LAST(&(parent->floating_head), floating_head) != next) {
615 Con *last =
TAILQ_LAST(&(parent->floating_head), floating_head);
616 TAILQ_REMOVE(&(parent->floating_head), last, floating_windows);
652 Con *current, *child, *parent = con->
parent;
653 DLOG(
"Checking if I can flatten con = %p / %s\n", con, con->
name);
656 if (con->
type != CT_CON ||
663 if (child == NULL ||
TAILQ_NEXT(child, nodes) != NULL)
666 DLOG(
"child = %p, con = %p, parent = %p\n", child, con, parent);
678 DLOG(
"Alright, I have to flatten this situation now. Stay calm.\n");
682 DLOG(
"detaching...\n");
686 DLOG(
"detaching current=%p / %s\n", current, current->
name);
688 DLOG(
"re-attaching\n");
695 DLOG(
"attaching to focus list\n");
699 DLOG(
"re-attached all\n");
702 if (focus_next != NULL &&
704 DLOG(
"restoring focus to focus_next=%p\n", focus_next);
707 DLOG(
"restored focus.\n");
711 DLOG(
"closing redundant cons\n");
725 while (current != NULL) {
732 while (current != NULL) {
#define TAILQ_FIRST(head)
Con * con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode)
Returns the first fullscreen node below this node.
#define TAILQ_LAST(head, headname)
A 'Window' is a type which contains an xcb_window_t and all the related information (hints like _NET_...
void ipc_send_window_event(const char *property, Con *con)
For the window events we send, along the usual "change" field, also the window container,...
void x_set_warp_to(Rect *rect)
Set warp_to coordinates.
Con * con_new(Con *parent, i3Window *window)
A wrapper for con_new_skeleton, to retain the old con_new behaviour.
void tree_next(Con *con, direction_t direction)
Changes focus in the given direction.
Con * con_descend_tiling_focused(Con *con)
Returns the focused con inside this client, descending the tree as far as possible.
void window_free(i3Window *win)
Frees an i3Window and all its members.
Output * get_output_next(direction_t direction, Output *current, output_close_far_t close_far)
Gets the output which is the next one in the given direction.
bool con_is_floating(Con *con)
Returns true if the node is floating.
Con * workspace_encapsulate(Con *ws)
Creates a new container and re-parents all of children from the given workspace into it.
void workspace_update_urgent_flag(Con *ws)
Goes through all clients on the given workspace and updates the workspace’s urgent flag accordingly.
Output * get_output_containing(unsigned int x, unsigned int y)
Returns the active (!) output which contains the coordinates x, y or NULL if there is no output which...
char * output_primary_name(Output *output)
Retrieves the primary name of an output.
Con * con
Pointer to the Con which represents this output.
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
bool level_up(void)
Moves focus one level up.
static void mark_unmapped(Con *con)
void x_push_changes(Con *con)
Pushes all changes (state of each node, see x_push_node() and the window stack) to X11.
#define TAILQ_NEXT(elm, field)
void con_detach(Con *con)
Detaches the given container from its current parent.
void ewmh_update_desktop_properties(void)
Updates all the EWMH desktop properties.
bool level_down(void)
Moves focus one level down.
ssize_t slurp(const char *path, char **buf)
Slurp reads path in its entirety into buf, returning the length of the file or -1 if the file could n...
bool path_exists(const char *path)
Checks if the given path exists by calling stat().
#define TAILQ_EMPTY(head)
void con_activate(Con *con)
Sets input focus to the given container and raises it to the top.
void tree_init(xcb_get_geometry_reply_t *geometry)
Initializes the tree by creating the root node, adding all RandR outputs to the tree (that means rand...
bool workspace_is_visible(Con *ws)
Returns true if the workspace is currently visible.
#define TAILQ_PREV(elm, headname, field)
void tree_split(Con *con, orientation_t orientation)
Splits (horizontally or vertically) the given container by creating a new container which contains th...
Con * get_tree_next_sibling(Con *con, position_t direction)
Get the previous / next sibling.
void workspace_show(Con *workspace)
Switches to the given workspace.
focus_wrapping_t focus_wrapping
When focus wrapping is enabled (the default), attempting to move focus past the edge of the screen (i...
int num
the workspace number, if this Con is of type CT_WORKSPACE and the workspace is not a named workspace ...
#define TAILQ_INSERT_TAIL(head, elm, field)
void tree_render(void)
Renders the tree, that is rendering all outputs using render_con() and pushing the changes to X11 usi...
char * resolve_tilde(const char *path)
This function resolves ~ in pathnames.
void add_ignore_event(const int sequence, const int response_type)
Adds the given sequence to the list of events which are ignored.
orientation_t con_orientation(Con *con)
Returns the orientation of the given container (for stacked containers, vertical orientation is used ...
bool con_fullscreen_permits_focusing(Con *con)
Returns true if changing the focus to con would be allowed considering the fullscreen focus constrain...
struct all_cons_head all_cons
kill_window_t
parameter to specify whether tree_close_internal() and x_window_kill() should kill only this specific...
void con_update_parents_urgency(Con *con)
Make all parent containers urgent if con is urgent or clear the urgent flag of all parent containers ...
int con_num_children(Con *con)
Returns the number of children of this container.
layout_t workspace_layout
#define GREP_FIRST(dest, head, condition)
#define TAILQ_HEAD_INITIALIZER(head)
bool tree_close_internal(Con *con, kill_window_t kill_window, bool dont_kill_parent)
Closes the given container including all children.
void x_con_kill(Con *con)
Kills the window decoration associated with the given container.
void render_con(Con *con)
"Renders" the given container (and its children), meaning that all rects are updated correctly.
void restore_open_placeholder_windows(Con *parent)
Open placeholder windows for all children of parent.
void con_force_split_parents_redraw(Con *con)
force parent split containers to be redrawn
void x_window_kill(xcb_window_t window, kill_window_t kill_window)
Kills the given X11 window using WM_DELETE_WINDOW (if supported).
static Con * get_tree_next(Con *con, direction_t direction)
An Output is a physical output on your graphics driver.
void con_set_urgency(Con *con, bool urgent)
Set urgency flag to the container, all the parent containers and the workspace.
static Con * get_tree_next_workspace(Con *con, direction_t direction)
struct ev_loop * main_loop
void con_attach(Con *con, Con *parent, bool ignore_focus)
Attaches the given container to the given parent.
static Con * _create___i3(void)
position_t position_from_direction(direction_t direction)
Convert a direction to its corresponding position.
#define TAILQ_REPLACE(head, elm, elm2, field)
#define CALL(obj, member,...)
void x_set_name(Con *con, const char *name)
Sets the WM_NAME property (so, no UTF8, but used only for debugging anyways) of the given name.
Con * con_next_focused(Con *con)
Returns the container which will be focused next when the given container is not available anymore.
Con * tree_open_con(Con *con, i3Window *window)
Opens an empty container in the current container.
Con * con_descend_focused(Con *con)
Returns the focused con inside this client, descending the tree as far as possible.
struct ev_timer * urgency_timer
void tree_flatten(Con *con)
tree_flatten() removes pairs of redundant split containers, e.g.
#define TAILQ_INSERT_HEAD(head, elm, field)
bool con_is_split(Con *con)
Returns true if a container should be considered split.
void tree_append_json(Con *con, const char *buf, const size_t len, char **errormsg)
orientation_t orientation_from_direction(direction_t direction)
Convert a direction to its corresponding orientation.
xcb_connection_t * conn
XCB connection and root screen.
#define TAILQ_FOREACH(var, head, field)
bool tree_restore(const char *path, xcb_get_geometry_reply_t *geometry)
Loads tree from ~/.i3/_restart.json (used for in-place restarts).
A 'Con' represents everything from the X11 root window down to a single X11 window.
void con_free(Con *con)
Frees the specified container.
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
fullscreen_mode_t fullscreen_mode
@ FOCUS_WRAPPING_WORKSPACE
Con * output_get_content(Con *output)
Returns the output container below the given output container.
#define TAILQ_INSERT_BEFORE(listelm, elm, field)
void con_fix_percent(Con *con)
Updates the percent attribute of the children of the given container.
#define TAILQ_REMOVE(head, elm, field)