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
initialize_fonts(const struct terminal *term, const struct config *conf,
struct font *fonts[static 4])
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);
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 char *names[count];
@ -517,18 +563,11 @@ initialize_fonts(const struct terminal *term, const struct config *conf,
tll_foreach(conf->fonts, it)
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];
snprintf(attrs0, sizeof(attrs0), "dpi=%u", dpi);
snprintf(attrs1, sizeof(attrs1), "dpi=%u:weight=bold", dpi);
snprintf(attrs2, sizeof(attrs2), "dpi=%u:slant=italic", dpi);
snprintf(attrs3, sizeof(attrs3), "dpi=%u:weight=bold:slant=italic", dpi);
snprintf(attrs0, sizeof(attrs0), "dpi=%u", term->font_dpi);
snprintf(attrs1, sizeof(attrs1), "dpi=%u:weight=bold", term->font_dpi);
snprintf(attrs2, sizeof(attrs2), "dpi=%u:slant=italic", term->font_dpi);
snprintf(attrs3, sizeof(attrs3), "dpi=%u:weight=bold:slant=italic", term->font_dpi);
fonts[0] = fonts[1] = fonts[2] = fonts[3] = NULL;
bool ret =
@ -619,6 +658,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
.quit = false,
.ptmx = ptmx,
.ptmx_buffer = tll_init(),
.font_dpi = 0,
.font_adjustments = 0,
.cursor_keys_mode = CURSOR_KEYS_NORMAL,
.keypad_keys_mode = KEYPAD_NUMERICAL,
.auto_margin = true,
@ -706,21 +747,16 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
.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);
if (!initialize_render_workers(term))
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 */
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 */
tll_push_back(wayl->terms, term);
wayl_roundtrip(term->wl);
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) {
/* Try to use user-configured window dimentions */
@ -1112,25 +1160,7 @@ term_reset(struct terminal *term, bool hard)
term_damage_all(term);
}
static void
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
static bool
term_font_size_adjust(struct terminal *term, double amount)
{
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++)
font_destroy(fonts[i]);
return;
return false;
}
term_set_fonts(term, fonts);
return true;
}
void
bool
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_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)
{
struct font *fonts[4];
if (!initialize_fonts(term, term->conf, fonts))
return;
if (!load_fonts_from_conf(term, term->conf, fonts))
return false;
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

View file

@ -187,6 +187,8 @@ struct terminal {
struct grid *grid;
struct font *fonts[4];
int font_dpi;
int font_adjustments;
tll(struct ptmx_buffer) ptmx_buffer;
@ -364,9 +366,10 @@ int term_destroy(struct terminal *term);
void term_reset(struct terminal *term, bool hard);
bool term_to_slave(struct terminal *term, const void *data, size_t len);
void term_font_size_increase(struct terminal *term);
void term_font_size_decrease(struct terminal *term);
void term_font_size_reset(struct terminal *term);
bool term_font_size_increase(struct terminal *term);
bool term_font_size_decrease(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_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,
};
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
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;
mon->refresh = (float)refresh / 1000;
mon->width_px = width;
mon->height_px = height;
}
static void
output_done(void *data, struct wl_output *wl_output)
{
struct monitor *mon = data;
update_terms_on_monitor(mon);
}
static void
output_scale(void *data, struct wl_output *wl_output, int32_t factor)
{
struct monitor *mon = data;
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 = {
@ -171,10 +191,6 @@ static void
xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
int32_t width, int32_t height)
{
struct monitor *mon = data;
mon->width_px = width;
mon->height_px = height;
output_update_ppi(mon);
}
static void
@ -370,11 +386,7 @@ surface_enter(void *data, struct wl_surface *wl_surface,
if (it->item.output == wl_output) {
LOG_DBG("mapped on %s", it->item.name);
tll_push_back(term->window->on_outputs, &it->item);
/* 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);
update_term_for_output_change(term);
return;
}
}
@ -395,11 +407,7 @@ surface_leave(void *data, struct wl_surface *wl_surface,
LOG_DBG("unmapped from %s", it->item->name);
tll_remove(term->window->on_outputs, it);
/* 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);
update_term_for_output_change(term);
return;
}