overlay: add theme setting snapping.preview.[region|edge].fill

This settings allows user to choose whether to draw a filled rectangle
or an outlined rectangle as the preview for window snapping.
This commit is contained in:
tokyo4j 2024-04-14 02:24:36 +09:00
parent bc25b34340
commit b1ba2b841a
8 changed files with 114 additions and 36 deletions

View file

@ -195,6 +195,16 @@ elements are not listed here, but are supported.
Height of boxes in workspace switcher in pixels. Setting to 0 disables Height of boxes in workspace switcher in pixels. Setting to 0 disables
boxes. Default is 20. boxes. Default is 20.
*snapping.preview.region.fill* [yes|no]
Show a filled rectangle as the preview when a window is snapped to a region.
Otherwise, an outlined rectangle is shown instead.
If software rendering is used, an outlined rectangle is always shown.
*snapping.preview.edge.fill* [yes|no]
Show a filled rectangle as the preview when a window is snapped to an edge.
Otherwise, an outlined rectangle is shown instead.
If software rendering is used, an outlined rectangle is always shown.
*border.color* *border.color*
Set all border colors. This is obsolete, but supported for backward Set all border colors. This is obsolete, but supported for backward
compatibility as some themes still contain it. compatibility as some themes still contain it.

View file

@ -71,3 +71,6 @@ osd.window-switcher.item.active.border.width: 2
osd.workspace-switcher.boxes.width: 20 osd.workspace-switcher.boxes.width: 20
osd.workspace-switcher.boxes.height: 20 osd.workspace-switcher.boxes.height: 20
snapping.preview.region.fill: yes
snapping.preview.edge.fill: yes

View file

@ -7,12 +7,19 @@
#include "regions.h" #include "regions.h"
#include "view.h" #include "view.h"
struct overlay { struct overlay_rect {
struct wlr_scene_tree *tree; struct wlr_scene_node *node;
bool fill;
union { union {
struct wlr_scene_rect *rect; /* if fill is true */
struct wlr_scene_rect *scene_rect;
/* if fill is false */
struct multi_rect *pixman_rect; struct multi_rect *pixman_rect;
}; };
};
struct overlay {
struct overlay_rect region_rect, edge_rect;
/* Represents currently shown or delayed overlay */ /* Represents currently shown or delayed overlay */
struct { struct {
@ -28,6 +35,7 @@ struct overlay {
struct wl_event_source *timer; struct wl_event_source *timer;
}; };
void overlay_reconfigure(struct seat *seat);
/* Calls overlay_hide() internally if there's no overlay to show */ /* Calls overlay_hide() internally if there's no overlay to show */
void overlay_update(struct seat *seat); void overlay_update(struct seat *seat);
/* This function must be called when server->grabbed_view is destroyed */ /* This function must be called when server->grabbed_view is destroyed */

View file

@ -80,6 +80,9 @@ struct theme {
int osd_workspace_switcher_boxes_width; int osd_workspace_switcher_boxes_width;
int osd_workspace_switcher_boxes_height; int osd_workspace_switcher_boxes_height;
bool snapping_preview_region_fill;
bool snapping_preview_edge_fill;
/* textures */ /* textures */
struct lab_data_buffer *button_close_active_unpressed; struct lab_data_buffer *button_close_active_unpressed;
struct lab_data_buffer *button_maximize_active_unpressed; struct lab_data_buffer *button_maximize_active_unpressed;

View file

@ -18,6 +18,7 @@
#define IGNORE_SSD true #define IGNORE_SSD true
#define IGNORE_MENU true #define IGNORE_MENU true
#define IGNORE_OSD_PREVIEW_OUTLINE true #define IGNORE_OSD_PREVIEW_OUTLINE true
#define IGNORE_SNAPPING_PREVIEW_OUTLINE true
static struct view *last_view; static struct view *last_view;
@ -136,10 +137,15 @@ get_special(struct server *server, struct wlr_scene_node *node)
if (node == &server->seat.drag.icons->node) { if (node == &server->seat.drag.icons->node) {
return "seat->drag.icons"; return "seat->drag.icons";
} }
if (server->seat.overlay.tree if (server->seat.overlay.region_rect.node
&& node == &server->seat.overlay.tree->node) { && node == server->seat.overlay.region_rect.node) {
/* Created on-demand */ /* Created on-demand */
return "seat->overlay"; return "seat->overlay.region_rect";
}
if (server->seat.overlay.edge_rect.node
&& node == server->seat.overlay.edge_rect.node) {
/* Created on-demand */
return "seat->overlay.edge_rect";
} }
if (server->seat.input_method_relay->popup_tree if (server->seat.input_method_relay->popup_tree
&& node == &server->seat.input_method_relay->popup_tree->node) { && node == &server->seat.input_method_relay->popup_tree->node) {
@ -216,7 +222,13 @@ dump_tree(struct server *server, struct wlr_scene_node *node,
|| (IGNORE_SSD && last_view || (IGNORE_SSD && last_view
&& ssd_debug_is_root_node(last_view->ssd, node)) && ssd_debug_is_root_node(last_view->ssd, node))
|| (IGNORE_OSD_PREVIEW_OUTLINE && server->osd_state.preview_outline || (IGNORE_OSD_PREVIEW_OUTLINE && server->osd_state.preview_outline
&& node == &server->osd_state.preview_outline->tree->node)) { && node == &server->osd_state.preview_outline->tree->node)
|| (IGNORE_SNAPPING_PREVIEW_OUTLINE && server->seat.overlay.region_rect.node
&& !server->seat.overlay.region_rect.fill
&& node == server->seat.overlay.region_rect.node)
|| (IGNORE_SNAPPING_PREVIEW_OUTLINE && server->seat.overlay.edge_rect.node
&& !server->seat.overlay.edge_rect.fill
&& node == server->seat.overlay.edge_rect.node)) {
printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', "<skipping children>"); printf("%*c%s\n", pos + 4 + INDENT_SIZE, ' ', "<skipping children>");
return; return;
} }

View file

@ -6,52 +6,74 @@
#include "view.h" #include "view.h"
static void static void
create_overlay(struct seat *seat) create_overlay_rect(struct seat *seat, struct overlay_rect *rect, int fill)
{ {
assert(!seat->overlay.tree);
struct server *server = seat->server; struct server *server = seat->server;
struct wlr_scene_tree *parent = wlr_scene_tree_create(&server->scene->tree);
seat->overlay.tree = parent; rect->fill = fill;
wlr_scene_node_set_enabled(&parent->node, false); /* For pixman renderer, always render outlines to save CPU resource */
if (!wlr_renderer_is_pixman(server->renderer)) { if (wlr_renderer_is_pixman(server->renderer)) {
/* Hardware assisted rendering: Half transparent overlay, pre-multiplied */ rect->fill = false;
}
if (rect->fill) {
/* Create a filled rectangle */
float color[4] = { 0.25, 0.25, 0.35, 0.5 }; float color[4] = { 0.25, 0.25, 0.35, 0.5 };
seat->overlay.rect = wlr_scene_rect_create(parent, 0, 0, color); rect->scene_rect = wlr_scene_rect_create(&server->scene->tree,
0, 0, color);
rect->node = &rect->scene_rect->node;
} else { } else {
/* Software rendering: Outlines */ /* Create outlines */
int line_width = server->theme->osd_border_width; int line_width = server->theme->osd_border_width;
float *colors[3] = { float *colors[3] = {
server->theme->osd_bg_color, server->theme->osd_bg_color,
server->theme->osd_label_text_color, server->theme->osd_label_text_color,
server->theme->osd_bg_color server->theme->osd_bg_color
}; };
seat->overlay.pixman_rect = multi_rect_create(parent, colors, line_width); rect->pixman_rect = multi_rect_create(&server->scene->tree,
colors, line_width);
rect->node = &rect->pixman_rect->tree->node;
} }
wlr_scene_node_set_enabled(rect->node, false);
}
void overlay_reconfigure(struct seat *seat)
{
if (seat->overlay.region_rect.node) {
wlr_scene_node_destroy(seat->overlay.region_rect.node);
}
if (seat->overlay.edge_rect.node) {
wlr_scene_node_destroy(seat->overlay.edge_rect.node);
}
struct theme *theme = seat->server->theme;
create_overlay_rect(seat, &seat->overlay.region_rect,
theme->snapping_preview_region_fill);
create_overlay_rect(seat, &seat->overlay.edge_rect,
theme->snapping_preview_edge_fill);
} }
static void static void
show_overlay(struct seat *seat, struct wlr_box *box) show_overlay(struct seat *seat, struct overlay_rect *rect, struct wlr_box *box)
{ {
struct server *server = seat->server; struct server *server = seat->server;
struct view *view = server->grabbed_view; struct view *view = server->grabbed_view;
assert(view); assert(view);
struct wlr_scene_node *node = rect->node;
if (!seat->overlay.tree) { if (!node) {
create_overlay(seat); overlay_reconfigure(seat);
node = rect->node;
assert(node);
} }
struct wlr_scene_node *node = &seat->overlay.tree->node; if (rect->fill) {
if (!wlr_renderer_is_pixman(server->renderer)) { wlr_scene_rect_set_size(rect->scene_rect, box->width, box->height);
/* Hardware assisted rendering: Half transparent overlay */
wlr_scene_rect_set_size(seat->overlay.rect,
box->width, box->height);
} else { } else {
/* Software rendering: Outlines */ multi_rect_set_size(rect->pixman_rect, box->width, box->height);
multi_rect_set_size(seat->overlay.pixman_rect,
box->width, box->height);
} }
wlr_scene_node_reparent(node, view->scene_tree->node.parent); wlr_scene_node_reparent(node, view->scene_tree->node.parent);
wlr_scene_node_place_below(node, &view->scene_tree->node); wlr_scene_node_place_below(node, &view->scene_tree->node);
wlr_scene_node_set_position(node, box->x, box->y); wlr_scene_node_set_position(node, box->x, box->y);
@ -61,8 +83,13 @@ show_overlay(struct seat *seat, struct wlr_box *box)
static void static void
inactivate_overlay(struct overlay *overlay) inactivate_overlay(struct overlay *overlay)
{ {
if (overlay->tree) { if (overlay->region_rect.node) {
wlr_scene_node_set_enabled(&overlay->tree->node, false); wlr_scene_node_set_enabled(
overlay->region_rect.node, false);
}
if (overlay->edge_rect.node) {
wlr_scene_node_set_enabled(
overlay->edge_rect.node, false);
} }
overlay->active.region = NULL; overlay->active.region = NULL;
overlay->active.edge = VIEW_EDGE_INVALID; overlay->active.edge = VIEW_EDGE_INVALID;
@ -81,7 +108,7 @@ show_region_overlay(struct seat *seat, struct region *region)
inactivate_overlay(&seat->overlay); inactivate_overlay(&seat->overlay);
seat->overlay.active.region = region; seat->overlay.active.region = region;
show_overlay(seat, &region->geo); show_overlay(seat, &seat->overlay.region_rect, &region->geo);
} }
/* TODO: share logic with view_get_edge_snap_box() */ /* TODO: share logic with view_get_edge_snap_box() */
@ -119,7 +146,7 @@ handle_edge_overlay_timeout(void *data)
&& seat->overlay.active.output); && seat->overlay.active.output);
struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge, struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge,
seat->overlay.active.output); seat->overlay.active.output);
show_overlay(seat, &box); show_overlay(seat, &seat->overlay.edge_rect, &box);
return 0; return 0;
} }
@ -186,7 +213,7 @@ show_edge_overlay(struct seat *seat, enum view_edge edge,
/* Show overlay now */ /* Show overlay now */
struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge, struct wlr_box box = get_edge_snap_box(seat->overlay.active.edge,
seat->overlay.active.output); seat->overlay.active.output);
show_overlay(seat, &box); show_overlay(seat, &seat->overlay.edge_rect, &box);
} }
} }
@ -227,8 +254,12 @@ overlay_hide(struct seat *seat)
* Reparent the rectangle nodes to server's scene-tree so they don't * Reparent the rectangle nodes to server's scene-tree so they don't
* get destroyed on view destruction * get destroyed on view destruction
*/ */
if (seat->overlay.tree) { if (overlay->region_rect.node) {
wlr_scene_node_reparent(&overlay->tree->node, wlr_scene_node_reparent(overlay->region_rect.node,
&server->scene->tree);
}
if (overlay->edge_rect.node) {
wlr_scene_node_reparent(overlay->edge_rect.node,
&server->scene->tree); &server->scene->tree);
} }
} }

View file

@ -587,6 +587,7 @@ seat_reconfigure(struct server *server)
struct seat *seat = &server->seat; struct seat *seat = &server->seat;
struct input *input; struct input *input;
cursor_load(seat); cursor_load(seat);
overlay_reconfigure(seat);
wl_list_for_each(input, &seat->inputs, link) { wl_list_for_each(input, &seat->inputs, link) {
switch (input->wlr_input_device->type) { switch (input->wlr_input_device->type) {
case WLR_INPUT_DEVICE_KEYBOARD: case WLR_INPUT_DEVICE_KEYBOARD:

View file

@ -24,6 +24,7 @@
#include "common/graphic-helpers.h" #include "common/graphic-helpers.h"
#include "common/match.h" #include "common/match.h"
#include "common/mem.h" #include "common/mem.h"
#include "common/parse-bool.h"
#include "common/string-helpers.h" #include "common/string-helpers.h"
#include "config/rcxml.h" #include "config/rcxml.h"
#include "button/button-png.h" #include "button/button-png.h"
@ -520,6 +521,9 @@ theme_builtin(struct theme *theme)
theme->osd_border_width = INT_MIN; theme->osd_border_width = INT_MIN;
theme->osd_border_color[0] = FLT_MIN; theme->osd_border_color[0] = FLT_MIN;
theme->osd_label_text_color[0] = FLT_MIN; theme->osd_label_text_color[0] = FLT_MIN;
theme->snapping_preview_region_fill = true;
theme->snapping_preview_edge_fill = true;
} }
static void static void
@ -715,6 +719,12 @@ entry(struct theme *theme, const char *key, const char *value)
if (match_glob(key, "osd.label.text.color")) { if (match_glob(key, "osd.label.text.color")) {
parse_hexstr(value, theme->osd_label_text_color); parse_hexstr(value, theme->osd_label_text_color);
} }
if (match_glob(key, "snapping.preview.region.fill")) {
theme->snapping_preview_region_fill = parse_bool(value, true);
}
if (match_glob(key, "snapping.preview.edge.fill")) {
theme->snapping_preview_edge_fill = parse_bool(value, true);
}
} }
static void static void