]> git.mdlowis.com Git - proto/labwc.git/commitdiff
view: add view_array_append()
authorJohan Malm <jgm323@gmail.com>
Thu, 10 Aug 2023 14:46:00 +0000 (15:46 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sun, 20 Aug 2023 08:56:49 +0000 (09:56 +0100)
...to reduce code duplication.

The function populates an array with views which meet any set of critera
from:

  - current-workspace
  - no-always-on-top
  - no-skipWindowSwitcher (window-rule)

Make src/osd.c use this new interface. Note that always-on-top views are
still filtered out from the window-switcher and that desktop_cycle_view()
needs to be re-worked before always-on-top views can be opted in.

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

index 064200f860f7c5e3d6ad4fcf745410c5e20cacf9..80819135696fdd9e338cea56fec7dcd2b9832fb4 100644 (file)
@@ -168,6 +168,36 @@ struct xdg_toplevel_view {
        struct wl_listener new_popup;
 };
 
+enum lab_view_criteria {
+       LAB_VIEW_CRITERIA_ALL = 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
+ * @server: server context
+ * @views: arrays to append to
+ * @criteria: criteria to match against
+ *
+ * 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);
+ *     view_array_append(server, &views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE);
+ *     wl_array_for_each(view, &views) {
+ *             // Do something with *view
+ *     }
+ *     wl_array_release(&views);
+ */
+void view_array_append(struct server *server, struct wl_array *views,
+       enum lab_view_criteria criteria);
+
 bool view_inhibits_keybinds(struct view *view);
 void view_toggle_keybinds(struct view *view);
 
index 7c6e944edd1d76ecb758da3c80edf1320b0ced52..00fcda64c0edc67906960aeee9930ada8b107692 100644 (file)
@@ -435,3 +435,4 @@ get_cursor_context(struct server *server)
        wlr_log(WLR_ERROR, "Unknown node detected");
        return ret;
 }
+
index 8a076dade3004928bbc1ebcc5f5740dcf4cfbf63..3b30ed9aa745d546ef4bd05905597699fa429dd5 100644 (file)
--- a/src/osd.c
+++ b/src/osd.c
@@ -258,12 +258,11 @@ get_title(struct view *view)
 static void
 render_osd(struct server *server, cairo_t *cairo, int w, int h,
                struct wl_list *node_list, bool show_workspace,
-               const char *workspace_name)
+               const char *workspace_name, enum lab_view_criteria criteria)
 {
        struct view *cycle_view = server->osd_state.cycle_view;
        struct theme *theme = server->theme;
 
-       struct wlr_scene_node *node;
        cairo_surface_t *surf = cairo_get_target(cairo);
 
        /* Draw background */
@@ -317,17 +316,11 @@ render_osd(struct server *server, cairo_t *cairo, int w, int h,
                - 2 * theme->osd_window_switcher_item_active_border_width;
 
        /* Draw text for each node */
-       wl_list_for_each_reverse(node, node_list, link) {
-               if (!node->data) {
-                       /* We found some non-view, most likely the region overlay */
-                       continue;
-               }
-               struct view *view = node_view_from_node(node);
-               enum property skip = window_rules_get_property(view, "skipWindowSwitcher");
-               if (!isfocusable(view) || skip == LAB_PROP_TRUE) {
-                       continue;
-               }
-
+       struct view **view;
+       struct wl_array views;
+       wl_array_init(&views);
+       desktop_views_append(server, &views, criteria);
+       wl_array_for_each(view, &views) {
                /*
                 *    OSD border
                 * +---------------------------------+
@@ -359,13 +352,13 @@ render_osd(struct server *server, cairo_t *cairo, int w, int h,
 
                        switch (field->content) {
                        case LAB_FIELD_TYPE:
-                               buf_add(&buf, get_type(view));
+                               buf_add(&buf, get_type(*view));
                                break;
                        case LAB_FIELD_APP_ID:
-                               buf_add(&buf, get_app_id(view));
+                               buf_add(&buf, get_app_id(*view));
                                break;
                        case LAB_FIELD_TITLE:
-                               buf_add(&buf, get_title(view));
+                               buf_add(&buf, get_title(*view));
                                break;
                        default:
                                break;
@@ -379,7 +372,7 @@ render_osd(struct server *server, cairo_t *cairo, int w, int h,
                        x += field_width + theme->osd_window_switcher_item_padding_x;
                }
 
-               if (view == cycle_view) {
+               if (*view == cycle_view) {
                        /* Highlight current window */
                        struct wlr_fbox fbox = {
                                .x = theme->osd_border_width + theme->osd_window_switcher_padding,
@@ -398,30 +391,23 @@ render_osd(struct server *server, cairo_t *cairo, int w, int h,
        }
        free(buf.buf);
        g_object_unref(layout);
+       wl_array_release(&views);
 
        cairo_surface_flush(surf);
 }
 
 static int
-get_osd_height(struct wl_list *node_list)
+get_osd_height(struct server *server, enum lab_view_criteria criteria)
 {
        int height = 0;
-       struct view *view;
-       struct wlr_scene_node *node;
-       wl_list_for_each(node, node_list, link) {
-               if (!node->data) {
-                       /* We found some non-view, most likely the region overlay */
-                       continue;
-               }
-               view = node_view_from_node(node);
-               enum property skip = window_rules_get_property(view, "skipWindowSwitcher");
-               if (!isfocusable(view) || skip == LAB_PROP_TRUE) {
-                       continue;
-               }
+       struct wl_array views;
+       wl_array_init(&views);
+       desktop_views_append(server, &views, criteria);
 
-               /* Include item border width */
-               height += rc.theme->osd_window_switcher_item_height;
-       }
+       /* Includes item border width */
+       size_t len = views.size / sizeof(struct view *);
+       height += len * rc.theme->osd_window_switcher_item_height;
+       wl_array_release(&views);
 
        /* Add OSD border width */
        height += 2 * rc.theme->osd_border_width;
@@ -439,9 +425,16 @@ display_osd(struct output *output)
        bool show_workspace = wl_list_length(&rc.workspace_config.workspaces) > 1;
        const char *workspace_name = server->workspace_current->name;
 
+       struct wl_array views;
+       wl_array_init(&views);
+       view_array_append(server, &views,
+               LAB_VIEW_CRITERIA_CURRENT_WORKSPACE
+               | LAB_VIEW_CRITERIA_NO_ALWAYS_ON_TOP
+               | LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER);
+
        float scale = output->wlr_output->scale;
        int w = theme->osd_window_switcher_width;
-       int h = get_osd_height(node_list);
+       int h = get_osd_height(server, criteria);
        if (show_workspace) {
                /* workspace indicator */
                h += theme->osd_window_switcher_item_height;
@@ -455,7 +448,8 @@ display_osd(struct output *output)
 
        /* Render OSD image */
        cairo_t *cairo = output->osd_buffer->cairo;
-       render_osd(server, cairo, w, h, node_list, show_workspace, workspace_name);
+       render_osd(server, cairo, w, h, node_list, show_workspace,
+               workspace_name, criteria);
 
        struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create(
                output->osd_tree, &output->osd_buffer->base);
index d85723e48dc4b849942810e2a4ad2dfb179aa4e4..b6997eb6361b5b9891977c4992a18d0d8026f8f5 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)
+{
+       struct view *view;
+       wl_list_for_each(view, &server->views, link)
+       {
+               if (!isfocusable(view)) {
+                       continue;
+               }
+
+               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;
+                       }
+               }
+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) {
+                               continue;
+                       }
+               }
+
+               struct view **entry = wl_array_add(views, sizeof(*entry));
+               *entry = view;
+       }
+}
+
 /**
  * All view_apply_xxx_geometry() functions must *not* modify
  * any state besides repositioning or resizing the view.
@@ -1264,3 +1306,4 @@ view_destroy(struct view *view)
                cursor_update_focus(server);
        }
 }
+