Add `popup_during_fullscreen all` option

This commit is contained in:
Orestis Floros 2024-05-20 21:10:21 +02:00
parent 3b1747a107
commit 1993b7e318
No known key found for this signature in database
GPG Key ID: A09DBD7D3222C1C3
9 changed files with 82 additions and 39 deletions

View File

@ -1229,19 +1229,21 @@ mouse_warping none
When you are in fullscreen mode, some applications still open popup windows
(take Xpdf for example). This is because these applications might not be aware
that they are in fullscreen mode (they do not check the corresponding hint).
There are three things which are possible to do in this situation:
i3 supports four options for this situation:
1. Display the popup if it belongs to the fullscreen application only. This is
the default and should be reasonable behavior for most users.
2. Just ignore the popup (dont map it). This wont interrupt you while you are
in fullscreen. However, some apps might react badly to this (deadlock until
you go out of fullscreen).
3. Leave fullscreen mode.
1. +smart+: Display the popup if it belongs to the fullscreen application only.
This is the default and should be reasonable behavior for most users.
2. +ignore+: Just ignore the popup (dont map it). This wont interrupt you
while you are in fullscreen. However, some apps might react badly to this
(deadlock until you go out of fullscreen).
3. +leave_fullscreen+: Leave fullscreen mode.
4. +all+: Since i3 4.24: Display all floating windows regardless to which
application they belong to.
*Syntax*:
-----------------------------------------------------
popup_during_fullscreen smart|ignore|leave_fullscreen
-----------------------------------------------------
---------------------------------------------------------
popup_during_fullscreen smart|ignore|leave_fullscreen|all
---------------------------------------------------------
*Example*:
------------------------------

View File

@ -262,6 +262,9 @@ struct Config {
/* just ignore the popup, that is, dont map it */
PDF_IGNORE = 2,
/* display all floating windows */
PDF_ALL = 3,
} popup_during_fullscreen;
/* The number of currently parsed barconfigs */

View File

@ -366,7 +366,7 @@ state RESTART_STATE:
# popup_during_fullscreen
state POPUP_DURING_FULLSCREEN:
value = 'ignore', 'leave_fullscreen', 'smart'
value = 'ignore', 'leave_fullscreen', 'all', 'smart'
-> call cfg_popup_during_fullscreen($value)
state TILING_DRAG_MODE:

View File

@ -0,0 +1 @@
Add popup_during_fullscreen all option

View File

@ -579,6 +579,8 @@ CFGFUN(popup_during_fullscreen, const char *value) {
config.popup_during_fullscreen = PDF_IGNORE;
} else if (strcmp(value, "leave_fullscreen") == 0) {
config.popup_during_fullscreen = PDF_LEAVE_FULLSCREEN;
} else if (strcmp(value, "all") == 0) {
config.popup_during_fullscreen = PDF_ALL;
} else {
config.popup_during_fullscreen = PDF_SMART;
}

View File

