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;
#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,
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 */
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);
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);
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,
}
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);
/* 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);
}
#include <assert.h>
#include "config/rcxml.h"
#include "labwc.h"
+#include "theme.h"
#include "ssd.h"
#define BORDER_WIDTH (2)
}
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;
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);
+}
.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->pending_move_resize.configure_serial = 0;
}
}
+ ssd_update_geometry(view);
damage_view_part(view);
}
{
struct view *view = wl_container_of(listener, view, destroy);
wl_list_remove(&view->link);
+ ssd_destroy(view);
free(view);
}
} 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);
}
}
{
view->x = x;
view->y = y;
+ ssd_update_geometry(view);
damage_all_outputs(view->server);
}
*/
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);
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->pending_move_resize.height - view->h;
view->pending_move_resize.update_y = false;
}
+ ssd_update_geometry(view);
damage_view_whole(view);
}
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);
}
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);
}
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);
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);