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;
} 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;

View file

@ -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 */

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)) {
return view;
}
if (!view->server_side_deco) {
if (!view->ssd.enabled) {
continue;
}
*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);
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);
}

View file

@ -7,6 +7,7 @@
#include <assert.h>
#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);
}

View file

@ -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;

View file

@ -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);

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.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);
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);