mirror of
https://github.com/labwc/labwc.git
synced 2025-11-04 13:30:07 -05:00
view: account for base size in resize indicator
For views with a non-pixel size increment (e.g. X11 terminals), it's helpful to subtract the base size of the window (typically including menu bar, scrollbars, etc.) before computing the number of size increments (e.g. cells/characters). This way, the displayed size will exactly match the terminal grid (e.g. 80x25 or whatever). wlr_box isn't really the best fit for size hints, so let's define a struct view_size_hints and a nice view_get_size_hints() function, wrapping view->impl->get_size_hints(). This also seems like a great opportunity to make view_adjust_size() window-system-agnostic and eliminate xwayland_apply_size_hints().
This commit is contained in:
parent
48e0b3f6a6
commit
ce36cbac2d
5 changed files with 90 additions and 77 deletions
|
|
@ -37,6 +37,17 @@ enum view_edge {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct view;
|
struct view;
|
||||||
|
|
||||||
|
/* Basic size hints (subset of XSizeHints from X11) */
|
||||||
|
struct view_size_hints {
|
||||||
|
int min_width;
|
||||||
|
int min_height;
|
||||||
|
int width_inc;
|
||||||
|
int height_inc;
|
||||||
|
int base_width;
|
||||||
|
int base_height;
|
||||||
|
};
|
||||||
|
|
||||||
struct view_impl {
|
struct view_impl {
|
||||||
void (*configure)(struct view *view, struct wlr_box geo);
|
void (*configure)(struct view *view, struct wlr_box geo);
|
||||||
void (*close)(struct view *view);
|
void (*close)(struct view *view);
|
||||||
|
|
@ -57,7 +68,7 @@ struct view_impl {
|
||||||
void (*move_to_back)(struct view *view);
|
void (*move_to_back)(struct view *view);
|
||||||
struct view *(*get_root)(struct view *self);
|
struct view *(*get_root)(struct view *self);
|
||||||
void (*append_children)(struct view *self, struct wl_array *children);
|
void (*append_children)(struct view *self, struct wl_array *children);
|
||||||
void (*fill_size_hints)(struct view *self, struct wlr_box *box);
|
struct view_size_hints (*get_size_hints)(struct view *self);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct view {
|
struct view {
|
||||||
|
|
@ -306,6 +317,7 @@ void view_update_title(struct view *view);
|
||||||
void view_update_app_id(struct view *view);
|
void view_update_app_id(struct view *view);
|
||||||
void view_reload_ssd(struct view *view);
|
void view_reload_ssd(struct view *view);
|
||||||
|
|
||||||
|
struct view_size_hints view_get_size_hints(struct view *view);
|
||||||
void view_adjust_size(struct view *view, int *w, int *h);
|
void view_adjust_size(struct view *view, int *w, int *h);
|
||||||
|
|
||||||
void view_evacuate_region(struct view *view);
|
void view_evacuate_region(struct view *view);
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,6 @@ void xwayland_view_create(struct server *server,
|
||||||
|
|
||||||
struct wlr_xwayland_surface *xwayland_surface_from_view(struct view *view);
|
struct wlr_xwayland_surface *xwayland_surface_from_view(struct view *view);
|
||||||
|
|
||||||
bool xwayland_apply_size_hints(struct view *view, int *w, int *h);
|
|
||||||
|
|
||||||
void xwayland_server_init(struct server *server,
|
void xwayland_server_init(struct server *server,
|
||||||
struct wlr_compositor *compositor);
|
struct wlr_compositor *compositor);
|
||||||
void xwayland_server_finish(struct server *server);
|
void xwayland_server_finish(struct server *server);
|
||||||
|
|
|
||||||
|
|
@ -49,18 +49,6 @@ resize_indicator_init(struct view *view)
|
||||||
resize_indicator_reconfigure_view(indicator);
|
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
|
static bool
|
||||||
wants_indicator(struct view *view)
|
wants_indicator(struct view *view)
|
||||||
{
|
{
|
||||||
|
|
@ -70,8 +58,8 @@ wants_indicator(struct view *view)
|
||||||
if (view->server->input_mode != LAB_INPUT_STATE_RESIZE) {
|
if (view->server->input_mode != LAB_INPUT_STATE_RESIZE) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct wlr_box size_hints = get_size_hints(view);
|
struct view_size_hints hints = view_get_size_hints(view);
|
||||||
if (size_hints.width && size_hints.height) {
|
if (hints.width_inc && hints.height_inc) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,10 +161,12 @@ resize_indicator_update(struct view *view)
|
||||||
switch (view->server->input_mode) {
|
switch (view->server->input_mode) {
|
||||||
case LAB_INPUT_STATE_RESIZE:
|
case LAB_INPUT_STATE_RESIZE:
|
||||||
; /* works around "a label can only be part of a statement" */
|
; /* works around "a label can only be part of a statement" */
|
||||||
struct wlr_box size_hints = get_size_hints(view);
|
struct view_size_hints hints = view_get_size_hints(view);
|
||||||
snprintf(text, sizeof(text), "%d x %d",
|
snprintf(text, sizeof(text), "%d x %d",
|
||||||
view->current.width / MAX(1, size_hints.width),
|
MAX(0, view->current.width - hints.base_width)
|
||||||
view->current.height / MAX(1, size_hints.height));
|
/ MAX(1, hints.width_inc),
|
||||||
|
MAX(0, view->current.height - hints.base_height)
|
||||||
|
/ MAX(1, hints.height_inc));
|
||||||
break;
|
break;
|
||||||
case LAB_INPUT_STATE_MOVE:
|
case LAB_INPUT_STATE_MOVE:
|
||||||
; /* works around "a label can only be part of a statement" */
|
; /* works around "a label can only be part of a statement" */
|
||||||
|
|
|
||||||
64
src/view.c
64
src/view.c
|
|
@ -296,20 +296,68 @@ view_move_relative(struct view *view, int x, int y)
|
||||||
view_move(view, view->pending.x + x, view->pending.y + y);
|
view_move(view, view->pending.x + x, view->pending.y + y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct view_size_hints
|
||||||
|
view_get_size_hints(struct view *view)
|
||||||
|
{
|
||||||
|
if (view->impl->get_size_hints) {
|
||||||
|
return view->impl->get_size_hints(view);
|
||||||
|
}
|
||||||
|
return (struct view_size_hints){0};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
substitute_nonzero(int *a, int *b)
|
||||||
|
{
|
||||||
|
if (!(*a)) {
|
||||||
|
*a = *b;
|
||||||
|
} else if (!(*b)) {
|
||||||
|
*b = *a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
round_to_increment(int val, int base, int inc)
|
||||||
|
{
|
||||||
|
if (base < 0 || inc <= 0) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
return base + (val - base + inc / 2) / inc * inc;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
view_adjust_size(struct view *view, int *w, int *h)
|
view_adjust_size(struct view *view, int *w, int *h)
|
||||||
{
|
{
|
||||||
assert(view);
|
assert(view);
|
||||||
|
struct view_size_hints hints = view_get_size_hints(view);
|
||||||
|
|
||||||
#if HAVE_XWAYLAND
|
/*
|
||||||
if (xwayland_apply_size_hints(view, w, h)) {
|
* "If a base size is not provided, the minimum size is to be
|
||||||
/* We don't want to cap the size to keep the aspect ratio */
|
* used in its place and vice versa." (ICCCM 4.1.2.3)
|
||||||
return;
|
*/
|
||||||
|
substitute_nonzero(&hints.min_width, &hints.base_width);
|
||||||
|
substitute_nonzero(&hints.min_height, &hints.base_height);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Snap width/height to requested size increments (if any).
|
||||||
|
* Typically, terminal emulators use these to make sure that the
|
||||||
|
* terminal is resized to a width/height evenly divisible by the
|
||||||
|
* cell (character) size.
|
||||||
|
*/
|
||||||
|
*w = round_to_increment(*w, hints.base_width, hints.width_inc);
|
||||||
|
*h = round_to_increment(*h, hints.base_height, hints.height_inc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a minimum width/height was not set, then use default.
|
||||||
|
* This is currently always the case for xdg-shell views.
|
||||||
|
*/
|
||||||
|
if (hints.min_width < 1) {
|
||||||
|
hints.min_width = LAB_MIN_VIEW_WIDTH;
|
||||||
}
|
}
|
||||||
#endif
|
if (hints.min_height < 1) {
|
||||||
|
hints.min_height = LAB_MIN_VIEW_HEIGHT;
|
||||||
*w = MAX(*w, LAB_MIN_VIEW_WIDTH);
|
}
|
||||||
*h = MAX(*h, LAB_MIN_VIEW_HEIGHT);
|
*w = MAX(*w, hints.min_width);
|
||||||
|
*h = MAX(*h, hints.min_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -13,56 +13,21 @@
|
||||||
#include "workspaces.h"
|
#include "workspaces.h"
|
||||||
#include "xwayland.h"
|
#include "xwayland.h"
|
||||||
|
|
||||||
static int
|
static struct view_size_hints
|
||||||
round_to_increment(int val, int base, int inc)
|
xwayland_view_get_size_hints(struct view *view)
|
||||||
{
|
{
|
||||||
if (base < 0 || inc <= 0) {
|
xcb_size_hints_t *hints = xwayland_surface_from_view(view)->size_hints;
|
||||||
return val;
|
if (!hints) {
|
||||||
|
return (struct view_size_hints){0};
|
||||||
}
|
}
|
||||||
return base + (val - base + inc / 2) / inc * inc;
|
return (struct view_size_hints){
|
||||||
}
|
.min_width = hints->min_width,
|
||||||
|
.min_height = hints->min_height,
|
||||||
bool
|
.width_inc = hints->width_inc,
|
||||||
xwayland_apply_size_hints(struct view *view, int *w, int *h)
|
.height_inc = hints->height_inc,
|
||||||
{
|
.base_width = hints->base_width,
|
||||||
assert(view);
|
.base_height = hints->base_height,
|
||||||
if (view->type == LAB_XWAYLAND_VIEW) {
|
};
|
||||||
xcb_size_hints_t *hints =
|
|
||||||
xwayland_surface_from_view(view)->size_hints;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Honor size increments from WM_SIZE_HINTS. Typically, X11
|
|
||||||
* terminal emulators will use WM_SIZE_HINTS to make sure that
|
|
||||||
* the terminal is resized to a width/height evenly divisible by
|
|
||||||
* the cell (character) size.
|
|
||||||
*/
|
|
||||||
if (hints) {
|
|
||||||
*w = round_to_increment(*w, hints->base_width,
|
|
||||||
hints->width_inc);
|
|
||||||
*h = round_to_increment(*h, hints->base_height,
|
|
||||||
hints->height_inc);
|
|
||||||
|
|
||||||
*w = MAX(*w, MAX(1, hints->min_width));
|
|
||||||
*h = MAX(*h, MAX(1, hints->min_height));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xwayland_view_fill_size_hints(struct view *view, struct wlr_box *box)
|
|
||||||
{
|
|
||||||
if (view->type == LAB_XWAYLAND_VIEW) {
|
|
||||||
xcb_size_hints_t *hints = xwayland_surface_from_view(view)->size_hints;
|
|
||||||
if (hints) {
|
|
||||||
box->width = hints->width_inc;
|
|
||||||
box->height = hints->height_inc;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
box->width = 0;
|
|
||||||
box->height = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_xwayland_surface *
|
static struct wlr_xwayland_surface *
|
||||||
|
|
@ -669,7 +634,7 @@ static const struct view_impl xwayland_view_impl = {
|
||||||
.move_to_back = xwayland_view_move_to_back,
|
.move_to_back = xwayland_view_move_to_back,
|
||||||
.get_root = xwayland_view_get_root,
|
.get_root = xwayland_view_get_root,
|
||||||
.append_children = xwayland_view_append_children,
|
.append_children = xwayland_view_append_children,
|
||||||
.fill_size_hints = xwayland_view_fill_size_hints,
|
.get_size_hints = xwayland_view_get_size_hints,
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue