mirror of
https://github.com/swaywm/sway.git
synced 2026-04-25 06:46:24 -04:00
Don't use title content in size calculations
Make height configurable instead This prevents distracting screen flashing and seems to work fine for larger glyphs as well (Tested with Japanese). squashed: Free layout and buffer squashed: pass in markup information
This commit is contained in:
parent
9d6787d10d
commit
0e866013b6
15 changed files with 91 additions and 68 deletions
|
|
@ -82,6 +82,40 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void get_text_physical_size(cairo_t *cairo, const char *font, int* ascent, int* descent,
|
||||||
|
int* ink_size, bool markup, const char *fmt, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
// Add one since vsnprintf excludes null terminator.
|
||||||
|
int length = vsnprintf(NULL, 0, fmt, args) + 1;
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
char *buf = malloc(length);
|
||||||
|
if (buf == NULL) {
|
||||||
|
sway_log(SWAY_ERROR, "Failed to allocate memory");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(buf, length, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
PangoLayout *layout = get_pango_layout(cairo, font, buf, 1, markup);
|
||||||
|
pango_cairo_update_layout(cairo, layout);
|
||||||
|
PangoRectangle ir, lr;
|
||||||
|
pango_layout_get_pixel_extents(layout, &ir, &lr);
|
||||||
|
if (ascent) {
|
||||||
|
*ascent = PANGO_ASCENT(ir);
|
||||||
|
}
|
||||||
|
if (descent) {
|
||||||
|
*descent = PANGO_DESCENT(ir);
|
||||||
|
}
|
||||||
|
if (ink_size) {
|
||||||
|
*ink_size = ir.height;
|
||||||
|
}
|
||||||
|
g_object_unref(layout);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
|
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
|
||||||
int *baseline, double scale, bool markup, const char *fmt, ...) {
|
int *baseline, double scale, bool markup, const char *fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@
|
||||||
size_t escape_markup_text(const char *src, char *dest);
|
size_t escape_markup_text(const char *src, char *dest);
|
||||||
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
|
PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
|
||||||
const char *text, double scale, bool markup);
|
const char *text, double scale, bool markup);
|
||||||
|
void get_text_physical_size(cairo_t *cairo, const char *font, int *ascent, int* descent,
|
||||||
|
int *ink_size, bool markup, const char *fmt, ...);
|
||||||
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
|
void get_text_size(cairo_t *cairo, const char *font, int *width, int *height,
|
||||||
int *baseline, double scale, bool markup, const char *fmt, ...);
|
int *baseline, double scale, bool markup, const char *fmt, ...);
|
||||||
void pango_printf(cairo_t *cairo, const char *font,
|
void pango_printf(cairo_t *cairo, const char *font,
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,7 @@ sway_cmd cmd_tiling_drag_threshold;
|
||||||
sway_cmd cmd_title_align;
|
sway_cmd cmd_title_align;
|
||||||
sway_cmd cmd_title_format;
|
sway_cmd cmd_title_format;
|
||||||
sway_cmd cmd_titlebar_border_thickness;
|
sway_cmd cmd_titlebar_border_thickness;
|
||||||
|
sway_cmd cmd_titlebar_max_text_height;
|
||||||
sway_cmd cmd_titlebar_padding;
|
sway_cmd cmd_titlebar_padding;
|
||||||
sway_cmd cmd_unbindcode;
|
sway_cmd cmd_unbindcode;
|
||||||
sway_cmd cmd_unbindswitch;
|
sway_cmd cmd_unbindswitch;
|
||||||
|
|
|
||||||
|
|
@ -480,10 +480,9 @@ struct sway_config {
|
||||||
enum sway_container_layout default_orientation;
|
enum sway_container_layout default_orientation;
|
||||||
enum sway_container_layout default_layout;
|
enum sway_container_layout default_layout;
|
||||||
char *font;
|
char *font;
|
||||||
size_t font_height;
|
|
||||||
size_t font_baseline;
|
|
||||||
bool pango_markup;
|
bool pango_markup;
|
||||||
int titlebar_border_thickness;
|
int titlebar_border_thickness;
|
||||||
|
int titlebar_max_text_height;
|
||||||
int titlebar_h_padding;
|
int titlebar_h_padding;
|
||||||
int titlebar_v_padding;
|
int titlebar_v_padding;
|
||||||
size_t urgent_timeout;
|
size_t urgent_timeout;
|
||||||
|
|
@ -689,16 +688,6 @@ void free_bar_binding(struct bar_binding *binding);
|
||||||
|
|
||||||
void free_workspace_config(struct workspace_config *wsc);
|
void free_workspace_config(struct workspace_config *wsc);
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the value of config->font_height based on the max title height
|
|
||||||
* reported by each container. If recalculate is true, the containers will
|
|
||||||
* recalculate their heights before reporting.
|
|
||||||
*
|
|
||||||
* If the height has changed, all containers will be rearranged to take on the
|
|
||||||
* new size.
|
|
||||||
*/
|
|
||||||
void config_update_font_height(bool recalculate);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert bindsym into bindcode using the first configured layout.
|
* Convert bindsym into bindcode using the first configured layout.
|
||||||
* Return false in case the conversion is unsuccessful.
|
* Return false in case the conversion is unsuccessful.
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@ struct sway_container {
|
||||||
struct wlr_texture *title_unfocused;
|
struct wlr_texture *title_unfocused;
|
||||||
struct wlr_texture *title_urgent;
|
struct wlr_texture *title_urgent;
|
||||||
size_t title_height;
|
size_t title_height;
|
||||||
size_t title_baseline;
|
int title_ascent;
|
||||||
|
|
||||||
list_t *marks; // char *
|
list_t *marks; // char *
|
||||||
struct wlr_texture *marks_focused;
|
struct wlr_texture *marks_focused;
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ static struct cmd_handler handlers[] = {
|
||||||
{ "tiling_drag_threshold", cmd_tiling_drag_threshold },
|
{ "tiling_drag_threshold", cmd_tiling_drag_threshold },
|
||||||
{ "title_align", cmd_title_align },
|
{ "title_align", cmd_title_align },
|
||||||
{ "titlebar_border_thickness", cmd_titlebar_border_thickness },
|
{ "titlebar_border_thickness", cmd_titlebar_border_thickness },
|
||||||
|
{ "titlebar_max_text_height", cmd_titlebar_max_text_height },
|
||||||
{ "titlebar_padding", cmd_titlebar_padding },
|
{ "titlebar_padding", cmd_titlebar_padding },
|
||||||
{ "unbindcode", cmd_unbindcode },
|
{ "unbindcode", cmd_unbindcode },
|
||||||
{ "unbindswitch", cmd_unbindswitch },
|
{ "unbindswitch", cmd_unbindswitch },
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,5 @@ struct cmd_results *cmd_font(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
|
|
||||||
free(font);
|
free(font);
|
||||||
config_update_font_height(true);
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,6 @@ static void do_reload(void *data) {
|
||||||
}
|
}
|
||||||
list_free_items_and_destroy(bar_ids);
|
list_free_items_and_destroy(bar_ids);
|
||||||
|
|
||||||
config_update_font_height(true);
|
|
||||||
root_for_each_container(rebuild_textures_iterator, NULL);
|
root_for_each_container(rebuild_textures_iterator, NULL);
|
||||||
|
|
||||||
arrange_root();
|
arrange_root();
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,5 @@ struct cmd_results *cmd_title_format(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
view->title_format = format;
|
view->title_format = format;
|
||||||
view_update_title(view, true);
|
view_update_title(view, true);
|
||||||
config_update_font_height(true);
|
|
||||||
return cmd_results_new(CMD_SUCCESS, NULL);
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
sway/commands/titlebar_max_text_height.c
Normal file
29
sway/commands/titlebar_max_text_height.c
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include <string.h>
|
||||||
|
#include "sway/commands.h"
|
||||||
|
#include "sway/config.h"
|
||||||
|
#include "sway/output.h"
|
||||||
|
#include "sway/tree/arrange.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
struct cmd_results *cmd_titlebar_max_text_height(int argc, char **argv) {
|
||||||
|
struct cmd_results *error = NULL;
|
||||||
|
if ((error = checkarg(argc, "titlebar_max_text_height", EXPECTED_EQUAL_TO, 1))) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *inv;
|
||||||
|
int value = strtol(argv[0], &inv, 10);
|
||||||
|
if (*inv != '\0' || value < 0) {
|
||||||
|
return cmd_results_new(CMD_FAILURE, "Invalid size specified");
|
||||||
|
}
|
||||||
|
|
||||||
|
config->titlebar_max_text_height = value;
|
||||||
|
|
||||||
|
for (int i = 0; i < root->outputs->length; ++i) {
|
||||||
|
struct sway_output *output = root->outputs->items[i];
|
||||||
|
arrange_workspace(output_get_active_workspace(output));
|
||||||
|
output_damage_whole(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd_results_new(CMD_SUCCESS, NULL);
|
||||||
|
}
|
||||||
|
|
@ -236,13 +236,14 @@ static void config_defaults(struct sway_config *config) {
|
||||||
config->default_layout = L_NONE;
|
config->default_layout = L_NONE;
|
||||||
config->default_orientation = L_NONE;
|
config->default_orientation = L_NONE;
|
||||||
if (!(config->font = strdup("monospace 10"))) goto cleanup;
|
if (!(config->font = strdup("monospace 10"))) goto cleanup;
|
||||||
config->font_height = 17; // height of monospace 10
|
|
||||||
config->urgent_timeout = 500;
|
config->urgent_timeout = 500;
|
||||||
config->focus_on_window_activation = FOWA_URGENT;
|
config->focus_on_window_activation = FOWA_URGENT;
|
||||||
config->popup_during_fullscreen = POPUP_SMART;
|
config->popup_during_fullscreen = POPUP_SMART;
|
||||||
config->xwayland = XWAYLAND_MODE_LAZY;
|
config->xwayland = XWAYLAND_MODE_LAZY;
|
||||||
|
|
||||||
|
config->titlebar_max_text_height = 17; // height of monospace 10
|
||||||
config->titlebar_border_thickness = 1;
|
config->titlebar_border_thickness = 1;
|
||||||
|
|
||||||
config->titlebar_h_padding = 5;
|
config->titlebar_h_padding = 5;
|
||||||
config->titlebar_v_padding = 4;
|
config->titlebar_v_padding = 4;
|
||||||
|
|
||||||
|
|
@ -960,37 +961,6 @@ int workspace_output_cmp_workspace(const void *a, const void *b) {
|
||||||
return lenient_strcmp(wsa->workspace, wsb->workspace);
|
return lenient_strcmp(wsa->workspace, wsb->workspace);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void find_font_height_iterator(struct sway_container *con, void *data) {
|
|
||||||
size_t amount_below_baseline = con->title_height - con->title_baseline;
|
|
||||||
size_t extended_height = config->font_baseline + amount_below_baseline;
|
|
||||||
if (extended_height > config->font_height) {
|
|
||||||
config->font_height = extended_height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void find_baseline_iterator(struct sway_container *con, void *data) {
|
|
||||||
bool *recalculate = data;
|
|
||||||
if (*recalculate) {
|
|
||||||
container_calculate_title_height(con);
|
|
||||||
}
|
|
||||||
if (con->title_baseline > config->font_baseline) {
|
|
||||||
config->font_baseline = con->title_baseline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void config_update_font_height(bool recalculate) {
|
|
||||||
size_t prev_max_height = config->font_height;
|
|
||||||
config->font_height = 0;
|
|
||||||
config->font_baseline = 0;
|
|
||||||
|
|
||||||
root_for_each_container(find_baseline_iterator, &recalculate);
|
|
||||||
root_for_each_container(find_font_height_iterator, NULL);
|
|
||||||
|
|
||||||
if (config->font_height != prev_max_height) {
|
|
||||||
arrange_root();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void translate_binding_list(list_t *bindings, list_t *bindsyms,
|
static void translate_binding_list(list_t *bindings, list_t *bindsyms,
|
||||||
list_t *bindcodes) {
|
list_t *bindcodes) {
|
||||||
for (int i = 0; i < bindings->length; ++i) {
|
for (int i = 0; i < bindings->length; ++i) {
|
||||||
|
|
|
||||||
|
|
@ -468,7 +468,7 @@ static void render_titlebar(struct sway_output *output,
|
||||||
int ob_inner_width = scale_length(inner_width, inner_x, output_scale);
|
int ob_inner_width = scale_length(inner_width, inner_x, output_scale);
|
||||||
int ob_bg_height = scale_length(
|
int ob_bg_height = scale_length(
|
||||||
(titlebar_v_padding - titlebar_border_thickness) * 2 +
|
(titlebar_v_padding - titlebar_border_thickness) * 2 +
|
||||||
config->font_height, bg_y, output_scale);
|
config->titlebar_max_text_height, bg_y, output_scale);
|
||||||
|
|
||||||
// Marks
|
// Marks
|
||||||
int ob_marks_x = 0; // output-buffer-local
|
int ob_marks_x = 0; // output-buffer-local
|
||||||
|
|
@ -479,11 +479,11 @@ static void render_titlebar(struct sway_output *output,
|
||||||
&texture_box.width, &texture_box.height);
|
&texture_box.width, &texture_box.height);
|
||||||
ob_marks_width = texture_box.width;
|
ob_marks_width = texture_box.width;
|
||||||
|
|
||||||
// The marks texture might be shorter than the config->font_height, in
|
// The marks texture might be shorter than config->titlebar_max_text_height, in
|
||||||
// which case we need to pad it as evenly as possible above and below.
|
// which case we need to pad it as evenly as possible above and below.
|
||||||
int ob_padding_total = ob_bg_height - texture_box.height;
|
int ob_padding_total = ob_bg_height - texture_box.height;
|
||||||
int ob_padding_above = floor(ob_padding_total / 2.0);
|
int ob_padding_above = floor(ob_padding_total / 2.0);
|
||||||
int ob_padding_below = ceil(ob_padding_total / 2.0);
|
int ob_padding_below = ob_padding_total - ob_padding_above;
|
||||||
|
|
||||||
// Render texture. If the title is on the right, the marks will be on
|
// Render texture. If the title is on the right, the marks will be on
|
||||||
// the left. Otherwise, they will be on the right.
|
// the left. Otherwise, they will be on the right.
|
||||||
|
|
@ -532,13 +532,11 @@ static void render_titlebar(struct sway_output *output,
|
||||||
&texture_box.width, &texture_box.height);
|
&texture_box.width, &texture_box.height);
|
||||||
ob_title_width = texture_box.width;
|
ob_title_width = texture_box.width;
|
||||||
|
|
||||||
// The title texture might be shorter than the config->font_height,
|
// The title texture might be shorter than config->titlebar_max_text_height,
|
||||||
// in which case we need to pad it above and below.
|
// in which case we need to pad it above and below.
|
||||||
int ob_padding_above = round((config->font_baseline -
|
int ob_padding_total = fmax(0, (ob_bg_height - con->title_height));
|
||||||
con->title_baseline + titlebar_v_padding -
|
int ob_padding_above = floor(ob_padding_total / 2.0);
|
||||||
titlebar_border_thickness) * output_scale);
|
int ob_padding_below = ob_padding_total - ob_padding_above;
|
||||||
int ob_padding_below = ob_bg_height - ob_padding_above -
|
|
||||||
texture_box.height;
|
|
||||||
|
|
||||||
// Render texture
|
// Render texture
|
||||||
if (texture_box.width > ob_inner_width - ob_marks_width) {
|
if (texture_box.width > ob_inner_width - ob_marks_width) {
|
||||||
|
|
@ -630,7 +628,7 @@ static void render_titlebar(struct sway_output *output,
|
||||||
box.y = y + titlebar_border_thickness;
|
box.y = y + titlebar_border_thickness;
|
||||||
box.width = titlebar_h_padding - titlebar_border_thickness;
|
box.width = titlebar_h_padding - titlebar_border_thickness;
|
||||||
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
||||||
config->font_height;
|
config->titlebar_max_text_height;
|
||||||
scale_box(&box, output_scale);
|
scale_box(&box, output_scale);
|
||||||
int left_x = ob_left_x + round(output_x * output_scale);
|
int left_x = ob_left_x + round(output_x * output_scale);
|
||||||
if (box.x + box.width < left_x) {
|
if (box.x + box.width < left_x) {
|
||||||
|
|
@ -643,7 +641,7 @@ static void render_titlebar(struct sway_output *output,
|
||||||
box.y = y + titlebar_border_thickness;
|
box.y = y + titlebar_border_thickness;
|
||||||
box.width = titlebar_h_padding - titlebar_border_thickness;
|
box.width = titlebar_h_padding - titlebar_border_thickness;
|
||||||
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
box.height = (titlebar_v_padding - titlebar_border_thickness) * 2 +
|
||||||
config->font_height;
|
config->titlebar_max_text_height;
|
||||||
scale_box(&box, output_scale);
|
scale_box(&box, output_scale);
|
||||||
int right_rx = ob_right_x + ob_right_width + round(output_x * output_scale);
|
int right_rx = ob_right_x + ob_right_width + round(output_x * output_scale);
|
||||||
if (right_rx < box.x) {
|
if (right_rx < box.x) {
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ sway_sources = files(
|
||||||
'commands/title_align.c',
|
'commands/title_align.c',
|
||||||
'commands/title_format.c',
|
'commands/title_format.c',
|
||||||
'commands/titlebar_border_thickness.c',
|
'commands/titlebar_border_thickness.c',
|
||||||
|
'commands/titlebar_max_text_height.c',
|
||||||
'commands/titlebar_padding.c',
|
'commands/titlebar_padding.c',
|
||||||
'commands/unmark.c',
|
'commands/unmark.c',
|
||||||
'commands/urgent.c',
|
'commands/urgent.c',
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ struct sway_container *container_create(struct sway_view *view) {
|
||||||
c->layout = L_NONE;
|
c->layout = L_NONE;
|
||||||
c->view = view;
|
c->view = view;
|
||||||
c->alpha = 1.0f;
|
c->alpha = 1.0f;
|
||||||
|
c->title_ascent = 0;
|
||||||
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
c->children = create_list();
|
c->children = create_list();
|
||||||
|
|
@ -497,7 +498,7 @@ static void update_title_texture(struct sway_container *con,
|
||||||
PangoContext *pango = pango_cairo_create_context(cairo);
|
PangoContext *pango = pango_cairo_create_context(cairo);
|
||||||
cairo_set_source_rgba(cairo, class->text[0], class->text[1],
|
cairo_set_source_rgba(cairo, class->text[0], class->text[1],
|
||||||
class->text[2], class->text[3]);
|
class->text[2], class->text[3]);
|
||||||
cairo_move_to(cairo, 0, 0);
|
cairo_move_to(cairo, 0, con->title_ascent);
|
||||||
|
|
||||||
pango_printf(cairo, config->font, scale, config->pango_markup,
|
pango_printf(cairo, config->font, scale, config->pango_markup,
|
||||||
"%s", con->formatted_title);
|
"%s", con->formatted_title);
|
||||||
|
|
@ -532,13 +533,14 @@ void container_calculate_title_height(struct sway_container *container) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
cairo_t *cairo = cairo_create(NULL);
|
cairo_t *cairo = cairo_create(NULL);
|
||||||
int height;
|
int ink_size, ascent;
|
||||||
int baseline;
|
get_text_physical_size(cairo, config->font, &ascent, NULL,
|
||||||
get_text_size(cairo, config->font, NULL, &height, &baseline, 1,
|
&ink_size, config->pango_markup, "%s",
|
||||||
config->pango_markup, "%s", container->formatted_title);
|
container->formatted_title);
|
||||||
|
|
||||||
cairo_destroy(cairo);
|
cairo_destroy(cairo);
|
||||||
container->title_height = height;
|
container->title_height = ink_size;
|
||||||
container->title_baseline = baseline;
|
container->title_ascent = ascent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -617,7 +619,7 @@ void container_update_representation(struct sway_container *con) {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t container_titlebar_height(void) {
|
size_t container_titlebar_height(void) {
|
||||||
return config->font_height + config->titlebar_v_padding * 2;
|
return config->titlebar_max_text_height + config->titlebar_v_padding * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void floating_calculate_constraints(int *min_width, int *max_width,
|
void floating_calculate_constraints(int *min_width, int *max_width,
|
||||||
|
|
|
||||||
|
|
@ -1214,7 +1214,6 @@ void view_update_title(struct sway_view *view, bool force) {
|
||||||
view->container->formatted_title = NULL;
|
view->container->formatted_title = NULL;
|
||||||
}
|
}
|
||||||
container_calculate_title_height(view->container);
|
container_calculate_title_height(view->container);
|
||||||
config_update_font_height(false);
|
|
||||||
|
|
||||||
// Update title after the global font height is updated
|
// Update title after the global font height is updated
|
||||||
container_update_title_textures(view->container);
|
container_update_title_textures(view->container);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue