From 1e8b0414fef7f11b61e8ffc580ab46d485651b53 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Sat, 26 Nov 2022 16:46:28 -0500 Subject: [PATCH] ssd: Allocate `struct ssd` and `struct ssd_hover_state` separately - Store a pointer to the `struct view` in `struct ssd` - Pass `struct ssd *` instead of `struct view *` to ssd functions - Add `ssd_get_margin()` convenience function --- include/labwc.h | 3 +-- include/ssd.h | 24 +++++++++++++----- include/view.h | 4 +-- src/action.c | 2 +- src/cursor.c | 2 +- src/debug.c | 4 +-- src/desktop.c | 2 +- src/resistance.c | 4 +-- src/server.c | 2 ++ src/ssd/ssd.c | 56 ++++++++++++++++++++++++++++-------------- src/ssd/ssd_border.c | 4 +-- src/ssd/ssd_extents.c | 4 +-- src/ssd/ssd_titlebar.c | 16 ++++++------ src/view.c | 44 ++++++++++++++++++++++----------- src/xdg.c | 6 +++-- 15 files changed, 112 insertions(+), 65 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index 788bfa0e..0f8217d6 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -50,7 +50,6 @@ #include "cursor.h" #include "config/keybind.h" #include "config/rcxml.h" -#include "ssd.h" #if HAVE_NLS #include #include @@ -232,7 +231,7 @@ struct server { /* SSD state */ struct view *focused_view; - struct ssd_hover_state ssd_hover_state; + struct ssd_hover_state *ssd_hover_state; /* Tree for all non-layer xdg/xwayland-shell surfaces */ struct wlr_scene_tree *view_tree; diff --git a/include/ssd.h b/include/ssd.h index 66780390..21821ee7 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -80,6 +80,7 @@ struct ssd_state_title_width { }; struct ssd { + struct view *view; struct wlr_scene_tree *tree; /* @@ -144,12 +145,23 @@ struct ssd_hover_state { struct wlr_scene_node *node; }; -/* Public SSD API */ -void ssd_create(struct view *view, bool active); -void ssd_set_active(struct view *view, bool active); -void ssd_update_title(struct view *view); -void ssd_update_geometry(struct view *view); -void ssd_destroy(struct view *view); +/* + * Public SSD API + * + * For convenience in dealing with non-SSD views, this API allows NULL + * ssd/button/node arguments and attempts to do something sensible in + * that case (e.g. no-op/return default values). + * + * NULL scene/view arguments are not allowed. + */ +struct ssd *ssd_create(struct view *view, bool active); +struct border ssd_get_margin(const struct ssd *ssd); +void ssd_set_active(struct ssd *ssd, bool active); +void ssd_update_title(struct ssd *ssd); +void ssd_update_geometry(struct ssd *ssd); +void ssd_destroy(struct ssd *ssd); + +struct ssd_hover_state *ssd_hover_state_new(void); void ssd_update_button_hover(struct wlr_scene_node *node, struct ssd_hover_state *hover_state); diff --git a/include/view.h b/include/view.h index a174b1b7..1cbe8b22 100644 --- a/include/view.h +++ b/include/view.h @@ -7,7 +7,6 @@ #include #include #include -#include "ssd.h" /* * In labwc, a view is a container for surfaces which can be moved around by @@ -21,6 +20,7 @@ enum view_type { #endif }; +struct view; struct view_impl { void (*configure)(struct view *view, struct wlr_box geo); void (*close)(struct view *view); @@ -65,7 +65,7 @@ struct view { uint32_t configure_serial; } pending_move_resize; - struct ssd ssd; + struct ssd *ssd; struct wlr_foreign_toplevel_handle_v1 *toplevel_handle; struct wl_listener toplevel_handle_request_maximize; diff --git a/src/action.c b/src/action.c index 879f3e9b..b6440a5a 100644 --- a/src/action.c +++ b/src/action.c @@ -161,7 +161,7 @@ show_menu(struct server *server, struct view *view, const char *menu_name) if (!view) { return; } - enum ssd_part_type type = ssd_at(&view->ssd, server->scene, + enum ssd_part_type type = ssd_at(view->ssd, server->scene, server->seat.cursor->x, server->seat.cursor->y); if (type == LAB_SSD_BUTTON_WINDOW_MENU) { force_menu_top_left = true; diff --git a/src/cursor.c b/src/cursor.c index 3e1cb2c4..3cfc6b1c 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -330,7 +330,7 @@ cursor_update_common(struct server *server, struct cursor_context *ctx, struct seat *seat = &server->seat; struct wlr_seat *wlr_seat = seat->seat; - ssd_update_button_hover(ctx->node, &server->ssd_hover_state); + ssd_update_button_hover(ctx->node, server->ssd_hover_state); if (server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) { /* diff --git a/src/debug.c b/src/debug.c index 8be927be..83754a3d 100644 --- a/src/debug.c +++ b/src/debug.c @@ -61,7 +61,7 @@ get_view_part(struct view *view, struct wlr_scene_node *node) return "view->scene_node"; } if (view) { - return ssd_debug_get_node_name(&view->ssd, node); + return ssd_debug_get_node_name(view->ssd, node); } return NULL; } @@ -159,7 +159,7 @@ dump_tree(struct server *server, struct wlr_scene_node *node, if ((IGNORE_MENU && node == &server->menu_tree->node) || (IGNORE_SSD && view - && ssd_debug_is_root_node(&view->ssd, node))) { + && ssd_debug_is_root_node(view->ssd, node))) { printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', ""); return; } diff --git a/src/desktop.c b/src/desktop.c index 895c9011..99948d94 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -339,7 +339,7 @@ get_cursor_context(struct server *server) case LAB_NODE_DESC_VIEW: case LAB_NODE_DESC_XDG_POPUP: ret.view = desc->data; - ret.type = ssd_get_part_type(&ret.view->ssd, ret.node); + ret.type = ssd_get_part_type(ret.view->ssd, ret.node); if (ret.type == LAB_SSD_CLIENT) { ret.surface = lab_wlr_surface_from_node(ret.node); } diff --git a/src/resistance.c b/src/resistance.c index 9a090974..2f40ca15 100644 --- a/src/resistance.c +++ b/src/resistance.c @@ -41,7 +41,7 @@ resistance_move_apply(struct view *view, double *x, double *y) struct wlr_box tgeom = {.x = *x, .y = *y, .width = view->w, .height = view->h}; struct output *output; - struct border border = view->ssd.margin; + struct border border = ssd_get_margin(view->ssd); struct edges view_edges; /* The edges of the current view */ struct edges target_edges; /* The desired edges */ struct edges other_edges; /* The edges of the monitor/other view */ @@ -112,7 +112,7 @@ resistance_resize_apply(struct view *view, struct wlr_box *new_view_geo) .height = view->h}; struct wlr_box tgeom = {.x = new_view_geo->x, .y = new_view_geo->y, .width = new_view_geo->width, .height = new_view_geo->height}; - struct border border = view->ssd.margin; + struct border border = ssd_get_margin(view->ssd); struct edges view_edges; /* The edges of the current view */ struct edges target_edges; /* The desired edges */ struct edges other_edges; /* The edges of the monitor/other view */ diff --git a/src/server.c b/src/server.c index a1f40f99..457960c0 100644 --- a/src/server.c +++ b/src/server.c @@ -221,6 +221,8 @@ server_init(struct server *server) wl_list_init(&server->views); wl_list_init(&server->unmanaged_surfaces); + server->ssd_hover_state = ssd_hover_state_new(); + server->scene = wlr_scene_create(); if (!server->scene) { wlr_log(WLR_ERROR, "unable to create scene"); diff --git a/src/ssd/ssd.c b/src/ssd/ssd.c index 01dd66cc..7f987f21 100644 --- a/src/ssd/ssd.c +++ b/src/ssd/ssd.c @@ -7,6 +7,7 @@ */ #include +#include "common/mem.h" #include "common/scene-helpers.h" #include "labwc.h" #include "ssd.h" @@ -16,6 +17,7 @@ struct border ssd_thickness(struct view *view) { + assert(view); /* * Check preconditions for displaying SSD. Note that this * needs to work even before ssd_create() has been called. @@ -35,6 +37,7 @@ ssd_thickness(struct view *view) struct wlr_box ssd_max_extents(struct view *view) { + assert(view); struct border border = ssd_thickness(view); return (struct wlr_box){ .x = view->x - border.left, @@ -61,7 +64,7 @@ ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node) } else if (node->type == WLR_SCENE_NODE_BUFFER && lab_wlr_surface_from_node(node)) { return LAB_SSD_CLIENT; - } else if (!ssd->tree) { + } else if (!ssd) { return LAB_SSD_NONE; } @@ -114,6 +117,7 @@ ssd_get_part_type(const struct ssd *ssd, struct wlr_scene_node *node) enum ssd_part_type ssd_at(const struct ssd *ssd, struct wlr_scene *scene, double lx, double ly) { + assert(scene); double sx, sy; struct wlr_scene_node *node = wlr_scene_node_at( &scene->tree.node, lx, ly, &sx, &sy); @@ -145,34 +149,43 @@ ssd_resize_edges(enum ssd_part_type type) } } -void +struct ssd * ssd_create(struct view *view, bool active) { - struct ssd *ssd = &view->ssd; - assert(!ssd->tree); + assert(view); + struct ssd *ssd = znew(*ssd); + ssd->view = view; ssd->tree = wlr_scene_tree_create(view->scene_tree); wlr_scene_node_lower_to_bottom(&ssd->tree->node); ssd_extents_create(ssd); ssd_border_create(ssd); ssd_titlebar_create(ssd); ssd->margin = ssd_thickness(view); - ssd_set_active(view, active); + ssd_set_active(ssd, active); ssd->state.width = view->w; ssd->state.height = view->h; ssd->state.x = view->x; ssd->state.y = view->y; + + return ssd; +} + +struct border +ssd_get_margin(const struct ssd *ssd) +{ + return ssd ? ssd->margin : (struct border){ 0 }; } void -ssd_update_geometry(struct view *view) +ssd_update_geometry(struct ssd *ssd) { - struct ssd *ssd = &view->ssd; - if (!ssd->tree) { + if (!ssd) { return; } + struct view *view = ssd->view; if (view->w == ssd->state.width && view->h == ssd->state.height) { if (view->x != ssd->state.x || view->y != ssd->state.y) { /* Dynamically resize extents based on position and usable_area */ @@ -193,16 +206,16 @@ ssd_update_geometry(struct view *view) } void -ssd_destroy(struct view *view) +ssd_destroy(struct ssd *ssd) { - struct ssd *ssd = &view->ssd; - if (!ssd->tree) { + if (!ssd) { return; } /* Maybe reset hover view */ + struct view *view = ssd->view; struct ssd_hover_state *hover_state; - hover_state = &view->server->ssd_hover_state; + hover_state = view->server->ssd_hover_state; if (hover_state->view == view) { hover_state->view = NULL; hover_state->node = NULL; @@ -213,8 +226,8 @@ ssd_destroy(struct view *view) ssd_border_destroy(ssd); ssd_extents_destroy(ssd); wlr_scene_node_destroy(&ssd->tree->node); - ssd->tree = NULL; - ssd->margin = (struct border){ 0 }; + + free(ssd); } bool @@ -256,10 +269,9 @@ ssd_part_contains(enum ssd_part_type whole, enum ssd_part_type candidate) } void -ssd_set_active(struct view *view, bool active) +ssd_set_active(struct ssd *ssd, bool active) { - struct ssd *ssd = &view->ssd; - if (!ssd->tree) { + if (!ssd) { return; } wlr_scene_node_set_enabled(&ssd->border.active.tree->node, active); @@ -268,10 +280,16 @@ ssd_set_active(struct view *view, bool active) wlr_scene_node_set_enabled(&ssd->titlebar.inactive.tree->node, !active); } +struct ssd_hover_state * +ssd_hover_state_new(void) +{ + return znew(struct ssd_hover_state); +} + bool ssd_debug_is_root_node(const struct ssd *ssd, struct wlr_scene_node *node) { - if (!ssd->tree || !node) { + if (!ssd || !node) { return false; } return node == &ssd->tree->node; @@ -280,7 +298,7 @@ ssd_debug_is_root_node(const struct ssd *ssd, struct wlr_scene_node *node) const char * ssd_debug_get_node_name(const struct ssd *ssd, struct wlr_scene_node *node) { - if (!ssd->tree || !node) { + if (!ssd || !node) { return NULL; } if (node == &ssd->tree->node) { diff --git a/src/ssd/ssd_border.c b/src/ssd/ssd_border.c index b1ef3e85..a145c424 100644 --- a/src/ssd/ssd_border.c +++ b/src/ssd/ssd_border.c @@ -13,7 +13,7 @@ void ssd_border_create(struct ssd *ssd) { - struct view *view = wl_container_of(ssd, view, ssd); + struct view *view = ssd->view; struct theme *theme = view->server->theme; int width = view->w; int height = view->h; @@ -51,7 +51,7 @@ ssd_border_create(struct ssd *ssd) void ssd_border_update(struct ssd *ssd) { - struct view *view = wl_container_of(ssd, view, ssd); + struct view *view = ssd->view; struct theme *theme = view->server->theme; int width = view->w; diff --git a/src/ssd/ssd_extents.c b/src/ssd/ssd_extents.c index 2d203609..25ed8af6 100644 --- a/src/ssd/ssd_extents.c +++ b/src/ssd/ssd_extents.c @@ -37,7 +37,7 @@ lab_wlr_output_layout_layout_coords(struct wlr_output_layout *layout, void ssd_extents_create(struct ssd *ssd) { - struct view *view = wl_container_of(ssd, view, ssd); + struct view *view = ssd->view; struct theme *theme = view->server->theme; struct wl_list *part_list = &ssd->extents.parts; int extended_area = EXTENDED_AREA; @@ -98,7 +98,7 @@ ssd_extents_create(struct ssd *ssd) void ssd_extents_update(struct ssd *ssd) { - struct view *view = wl_container_of(ssd, view, ssd); + struct view *view = ssd->view; if (view->maximized || view->fullscreen) { wlr_scene_node_set_enabled(&ssd->extents.tree->node, false); return; diff --git a/src/ssd/ssd_titlebar.c b/src/ssd/ssd_titlebar.c index 15bb2c07..93b300d8 100644 --- a/src/ssd/ssd_titlebar.c +++ b/src/ssd/ssd_titlebar.c @@ -20,7 +20,7 @@ void ssd_titlebar_create(struct ssd *ssd) { - struct view *view = wl_container_of(ssd, view, ssd); + struct view *view = ssd->view; struct theme *theme = view->server->theme; int width = view->w; @@ -78,7 +78,7 @@ ssd_titlebar_create(struct ssd *ssd) corner_top_right, close_button_unpressed, width - BUTTON_WIDTH * 1, view); } FOR_EACH_END - ssd_update_title(view); + ssd_update_title(ssd); } static bool @@ -90,7 +90,7 @@ is_direct_child(struct wlr_scene_node *node, struct ssd_sub_tree *subtree) void ssd_titlebar_update(struct ssd *ssd) { - struct view *view = wl_container_of(ssd, view, ssd); + struct view *view = ssd->view; int width = view->w; if (width == ssd->state.width) { return; @@ -131,7 +131,7 @@ ssd_titlebar_update(struct ssd *ssd) } } } FOR_EACH_END - ssd_update_title(view); + ssd_update_title(ssd); } void @@ -169,7 +169,7 @@ ssd_titlebar_destroy(struct ssd *ssd) static void ssd_update_title_positions(struct ssd *ssd) { - struct view *view = wl_container_of(ssd, view, ssd); + struct view *view = ssd->view; struct theme *theme = view->server->theme; int width = view->w; int title_bg_width = width - BUTTON_WIDTH * BUTTON_COUNT; @@ -219,13 +219,13 @@ ssd_update_title_positions(struct ssd *ssd) } void -ssd_update_title(struct view *view) +ssd_update_title(struct ssd *ssd) { - struct ssd *ssd = &view->ssd; - if (!ssd->tree) { + if (!ssd) { return; } + struct view *view = ssd->view; char *title = (char *)view_get_string_prop(view, "title"); if (!title || !*title) { return; diff --git a/src/view.c b/src/view.c index a747c0a6..cd243137 100644 --- a/src/view.c +++ b/src/view.c @@ -88,7 +88,7 @@ view_get_edge_snap_box(struct view *view, struct output *output, break; } - struct border margin = view->ssd.margin; + struct border margin = ssd_get_margin(view->ssd); struct wlr_box dst = { .x = x_offset + usable.x + margin.left, .y = y_offset + usable.y + margin.top, @@ -102,9 +102,7 @@ view_get_edge_snap_box(struct view *view, struct output *output, static void _view_set_activated(struct view *view, bool activated) { - if (view->ssd.tree) { - ssd_set_active(view, activated); - } + ssd_set_active(view->ssd, activated); if (view->impl->set_activated) { view->impl->set_activated(view, activated); } @@ -153,7 +151,7 @@ view_moved(struct view *view) assert(view); wlr_scene_node_set_position(&view->scene_tree->node, view->x, view->y); view_discover_output(view); - ssd_update_geometry(view); + ssd_update_geometry(view->ssd); cursor_update_focus(view->server); } @@ -278,7 +276,7 @@ view_compute_centered_position(struct view *view, int w, int h, int *x, int *y) return false; } - struct border margin = view->ssd.margin; + struct border margin = ssd_get_margin(view->ssd); struct wlr_box usable = output_usable_area_in_layout_coords(output); int width = w + margin.left + margin.right; int height = h + margin.top + margin.bottom; @@ -554,6 +552,22 @@ view_move_to_workspace(struct view *view, struct workspace *workspace) } } +static void +decorate(struct view *view) +{ + if (!view->ssd) { + view->ssd = ssd_create(view, + view == view->server->focused_view); + } +} + +static void +undecorate(struct view *view) +{ + ssd_destroy(view->ssd); + view->ssd = NULL; +} + void view_set_decorations(struct view *view, bool decorations) { @@ -565,9 +579,9 @@ view_set_decorations(struct view *view, bool decorations) */ view->ssd_enabled = decorations; if (decorations) { - ssd_create(view, view == view->server->focused_view); + decorate(view); } else { - ssd_destroy(view); + undecorate(view); } if (view->maximized) { view_apply_maximized_geometry(view); @@ -614,7 +628,7 @@ view_set_fullscreen(struct view *view, bool fullscreen, } /* Hide decorations when going fullscreen */ if (view->ssd_enabled) { - ssd_destroy(view); + undecorate(view); } view->fullscreen = wlr_output; view_apply_fullscreen_geometry(view, view->fullscreen); @@ -630,7 +644,7 @@ view_set_fullscreen(struct view *view, bool fullscreen, } /* Re-show decorations when no longer fullscreen */ if (view->ssd_enabled) { - ssd_create(view, view == view->server->focused_view); + decorate(view); } } @@ -734,7 +748,7 @@ view_move_to_edge(struct view *view, const char *direction) return; } - struct border margin = view->ssd.margin; + struct border margin = ssd_get_margin(view->ssd); struct wlr_box usable = output_usable_area_in_layout_coords(output); if (usable.height == output->wlr_output->height && output->wlr_output->scale != 1) { @@ -872,7 +886,7 @@ view_update_title(struct view *view) if (!view->toplevel_handle || !title) { return; } - ssd_update_title(view); + ssd_update_title(view->ssd); wlr_foreign_toplevel_handle_v1_set_title(view->toplevel_handle, title); } @@ -893,8 +907,8 @@ view_reload_ssd(struct view *view) { assert(view); if (view->ssd_enabled && !view->fullscreen) { - ssd_destroy(view); - ssd_create(view, view == view->server->focused_view); + undecorate(view); + decorate(view); } } @@ -926,9 +940,9 @@ view_destroy(struct view *view) } osd_on_view_destroy(view); + undecorate(view); if (view->scene_tree) { - ssd_destroy(view); wlr_scene_node_destroy(&view->scene_tree->node); view->scene_tree = NULL; } diff --git a/src/xdg.c b/src/xdg.c index 3f5bf2cd..edfdabbf 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -303,8 +303,10 @@ position_xdg_toplevel_view(struct view *view) view->x = center_x - xdg_surface->current.geometry.width / 2; view->y = center_y - xdg_surface->current.geometry.height / 2; } - view->x += view->ssd.margin.left; - view->y += view->ssd.margin.top; + + struct border margin = ssd_get_margin(view->ssd); + view->x += margin.left; + view->y += margin.top; } static const char * -- 2.52.0