Merge branch 'font-dpi-adjust-on-the-fly'

This commit is contained in:
Daniel Eklöf 2020-02-15 19:16:22 +01:00
commit 1a808d2552
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 178 additions and 79 deletions

View file

@ -507,8 +507,54 @@ initialize_render_workers(struct terminal *term)
} }
static bool static bool
initialize_fonts(const struct terminal *term, const struct config *conf, term_set_fonts(struct terminal *term, struct font *fonts[static 4])
struct font *fonts[static 4]) {
for (size_t i = 0; i < 4; i++) {
assert(fonts[i] != NULL);
font_destroy(term->fonts[i]);
term->fonts[i] = fonts[i];
}
term->cell_width = term->fonts[0]->space_x_advance > 0
? term->fonts[0]->space_x_advance : term->fonts[0]->max_x_advance;
term->cell_height = term->fonts[0]->height;
LOG_INFO("cell width=%d, height=%d", term->cell_width, term->cell_height);
render_resize_force(term, term->width, term->height);
return true;
}
static unsigned
get_font_dpi(const struct terminal *term)
{
/* Use highest DPI from outputs we're mapped on */
unsigned dpi = 0;
assert(term->window != NULL);
tll_foreach(term->window->on_outputs, it) {
if (it->item->y_ppi > dpi)
dpi = it->item->y_ppi;
}
/* If we're not mapped, use DPI from first monitor. Hopefully this is where we'll get mapped later... */
if (dpi == 0) {
tll_foreach(term->wl->monitors, it) {
dpi = it->item.y_ppi;
break;
}
}
if (dpi == 0) {
/* No monitors? */
dpi = 96;
}
return dpi;
}
static bool
load_fonts_from_conf(const struct terminal *term, const struct config *conf,
struct font *fonts[static 4])
{ {
const size_t count = tll_length(conf->fonts); const size_t count = tll_length(conf->fonts);
const char *names[count]; const char *names[count];
@ -517,18 +563,11 @@ initialize_fonts(const struct terminal *term, const struct config *conf,
tll_foreach(conf->fonts, it) tll_foreach(conf->fonts, it)
names[i++] = it->item; names[i++] = it->item;
/* Use highest DPI available */
unsigned dpi = 96;
tll_foreach(term->wl->monitors, it) {
if (it->item.y_ppi > dpi)
dpi = it->item.y_ppi;
}
char attrs0[64], attrs1[64], attrs2[64], attrs3[64]; char attrs0[64], attrs1[64], attrs2[64], attrs3[64];
snprintf(attrs0, sizeof(attrs0), "dpi=%u", dpi); snprintf(attrs0, sizeof(attrs0), "dpi=%u", term->font_dpi);
snprintf(attrs1, sizeof(attrs1), "dpi=%u:weight=bold", dpi); snprintf(attrs1, sizeof(attrs1), "dpi=%u:weight=bold", term->font_dpi);
snprintf(attrs2, sizeof(attrs2), "dpi=%u:slant=italic", dpi); snprintf(attrs2, sizeof(attrs2), "dpi=%u:slant=italic", term->font_dpi);
snprintf(attrs3, sizeof(attrs3), "dpi=%u:weight=bold:slant=italic", dpi); snprintf(attrs3, sizeof(attrs3), "dpi=%u:weight=bold:slant=italic", term->font_dpi);
fonts[0] = fonts[1] = fonts[2] = fonts[3] = NULL; fonts[0] = fonts[1] = fonts[2] = fonts[3] = NULL;
bool ret = bool ret =
@ -619,6 +658,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
.quit = false, .quit = false,
.ptmx = ptmx, .ptmx = ptmx,
.ptmx_buffer = tll_init(), .ptmx_buffer = tll_init(),
.font_dpi = 0,
.font_adjustments = 0,
.cursor_keys_mode = CURSOR_KEYS_NORMAL, .cursor_keys_mode = CURSOR_KEYS_NORMAL,
.keypad_keys_mode = KEYPAD_NUMERICAL, .keypad_keys_mode = KEYPAD_NUMERICAL,
.auto_margin = true, .auto_margin = true,
@ -706,21 +747,16 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
.cwd = strdup(cwd), .cwd = strdup(cwd),
}; };
/* Guess scale; we're not mapped yet, so we don't know on which
* output we'll be. Pick highest scale we find for now */
tll_foreach(term->wl->monitors, it) {
if (it->item.scale > term->scale)
term->scale = it->item.scale;
}
initialize_color_cube(term); initialize_color_cube(term);
if (!initialize_render_workers(term)) if (!initialize_render_workers(term))
goto err; goto err;
if (!initialize_fonts(term, conf, term->fonts))
goto err;
/* Cell dimensions are based on the font metrics. Obviously */
term->cell_width = term->fonts[0]->space_x_advance > 0
? term->fonts[0]->space_x_advance : term->fonts[0]->max_x_advance;
term->cell_height = term->fonts[0]->height;
LOG_INFO("cell width=%d, height=%d", term->cell_width, term->cell_height);
/* Start the slave/client */
if ((term->slave = slave_spawn(term->ptmx, argc, term->cwd, argv, term_env, conf->shell)) == -1)
goto err;
/* Initialize the Wayland window backend */ /* Initialize the Wayland window backend */
if ((term->window = wayl_win_init(term)) == NULL) if ((term->window = wayl_win_init(term)) == NULL)
@ -729,9 +765,21 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
/* Let the Wayland backend know we exist */ /* Let the Wayland backend know we exist */
tll_push_back(wayl->terms, term); tll_push_back(wayl->terms, term);
wayl_roundtrip(term->wl); wayl_roundtrip(term->wl);
term_set_window_title(term, "foot"); term_set_window_title(term, "foot");
/* Load fonts */
#if 0
struct font *fonts[4];
if (!load_fonts_from_conf(term, conf, fonts))
goto err;
term_set_fonts(term, fonts);
#endif
term_font_dpi_changed(term);
/* Start the slave/client */
if ((term->slave = slave_spawn(term->ptmx, argc, term->cwd, argv, term_env, conf->shell)) == -1)
goto err;
if (term->width == 0 && term->height == 0) { if (term->width == 0 && term->height == 0) {
/* Try to use user-configured window dimentions */ /* Try to use user-configured window dimentions */
@ -1112,25 +1160,7 @@ term_reset(struct terminal *term, bool hard)
term_damage_all(term); term_damage_all(term);
} }
static void static bool
term_set_fonts(struct terminal *term, struct font *fonts[static 4])
{
for (size_t i = 0; i < 4; i++) {
assert(fonts[i] != NULL);
font_destroy(term->fonts[i]);
term->fonts[i] = fonts[i];
}
term->cell_width = term->fonts[0]->space_x_advance > 0
? term->fonts[0]->space_x_advance : term->fonts[0]->max_x_advance;
term->cell_height = term->fonts[0]->height;
LOG_INFO("cell width=%d, height=%d", term->cell_width, term->cell_height);
render_resize_force(term, term->width, term->height);
}
static void
term_font_size_adjust(struct terminal *term, double amount) term_font_size_adjust(struct terminal *term, double amount)
{ {
struct font *fonts[4] = { struct font *fonts[4] = {
@ -1145,32 +1175,90 @@ term_font_size_adjust(struct terminal *term, double amount)
{ {
for (size_t i = 0; i < 4; i++) for (size_t i = 0; i < 4; i++)
font_destroy(fonts[i]); font_destroy(fonts[i]);
return; return false;
} }
term_set_fonts(term, fonts); term_set_fonts(term, fonts);
return true;
} }
void bool
term_font_size_increase(struct terminal *term) term_font_size_increase(struct terminal *term)
{ {
term_font_size_adjust(term, 0.5); if (!term_font_size_adjust(term, 0.5))
return false;
term->font_adjustments++;
return true;
} }
void bool
term_font_size_decrease(struct terminal *term) term_font_size_decrease(struct terminal *term)
{ {
term_font_size_adjust(term, -0.5); if (!term_font_size_adjust(term, -0.5))
return false;
term->font_adjustments--;
return true;
} }
void bool
term_font_size_reset(struct terminal *term) term_font_size_reset(struct terminal *term)
{ {
struct font *fonts[4]; struct font *fonts[4];
if (!initialize_fonts(term, term->conf, fonts)) if (!load_fonts_from_conf(term, term->conf, fonts))
return; return false;
term_set_fonts(term, fonts); term_set_fonts(term, fonts);
term->font_adjustments = 0;
return true;
}
bool
term_font_dpi_changed(struct terminal *term)
{
unsigned dpi = get_font_dpi(term);
if (dpi == term->font_dpi)
return true;
LOG_DBG("DPI changed (%u -> %u): reloading fonts", term->font_dpi, dpi);
term->font_dpi = dpi;
struct font *fonts[4];
if (!load_fonts_from_conf(term, term->conf, fonts))
return false;
if (term->font_adjustments == 0)
return term_set_fonts(term, fonts);
/* User has adjusted the font size run-time, re-apply */
double amount = term->font_adjustments * 0.5;
struct font *adjusted_fonts[4] = {
font_size_adjust(fonts[0], amount),
font_size_adjust(fonts[1], amount),
font_size_adjust(fonts[2], amount),
font_size_adjust(fonts[3], amount),
};
if (adjusted_fonts[0] == NULL || adjusted_fonts[1] == NULL ||
adjusted_fonts[2] == NULL || adjusted_fonts[3] == NULL)
{
for (size_t i = 0; i < 4; i++)
font_destroy(adjusted_fonts[i]);
/* At least use the newly re-loaded default fonts */
term->font_adjustments = 0;
return term_set_fonts(term, fonts);
} else {
for (size_t i = 0; i < 4; i++)
font_destroy(fonts[i]);
return term_set_fonts(term, adjusted_fonts);
}
assert(false);
return false;
} }
void void

View file

@ -187,6 +187,8 @@ struct terminal {
struct grid *grid; struct grid *grid;
struct font *fonts[4]; struct font *fonts[4];
int font_dpi;
int font_adjustments;
tll(struct ptmx_buffer) ptmx_buffer; tll(struct ptmx_buffer) ptmx_buffer;
@ -364,9 +366,10 @@ int term_destroy(struct terminal *term);
void term_reset(struct terminal *term, bool hard); void term_reset(struct terminal *term, bool hard);
bool term_to_slave(struct terminal *term, const void *data, size_t len); bool term_to_slave(struct terminal *term, const void *data, size_t len);
void term_font_size_increase(struct terminal *term); bool term_font_size_increase(struct terminal *term);
void term_font_size_decrease(struct terminal *term); bool term_font_size_decrease(struct terminal *term);
void term_font_size_reset(struct terminal *term); bool term_font_size_reset(struct terminal *term);
bool term_font_dpi_changed(struct terminal *term);
void term_damage_rows(struct terminal *term, int start, int end); void term_damage_rows(struct terminal *term, int start, int end);
void term_damage_rows_in_view(struct terminal *term, int start, int end); void term_damage_rows_in_view(struct terminal *term, int start, int end);

View file

@ -95,6 +95,31 @@ static const struct wl_seat_listener seat_listener = {
.name = seat_handle_name, .name = seat_handle_name,
}; };
static void
update_term_for_output_change(struct terminal *term)
{
render_resize(term, term->width / term->scale, term->height / term->scale);
term_font_dpi_changed(term);
wayl_reload_cursor_theme(term->wl, term);
}
static void
update_terms_on_monitor(struct monitor *mon)
{
struct wayland *wayl = mon->wayl;
tll_foreach(wayl->terms, it) {
struct terminal *term = it->item;
tll_foreach(term->window->on_outputs, it2) {
if (it2->item == mon) {
update_term_for_output_change(term);
break;
}
}
}
}
static void static void
output_update_ppi(struct monitor *mon) output_update_ppi(struct monitor *mon)
{ {
@ -128,27 +153,22 @@ output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
struct monitor *mon = data; struct monitor *mon = data;
mon->refresh = (float)refresh / 1000; mon->refresh = (float)refresh / 1000;
mon->width_px = width;
mon->height_px = height;
} }
static void static void
output_done(void *data, struct wl_output *wl_output) output_done(void *data, struct wl_output *wl_output)
{ {
struct monitor *mon = data;
update_terms_on_monitor(mon);
} }
static void static void
output_scale(void *data, struct wl_output *wl_output, int32_t factor) output_scale(void *data, struct wl_output *wl_output, int32_t factor)
{ {
struct monitor *mon = data; struct monitor *mon = data;
mon->scale = factor; mon->scale = factor;
tll_foreach(mon->wayl->terms, it) {
struct terminal *term = it->item;
int scale = term->scale;
render_resize(term, term->width / scale, term->height / scale);
wayl_reload_cursor_theme(mon->wayl, term);
}
} }
static const struct wl_output_listener output_listener = { static const struct wl_output_listener output_listener = {
@ -171,10 +191,6 @@ static void
xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
int32_t width, int32_t height) int32_t width, int32_t height)
{ {
struct monitor *mon = data;
mon->width_px = width;
mon->height_px = height;
output_update_ppi(mon);
} }
static void static void
@ -370,11 +386,7 @@ surface_enter(void *data, struct wl_surface *wl_surface,
if (it->item.output == wl_output) { if (it->item.output == wl_output) {
LOG_DBG("mapped on %s", it->item.name); LOG_DBG("mapped on %s", it->item.name);
tll_push_back(term->window->on_outputs, &it->item); tll_push_back(term->window->on_outputs, &it->item);
update_term_for_output_change(term);
/* Resize, since scale-to-use may have changed */
int scale = term->scale;
render_resize(term, term->width / scale, term->height / scale);
wayl_reload_cursor_theme(term->wl, term);
return; return;
} }
} }
@ -395,11 +407,7 @@ surface_leave(void *data, struct wl_surface *wl_surface,
LOG_DBG("unmapped from %s", it->item->name); LOG_DBG("unmapped from %s", it->item->name);
tll_remove(term->window->on_outputs, it); tll_remove(term->window->on_outputs, it);
update_term_for_output_change(term);
/* Resize, since scale-to-use may have changed */
int scale = term->scale;
render_resize(term, term->width / scale, term->height / scale);
wayl_reload_cursor_theme(term->wl, term);
return; return;
} }