i3
render.c
Go to the documentation of this file.
1 /*
2  * vim:ts=4:sw=4:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  * © 2009 Michael Stapelberg and contributors (see also: LICENSE)
6  *
7  * render.c: Renders (determines position/sizes) the layout tree, updating the
8  * various rects. Needs to be pushed to X11 (see x.c) to be visible.
9  *
10  */
11 #include "all.h"
12 
13 /* Forward declarations */
14 static int *precalculate_sizes(Con *con, render_params *p);
15 static void render_root(Con *con, Con *fullscreen);
16 static void render_output(Con *con);
17 static void render_con_split(Con *con, Con *child, render_params *p, int i);
18 static void render_con_stacked(Con *con, Con *child, render_params *p, int i);
19 static void render_con_tabbed(Con *con, Con *child, render_params *p, int i);
20 static void render_con_dockarea(Con *con, Con *child, render_params *p);
21 bool should_inset_con(Con *con, int children);
22 bool has_adjacent_container(Con *con, direction_t direction);
23 
24 /*
25  * Returns the height for the decorations
26  */
27 int render_deco_height(void) {
28  int deco_height = config.font.height + 4;
29  if (config.font.height & 0x01)
30  ++deco_height;
31  return deco_height;
32 }
33 
34 /*
35  * "Renders" the given container (and its children), meaning that all rects are
36  * updated correctly. Note that this function does not call any xcb_*
37  * functions, so the changes are completely done in memory only (and
38  * side-effect free). As soon as you call x_push_changes(), the changes will be
39  * updated in X11.
40  *
41  */
42 void render_con(Con *con, bool already_inset) {
43  render_params params = {
44  .rect = con->rect,
45  .x = con->rect.x,
46  .y = con->rect.y,
47  .children = con_num_children(con)};
48 
49  DLOG("Rendering node %p / %s / layout %d / children %d\n", con, con->name,
50  con->layout, params.children);
51 
52  bool should_inset = should_inset_con(con, params.children);
53  if (!already_inset && should_inset) {
54  gaps_t gaps = calculate_effective_gaps(con);
55  Rect inset = (Rect){
56  has_adjacent_container(con, D_LEFT) ? gaps.inner : gaps.left,
57  has_adjacent_container(con, D_UP) ? gaps.inner : gaps.top,
58  has_adjacent_container(con, D_RIGHT) ? -gaps.inner : -gaps.right,
59  has_adjacent_container(con, D_DOWN) ? -gaps.inner : -gaps.bottom};
60  inset.width -= inset.x;
61  inset.height -= inset.y;
62 
63  if (con->fullscreen_mode == CF_NONE) {
64  params.rect = rect_add(params.rect, inset);
65  con->rect = rect_add(con->rect, inset);
66  if (con->window) {
67  con->window_rect = rect_add(con->window_rect, inset);
68  }
69  }
70  inset.height = 0;
71  if (con->deco_rect.width != 0 && con->deco_rect.height != 0) {
72  con->deco_rect = rect_add(con->deco_rect, inset);
73  }
74 
75  params.x = con->rect.x;
76  params.y = con->rect.y;
77  }
78 
79  int i = 0;
80  con->mapped = true;
81 
82  /* if this container contains a window, set the coordinates */
83  if (con->window) {
84  /* depending on the border style, the rect of the child window
85  * needs to be smaller */
86  Rect *inset = &(con->window_rect);
87  *inset = (Rect){0, 0, con->rect.width, con->rect.height};
88  if (con->fullscreen_mode == CF_NONE) {
89  *inset = rect_add(*inset, con_border_style_rect(con));
90  }
91 
92  /* Obey x11 border */
93  inset->width -= (2 * con->border_width);
94  inset->height -= (2 * con->border_width);
95 
96  /* NB: We used to respect resize increment size hints for tiling
97  * windows up until commit 0db93d9 here. However, since all terminal
98  * emulators cope with ignoring the size hints in a better way than we
99  * can (by providing their fake-transparency or background color), this
100  * code was removed. See also https://bugs.i3wm.org/540 */
101 
102  DLOG("child will be at %dx%d with size %dx%d\n", inset->x, inset->y, inset->width, inset->height);
103  }
104 
105  /* Check for fullscreen nodes */
106  Con *fullscreen = NULL;
107  if (con->type != CT_OUTPUT) {
108  fullscreen = con_get_fullscreen_con(con, (con->type == CT_ROOT ? CF_GLOBAL : CF_OUTPUT));
109  }
110  if (fullscreen) {
111  fullscreen->rect = params.rect;
112  x_raise_con(fullscreen);
113  render_con(fullscreen, false);
114  /* Fullscreen containers are either global (underneath the CT_ROOT
115  * container) or per-output (underneath the CT_CONTENT container). For
116  * global fullscreen containers, we cannot abort rendering here yet,
117  * because the floating windows (with popup_during_fullscreen smart)
118  * have not yet been rendered (see the CT_ROOT code path below). See
119  * also https://bugs.i3wm.org/1393 */
120  if (con->type != CT_ROOT) {
121  return;
122  }
123  }
124 
125  /* find the height for the decorations */
126  params.deco_height = render_deco_height();
127 
128  /* precalculate the sizes to be able to correct rounding errors */
129  params.sizes = precalculate_sizes(con, &params);
130 
131  if (con->layout == L_OUTPUT) {
132  /* Skip i3-internal outputs */
133  if (con_is_internal(con))
134  goto free_params;
135  render_output(con);
136  } else if (con->type == CT_ROOT) {
137  render_root(con, fullscreen);
138  } else {
139  Con *child;
140  TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
141  assert(params.children > 0);
142 
143  if (con->layout == L_SPLITH || con->layout == L_SPLITV) {
144  render_con_split(con, child, &params, i);
145  } else if (con->layout == L_STACKED) {
146  render_con_stacked(con, child, &params, i);
147  } else if (con->layout == L_TABBED) {
148  render_con_tabbed(con, child, &params, i);
149  } else if (con->layout == L_DOCKAREA) {
150  render_con_dockarea(con, child, &params);
151  }
152 
153  DLOG("child at (%d, %d) with (%d x %d)\n",
154  child->rect.x, child->rect.y, child->rect.width, child->rect.height);
155  x_raise_con(child);
156  render_con(child, should_inset || already_inset);
157  i++;
158  }
159 
160  /* in a stacking or tabbed container, we ensure the focused client is raised */
161  if (con->layout == L_STACKED || con->layout == L_TABBED) {
162  TAILQ_FOREACH_REVERSE(child, &(con->focus_head), focus_head, focused)
163  x_raise_con(child);
164  if ((child = TAILQ_FIRST(&(con->focus_head)))) {
165  /* By rendering the stacked container again, we handle the case
166  * that we have a non-leaf-container inside the stack. In that
167  * case, the children of the non-leaf-container need to be
168  * raised as well. */
169  render_con(child, true);
170  }
171 
172  if (params.children != 1)
173  /* Raise the stack con itself. This will put the stack
174  * decoration on top of every stack window. That way, when a
175  * new window is opened in the stack, the old window will not
176  * obscure part of the decoration (it’s unmapped afterwards). */
177  x_raise_con(con);
178  }
179  }
180 
181 free_params:
182  FREE(params.sizes);
183 }
184 
185 static int *precalculate_sizes(Con *con, render_params *p) {
186  if ((con->layout != L_SPLITH && con->layout != L_SPLITV) || p->children <= 0) {
187  return NULL;
188  }
189 
190  int *sizes = smalloc(p->children * sizeof(int));
191  assert(!TAILQ_EMPTY(&con->nodes_head));
192 
193  Con *child;
194  int i = 0, assigned = 0;
195  int total = con_rect_size_in_orientation(con);
196  TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
197  double percentage = child->percent > 0.0 ? child->percent : 1.0 / p->children;
198  assigned += sizes[i++] = lround(percentage * total);
199  }
200  assert(assigned == total ||
201  (assigned > total && assigned - total <= p->children * 2) ||
202  (assigned < total && total - assigned <= p->children * 2));
203  int signal = assigned < total ? 1 : -1;
204  while (assigned != total) {
205  for (i = 0; i < p->children && assigned != total; ++i) {
206  sizes[i] += signal;
207  assigned += signal;
208  }
209  }
210 
211  return sizes;
212 }
213 
214 static void render_root(Con *con, Con *fullscreen) {
215  Con *output;
216  if (!fullscreen) {
217  TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
218  render_con(output, false);
219  }
220  }
221 
222  /* We need to render floating windows after rendering all outputs’
223  * tiling windows because they need to be on top of *every* output at
224  * all times. This is important when the user places floating
225  * windows/containers so that they overlap on another output. */
226  DLOG("Rendering floating windows:\n");
227  TAILQ_FOREACH(output, &(con->nodes_head), nodes) {
228  if (con_is_internal(output))
229  continue;
230  /* Get the active workspace of that output */
231  Con *content = output_get_content(output);
232  if (!content || TAILQ_EMPTY(&(content->focus_head))) {
233  DLOG("Skipping this output because it is currently being destroyed.\n");
234  continue;
235  }
236  Con *workspace = TAILQ_FIRST(&(content->focus_head));
237  Con *fullscreen = con_get_fullscreen_covering_ws(workspace);
238  Con *child;
239  TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) {
240  if (fullscreen != NULL) {
241  /* Don’t render floating windows when there is a fullscreen
242  * window on that workspace. Necessary to make floating
243  * fullscreen work correctly (ticket #564). Exception to the
244  * above rule: smart popup_during_fullscreen handling (popups
245  * belonging to the fullscreen app will be rendered). */
246  if (config.popup_during_fullscreen != PDF_SMART || fullscreen->window == NULL) {
247  continue;
248  }
249 
250  Con *floating_child = con_descend_focused(child);
251  Con *transient_con = floating_child;
252  bool is_transient_for = false;
253  while (transient_con != NULL &&
254  transient_con->window != NULL &&
255  transient_con->window->transient_for != XCB_NONE) {
256  DLOG("transient_con = 0x%08x, transient_con->window->transient_for = 0x%08x, fullscreen_id = 0x%08x\n",
257  transient_con->window->id, transient_con->window->transient_for, fullscreen->window->id);
258  if (transient_con->window->transient_for == fullscreen->window->id) {
259  is_transient_for = true;
260  break;
261  }
262  Con *next_transient = con_by_window_id(transient_con->window->transient_for);
263  if (next_transient == NULL)
264  break;
265  /* Some clients (e.g. x11-ssh-askpass) actually set
266  * WM_TRANSIENT_FOR to their own window id, so break instead of
267  * looping endlessly. */
268  if (transient_con == next_transient)
269  break;
270  transient_con = next_transient;
271  }
272 
273  if (!is_transient_for)
274  continue;
275  else {
276  DLOG("Rendering floating child even though in fullscreen mode: "
277  "floating->transient_for (0x%08x) --> fullscreen->id (0x%08x)\n",
278  floating_child->window->transient_for, fullscreen->window->id);
279  }
280  }
281  DLOG("floating child at (%d,%d) with %d x %d\n",
282  child->rect.x, child->rect.y, child->rect.width, child->rect.height);
283  x_raise_con(child);
284  render_con(child, true);
285  }
286  }
287 }
288 
289 /*
290  * Renders a container with layout L_OUTPUT. In this layout, all CT_DOCKAREAs
291  * get the height of their content and the remaining CT_CON gets the rest.
292  *
293  */
294 static void render_output(Con *con) {
295  Con *child, *dockchild;
296 
297  int x = con->rect.x;
298  int y = con->rect.y;
299  int height = con->rect.height;
300 
301  /* Find the content container and ensure that there is exactly one. Also
302  * check for any non-CT_DOCKAREA clients. */
303  Con *content = NULL;
304  TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
305  if (child->type == CT_CON) {
306  if (content != NULL) {
307  DLOG("More than one CT_CON on output container\n");
308  assert(false);
309  }
310  content = child;
311  } else if (child->type != CT_DOCKAREA) {
312  DLOG("Child %p of type %d is inside the OUTPUT con\n", child, child->type);
313  assert(false);
314  }
315  }
316 
317  if (content == NULL) {
318  DLOG("Skipping this output because it is currently being destroyed.\n");
319  return;
320  }
321 
322  /* We need to find out if there is a fullscreen con on the current workspace
323  * and take the short-cut to render it directly (the user does not want to
324  * see the dockareas in that case) */
325  Con *ws = con_get_fullscreen_con(content, CF_OUTPUT);
326  if (!ws) {
327  DLOG("Skipping this output because it is currently being destroyed.\n");
328  return;
329  }
330  Con *fullscreen = con_get_fullscreen_con(ws, CF_OUTPUT);
331  if (fullscreen) {
332  fullscreen->rect = con->rect;
333  x_raise_con(fullscreen);
334  render_con(fullscreen, false);
335  return;
336  }
337 
338  /* First pass: determine the height of all CT_DOCKAREAs (the sum of their
339  * children) and figure out how many pixels we have left for the rest */
340  TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
341  if (child->type != CT_DOCKAREA)
342  continue;
343 
344  child->rect.height = 0;
345  TAILQ_FOREACH(dockchild, &(child->nodes_head), nodes)
346  child->rect.height += dockchild->geometry.height;
347 
348  height -= child->rect.height;
349  }
350 
351  /* Second pass: Set the widths/heights */
352  TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
353  if (child->type == CT_CON) {
354  child->rect.x = x;
355  child->rect.y = y;
356  child->rect.width = con->rect.width;
357  child->rect.height = height;
358  }
359 
360  child->rect.x = x;
361  child->rect.y = y;
362  child->rect.width = con->rect.width;
363 
364  child->deco_rect.x = 0;
365  child->deco_rect.y = 0;
366  child->deco_rect.width = 0;
367  child->deco_rect.height = 0;
368 
369  y += child->rect.height;
370 
371  DLOG("child at (%d, %d) with (%d x %d)\n",
372  child->rect.x, child->rect.y, child->rect.width, child->rect.height);
373  x_raise_con(child);
374  render_con(child, child->type == CT_DOCKAREA);
375  }
376 }
377 
378 static void render_con_split(Con *con, Con *child, render_params *p, int i) {
379  assert(con->layout == L_SPLITH || con->layout == L_SPLITV);
380 
381  if (con->layout == L_SPLITH) {
382  child->rect.x = p->x;
383  child->rect.y = p->y;
384  child->rect.width = p->sizes[i];
385  child->rect.height = p->rect.height;
386  p->x += child->rect.width;
387  } else {
388  child->rect.x = p->x;
389  child->rect.y = p->y;
390  child->rect.width = p->rect.width;
391  child->rect.height = p->sizes[i];
392  p->y += child->rect.height;
393  }
394 
395  /* first we have the decoration, if this is a leaf node */
396  if (con_is_leaf(child)) {
397  if (child->border_style == BS_NORMAL) {
398  /* TODO: make a function for relative coords? */
399  child->deco_rect.x = child->rect.x - con->rect.x;
400  child->deco_rect.y = child->rect.y - con->rect.y;
401 
402  child->rect.y += p->deco_height;
403  child->rect.height -= p->deco_height;
404 
405  child->deco_rect.width = child->rect.width;
406  child->deco_rect.height = p->deco_height;
407  } else {
408  child->deco_rect.x = 0;
409  child->deco_rect.y = 0;
410  child->deco_rect.width = 0;
411  child->deco_rect.height = 0;
412  }
413  }
414 }
415 
416 static void render_con_stacked(Con *con, Con *child, render_params *p, int i) {
417  assert(con->layout == L_STACKED);
418 
419  child->rect.x = p->x;
420  child->rect.y = p->y;
421  child->rect.width = p->rect.width;
422  child->rect.height = p->rect.height;
423 
424  child->deco_rect.x = p->x - con->rect.x;
425  child->deco_rect.y = p->y - con->rect.y + (i * p->deco_height);
426  child->deco_rect.width = child->rect.width;
427  child->deco_rect.height = p->deco_height;
428 
429  if (p->children > 1 || (child->border_style != BS_PIXEL && child->border_style != BS_NONE)) {
430  child->rect.y += (p->deco_height * p->children);
431  child->rect.height -= (p->deco_height * p->children);
432  }
433 }
434 
435 static void render_con_tabbed(Con *con, Con *child, render_params *p, int i) {
436  assert(con->layout == L_TABBED);
437 
438  child->rect.x = p->x;
439  child->rect.y = p->y;
440  child->rect.width = p->rect.width;
441  child->rect.height = p->rect.height;
442 
443  child->deco_rect.width = floor((float)child->rect.width / p->children);
444  child->deco_rect.x = p->x - con->rect.x + i * child->deco_rect.width;
445  child->deco_rect.y = p->y - con->rect.y;
446 
447  /* Since the tab width may be something like 31,6 px per tab, we
448  * let the last tab have all the extra space (0,6 * children). */
449  if (i == (p->children - 1)) {
450  child->deco_rect.width += (child->rect.width - (child->deco_rect.x + child->deco_rect.width));
451  }
452 
453  if (p->children > 1 || (child->border_style != BS_PIXEL && child->border_style != BS_NONE)) {
454  child->rect.y += p->deco_height;
455  child->rect.height -= p->deco_height;
456  child->deco_rect.height = p->deco_height;
457  } else {
458  child->deco_rect.height = (child->border_style == BS_PIXEL ? 1 : 0);
459  }
460 }
461 
462 static void render_con_dockarea(Con *con, Con *child, render_params *p) {
463  assert(con->layout == L_DOCKAREA);
464 
465  child->rect.x = p->x;
466  child->rect.y = p->y;
467  child->rect.width = p->rect.width;
468  child->rect.height = child->geometry.height;
469 
470  child->deco_rect.x = 0;
471  child->deco_rect.y = 0;
472  child->deco_rect.width = 0;
473  child->deco_rect.height = 0;
474  p->y += child->rect.height;
475 }
476 
477 /*
478  * Decides whether the container should be inset.
479  */
480 bool should_inset_con(Con *con, int children) {
481  /* Don't inset floating containers and workspaces. */
482  if (con->type == CT_FLOATING_CON || con->type == CT_WORKSPACE)
483  return false;
484 
485  if (con_is_leaf(con))
486  return true;
487 
488  return (con->layout == L_STACKED || con->layout == L_TABBED) && children > 0;
489 }
490 
491 /*
492  * Returns whether the given container has an adjacent container in the
493  * specified direction. In other words, this returns true if and only if
494  * the container is not touching the edge of the screen in that direction.
495  */
496 bool has_adjacent_container(Con *con, direction_t direction) {
497  Con *workspace = con_get_workspace(con);
498  Con *fullscreen = con_get_fullscreen_con(workspace, CF_GLOBAL);
499  if (fullscreen == NULL)
500  fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT);
501 
502  /* If this container is fullscreen by itself, there's no adjacent container. */
503  if (con == fullscreen)
504  return false;
505 
506  Con *first = con;
507  Con *second = NULL;
508  bool found_neighbor = resize_find_tiling_participants(&first, &second, direction, false);
509  if (!found_neighbor)
510  return false;
511 
512  /* If we have an adjacent container and nothing is fullscreen, we consider it. */
513  if (fullscreen == NULL)
514  return true;
515 
516  /* For fullscreen containers, only consider the adjacent container if it is also fullscreen. */
517  return con_has_parent(con, fullscreen) && con_has_parent(second, fullscreen);
518 }
gaps_t::left
int left
Definition: data.h:153
Window::transient_for
xcb_window_t transient_for
Definition: data.h:436
con_by_window_id
Con * con_by_window_id(xcb_window_t window)
Returns the container with the given client window ID or NULL if no such container exists.
Definition: con.c:647
render_con_stacked
static void render_con_stacked(Con *con, Con *child, render_params *p, int i)
Definition: render.c:416
con_get_fullscreen_con
Con * con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode)
Returns the first fullscreen node below this node.
Definition: con.c:502
L_OUTPUT
@ L_OUTPUT
Definition: data.h:108
should_inset_con
bool should_inset_con(Con *con, int children)
Definition: render.c:480
Rect::y
uint32_t y
Definition: data.h:178
calculate_effective_gaps
gaps_t calculate_effective_gaps(Con *con)
Calculates the effective gap sizes for a container.
Definition: con.c:2276
gaps_t::inner
int inner
Definition: data.h:149
Con::rect
struct Rect rect
Definition: data.h:676
Con::floating_head
floating_head
Definition: data.h:718
Font::height
int height
The height of the font, built from font_ascent + font_descent.
Definition: libi3.h:67
gaps_t::bottom
int bottom
Definition: data.h:152
con_is_leaf
bool con_is_leaf(Con *con)
Returns true when this node is a leaf node (has no children)
Definition: con.c:337
L_SPLITV
@ L_SPLITV
Definition: data.h:109
gaps_t
Definition: data.h:148
D_LEFT
@ D_LEFT
Definition: data.h:58
render_params::y
int y
Definition: render.h:22
render_deco_height
int render_deco_height(void)
Returns the height for the decorations.
Definition: render.c:27
Con::mapped
bool mapped
Definition: data.h:638
L_DOCKAREA
@ L_DOCKAREA
Definition: data.h:107
Con::layout
layout_t layout
Definition: data.h:750
render_output
static void render_output(Con *con)
Definition: render.c:294
con_has_parent
bool con_has_parent(Con *con, Con *parent)
Checks if the container has the given parent as an actual parent.
Definition: con.c:629
TAILQ_EMPTY
#define TAILQ_EMPTY(head)
Definition: queue.h:344
BS_PIXEL
@ BS_PIXEL
Definition: data.h:67
render_params::rect
Rect rect
Definition: render.h:28
Con::window_rect
struct Rect window_rect
Definition: data.h:679
L_SPLITH
@ L_SPLITH
Definition: data.h:110
all.h
CF_OUTPUT
@ CF_OUTPUT
Definition: data.h:623
render_root
static void render_root(Con *con, Con *fullscreen)
Definition: render.c:214
y
#define y(x,...)
Definition: commands.c:21
L_TABBED
@ L_TABBED
Definition: data.h:106
DLOG
#define DLOG(fmt,...)
Definition: libi3.h:104
Con::window
struct Window * window
Definition: data.h:708
CF_NONE
@ CF_NONE
Definition: data.h:622
rect_add
Rect rect_add(Rect a, Rect b)
Definition: util.c:42
TAILQ_FOREACH_REVERSE
#define TAILQ_FOREACH_REVERSE(var, head, headname, field)
Definition: queue.h:352
Con::focus_head
focus_head
Definition: data.h:724
render_params::sizes
int * sizes
Definition: render.h:32
TAILQ_FIRST
#define TAILQ_FIRST(head)
Definition: queue.h:336
render_con_dockarea
static void render_con_dockarea(Con *con, Con *child, render_params *p)
Definition: render.c:462
FREE
#define FREE(pointer)
Definition: util.h:47
D_RIGHT
@ D_RIGHT
Definition: data.h:59
precalculate_sizes
static int * precalculate_sizes(Con *con, render_params *p)
Definition: render.c:185
resize_find_tiling_participants
bool resize_find_tiling_participants(Con **current, Con **other, direction_t direction, bool both_sides)
Definition: resize.c:70
D_DOWN
@ D_DOWN
Definition: data.h:61
con_rect_size_in_orientation
uint32_t con_rect_size_in_orientation(Con *con)
Returns given container's rect size depending on its orientation.
Definition: con.c:2480
Con::percent
double percent
Definition: data.h:702
render_con_tabbed
static void render_con_tabbed(Con *con, Con *child, render_params *p, int i)
Definition: render.c:435
Con::fullscreen_mode
fullscreen_mode_t fullscreen_mode
Definition: data.h:729
gaps_t::right
int right
Definition: data.h:151
Con::deco_rect
struct Rect deco_rect
Definition: data.h:682
render_params::deco_height
int deco_height
Definition: render.h:25
Con::border_width
int border_width
Definition: data.h:705
con_border_style_rect
Rect con_border_style_rect(Con *con)
Returns a "relative" Rect which contains the amount of pixels that need to be added to the original R...
Definition: con.c:1630
Config::font
i3Font font
Definition: configuration.h:98
con_num_children
int con_num_children(Con *con)
Returns the number of children of this container.
Definition: con.c:922
gaps_t::top
int top
Definition: data.h:150
render_params
This is used to keep a state to pass around when rendering a con in render_con().
Definition: render.h:19
con_is_internal
bool con_is_internal(Con *con)
Returns true if the container is internal, such as __i3_scratch.
Definition: con.c:567
Con::nodes_head
nodes_head
Definition: data.h:721
Rect::width
uint32_t width
Definition: data.h:179
L_STACKED
@ L_STACKED
Definition: data.h:105
Con::type
enum Con::@20 type
Window::id
xcb_window_t id
Definition: data.h:431
Rect
struct Rect Rect
Definition: data.h:44
smalloc
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
focused
struct Con * focused
Definition: tree.c:13
config
Config config
Definition: config.c:17
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:347
BS_NONE
@ BS_NONE
Definition: data.h:66
render_params::x
int x
Definition: render.h:21
Con::border_style
border_style_t border_style
Definition: data.h:751
render_params::children
int children
Definition: render.h:30
Con::geometry
struct Rect geometry
the geometry this window requested when getting mapped
Definition: data.h:684
con_descend_focused
Con * con_descend_focused(Con *con)
Returns the focused con inside this client, descending the tree as far as possible.
Definition: con.c:1516
Con
A 'Con' represents everything from the X11 root window down to a single X11 window.
Definition: data.h:637
BS_NORMAL
@ BS_NORMAL
Definition: data.h:65
render_con
void render_con(Con *con, bool already_inset)
"Renders" the given container (and its children), meaning that all rects are updated correctly.
Definition: render.c:42
render_con_split
static void render_con_split(Con *con, Con *child, render_params *p, int i)
Definition: render.c:378
CF_GLOBAL
@ CF_GLOBAL
Definition: data.h:624
Rect::height
uint32_t height
Definition: data.h:180
con_get_fullscreen_covering_ws
Con * con_get_fullscreen_covering_ws(Con *ws)
Returns the fullscreen node that covers the given workspace if it exists.
Definition: con.c:552
Con::name
char * name
Definition: data.h:686
Rect::x
uint32_t x
Definition: data.h:177
D_UP
@ D_UP
Definition: data.h:60
con_get_workspace
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
Definition: con.c:453
output_get_content
Con * output_get_content(Con *output)
Returns the output container below the given output container.
Definition: output.c:16
x_raise_con
void x_raise_con(Con *con)
Raises the specified container in the internal stack of X windows.
Definition: x.c:1366
has_adjacent_container
bool has_adjacent_container(Con *con, direction_t direction)
Definition: render.c:496
direction_t
direction_t
Definition: data.h:56
Config::popup_during_fullscreen
enum Config::@8 popup_during_fullscreen
What should happen when a new popup is opened during fullscreen mode.
Rect
Stores a rectangle, for example the size of a window, the child window etc.
Definition: data.h:176