]> git.mdlowis.com Git - proto/labwc.git/commitdiff
desktop: switch workspaces and optionally raise in desktop_focus_view()
authorJohn Lindgren <john@jlindgren.net>
Wed, 27 Sep 2023 22:37:28 +0000 (18:37 -0400)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Thu, 28 Sep 2023 01:38:51 +0000 (03:38 +0200)
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.

include/labwc.h
include/workspaces.h
src/action.c
src/cursor.c
src/desktop.c
src/foreign.c
src/keyboard.c
src/view-impl-common.c
src/workspaces.c
src/xdg.c
src/xwayland.c

index 91c9cfdc972647e52cc9d874581f3c83299dbf09..d7f5cbdecc04277e2582bc5a6c0a8cc7eabf7ece 100644 (file)
@@ -377,7 +377,7 @@ void foreign_toplevel_update_outputs(struct view *view);
  *              cannot assume this means that the window actually has keyboard
  *              or pointer focus, in this compositor are they called together.
  */
-void desktop_focus_view(struct view *view);
+void desktop_focus_view(struct view *view, bool raise);
 void desktop_arrange_all_views(struct server *server);
 void desktop_focus_output(struct output *output);
 struct view *desktop_topmost_mapped_view(struct server *server);
index e533f7f90e0441e11be78849fd6c57ce12f4fcfa..997865f272f1708841df6d173c26297f3a99bf60 100644 (file)
@@ -2,10 +2,12 @@
 #ifndef LABWC_WORKSPACES_H
 #define LABWC_WORKSPACES_H
 
+#include <stdbool.h>
+#include <wayland-util.h>
+
 struct seat;
-struct view;
 struct server;
-struct wl_list;
+struct wlr_scene_tree;
 
 /* Double use: as config in config/rcxml.c and as instance in workspaces.c */
 struct workspace {
@@ -20,7 +22,7 @@ struct workspace {
 };
 
 void workspaces_init(struct server *server);
-void workspaces_switch_to(struct workspace *target);
+void workspaces_switch_to(struct workspace *target, bool update_focus);
 void workspaces_destroy(struct server *server);
 void workspaces_osd_hide(struct seat *seat);
 struct workspace *workspaces_find(struct workspace *anchor, const char *name,
index 8433268d91c1bf6c1a7f68da797c6420f008b45d..cf8b4558121825de84780791176563ddd8c7b025 100644 (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;
index 4a5b30cd586b4651cbdc3f136c306f301cff2161..16d9e8247e50130cb661ffe01cada9a4353e268d 100644 (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),
index 581772246546772c0090277e41c647932a8498fc..cbaa0de6b3517a0876a3cd98292f27f4058f3197 100644 (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);
index fd5237d7f156ef5891e9b64405c1d46cfb0165be..e71292d79993e1d38c761565d711797261cc8221 100644 (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
index 73b8c9febb47fa3b8df2842a86cab9cb1c0ca469..b3d44766755a19bf099983e268014203f6f31937 100644 (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 */
index 1c7a1e712f956fc21b9e4e655b72ce83a87b1059..ea0fe1a7a0882f313c284418b5b49bcab28bc53f 100644 (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) {
index e3943ac43d16d6333e2ea909b1c02428d5f0557d..48be68f363da1ca3b8f6e46c5c1b20ba51f687a0 100644 (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 */
index 2f429aff69703f4ae3a61d58a24afded204d0b7d..65f164d313d5aba51dbdefa7601bea019b41cbbb 100644 (file)
--- a/src/xdg.c
+++ b/src/xdg.c
@@ -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);
 }
 
 /*
index 3a0a8a9a21d5af04eb3257f66185f0ec58a124cd..4423345bdc4329801777f529f984072aee802879 100644 (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