]> git.mdlowis.com Git - proto/labwc.git/commitdiff
desktop: refactor desktop_cycle_view()
authorJohan Malm <jgm323@gmail.com>
Thu, 25 Jan 2024 19:52:54 +0000 (19:52 +0000)
committerConsolatis <35009135+Consolatis@users.noreply.github.com>
Tue, 5 Mar 2024 21:16:55 +0000 (22:16 +0100)
...in preparation for using common window-rule criteria with osd.c

No functional change intended.

Related-to #1454

include/view.h
src/desktop.c
src/view.c

index 4a7cc207e6ce44a885ba067fed7e1814f0d8f196..f68c89d83a11872541d30db10bfd8de2a12c3c12 100644 (file)
@@ -321,6 +321,15 @@ bool view_matches_query(struct view *view, struct view_query *query);
 struct view *view_next(struct wl_list *head, struct view *view,
        enum lab_view_criteria criteria);
 
+/*
+ * Same as `view_next()` except that they iterate one whole cycle rather than
+ * stopping at the list-head
+ */
+struct view *view_next_no_head_stop(struct wl_list *head, struct view *from,
+       enum lab_view_criteria criteria);
+struct view *view_prev_no_head_stop(struct wl_list *head, struct view *from,
+       enum lab_view_criteria criteria);
+
 /**
  * view_array_append() - Append views that match criteria to array
  * @server: server context
index 523f919c97bf9f76198920c68e7ae06aad2b5933..0864b9b8e491b2235a4fd189b305ae7b1cbcb3b0 100644 (file)
@@ -106,109 +106,45 @@ desktop_focus_view_or_surface(struct seat *seat, struct view *view,
        }
 }
 
-static struct wl_list *
-get_prev_item(struct wl_list *item)
-{
-       return item->prev;
-}
-
-static struct wl_list *
-get_next_item(struct wl_list *item)
-{
-       return item->next;
-}
-
-static struct view *
-first_view(struct server *server)
-{
-       struct wlr_scene_node *node;
-       struct wl_list *list_head =
-               &server->workspace_current->tree->children;
-       wl_list_for_each_reverse(node, list_head, link) {
-               if (!node->data) {
-                       /* We found some non-view, most likely the region overlay */
-                       continue;
-               }
-               struct view *view = node_view_from_node(node);
-               if (view_is_focusable(view)) {
-                       return view;
-               }
-       }
-       return NULL;
-}
-
 struct view *
 desktop_cycle_view(struct server *server, struct view *start_view,
                enum lab_cycle_dir dir)
 {
+       /* Make sure to have all nodes in their actual ordering */
+       osd_preview_restore(server);
+
+       struct view *(*iter)(struct wl_list *head, struct view *view,
+               enum lab_view_criteria criteria);
+       bool forwards = dir == LAB_CYCLE_DIR_FORWARD;
+       iter = forwards ? view_next_no_head_stop : view_prev_no_head_stop;
+
        /*
-        * Views are listed in stacking order, topmost first.  Usually
-        * the topmost view is already focused, so we pre-select the
-        * view second from the top:
+        * TODO: These criteria are the same as in display_osd() in osd.c
+        * for the time being.
+        *
+        * A future improvement could be to make this configurable for example
+        * in rc.xml and then use rc.cycle_view_criteria (or whatever) both
+        * here and in the osd.c window-switcher code
+        */
+       enum lab_view_criteria criteria = LAB_VIEW_CRITERIA_CURRENT_WORKSPACE
+               | LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP
+               | LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER;
+
+       /*
+        * Views are listed in stacking order, topmost first.  Usually the
+        * topmost view is already focused, so when iterating in the forward
+        * direction we pre-select the view second from the top:
         *
         *   View #1 (on top, currently focused)
         *   View #2 (pre-selected)
         *   View #3
         *   ...
-        *
-        * This assumption doesn't always hold with XWayland views,
-        * where a main application window may be focused but an
-        * focusable sub-view (e.g. an about dialog) may still be on
-        * top of it.  In that case, we pre-select the sub-view:
-        *
-        *   Sub-view of #1 (on top, pre-selected)
-        *   Main view #1 (currently focused)
-        *   Main view #2
-        *   ...
-        *
-        * The general rule is:
-        *
-        *   - Pre-select the top view if NOT already focused
-        *   - Otherwise select the view second from the top
         */
-
-       /* Make sure to have all nodes in their actual ordering */
-       osd_preview_restore(server);
-
-       if (!start_view) {
-               start_view = first_view(server);
-               if (!start_view || start_view != server->active_view) {
-                       return start_view;  /* may be NULL */
-               }
+       if (!start_view && forwards) {
+               start_view = iter(&server->views, NULL, criteria);
        }
-       struct view *view = start_view;
-       struct wlr_scene_node *node = &view->scene_tree->node;
-
-       assert(node->parent);
-       struct wl_list *list_head = &node->parent->children;
-       struct wl_list *list_item = &node->link;
-       struct wl_list *(*iter)(struct wl_list *list);
-
-       /* Scene nodes are ordered like last node == displayed topmost */
-       iter = dir == LAB_CYCLE_DIR_FORWARD ? get_prev_item : get_next_item;
-
-       do {
-               list_item = iter(list_item);
-               if (list_item == list_head) {
-                       /* Start / End of list reached. Roll over */
-                       list_item = iter(list_item);
-               }
-               node = wl_container_of(list_item, node, link);
-               if (!node->data) {
-                       /* We found some non-view, most likely the region overlay */
-                       view = NULL;
-                       continue;
-               }
-               view = node_view_from_node(node);
-
-               enum property skip = window_rules_get_property(view, "skipWindowSwitcher");
-               if (view_is_focusable(view) && skip != LAB_PROP_TRUE) {
-                       return view;
-               }
-       } while (view != start_view);
 
-       /* No focusable views found, including the one we started with */
-       return NULL;
+       return iter(&server->views, start_view, criteria);
 }
 
 struct view *
index e8616614c2f5464d76d102dc9f2a09b1cac5dfad..3443c5be95e8a5c3c3286b742fc00f48f4cabf55 100644 (file)
@@ -137,6 +137,48 @@ view_next(struct wl_list *head, struct view *view, enum lab_view_criteria criter
        return NULL;
 }
 
+struct view *
+view_next_no_head_stop(struct wl_list *head, struct view *from,
+               enum lab_view_criteria criteria)
+{
+       assert(head);
+
+       struct wl_list *elm = from ? &from->link : head;
+
+       struct wl_list *end = elm;
+       for (elm = elm->next; elm != end; elm = elm->next) {
+               if (elm == head) {
+                       continue;
+               }
+               struct view *view = wl_container_of(elm, view, link);
+               if (matches_criteria(view, criteria)) {
+                       return view;
+               }
+       }
+       return from;
+}
+
+struct view *
+view_prev_no_head_stop(struct wl_list *head, struct view *from,
+               enum lab_view_criteria criteria)
+{
+       assert(head);
+
+       struct wl_list *elm = from ? &from->link : head;
+
+       struct wl_list *end = elm;
+       for (elm = elm->prev; elm != end; elm = elm->prev) {
+               if (elm == head) {
+                       continue;
+               }
+               struct view *view = wl_container_of(elm, view, link);
+               if (matches_criteria(view, criteria)) {
+                       return view;
+               }
+       }
+       return from;
+}
+
 void
 view_array_append(struct server *server, struct wl_array *views,
                enum lab_view_criteria criteria)