From 2a48f2801b271334499ad2bbfbdaaa39069e138b Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sun, 21 Mar 2021 21:46:16 +0000 Subject: [PATCH] Create a linked list of SSD for each view --- include/labwc.h | 6 +++- include/ssd.h | 17 ++++++++-- src/desktop.c | 2 +- src/output.c | 50 ++++++++++++----------------- src/ssd.c | 83 ++++++++++++++++++++++++++++++++++++++++++++----- src/view.c | 2 +- src/xdg.c | 10 ++++-- src/xwayland.c | 11 +++++-- 8 files changed, 134 insertions(+), 47 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index eb6e0c4e..fa0bac02 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -213,7 +213,11 @@ struct view { uint32_t configure_serial; } pending_move_resize; - bool server_side_deco; + struct { + bool enabled; + struct wl_list parts; + struct wlr_box box; /* remember geo so we know when to update */ + } ssd; struct wl_listener map; struct wl_listener unmap; diff --git a/include/ssd.h b/include/ssd.h index 76544cf3..734f2901 100644 --- a/include/ssd.h +++ b/include/ssd.h @@ -1,7 +1,7 @@ #ifndef __LABWC_SSD_H #define __LABWC_SSD_H -enum ssd_part { +enum ssd_part_type { LAB_SSD_NONE = 0, LAB_SSD_BUTTON_CLOSE, LAB_SSD_BUTTON_MAXIMIZE, @@ -14,11 +14,22 @@ enum ssd_part { LAB_SSD_END_MARKER }; +struct ssd_part { + struct wlr_box box; + enum ssd_part_type type; + struct wlr_texture *texture; + float *color; + struct wl_list link; +}; + struct view; struct border ssd_thickness(struct view *view); struct wlr_box ssd_max_extents(struct view *view); -struct wlr_box ssd_box(struct view *view, enum ssd_part ssd_part); -enum ssd_part ssd_at(struct view *view, double lx, double ly); +struct wlr_box ssd_box(struct view *view, enum ssd_part_type type); +enum ssd_part_type ssd_at(struct view *view, double lx, double ly); +void ssd_create(struct view *view); +void ssd_destroy(struct view *view); +void ssd_update_geometry(struct view *view); #endif /* __LABWC_SSD_H */ diff --git a/src/desktop.c b/src/desktop.c index bb1a8c89..21521423 100644 --- a/src/desktop.c +++ b/src/desktop.c @@ -244,7 +244,7 @@ desktop_view_at(struct server *server, double lx, double ly, if (_view_at(view, lx, ly, surface, sx, sy)) { return view; } - if (!view->server_side_deco) { + if (!view->ssd.enabled) { continue; } *view_area = ssd_at(view, lx, ly); diff --git a/src/output.c b/src/output.c index b9377fb9..d0095137 100644 --- a/src/output.c +++ b/src/output.c @@ -321,6 +321,7 @@ render_rect(struct output *output, pixman_region32_t *output_damage, output->wlr_output, &ox, &oy); box.x += ox; box.y += oy; + scale_box(&box, wlr_output->scale); pixman_region32_t damage; pixman_region32_init(&damage); @@ -424,6 +425,7 @@ render_icon(struct output *output, pixman_region32_t *output_damage, output->wlr_output, &ox, &oy); button.x += ox; button.y += oy; + scale_box(&button, output->wlr_output->scale); float matrix[9]; wlr_matrix_project_box(matrix, &button, WL_OUTPUT_TRANSFORM_NORMAL, 0, @@ -433,54 +435,48 @@ render_icon(struct output *output, pixman_region32_t *output_damage, } static bool -isbutton(enum ssd_part ssd_part) +isbutton(enum ssd_part_type type) { - return ssd_part == LAB_SSD_BUTTON_CLOSE || - ssd_part == LAB_SSD_BUTTON_MAXIMIZE || - ssd_part == LAB_SSD_BUTTON_ICONIFY; + return type == LAB_SSD_BUTTON_CLOSE || + type == LAB_SSD_BUTTON_MAXIMIZE || + type == LAB_SSD_BUTTON_ICONIFY; } static void render_deco(struct view *view, struct output *output, pixman_region32_t *output_damage) { - if (!view->server_side_deco) { + if (!view->ssd.enabled) { return; } - struct theme *theme = view->server->theme; - - /* render border */ - float *color = theme->window_active_handle_bg_color; - enum ssd_part border[4] = { - LAB_SSD_PART_TOP, - LAB_SSD_PART_RIGHT, - LAB_SSD_PART_BOTTOM, - LAB_SSD_PART_LEFT, - }; - for (int i = 0; i < 4; i++) { - struct wlr_box box = ssd_box(view, border[i]); - scale_box(&box, output->wlr_output->scale); - render_rect(output, output_damage, &box, color); + struct ssd_part *part; + wl_list_for_each_reverse(part, &view->ssd.parts, link) { + if (part->texture) { + ; // render_texture() + } else { + render_rect(output, output_damage, &part->box, + part->color); + } } /* render title */ struct wlr_seat *seat = view->server->seat.seat; + float *color; + struct theme *theme = view->server->theme; if (view->surface == seat->keyboard_state.focused_surface) { color = theme->window_active_title_bg_color; } else { color = theme->window_inactive_title_bg_color; } struct wlr_box box = ssd_box(view, LAB_SSD_PART_TITLE); - scale_box(&box, output->wlr_output->scale); render_rect(output, output_damage, &box, color); /* button background */ struct wlr_cursor *cur = view->server->seat.cursor; - enum ssd_part ssd_part = ssd_at(view, cur->x, cur->y); - box = ssd_box(view, ssd_part); - scale_box(&box, output->wlr_output->scale); - if (isbutton(ssd_part) && + enum ssd_part_type type = ssd_at(view, cur->x, cur->y); + box = ssd_box(view, type); + if (isbutton(type) && wlr_box_contains_point(&box, cur->x, cur->y)) { color = (float[4]){ 0.5, 0.5, 0.5, 0.5 }; render_rect(output, output_damage, &box, color); @@ -489,28 +485,22 @@ render_deco(struct view *view, struct output *output, /* buttons */ if (view->surface == seat->keyboard_state.focused_surface) { box = ssd_box(view, LAB_SSD_BUTTON_CLOSE); - scale_box(&box, output->wlr_output->scale); render_icon(output, output_damage, &box, theme->xbm_close_active_unpressed); box = ssd_box(view, LAB_SSD_BUTTON_MAXIMIZE); - scale_box(&box, output->wlr_output->scale); render_icon(output, output_damage, &box, theme->xbm_maximize_active_unpressed); box = ssd_box(view, LAB_SSD_BUTTON_ICONIFY); - scale_box(&box, output->wlr_output->scale); render_icon(output, output_damage, &box, theme->xbm_iconify_active_unpressed); } else { box = ssd_box(view, LAB_SSD_BUTTON_CLOSE); - scale_box(&box, output->wlr_output->scale); render_icon(output, output_damage, &box, theme->xbm_close_inactive_unpressed); box = ssd_box(view, LAB_SSD_BUTTON_MAXIMIZE); - scale_box(&box, output->wlr_output->scale); render_icon(output, output_damage, &box, theme->xbm_maximize_inactive_unpressed); box = ssd_box(view, LAB_SSD_BUTTON_ICONIFY); - scale_box(&box, output->wlr_output->scale); render_icon(output, output_damage, &box, theme->xbm_iconify_inactive_unpressed); } diff --git a/src/ssd.c b/src/ssd.c index 0d89cebe..c7748a20 100644 --- a/src/ssd.c +++ b/src/ssd.c @@ -7,6 +7,7 @@ #include #include "config/rcxml.h" #include "labwc.h" +#include "theme.h" #include "ssd.h" #define BORDER_WIDTH (2) @@ -37,11 +38,11 @@ ssd_max_extents(struct view *view) } struct wlr_box -ssd_box(struct view *view, enum ssd_part ssd_part) +ssd_box(struct view *view, enum ssd_part_type type) { struct wlr_box box = { 0 }; assert(view); - switch (ssd_part) { + switch (type) { case LAB_SSD_BUTTON_CLOSE: box.width = rc.title_height; box.height = rc.title_height; @@ -96,17 +97,85 @@ ssd_box(struct view *view, enum ssd_part ssd_part) return box; } -enum ssd_part +enum ssd_part_type ssd_at(struct view *view, double lx, double ly) { - enum ssd_part ssd_part; - for (ssd_part = 0; ssd_part < LAB_SSD_END_MARKER; ++ssd_part) { - struct wlr_box box = ssd_box(view, ssd_part); + enum ssd_part_type type; + for (type = 0; type < LAB_SSD_END_MARKER; ++type) { + struct wlr_box box = ssd_box(view, type); if (wlr_box_contains_point(&box, lx, ly)) { - return ssd_part; + return type; } } return LAB_SSD_NONE; } +static struct ssd_part * +add_part(struct view *view, enum ssd_part_type type) +{ + struct ssd_part *part = calloc(1, sizeof(struct ssd_part)); + part->type = type; + wl_list_insert(&view->ssd.parts, &part->link); + return part; +} +void +ssd_create(struct view *view) +{ + struct theme *theme = view->server->theme; + struct ssd_part *part; + + view->ssd.box.x = view->x; + view->ssd.box.y = view->y; + view->ssd.box.width = view->w; + view->ssd.box.height = view->h; + + /* border */ + float *color = theme->window_active_handle_bg_color; + enum ssd_part_type border[4] = { + LAB_SSD_PART_TOP, + LAB_SSD_PART_RIGHT, + LAB_SSD_PART_BOTTOM, + LAB_SSD_PART_LEFT, + }; + for (int i = 0; i < 4; i++) { + part = add_part(view, border[i]); + part->box = ssd_box(view, border[i]); + part->color = color; + } +} + +void +ssd_destroy(struct view *view) +{ + struct ssd_part *part, *next; + wl_list_for_each_safe(part, next, &view->ssd.parts, link) { + wl_list_remove(&part->link); + free(part); + } +} + +static bool +geometry_changed(struct view *view) +{ + return view->x != view->ssd.box.x || view->y != view->ssd.box.y || + view->w != view->ssd.box.width || + view->h != view->ssd.box.height; +} + +void +ssd_update_geometry(struct view *view) +{ + if (!geometry_changed(view)) { + return; + } + struct ssd_part *part; + wl_list_for_each(part, &view->ssd.parts, link) { + part->box = ssd_box(view, part->type); + } + view->ssd.box.x = view->x; + view->ssd.box.y = view->y; + view->ssd.box.width = view->w; + view->ssd.box.height = view->h; + damage_all_outputs(view->server); +} diff --git a/src/view.c b/src/view.c index 9aeae4d5..2a463232 100644 --- a/src/view.c +++ b/src/view.c @@ -77,7 +77,7 @@ view_maximize(struct view *view, bool maximize) .width = output->width, .height = output->height, }; - if (view->server_side_deco) { + if (view->ssd.enabled) { struct border border = ssd_thickness(view); box.x += border.left; box.y += border.top; diff --git a/src/xdg.c b/src/xdg.c index 2ac771cd..1e0dc828 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -69,6 +69,7 @@ handle_commit(struct wl_listener *listener, void *data) view->pending_move_resize.configure_serial = 0; } } + ssd_update_geometry(view); damage_view_part(view); } @@ -91,6 +92,7 @@ handle_destroy(struct wl_listener *listener, void *data) { struct view *view = wl_container_of(listener, view, destroy); wl_list_remove(&view->link); + ssd_destroy(view); free(view); } @@ -151,6 +153,7 @@ xdg_toplevel_view_configure(struct view *view, struct wlr_box geo) } else if (view->pending_move_resize.configure_serial == 0) { view->x = geo.x; view->y = geo.y; + ssd_update_geometry(view); damage_all_outputs(view->server); } } @@ -160,6 +163,7 @@ xdg_toplevel_view_move(struct view *view, double x, double y) { view->x = x; view->y = y; + ssd_update_geometry(view); damage_all_outputs(view->server); } @@ -253,9 +257,10 @@ xdg_toplevel_view_map(struct view *view) */ view_maximize(view, false); - view->server_side_deco = has_ssd(view); - if (view->server_side_deco) { + view->ssd.enabled = has_ssd(view); + if (view->ssd.enabled) { view->margin = ssd_thickness(view); + ssd_create(view); } update_padding(view); position_xdg_toplevel_view(view); @@ -310,6 +315,7 @@ xdg_surface_new(struct wl_listener *listener, void *data) view->type = LAB_XDG_SHELL_VIEW; view->impl = &xdg_toplevel_view_impl; view->xdg_surface = xdg_surface; + wl_list_init(&view->ssd.parts); view->map.notify = handle_map; wl_signal_add(&xdg_surface->events.map, &view->map); diff --git a/src/xwayland.c b/src/xwayland.c index 1a8b4061..18520872 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -22,6 +22,7 @@ handle_commit(struct wl_listener *listener, void *data) view->pending_move_resize.height - view->h; view->pending_move_resize.update_y = false; } + ssd_update_geometry(view); damage_view_whole(view); } @@ -49,6 +50,7 @@ handle_destroy(struct wl_listener *listener, void *data) wl_list_remove(&view->destroy.link); wl_list_remove(&view->request_configure.link); wl_list_remove(&view->request_maximize.link); + ssd_destroy(view); free(view); } @@ -95,6 +97,7 @@ move(struct view *view, double x, double y) struct wlr_xwayland_surface *s = view->xwayland_surface; wlr_xwayland_surface_configure(s, (int16_t)x, (int16_t)y, (uint16_t)s->width, (uint16_t)s->height); + ssd_update_geometry(view); damage_all_outputs(view->server); } @@ -147,9 +150,12 @@ map(struct view *view) view->w = view->xwayland_surface->width; view->h = view->xwayland_surface->height; view->surface = view->xwayland_surface->surface; - view->server_side_deco = want_deco(view); + view->ssd.enabled = want_deco(view); - view->margin = ssd_thickness(view); + if (view->ssd.enabled) { + view->margin = ssd_thickness(view); + ssd_create(view); + } top_left_edge_boundary_check(view); @@ -209,6 +215,7 @@ xwayland_surface_new(struct wl_listener *listener, void *data) view->type = LAB_XWAYLAND_VIEW; view->impl = &xwl_view_impl; view->xwayland_surface = xsurface; + wl_list_init(&view->ssd.parts); view->map.notify = handle_map; wl_signal_add(&xsurface->events.map, &view->map);