From 363a0de8b9105a837484fed1f0d3da38063ab82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 29 Jul 2020 06:55:23 +0200 Subject: [PATCH 1/9] changelog: add 1.4.4 section --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 910944c8..117dbdc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,6 @@ # Changelog +* [1.4.4](#1-4-4) * [1.4.3](#1-4-3) * [1.4.2](#1-4-2) * [1.4.1](#1-4-1) @@ -10,6 +11,9 @@ * [1.2.1](#1-2-1) * [1.2.0](#1-2-0) +## 1.4.4 + + ## 1.4.3 ### Added From d675cf872022e0e1bf2100211d7607773de1016c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 12:31:13 +0200 Subject: [PATCH 2/9] input: margins are not selectable * Fix col/row calculation in pointer-enter event; we did not take the margins into account. * seat->mouse.col,row are now set to -1 if the cursor is inside the margins. That is, col/row are only ever valid when the mouse is actually over the grid, and not in the margins. * Use regular 'left-ptr' mouse cursor when mouse is inside the margins, to not make the user think he/she can start a selection. Besides making things clearer, this also fixes a crash that occurred if you started a selection in e.g. the right margin. --- CHANGELOG.md | 9 +++++++++ input.c | 40 ++++++++++++++++++++++++++-------------- selection.c | 7 ++++--- 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 117dbdc5..eafaed22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,15 @@ * [1.2.0](#1-2-0) ## 1.4.4 +### Changed + +* Mouse cursor is now always a `left_ptr` when inside the margins, to + indicate it is not possible to start a selection. + + +### Fixed + +* Crash when starting a selection inside the margins. ## 1.4.3 diff --git a/input.c b/input.c index c7f4b073..7fa62570 100644 --- a/input.c +++ b/input.c @@ -1023,11 +1023,16 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, int y = wl_fixed_to_int(surface_y) * term->scale; switch ((term->active_surface = term_surface_kind(term, surface))) { - case TERM_SURF_GRID: - seat->mouse.col = x / term->cell_width; - seat->mouse.row = y / term->cell_height; + case TERM_SURF_GRID: { + int col = (x - term->margins.left) / term->cell_width; + int row = (y - term->margins.top) / term->cell_height; + + seat->mouse.col = col >= 0 && col < term->cols ? col : -1; + seat->mouse.row = row >= 0 && row < term->rows ? row : -1; + term_xcursor_update(term); break; + } case TERM_SURF_SEARCH: case TERM_SURF_TITLE: @@ -1165,26 +1170,31 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, break; case TERM_SURF_GRID: { + term_xcursor_update(term); + int col = (x - term->margins.left) / term->cell_width; int row = (y - term->margins.top) / term->cell_height; - if (col < 0 || row < 0 || col >= term->cols || row >= term->rows) - return; + int old_col = seat->mouse.col; + int old_row = seat->mouse.row; + + seat->mouse.col = col >= 0 && col < term->cols ? col : -1; + seat->mouse.row = row >= 0 && row < term->rows ? row : -1; + + if (seat->mouse.col < 0 || seat->mouse.row < 0) + break; bool update_selection = seat->mouse.button == BTN_LEFT || seat->mouse.button == BTN_RIGHT; bool update_selection_early = term->selection.end.row == -1; if (update_selection && update_selection_early) - selection_update(term, col, row); + selection_update(term, seat->mouse.col, seat->mouse.row); - if (col == seat->mouse.col && row == seat->mouse.row) + if (old_col == seat->mouse.col && old_row == seat->mouse.row) break; - seat->mouse.col = col; - seat->mouse.row = row; - if (update_selection && !update_selection_early) - selection_update(term, col, row); + selection_update(term, seat->mouse.col, seat->mouse.row); if (!term_mouse_grabbed(term, seat)) { term_mouse_motion( @@ -1360,9 +1370,11 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (selection_enabled(term, seat)) { switch (seat->mouse.count) { case 1: - selection_start( - term, seat->mouse.col, seat->mouse.row, - seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + if (seat->mouse.col >= 0 && seat->mouse.row >= 0) { + selection_start( + term, seat->mouse.col, seat->mouse.row, + seat->kbd.ctrl ? SELECTION_BLOCK : SELECTION_NORMAL); + } break; case 2: diff --git a/selection.c b/selection.c index 354f6f53..ffe06c27 100644 --- a/selection.c +++ b/selection.c @@ -25,9 +25,10 @@ bool selection_enabled(const struct terminal *term, struct seat *seat) { return - term->mouse_tracking == MOUSE_NONE || - term_mouse_grabbed(term, seat) || - term->is_searching; + seat->mouse.col >= 0 && seat->mouse.row >= 0 && + (term->mouse_tracking == MOUSE_NONE || + term_mouse_grabbed(term, seat) || + term->is_searching); } bool From 9601ed7cfb120e993cb3fd5db7d47bb3a7c49bec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 07:41:57 +0200 Subject: [PATCH 3/9] wayland: calculate a single, scaled DPI value Previously, we calculated the monitors horizontal and vertical PPI values. For font sizing, we used the vertical PPI value. It seems however, that using the diagonal PPI value, i.e. diagonal_px / diagonal_inch, gives more consistent results. This is still a PPI value, but since it is intended to be used as a FontConfig DPI value, name it 'dpi'. --- wayland.c | 13 +++++++++++-- wayland.h | 2 ++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index 70d5e0f1..bb7405a2 100644 --- a/wayland.c +++ b/wayland.c @@ -294,11 +294,18 @@ output_update_ppi(struct monitor *mon) int x_inches = mon->dim.mm.width * 0.03937008; int y_inches = mon->dim.mm.height * 0.03937008; + mon->ppi.real.x = mon->dim.px_real.width / x_inches; mon->ppi.real.y = mon->dim.px_real.height / y_inches; mon->ppi.scaled.x = mon->dim.px_scaled.width / x_inches; mon->ppi.scaled.y = mon->dim.px_scaled.height / y_inches; + + float px_diag = sqrt( + pow(mon->dim.px_scaled.width, 2) + + pow(mon->dim.px_scaled.height, 2)); + + mon->dpi = px_diag / mon->inch * mon->scale; } static void @@ -343,6 +350,7 @@ output_scale(void *data, struct wl_output *wl_output, int32_t factor) { struct monitor *mon = data; mon->scale = factor; + output_update_ppi(mon); } static const struct wl_output_listener output_listener = { @@ -1029,13 +1037,14 @@ wayl_init(const struct config *conf, struct fdm *fdm) tll_foreach(wayl->monitors, it) { LOG_INFO( - "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical)", + "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical), DPI=%.2f", it->item.name, it->item.dim.px_real.width, it->item.dim.px_real.height, it->item.x, it->item.y, (int)round(it->item.refresh), it->item.model != NULL ? it->item.model : it->item.description, it->item.inch, it->item.scale, it->item.ppi.real.x, it->item.ppi.real.y, - it->item.ppi.scaled.x, it->item.ppi.scaled.y); + it->item.ppi.scaled.x, it->item.ppi.scaled.y, + it->item.dpi); } wayl->fd = wl_display_get_fd(wayl->display); diff --git a/wayland.h b/wayland.h index dbf63c1b..88be3d71 100644 --- a/wayland.h +++ b/wayland.h @@ -236,6 +236,8 @@ struct monitor { } scaled; } ppi; + float dpi; + int scale; float refresh; enum wl_output_subpixel subpixel; From 423bfd388a96e0e04061363773f3059c82d67d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 07:45:03 +0200 Subject: [PATCH 4/9] term: store current font DPI as a float instead of an integer FontConfig's DPI is a double, and using a float instead of an integer results in higher resolution. --- terminal.c | 22 +++++++++++----------- terminal.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/terminal.c b/terminal.c index 86672f06..d7f05c30 100644 --- a/terminal.c +++ b/terminal.c @@ -559,7 +559,7 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) return true; } -static unsigned +static float get_font_dpi(const struct terminal *term) { /* @@ -584,7 +584,7 @@ get_font_dpi(const struct terminal *term) */ /* Use highest DPI from outputs we're mapped on */ - unsigned dpi = 0; + double dpi = 0.0; assert(term->window != NULL); tll_foreach(term->window->on_outputs, it) { if (it->item->ppi.scaled.y > dpi) @@ -592,7 +592,7 @@ get_font_dpi(const struct terminal *term) } /* If we're not mapped, use DPI from first monitor. Hopefully this is where we'll get mapped later... */ - if (dpi == 0) { + if (dpi == 0.) { tll_foreach(term->wl->monitors, it) { dpi = it->item.ppi.scaled.y * term->scale; break; @@ -601,7 +601,7 @@ get_font_dpi(const struct terminal *term) if (dpi == 0) { /* No monitors? */ - dpi = 96; + dpi = 96.; } return dpi; @@ -692,10 +692,10 @@ reload_fonts(struct terminal *term) } char attrs0[256], attrs1[256], attrs2[256], attrs3[256]; - 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); + snprintf(attrs0, sizeof(attrs0), "dpi=%.2f", term->font_dpi); + snprintf(attrs1, sizeof(attrs1), "dpi=%.2f:weight=bold", term->font_dpi); + snprintf(attrs2, sizeof(attrs2), "dpi=%.2f:slant=italic", term->font_dpi); + snprintf(attrs3, sizeof(attrs3), "dpi=%.2f:weight=bold:slant=italic", term->font_dpi); struct fcft_font *fonts[4]; struct font_load_data data[4] = { @@ -836,7 +836,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .ptmx = ptmx, .ptmx_buffer = tll_init(), .font_sizes = malloc(sizeof(term->font_sizes[0]) * tll_length(conf->fonts)), - .font_dpi = 0, + .font_dpi = 0., .font_subpixel = (conf->colors.alpha == 0xffff /* Can't do subpixel rendering on transparent background */ ? FCFT_SUBPIXEL_DEFAULT : FCFT_SUBPIXEL_NONE), @@ -1490,11 +1490,11 @@ term_font_size_reset(struct terminal *term) bool term_font_dpi_changed(struct terminal *term) { - unsigned dpi = get_font_dpi(term); + float dpi = get_font_dpi(term); if (dpi == term->font_dpi) return true; - LOG_DBG("DPI changed (%u -> %u): reloading fonts", term->font_dpi, dpi); + LOG_DBG("DPI changed (%.2f -> %.2f): reloading fonts", term->font_dpi, dpi); term->font_dpi = dpi; return reload_fonts(term); diff --git a/terminal.h b/terminal.h index 85f89abf..d82e3e93 100644 --- a/terminal.h +++ b/terminal.h @@ -223,7 +223,7 @@ struct terminal { struct fcft_font *fonts[4]; struct config_font *font_sizes; - int font_dpi; + float font_dpi; enum fcft_subpixel font_subpixel; tll(struct ptmx_buffer) ptmx_buffer; From fb57e5630809f109a3378979714112b479fe1a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jul 2020 07:45:55 +0200 Subject: [PATCH 5/9] term: use the monitors diagonal DPI value, instead of it's vertical PPI value --- terminal.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/terminal.c b/terminal.c index d7f05c30..1a560ef2 100644 --- a/terminal.c +++ b/terminal.c @@ -587,14 +587,14 @@ get_font_dpi(const struct terminal *term) double dpi = 0.0; assert(term->window != NULL); tll_foreach(term->window->on_outputs, it) { - if (it->item->ppi.scaled.y > dpi) - dpi = it->item->ppi.scaled.y * term->scale; + if (it->item->dpi > dpi) + dpi = it->item->dpi; } /* 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.ppi.scaled.y * term->scale; + dpi = it->item.dpi; break; } } From 7eee2d715db20dfa5094148874dd77f7e3685052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Jul 2020 20:00:32 +0200 Subject: [PATCH 6/9] changelog: improved font size consistency across monitors with different DPI --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eafaed22..560552cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ ### Fixed * Crash when starting a selection inside the margins. +* Improved font size consistency across multiple monitors with + different DPI (https://codeberg.org/dnkl/foot/issues/47). ## 1.4.3 From f8d9bf18e5b67eac5838923620a5b11adc3f6cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 28 Jul 2020 19:55:09 +0200 Subject: [PATCH 7/9] config: handle trailing comments and empty values --- CHANGELOG.md | 1 + config.c | 48 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 560552cf..6b452aaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * Crash when starting a selection inside the margins. * Improved font size consistency across multiple monitors with different DPI (https://codeberg.org/dnkl/foot/issues/47). +* Handle trailing comments in `footrc` ## 1.4.3 diff --git a/config.c b/config.c index 283a72ea..9b63375c 100644 --- a/config.c +++ b/config.c @@ -792,7 +792,7 @@ parse_config_file(FILE *f, struct config *conf, const char *path) break; } - /* Strip whitespace */ + /* Strip leading whitespace */ char *line = _line; { while (isspace(*line)) @@ -809,11 +809,15 @@ parse_config_file(FILE *f, struct config *conf, const char *path) if (line[0] == '\0' || line[0] == '#') continue; + /* Split up into key/value pair + trailing comment */ + char *key_value = strtok(line, "#"); + char *comment __attribute__((unused)) = strtok(NULL, "\n"); + /* Check for new section */ - if (line[0] == '[') { - char *end = strchr(line, ']'); + if (key_value[0] == '[') { + char *end = strchr(key_value, ']'); if (end == NULL) { - LOG_ERR("%s:%d: syntax error: %s", path, lineno, line); + LOG_ERR("%s:%d: syntax error: %s", path, lineno, key_value); goto err; } @@ -821,13 +825,13 @@ parse_config_file(FILE *f, struct config *conf, const char *path) section = SECTION_COUNT; for (enum section i = 0; i < SECTION_COUNT; i++) { - if (strcmp(&line[1], section_info[i].name) == 0) { + if (strcmp(&key_value[1], section_info[i].name) == 0) { section = i; } } if (section == SECTION_COUNT) { - LOG_ERR("%s:%d: invalid section name: %s", path, lineno, &line[1]); + LOG_ERR("%s:%d: invalid section name: %s", path, lineno, &key_value[1]); goto err; } @@ -835,11 +839,20 @@ parse_config_file(FILE *f, struct config *conf, const char *path) continue; } - char *key = strtok(line, "="); + char *key = strtok(key_value, "="); + if (key == NULL) { + LOG_ERR("%s:%d: syntax error: no key specified", path, lineno); + goto err; + } + char *value = strtok(NULL, "\n"); + if (value == NULL) { + /* Empty value, i.e. "key=" */ + value = key + strlen(key); + } /* Strip trailing whitespace from key (leading stripped earlier) */ - { + if (key[0] != '\0') { assert(!isspace(*key)); char *end = key + strlen(key) - 1; @@ -850,25 +863,28 @@ parse_config_file(FILE *f, struct config *conf, const char *path) if (value == NULL) { if (key != NULL && strlen(key) > 0 && key[0] != '#') { - LOG_ERR("%s:%d: syntax error: %s", path, lineno, line); + LOG_ERR("%s:%d: syntax error: %s", path, lineno, key_value); goto err; } continue; } - /* Strip leading whitespace from value (trailing stripped earlier) */ + /* Strip leading+trailing whitespace from value */ { while (isspace(*value)) value++; - assert(!isspace(*(value + strlen(value) - 1))); + + if (value[0] != '\0') { + char *end = value + strlen(value) - 1; + while (isspace(*end)) + end--; + *(end + 1) = '\0'; + } } - if (key[0] == '#') - continue; - - LOG_DBG("section=%s, key='%s', value='%s'", - section_names[section], key, value); + LOG_DBG("section=%s, key='%s', value='%s', comment='%s'", + section_info[section].name, key, value, comment); parser_fun_t section_parser = section_info[section].fun; assert(section_parser != NULL); From a4d2a2bf28b0474400f451ca33444e2c9183bbcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 29 Jul 2020 07:01:44 +0200 Subject: [PATCH 8/9] changelog: add extra newline between index and first release --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b452aaa..ceb377fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * [1.2.1](#1-2-1) * [1.2.0](#1-2-0) + ## 1.4.4 ### Changed From 6b22758f351db4fa4b835a6bca6af2f392cd3019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 29 Jul 2020 07:02:43 +0200 Subject: [PATCH 9/9] meson/pkgbuild: update version to 1.4.4 --- PKGBUILD | 2 +- meson.build | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 36d020d4..fefc4d60 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -1,5 +1,5 @@ pkgname=('foot-git' 'foot-terminfo-git') -pkgver=1.4.3 +pkgver=1.4.4 pkgrel=1 arch=('x86_64' 'aarch64') url=https://codeberg.org/dnkl/foot diff --git a/meson.build b/meson.build index 1a75a151..ee3d532e 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project('foot', 'c', - version: '1.4.3', + version: '1.4.4', license: 'MIT', meson_version: '>=0.53.0', default_options: [