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