mirror of
https://github.com/labwc/labwc.git
synced 2025-11-03 09:01:51 -05:00
Add window resize indicator
This commit is contained in:
parent
c8321e3264
commit
58b33fb0c9
12 changed files with 296 additions and 0 deletions
|
|
@ -249,6 +249,22 @@ Therefore, where multiple objects of the same kind are required (for example
|
||||||
Specify the number of pixels to reserve at the edges of an output.
|
Specify the number of pixels to reserve at the edges of an output.
|
||||||
New, maximized and tiled windows will not be placed in these areas.
|
New, maximized and tiled windows will not be placed in these areas.
|
||||||
|
|
||||||
|
## RESIZE
|
||||||
|
|
||||||
|
*<resize><popupShow>* [Never|Always|Nonpixel]
|
||||||
|
Show a small indicator on top of the window when resizing or moving.
|
||||||
|
When the application sets size-hints (usually X11 terminal emulators),
|
||||||
|
the indicator will show the dimensions divided by size hints instead.
|
||||||
|
In the case of terminal emulators this usually means columns x rows.
|
||||||
|
|
||||||
|
The different values mean:
|
||||||
|
- *Never* Do not render the indicator
|
||||||
|
- *Always* Render the indicator while moving and resizing windows
|
||||||
|
- *Nonpixel* Only render the indicator during resize for windows using
|
||||||
|
size-hints
|
||||||
|
|
||||||
|
Default is Never.
|
||||||
|
|
||||||
## KEYBOARD
|
## KEYBOARD
|
||||||
|
|
||||||
*<keyboard><keybind key="">*
|
*<keyboard><keybind key="">*
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,9 @@
|
||||||
<screenEdgeStrength>20</screenEdgeStrength>
|
<screenEdgeStrength>20</screenEdgeStrength>
|
||||||
</resistance>
|
</resistance>
|
||||||
|
|
||||||
|
<!-- Show a simple resize and move indicator -->
|
||||||
|
<resize popupShow="Never" />
|
||||||
|
|
||||||
<focus>
|
<focus>
|
||||||
<followMouse>no</followMouse>
|
<followMouse>no</followMouse>
|
||||||
<followMouseRequiresMovement>yes</followMouseRequiresMovement>
|
<followMouseRequiresMovement>yes</followMouseRequiresMovement>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "common/buf.h"
|
#include "common/buf.h"
|
||||||
#include "common/font.h"
|
#include "common/font.h"
|
||||||
#include "config/libinput.h"
|
#include "config/libinput.h"
|
||||||
|
#include "resize_indicator.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
|
|
||||||
enum window_switcher_field_content {
|
enum window_switcher_field_content {
|
||||||
|
|
@ -78,6 +79,8 @@ struct rcxml {
|
||||||
int snap_edge_range;
|
int snap_edge_range;
|
||||||
bool snap_top_maximize;
|
bool snap_top_maximize;
|
||||||
|
|
||||||
|
enum resize_indicator_mode resize_indicator;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int popuptime;
|
int popuptime;
|
||||||
int min_nr_workspaces;
|
int min_nr_workspaces;
|
||||||
|
|
|
||||||
19
include/resize_indicator.h
Normal file
19
include/resize_indicator.h
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
#ifndef LABWC_RESIZE_INDICATOR_H
|
||||||
|
#define LABWC_RESIZE_INDICATOR_H
|
||||||
|
|
||||||
|
struct server;
|
||||||
|
struct view;
|
||||||
|
|
||||||
|
enum resize_indicator_mode {
|
||||||
|
LAB_RESIZE_INDICATOR_NEVER = 0,
|
||||||
|
LAB_RESIZE_INDICATOR_ALWAYS,
|
||||||
|
LAB_RESIZE_INDICATOR_NON_PIXEL
|
||||||
|
};
|
||||||
|
|
||||||
|
void resize_indicator_reconfigure(struct server *server);
|
||||||
|
void resize_indicator_show(struct view *view);
|
||||||
|
void resize_indicator_update(struct view *view);
|
||||||
|
void resize_indicator_hide(struct view *view);
|
||||||
|
|
||||||
|
#endif /* LABWC_RESIZE_INDICATOR_H */
|
||||||
|
|
@ -128,6 +128,13 @@ struct view {
|
||||||
struct wl_event_source *pending_configure_timeout;
|
struct wl_event_source *pending_configure_timeout;
|
||||||
|
|
||||||
struct ssd *ssd;
|
struct ssd *ssd;
|
||||||
|
struct resize_indicator {
|
||||||
|
int width, height;
|
||||||
|
struct wlr_scene_tree *tree;
|
||||||
|
struct wlr_scene_rect *border;
|
||||||
|
struct wlr_scene_rect *background;
|
||||||
|
struct scaled_font_buffer *text;
|
||||||
|
} resize_indicator;
|
||||||
|
|
||||||
struct foreign_toplevel {
|
struct foreign_toplevel {
|
||||||
struct wlr_foreign_toplevel_handle_v1 *handle;
|
struct wlr_foreign_toplevel_handle_v1 *handle;
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ font_extents(struct font *font, const char *string)
|
||||||
pango_extents_to_pixels(&rect, NULL);
|
pango_extents_to_pixels(&rect, NULL);
|
||||||
|
|
||||||
/* we put a 2 px edge on each side - because Openbox does it :) */
|
/* we put a 2 px edge on each side - because Openbox does it :) */
|
||||||
|
/* TODO: remove the 4 pixel addition and always do the padding by the caller */
|
||||||
rect.width += 4;
|
rect.width += 4;
|
||||||
|
|
||||||
cairo_destroy(c);
|
cairo_destroy(c);
|
||||||
|
|
|
||||||
|
|
@ -657,6 +657,16 @@ entry(xmlNode *node, char *nodename, char *content)
|
||||||
rc.workspace_config.popuptime = atoi(content);
|
rc.workspace_config.popuptime = atoi(content);
|
||||||
} else if (!strcasecmp(nodename, "number.desktops")) {
|
} else if (!strcasecmp(nodename, "number.desktops")) {
|
||||||
rc.workspace_config.min_nr_workspaces = MAX(1, atoi(content));
|
rc.workspace_config.min_nr_workspaces = MAX(1, atoi(content));
|
||||||
|
} else if (!strcasecmp(nodename, "popupShow.resize")) {
|
||||||
|
if (!strcasecmp(content, "Always")) {
|
||||||
|
rc.resize_indicator = LAB_RESIZE_INDICATOR_ALWAYS;
|
||||||
|
} else if (!strcasecmp(content, "Never")) {
|
||||||
|
rc.resize_indicator = LAB_RESIZE_INDICATOR_NEVER;
|
||||||
|
} else if (!strcasecmp(content, "Nonpixel")) {
|
||||||
|
rc.resize_indicator = LAB_RESIZE_INDICATOR_NON_PIXEL;
|
||||||
|
} else {
|
||||||
|
wlr_log(WLR_ERROR, "Invalid value for <resize popupShow />");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -806,6 +816,8 @@ rcxml_init(void)
|
||||||
rc.window_switcher.preview = true;
|
rc.window_switcher.preview = true;
|
||||||
rc.window_switcher.outlines = true;
|
rc.window_switcher.outlines = true;
|
||||||
|
|
||||||
|
rc.resize_indicator = LAB_RESIZE_INDICATOR_NEVER;
|
||||||
|
|
||||||
rc.workspace_config.popuptime = INT_MIN;
|
rc.workspace_config.popuptime = INT_MIN;
|
||||||
rc.workspace_config.min_nr_workspaces = 1;
|
rc.workspace_config.min_nr_workspaces = 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "regions.h"
|
#include "regions.h"
|
||||||
|
#include "resize_indicator.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
@ -96,6 +97,9 @@ interactive_begin(struct view *view, enum input_mode mode, uint32_t edges)
|
||||||
server->grab_y = seat->cursor->y;
|
server->grab_y = seat->cursor->y;
|
||||||
server->grab_box = geometry;
|
server->grab_box = geometry;
|
||||||
server->resize_edges = edges;
|
server->resize_edges = edges;
|
||||||
|
if (rc.resize_indicator) {
|
||||||
|
resize_indicator_show(view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if view was snapped to any edge */
|
/* Returns true if view was snapped to any edge */
|
||||||
|
|
@ -172,6 +176,7 @@ interactive_finish(struct view *view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resize_indicator_hide(view);
|
||||||
|
|
||||||
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;
|
||||||
|
|
@ -190,6 +195,7 @@ void
|
||||||
interactive_cancel(struct view *view)
|
interactive_cancel(struct view *view)
|
||||||
{
|
{
|
||||||
if (view->server->grabbed_view == view) {
|
if (view->server->grabbed_view == view) {
|
||||||
|
resize_indicator_hide(view);
|
||||||
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;
|
||||||
/* Update focus/cursor image */
|
/* Update focus/cursor image */
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "layers.h"
|
#include "layers.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "regions.h"
|
#include "regions.h"
|
||||||
|
#include "resize_indicator.h"
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "workspaces.h"
|
#include "workspaces.h"
|
||||||
|
|
@ -54,6 +55,7 @@ reload_config_and_theme(void)
|
||||||
menu_reconfigure(g_server);
|
menu_reconfigure(g_server);
|
||||||
seat_reconfigure(g_server);
|
seat_reconfigure(g_server);
|
||||||
regions_reconfigure(g_server);
|
regions_reconfigure(g_server);
|
||||||
|
resize_indicator_reconfigure(g_server);
|
||||||
kde_server_decoration_update_default();
|
kde_server_decoration_update_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
labwc_sources += files(
|
labwc_sources += files(
|
||||||
|
'resize_indicator.c',
|
||||||
'ssd.c',
|
'ssd.c',
|
||||||
'ssd_part.c',
|
'ssd_part.c',
|
||||||
'ssd_titlebar.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);
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "regions.h"
|
#include "regions.h"
|
||||||
|
#include "resize_indicator.h"
|
||||||
#include "ssd.h"
|
#include "ssd.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
#include "window-rules.h"
|
#include "window-rules.h"
|
||||||
|
|
@ -182,6 +183,9 @@ view_moved(struct view *view)
|
||||||
if (view->toplevel.handle) {
|
if (view->toplevel.handle) {
|
||||||
foreign_toplevel_update_outputs(view);
|
foreign_toplevel_update_outputs(view);
|
||||||
}
|
}
|
||||||
|
if (rc.resize_indicator && view->server->grabbed_view == view) {
|
||||||
|
resize_indicator_update(view);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue