Create a linked list of SSD for each view

This commit is contained in:
Johan Malm 2021-03-21 21:46:16 +00:00
parent f863e1916d
commit 2a48f2801b
8 changed files with 134 additions and 47 deletions

View file

@ -213,7 +213,11 @@ struct view {
uint32_t configure_serial; uint32_t configure_serial;
} pending_move_resize; } 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 map;
struct wl_listener unmap; struct wl_listener unmap;

View file

@ -1,7 +1,7 @@
#ifndef __LABWC_SSD_H #ifndef __LABWC_SSD_H
#define __LABWC_SSD_H #define __LABWC_SSD_H
enum ssd_part { enum ssd_part_type {
LAB_SSD_NONE = 0, LAB_SSD_NONE = 0,
LAB_SSD_BUTTON_CLOSE, LAB_SSD_BUTTON_CLOSE,
LAB_SSD_BUTTON_MAXIMIZE, LAB_SSD_BUTTON_MAXIMIZE,
@ -14,11 +14,22 @@ enum ssd_part {
LAB_SSD_END_MARKER 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 view;
struct border ssd_thickness(struct view *view); struct border ssd_thickness(struct view *view);
struct wlr_box ssd_max_extents(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); struct wlr_box ssd_box(struct view *view, enum ssd_part_type type);
enum ssd_part ssd_at(struct view *view, double lx, double ly); 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 */ #endif /* __LABWC_SSD_H */

View file

@ -244,7 +244,7 @@ desktop_view_at(struct server *server, double lx, double ly,
if (_view_at(view, lx, ly, surface, sx, sy)) { if (_view_at(view, lx, ly, surface, sx, sy)) {
return view; return view;
} }
if (!view->server_side_deco) { if (!view->ssd.enabled) {
continue; continue;
} }
*view_area = ssd_at(view, lx, ly); *view_area = ssd_at(view, lx, ly);

View file

@ -321,6 +321,7 @@ render_rect(struct output *output, pixman_region32_t *output_damage,
output->wlr_output, &ox, &oy); output->wlr_output, &ox, &oy);
box.x += ox; box.x += ox;
box.y += oy; box.y += oy;
scale_box(&box, wlr_output->scale);
pixman_region32_t damage; pixman_region32_t damage;
pixman_region32_init(&damage); pixman_region32_init(&damage);
@ -424,6 +425,7 @@ render_icon(struct output *output, pixman_region32_t *output_damage,
output->wlr_output, &ox, &oy); output->wlr_output, &ox, &oy);
button.x += ox; button.x += ox;
button.y += oy; button.y += oy;
scale_box(&button, output->wlr_output->scale);
float matrix[9]; float matrix[9];
wlr_matrix_project_box(matrix, &button, WL_OUTPUT_TRANSFORM_NORMAL, 0, 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 static bool
isbutton(enum ssd_part ssd_part) isbutton(enum ssd_part_type type)
{ {
return ssd_part == LAB_SSD_BUTTON_CLOSE || return type == LAB_SSD_BUTTON_CLOSE ||
ssd_part == LAB_SSD_BUTTON_MAXIMIZE || type == LAB_SSD_BUTTON_MAXIMIZE ||
ssd_part == LAB_SSD_BUTTON_ICONIFY; type == LAB_SSD_BUTTON_ICONIFY;
} }
static void static void
render_deco(struct view *view, struct output *output, render_deco(struct view *view, struct output *output,
pixman_region32_t *output_damage) pixman_region32_t *output_damage)
{ {
if (!view->server_side_deco) { if (!view->ssd.enabled) {
return; return;
} }
struct theme *theme = view->server->theme; struct ssd_part *part;
wl_list_for_each_reverse(part, &view->ssd.parts, link) {
/* render border */ if (part->texture) {
float *color = theme->window_active_handle_bg_color; ; // render_texture()
enum ssd_part border[4] = { } else {
LAB_SSD_PART_TOP, render_rect(output, output_damage, &part->box,
LAB_SSD_PART_RIGHT, part->color);
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);
} }
/* render title */ /* render title */
struct wlr_seat *seat = view->server->seat.seat; struct wlr_seat *seat = view->server->seat.seat;
float *color;
struct theme *theme = view->server->theme;
if (view->surface == seat->keyboard_state.focused_surface) { if (view->surface == seat->keyboard_state.focused_surface) {
color = theme->window_active_title_bg_color; color = theme->window_active_title_bg_color;
} else { } else {
color = theme->window_inactive_title_bg_color; color = theme->window_inactive_title_bg_color;
} }
struct wlr_box box = ssd_box(view, LAB_SSD_PART_TITLE); 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); render_rect(output, output_damage, &box, color);
/* button background */ /* button background */
struct wlr_cursor *cur = view->server->seat.cursor; struct wlr_cursor *cur = view->server->seat.cursor;
enum ssd_part ssd_part = ssd_at(view, cur->x, cur->y); enum ssd_part_type type = ssd_at(view, cur->x, cur->y);
box = ssd_box(view, ssd_part); box = ssd_box(view, type);
scale_box(&box, output->wlr_output->scale); if (isbutton(type) &&
if (isbutton(ssd_part) &&
wlr_box_contains_point(&box, cur->x, cur->y)) { wlr_box_contains_point(&box, cur->x, cur->y)) {
color = (float[4]){ 0.5, 0.5, 0.5, 0.5 }; color = (float[4]){ 0.5, 0.5, 0.5, 0.5 };
render_rect(output, output_damage, &box, color); render_rect(output, output_damage, &box, color);
@ -489,28 +485,22 @@ render_deco(struct view *view, struct output *output,
/* buttons */ /* buttons */
if (view->surface == seat->keyboard_state.focused_surface) { if (view->surface == seat->keyboard_state.focused_surface) {
box = ssd_box(view, LAB_SSD_BUTTON_CLOSE); box = ssd_box(view, LAB_SSD_BUTTON_CLOSE);
scale_box(&box, output->wlr_output->scale);
render_icon(output, output_damage, &box, render_icon(output, output_damage, &box,
theme->xbm_close_active_unpressed); theme->xbm_close_active_unpressed);
box = ssd_box(view, LAB_SSD_BUTTON_MAXIMIZE); box = ssd_box(view, LAB_SSD_BUTTON_MAXIMIZE);
scale_box(&box, output->wlr_output->scale);
render_icon(output, output_damage, &box, render_icon(output, output_damage, &box,
theme->xbm_maximize_active_unpressed); theme->xbm_maximize_active_unpressed);
box = ssd_box(view, LAB_SSD_BUTTON_ICONIFY); box = ssd_box(view, LAB_SSD_BUTTON_ICONIFY);
scale_box(&box, output->wlr_output->scale);
render_icon(output, output_damage, &box, render_icon(output, output_damage, &box,
theme->xbm_iconify_active_unpressed); theme->xbm_iconify_active_unpressed);
} else { } else {
box = ssd_box(view, LAB_SSD_BUTTON_CLOSE); box = ssd_box(view, LAB_SSD_BUTTON_CLOSE);
scale_box(&box, output->wlr_output->scale);
render_icon(output, output_damage, &box, render_icon(output, output_damage, &box,
theme->xbm_close_inactive_unpressed); theme->xbm_close_inactive_unpressed);
box = ssd_box(view, LAB_SSD_BUTTON_MAXIMIZE); box = ssd_box(view, LAB_SSD_BUTTON_MAXIMIZE);
scale_box(&box, output->wlr_output->scale);
render_icon(output, output_damage, &box, render_icon(output, output_damage, &box,
theme->xbm_maximize_inactive_unpressed); theme->xbm_maximize_inactive_unpressed);
box = ssd_box(view, LAB_SSD_BUTTON_ICONIFY); box = ssd_box(view, LAB_SSD_BUTTON_ICONIFY);
scale_box(&box, output->wlr_output->scale);
render_icon(output, output_damage, &box, render_icon(output, output_damage, &box,
theme->xbm_iconify_inactive_unpressed); theme->xbm_iconify_inactive_unpressed);
} }

View file

@ -7,6 +7,7 @@
#include <assert.h> #include <assert.h>
#include "config/rcxml.h" #include "config/rcxml.h"
#include "labwc.h" #include "labwc.h"
#include "theme.h"
#include "ssd.h" #include "ssd.h"
#define BORDER_WIDTH (2) #define BORDER_WIDTH (2)
@ -37,11 +38,11 @@ ssd_max_extents(struct view *view)
} }
struct wlr_box 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 }; struct wlr_box box = { 0 };
assert(view); assert(view);
switch (ssd_part) { switch (type) {
case LAB_SSD_BUTTON_CLOSE: case LAB_SSD_BUTTON_CLOSE:
box.width = rc.title_height; box.width = rc.title_height;
box.height = rc.title_height; box.height = rc.title_height;
@ -96,17 +97,85 @@ ssd_box(struct view *view, enum ssd_part ssd_part)
return box; return box;
} }
enum ssd_part enum ssd_part_type
ssd_at(struct view *view, double lx, double ly) ssd_at(struct view *view, double lx, double ly)
{ {
enum ssd_part ssd_part; enum ssd_part_type type;
for (ssd_part = 0; ssd_part < LAB_SSD_END_MARKER; ++ssd_part) { for (type = 0; type < LAB_SSD_END_MARKER; ++type) {
struct wlr_box box = ssd_box(view, ssd_part); struct wlr_box box = ssd_box(view, type);
if (wlr_box_contains_point(&box, lx, ly)) { if (wlr_box_contains_point(&box, lx, ly)) {
return ssd_part; return type;
} }
} }
return LAB_SSD_NONE; 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);
}

View file

@ -77,7 +77,7 @@ view_maximize(struct view *view, bool maximize)
.width = output->width, .width = output->width,
.height = output->height, .height = output->height,
}; };
if (view->server_side_deco) { if (view->ssd.enabled) {
struct border border = ssd_thickness(view); struct border border = ssd_thickness(view);
box.x += border.left; box.x += border.left;
box.y += border.top; box.y += border.top;

View file

@ -69,6 +69,7 @@ handle_commit(struct wl_listener *listener, void *data)
view->pending_move_resize.configure_serial = 0; view->pending_move_resize.configure_serial = 0;
} }
} }
ssd_update_geometry(view);
damage_view_part(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); struct view *view = wl_container_of(listener, view, destroy);
wl_list_remove(&view->link); wl_list_remove(&view->link);
ssd_destroy(view);
free(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) { } else if (view->pending_move_resize.configure_serial == 0) {
view->x = geo.x; view->x = geo.x;
view->y = geo.y; view->y = geo.y;
ssd_update_geometry(view);
damage_all_outputs(view->server); damage_all_outputs(view->server);
} }
} }
@ -160,6 +163,7 @@ xdg_toplevel_view_move(struct view *view, double x, double y)
{ {
view->x = x; view->x = x;
view->y = y; view->y = y;
ssd_update_geometry(view);
damage_all_outputs(view->server); damage_all_outputs(view->server);
} }
@ -253,9 +257,10 @@ xdg_toplevel_view_map(struct view *view)
*/ */
view_maximize(view, false); view_maximize(view, false);
view->server_side_deco = has_ssd(view); view->ssd.enabled = has_ssd(view);
if (view->server_side_deco) { if (view->ssd.enabled) {
view->margin = ssd_thickness(view); view->margin = ssd_thickness(view);
ssd_create(view);
} }
update_padding(view); update_padding(view);
position_xdg_toplevel_view(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->type = LAB_XDG_SHELL_VIEW;
view->impl = &xdg_toplevel_view_impl; view->impl = &xdg_toplevel_view_impl;
view->xdg_surface = xdg_surface; view->xdg_surface = xdg_surface;
wl_list_init(&view->ssd.parts);
view->map.notify = handle_map; view->map.notify = handle_map;
wl_signal_add(&xdg_surface->events.map, &view->map); wl_signal_add(&xdg_surface->events.map, &view->map);

View file

@ -22,6 +22,7 @@ handle_commit(struct wl_listener *listener, void *data)
view->pending_move_resize.height - view->h; view->pending_move_resize.height - view->h;
view->pending_move_resize.update_y = false; view->pending_move_resize.update_y = false;
} }
ssd_update_geometry(view);
damage_view_whole(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->destroy.link);
wl_list_remove(&view->request_configure.link); wl_list_remove(&view->request_configure.link);
wl_list_remove(&view->request_maximize.link); wl_list_remove(&view->request_maximize.link);
ssd_destroy(view);
free(view); free(view);
} }
@ -95,6 +97,7 @@ move(struct view *view, double x, double y)
struct wlr_xwayland_surface *s = view->xwayland_surface; struct wlr_xwayland_surface *s = view->xwayland_surface;
wlr_xwayland_surface_configure(s, (int16_t)x, (int16_t)y, wlr_xwayland_surface_configure(s, (int16_t)x, (int16_t)y,
(uint16_t)s->width, (uint16_t)s->height); (uint16_t)s->width, (uint16_t)s->height);
ssd_update_geometry(view);
damage_all_outputs(view->server); damage_all_outputs(view->server);
} }
@ -147,9 +150,12 @@ map(struct view *view)
view->w = view->xwayland_surface->width; view->w = view->xwayland_surface->width;
view->h = view->xwayland_surface->height; view->h = view->xwayland_surface->height;
view->surface = view->xwayland_surface->surface; 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); 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->type = LAB_XWAYLAND_VIEW;
view->impl = &xwl_view_impl; view->impl = &xwl_view_impl;
view->xwayland_surface = xsurface; view->xwayland_surface = xsurface;
wl_list_init(&view->ssd.parts);
view->map.notify = handle_map; view->map.notify = handle_map;
wl_signal_add(&xsurface->events.map, &view->map); wl_signal_add(&xsurface->events.map, &view->map);