]> git.mdlowis.com Git - proto/labwc.git/commitdiff
view: add for_each_view()
authorJohan Malm <jgm323@gmail.com>
Fri, 18 Aug 2023 21:18:59 +0000 (22:18 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sun, 20 Aug 2023 08:56:49 +0000 (09:56 +0100)
Helped-by: @Consolatis and @heroin-moose (by a significant amount)
include/view.h
scripts/checkpatch.pl
src/view.c

index 80819135696fdd9e338cea56fec7dcd2b9832fb4..9e5ddd62eec5f07cc006d0e6a39247e076ea8a21 100644 (file)
@@ -169,23 +169,54 @@ struct xdg_toplevel_view {
 };
 
 enum lab_view_criteria {
-       LAB_VIEW_CRITERIA_ALL = 0,
+       LAB_VIEW_CRITERIA_NONE = 0,
        LAB_VIEW_CRITERIA_CURRENT_WORKSPACE = 1 << 0,
        LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP = 1 << 1,
        LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER = 1 << 2,
 };
 
 /**
- * view_array_append - append views that match criteria to array
+ * for_each_view() - iterate over all views which match criteria
+ * @view: Iterator.
+ * @head: Head of list to iterate over.
+ * @criteria: Criteria to match against.
+ * Example:
+ *     struct view *view;
+ *     for_each_view(view, &server->views, LAB_VIEW_CRITERIA_NONE) {
+ *             printf("%s\n", view_get_string_prop(view, "app_id"));
+ *     }
+ */
+#define for_each_view(view, head, criteria)            \
+       for (view = view_next(head, NULL, criteria);    \
+            view;                                      \
+            view = view_next(head, view, criteria))
+
+/**
+ * view_next() - Get next view which matches criteria.
+ * @head: Head of list to iterate over.
+ * @view: Current view from which to find the next one. If NULL is provided as
+ *       the view argument, the start of the list will be used.
+ * @criteria: Criteria to match against.
+ *
+ * Returns NULL if there are no views matching the criteria.
+ */
+struct view *view_next(struct wl_list *head, struct view *view,
+       enum lab_view_criteria criteria);
+
+/**
+ * view_array_append() - Append views that match criteria to array
  * @server: server context
  * @views: arrays to append to
  * @criteria: criteria to match against
  *
+ * This function is useful in cases where the calling function may change the
+ * stacking order or where it needs to iterate over the views multiple times,
+ * for example to get the number of views before processing them.
+ *
  * Note: This array has a very short shelf-life so it is intended to be used
  *       with a single-use-throw-away approach.
  *
  * Example usage:
- *
  *     struct view **view;
  *     struct wl_array views;
  *     wl_array_init(&views);
index 30b3134372649afeb752092ed6b7a423a2025fca..98cba37f133c58e757a550e1125f489d183abe39 100755 (executable)
@@ -5526,10 +5526,11 @@ sub process {
                        # because (as opposed to Linux coding style) we use
                        # braces for single statement blocks.
                        #
-                       # include/ssd-internal.h contains a macro that we can't
-                       # deal with, so ignore that
+                       # We ignore a couple of header-files which contain
+                       # macros that we cannot deal with.
                        #
                        if ($starts_with_if_while_etc && !length($s)
+                                       && $filename ne "include/view.h"
                                        && $filename ne "include/ssd-internal.h") {
                                CHK("BRACES", "[labwc-custom] open brace { expected after if/while/for/switch - even with single statement blocks");
                        }
index b6997eb6361b5b9891977c4992a18d0d8026f8f5..aa6967559b551acdbf41b2e84cd823bf2c82fa7c 100644 (file)
 #define LAB_FALLBACK_WIDTH  640
 #define LAB_FALLBACK_HEIGHT 480
 
-void
-view_array_append(struct server *server, struct wl_array *views,
-               enum lab_view_criteria criteria)
+static bool
+matches_criteria(struct view *view, enum lab_view_criteria criteria)
 {
-       struct view *view;
-       wl_list_for_each(view, &server->views, link)
-       {
-               if (!isfocusable(view)) {
-                       continue;
+       if (!isfocusable(view)) {
+               return false;
+       }
+       if (criteria & LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
+               /*
+                * Always-on-top views are always on the current desktop and are
+                * special in that they live in a different tree.
+                */
+               struct server *server = view->server;
+               if (view->scene_tree->node.parent != server->workspace_current->tree
+                               && !view_is_always_on_top(view)) {
+                       return false;
                }
-
-               if (criteria & LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) {
-                       /*
-                        * Always-on-top views are always on the current
-                        * desktop and are special in that they live in a
-                        * different tree.
-                        */
-                       if (view_is_always_on_top(view)) {
-                               goto next;
-                       }
-                       if (view->scene_tree->node.parent != server->workspace_current->tree) {
-                               continue;
-                       }
+       }
+       if (criteria & LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP) {
+               if (view_is_always_on_top(view)) {
+                       return false;
                }
-next:
-               if (criteria & LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP) {
-                       if (view_is_always_on_top(view)) {
-                               continue;
-                       }
+       }
+       if (criteria & LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER) {
+               if (window_rules_get_property(view, "skipWindowSwitcher") == LAB_PROP_TRUE) {
+                       return false;
                }
-               if (criteria & LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER) {
-                       if (window_rules_get_property(view, "skipWindowSwitcher")
-                                       == LAB_PROP_TRUE) {
-                               continue;
-                       }
+       }
+       return true;
+}
+
+struct view *
+view_next(struct wl_list *head, struct view *view, enum lab_view_criteria criteria)
+{
+       assert(head);
+
+       struct wl_list *elm = view ? &view->link : head;
+
+       for (elm = elm->next; elm != head; elm = elm->next) {
+               view = wl_container_of(elm, view, link);
+               if (matches_criteria(view, criteria)) {
+                       return view;
                }
+       }
+       return NULL;
+}
 
+void
+view_array_append(struct server *server, struct wl_array *views,
+               enum lab_view_criteria criteria)
+{
+       struct view *view;
+       for_each_view(view, &server->views, criteria) {
                struct view **entry = wl_array_add(views, sizeof(*entry));
+               if (!entry) {
+                       wlr_log(WLR_ERROR, "wl_array_add(): out of memory");
+                       continue;
+               }
                *entry = view;
        }
 }