@ -502,7 +502,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
if (config.popup_during_fullscreen == PDF_LEAVE_FULLSCREEN &&
fs != NULL) {
DLOG("There is a fullscreen window, leaving fullscreen mode\n");
con_toggle_fullscreen(fs, CF_OUTPUT);
con_disable_fullscreen(fs);
} else if (config.popup_during_fullscreen == PDF_SMART &&
fs != NULL &&
fs->window != NULL) {
@ -524,6 +524,10 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
nc->geometry = (Rect){geom->x, geom->y, geom->width, geom->height};
}
if (config.popup_during_fullscreen == PDF_ALL && want_floating && fs != NULL) {
set_focus = true;
}
if (want_floating) {
DLOG("geometry = %d x %d\n", nc->geometry.width, nc->geometry.height);
if (floating_enable(nc, true)) {
@ -646,15 +650,13 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
xcb_discard_reply(conn, wm_user_time_cookie.sequence);
}
if (set_focus) {
/* Even if the client doesn't want focus, we still need to focus the
* container to not break focus workflows. Our handling towards X will
* take care of not setting the input focus. However, one exception to
* this are clients using the globally active input model which we
* don't want to focus at all. */
if (nc->window->doesnt_accept_focus && !nc->window->needs_take_focus) {
set_focus = false;
}
/* Even if the client doesn't want focus, we still need to focus the
* container to not break focus workflows. Our handling towards X will take
* care of not setting the input focus. However, one exception to this are
* clients using the globally active input model which we don't want to
* focus at all. */
if (nc->window->doesnt_accept_focus && !nc->window->needs_take_focus) {
set_focus = false;
}
/* Defer setting focus after the 'new' event has been sent to ensure the

View File

@ -250,6 +250,26 @@ static int *precalculate_sizes(Con *con, render_params *p) {
return sizes;
}
static bool fullscreen_blocks_floating_render(Con *fullscreen, Con *floating) {
if (fullscreen == NULL) {
return false;
}
/* Dont 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: popup_during_fullscreen smart|all. */
switch (config.popup_during_fullscreen) {
case PDF_LEAVE_FULLSCREEN:
case PDF_IGNORE:
return true;
case PDF_SMART:
return fullscreen->window == NULL ||
!con_find_transient_for_window(con_descend_focused(floating), fullscreen->window->id);
case PDF_ALL:
return con_has_parent(fullscreen, floating);
}
return false; /* not reachable */
}
static void render_root(Con *con, Con *fullscreen) {
Con *output;
if (!fullscreen) {
@ -277,24 +297,8 @@ static void render_root(Con *con, Con *fullscreen) {
Con *fullscreen = con_get_fullscreen_covering_ws(workspace);
Con *child;
TAILQ_FOREACH (child, &(workspace->floating_head), floating_windows) {
if (fullscreen != NULL) {
/* Dont 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 || fullscreen->window == NULL) {
continue;
}
Con *floating_child = con_descend_focused(child);
if (con_find_transient_for_window(floating_child, fullscreen->window->id)) {
DLOG("Rendering floating child even though in fullscreen mode: "
"floating->transient_for (0x%08x) --> fullscreen->id (0x%08x)\n",
floating_child->window->transient_for, fullscreen->window->id);
} else {
continue;
}
if (fullscreen_blocks_floating_render(fullscreen, child)) {
continue;
}
DLOG("floating child at (%d,%d) with %d x %d\n",
child->rect.x, child->rect.y, child->rect.width, child->rect.height);

View File

@ -202,12 +202,14 @@ $config = <<'EOT';
popup_during_fullscreen ignore
popup_during_fullscreen leave_fullscreen
popup_during_fullscreen SMArt
popup_during_fullscreen aLL
EOT
$expected = <<'EOT';
cfg_popup_during_fullscreen(ignore)
cfg_popup_during_fullscreen(leave_fullscreen)
cfg_popup_during_fullscreen(smart)
cfg_popup_during_fullscreen(all)
EOT
is(parser_calls($config),

View File

@ -122,6 +122,33 @@ is_num_fullscreen($ws, 1, 'still one fullscreen window');
is($x->input_focus, $w2->id, 'popup still focused');
exit_gracefully($pid);
################################################################################
# Test popup_during_fullscreen all
# See #6062
################################################################################
$config = <<EOT;
# i3 config file (v4)
font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
popup_during_fullscreen all
EOT
$pid = launch_with_config($config);
($ws, $w1) = setup;
# Fullscreen stays when transient windows open
$w2 = open_transient_for($w1);
is_num_fullscreen($ws, 1, 'still one fullscreen window');
is($x->input_focus, $w2->id, 'popup focused');
# Fullscreen stays when regular windows open
$w1->fullscreen(1);
open_without_map_wait;
is_num_fullscreen($ws, 1, 'still one fullscreen window');
exit_gracefully($pid);
done_testing;