Merge pull request #3814 from orestisfl/net_active_fullscreen
handlers.c: new focus should not end up behind fullscreen
This commit is contained in:
commit
736ac40b10
|
@ -45,6 +45,13 @@ void con_focus(Con *con);
|
||||||
*/
|
*/
|
||||||
void con_activate(Con *con);
|
void con_activate(Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activates the container like in con_activate but removes fullscreen
|
||||||
|
* restrictions and properly warps the pointer if needed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void con_activate_unblock(Con *con);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the given container.
|
* Closes the given container.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1238,20 +1238,6 @@ void cmd_focus_direction(I3_CMD, const char *direction) {
|
||||||
ysuccess(true);
|
ysuccess(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Focus a container and disable any other fullscreen container not permitting the focus.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
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 = 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);
|
|
||||||
}
|
|
||||||
con_activate(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implementation of 'focus tiling|floating|mode_toggle'.
|
* Implementation of 'focus tiling|floating|mode_toggle'.
|
||||||
*
|
*
|
||||||
|
@ -1276,7 +1262,7 @@ void cmd_focus_window_mode(I3_CMD, const char *window_mode) {
|
||||||
(!to_floating && current->type == CT_FLOATING_CON))
|
(!to_floating && current->type == CT_FLOATING_CON))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
cmd_focus_force_focus(con_descend_focused(current));
|
con_activate_unblock(con_descend_focused(current));
|
||||||
success = true;
|
success = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1353,26 +1339,8 @@ void cmd_focus(I3_CMD) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the container is not on the current workspace,
|
|
||||||
* workspace_show() will switch to a different workspace and (if
|
|
||||||
* enabled) trigger a mouse pointer warp to the currently focused
|
|
||||||
* container (!) on the target workspace.
|
|
||||||
*
|
|
||||||
* Therefore, before calling workspace_show(), we make sure that
|
|
||||||
* 'current' will be focused on the workspace. However, we cannot
|
|
||||||
* just con_focus(current) because then the pointer will not be
|
|
||||||
* warped at all (the code thinks we are already there).
|
|
||||||
*
|
|
||||||
* So we focus 'current' to make it the currently focused window of
|
|
||||||
* the target workspace, then revert focus. */
|
|
||||||
Con *currently_focused = focused;
|
|
||||||
cmd_focus_force_focus(current->con);
|
|
||||||
con_activate(currently_focused);
|
|
||||||
|
|
||||||
/* Now switch to the workspace, then focus */
|
|
||||||
workspace_show(ws);
|
|
||||||
LOG("focusing %p / %s\n", current->con, current->con->name);
|
LOG("focusing %p / %s\n", current->con, current->con->name);
|
||||||
con_activate(current->con);
|
con_activate_unblock(current->con);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
src/con.c
35
src/con.c
|
@ -265,6 +265,41 @@ void con_activate(Con *con) {
|
||||||
con_raise(con);
|
con_raise(con);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Activates the container like in con_activate but removes fullscreen
|
||||||
|
* restrictions and properly warps the pointer if needed.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void con_activate_unblock(Con *con) {
|
||||||
|
Con *ws = con_get_workspace(con);
|
||||||
|
Con *previous_focus = focused;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
con_activate(con);
|
||||||
|
|
||||||
|
/* If the container is not on the current workspace, workspace_show() will
|
||||||
|
* switch to a different workspace and (if enabled) trigger a mouse pointer
|
||||||
|
* warp to the currently focused container (!) on the target workspace.
|
||||||
|
*
|
||||||
|
* Therefore, before calling workspace_show(), we make sure that 'con' will
|
||||||
|
* be focused on the workspace. However, we cannot just con_focus(con)
|
||||||
|
* because then the pointer will not be warped at all (the code thinks we
|
||||||
|
* are already there).
|
||||||
|
*
|
||||||
|
* So we focus 'con' to make it the currently focused window of the target
|
||||||
|
* workspace, then revert focus. */
|
||||||
|
if (ws != con_get_workspace(previous_focus)) {
|
||||||
|
con_activate(previous_focus);
|
||||||
|
/* Now switch to the workspace, then focus */
|
||||||
|
workspace_show(ws);
|
||||||
|
con_activate(con);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Closes the given container.
|
* Closes the given container.
|
||||||
*
|
*
|
||||||
|
|
|
@ -412,7 +412,7 @@ static void handle_configure_request(xcb_configure_request_event_t *event) {
|
||||||
if (config.focus_on_window_activation == FOWA_FOCUS || (config.focus_on_window_activation == FOWA_SMART && workspace_is_visible(workspace))) {
|
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);
|
DLOG("Focusing con = %p\n", con);
|
||||||
workspace_show(workspace);
|
workspace_show(workspace);
|
||||||
con_activate(con);
|
con_activate_unblock(con);
|
||||||
tree_render();
|
tree_render();
|
||||||
} else if (config.focus_on_window_activation == FOWA_URGENT || (config.focus_on_window_activation == FOWA_SMART && !workspace_is_visible(workspace))) {
|
} 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);
|
DLOG("Marking con = %p urgent\n", con);
|
||||||
|
@ -758,7 +758,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
|
||||||
workspace_show(ws);
|
workspace_show(ws);
|
||||||
/* Re-set focus, even if unchanged from i3’s perspective. */
|
/* Re-set focus, even if unchanged from i3’s perspective. */
|
||||||
focused_id = XCB_NONE;
|
focused_id = XCB_NONE;
|
||||||
con_activate(con);
|
con_activate_unblock(con);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Request is from an application. */
|
/* Request is from an application. */
|
||||||
|
@ -769,8 +769,7 @@ static void handle_client_message(xcb_client_message_event_t *event) {
|
||||||
|
|
||||||
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(ws))) {
|
||||||
DLOG("Focusing con = %p\n", con);
|
DLOG("Focusing con = %p\n", con);
|
||||||
workspace_show(ws);
|
con_activate_unblock(con);
|
||||||
con_activate(con);
|
|
||||||
} 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(ws))) {
|
||||||
DLOG("Marking con = %p urgent\n", con);
|
DLOG("Marking con = %p urgent\n", con);
|
||||||
con_set_urgency(con, true);
|
con_set_urgency(con, true);
|
||||||
|
@ -1115,14 +1114,8 @@ static void handle_focus_in(xcb_focus_in_event_t *event) {
|
||||||
|
|
||||||
DLOG("focus is different / refocusing floating window: updating decorations\n");
|
DLOG("focus is different / refocusing floating window: updating decorations\n");
|
||||||
|
|
||||||
/* Get the currently focused workspace to check if the focus change also
|
con_activate_unblock(con);
|
||||||
* involves changing workspaces. If so, we need to call workspace_show() to
|
|
||||||
* correctly update state and send the IPC event. */
|
|
||||||
Con *ws = con_get_workspace(con);
|
|
||||||
if (ws != con_get_workspace(focused))
|
|
||||||
workspace_show(ws);
|
|
||||||
|
|
||||||
con_activate(con);
|
|
||||||
/* We update focused_id because we don’t need to set focus again */
|
/* We update focused_id because we don’t need to set focus again */
|
||||||
focused_id = event->event;
|
focused_id = event->event;
|
||||||
tree_render();
|
tree_render();
|
||||||
|
|
|
@ -149,6 +149,22 @@ send_net_active_window($scratch->id, 'pager');
|
||||||
|
|
||||||
is($x->input_focus, $scratch->id, 'scratchpad window is shown');
|
is($x->input_focus, $scratch->id, 'scratchpad window is shown');
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Send a _NET_ACTIVE_WINDOW ClientMessage for a window behind a fullscreen
|
||||||
|
# window
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
$ws1 = fresh_workspace;
|
||||||
|
$win1 = open_window;
|
||||||
|
$win2 = open_window;
|
||||||
|
cmd 'fullscreen enable';
|
||||||
|
is_num_fullscreen($ws1, 1, '1 fullscreen window in workspace');
|
||||||
|
|
||||||
|
send_net_active_window($win1->id);
|
||||||
|
|
||||||
|
is($x->input_focus, $win1->id, 'window behind fullscreen window is now focused');
|
||||||
|
is_num_fullscreen($ws1, 0, 'no fullscreen windows in workspace');
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Verify that the _NET_ACTIVE_WINDOW property is updated on the root window
|
# Verify that the _NET_ACTIVE_WINDOW property is updated on the root window
|
||||||
# correctly.
|
# correctly.
|
||||||
|
|
Loading…
Reference in New Issue