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