]> git.sur5r.net Git - i3/i3/blob - src/manage.c
first step of the big refactoring ("tree" branch).
[i3/i3] / src / manage.c
1 /*
2  * vim:ts=8:expandtab
3  *
4  * i3 - an improved dynamic tiling window manager
5  *
6  * © 2009-2010 Michael Stapelberg and contributors
7  *
8  * See file LICENSE for license information.
9  *
10  * src/manage.c: Contains all functions for initially managing new windows
11  *               (or existing ones on restart).
12  *
13  */
14
15 #include "all.h"
16
17 extern struct Con *focused;
18
19
20 /*
21  * Go through all existing windows (if the window manager is restarted) and manage them
22  *
23  */
24 void manage_existing_windows(xcb_window_t root) {
25         xcb_query_tree_reply_t *reply;
26         int i, len;
27         xcb_window_t *children;
28         xcb_get_window_attributes_cookie_t *cookies;
29
30         /* Get the tree of windows whose parent is the root window (= all) */
31         if ((reply = xcb_query_tree_reply(conn, xcb_query_tree(conn, root), 0)) == NULL)
32                 return;
33
34         len = xcb_query_tree_children_length(reply);
35         cookies = smalloc(len * sizeof(*cookies));
36
37         /* Request the window attributes for every window */
38         children = xcb_query_tree_children(reply);
39         for (i = 0; i < len; ++i)
40                 cookies[i] = xcb_get_window_attributes(conn, children[i]);
41
42         /* Call manage_window with the attributes for every window */
43         for (i = 0; i < len; ++i)
44                 manage_window(children[i], cookies[i], true);
45
46
47         free(reply);
48         free(cookies);
49 }
50
51 /*
52  * Restores the geometry of each window by reparenting it to the root window
53  * at the position of its frame.
54  *
55  * This is to be called *only* before exiting/restarting i3 because of evil
56  * side-effects which are to be expected when continuing to run i3.
57  *
58  */
59 void restore_geometry() {
60         LOG("Restoring geometry\n");
61
62         Con *con;
63         TAILQ_FOREACH(con, &all_cons, all_cons)
64                 if (con->window) {
65                         printf("placing window at %d %d\n", con->rect.x, con->rect.y);
66                         xcb_reparent_window(conn, con->window->id, root,
67                                             con->rect.x, con->rect.y);
68                 }
69
70         /* Make sure our changes reach the X server, we restart/exit now */
71         xcb_flush(conn);
72 }
73
74 /*
75  * Do some sanity checks and then reparent the window.
76  *
77  */
78 void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cookie,
79                    bool needs_to_be_mapped) {
80         xcb_drawable_t d = { window };
81         xcb_get_geometry_cookie_t geomc;
82         xcb_get_geometry_reply_t *geom;
83         xcb_get_window_attributes_reply_t *attr = 0;
84
85         printf("---> looking at window 0x%08x\n", window);
86
87         xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
88                                   utf8_title_cookie, title_cookie,
89                                   class_cookie, leader_cookie;
90
91         wm_type_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_WINDOW_TYPE], UINT32_MAX);
92         strut_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_STRUT_PARTIAL], UINT32_MAX);
93         state_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_STATE], UINT32_MAX);
94         utf8_title_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[_NET_WM_NAME], 128);
95         leader_cookie = xcb_get_any_property_unchecked(conn, false, window, atoms[WM_CLIENT_LEADER], UINT32_MAX);
96         title_cookie = xcb_get_any_property_unchecked(conn, false, window, WM_NAME, 128);
97         class_cookie = xcb_get_any_property_unchecked(conn, false, window, WM_CLASS, 128);
98
99
100         geomc = xcb_get_geometry(conn, d);
101
102         /* Check if the window is mapped (it could be not mapped when intializing and
103            calling manage_window() for every window) */
104         if ((attr = xcb_get_window_attributes_reply(conn, cookie, 0)) == NULL) {
105                 LOG("Could not get attributes\n");
106                 return;
107         }
108
109         if (needs_to_be_mapped && attr->map_state != XCB_MAP_STATE_VIEWABLE) {
110                 LOG("map_state unviewable\n");
111                 goto out;
112         }
113
114         /* Don’t manage clients with the override_redirect flag */
115         LOG("override_redirect is %d\n", attr->override_redirect);
116         if (attr->override_redirect)
117                 goto out;
118
119         /* Check if the window is already managed */
120         if (con_by_window_id(window) != NULL)
121                 goto out;
122
123         /* Get the initial geometry (position, size, …) */
124         if ((geom = xcb_get_geometry_reply(conn, geomc, 0)) == NULL)
125                 goto out;
126
127         LOG("reparenting!\n");
128
129         i3Window *cwindow = scalloc(sizeof(i3Window));
130         cwindow->id = window;
131
132         class_cookie = xcb_get_any_property_unchecked(conn, false, window, WM_CLASS, 128);
133         xcb_get_property_reply_t *preply;
134         preply = xcb_get_property_reply(conn, class_cookie, NULL);
135         if (preply == NULL || xcb_get_property_value_length(preply) == 0) {
136                 LOG("cannot get wm_class\n");
137         } else cwindow->class = strdup(xcb_get_property_value(preply));
138
139         Con *nc;
140         Match *match;
141
142         /* TODO: assignments */
143         /* TODO: two matches for one container */
144         /* See if any container swallows this new window */
145         nc = con_for_window(cwindow, &match);
146         if (nc == NULL) {
147                 if (focused->type == CT_CON && con_accepts_window(focused)) {
148                         LOG("using current container, focused = %p, focused->name = %s\n",
149                                         focused, focused->name);
150                         nc = focused;
151                 } else nc = tree_open_con(NULL);
152         } else {
153                 if (match != NULL && match->insert_where == M_ACTIVE) {
154                         /* We need to go down the focus stack starting from nc */
155                         while (TAILQ_FIRST(&(nc->focus_head)) != TAILQ_END(&(nc->focus_head))) {
156                                 printf("walking down one step...\n");
157                                 nc = TAILQ_FIRST(&(nc->focus_head));
158                         }
159                         /* We need to open a new con */
160                         /* TODO: make a difference between match-once containers (directly assign
161                          * cwindow) and match-multiple (tree_open_con first) */
162                         nc = tree_open_con(nc->parent);
163
164                 }
165
166         }
167         nc->window = cwindow;
168
169         xcb_void_cookie_t rcookie = xcb_reparent_window_checked(conn, window, nc->frame, 0, 0);
170         if (xcb_request_check(conn, rcookie) != NULL) {
171                 LOG("Could not reparent the window, aborting\n");
172                 goto out;
173                 //xcb_destroy_window(conn, nc->frame);
174         }
175
176         xcb_change_save_set(conn, XCB_SET_MODE_INSERT, window);
177
178         tree_render();
179
180 #if 0
181         /* Reparent the window and add it to our list of managed windows */
182         reparent_window(conn, window, attr->visual, geom->root, geom->depth,
183                         geom->x, geom->y, geom->width, geom->height,
184                         geom->border_width);
185 #endif
186
187         /* Generate callback events for every property we watch */
188         free(geom);
189 out:
190         free(attr);
191         return;
192 }
193
194 #if 0
195 /*
196  * reparent_window() gets called when a new window was opened and becomes a child of the root
197  * window, or it gets called by us when we manage the already existing windows at startup.
198  *
199  * Essentially, this is the point where we take over control.
200  *
201  */
202 void reparent_window(xcb_connection_t *conn, xcb_window_t child,
203                      xcb_visualid_t visual, xcb_window_t root, uint8_t depth,
204                      int16_t x, int16_t y, uint16_t width, uint16_t height,
205                      uint32_t border_width) {
206
207         xcb_get_property_cookie_t wm_type_cookie, strut_cookie, state_cookie,
208                                   utf8_title_cookie, title_cookie,
209                                   class_cookie, leader_cookie;
210         uint32_t mask = 0;
211         uint32_t values[3];
212         uint16_t original_height = height;
213         bool map_frame = true;
214
215         /* We are interested in property changes */
216         mask = XCB_CW_EVENT_MASK;
217         values[0] = CHILD_EVENT_MASK;
218         xcb_change_window_attributes(conn, child, mask, values);
219
220         /* Place requests for properties ASAP */
221         wm_type_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_WINDOW_TYPE], UINT32_MAX);
222         strut_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STRUT_PARTIAL], UINT32_MAX);
223         state_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_STATE], UINT32_MAX);
224         utf8_title_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[_NET_WM_NAME], 128);
225         leader_cookie = xcb_get_any_property_unchecked(conn, false, child, atoms[WM_CLIENT_LEADER], UINT32_MAX);
226         title_cookie = xcb_get_any_property_unchecked(conn, false, child, WM_NAME, 128);
227         class_cookie = xcb_get_any_property_unchecked(conn, false, child, WM_CLASS, 128);
228
229         Client *new = table_get(&by_child, child);
230
231         /* Events for already managed windows should already be filtered in manage_window() */
232         assert(new == NULL);
233
234         LOG("Managing window 0x%08x\n", child);
235         DLOG("x = %d, y = %d, width = %d, height = %d\n", x, y, width, height);
236         new = scalloc(sizeof(Client));
237         new->force_reconfigure = true;
238
239         /* Update the data structures */
240         Client *old_focused = CUR_CELL->currently_focused;
241
242         new->container = CUR_CELL;
243         new->workspace = new->container->workspace;
244
245         /* Minimum useful size for managed windows is 75x50 (primarily affects floating) */
246         width = max(width, 75);
247         height = max(height, 50);
248
249         new->frame = xcb_generate_id(conn);
250         new->child = child;
251         new->rect.width = width;
252         new->rect.height = height;
253         new->width_increment = 1;
254         new->height_increment = 1;
255         new->border_width = border_width;
256         /* Pre-initialize the values for floating */
257         new->floating_rect.x = -1;
258         new->floating_rect.width = width;
259         new->floating_rect.height = height;
260
261         if (config.default_border != NULL)
262                 client_init_border(conn, new, config.default_border[1]);
263
264         mask = 0;
265
266         /* Don’t generate events for our new window, it should *not* be managed */
267         mask |= XCB_CW_OVERRIDE_REDIRECT;
268         values[0] = 1;
269
270         /* We want to know when… */
271         mask |= XCB_CW_EVENT_MASK;
272         values[1] = FRAME_EVENT_MASK;
273
274         i3Font *font = load_font(conn, config.font);
275         width = min(width, c_ws->rect.x + c_ws->rect.width);
276         height = min(height, c_ws->rect.y + c_ws->rect.height);
277
278         Rect framerect = {x, y,
279                           width + 2 + 2,                  /* 2 px border at each side */
280                           height + 2 + 2 + font->height}; /* 2 px border plus font’s height */
281
282         /* Yo dawg, I heard you like windows, so I create a window around your window… */
283         new->frame = create_window(conn, framerect, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_CURSOR_LEFT_PTR, false, mask, values);
284
285         /* Put the client inside the save set. Upon termination (whether killed or normal exit
286            does not matter) of the window manager, these clients will be correctly reparented
287            to their most closest living ancestor (= cleanup) */
288         xcb_change_save_set(conn, XCB_SET_MODE_INSERT, child);
289
290         /* Generate a graphics context for the titlebar */
291         new->titlegc = xcb_generate_id(conn);
292         xcb_create_gc(conn, new->titlegc, new->frame, 0, 0);
293
294         /* Moves the original window into the new frame we've created for it */
295         new->awaiting_useless_unmap = true;
296         xcb_void_cookie_t cookie = xcb_reparent_window_checked(conn, child, new->frame, 0, font->height);
297         if (xcb_request_check(conn, cookie) != NULL) {
298                 DLOG("Could not reparent the window, aborting\n");
299                 xcb_destroy_window(conn, new->frame);
300                 free(new);
301                 return;
302         }
303
304         /* Put our data structure (Client) into the table */
305         table_put(&by_parent, new->frame, new);
306         table_put(&by_child, child, new);
307
308         /* We need to grab the mouse buttons for click to focus */
309         xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS,
310                         XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
311                         1 /* left mouse button */,
312                         XCB_BUTTON_MASK_ANY /* don’t filter for any modifiers */);
313
314         xcb_grab_button(conn, false, child, XCB_EVENT_MASK_BUTTON_PRESS,
315                         XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, root, XCB_NONE,
316                         3 /* right mouse button */,
317                         XCB_BUTTON_MASK_ANY /* don’t filter for any modifiers */);
318
319         /* Get _NET_WM_WINDOW_TYPE (to see if it’s a dock) */
320         xcb_atom_t *atom;
321         xcb_get_property_reply_t *preply = xcb_get_property_reply(conn, wm_type_cookie, NULL);
322         if (preply != NULL && preply->value_len > 0 && (atom = xcb_get_property_value(preply))) {
323                 for (int i = 0; i < xcb_get_property_value_length(preply); i++)
324                         if (atom[i] == atoms[_NET_WM_WINDOW_TYPE_DOCK]) {
325                                 DLOG("Window is a dock.\n");
326                                 Output *t_out = get_output_containing(x, y);
327                                 if (t_out != c_ws->output) {
328                                         DLOG("Dock client requested to be on output %s by geometry (%d, %d)\n",
329                                                         t_out->name, x, y);
330                                         new->workspace = t_out->current_workspace;
331                                 }
332                                 new->dock = true;
333                                 new->borderless = true;
334                                 new->titlebar_position = TITLEBAR_OFF;
335                                 new->force_reconfigure = true;
336                                 new->container = NULL;
337                                 SLIST_INSERT_HEAD(&(t_out->dock_clients), new, dock_clients);
338                                 /* If it’s a dock we can’t make it float, so we break */
339                                 new->floating = FLOATING_AUTO_OFF;
340                                 break;
341                         } else if (atom[i] == atoms[_NET_WM_WINDOW_TYPE_DIALOG] ||
342                                    atom[i] == atoms[_NET_WM_WINDOW_TYPE_UTILITY] ||
343                                    atom[i] == atoms[_NET_WM_WINDOW_TYPE_TOOLBAR] ||
344                                    atom[i] == atoms[_NET_WM_WINDOW_TYPE_SPLASH]) {
345                                 /* Set the dialog window to automatically floating, will be used below */
346                                 new->floating = FLOATING_AUTO_ON;
347                                 DLOG("dialog/utility/toolbar/splash window, automatically floating\n");
348                         }
349         }
350
351         /* All clients which have a leader should be floating */
352         if (!new->dock && !client_is_floating(new) && new->leader != 0) {
353                 DLOG("Client has WM_CLIENT_LEADER hint set, setting floating\n");
354                 new->floating = FLOATING_AUTO_ON;
355         }
356
357         if (new->workspace->auto_float) {
358                 new->floating = FLOATING_AUTO_ON;
359                 DLOG("workspace is in autofloat mode, setting floating\n");
360         }
361
362         if (new->dock) {
363                 /* Get _NET_WM_STRUT_PARTIAL to determine the client’s requested height */
364                 uint32_t *strut;
365                 preply = xcb_get_property_reply(conn, strut_cookie, NULL);
366                 if (preply != NULL && preply->value_len > 0 && (strut = xcb_get_property_value(preply))) {
367                         /* We only use a subset of the provided values, namely the reserved space at the top/bottom
368                            of the screen. This is because the only possibility for bars is at to be at the top/bottom
369                            with maximum horizontal size.
370                            TODO: bars at the top */
371                         new->desired_height = strut[3];
372                         if (new->desired_height == 0) {
373                                 DLOG("Client wanted to be 0 pixels high, using the window's height (%d)\n", original_height);
374                                 new->desired_height = original_height;
375                         }
376                         DLOG("the client wants to be %d pixels high\n", new->desired_height);
377                 } else {
378                         DLOG("The client didn't specify space to reserve at the screen edge, using its height (%d)\n", original_height);
379                         new->desired_height = original_height;
380                 }
381         } else {
382                 /* If it’s not a dock, we can check on which workspace we should put it. */
383
384                 /* Firstly, we need to get the window’s class / title. We asked for the properties at the
385                  * top of this function, get them now and pass them to our callback function for window class / title
386                  * changes. It is important that the client was already inserted into the by_child table,
387                  * because the callbacks won’t work otherwise. */
388                 preply = xcb_get_property_reply(conn, utf8_title_cookie, NULL);
389                 handle_windowname_change(NULL, conn, 0, new->child, atoms[_NET_WM_NAME], preply);
390
391                 preply = xcb_get_property_reply(conn, title_cookie, NULL);
392                 handle_windowname_change_legacy(NULL, conn, 0, new->child, WM_NAME, preply);
393
394                 preply = xcb_get_property_reply(conn, class_cookie, NULL);
395                 handle_windowclass_change(NULL, conn, 0, new->child, WM_CLASS, preply);
396
397                 preply = xcb_get_property_reply(conn, leader_cookie, NULL);
398                 handle_clientleader_change(NULL, conn, 0, new->child, atoms[WM_CLIENT_LEADER], preply);
399
400                 /* if WM_CLIENT_LEADER is set, we put the new window on the
401                  * same window as its leader. This might be overwritten by
402                  * assignments afterwards. */
403                 if (new->leader != XCB_NONE) {
404                         DLOG("client->leader is set (to 0x%08x)\n", new->leader);
405                         Client *parent = table_get(&by_child, new->leader);
406                         if (parent != NULL && parent->container != NULL) {
407                                 Workspace *t_ws = parent->workspace;
408                                 new->container = t_ws->table[parent->container->col][parent->container->row];
409                                 new->workspace = t_ws;
410                                 old_focused = new->container->currently_focused;
411                                 map_frame = workspace_is_visible(t_ws);
412                                 new->urgent = true;
413                                 /* This is a little tricky: we cannot use
414                                  * workspace_update_urgent_flag() because the
415                                  * new window was not yet inserted into the
416                                  * focus stack on t_ws. */
417                                 t_ws->urgent = true;
418                         } else {
419                                 DLOG("parent is not usable\n");
420                         }
421                 }
422
423                 struct Assignment *assign;
424                 TAILQ_FOREACH(assign, &assignments, assignments) {
425                         if (get_matching_client(conn, assign->windowclass_title, new) == NULL)
426                                 continue;
427
428                         if (assign->floating == ASSIGN_FLOATING_ONLY ||
429                             assign->floating == ASSIGN_FLOATING) {
430                                 new->floating = FLOATING_AUTO_ON;
431                                 LOG("Assignment matches, putting client into floating mode\n");
432                                 if (assign->floating == ASSIGN_FLOATING_ONLY)
433                                         break;
434                         }
435
436                         LOG("Assignment \"%s\" matches, so putting it on workspace %d\n",
437                             assign->windowclass_title, assign->workspace);
438
439                         if (c_ws->output->current_workspace->num == (assign->workspace-1)) {
440                                 DLOG("We are already there, no need to do anything\n");
441                                 break;
442                         }
443
444                         DLOG("Changing container/workspace and unmapping the client\n");
445                         Workspace *t_ws = workspace_get(assign->workspace-1);
446                         workspace_initialize(t_ws, c_ws->output, false);
447
448                         new->container = t_ws->table[t_ws->current_col][t_ws->current_row];
449                         new->workspace = t_ws;
450                         old_focused = new->container->currently_focused;
451
452                         map_frame = workspace_is_visible(t_ws);
453                         break;
454                 }
455         }
456
457         if (new->workspace->fullscreen_client != NULL) {
458                 DLOG("Setting below fullscreen window\n");
459
460                 /* If we are in fullscreen, we should place the window below
461                  * the fullscreen window to not be annoying */
462                 uint32_t values[] = {
463                         new->workspace->fullscreen_client->frame,
464                         XCB_STACK_MODE_BELOW
465                 };
466                 xcb_configure_window(conn, new->frame,
467                                      XCB_CONFIG_WINDOW_SIBLING |
468                                      XCB_CONFIG_WINDOW_STACK_MODE, values);
469         }
470
471         /* Insert into the currently active container, if it’s not a dock window */
472         if (!new->dock && !client_is_floating(new)) {
473                 /* Insert after the old active client, if existing. If it does not exist, the
474                    container is empty and it does not matter, where we insert it */
475                 if (old_focused != NULL && !old_focused->dock)
476                         CIRCLEQ_INSERT_AFTER(&(new->container->clients), old_focused, new, clients);
477                 else CIRCLEQ_INSERT_TAIL(&(new->container->clients), new, clients);
478
479                 if (new->container->workspace->fullscreen_client != NULL)
480                         SLIST_INSERT_AFTER(new->container->workspace->fullscreen_client, new, focus_clients);
481                 else SLIST_INSERT_HEAD(&(new->container->workspace->focus_stack), new, focus_clients);
482
483                 client_set_below_floating(conn, new);
484         }
485
486         if (client_is_floating(new)) {
487                 SLIST_INSERT_HEAD(&(new->workspace->focus_stack), new, focus_clients);
488
489                 /* Add the client to the list of floating clients for its workspace */
490                 TAILQ_INSERT_TAIL(&(new->workspace->floating_clients), new, floating_clients);
491
492                 new->container = NULL;
493
494                 new->rect.width = new->floating_rect.width + 2 + 2;
495                 new->rect.height = new->floating_rect.height + (font->height + 2 + 2) + 2;
496
497                 /* Some clients (like GIMP’s color picker window) get mapped
498                  * to (0, 0), so we push them to a reasonable position
499                  * (centered over their leader) */
500                 if (new->leader != 0 && x == 0 && y == 0) {
501                         DLOG("Floating client wants to (0x0), moving it over its leader instead\n");
502                         Client *leader = table_get(&by_child, new->leader);
503                         if (leader == NULL) {
504                                 DLOG("leader is NULL, centering it over current workspace\n");
505
506                                 x = c_ws->rect.x + (c_ws->rect.width / 2) - (new->rect.width / 2);
507                                 y = c_ws->rect.y + (c_ws->rect.height / 2) - (new->rect.height / 2);
508                         } else {
509                                 x = leader->rect.x + (leader->rect.width / 2) - (new->rect.width / 2);
510                                 y = leader->rect.y + (leader->rect.height / 2) - (new->rect.height / 2);
511                         }
512                 }
513                 new->floating_rect.x = new->rect.x = x;
514                 new->floating_rect.y = new->rect.y = y;
515                 DLOG("copying floating_rect from tiling (%d, %d) size (%d, %d)\n",
516                                 new->floating_rect.x, new->floating_rect.y,
517                                 new->floating_rect.width, new->floating_rect.height);
518                 DLOG("outer rect (%d, %d) size (%d, %d)\n",
519                                 new->rect.x, new->rect.y, new->rect.width, new->rect.height);
520
521                 /* Make sure it is on top of the other windows */
522                 xcb_raise_window(conn, new->frame);
523                 reposition_client(conn, new);
524                 resize_client(conn, new);
525                 /* redecorate_window flushes */
526                 redecorate_window(conn, new);
527         }
528
529         new->initialized = true;
530
531         /* Check if the window already got the fullscreen hint set */
532         xcb_atom_t *state;
533         if ((preply = xcb_get_property_reply(conn, state_cookie, NULL)) != NULL &&
534             (state = xcb_get_property_value(preply)) != NULL)
535                 /* Check all set _NET_WM_STATEs */
536                 for (int i = 0; i < xcb_get_property_value_length(preply); i++) {
537                         if (state[i] != atoms[_NET_WM_STATE_FULLSCREEN])
538                                 continue;
539                         /* If the window got the fullscreen state, we just toggle fullscreen
540                            and don’t event bother to redraw the layout – that would not change
541                            anything anyways */
542                         client_toggle_fullscreen(conn, new);
543                         goto map;
544                 }
545
546         render_layout(conn);
547
548 map:
549         /* Map the window first to avoid flickering */
550         xcb_map_window(conn, child);
551         if (map_frame)
552                 client_map(conn, new);
553
554         if ((CUR_CELL->workspace->fullscreen_client == NULL || new->fullscreen) && !new->dock) {
555                 /* Focus the new window if we’re not in fullscreen mode and if it is not a dock window */
556                 if ((new->workspace->fullscreen_client == NULL) || new->fullscreen) {
557                         if (!client_is_floating(new)) {
558                                 new->container->currently_focused = new;
559                                 if (map_frame)
560                                         render_container(conn, new->container);
561                         }
562                         if (new->container == CUR_CELL || client_is_floating(new)) {
563                                 xcb_set_input_focus(conn, XCB_INPUT_FOCUS_POINTER_ROOT, new->child, XCB_CURRENT_TIME);
564                                 ewmh_update_active_window(new->child);
565                         }
566                 }
567         }
568
569         xcb_flush(conn);
570 }
571 #endif