mirror of
https://github.com/labwc/labwc.git
synced 2026-04-12 08:21:13 -04:00
ssd: scale titlebar buttons to fit for very small views
This commit is contained in:
parent
a75301dae5
commit
a7f9680cda
6 changed files with 132 additions and 62 deletions
|
|
@ -65,6 +65,7 @@ struct ssd {
|
||||||
/* The top of the view, containing buttons, title, .. */
|
/* The top of the view, containing buttons, title, .. */
|
||||||
struct {
|
struct {
|
||||||
int height;
|
int height;
|
||||||
|
int button_width;
|
||||||
struct wlr_scene_tree *tree;
|
struct wlr_scene_tree *tree;
|
||||||
struct ssd_sub_tree active;
|
struct ssd_sub_tree active;
|
||||||
struct ssd_sub_tree inactive;
|
struct ssd_sub_tree inactive;
|
||||||
|
|
@ -129,15 +130,15 @@ struct ssd_part *add_scene_button(
|
||||||
struct wl_list *part_list, enum ssd_part_type type,
|
struct wl_list *part_list, enum ssd_part_type type,
|
||||||
struct wlr_scene_tree *parent, float *bg_color,
|
struct wlr_scene_tree *parent, float *bg_color,
|
||||||
struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer,
|
struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer,
|
||||||
int x, struct view *view);
|
int x, int width, struct view *view);
|
||||||
void add_toggled_icon(struct ssd_button *button, struct wl_list *part_list,
|
void add_toggled_icon(struct ssd_button *button, struct wl_list *part_list,
|
||||||
enum ssd_part_type type, struct wlr_buffer *icon_buffer,
|
enum ssd_part_type type, struct wlr_buffer *icon_buffer,
|
||||||
struct wlr_buffer *hover_buffer);
|
struct wlr_buffer *hover_buffer, int width);
|
||||||
struct ssd_part *add_scene_button_corner(
|
struct ssd_part *add_scene_button_corner(
|
||||||
struct wl_list *part_list, enum ssd_part_type type,
|
struct wl_list *part_list, enum ssd_part_type type,
|
||||||
enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
|
enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
|
||||||
struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
|
struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
|
||||||
struct wlr_buffer *hover_buffer, int x, struct view *view);
|
struct wlr_buffer *hover_buffer, int x, int width, struct view *view);
|
||||||
|
|
||||||
/* SSD internal helpers */
|
/* SSD internal helpers */
|
||||||
struct ssd_part *ssd_get_part(
|
struct ssd_part *ssd_get_part(
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ ssd_border_create(struct ssd *ssd)
|
||||||
int width = view->current.width;
|
int width = view->current.width;
|
||||||
int height = view_effective_height(view, /* use_pending */ false);
|
int height = view_effective_height(view, /* use_pending */ false);
|
||||||
int full_width = width + 2 * theme->border_width;
|
int full_width = width + 2 * theme->border_width;
|
||||||
|
int button_width = ssd->titlebar.button_width;
|
||||||
|
|
||||||
float *color;
|
float *color;
|
||||||
struct wlr_scene_tree *parent;
|
struct wlr_scene_tree *parent;
|
||||||
|
|
@ -48,8 +49,8 @@ ssd_border_create(struct ssd *ssd)
|
||||||
add_scene_rect(&subtree->parts, LAB_SSD_PART_BOTTOM, parent,
|
add_scene_rect(&subtree->parts, LAB_SSD_PART_BOTTOM, parent,
|
||||||
full_width, theme->border_width, 0, height, color);
|
full_width, theme->border_width, 0, height, color);
|
||||||
add_scene_rect(&subtree->parts, LAB_SSD_PART_TOP, parent,
|
add_scene_rect(&subtree->parts, LAB_SSD_PART_TOP, parent,
|
||||||
width - 2 * theme->window_button_width, theme->border_width,
|
width - 2 * button_width, theme->border_width,
|
||||||
theme->border_width + theme->window_button_width,
|
theme->border_width + button_width,
|
||||||
-(ssd->titlebar.height + theme->border_width), color);
|
-(ssd->titlebar.height + theme->border_width), color);
|
||||||
} FOR_EACH_END
|
} FOR_EACH_END
|
||||||
|
|
||||||
|
|
@ -93,6 +94,7 @@ ssd_border_update(struct ssd *ssd)
|
||||||
int width = view->current.width;
|
int width = view->current.width;
|
||||||
int height = view_effective_height(view, /* use_pending */ false);
|
int height = view_effective_height(view, /* use_pending */ false);
|
||||||
int full_width = width + 2 * theme->border_width;
|
int full_width = width + 2 * theme->border_width;
|
||||||
|
int button_width = ssd->titlebar.button_width;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From here on we have to cover the following border scenarios:
|
* From here on we have to cover the following border scenarios:
|
||||||
|
|
@ -121,10 +123,10 @@ ssd_border_update(struct ssd *ssd)
|
||||||
: 0;
|
: 0;
|
||||||
int top_width = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized
|
int top_width = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized
|
||||||
? full_width
|
? full_width
|
||||||
: width - 2 * theme->window_button_width;
|
: width - 2 * button_width;
|
||||||
int top_x = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized
|
int top_x = ssd->titlebar.height <= 0 || ssd->state.was_tiled_not_maximized
|
||||||
? 0
|
? 0
|
||||||
: theme->border_width + theme->window_button_width;
|
: theme->border_width + button_width;
|
||||||
|
|
||||||
struct ssd_part *part;
|
struct ssd_part *part;
|
||||||
struct wlr_scene_rect *rect;
|
struct wlr_scene_rect *rect;
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ ssd_extents_create(struct ssd *ssd)
|
||||||
struct theme *theme = view->server->theme;
|
struct theme *theme = view->server->theme;
|
||||||
struct wl_list *part_list = &ssd->extents.parts;
|
struct wl_list *part_list = &ssd->extents.parts;
|
||||||
int extended_area = SSD_EXTENDED_AREA;
|
int extended_area = SSD_EXTENDED_AREA;
|
||||||
int corner_size = extended_area + theme->border_width +
|
int corner_size = extended_area + theme->border_width
|
||||||
theme->window_button_width / 2;
|
+ ssd->titlebar.button_width / 2;
|
||||||
|
|
||||||
ssd->extents.tree = wlr_scene_tree_create(ssd->tree);
|
ssd->extents.tree = wlr_scene_tree_create(ssd->tree);
|
||||||
struct wlr_scene_tree *parent = ssd->extents.tree;
|
struct wlr_scene_tree *parent = ssd->extents.tree;
|
||||||
|
|
@ -110,8 +110,8 @@ ssd_extents_update(struct ssd *ssd)
|
||||||
int full_height = height + theme->border_width * 2 + ssd->titlebar.height;
|
int full_height = height + theme->border_width * 2 + ssd->titlebar.height;
|
||||||
int full_width = width + 2 * theme->border_width;
|
int full_width = width + 2 * theme->border_width;
|
||||||
int extended_area = SSD_EXTENDED_AREA;
|
int extended_area = SSD_EXTENDED_AREA;
|
||||||
int corner_size = extended_area + theme->border_width +
|
int corner_size = extended_area + theme->border_width
|
||||||
theme->window_button_width / 2;
|
+ ssd->titlebar.button_width / 2;
|
||||||
int side_width = full_width + extended_area * 2 - corner_size * 2;
|
int side_width = full_width + extended_area * 2 - corner_size * 2;
|
||||||
int side_height = full_height + extended_area * 2 - corner_size * 2;
|
int side_height = full_height + extended_area * 2 - corner_size * 2;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ struct ssd_part *
|
||||||
add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type,
|
add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
|
enum ssd_part_type corner_type, struct wlr_scene_tree *parent,
|
||||||
struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
|
struct wlr_buffer *corner_buffer, struct wlr_buffer *icon_buffer,
|
||||||
struct wlr_buffer *hover_buffer, int x, struct view *view)
|
struct wlr_buffer *hover_buffer, int x, int width, struct view *view)
|
||||||
{
|
{
|
||||||
int offset_x;
|
int offset_x;
|
||||||
float invisible[4] = { 0, 0, 0, 0 };
|
float invisible[4] = { 0, 0, 0, 0 };
|
||||||
|
|
@ -106,17 +106,29 @@ add_scene_button_corner(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
* Background, x and y adjusted for border_width which is
|
* Background, x and y adjusted for border_width which is
|
||||||
* already included in rendered theme.c / corner_buffer
|
* already included in rendered theme.c / corner_buffer
|
||||||
*/
|
*/
|
||||||
add_scene_buffer(part_list, corner_type, parent, corner_buffer,
|
struct ssd_part *corner_part =
|
||||||
-offset_x, -rc.theme->border_width);
|
add_scene_buffer(part_list, corner_type, parent, corner_buffer,
|
||||||
|
-offset_x, -rc.theme->border_width);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Scale down corner if needed for very small views. The
|
||||||
|
* rendering will not be perfect, but this is an abnormal case
|
||||||
|
* so we probably don't care.
|
||||||
|
*/
|
||||||
|
wlr_scene_buffer_set_dest_size(
|
||||||
|
wlr_scene_buffer_from_node(corner_part->node),
|
||||||
|
width + rc.theme->border_width,
|
||||||
|
rc.theme->title_height + rc.theme->border_width);
|
||||||
|
|
||||||
/* Finally just put a usual theme button on top, using an invisible hitbox */
|
/* Finally just put a usual theme button on top, using an invisible hitbox */
|
||||||
add_scene_button(part_list, type, parent, invisible, icon_buffer, hover_buffer, 0, view);
|
add_scene_button(part_list, type, parent, invisible, icon_buffer,
|
||||||
|
hover_buffer, 0, width, view);
|
||||||
return button_root;
|
return button_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_box
|
static struct wlr_box
|
||||||
get_scale_box(struct wlr_buffer *buffer, double container_width,
|
get_scale_box(struct wlr_buffer *buffer, double container_width,
|
||||||
double container_height)
|
double container_height, double max_scale)
|
||||||
{
|
{
|
||||||
struct wlr_box icon_geo = {
|
struct wlr_box icon_geo = {
|
||||||
.width = buffer->width,
|
.width = buffer->width,
|
||||||
|
|
@ -127,6 +139,7 @@ get_scale_box(struct wlr_buffer *buffer, double container_width,
|
||||||
if (icon_geo.width && icon_geo.height) {
|
if (icon_geo.width && icon_geo.height) {
|
||||||
double scale = MIN(container_width / icon_geo.width,
|
double scale = MIN(container_width / icon_geo.width,
|
||||||
container_height / icon_geo.height);
|
container_height / icon_geo.height);
|
||||||
|
scale = MIN(scale, max_scale);
|
||||||
if (scale < 1.0f) {
|
if (scale < 1.0f) {
|
||||||
icon_geo.width = (double)icon_geo.width * scale;
|
icon_geo.width = (double)icon_geo.width * scale;
|
||||||
icon_geo.height = (double)icon_geo.height * scale;
|
icon_geo.height = (double)icon_geo.height * scale;
|
||||||
|
|
@ -144,7 +157,7 @@ struct ssd_part *
|
||||||
add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
struct wlr_scene_tree *parent, float *bg_color,
|
struct wlr_scene_tree *parent, float *bg_color,
|
||||||
struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer,
|
struct wlr_buffer *icon_buffer, struct wlr_buffer *hover_buffer,
|
||||||
int x, struct view *view)
|
int x, int width, struct view *view)
|
||||||
{
|
{
|
||||||
struct ssd_part *button_root = add_scene_part(part_list, type);
|
struct ssd_part *button_root = add_scene_part(part_list, type);
|
||||||
parent = wlr_scene_tree_create(parent);
|
parent = wlr_scene_tree_create(parent);
|
||||||
|
|
@ -153,13 +166,19 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
|
|
||||||
/* Background */
|
/* Background */
|
||||||
struct ssd_part *bg_rect = add_scene_rect(part_list, type, parent,
|
struct ssd_part *bg_rect = add_scene_rect(part_list, type, parent,
|
||||||
rc.theme->window_button_width, rc.theme->title_height, 0, 0,
|
width, rc.theme->title_height, 0, 0, bg_color);
|
||||||
bg_color);
|
|
||||||
|
|
||||||
/* Icon */
|
/* Icon */
|
||||||
struct wlr_scene_tree *icon_tree = wlr_scene_tree_create(parent);
|
struct wlr_scene_tree *icon_tree = wlr_scene_tree_create(parent);
|
||||||
|
/*
|
||||||
|
* Always scale icon down proportionally if the button is
|
||||||
|
* narrowed from the default (as for a very small view). The
|
||||||
|
* hover icon is already pre-rendered in a default-size buffer
|
||||||
|
* and so doesn't need this extra step.
|
||||||
|
*/
|
||||||
|
double max_icon_scale = (double)width / rc.theme->window_button_width;
|
||||||
struct wlr_box icon_geo = get_scale_box(icon_buffer,
|
struct wlr_box icon_geo = get_scale_box(icon_buffer,
|
||||||
rc.theme->window_button_width, rc.theme->title_height);
|
width, rc.theme->title_height, max_icon_scale);
|
||||||
struct ssd_part *icon_part = add_scene_buffer(part_list, type,
|
struct ssd_part *icon_part = add_scene_buffer(part_list, type,
|
||||||
icon_tree, icon_buffer, icon_geo.x, icon_geo.y);
|
icon_tree, icon_buffer, icon_geo.x, icon_geo.y);
|
||||||
|
|
||||||
|
|
@ -172,7 +191,7 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
struct wlr_scene_tree *hover_tree = wlr_scene_tree_create(parent);
|
struct wlr_scene_tree *hover_tree = wlr_scene_tree_create(parent);
|
||||||
wlr_scene_node_set_enabled(&hover_tree->node, false);
|
wlr_scene_node_set_enabled(&hover_tree->node, false);
|
||||||
struct wlr_box hover_geo = get_scale_box(hover_buffer,
|
struct wlr_box hover_geo = get_scale_box(hover_buffer,
|
||||||
rc.theme->window_button_width, rc.theme->title_height);
|
width, rc.theme->title_height, /*max_scale*/ 1.0);
|
||||||
struct ssd_part *hover_part = add_scene_buffer(part_list, type,
|
struct ssd_part *hover_part = add_scene_buffer(part_list, type,
|
||||||
hover_tree, hover_buffer, hover_geo.x, hover_geo.y);
|
hover_tree, hover_buffer, hover_geo.x, hover_geo.y);
|
||||||
|
|
||||||
|
|
@ -197,11 +216,18 @@ add_scene_button(struct wl_list *part_list, enum ssd_part_type type,
|
||||||
void
|
void
|
||||||
add_toggled_icon(struct ssd_button *button, struct wl_list *part_list,
|
add_toggled_icon(struct ssd_button *button, struct wl_list *part_list,
|
||||||
enum ssd_part_type type, struct wlr_buffer *icon_buffer,
|
enum ssd_part_type type, struct wlr_buffer *icon_buffer,
|
||||||
struct wlr_buffer *hover_buffer)
|
struct wlr_buffer *hover_buffer, int width)
|
||||||
{
|
{
|
||||||
/* Alternate icon */
|
/* Alternate icon */
|
||||||
|
/*
|
||||||
|
* Always scale icon down proportionally if the button is
|
||||||
|
* narrowed from the default (as for a very small view). The
|
||||||
|
* hover icon is already pre-rendered in a default-size buffer
|
||||||
|
* and so doesn't need this extra step.
|
||||||
|
*/
|
||||||
|
double max_icon_scale = (double)width / rc.theme->window_button_width;
|
||||||
struct wlr_box icon_geo = get_scale_box(icon_buffer,
|
struct wlr_box icon_geo = get_scale_box(icon_buffer,
|
||||||
rc.theme->window_button_width, rc.theme->title_height);
|
width, rc.theme->title_height, max_icon_scale);
|
||||||
|
|
||||||
struct ssd_part *alticon_part = add_scene_buffer(part_list, type,
|
struct ssd_part *alticon_part = add_scene_buffer(part_list, type,
|
||||||
button->icon_tree, icon_buffer, icon_geo.x, icon_geo.y);
|
button->icon_tree, icon_buffer, icon_geo.x, icon_geo.y);
|
||||||
|
|
@ -213,7 +239,7 @@ add_toggled_icon(struct ssd_button *button, struct wl_list *part_list,
|
||||||
wlr_scene_node_set_enabled(alticon_part->node, false);
|
wlr_scene_node_set_enabled(alticon_part->node, false);
|
||||||
|
|
||||||
struct wlr_box hover_geo = get_scale_box(hover_buffer,
|
struct wlr_box hover_geo = get_scale_box(hover_buffer,
|
||||||
rc.theme->window_button_width, rc.theme->title_height);
|
width, rc.theme->title_height, /*max_scale*/ 1.0);
|
||||||
struct ssd_part *althover_part = add_scene_buffer(part_list, type,
|
struct ssd_part *althover_part = add_scene_buffer(part_list, type,
|
||||||
button->hover_tree, hover_buffer, hover_geo.x, hover_geo.y);
|
button->hover_tree, hover_buffer, hover_geo.x, hover_geo.y);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ ssd_titlebar_create(struct ssd *ssd)
|
||||||
struct view *view = ssd->view;
|
struct view *view = ssd->view;
|
||||||
struct theme *theme = view->server->theme;
|
struct theme *theme = view->server->theme;
|
||||||
int width = view->current.width;
|
int width = view->current.width;
|
||||||
|
int button_width = ssd->titlebar.button_width;
|
||||||
|
|
||||||
float *color;
|
float *color;
|
||||||
struct wlr_scene_tree *parent;
|
struct wlr_scene_tree *parent;
|
||||||
|
|
@ -90,29 +91,30 @@ ssd_titlebar_create(struct ssd *ssd)
|
||||||
|
|
||||||
/* Title */
|
/* Title */
|
||||||
add_scene_rect(&subtree->parts, LAB_SSD_PART_TITLEBAR, parent,
|
add_scene_rect(&subtree->parts, LAB_SSD_PART_TITLEBAR, parent,
|
||||||
width - theme->window_button_width * SSD_BUTTON_COUNT,
|
width - button_width * SSD_BUTTON_COUNT, theme->title_height,
|
||||||
theme->title_height, theme->window_button_width, 0, color);
|
button_width, 0, color);
|
||||||
/* Buttons */
|
/* Buttons */
|
||||||
add_scene_button_corner(&subtree->parts,
|
add_scene_button_corner(&subtree->parts,
|
||||||
LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_CORNER_TOP_LEFT, parent,
|
LAB_SSD_BUTTON_WINDOW_MENU, LAB_SSD_PART_CORNER_TOP_LEFT,
|
||||||
corner_top_left, menu_button_unpressed, menu_button_hover, 0, view);
|
parent, corner_top_left, menu_button_unpressed,
|
||||||
|
menu_button_hover, 0, button_width, view);
|
||||||
add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent,
|
add_scene_button(&subtree->parts, LAB_SSD_BUTTON_ICONIFY, parent,
|
||||||
color, iconify_button_unpressed, iconify_button_hover,
|
color, iconify_button_unpressed, iconify_button_hover,
|
||||||
width - theme->window_button_width * 3, view);
|
width - button_width * 3, button_width, view);
|
||||||
|
|
||||||
/* Maximize button has an alternate state when maximized */
|
/* Maximize button has an alternate state when maximized */
|
||||||
struct ssd_part *btn_max_root = add_scene_button(
|
struct ssd_part *btn_max_root = add_scene_button(
|
||||||
&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent,
|
&subtree->parts, LAB_SSD_BUTTON_MAXIMIZE, parent,
|
||||||
color, maximize_button_unpressed, maximize_button_hover,
|
color, maximize_button_unpressed, maximize_button_hover,
|
||||||
width - theme->window_button_width * 2, view);
|
width - button_width * 2, button_width, view);
|
||||||
struct ssd_button *btn_max = node_ssd_button_from_node(btn_max_root->node);
|
struct ssd_button *btn_max = node_ssd_button_from_node(btn_max_root->node);
|
||||||
add_toggled_icon(btn_max, &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE,
|
add_toggled_icon(btn_max, &subtree->parts, LAB_SSD_BUTTON_MAXIMIZE,
|
||||||
restore_button_unpressed, restore_button_hover);
|
restore_button_unpressed, restore_button_hover, button_width);
|
||||||
|
|
||||||
add_scene_button_corner(&subtree->parts,
|
add_scene_button_corner(&subtree->parts,
|
||||||
LAB_SSD_BUTTON_CLOSE, LAB_SSD_PART_CORNER_TOP_RIGHT, parent,
|
LAB_SSD_BUTTON_CLOSE, LAB_SSD_PART_CORNER_TOP_RIGHT, parent,
|
||||||
corner_top_right, close_button_unpressed, close_button_hover,
|
corner_top_right, close_button_unpressed, close_button_hover,
|
||||||
width - theme->window_button_width * 1, view);
|
width - button_width * 1, button_width, view);
|
||||||
} FOR_EACH_END
|
} FOR_EACH_END
|
||||||
|
|
||||||
ssd_update_title(ssd);
|
ssd_update_title(ssd);
|
||||||
|
|
@ -189,8 +191,9 @@ void
|
||||||
ssd_titlebar_update(struct ssd *ssd)
|
ssd_titlebar_update(struct ssd *ssd)
|
||||||
{
|
{
|
||||||
struct view *view = ssd->view;
|
struct view *view = ssd->view;
|
||||||
int width = view->current.width;
|
|
||||||
struct theme *theme = view->server->theme;
|
struct theme *theme = view->server->theme;
|
||||||
|
int width = view->current.width;
|
||||||
|
int button_width = ssd->titlebar.button_width;
|
||||||
|
|
||||||
bool maximized = view->maximized == VIEW_AXIS_BOTH;
|
bool maximized = view->maximized == VIEW_AXIS_BOTH;
|
||||||
bool tiled_not_maximized = view_is_tiled_and_notify_tiled(ssd->view)
|
bool tiled_not_maximized = view_is_tiled_and_notify_tiled(ssd->view)
|
||||||
|
|
@ -218,25 +221,25 @@ ssd_titlebar_update(struct ssd *ssd)
|
||||||
case LAB_SSD_PART_TITLEBAR:
|
case LAB_SSD_PART_TITLEBAR:
|
||||||
wlr_scene_rect_set_size(
|
wlr_scene_rect_set_size(
|
||||||
wlr_scene_rect_from_node(part->node),
|
wlr_scene_rect_from_node(part->node),
|
||||||
width - theme->window_button_width * SSD_BUTTON_COUNT,
|
width - button_width * SSD_BUTTON_COUNT,
|
||||||
theme->title_height);
|
theme->title_height);
|
||||||
continue;
|
continue;
|
||||||
case LAB_SSD_BUTTON_ICONIFY:
|
case LAB_SSD_BUTTON_ICONIFY:
|
||||||
if (is_direct_child(part->node, subtree)) {
|
if (is_direct_child(part->node, subtree)) {
|
||||||
wlr_scene_node_set_position(part->node,
|
wlr_scene_node_set_position(part->node,
|
||||||
width - theme->window_button_width * 3, 0);
|
width - button_width * 3, 0);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case LAB_SSD_BUTTON_MAXIMIZE:
|
case LAB_SSD_BUTTON_MAXIMIZE:
|
||||||
if (is_direct_child(part->node, subtree)) {
|
if (is_direct_child(part->node, subtree)) {
|
||||||
wlr_scene_node_set_position(part->node,
|
wlr_scene_node_set_position(part->node,
|
||||||
width - theme->window_button_width * 2, 0);
|
width - button_width * 2, 0);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
case LAB_SSD_PART_CORNER_TOP_RIGHT:
|
||||||
if (is_direct_child(part->node, subtree)) {
|
if (is_direct_child(part->node, subtree)) {
|
||||||
wlr_scene_node_set_position(part->node,
|
wlr_scene_node_set_position(part->node,
|
||||||
width - theme->window_button_width * 1, 0);
|
width - button_width * 1, 0);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
|
|
@ -270,6 +273,20 @@ ssd_titlebar_destroy(struct ssd *ssd)
|
||||||
ssd->titlebar.tree = NULL;
|
ssd->titlebar.tree = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_title_width(int view_width, int button_width)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Always return 0 if the button width is narrower than default.
|
||||||
|
* Simply computing (width - button_width * SSD_BUTTON_COUNT)
|
||||||
|
* gives undesired widths of 1 to (SSD_BUTTON_COUNT - 1) pixels
|
||||||
|
* due to rounding errors (since button_width is an integer).
|
||||||
|
*/
|
||||||
|
int theme_button_width = rc.theme->window_button_width;
|
||||||
|
return (button_width < theme_button_width) ? 0
|
||||||
|
: view_width - theme_button_width * SSD_BUTTON_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For ssd_update_title* we do not early out because
|
* For ssd_update_title* we do not early out because
|
||||||
* .active and .inactive may result in different sizes
|
* .active and .inactive may result in different sizes
|
||||||
|
|
@ -288,7 +305,8 @@ ssd_update_title_positions(struct ssd *ssd)
|
||||||
struct view *view = ssd->view;
|
struct view *view = ssd->view;
|
||||||
struct theme *theme = view->server->theme;
|
struct theme *theme = view->server->theme;
|
||||||
int width = view->current.width;
|
int width = view->current.width;
|
||||||
int title_bg_width = width - theme->window_button_width * SSD_BUTTON_COUNT;
|
int button_width = ssd->titlebar.button_width;
|
||||||
|
int title_bg_width = get_title_width(width, button_width);
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
int buffer_height, buffer_width;
|
int buffer_height, buffer_width;
|
||||||
|
|
@ -304,7 +322,7 @@ ssd_update_title_positions(struct ssd *ssd)
|
||||||
|
|
||||||
buffer_width = part->buffer ? part->buffer->width : 0;
|
buffer_width = part->buffer ? part->buffer->width : 0;
|
||||||
buffer_height = part->buffer ? part->buffer->height : 0;
|
buffer_height = part->buffer ? part->buffer->height : 0;
|
||||||
x = theme->window_button_width;
|
x = button_width;
|
||||||
y = (theme->title_height - buffer_height) / 2;
|
y = (theme->title_height - buffer_height) / 2;
|
||||||
|
|
||||||
if (title_bg_width <= 0) {
|
if (title_bg_width <= 0) {
|
||||||
|
|
@ -314,7 +332,7 @@ ssd_update_title_positions(struct ssd *ssd)
|
||||||
wlr_scene_node_set_enabled(part->node, true);
|
wlr_scene_node_set_enabled(part->node, true);
|
||||||
|
|
||||||
if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) {
|
if (theme->window_label_text_justify == LAB_JUSTIFY_CENTER) {
|
||||||
if (buffer_width + theme->window_button_width * 2 <= title_bg_width) {
|
if (buffer_width + button_width * 2 <= title_bg_width) {
|
||||||
/* Center based on the full width */
|
/* Center based on the full width */
|
||||||
x = (width - buffer_width) / 2;
|
x = (width - buffer_width) / 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -357,8 +375,8 @@ ssd_update_title(struct ssd *ssd)
|
||||||
struct ssd_part *part;
|
struct ssd_part *part;
|
||||||
struct ssd_sub_tree *subtree;
|
struct ssd_sub_tree *subtree;
|
||||||
struct ssd_state_title_width *dstate;
|
struct ssd_state_title_width *dstate;
|
||||||
int title_bg_width = view->current.width
|
int title_bg_width = get_title_width(view->current.width,
|
||||||
- theme->window_button_width * SSD_BUTTON_COUNT;
|
ssd->titlebar.button_width);
|
||||||
|
|
||||||
FOR_EACH_STATE(ssd, subtree) {
|
FOR_EACH_STATE(ssd, subtree) {
|
||||||
if (subtree == &ssd->titlebar.active) {
|
if (subtree == &ssd->titlebar.active) {
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,15 @@ ssd_resize_edges(enum ssd_part_type type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_button_width(int view_width)
|
||||||
|
{
|
||||||
|
/* view_width may be 0 if view isn't mapped yet */
|
||||||
|
int theme_button_width = rc.theme->window_button_width;
|
||||||
|
return (view_width > 0 && view_width < theme_button_width * SSD_BUTTON_COUNT)
|
||||||
|
? view_width / SSD_BUTTON_COUNT : theme_button_width;
|
||||||
|
}
|
||||||
|
|
||||||
struct ssd *
|
struct ssd *
|
||||||
ssd_create(struct view *view, bool active)
|
ssd_create(struct view *view, bool active)
|
||||||
{
|
{
|
||||||
|
|
@ -186,6 +195,7 @@ ssd_create(struct view *view, bool active)
|
||||||
ssd->tree = wlr_scene_tree_create(view->scene_tree);
|
ssd->tree = wlr_scene_tree_create(view->scene_tree);
|
||||||
wlr_scene_node_lower_to_bottom(&ssd->tree->node);
|
wlr_scene_node_lower_to_bottom(&ssd->tree->node);
|
||||||
ssd->titlebar.height = view->server->theme->title_height;
|
ssd->titlebar.height = view->server->theme->title_height;
|
||||||
|
ssd->titlebar.button_width = get_button_width(view->current.width);
|
||||||
ssd_shadow_create(ssd);
|
ssd_shadow_create(ssd);
|
||||||
ssd_extents_create(ssd);
|
ssd_extents_create(ssd);
|
||||||
/*
|
/*
|
||||||
|
|
@ -223,6 +233,21 @@ ssd_update_margin(struct ssd *ssd)
|
||||||
ssd->margin = ssd_thickness(ssd->view);
|
ssd->margin = ssd_thickness(ssd->view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clears pointers to this view's SSD from the global hover state.
|
||||||
|
* Must be called before the SSD or any buttons are destroyed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ssd_reset_hover_state(struct ssd *ssd)
|
||||||
|
{
|
||||||
|
struct ssd_hover_state *hover_state =
|
||||||
|
ssd->view->server->ssd_hover_state;
|
||||||
|
if (hover_state->view == ssd->view) {
|
||||||
|
hover_state->view = NULL;
|
||||||
|
hover_state->button = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ssd_update_geometry(struct ssd *ssd)
|
ssd_update_geometry(struct ssd *ssd)
|
||||||
{
|
{
|
||||||
|
|
@ -233,20 +258,9 @@ ssd_update_geometry(struct ssd *ssd)
|
||||||
struct wlr_box cached = ssd->state.geometry;
|
struct wlr_box cached = ssd->state.geometry;
|
||||||
struct wlr_box current = ssd->view->current;
|
struct wlr_box current = ssd->view->current;
|
||||||
|
|
||||||
int min_view_width = rc.theme->window_button_width * SSD_BUTTON_COUNT;
|
|
||||||
int eff_width = current.width;
|
int eff_width = current.width;
|
||||||
int eff_height = view_effective_height(ssd->view, /* use_pending */ false);
|
int eff_height = view_effective_height(ssd->view, /* use_pending */ false);
|
||||||
|
|
||||||
if (eff_width > 0 && eff_width < min_view_width) {
|
|
||||||
/*
|
|
||||||
* Prevent negative values in calculations like
|
|
||||||
* `width - SSD_BUTTON_WIDTH * SSD_BUTTON_COUNT`
|
|
||||||
*/
|
|
||||||
wlr_log(WLR_ERROR,
|
|
||||||
"view width is smaller than its minimal value");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eff_width == cached.width && eff_height == cached.height) {
|
if (eff_width == cached.width && eff_height == cached.height) {
|
||||||
if (current.x != cached.x || current.y != cached.y) {
|
if (current.x != cached.x || current.y != cached.y) {
|
||||||
/* Dynamically resize extents based on position and usable_area */
|
/* Dynamically resize extents based on position and usable_area */
|
||||||
|
|
@ -274,6 +288,22 @@ ssd_update_geometry(struct ssd *ssd)
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rather than resizing/re-rendering individual buttons and
|
||||||
|
* icons in ssd_titlebar_update(), it's simpler to just recreate
|
||||||
|
* them all. This case is only hit for abnormally small views,
|
||||||
|
* so it's probably not worth optimizing further.
|
||||||
|
*/
|
||||||
|
int button_width = get_button_width(current.width);
|
||||||
|
if (button_width != ssd->titlebar.button_width) {
|
||||||
|
/* Reset hover state before recreating buttons */
|
||||||
|
ssd_reset_hover_state(ssd);
|
||||||
|
ssd_titlebar_destroy(ssd);
|
||||||
|
ssd->titlebar.button_width = button_width;
|
||||||
|
ssd_titlebar_create(ssd);
|
||||||
|
}
|
||||||
|
|
||||||
ssd_extents_update(ssd);
|
ssd_extents_update(ssd);
|
||||||
ssd_titlebar_update(ssd);
|
ssd_titlebar_update(ssd);
|
||||||
ssd_border_update(ssd);
|
ssd_border_update(ssd);
|
||||||
|
|
@ -302,16 +332,9 @@ ssd_destroy(struct ssd *ssd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Maybe reset hover view */
|
|
||||||
struct view *view = ssd->view;
|
|
||||||
struct ssd_hover_state *hover_state;
|
|
||||||
hover_state = view->server->ssd_hover_state;
|
|
||||||
if (hover_state->view == view) {
|
|
||||||
hover_state->view = NULL;
|
|
||||||
hover_state->button = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy subcomponents */
|
/* Destroy subcomponents */
|
||||||
|
/* Reset hover state before destroying */
|
||||||
|
ssd_reset_hover_state(ssd);
|
||||||
ssd_titlebar_destroy(ssd);
|
ssd_titlebar_destroy(ssd);
|
||||||
ssd_border_destroy(ssd);
|
ssd_border_destroy(ssd);
|
||||||
ssd_extents_destroy(ssd);
|
ssd_extents_destroy(ssd);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue