mirror of
https://github.com/labwc/labwc.git
synced 2025-10-31 22:25:34 -04:00
SnapToRegion: Add dynamic overlay
Either uses a half transparent single rect if running hardware accelerated or uses a solid struct multirect outline if not.
This commit is contained in:
parent
4edd67de17
commit
eb5c8cfdad
10 changed files with 88 additions and 45 deletions
|
|
@ -47,6 +47,7 @@
|
||||||
#include "cursor.h"
|
#include "cursor.h"
|
||||||
#include "config/keybind.h"
|
#include "config/keybind.h"
|
||||||
#include "config/rcxml.h"
|
#include "config/rcxml.h"
|
||||||
|
#include "regions.h"
|
||||||
#if HAVE_NLS
|
#if HAVE_NLS
|
||||||
#include <libintl.h>
|
#include <libintl.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
@ -156,7 +157,9 @@ struct seat {
|
||||||
struct wlr_scene_tree *icons;
|
struct wlr_scene_tree *icons;
|
||||||
} drag;
|
} drag;
|
||||||
|
|
||||||
struct wlr_scene_rect *region_overlay;
|
/* Private use by regions.c */
|
||||||
|
struct region *region_active;
|
||||||
|
struct region_overlay region_overlay;
|
||||||
|
|
||||||
struct wl_client *active_client_while_inhibited;
|
struct wl_client *active_client_while_inhibited;
|
||||||
struct wl_list inputs;
|
struct wl_list inputs;
|
||||||
|
|
@ -312,6 +315,7 @@ struct output {
|
||||||
struct wlr_box usable_area;
|
struct wlr_box usable_area;
|
||||||
|
|
||||||
struct wl_list regions; /* struct region.link */
|
struct wl_list regions; /* struct region.link */
|
||||||
|
struct wlr_box regions_usable_area;
|
||||||
|
|
||||||
struct lab_data_buffer *osd_buffer;
|
struct lab_data_buffer *osd_buffer;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,13 @@
|
||||||
#ifndef __LABWC_REGIONS_H
|
#ifndef __LABWC_REGIONS_H
|
||||||
#define __LABWC_REGIONS_H
|
#define __LABWC_REGIONS_H
|
||||||
|
|
||||||
//FIXME: ignore that there could be more than a single seat
|
|
||||||
|
|
||||||
struct seat;
|
struct seat;
|
||||||
struct view;
|
struct view;
|
||||||
struct server;
|
struct server;
|
||||||
struct output;
|
struct output;
|
||||||
struct wl_list;
|
struct wl_list;
|
||||||
struct wlr_box;
|
struct wlr_box;
|
||||||
|
struct multi_rect;
|
||||||
|
|
||||||
/* Double use: rcxml.c for config and output.c for usage */
|
/* Double use: rcxml.c for config and output.c for usage */
|
||||||
struct region {
|
struct region {
|
||||||
|
|
@ -23,17 +22,24 @@ struct region {
|
||||||
} center;
|
} center;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct region_overlay {
|
||||||
|
struct wlr_scene_tree *tree;
|
||||||
|
union {
|
||||||
|
struct wlr_scene_rect *overlay;
|
||||||
|
struct multi_rect *pixman_overlay;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/* Can be used as a cheap check to detect if there are any regions configured */
|
/* Can be used as a cheap check to detect if there are any regions configured */
|
||||||
bool regions_available(void);
|
bool regions_available(void);
|
||||||
|
|
||||||
void regions_init(struct server *server, struct seat *seat);
|
|
||||||
void regions_update(struct output *output);
|
void regions_update(struct output *output);
|
||||||
void regions_evacuate_output(struct output *output);
|
void regions_evacuate_output(struct output *output);
|
||||||
void regions_destroy(struct wl_list *regions);
|
void regions_destroy(struct seat *seat, struct wl_list *regions);
|
||||||
|
|
||||||
struct region *regions_from_cursor(struct server *server);
|
struct region *regions_from_cursor(struct server *server);
|
||||||
struct region *regions_from_name(const char *region_name, struct output *output);
|
struct region *regions_from_name(const char *region_name, struct output *output);
|
||||||
void regions_show_overlay(struct view *view, struct seat *seat, struct region *region);
|
void regions_show_overlay(struct view *view, struct seat *seat, struct region *region);
|
||||||
void regions_hide_overlay(struct server *server, struct seat *seat);
|
void regions_hide_overlay(struct seat *seat);
|
||||||
|
|
||||||
#endif /* __LABWC_REGIONS_H */
|
#endif /* __LABWC_REGIONS_H */
|
||||||
|
|
|
||||||
|
|
@ -868,7 +868,7 @@ rcxml_finish(void)
|
||||||
zfree(w);
|
zfree(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
regions_destroy(&rc.regions);
|
regions_destroy(NULL, &rc.regions);
|
||||||
|
|
||||||
/* Reset state vars for starting fresh when Reload is triggered */
|
/* Reset state vars for starting fresh when Reload is triggered */
|
||||||
current_keybind = NULL;
|
current_keybind = NULL;
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ process_cursor_move(struct server *server, uint32_t time)
|
||||||
if (region) {
|
if (region) {
|
||||||
regions_show_overlay(view, &server->seat, region);
|
regions_show_overlay(view, &server->seat, region);
|
||||||
} else {
|
} else {
|
||||||
regions_hide_overlay(server, &server->seat);
|
regions_hide_overlay(&server->seat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ interactive_finish(struct view *view)
|
||||||
{
|
{
|
||||||
if (view->server->grabbed_view == view) {
|
if (view->server->grabbed_view == view) {
|
||||||
enum input_mode mode = view->server->input_mode;
|
enum input_mode mode = view->server->input_mode;
|
||||||
regions_hide_overlay(view->server, &view->server->seat);
|
regions_hide_overlay(&view->server->seat);
|
||||||
view->server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
|
view->server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
|
||||||
view->server->grabbed_view = NULL;
|
view->server->grabbed_view = NULL;
|
||||||
if (mode == LAB_INPUT_STATE_MOVE) {
|
if (mode == LAB_INPUT_STATE_MOVE) {
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ keyboard_modifiers_notify(struct wl_listener *listener, void *data)
|
||||||
workspaces_osd_hide(seat);
|
workspaces_osd_hide(seat);
|
||||||
}
|
}
|
||||||
if (server->grabbed_view) {
|
if (server->grabbed_view) {
|
||||||
regions_hide_overlay(server, seat);
|
regions_hide_overlay(seat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ output_destroy_notify(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
struct output *output = wl_container_of(listener, output, destroy);
|
struct output *output = wl_container_of(listener, output, destroy);
|
||||||
regions_evacuate_output(output);
|
regions_evacuate_output(output);
|
||||||
regions_destroy(&output->regions);
|
regions_destroy(&output->server->seat, &output->regions);
|
||||||
wl_list_remove(&output->link);
|
wl_list_remove(&output->link);
|
||||||
wl_list_remove(&output->frame.link);
|
wl_list_remove(&output->frame.link);
|
||||||
wl_list_remove(&output->destroy.link);
|
wl_list_remove(&output->destroy.link);
|
||||||
|
|
|
||||||
|
|
@ -22,22 +22,30 @@ regions_available(void)
|
||||||
return !wl_list_empty(&rc.regions);
|
return !wl_list_empty(&rc.regions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
regions_init(struct server *server, struct seat *seat)
|
overlay_create(struct seat *seat)
|
||||||
{
|
{
|
||||||
assert(server);
|
assert(!seat->region_overlay.tree);
|
||||||
assert(seat);
|
|
||||||
|
|
||||||
float *color;
|
struct server *server = seat->server;
|
||||||
float solid[4] = { 0.5, 0.5, 0.7, 1 };
|
struct wlr_scene_tree *parent = wlr_scene_tree_create(&server->scene->tree);
|
||||||
float trans[4] = { 0.25, 0.25, 0.35, 0.5 };
|
|
||||||
if (wlr_renderer_is_pixman(server->renderer)) {
|
seat->region_overlay.tree = parent;
|
||||||
color = solid;
|
wlr_scene_node_set_enabled(&parent->node, false);
|
||||||
|
if (!wlr_renderer_is_pixman(server->renderer)) {
|
||||||
|
/* Hardware assisted rendering: Half transparent overlay */
|
||||||
|
float color[4] = { 0.25, 0.25, 0.35, 0.5 };
|
||||||
|
seat->region_overlay.overlay = wlr_scene_rect_create(parent, 0, 0, color);
|
||||||
} else {
|
} else {
|
||||||
color = trans;
|
/* Software rendering: Outlines */
|
||||||
|
int line_width = server->theme->osd_border_width;
|
||||||
|
float *colors[3] = {
|
||||||
|
server->theme->osd_bg_color,
|
||||||
|
server->theme->osd_label_text_color,
|
||||||
|
server->theme->osd_bg_color
|
||||||
|
};
|
||||||
|
seat->region_overlay.pixman_overlay = multi_rect_create(parent, colors, line_width);
|
||||||
}
|
}
|
||||||
seat->region_overlay = wlr_scene_rect_create(&server->scene->tree, 0, 0, color);
|
|
||||||
wlr_scene_node_set_enabled(&seat->region_overlay->node, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct region *
|
struct region *
|
||||||
|
|
@ -91,36 +99,53 @@ regions_show_overlay(struct view *view, struct seat *seat, struct region *region
|
||||||
assert(view);
|
assert(view);
|
||||||
assert(seat);
|
assert(seat);
|
||||||
assert(region);
|
assert(region);
|
||||||
static struct region *old_region;
|
|
||||||
|
|
||||||
struct wlr_scene_rect *overlay = seat->region_overlay;
|
/* Don't show active region */
|
||||||
if (old_region != region) {
|
if (seat->region_active == region) {
|
||||||
wlr_scene_rect_set_size(overlay, region->geo.width, region->geo.height);
|
return;
|
||||||
wlr_scene_node_set_position(&overlay->node, region->geo.x, region->geo.y);
|
|
||||||
old_region = region;
|
|
||||||
}
|
}
|
||||||
if (overlay->node.parent != view->scene_tree->node.parent) {
|
|
||||||
wlr_scene_node_reparent(&overlay->node, view->scene_tree->node.parent);
|
if (!seat->region_overlay.tree) {
|
||||||
wlr_scene_node_place_below(&overlay->node, &view->scene_tree->node);
|
overlay_create(seat);
|
||||||
}
|
}
|
||||||
if (!overlay->node.enabled) {
|
|
||||||
wlr_scene_node_set_enabled(&overlay->node, true);
|
/* Update overlay */
|
||||||
|
struct server *server = seat->server;
|
||||||
|
struct wlr_scene_node *node = &seat->region_overlay.tree->node;
|
||||||
|
if (!wlr_renderer_is_pixman(server->renderer)) {
|
||||||
|
/* Hardware assisted rendering: Half transparent overlay */
|
||||||
|
wlr_scene_rect_set_size(seat->region_overlay.overlay,
|
||||||
|
region->geo.width, region->geo.height);
|
||||||
|
} else {
|
||||||
|
/* Software rendering: Outlines */
|
||||||
|
multi_rect_set_size(seat->region_overlay.pixman_overlay,
|
||||||
|
region->geo.width, region->geo.height);
|
||||||
}
|
}
|
||||||
|
if (node->parent != 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_set_position(node, region->geo.x, region->geo.y);
|
||||||
|
wlr_scene_node_set_enabled(node, true);
|
||||||
|
seat->region_active = region;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
regions_hide_overlay(struct server *server, struct seat *seat)
|
regions_hide_overlay(struct seat *seat)
|
||||||
{
|
{
|
||||||
assert(server);
|
|
||||||
assert(seat);
|
assert(seat);
|
||||||
|
if (!seat->region_active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
struct wlr_scene_rect *overlay = seat->region_overlay;
|
struct server *server = seat->server;
|
||||||
if (overlay->node.enabled) {
|
struct wlr_scene_node *node = &seat->region_overlay.tree->node;
|
||||||
wlr_scene_node_set_enabled(&overlay->node, false);
|
|
||||||
}
|
wlr_scene_node_set_enabled(node, false);
|
||||||
if (overlay->node.parent != &server->scene->tree) {
|
if (node->parent != &server->scene->tree) {
|
||||||
wlr_scene_node_reparent(&overlay->node, &server->scene->tree);
|
wlr_scene_node_reparent(node, &server->scene->tree);
|
||||||
}
|
}
|
||||||
|
seat->region_active = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -142,6 +167,12 @@ regions_update(struct output *output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wlr_box_equal(&output->regions_usable_area, &usable)) {
|
||||||
|
/* Nothing changed */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
output->regions_usable_area = usable;
|
||||||
|
|
||||||
/* Update regions */
|
/* Update regions */
|
||||||
struct wlr_box *perc, *geo;
|
struct wlr_box *perc, *geo;
|
||||||
wl_list_for_each(region, &output->regions, link) {
|
wl_list_for_each(region, &output->regions, link) {
|
||||||
|
|
@ -177,13 +208,16 @@ regions_evacuate_output(struct output *output)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
regions_destroy(struct wl_list *regions)
|
regions_destroy(struct seat *seat, struct wl_list *regions)
|
||||||
{
|
{
|
||||||
assert(regions);
|
assert(regions);
|
||||||
struct region *region, *region_tmp;
|
struct region *region, *region_tmp;
|
||||||
wl_list_for_each_safe(region, region_tmp, regions, link) {
|
wl_list_for_each_safe(region, region_tmp, regions, link) {
|
||||||
wl_list_remove(®ion->link);
|
wl_list_remove(®ion->link);
|
||||||
zfree(region->name);
|
zfree(region->name);
|
||||||
|
if (seat && seat->region_active == region) {
|
||||||
|
seat->region_active = NULL;
|
||||||
|
}
|
||||||
zfree(region);
|
zfree(region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "layers.h"
|
#include "layers.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "regions.h"
|
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "workspaces.h"
|
#include "workspaces.h"
|
||||||
|
|
@ -389,7 +388,6 @@ server_init(struct server *server)
|
||||||
&server->output_power_manager_set_mode);
|
&server->output_power_manager_set_mode);
|
||||||
|
|
||||||
layers_init(server);
|
layers_init(server);
|
||||||
regions_init(server, &server->seat);
|
|
||||||
|
|
||||||
#if HAVE_XWAYLAND
|
#if HAVE_XWAYLAND
|
||||||
xwayland_server_init(server, compositor);
|
xwayland_server_init(server, compositor);
|
||||||
|
|
|
||||||
|
|
@ -993,6 +993,7 @@ view_destroy(struct view *view)
|
||||||
server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
|
server->input_mode = LAB_INPUT_STATE_PASSTHROUGH;
|
||||||
server->grabbed_view = NULL;
|
server->grabbed_view = NULL;
|
||||||
need_cursor_update = true;
|
need_cursor_update = true;
|
||||||
|
regions_hide_overlay(&server->seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->focused_view == view) {
|
if (server->focused_view == view) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue