mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-22 05:33:45 -04:00
Merge branch 'font-dpi-adjust-on-the-fly'
This commit is contained in:
commit
1a808d2552
3 changed files with 178 additions and 79 deletions
194
terminal.c
194
terminal.c
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
54
wayland.c
54
wayland.c
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue