mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
render: delay TIOCSWINSZ while doing an interactive resize
Instead of disabling content centering, delay the TIOCSWINSZ (a.k.a delay sending the new dimensions to the client) by a small amount while doing an interactive resize. Non-interactive resizes are still immediate. For now, force a resize when the user stops the interactive resize. This ensures the client application receives the new dimensions immediately. It still works without the last, forced, resize, but there typically be a small delay until the client application receives the final dimensions. Closes #301 Closes #283
This commit is contained in:
parent
6876ab6bc2
commit
9a1df7bb03
5 changed files with 126 additions and 12 deletions
14
config.c
14
config.c
|
|
@ -1745,6 +1745,19 @@ parse_section_tweak(
|
|||
conf->tweak.box_drawing_base_thickness);
|
||||
}
|
||||
|
||||
else if (strcmp(key, "resize-delay-ms") == 0) {
|
||||
unsigned long ms;
|
||||
if (!str_to_ulong(value, 10, &ms)) {
|
||||
LOG_AND_NOTIFY_ERR(
|
||||
"%s:%d: [tweak]: resize-delay-ms: expected an integer, got '%s'",
|
||||
path, lineno, value);
|
||||
return false;
|
||||
}
|
||||
|
||||
conf->tweak.resize_delay_ms = ms;
|
||||
LOG_WARN("tweak: resize-delay-ms=%hu", conf->tweak.resize_delay_ms);
|
||||
}
|
||||
|
||||
else {
|
||||
LOG_AND_NOTIFY_ERR("%s:%u: [tweak]: %s: invalid key", path, lineno, key);
|
||||
return false;
|
||||
|
|
@ -2166,6 +2179,7 @@ config_load(struct config *conf, const char *conf_path,
|
|||
.render_timer_log = false,
|
||||
.damage_whole_window = false,
|
||||
.box_drawing_base_thickness = 0.04,
|
||||
.resize_delay_ms = 100,
|
||||
},
|
||||
|
||||
.notifications = tll_init(),
|
||||
|
|
|
|||
1
config.h
1
config.h
|
|
@ -203,6 +203,7 @@ struct config {
|
|||
uint64_t delayed_render_upper_ns;
|
||||
off_t max_shm_pool_size;
|
||||
float box_drawing_base_thickness;
|
||||
uint16_t resize_delay_ms;
|
||||
} tweak;
|
||||
|
||||
user_notifications_t notifications;
|
||||
|
|
|
|||
104
render.c
104
render.c
|
|
@ -1,10 +1,12 @@
|
|||
#include "render.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <pthread.h>
|
||||
#if __has_include(<pthread_np.h>)
|
||||
#include <pthread_np.h>
|
||||
|
|
@ -2545,6 +2547,92 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da
|
|||
grid_render(term);
|
||||
}
|
||||
|
||||
static void
|
||||
tiocswinsz(struct terminal *term)
|
||||
{
|
||||
if (term->ptmx >= 0) {
|
||||
if (ioctl(term->ptmx, (unsigned int)TIOCSWINSZ,
|
||||
&(struct winsize){
|
||||
.ws_row = term->rows,
|
||||
.ws_col = term->cols,
|
||||
.ws_xpixel = term->cols * term->cell_width,
|
||||
.ws_ypixel = term->rows * term->cell_height}) < 0)
|
||||
{
|
||||
LOG_ERRNO("TIOCSWINSZ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
fdm_tiocswinsz(struct fdm *fdm, int fd, int events, void *data)
|
||||
{
|
||||
struct terminal *term = data;
|
||||
|
||||
if (events & EPOLLIN) {
|
||||
tiocswinsz(term);
|
||||
LOG_WARN("DELAYED");
|
||||
}
|
||||
|
||||
fdm_del(fdm, fd);
|
||||
term->window->resize_timeout_fd = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
send_dimensions_to_client(struct terminal *term)
|
||||
{
|
||||
struct wl_window *win = term->window;
|
||||
|
||||
if (!win->is_resizing || term->conf->tweak.resize_delay_ms == 0) {
|
||||
/* Send new dimensions to client immediately */
|
||||
tiocswinsz(term);
|
||||
LOG_ERR("IMMEDIATELY");
|
||||
|
||||
/* And make sure to reset and deallocate a lingering timer */
|
||||
if (win->resize_timeout_fd >= 0) {
|
||||
fdm_del(term->fdm, win->resize_timeout_fd);
|
||||
win->resize_timeout_fd = -1;
|
||||
}
|
||||
} else {
|
||||
/* Send new dimensions to client “in a while” */
|
||||
assert(win->is_resizing && term->conf->tweak.resize_delay_ms > 0);
|
||||
|
||||
int fd = win->resize_timeout_fd;
|
||||
uint16_t delay_ms = term->conf->tweak.resize_delay_ms;
|
||||
bool successfully_scheduled = false;
|
||||
|
||||
if (fd < 0) {
|
||||
/* Lazy create timer fd */
|
||||
fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
||||
if (fd < 0)
|
||||
LOG_ERRNO("failed to create TIOCSWINSZ timer");
|
||||
else if (!fdm_add(term->fdm, fd, EPOLLIN, &fdm_tiocswinsz, term)) {
|
||||
close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
win->resize_timeout_fd = fd;
|
||||
}
|
||||
|
||||
if (fd >= 0) {
|
||||
/* Reset tiemout */
|
||||
const struct itimerspec timeout = {
|
||||
.it_value = {.tv_sec = 0, .tv_nsec = delay_ms * 1000000},
|
||||
};
|
||||
|
||||
if (timerfd_settime(fd, 0, &timeout, NULL) < 0) {
|
||||
LOG_ERRNO("failed to arm TIOCSWINSZ timer");
|
||||
fdm_del(term->fdm, fd);
|
||||
win->resize_timeout_fd = -1;
|
||||
} else
|
||||
successfully_scheduled = true;
|
||||
}
|
||||
|
||||
if (!successfully_scheduled)
|
||||
tiocswinsz(term);
|
||||
}
|
||||
}
|
||||
|
||||
/* Move to terminal.c? */
|
||||
static bool
|
||||
maybe_resize(struct terminal *term, int width, int height, bool force)
|
||||
|
|
@ -2671,7 +2759,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
const int total_x_pad = term->width - grid_width;
|
||||
const int total_y_pad = term->height - grid_height;
|
||||
|
||||
if (term->conf->center && !term->window->is_resizing) {
|
||||
if (term->conf->center) {
|
||||
term->margins.left = total_x_pad / 2;
|
||||
term->margins.top = total_y_pad / 2;
|
||||
} else {
|
||||
|
|
@ -2723,17 +2811,6 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
term->width, term->height, term->cols, term->rows,
|
||||
term->margins.left, term->margins.right, term->margins.top, term->margins.bottom);
|
||||
|
||||
/* Signal TIOCSWINSZ */
|
||||
if (term->ptmx >= 0 && ioctl(term->ptmx, (unsigned int)TIOCSWINSZ,
|
||||
&(struct winsize){
|
||||
.ws_row = term->rows,
|
||||
.ws_col = term->cols,
|
||||
.ws_xpixel = term->cols * term->cell_width,
|
||||
.ws_ypixel = term->rows * term->cell_height}) == -1)
|
||||
{
|
||||
LOG_ERRNO("TIOCSWINSZ");
|
||||
}
|
||||
|
||||
if (term->scroll_region.start >= term->rows)
|
||||
term->scroll_region.start = 0;
|
||||
|
||||
|
|
@ -2743,6 +2820,9 @@ maybe_resize(struct terminal *term, int width, int height, bool force)
|
|||
term->render.last_cursor.row = NULL;
|
||||
|
||||
damage_view:
|
||||
/* Signal TIOCSWINSZ */
|
||||
send_dimensions_to_client(term);
|
||||
|
||||
if (!term->window->is_maximized &&
|
||||
!term->window->is_fullscreen &&
|
||||
!term->window->is_tiled)
|
||||
|
|
|
|||
17
wayland.c
17
wayland.c
|
|
@ -677,9 +677,22 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface,
|
|||
term->window->frame_callback = NULL;
|
||||
}
|
||||
|
||||
#if 1
|
||||
/*
|
||||
* TODO: decide if we should to the last “forced” call when ending
|
||||
* an interactive resize.
|
||||
*
|
||||
* Without it, the last TIOCSWINSZ sent to the client will be a
|
||||
* scheduled one. I.e. there will be a small delay after the user
|
||||
* has *stopped* resizing, and the client application receives the
|
||||
* final size.
|
||||
*/
|
||||
bool resized = was_resizing && !win->is_resizing
|
||||
? render_resize_force(term, win->configure.width, win->configure.height)
|
||||
: render_resize(term, win->configure.width, win->configure.height);
|
||||
#else
|
||||
bool resized = render_resize(term, win->configure.width, win->configure.height);
|
||||
#endif
|
||||
|
||||
if (win->configure.is_activated)
|
||||
term_visual_focus_in(term);
|
||||
|
|
@ -1278,6 +1291,7 @@ wayl_win_init(struct terminal *term)
|
|||
win->term = term;
|
||||
win->use_csd = CSD_UNKNOWN;
|
||||
win->csd.move_timeout_fd = -1;
|
||||
win->resize_timeout_fd = -1;
|
||||
|
||||
win->surface = wl_compositor_create_surface(wayl->compositor);
|
||||
if (win->surface == NULL) {
|
||||
|
|
@ -1430,6 +1444,9 @@ wayl_win_destroy(struct wl_window *win)
|
|||
wl_surface_destroy(win->surface);
|
||||
|
||||
wayl_roundtrip(win->term->wl);
|
||||
|
||||
if (win->resize_timeout_fd >= 0)
|
||||
fdm_del(win->term->wl->fdm, win->resize_timeout_fd);
|
||||
free(win);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -390,6 +390,8 @@ struct wl_window {
|
|||
bool is_tiled_left:1;
|
||||
bool is_tiled_right:1;
|
||||
} configure;
|
||||
|
||||
int resize_timeout_fd;
|
||||
};
|
||||
|
||||
struct config;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue