From b3e69ed12a5c62b74501b9f375ddf742fb9fb44c Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Wed, 22 Aug 2018 03:40:51 +0300 Subject: [PATCH 1/6] render_root: fix popup_during_fullscreen logic The first issue is that there seems to be a typo: fullscreen->window should have been child->window. The corrected check is redundant since the while loop checks if the transient_con has a window. The second issue is that popup_during_fullscreen is never checked even though the behaviour should be exclusive to the "smart" option. --- src/render.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/render.c b/src/render.c index 0125b89d..f54094bb 100644 --- a/src/render.c +++ b/src/render.c @@ -235,22 +235,19 @@ static void render_root(Con *con, Con *fullscreen) { Con *fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT); Con *child; TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) { - /* Don’t render floating windows when there is a fullscreen window - * on that workspace. Necessary to make floating fullscreen work - * correctly (ticket #564). */ - /* If there is no fullscreen->window, this cannot be a - * transient window, so we _know_ we need to skip it. This - * happens during restarts where the container already exists, - * but the window was not yet associated. */ - if (fullscreen != NULL && fullscreen->window == NULL) - continue; - if (fullscreen != NULL && fullscreen->window != NULL) { + if (fullscreen != NULL) { + /* Don’t render floating windows when there is a fullscreen + * window on that workspace. Necessary to make floating + * fullscreen work correctly (ticket #564). Exception to the + * above rule: smart popup_during_fullscreen handling (popups + * belonging to the fullscreen app will be rendered). */ + if (config.popup_during_fullscreen != PDF_SMART) { + continue; + } + Con *floating_child = con_descend_focused(child); Con *transient_con = floating_child; bool is_transient_for = false; - /* Exception to the above rule: smart - * popup_during_fullscreen handling (popups belonging to - * the fullscreen app will be rendered). */ while (transient_con != NULL && transient_con->window != NULL && transient_con->window->transient_for != XCB_NONE) { From efc78de4eee704672c09b5652afce4739e1e54f1 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Wed, 22 Aug 2018 14:02:27 +0300 Subject: [PATCH 2/6] Introduce con_get_fullscreen_covering_ws This commit will also fix the following bugs: 1. click.c: Users could drag global fullscreen floating containers. 2. render.c: Floating containers would get rendered with a global fullscreen container in another workspace. --- include/con.h | 8 ++++++++ src/click.c | 2 +- src/commands.c | 2 +- src/con.c | 17 +++++++++++++++++ src/handlers.c | 12 ++---------- src/manage.c | 4 +--- src/render.c | 2 +- 7 files changed, 31 insertions(+), 16 deletions(-) diff --git a/include/con.h b/include/con.h index 58123a87..672d80ac 100644 --- a/include/con.h +++ b/include/con.h @@ -120,6 +120,14 @@ Con *con_parent_with_orientation(Con *con, orientation_t orientation); */ Con *con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode); +/** + * Returns the fullscreen node that covers the given workspace if it exists. + * This is either a CF_GLOBAL fullscreen container anywhere or a CF_OUTPUT + * fullscreen container in the workspace. + * + */ +Con *con_get_fullscreen_covering_ws(Con *ws); + /** * Returns true if the container is internal, such as __i3_scratch * diff --git a/src/click.c b/src/click.c index 81e95dfa..1218a4c2 100644 --- a/src/click.c +++ b/src/click.c @@ -254,7 +254,7 @@ static int route_click(Con *con, xcb_button_press_event_t *event, const bool mod /* 3: For floating containers, we also want to raise them on click. * We will skip handling events on floating cons in fullscreen mode */ - Con *fs = (ws ? con_get_fullscreen_con(ws, CF_OUTPUT) : NULL); + Con *fs = con_get_fullscreen_covering_ws(ws); if (floatingcon != NULL && fs != con) { /* 4: floating_modifier plus left mouse button drags */ if (mod_pressed && event->detail == XCB_BUTTON_CLICK_LEFT) { diff --git a/src/commands.c b/src/commands.c index ad7d9770..22ec6c3f 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1282,7 +1282,7 @@ void cmd_focus_direction(I3_CMD, const char *direction) { static void cmd_focus_force_focus(Con *con) { /* Disable fullscreen container in workspace with container to be focused. */ Con *ws = con_get_workspace(con); - Con *fullscreen_on_ws = (focused && focused->fullscreen_mode == CF_GLOBAL) ? focused : con_get_fullscreen_con(ws, CF_OUTPUT); + Con *fullscreen_on_ws = con_get_fullscreen_covering_ws(ws); if (fullscreen_on_ws && fullscreen_on_ws != con && !con_has_parent(con, fullscreen_on_ws)) { con_disable_fullscreen(fullscreen_on_ws); } diff --git a/src/con.c b/src/con.c index f20f7c35..844d9b68 100644 --- a/src/con.c +++ b/src/con.c @@ -509,6 +509,23 @@ Con *con_get_fullscreen_con(Con *con, fullscreen_mode_t fullscreen_mode) { return NULL; } +/* + * Returns the fullscreen node that covers the given workspace if it exists. + * This is either a CF_GLOBAL fullscreen container anywhere or a CF_OUTPUT + * fullscreen container in the workspace. + * + */ +Con *con_get_fullscreen_covering_ws(Con *ws) { + if (!ws) { + return NULL; + } + Con *fs = con_get_fullscreen_con(croot, CF_GLOBAL); + if (!fs) { + return con_get_fullscreen_con(ws, CF_OUTPUT); + } + return fs; +} + /** * Returns true if the container is internal, such as __i3_scratch * diff --git a/src/handlers.c b/src/handlers.c index 2c81939c..fe10d4b9 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -310,16 +310,8 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { DLOG("Configure request!\n"); - Con *workspace = con_get_workspace(con), - *fullscreen = NULL; - - /* There might not be a corresponding workspace for dock cons, therefore we - * have to be careful here. */ - if (workspace) { - fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT); - if (!fullscreen) - fullscreen = con_get_fullscreen_con(workspace, CF_GLOBAL); - } + Con *workspace = con_get_workspace(con); + Con *fullscreen = con_get_fullscreen_covering_ws(workspace); if (fullscreen != con && con_is_floating(con) && con_is_leaf(con)) { /* find the height for the decorations */ diff --git a/src/manage.c b/src/manage.c index b4d0af95..f97ecc62 100644 --- a/src/manage.c +++ b/src/manage.c @@ -378,9 +378,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki /* handle fullscreen containers */ Con *ws = con_get_workspace(nc); - Con *fs = (ws ? con_get_fullscreen_con(ws, CF_OUTPUT) : NULL); - if (fs == NULL) - fs = con_get_fullscreen_con(croot, CF_GLOBAL); + Con *fs = con_get_fullscreen_covering_ws(ws); if (xcb_reply_contains_atom(state_reply, A__NET_WM_STATE_FULLSCREEN)) { /* If this window is already fullscreen (after restarting!), skip diff --git a/src/render.c b/src/render.c index f54094bb..d6306260 100644 --- a/src/render.c +++ b/src/render.c @@ -232,7 +232,7 @@ static void render_root(Con *con, Con *fullscreen) { continue; } Con *workspace = TAILQ_FIRST(&(content->focus_head)); - Con *fullscreen = con_get_fullscreen_con(workspace, CF_OUTPUT); + Con *fullscreen = con_get_fullscreen_covering_ws(workspace); Con *child; TAILQ_FOREACH(child, &(workspace->floating_head), floating_windows) { if (fullscreen != NULL) { From 0ac75bea5a21e9cac6ad2139bc57d44d1a77a6e0 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Wed, 22 Aug 2018 14:09:05 +0300 Subject: [PATCH 3/6] con_border_style: check con->fullscreen_mode directly --- src/con.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/con.c b/src/con.c index 844d9b68..253d1d54 100644 --- a/src/con.c +++ b/src/con.c @@ -1711,8 +1711,7 @@ adjacent_t con_adjacent_borders(Con *con) { * */ int con_border_style(Con *con) { - Con *fs = con_get_fullscreen_con(con->parent, CF_OUTPUT); - if (fs == con) { + if (con->fullscreen_mode == CF_OUTPUT || con->fullscreen_mode == CF_GLOBAL) { DLOG("this one is fullscreen! overriding BS_NONE\n"); return BS_NONE; } From 9ae84593baa6d5b963d127aac52d02445767cd42 Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Wed, 22 Aug 2018 14:10:42 +0300 Subject: [PATCH 4/6] handle_configure_request: reuse 'workspace' variable --- src/handlers.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index fe10d4b9..c203517b 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -406,23 +406,22 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { goto out; } - Con *ws = con_get_workspace(con); - if (ws == NULL) { + if (workspace == NULL) { DLOG("Window is not being managed, ignoring ConfigureRequest\n"); goto out; } - if (strcmp(ws->name, "__i3_scratch") == 0) { + if (strcmp(workspace->name, "__i3_scratch") == 0) { DLOG("This is a scratchpad container, ignoring ConfigureRequest\n"); goto out; } - if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(ws))) { + if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(workspace))) { DLOG("Focusing con = %p\n", con); - workspace_show(ws); + workspace_show(workspace); con_activate(con); tree_render(); - } else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(ws))) { + } else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(workspace))) { DLOG("Marking con = %p urgent\n", con); con_set_urgency(con, true); tree_render(); From 9190a9ab702463c98fe3c35ecab4311b4e6c8d6e Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Wed, 22 Aug 2018 14:11:26 +0300 Subject: [PATCH 5/6] handle_configure_request: use 'goto out' --- src/handlers.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index c203517b..66b3038a 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -327,7 +327,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { if (strcmp(con_get_workspace(floatingcon)->name, "__i3_scratch") == 0) { DLOG("This is a scratchpad container, ignoring ConfigureRequest\n"); - return; + goto out; } Rect newrect = floatingcon->rect; @@ -387,15 +387,14 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { DLOG("Dock client will not be moved, we only support moving it to another output.\n"); } } - fake_absolute_configure_notify(con); - return; + goto out; } if (event->value_mask & XCB_CONFIG_WINDOW_STACK_MODE) { DLOG("window 0x%08x wants to be stacked %d\n", event->window, event->stack_mode); /* Emacs and IntelliJ Idea “request focus” by stacking their window - * above all others. */ + * above all others. */ if (event->stack_mode != XCB_STACK_MODE_ABOVE) { DLOG("stack_mode != XCB_STACK_MODE_ABOVE, ignoring ConfigureRequest\n"); goto out; From e1a83d057f81bf402c73ac051abde27832500bfe Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Wed, 22 Aug 2018 14:23:01 +0300 Subject: [PATCH 6/6] handle_configure_request: check for scratchpad once --- src/handlers.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/handlers.c b/src/handlers.c index 66b3038a..f632d91c 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -311,6 +311,10 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { DLOG("Configure request!\n"); Con *workspace = con_get_workspace(con); + if (workspace && (strcmp(workspace->name, "__i3_scratch") == 0)) { + DLOG("This is a scratchpad container, ignoring ConfigureRequest\n"); + goto out; + } Con *fullscreen = con_get_fullscreen_covering_ws(workspace); if (fullscreen != con && con_is_floating(con) && con_is_leaf(con)) { @@ -324,12 +328,6 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { bsr.height -= deco_height; } Con *floatingcon = con->parent; - - if (strcmp(con_get_workspace(floatingcon)->name, "__i3_scratch") == 0) { - DLOG("This is a scratchpad container, ignoring ConfigureRequest\n"); - goto out; - } - Rect newrect = floatingcon->rect; if (event->value_mask & XCB_CONFIG_WINDOW_X) { @@ -410,11 +408,6 @@ static void handle_configure_request(xcb_configure_request_event_t *event) { goto out; } - if (strcmp(workspace->name, "__i3_scratch") == 0) { - DLOG("This is a scratchpad container, ignoring ConfigureRequest\n"); - goto out; - } - if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(workspace))) { DLOG("Focusing con = %p\n", con); workspace_show(workspace);