From 8659419ef66fe64fd45dcf086262b7020fa438b4 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Thu, 25 Jun 2009 13:46:47 +0200 Subject: [PATCH] Bugfix: Correctly handle moving fullscreen client onto another screen (Thanks dirkson) --- include/client.h | 7 +++ src/client.c | 117 ++++++++++++++++++++++++++--------------------- src/commands.c | 15 ++++-- 3 files changed, 85 insertions(+), 54 deletions(-) diff --git a/include/client.h b/include/client.h index 964dd2ea..85a41531 100644 --- a/include/client.h +++ b/include/client.h @@ -44,6 +44,13 @@ void client_kill(xcb_connection_t *conn, Client *window); bool client_matches_class_name(Client *client, char *to_class, char *to_title, char *to_title_ucs, int to_title_ucs_len); +/** + * Enters fullscreen mode for the given client. This is called by toggle_fullscreen + * and when moving a fullscreen client to another screen. + * + */ +void client_enter_fullscreen(xcb_connection_t *conn, Client *client); + /** * Toggles fullscreen mode for the given client. It updates the data structures and * reconfigures (= resizes/moves) the client and its frame to the full size of the diff --git a/src/client.c b/src/client.c index 5d78d38f..c3a80c36 100644 --- a/src/client.c +++ b/src/client.c @@ -136,6 +136,53 @@ bool client_matches_class_name(Client *client, char *to_class, char *to_title, return true; } +/* + * Enters fullscreen mode for the given client. This is called by toggle_fullscreen + * and when moving a fullscreen client to another screen. + * + */ +void client_enter_fullscreen(xcb_connection_t *conn, Client *client) { + Workspace *workspace = client->workspace; + + if (workspace->fullscreen_client != NULL) { + LOG("Not entering fullscreen mode, there already is a fullscreen client.\n"); + return; + } + + client->fullscreen = true; + workspace->fullscreen_client = client; + LOG("Entering fullscreen mode...\n"); + /* We just entered fullscreen mode, let’s configure the window */ + uint32_t mask = XCB_CONFIG_WINDOW_X | + XCB_CONFIG_WINDOW_Y | + XCB_CONFIG_WINDOW_WIDTH | + XCB_CONFIG_WINDOW_HEIGHT; + uint32_t values[4] = {workspace->rect.x, + workspace->rect.y, + workspace->rect.width, + workspace->rect.height}; + + LOG("child itself will be at %dx%d with size %dx%d\n", + values[0], values[1], values[2], values[3]); + + xcb_configure_window(conn, client->frame, mask, values); + + /* Child’s coordinates are relative to the parent (=frame) */ + values[0] = 0; + values[1] = 0; + xcb_configure_window(conn, client->child, mask, values); + + /* Raise the window */ + values[0] = XCB_STACK_MODE_ABOVE; + xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_STACK_MODE, values); + + Rect child_rect = workspace->rect; + child_rect.x = child_rect.y = 0; + fake_configure_notify(conn, child_rect, client->child); + + xcb_flush(conn); +} + /* * Toggles fullscreen mode for the given client. It updates the data structures and * reconfigures (= resizes/moves) the client and its frame to the full size of the @@ -149,60 +196,28 @@ void client_toggle_fullscreen(xcb_connection_t *conn, Client *client) { Workspace *workspace = client->workspace; if (!client->fullscreen) { - if (workspace->fullscreen_client != NULL) { - LOG("Not entering fullscreen mode, there already is a fullscreen client.\n"); - return; - } - client->fullscreen = true; - workspace->fullscreen_client = client; - LOG("Entering fullscreen mode...\n"); - /* We just entered fullscreen mode, let’s configure the window */ - uint32_t mask = XCB_CONFIG_WINDOW_X | - XCB_CONFIG_WINDOW_Y | - XCB_CONFIG_WINDOW_WIDTH | - XCB_CONFIG_WINDOW_HEIGHT; - uint32_t values[4] = {workspace->rect.x, - workspace->rect.y, - workspace->rect.width, - workspace->rect.height}; + client_enter_fullscreen(conn, client); + return; + } - LOG("child itself will be at %dx%d with size %dx%d\n", - values[0], values[1], values[2], values[3]); - - xcb_configure_window(conn, client->frame, mask, values); - - /* Child’s coordinates are relative to the parent (=frame) */ - values[0] = 0; - values[1] = 0; - xcb_configure_window(conn, client->child, mask, values); - - /* Raise the window */ - values[0] = XCB_STACK_MODE_ABOVE; - xcb_configure_window(conn, client->frame, XCB_CONFIG_WINDOW_STACK_MODE, values); - - Rect child_rect = workspace->rect; - child_rect.x = child_rect.y = 0; - fake_configure_notify(conn, child_rect, client->child); + LOG("leaving fullscreen mode\n"); + client->fullscreen = false; + workspace->fullscreen_client = NULL; + if (client_is_floating(client)) { + /* For floating clients it’s enough if we just reconfigure that window (in fact, + * re-rendering the layout will not update the client.) */ + reposition_client(conn, client); + resize_client(conn, client); + /* redecorate_window flushes */ + redecorate_window(conn, client); } else { - LOG("leaving fullscreen mode\n"); - client->fullscreen = false; - workspace->fullscreen_client = NULL; - if (client_is_floating(client)) { - /* For floating clients it’s enough if we just reconfigure that window (in fact, - * re-rendering the layout will not update the client.) */ - reposition_client(conn, client); - resize_client(conn, client); - /* redecorate_window flushes */ - redecorate_window(conn, client); - } else { - client_set_below_floating(conn, client); + client_set_below_floating(conn, client); - /* Because the coordinates of the window haven’t changed, it would not be - re-configured if we don’t set the following flag */ - client->force_reconfigure = true; - /* We left fullscreen mode, redraw the whole layout to ensure enternotify events are disabled */ - render_layout(conn); - } + /* Because the coordinates of the window haven’t changed, it would not be + re-configured if we don’t set the following flag */ + client->force_reconfigure = true; + /* We left fullscreen mode, redraw the whole layout to ensure enternotify events are disabled */ + render_layout(conn); } xcb_flush(conn); diff --git a/src/commands.c b/src/commands.c index 507fdf6d..e0935525 100644 --- a/src/commands.c +++ b/src/commands.c @@ -25,6 +25,7 @@ #include "xinerama.h" #include "client.h" #include "floating.h" +#include "xcb.h" bool focus_window_in_container(xcb_connection_t *conn, Container *container, direction_t direction) { /* If this container is empty, we’re done */ @@ -559,8 +560,6 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa CIRCLEQ_INSERT_TAIL(&(to_container->clients), current_client, clients); SLIST_INSERT_HEAD(&(to_container->workspace->focus_stack), current_client, focus_clients); - if (current_client->fullscreen) - t_ws->fullscreen_client = current_client; LOG("Moved.\n"); current_client->container = to_container; @@ -568,16 +567,26 @@ static void move_current_window_to_workspace(xcb_connection_t *conn, int workspa container->currently_focused = to_focus; to_container->currently_focused = current_client; + bool target_invisible = (to_container->workspace->screen->current_workspace != to_container->workspace->num); + /* If we’re moving it to an invisible screen, we need to unmap it */ - if (to_container->workspace->screen->current_workspace != to_container->workspace->num) { + if (target_invisible) { LOG("This workspace is not visible, unmapping\n"); xcb_unmap_window(conn, current_client->frame); + } else { + if (current_client->fullscreen) { + LOG("Calling client_enter_fullscreen again\n"); + client_enter_fullscreen(conn, current_client); + } } /* delete all empty columns/rows */ cleanup_table(conn, container->workspace); render_layout(conn); + + if (!target_invisible) + set_focus(conn, current_client, true); } /*