mirror of
https://github.com/labwc/labwc.git
synced 2025-11-05 13:29:58 -05:00
Add window resize indicator
This commit is contained in:
parent
c8321e3264
commit
58b33fb0c9
12 changed files with 296 additions and 0 deletions
|
|
@ -1,4 +1,5 @@
|
|||
labwc_sources += files(
|
||||
'resize_indicator.c',
|
||||
'ssd.c',
|
||||
'ssd_part.c',
|
||||
'ssd_titlebar.c',
|
||||
|
|
|
|||
222
src/ssd/resize_indicator.c
Normal file
222
src/ssd/resize_indicator.c
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
#include <assert.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "common/scaled_font_buffer.h"
|
||||
#include "labwc.h"
|
||||
#include "resize_indicator.h"
|
||||
#include "view.h"
|
||||
|
||||
static void
|
||||
resize_indicator_reconfigure_view(struct resize_indicator *indicator)
|
||||
{
|
||||
assert(indicator->tree);
|
||||
|
||||
struct theme *theme = rc.theme;
|
||||
indicator->height = font_height(&rc.font_osd)
|
||||
+ 2 * theme->osd_window_switcher_padding
|
||||
+ 2 * theme->osd_border_width;
|
||||
|
||||
/* Static positions */
|
||||
wlr_scene_node_set_position(&indicator->background->node,
|
||||
theme->osd_border_width, theme->osd_border_width);
|
||||
|
||||
wlr_scene_node_set_position(&indicator->text->scene_buffer->node,
|
||||
theme->osd_border_width + theme->osd_window_switcher_padding,
|
||||
theme->osd_border_width + theme->osd_window_switcher_padding);
|
||||
|
||||
/* Colors */
|
||||
wlr_scene_rect_set_color(indicator->border, theme->osd_border_color);
|
||||
wlr_scene_rect_set_color(indicator->background, theme->osd_bg_color);
|
||||
}
|
||||
|
||||
static void
|
||||
resize_indicator_init(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
struct resize_indicator *indicator = &view->resize_indicator;
|
||||
assert(!indicator->tree);
|
||||
|
||||
indicator->tree = wlr_scene_tree_create(view->scene_tree);
|
||||
indicator->border = wlr_scene_rect_create(
|
||||
indicator->tree, 0, 0, rc.theme->osd_border_color);
|
||||
indicator->background = wlr_scene_rect_create(
|
||||
indicator->tree, 0, 0, rc.theme->osd_bg_color);
|
||||
indicator->text = scaled_font_buffer_create(indicator->tree);
|
||||
|
||||
wlr_scene_node_set_enabled(&indicator->tree->node, false);
|
||||
resize_indicator_reconfigure_view(indicator);
|
||||
}
|
||||
|
||||
static struct wlr_box
|
||||
get_size_hints(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
|
||||
struct wlr_box hints = { 0 };
|
||||
if (view->impl->fill_size_hints) {
|
||||
view->impl->fill_size_hints(view, &hints);
|
||||
}
|
||||
return hints;
|
||||
}
|
||||
|
||||
static bool
|
||||
wants_indicator(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
|
||||
if (rc.resize_indicator == LAB_RESIZE_INDICATOR_NON_PIXEL) {
|
||||
if (view->server->input_mode != LAB_INPUT_STATE_RESIZE) {
|
||||
return false;
|
||||
}
|
||||
struct wlr_box size_hints = get_size_hints(view);
|
||||
if (size_hints.width && size_hints.height) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return rc.resize_indicator == LAB_RESIZE_INDICATOR_ALWAYS;
|
||||
}
|
||||
|
||||
void
|
||||
resize_indicator_reconfigure(struct server *server)
|
||||
{
|
||||
struct view *view;
|
||||
wl_list_for_each(view, &server->views, link) {
|
||||
struct resize_indicator *indicator = &view->resize_indicator;
|
||||
if (indicator->tree) {
|
||||
resize_indicator_reconfigure_view(indicator);
|
||||
}
|
||||
if (view != server->grabbed_view) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This view is currently in an interactive move/resize operation */
|
||||
if (indicator->tree && indicator->tree->node.enabled) {
|
||||
/* Indicator was active while reloading the config */
|
||||
if (wants_indicator(view)) {
|
||||
/* Apply new font setting */
|
||||
resize_indicator_update(view);
|
||||
} else {
|
||||
/* Indicator was disabled in config */
|
||||
resize_indicator_hide(view);
|
||||
}
|
||||
} else if (wants_indicator(view)) {
|
||||
/* Indicator not yet active */
|
||||
resize_indicator_show(view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
resize_indicator_set_size(struct resize_indicator *indicator, int width)
|
||||
{
|
||||
assert(indicator->tree);
|
||||
|
||||
/* We are not using a width-cache-early-out here to allow for theme changes */
|
||||
indicator->width = width
|
||||
+ 2 * rc.theme->osd_window_switcher_padding
|
||||
+ 2 * rc.theme->osd_border_width;
|
||||
|
||||
wlr_scene_rect_set_size(indicator->border, indicator->width, indicator->height);
|
||||
wlr_scene_rect_set_size(indicator->background,
|
||||
indicator->width - 2 * rc.theme->osd_border_width,
|
||||
indicator->height - 2 * rc.theme->osd_border_width);
|
||||
}
|
||||
|
||||
void
|
||||
resize_indicator_show(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
|
||||
if (!wants_indicator(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct resize_indicator *indicator = &view->resize_indicator;
|
||||
if (!indicator->tree) {
|
||||
/* Lazy initialize */
|
||||
resize_indicator_init(view);
|
||||
}
|
||||
|
||||
wlr_scene_node_raise_to_top(&indicator->tree->node);
|
||||
wlr_scene_node_set_enabled(&indicator->tree->node, true);
|
||||
resize_indicator_update(view);
|
||||
}
|
||||
|
||||
void
|
||||
resize_indicator_update(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
assert(view == view->server->grabbed_view);
|
||||
|
||||
if (!wants_indicator(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct resize_indicator *indicator = &view->resize_indicator;
|
||||
if (!indicator->tree) {
|
||||
/*
|
||||
* Future-proofs this routine:
|
||||
*
|
||||
* This can only happen when either src/interactive.c
|
||||
* stops calling resize_indicator_show(), there is a
|
||||
* bug in this file or resize_indicator_reconfigure()
|
||||
* gets changed.
|
||||
*/
|
||||
wlr_log(WLR_INFO, "Warning: resize_indicator has to use a fallback path");
|
||||
resize_indicator_show(view);
|
||||
}
|
||||
|
||||
char text[32]; /* 12345 x 12345 would be 13 chars + 1 null byte */
|
||||
|
||||
switch (view->server->input_mode) {
|
||||
case LAB_INPUT_STATE_RESIZE:
|
||||
; /* works around "a label can only be part of a statement" */
|
||||
struct wlr_box size_hints = get_size_hints(view);
|
||||
snprintf(text, sizeof(text), "%d x %d",
|
||||
view->current.width / MAX(1, size_hints.width),
|
||||
view->current.height / MAX(1, size_hints.height));
|
||||
break;
|
||||
case LAB_INPUT_STATE_MOVE:
|
||||
; /* works around "a label can only be part of a statement" */
|
||||
struct border margin = ssd_get_margin(view->ssd);
|
||||
snprintf(text, sizeof(text), "%d , %d",
|
||||
view->current.x - margin.left,
|
||||
view->current.y - margin.top);
|
||||
break;
|
||||
default:
|
||||
wlr_log(WLR_ERROR, "Invalid input mode for indicator update %u",
|
||||
view->server->input_mode);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Let the indicator change width as required by the content */
|
||||
int width = font_width(&rc.font_osd, text);
|
||||
|
||||
/* font_extents() adds 4 pixels to the calculated width */
|
||||
width -= 4;
|
||||
|
||||
resize_indicator_set_size(indicator, width);
|
||||
|
||||
/* Center the indicator in the window */
|
||||
wlr_scene_node_set_position(&indicator->tree->node,
|
||||
(view->current.width - indicator->width) / 2,
|
||||
(view->current.height - indicator->height) / 2);
|
||||
|
||||
scaled_font_buffer_update(indicator->text, text, width, &rc.font_osd,
|
||||
rc.theme->osd_label_text_color, NULL /* const char *arrow */);
|
||||
}
|
||||
|
||||
void
|
||||
resize_indicator_hide(struct view *view)
|
||||
{
|
||||
assert(view);
|
||||
|
||||
struct resize_indicator *indicator = &view->resize_indicator;
|
||||
if (!indicator->tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_scene_node_set_enabled(&indicator->tree->node, false);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue