mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-08-03 22:25:57 +00:00
Fix jerky behavior when live resizing an OS window on platforms that report live resize being and end events
Also disable live resize begin/end events on Wayland since they are not reliable. On platforms that support live resize begin/end use a separately configurable pause time before the screen is redrawn. Fixes #6341
This commit is contained in:
parent
af389d6860
commit
89875af5e6
9 changed files with 54 additions and 19 deletions
10
glfw/wl_window.c
vendored
10
glfw/wl_window.c
vendored
|
|
@ -504,6 +504,12 @@ _glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) {
|
|||
return !already_fullscreen;
|
||||
}
|
||||
|
||||
static void
|
||||
report_live_resize(_GLFWwindow *w, bool started) {
|
||||
// disabled as mutter, for instance, does not send a configure event when the user stops resizing (aka releases the mouse button)
|
||||
if (false) _glfwInputLiveResize(w, started);
|
||||
}
|
||||
|
||||
static void
|
||||
xdgToplevelHandleConfigure(void* data,
|
||||
struct xdg_toplevel* toplevel UNUSED,
|
||||
|
|
@ -536,7 +542,7 @@ xdgToplevelHandleConfigure(void* data,
|
|||
if (new_states & TOPLEVEL_STATE_RESIZING) {
|
||||
if (width) window->wl.user_requested_content_size.width = width;
|
||||
if (height) window->wl.user_requested_content_size.height = height;
|
||||
if (!(window->wl.current.toplevel_states & TOPLEVEL_STATE_RESIZING)) _glfwInputLiveResize(window, true);
|
||||
if (!(window->wl.current.toplevel_states & TOPLEVEL_STATE_RESIZING)) report_live_resize(window, true);
|
||||
}
|
||||
if (width != 0 && height != 0)
|
||||
{
|
||||
|
|
@ -606,7 +612,7 @@ static void xdgSurfaceHandleConfigure(void* data,
|
|||
window->wl.current.width = width;
|
||||
window->wl.current.height = height;
|
||||
_glfwInputWindowFocus(window, window->wl.current.toplevel_states & TOPLEVEL_STATE_ACTIVATED);
|
||||
if (live_resize_done) _glfwInputLiveResize(window, false);
|
||||
if (live_resize_done) report_live_resize(window, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1004,9 +1004,19 @@ process_pending_resizes(monotonic_t now) {
|
|||
if (w->live_resize.in_progress) {
|
||||
bool update_viewport = false;
|
||||
if (w->live_resize.from_os_notification) {
|
||||
if (w->live_resize.os_says_resize_complete || (now - w->live_resize.last_resize_event_at) > 1) update_viewport = true;
|
||||
if (w->live_resize.os_says_resize_complete) update_viewport = true;
|
||||
else {
|
||||
// prevent a "hang" if the OS never sends a resize complete event
|
||||
// also reflow the screen when the user pauses resizing so the user can see what the resized
|
||||
// screen will look like.
|
||||
if ((now - w->live_resize.last_resize_event_at) > OPT(resize_debounce_time).on_pause) update_viewport = true;
|
||||
else {
|
||||
global_state.has_pending_resizes = true;
|
||||
set_maximum_wait(s_double_to_monotonic_t(0.05));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
monotonic_t debounce_time = OPT(resize_debounce_time);
|
||||
monotonic_t debounce_time = OPT(resize_debounce_time).on_end;
|
||||
// if more than one resize event has occurred, wait at least 0.2 secs
|
||||
// before repainting, to avoid rapid transitions between the cells banner
|
||||
// and the normal screen
|
||||
|
|
|
|||
|
|
@ -1065,12 +1065,18 @@ faded and one being fully opaque.
|
|||
)
|
||||
|
||||
|
||||
opt('resize_debounce_time', '0.1',
|
||||
option_type='positive_float', ctype='time',
|
||||
opt('resize_debounce_time', '0.1 0.5',
|
||||
option_type='resize_debounce_time', ctype='!resize_debounce_time',
|
||||
long_text='''
|
||||
The time to wait before redrawing the screen when a resize event is received (in
|
||||
seconds). On platforms such as macOS, where the operating system sends events
|
||||
corresponding to the start and end of a resize, this number is ignored.
|
||||
The time to wait before redrawing the screen during a live resize of the OS
|
||||
window, when no new resize events have been received, i.e. when resizing is
|
||||
either paused or finished. On platforms such as macOS, where the operating
|
||||
system sends events corresponding to the start and end of a live resize, the
|
||||
second number is used for redraw-after-pause since kitty can distinguish
|
||||
between a pause and end of resizing. On such systems the first number is
|
||||
ignored and redraw is immediate after end of resize. On other systems the
|
||||
first number is used so that kitty is "ready" quickly after the end of
|
||||
resizing, while not also continuously redrawing, to save energy.
|
||||
'''
|
||||
)
|
||||
|
||||
|
|
|
|||
14
kitty/options/parse.py
generated
14
kitty/options/parse.py
generated
|
|
@ -13,12 +13,12 @@ from kitty.options.utils import (
|
|||
deprecated_hide_window_decorations_aliases, deprecated_macos_show_window_title_in_menubar_alias,
|
||||
deprecated_send_text, disable_ligatures, edge_width, env, font_features, hide_window_decorations,
|
||||
macos_option_as_alt, macos_titlebar_color, modify_font, narrow_symbols, optional_edge_width,
|
||||
parse_map, parse_mouse_map, paste_actions, remote_control_password, resize_draw_strategy,
|
||||
scrollback_lines, scrollback_pager_history_size, shell_integration, store_multiple, symbol_map,
|
||||
tab_activity_symbol, tab_bar_edge, tab_bar_margin_height, tab_bar_min_tabs, tab_fade,
|
||||
tab_font_style, tab_separator, tab_title_template, titlebar_color, to_cursor_shape, to_font_size,
|
||||
to_layout_names, to_modifiers, url_prefixes, url_style, visual_window_select_characters,
|
||||
window_border_width, window_size
|
||||
parse_map, parse_mouse_map, paste_actions, remote_control_password, resize_debounce_time,
|
||||
resize_draw_strategy, scrollback_lines, scrollback_pager_history_size, shell_integration,
|
||||
store_multiple, symbol_map, tab_activity_symbol, tab_bar_edge, tab_bar_margin_height,
|
||||
tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator, tab_title_template, titlebar_color,
|
||||
to_cursor_shape, to_font_size, to_layout_names, to_modifiers, url_prefixes, url_style,
|
||||
visual_window_select_characters, window_border_width, window_size
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1151,7 +1151,7 @@ class Parser:
|
|||
ans['repaint_delay'] = positive_int(val)
|
||||
|
||||
def resize_debounce_time(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['resize_debounce_time'] = positive_float(val)
|
||||
ans['resize_debounce_time'] = resize_debounce_time(val)
|
||||
|
||||
def resize_draw_strategy(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
|
||||
ans['resize_draw_strategy'] = resize_draw_strategy(val)
|
||||
|
|
|
|||
2
kitty/options/to-c-generated.h
generated
2
kitty/options/to-c-generated.h
generated
|
|
@ -592,7 +592,7 @@ convert_from_opts_window_logo_alpha(PyObject *py_opts, Options *opts) {
|
|||
|
||||
static void
|
||||
convert_from_python_resize_debounce_time(PyObject *val, Options *opts) {
|
||||
opts->resize_debounce_time = parse_s_double_to_monotonic_t(val);
|
||||
resize_debounce_time(val, opts);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -255,3 +255,9 @@ tab_bar_margin_height(PyObject *val, Options *opts) {
|
|||
opts->tab_bar_margin_height.outer = PyFloat_AsDouble(PyTuple_GET_ITEM(val, 0));
|
||||
opts->tab_bar_margin_height.inner = PyFloat_AsDouble(PyTuple_GET_ITEM(val, 1));
|
||||
}
|
||||
|
||||
static void
|
||||
resize_debounce_time(PyObject *src, Options *opts) {
|
||||
opts->resize_debounce_time.on_end = s_double_to_monotonic_t(PyFloat_AsDouble(PyTuple_GET_ITEM(src, 0)));
|
||||
opts->resize_debounce_time.on_pause = s_double_to_monotonic_t(PyFloat_AsDouble(PyTuple_GET_ITEM(src, 1)));
|
||||
}
|
||||
|
|
|
|||
2
kitty/options/types.py
generated
2
kitty/options/types.py
generated
|
|
@ -564,7 +564,7 @@ class Options:
|
|||
pointer_shape_when_grabbed: choices_for_pointer_shape_when_grabbed = 'arrow'
|
||||
remember_window_size: bool = True
|
||||
repaint_delay: int = 10
|
||||
resize_debounce_time: float = 0.1
|
||||
resize_debounce_time: typing.Tuple[float, float] = (0.1, 0.5)
|
||||
resize_draw_strategy: int = 0
|
||||
resize_in_steps: bool = False
|
||||
scrollback_fill_enlarged_window: bool = False
|
||||
|
|
|
|||
|
|
@ -604,6 +604,13 @@ def resize_draw_strategy(x: str) -> int:
|
|||
return cmap.get(x.lower(), 0)
|
||||
|
||||
|
||||
def resize_debounce_time(x: str) -> Tuple[float, float]:
|
||||
parts = x.split(maxsplit=1)
|
||||
if len(parts) == 1:
|
||||
return positive_float(parts[0]), 0.5
|
||||
return positive_float(parts[0]), positive_float(parts[1])
|
||||
|
||||
|
||||
def visual_window_select_characters(x: str) -> str:
|
||||
import string
|
||||
valid_characters = string.digits + string.ascii_uppercase
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ typedef struct {
|
|||
bool window_alert_on_bell;
|
||||
bool debug_keyboard;
|
||||
bool allow_hyperlinks;
|
||||
monotonic_t resize_debounce_time;
|
||||
struct { monotonic_t on_end, on_pause; } resize_debounce_time;
|
||||
MouseShape pointer_shape_when_grabbed;
|
||||
MouseShape default_pointer_shape;
|
||||
MouseShape pointer_shape_when_dragging;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue