Debounce resize requests

This commit is contained in:
Kovid Goyal 2017-11-16 09:51:41 +05:30
parent 8e3b5ddb0b
commit 407431adc8
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 36 additions and 7 deletions

View File

@ -627,6 +627,20 @@ wait_for_events() {
maximum_wait = -1; maximum_wait = -1;
} }
static inline void
process_pending_resizes(double now) {
global_state.has_pending_resizes = false;
for (size_t i = 0; i < global_state.num_os_windows; i++) {
OSWindow *w = global_state.os_windows + i;
if (w->has_pending_resizes) {
if (now - w->last_resize_at >= RESIZE_DEBOUNCE_TIME) update_os_window_viewport(w, true);
else {
global_state.has_pending_resizes = true;
set_maximum_wait(RESIZE_DEBOUNCE_TIME - now + w->last_resize_at);
}
}
}
}
static PyObject* static PyObject*
main_loop(ChildMonitor *self) { main_loop(ChildMonitor *self) {
@ -635,6 +649,7 @@ main_loop(ChildMonitor *self) {
while (has_open_windows) { while (has_open_windows) {
double now = monotonic(); double now = monotonic();
if (global_state.has_pending_resizes) process_pending_resizes(now);
render(now); render(now);
wait_for_events(); wait_for_events();
parse_input(self); parse_input(self);

View File

@ -29,16 +29,22 @@ extern bool cocoa_make_window_resizable(void *w);
static GLFWcursor *standard_cursor = NULL, *click_cursor = NULL, *arrow_cursor = NULL; static GLFWcursor *standard_cursor = NULL, *click_cursor = NULL, *arrow_cursor = NULL;
static void void
update_viewport(OSWindow *window) { update_os_window_viewport(OSWindow *window, bool notify_boss) {
int w, h; int w, h;
glfwGetFramebufferSize(window->handle, &window->viewport_width, &window->viewport_height); glfwGetFramebufferSize(window->handle, &window->viewport_width, &window->viewport_height);
glfwGetWindowSize(window->handle, &w, &h); glfwGetWindowSize(window->handle, &w, &h);
window->viewport_x_ratio = (double)window->viewport_width / (double)w; window->viewport_x_ratio = (double)window->viewport_width / (double)w;
window->viewport_y_ratio = (double)window->viewport_height / (double)h; window->viewport_y_ratio = (double)window->viewport_height / (double)h;
window->viewport_size_dirty = true; window->viewport_size_dirty = true;
window->has_pending_resizes = false;
if (notify_boss) {
call_boss(on_window_resize, "Kii", window->id, window->viewport_width, window->viewport_height);
}
window->last_resize_at = monotonic();
} }
// callbacks {{{ // callbacks {{{
void void
@ -85,11 +91,13 @@ static void
framebuffer_size_callback(GLFWwindow *w, int width, int height) { framebuffer_size_callback(GLFWwindow *w, int width, int height) {
if (!set_callback_window(w)) return; if (!set_callback_window(w)) return;
if (width > 100 && height > 100) { if (width > 100 && height > 100) {
update_viewport(global_state.callback_os_window); double now = monotonic();
if (is_window_ready_for_callbacks()) { OSWindow *window = global_state.callback_os_window;
WINDOW_CALLBACK(on_window_resize, "ii", width, height); if (now - window->last_resize_at < RESIZE_DEBOUNCE_TIME) { window->has_pending_resizes = true; global_state.has_pending_resizes = true; }
else {
update_os_window_viewport(global_state.callback_os_window, is_window_ready_for_callbacks());
glfwPostEmptyEvent();
} }
glfwPostEmptyEvent();
} else fprintf(stderr, "Ignoring resize request for tiny size: %dx%d\n", width, height); } else fprintf(stderr, "Ignoring resize request for tiny size: %dx%d\n", width, height);
global_state.callback_os_window = NULL; global_state.callback_os_window = NULL;
} }
@ -247,7 +255,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
update_os_window_references(); update_os_window_references();
if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo); if (logo.pixels && logo.width && logo.height) glfwSetWindowIcon(glfw_window, 1, &logo);
glfwSetCursor(glfw_window, standard_cursor); glfwSetCursor(glfw_window, standard_cursor);
update_viewport(w); update_os_window_viewport(w, false);
glfwSetFramebufferSizeCallback(glfw_window, framebuffer_size_callback); glfwSetFramebufferSizeCallback(glfw_window, framebuffer_size_callback);
glfwSetCharModsCallback(glfw_window, char_mods_callback); glfwSetCharModsCallback(glfw_window, char_mods_callback);
glfwSetMouseButtonCallback(glfw_window, mouse_button_callback); glfwSetMouseButtonCallback(glfw_window, mouse_button_callback);

View File

@ -98,6 +98,8 @@ typedef struct {
PyObject *window_title; PyObject *window_title;
bool is_key_pressed[MAX_KEY_COUNT]; bool is_key_pressed[MAX_KEY_COUNT];
bool viewport_size_dirty; bool viewport_size_dirty;
double last_resize_at;
bool has_pending_resizes;
} OSWindow; } OSWindow;
@ -115,6 +117,7 @@ typedef struct {
bool close_all_windows; bool close_all_windows;
bool is_wayland; bool is_wayland;
bool debug_gl; bool debug_gl;
bool has_pending_resizes;
} GlobalState; } GlobalState;
extern GlobalState global_state; extern GlobalState global_state;
@ -125,11 +128,14 @@ extern GlobalState global_state;
else Py_DECREF(cret_); \ else Py_DECREF(cret_); \
} }
#define RESIZE_DEBOUNCE_TIME 0.2
void gl_init(); void gl_init();
void remove_vao(ssize_t vao_idx); void remove_vao(ssize_t vao_idx);
bool remove_os_window(id_type os_window_id); bool remove_os_window(id_type os_window_id);
void remove_os_window_reference(OSWindow *w); void remove_os_window_reference(OSWindow *w);
void mark_os_window_for_close(OSWindow* w, bool yes); void mark_os_window_for_close(OSWindow* w, bool yes);
void update_os_window_viewport(OSWindow *window, bool);
bool should_os_window_close(OSWindow* w); bool should_os_window_close(OSWindow* w);
bool should_os_window_be_rendered(OSWindow* w); bool should_os_window_be_rendered(OSWindow* w);
void wakeup_main_loop(); void wakeup_main_loop();