/* Focus the output on which the user moved his cursor */
Con *old_focused = focused;
- con_focus(con_descend_focused(output_get_content(output->con)));
+ Con *next = con_descend_focused(output_get_content(output->con));
+ /* Since we are switching outputs, this *must* be a different workspace, so
+ * call workspace_show() */
+ workspace_show(con_get_workspace(next));
+ con_focus(next);
/* If the focus changed, we re-render to get updated decorations */
if (old_focused != focused)
bsr.height -= deco_height;
}
Con *floatingcon = con->parent;
- DLOG("Container is a floating leaf node, will do that.\n");
+
+ Rect newrect = floatingcon->rect;
+
if (event->value_mask & XCB_CONFIG_WINDOW_X) {
- floatingcon->rect.x = event->x + (-1) * bsr.x;
- DLOG("proposed x = %d, new x is %d\n", event->x, floatingcon->rect.x);
+ newrect.x = event->x + (-1) * bsr.x;
+ DLOG("proposed x = %d, new x is %d\n", event->x, newrect.x);
}
if (event->value_mask & XCB_CONFIG_WINDOW_Y) {
- floatingcon->rect.y = event->y + (-1) * bsr.y;
- DLOG("proposed y = %d, new y is %d\n", event->y, floatingcon->rect.y);
+ newrect.y = event->y + (-1) * bsr.y;
+ DLOG("proposed y = %d, new y is %d\n", event->y, newrect.y);
}
if (event->value_mask & XCB_CONFIG_WINDOW_WIDTH) {
- floatingcon->rect.width = event->width + (-1) * bsr.width;
- floatingcon->rect.width += con->border_width * 2;
- DLOG("proposed width = %d, new width is %d (x11 border %d)\n", event->width, floatingcon->rect.width, con->border_width);
+ newrect.width = event->width + (-1) * bsr.width;
+ newrect.width += con->border_width * 2;
+ DLOG("proposed width = %d, new width is %d (x11 border %d)\n",
+ event->width, newrect.width, con->border_width);
}
if (event->value_mask & XCB_CONFIG_WINDOW_HEIGHT) {
- floatingcon->rect.height = event->height + (-1) * bsr.height;
- floatingcon->rect.height += con->border_width * 2;
- DLOG("proposed height = %d, new height is %d (x11 border %d)\n", event->height, floatingcon->rect.height, con->border_width);
+ newrect.height = event->height + (-1) * bsr.height;
+ newrect.height += con->border_width * 2;
+ DLOG("proposed height = %d, new height is %d (x11 border %d)\n",
+ event->height, newrect.height, con->border_width);
}
- floating_maybe_reassign_ws(floatingcon);
- tree_render();
+
+ DLOG("Container is a floating leaf node, will do that.\n");
+ floating_reposition(floatingcon, newrect);
+ return 1;
}
/* Dock windows can be reconfigured in their height */
*
*/
static int handle_unmap_notify_event(xcb_unmap_notify_event_t *event) {
- // XXX: this is commented out because in src/x.c we disable EnterNotify events
- /* we need to ignore EnterNotify events which will be generated because a
- * different window is visible now */
- //add_ignore_event(event->sequence, XCB_ENTER_NOTIFY);
+ /* If the client (as opposed to i3) destroyed or unmapped a window, an
+ * EnterNotify event will follow (indistinguishable from an EnterNotify
+ * event caused by moving your mouse), causing i3 to set focus to whichever
+ * window is now visible.
+ *
+ * In a complex stacked or tabbed layout (take two v-split containers in a
+ * tabbed container), when the bottom window in tab2 is closed, the bottom
+ * window of tab1 is visible instead. X11 will thus send an EnterNotify
+ * event for the bottom window of tab1, while the focus should be set to
+ * the remaining window of tab2.
+ *
+ * Therefore, we ignore all EnterNotify events which have the same sequence
+ * as an UnmapNotify event. */
+ add_ignore_event(event->sequence, XCB_ENTER_NOTIFY);
DLOG("UnmapNotify for 0x%08x (received from 0x%08x), serial %d\n", event->window, event->event, event->sequence);
Con *con = con_by_window_id(event->window);
static int handle_expose_event(xcb_expose_event_t *event) {
Con *parent;
- /* event->count is the number of minimum remaining expose events for this
- * window, so we skip all events but the last one */
- if (event->count != 0)
- return 1;
-
DLOG("window = %08x\n", event->window);
if ((parent = con_by_frame_id(event->window)) == NULL) {
return 1;
}
- /* re-render the parent (recursively, if it’s a split con) */
- x_deco_recurse(parent);
+ /* Since we render to our pixmap on every change anyways, expose events
+ * only tell us that the X server lost (parts of) the window contents. We
+ * can handle that by copying the appropriate part from our pixmap to the
+ * window. */
+ xcb_copy_area(conn, parent->pixmap, parent->frame, parent->pm_gc,
+ event->x, event->y, event->x, event->y,
+ event->width, event->height);
xcb_flush(conn);
return 1;
return 1;
}
+ /* Skip dock clients, they cannot get the i3 focus. */
+ if (con->parent->type == CT_DOCKAREA) {
+ DLOG("This is a dock client, not focusing.\n");
+ return 1;
+ }
+
DLOG("focus is different, updating decorations\n");
/* Get the currently focused workspace to check if the focus change also