From: Johan Malm Date: Thu, 10 Aug 2023 14:46:00 +0000 (+0100) Subject: view: add view_array_append() X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=57b9efeb45091c47ae4ec0918306fe622c99aad8;p=proto%2Flabwc.git view: add view_array_append() ...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. --- diff --git a/include/view.h b/include/view.h index 064200f8..80819135 100644 --- a/include/view.h +++ b/include/view.h @@ -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); diff --git a/src/desktop.c b/src/desktop.c index 7c6e944e..00fcda64 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -435,3 +435,4 @@ get_cursor_context(struct server *server) wlr_log(WLR_ERROR, "Unknown node detected"); return ret; } + diff --git a/src/osd.c b/src/osd.c index 8a076dad..3b30ed9a 100644 --- 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); diff --git a/src/view.c b/src/view.c index d85723e4..b6997eb6 100644 --- a/src/view.c +++ b/src/view.c @@ -19,6 +19,48 @@ #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); } } +