desktop: switch workspaces and optionally raise in desktop_focus_view()

Make desktop_focus_view() always switch to the workspace containing the
view being focused. It doesn't make much sense for an invisible view to
have the keyboard focus.

Also add an optional "raise" parameter to desktop_focus_view(). This
allows the common pattern of desktop_focus_view() + view_move_to_front()
to be reduced to a single function call.
This commit is contained in:
John Lindgren 2023-09-27 18:37:28 -04:00 committed by Consolatis
parent e77330bc3f
commit e5aef03319
11 changed files with 44 additions and 43 deletions

View file

@ -634,7 +634,7 @@ actions_run(struct view *activator, struct server *server,
break;
case ACTION_TYPE_FOCUS:
if (view) {
desktop_focus_view(view);
desktop_focus_view(view, /*raise*/ false);
}
break;
case ACTION_TYPE_ICONIFY:
@ -711,7 +711,8 @@ actions_run(struct view *activator, struct server *server,
follow = get_arg_value_bool(action, "follow", true);
}
if (follow) {
workspaces_switch_to(target);
workspaces_switch_to(target,
/*update_focus*/ true);
}
}
break;

View file

@ -478,10 +478,7 @@ process_cursor_motion(struct server *server, uint32_t time)
}
if (ctx.view && rc.focus_follow_mouse) {
desktop_focus_view(ctx.view);
if (rc.raise_on_focus) {
view_move_to_front(ctx.view);
}
desktop_focus_view(ctx.view, rc.raise_on_focus);
}
struct mousebind *mousebind;
@ -522,10 +519,7 @@ _cursor_update_focus(struct server *server)
&& !rc.focus_follow_mouse_requires_movement
&& !server->osd_state.cycle_view) {
/* Prevents changing keyboard focus during A-Tab */
desktop_focus_view(ctx.view);
if (rc.raise_on_focus) {
view_move_to_front(ctx.view);
}
desktop_focus_view(ctx.view, rc.raise_on_focus);
}
cursor_update_common(server, &ctx, msec(&now),

View file

@ -35,7 +35,7 @@ desktop_arrange_all_views(struct server *server)
}
void
desktop_focus_view(struct view *view)
desktop_focus_view(struct view *view, bool raise)
{
assert(view);
/*
@ -56,7 +56,7 @@ desktop_focus_view(struct view *view)
if (view->minimized) {
/*
* Unminimizing will map the view which triggers a call to this
* function again.
* function again (with raise=true).
*/
view_minimize(view, false);
return;
@ -66,7 +66,19 @@ desktop_focus_view(struct view *view)
return;
}
/*
* Switch workspace if necessary to make the view visible
* (unnecessary for "always on top" views).
*/
if (!view_is_always_on_top(view)) {
workspaces_switch_to(view->workspace, /*update_focus*/ false);
}
view_focus(view);
if (raise) {
view_move_to_front(view);
}
}
static struct wl_list *
@ -225,8 +237,7 @@ desktop_focus_topmost_mapped_view(struct server *server)
{
struct view *view = desktop_topmost_mapped_view(server);
if (view) {
desktop_focus_view(view);
view_move_to_front(view);
desktop_focus_view(view, /*raise*/ true);
} else {
/*
* Defocus previous focused surface/view if no longer
@ -262,7 +273,7 @@ desktop_focus_output(struct output *output)
}
if (wlr_output_layout_intersects(layout,
output->wlr_output, &view->current)) {
desktop_focus_view(view);
desktop_focus_view(view, /*raise*/ false);
wlr_cursor_warp(output->server->seat.cursor, NULL,
view->current.x + view->current.width / 2,
view->current.y + view->current.height / 2);

View file

@ -34,11 +34,7 @@ handle_request_activate(struct wl_listener *listener, void *data)
struct view *view = wl_container_of(listener, view, toplevel.activate);
// struct wlr_foreign_toplevel_handle_v1_activated_event *event = data;
/* In a multi-seat world we would select seat based on event->seat here. */
if (view->workspace != view->server->workspace_current) {
workspaces_switch_to(view->workspace);
}
desktop_focus_view(view);
view_move_to_front(view);
desktop_focus_view(view, /*raise*/ true);
}
static void

View file

@ -42,8 +42,8 @@ static void
end_cycling(struct server *server)
{
if (server->osd_state.cycle_view) {
desktop_focus_view(server->osd_state.cycle_view);
view_move_to_front(server->osd_state.cycle_view);
desktop_focus_view(server->osd_state.cycle_view,
/*raise*/ true);
}
/* osd_finish() additionally resets cycle_view to NULL */

View file

@ -51,8 +51,7 @@ view_impl_move_sub_views(struct view *parent, enum z_direction z_direction)
void
view_impl_map(struct view *view)
{
desktop_focus_view(view);
view_move_to_front(view);
desktop_focus_view(view, /*raise*/ true);
view_update_title(view);
view_update_app_id(view);
if (!view->been_mapped) {

View file

@ -255,8 +255,13 @@ workspaces_init(struct server *server)
}
}
/*
* update_focus should normally be set to true. It is set to false only
* when this function is called from desktop_focus_view(), in order to
* avoid unnecessary extra focus changes and possible recursion.
*/
void
workspaces_switch_to(struct workspace *target)
workspaces_switch_to(struct workspace *target, bool update_focus)
{
assert(target);
struct server *server = target->server;
@ -281,9 +286,11 @@ workspaces_switch_to(struct workspace *target)
* Make sure we are focusing what the user sees.
* Only refocus if the focus is not already on an always-on-top view.
*/
struct view *view = desktop_focused_view(server);
if (!view || !view_is_always_on_top(view)) {
desktop_focus_topmost_mapped_view(server);
if (update_focus) {
struct view *view = desktop_focused_view(server);
if (!view || !view_is_always_on_top(view)) {
desktop_focus_topmost_mapped_view(server);
}
}
/* And finally show the OSD */

View file

@ -607,16 +607,8 @@ xdg_activation_handle_request(struct wl_listener *listener, void *data)
return;
}
/*
* TODO: This is the exact same code as used in foreign.c.
* Refactor it into a public helper function somewhere.
*/
wlr_log(WLR_DEBUG, "Activating surface");
if (view->workspace != view->server->workspace_current) {
workspaces_switch_to(view->workspace);
}
desktop_focus_view(view);
view_move_to_front(view);
desktop_focus_view(view, /*raise*/ true);
}
/*

View file

@ -256,8 +256,7 @@ handle_request_activate(struct wl_listener *listener, void *data)
return;
}
desktop_focus_view(view);
view_move_to_front(view);
desktop_focus_view(view, /*raise*/ true);
}
static void