Simplify the event loop code
Also reduce input latency by ignoring repaint_delay when there is actual pending input. Gets rid of request_tick_callback(). Now empty events result in the tick callback being called so there is only a single mechanism for waking up the main loop and getting the tick callback called.
This commit is contained in:
parent
5521d6b623
commit
1cb15dedac
23
glfw/backend_utils.c
vendored
23
glfw/backend_utils.c
vendored
@ -222,19 +222,25 @@ dispatchTimers(EventLoopData *eld) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drain_wakeup_fd(int fd, int events UNUSED, void* data UNUSED) {
|
drain_wakeup_fd(int fd, EventLoopData* eld) {
|
||||||
static char drain_buf[64];
|
static char drain_buf[64];
|
||||||
|
eld->wakeup_data_read = false;
|
||||||
while(true) {
|
while(true) {
|
||||||
ssize_t ret = read(fd, drain_buf, sizeof(drain_buf));
|
ssize_t ret = read(fd, drain_buf, sizeof(drain_buf));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == EINTR) continue;
|
if (errno == EINTR) continue;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (ret > 0) continue;
|
if (ret > 0) { eld->wakeup_data_read = true; continue; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mark_wakep_fd_ready(int fd UNUSED, int events UNUSED, void *data) {
|
||||||
|
((EventLoopData*)(data))->wakeup_fd_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
initPollData(EventLoopData *eld, int display_fd) {
|
initPollData(EventLoopData *eld, int display_fd) {
|
||||||
if (!addWatch(eld, "display", display_fd, POLLIN, 1, NULL, NULL)) return false;
|
if (!addWatch(eld, "display", display_fd, POLLIN, 1, NULL, NULL)) return false;
|
||||||
@ -246,10 +252,20 @@ initPollData(EventLoopData *eld, int display_fd) {
|
|||||||
if (pipe2(eld->wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0) return false;
|
if (pipe2(eld->wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0) return false;
|
||||||
const int wakeup_fd = eld->wakeupFds[0];
|
const int wakeup_fd = eld->wakeupFds[0];
|
||||||
#endif
|
#endif
|
||||||
if (!addWatch(eld, "wakeup", wakeup_fd, POLLIN, 1, drain_wakeup_fd, NULL)) return false;
|
if (!addWatch(eld, "wakeup", wakeup_fd, POLLIN, 1, mark_wakep_fd_ready, eld)) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
check_for_wakeup_events(EventLoopData *eld) {
|
||||||
|
#ifdef HAS_EVENT_FD
|
||||||
|
int fd = eld->wakeupFd;
|
||||||
|
#else
|
||||||
|
int fd = eld->wakeupFds[0];
|
||||||
|
#endif
|
||||||
|
drain_wakeup_fd(fd, eld);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
wakeupEventLoop(EventLoopData *eld) {
|
wakeupEventLoop(EventLoopData *eld) {
|
||||||
#ifdef HAS_EVENT_FD
|
#ifdef HAS_EVENT_FD
|
||||||
@ -289,6 +305,7 @@ pollForEvents(EventLoopData *eld, double timeout) {
|
|||||||
EVDBG("pollForEvents final timeout: %.3f", timeout);
|
EVDBG("pollForEvents final timeout: %.3f", timeout);
|
||||||
int result;
|
int result;
|
||||||
double end_time = monotonic() + timeout;
|
double end_time = monotonic() + timeout;
|
||||||
|
eld->wakeup_fd_ready = false;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if (timeout >= 0) {
|
if (timeout >= 0) {
|
||||||
|
|||||||
2
glfw/backend_utils.h
vendored
2
glfw/backend_utils.h
vendored
@ -66,12 +66,14 @@ typedef struct {
|
|||||||
#else
|
#else
|
||||||
int wakeupFds[2];
|
int wakeupFds[2];
|
||||||
#endif
|
#endif
|
||||||
|
bool wakeup_data_read, wakeup_fd_ready;
|
||||||
nfds_t watches_count, timers_count;
|
nfds_t watches_count, timers_count;
|
||||||
Watch watches[32];
|
Watch watches[32];
|
||||||
Timer timers[128];
|
Timer timers[128];
|
||||||
} EventLoopData;
|
} EventLoopData;
|
||||||
|
|
||||||
|
|
||||||
|
void check_for_wakeup_events(EventLoopData *eld);
|
||||||
id_type addWatch(EventLoopData *eld, const char *name, int fd, int events, int enabled, watch_callback_func cb, void *cb_data);
|
id_type addWatch(EventLoopData *eld, const char *name, int fd, int events, int enabled, watch_callback_func cb, void *cb_data);
|
||||||
void removeWatch(EventLoopData *eld, id_type watch_id);
|
void removeWatch(EventLoopData *eld, id_type watch_id);
|
||||||
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
|
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include <sys/param.h> // For MAXPATHLEN
|
#include <sys/param.h> // For MAXPATHLEN
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
// Change to our application bundle's resources directory, if present
|
// Change to our application bundle's resources directory, if present
|
||||||
//
|
//
|
||||||
@ -471,32 +472,56 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
static GLFWtickcallback tick_callback = NULL;
|
static GLFWtickcallback tick_callback = NULL;
|
||||||
static void* tick_callback_data = NULL;
|
static void* tick_callback_data = NULL;
|
||||||
static bool tick_callback_requested = false;
|
static bool tick_callback_requested = false;
|
||||||
|
static pthread_t main_thread;
|
||||||
|
static NSLock *tick_lock = NULL;
|
||||||
|
|
||||||
|
|
||||||
void _glfwDispatchTickCallback() {
|
void _glfwDispatchTickCallback() {
|
||||||
if (tick_callback) {
|
if (tick_lock && tick_callback) {
|
||||||
|
[tick_lock lock];
|
||||||
|
while(tick_callback_requested) {
|
||||||
tick_callback_requested = false;
|
tick_callback_requested = false;
|
||||||
tick_callback(tick_callback_data);
|
tick_callback(tick_callback_data);
|
||||||
}
|
}
|
||||||
|
[tick_lock unlock];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRequestTickCallback() {
|
static void
|
||||||
|
request_tick_callback() {
|
||||||
if (!tick_callback_requested) {
|
if (!tick_callback_requested) {
|
||||||
tick_callback_requested = true;
|
tick_callback_requested = true;
|
||||||
[NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO];
|
[NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwPlatformPostEmptyEvent(void)
|
||||||
|
{
|
||||||
|
if (pthread_equal(pthread_self(), main_thread)) {
|
||||||
|
request_tick_callback();
|
||||||
|
} else if (tick_lock) {
|
||||||
|
[tick_lock lock];
|
||||||
|
request_tick_callback();
|
||||||
|
[tick_lock unlock];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _glfwPlatformStopMainLoop(void) {
|
void _glfwPlatformStopMainLoop(void) {
|
||||||
tick_callback = NULL;
|
|
||||||
[NSApp stop:nil];
|
[NSApp stop:nil];
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwCocoaPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) {
|
void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) {
|
||||||
|
main_thread = pthread_self();
|
||||||
tick_callback = callback;
|
tick_callback = callback;
|
||||||
tick_callback_data = data;
|
tick_callback_data = data;
|
||||||
|
tick_lock = [NSLock new];
|
||||||
[NSApp run];
|
[NSApp run];
|
||||||
|
[tick_lock release];
|
||||||
|
tick_lock = NULL;
|
||||||
|
tick_callback = NULL;
|
||||||
|
tick_callback_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
glfw/cocoa_platform.h
vendored
2
glfw/cocoa_platform.h
vendored
@ -225,7 +225,7 @@ float _glfwTransformYNS(float y);
|
|||||||
|
|
||||||
void _glfwClearDisplayLinks(void);
|
void _glfwClearDisplayLinks(void);
|
||||||
void _glfwRestartDisplayLinks(void);
|
void _glfwRestartDisplayLinks(void);
|
||||||
void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start);
|
|
||||||
void _glfwDispatchTickCallback(void);
|
void _glfwDispatchTickCallback(void);
|
||||||
void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
void _glfwDispatchRenderFrame(CGDirectDisplayID);
|
||||||
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
|
||||||
|
void _glfwCocoaPostEmptyEvent(void);
|
||||||
|
|||||||
@ -579,7 +579,7 @@ static GLFWapplicationshouldhandlereopenfun handle_reopen_callback = NULL;
|
|||||||
[NSApp stop:nil];
|
[NSApp stop:nil];
|
||||||
|
|
||||||
CGDisplayRegisterReconfigurationCallback(display_reconfigured, NULL);
|
CGDisplayRegisterReconfigurationCallback(display_reconfigured, NULL);
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwCocoaPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
- (void)applicationWillTerminate:(NSNotification *)aNotification
|
||||||
@ -1916,29 +1916,6 @@ _glfwDispatchRenderFrame(CGDirectDisplayID displayID) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start)
|
|
||||||
{
|
|
||||||
@autoreleasepool {
|
|
||||||
|
|
||||||
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
|
||||||
location:NSMakePoint(0, 0)
|
|
||||||
modifierFlags:0
|
|
||||||
timestamp:0
|
|
||||||
windowNumber:0
|
|
||||||
context:nil
|
|
||||||
subtype:subtype
|
|
||||||
data1:data1
|
|
||||||
data2:0];
|
|
||||||
[NSApp postEvent:event atStart:at_start ? YES : NO];
|
|
||||||
|
|
||||||
} // autoreleasepool
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformPostEmptyEvent(void)
|
|
||||||
{
|
|
||||||
_glfwCocoaPostEmptyEvent(0, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
|
||||||
{
|
{
|
||||||
const NSRect contentRect = [window->ns.view frame];
|
const NSRect contentRect = [window->ns.view frame];
|
||||||
@ -2381,3 +2358,16 @@ float _glfwTransformYNS(float y)
|
|||||||
{
|
{
|
||||||
return CGDisplayBounds(CGMainDisplayID()).size.height - y - 1;
|
return CGDisplayBounds(CGMainDisplayID()).size.height - y - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _glfwCocoaPostEmptyEvent(void) {
|
||||||
|
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined
|
||||||
|
location:NSMakePoint(0, 0)
|
||||||
|
modifierFlags:0
|
||||||
|
timestamp:0
|
||||||
|
windowNumber:0
|
||||||
|
context:nil
|
||||||
|
subtype:0
|
||||||
|
data1:0
|
||||||
|
data2:0];
|
||||||
|
[NSApp postEvent:event atStart:YES];
|
||||||
|
}
|
||||||
|
|||||||
1
glfw/glfw3.h
vendored
1
glfw/glfw3.h
vendored
@ -1628,7 +1628,6 @@ typedef struct GLFWgamepadstate
|
|||||||
GLFWAPI int glfwInit(void);
|
GLFWAPI int glfwInit(void);
|
||||||
GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *callback_data);
|
GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *callback_data);
|
||||||
GLFWAPI void glfwStopMainLoop(void);
|
GLFWAPI void glfwStopMainLoop(void);
|
||||||
GLFWAPI void glfwRequestTickCallback(void);
|
|
||||||
GLFWAPI unsigned long long glfwAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void * callback_data, GLFWuserdatafun free_callback);
|
GLFWAPI unsigned long long glfwAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void * callback_data, GLFWuserdatafun free_callback);
|
||||||
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
|
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
|
||||||
GLFWAPI void glfwRemoveTimer(unsigned long long);
|
GLFWAPI void glfwRemoveTimer(unsigned long long);
|
||||||
|
|||||||
4
glfw/init.c
vendored
4
glfw/init.c
vendored
@ -342,10 +342,6 @@ GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *data)
|
|||||||
_glfwPlatformRunMainLoop(callback, data);
|
_glfwPlatformRunMainLoop(callback, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwRequestTickCallback(void) {
|
|
||||||
_glfwPlatformRequestTickCallback();
|
|
||||||
}
|
|
||||||
|
|
||||||
GLFWAPI void glfwStopMainLoop(void) {
|
GLFWAPI void glfwStopMainLoop(void) {
|
||||||
_GLFW_REQUIRE_INIT();
|
_GLFW_REQUIRE_INIT();
|
||||||
_glfwPlatformStopMainLoop();
|
_glfwPlatformStopMainLoop();
|
||||||
|
|||||||
1
glfw/internal.h
vendored
1
glfw/internal.h
vendored
@ -822,7 +822,6 @@ const char* _glfwGetVulkanResultString(VkResult result);
|
|||||||
_GLFWwindow* _glfwFocusedWindow(void);
|
_GLFWwindow* _glfwFocusedWindow(void);
|
||||||
_GLFWwindow* _glfwWindowForId(GLFWid id);
|
_GLFWwindow* _glfwWindowForId(GLFWid id);
|
||||||
void _glfwPlatformRunMainLoop(GLFWtickcallback, void*);
|
void _glfwPlatformRunMainLoop(GLFWtickcallback, void*);
|
||||||
void _glfwPlatformRequestTickCallback(void);
|
|
||||||
void _glfwPlatformStopMainLoop(void);
|
void _glfwPlatformStopMainLoop(void);
|
||||||
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback);
|
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback);
|
||||||
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
|
void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
|
||||||
|
|||||||
26
glfw/main_loop.h
vendored
26
glfw/main_loop.h
vendored
@ -13,36 +13,26 @@
|
|||||||
#define GLFW_LOOP_BACKEND x11
|
#define GLFW_LOOP_BACKEND x11
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static volatile atomic_int keep_going = 0, tick_callback_requested = 0;
|
static bool keep_going = false;
|
||||||
|
|
||||||
void _glfwPlatformRequestTickCallback() {
|
|
||||||
EVDBG("tick_callback requested");
|
|
||||||
tick_callback_requested = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformStopMainLoop(void) {
|
void _glfwPlatformStopMainLoop(void) {
|
||||||
if (keep_going) {
|
if (keep_going) {
|
||||||
keep_going = 0;
|
keep_going = false;
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwPlatformPostEmptyEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
dispatch_tick_callbacks(GLFWtickcallback tick_callback, void *data) {
|
|
||||||
while (tick_callback_requested) {
|
|
||||||
EVDBG("Calling tick callback");
|
|
||||||
tick_callback_requested = 0;
|
|
||||||
tick_callback(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) {
|
void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) {
|
||||||
keep_going = 1;
|
keep_going = 1;
|
||||||
tick_callback_requested = 0;
|
EventLoopData *eld = &_glfw.GLFW_LOOP_BACKEND.eventLoopData;
|
||||||
while(keep_going) {
|
while(keep_going) {
|
||||||
EVDBG("loop tick, tick_callback_requested: %d", tick_callback_requested);
|
|
||||||
dispatch_tick_callbacks(tick_callback, data);
|
|
||||||
_glfwPlatformWaitEvents();
|
_glfwPlatformWaitEvents();
|
||||||
|
EVDBG("--------- loop tick, wakeups_happened: %d ----------", eld->wakeup_data_read);
|
||||||
|
if (eld->wakeup_data_read) {
|
||||||
|
eld->wakeup_data_read = false;
|
||||||
|
tick_callback(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EVDBG("main loop exiting");
|
EVDBG("main loop exiting");
|
||||||
}
|
}
|
||||||
|
|||||||
1
glfw/wl_window.c
vendored
1
glfw/wl_window.c
vendored
@ -783,6 +783,7 @@ handleEvents(double timeout)
|
|||||||
}
|
}
|
||||||
glfw_ibus_dispatch(&_glfw.wl.xkb.ibus);
|
glfw_ibus_dispatch(&_glfw.wl.xkb.ibus);
|
||||||
glfw_dbus_session_bus_dispatch();
|
glfw_dbus_session_bus_dispatch();
|
||||||
|
if (_glfw.wl.eventLoopData.wakeup_fd_ready) check_for_wakeup_events(&_glfw.wl.eventLoopData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wl_cursor*
|
static struct wl_cursor*
|
||||||
|
|||||||
1
glfw/x11_window.c
vendored
1
glfw/x11_window.c
vendored
@ -71,6 +71,7 @@ handleEvents(double timeout) {
|
|||||||
glfw_ibus_dispatch(&_glfw.x11.xkb.ibus);
|
glfw_ibus_dispatch(&_glfw.x11.xkb.ibus);
|
||||||
glfw_dbus_session_bus_dispatch();
|
glfw_dbus_session_bus_dispatch();
|
||||||
EVDBG("other dispatch done");
|
EVDBG("other dispatch done");
|
||||||
|
if (_glfw.x11.eventLoopData.wakeup_fd_ready) check_for_wakeup_events(&_glfw.x11.eventLoopData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
|||||||
@ -295,13 +295,15 @@ shutdown_monitor(ChildMonitor *self, PyObject *a UNUSED) {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline bool
|
||||||
do_parse(ChildMonitor *self, Screen *screen, double now) {
|
do_parse(ChildMonitor *self, Screen *screen, double now) {
|
||||||
|
bool input_read = false;
|
||||||
screen_mutex(lock, read);
|
screen_mutex(lock, read);
|
||||||
if (screen->read_buf_sz || screen->pending_mode.used) {
|
if (screen->read_buf_sz || screen->pending_mode.used) {
|
||||||
double time_since_new_input = now - screen->new_input_at;
|
double time_since_new_input = now - screen->new_input_at;
|
||||||
if (time_since_new_input >= OPT(input_delay)) {
|
if (time_since_new_input >= OPT(input_delay)) {
|
||||||
bool read_buf_full = screen->read_buf_sz >= READ_BUF_SZ;
|
bool read_buf_full = screen->read_buf_sz >= READ_BUF_SZ;
|
||||||
|
input_read = true;
|
||||||
parse_func(screen, self->dump_callback, now);
|
parse_func(screen, self->dump_callback, now);
|
||||||
if (read_buf_full) wakeup_io_loop(self, false); // Ensure the read fd has POLLIN set
|
if (read_buf_full) wakeup_io_loop(self, false); // Ensure the read fd has POLLIN set
|
||||||
screen->new_input_at = 0;
|
screen->new_input_at = 0;
|
||||||
@ -312,12 +314,14 @@ do_parse(ChildMonitor *self, Screen *screen, double now) {
|
|||||||
} else set_maximum_wait(OPT(input_delay) - time_since_new_input);
|
} else set_maximum_wait(OPT(input_delay) - time_since_new_input);
|
||||||
}
|
}
|
||||||
screen_mutex(unlock, read);
|
screen_mutex(unlock, read);
|
||||||
|
return input_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static bool
|
||||||
parse_input(ChildMonitor *self) {
|
parse_input(ChildMonitor *self) {
|
||||||
// Parse all available input that was read in the I/O thread.
|
// Parse all available input that was read in the I/O thread.
|
||||||
size_t count = 0, remove_count = 0;
|
size_t count = 0, remove_count = 0;
|
||||||
|
bool input_read = false;
|
||||||
double now = monotonic();
|
double now = monotonic();
|
||||||
PyObject *msg = NULL;
|
PyObject *msg = NULL;
|
||||||
children_mutex(lock);
|
children_mutex(lock);
|
||||||
@ -372,10 +376,11 @@ parse_input(ChildMonitor *self) {
|
|||||||
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
if (!scratch[i].needs_removal) {
|
if (!scratch[i].needs_removal) {
|
||||||
do_parse(self, scratch[i].screen, now);
|
if (do_parse(self, scratch[i].screen, now)) input_read = true;
|
||||||
}
|
}
|
||||||
DECREF_CHILD(scratch[i]);
|
DECREF_CHILD(scratch[i]);
|
||||||
}
|
}
|
||||||
|
return input_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -634,10 +639,11 @@ no_render_frame_received_recently(OSWindow *w, double now, double max_wait) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
render(double now) {
|
render(double now, bool input_read) {
|
||||||
|
EVDBG("input_read: %d", input_read);
|
||||||
static double last_render_at = -DBL_MAX;
|
static double last_render_at = -DBL_MAX;
|
||||||
double time_since_last_render = now - last_render_at;
|
double time_since_last_render = now - last_render_at;
|
||||||
if (time_since_last_render < OPT(repaint_delay)) {
|
if (!input_read && time_since_last_render < OPT(repaint_delay)) {
|
||||||
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -905,7 +911,8 @@ process_global_state(void *data) {
|
|||||||
|
|
||||||
double now = monotonic();
|
double now = monotonic();
|
||||||
if (global_state.has_pending_resizes) process_pending_resizes(now);
|
if (global_state.has_pending_resizes) process_pending_resizes(now);
|
||||||
render(now);
|
bool input_read = parse_input(self);
|
||||||
|
render(now, input_read);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (cocoa_pending_actions) {
|
if (cocoa_pending_actions) {
|
||||||
if (cocoa_pending_actions & PREFERENCES_WINDOW) { call_boss(edit_config_file, NULL); }
|
if (cocoa_pending_actions & PREFERENCES_WINDOW) { call_boss(edit_config_file, NULL); }
|
||||||
@ -919,7 +926,6 @@ process_global_state(void *data) {
|
|||||||
cocoa_pending_actions = 0;
|
cocoa_pending_actions = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
parse_input(self);
|
|
||||||
if (global_state.terminate) {
|
if (global_state.terminate) {
|
||||||
global_state.terminate = false;
|
global_state.terminate = false;
|
||||||
close_all_windows();
|
close_all_windows();
|
||||||
|
|||||||
@ -481,7 +481,8 @@ Delay (in milliseconds) between screen updates. Decreasing it, increases
|
|||||||
frames-per-second (FPS) at the cost of more CPU usage. The default value
|
frames-per-second (FPS) at the cost of more CPU usage. The default value
|
||||||
yields ~100 FPS which is more than sufficient for most uses. Note that to
|
yields ~100 FPS which is more than sufficient for most uses. Note that to
|
||||||
actually achieve 100 FPS you have to either set :opt:`sync_to_monitor` to no
|
actually achieve 100 FPS you have to either set :opt:`sync_to_monitor` to no
|
||||||
or use a monitor with a high refresh rate.'''))
|
or use a monitor with a high refresh rate. Also, to minimize latency
|
||||||
|
when there is pending input to be processed, repaint_delay is ignored.'''))
|
||||||
|
|
||||||
o('input_delay', 3, option_type=positive_int, long_text=_('''
|
o('input_delay', 3, option_type=positive_int, long_text=_('''
|
||||||
Delay (in milliseconds) before input from the program running in the terminal
|
Delay (in milliseconds) before input from the program running in the terminal
|
||||||
|
|||||||
3
kitty/glfw-wrapper.c
generated
3
kitty/glfw-wrapper.c
generated
@ -23,9 +23,6 @@ load_glfw(const char* path) {
|
|||||||
*(void **) (&glfwStopMainLoop_impl) = dlsym(handle, "glfwStopMainLoop");
|
*(void **) (&glfwStopMainLoop_impl) = dlsym(handle, "glfwStopMainLoop");
|
||||||
if (glfwStopMainLoop_impl == NULL) fail("Failed to load glfw function glfwStopMainLoop with error: %s", dlerror());
|
if (glfwStopMainLoop_impl == NULL) fail("Failed to load glfw function glfwStopMainLoop with error: %s", dlerror());
|
||||||
|
|
||||||
*(void **) (&glfwRequestTickCallback_impl) = dlsym(handle, "glfwRequestTickCallback");
|
|
||||||
if (glfwRequestTickCallback_impl == NULL) fail("Failed to load glfw function glfwRequestTickCallback with error: %s", dlerror());
|
|
||||||
|
|
||||||
*(void **) (&glfwAddTimer_impl) = dlsym(handle, "glfwAddTimer");
|
*(void **) (&glfwAddTimer_impl) = dlsym(handle, "glfwAddTimer");
|
||||||
if (glfwAddTimer_impl == NULL) fail("Failed to load glfw function glfwAddTimer with error: %s", dlerror());
|
if (glfwAddTimer_impl == NULL) fail("Failed to load glfw function glfwAddTimer with error: %s", dlerror());
|
||||||
|
|
||||||
|
|||||||
4
kitty/glfw-wrapper.h
generated
4
kitty/glfw-wrapper.h
generated
@ -1403,10 +1403,6 @@ typedef void (*glfwStopMainLoop_func)(void);
|
|||||||
glfwStopMainLoop_func glfwStopMainLoop_impl;
|
glfwStopMainLoop_func glfwStopMainLoop_impl;
|
||||||
#define glfwStopMainLoop glfwStopMainLoop_impl
|
#define glfwStopMainLoop glfwStopMainLoop_impl
|
||||||
|
|
||||||
typedef void (*glfwRequestTickCallback_func)(void);
|
|
||||||
glfwRequestTickCallback_func glfwRequestTickCallback_impl;
|
|
||||||
#define glfwRequestTickCallback glfwRequestTickCallback_impl
|
|
||||||
|
|
||||||
typedef unsigned long long (*glfwAddTimer_func)(double, bool, GLFWuserdatafun, void *, GLFWuserdatafun);
|
typedef unsigned long long (*glfwAddTimer_func)(double, bool, GLFWuserdatafun, void *, GLFWuserdatafun);
|
||||||
glfwAddTimer_func glfwAddTimer_impl;
|
glfwAddTimer_func glfwAddTimer_impl;
|
||||||
#define glfwAddTimer glfwAddTimer_impl
|
#define glfwAddTimer glfwAddTimer_impl
|
||||||
|
|||||||
@ -30,7 +30,7 @@ static void set_os_window_dpi(OSWindow *w);
|
|||||||
|
|
||||||
void
|
void
|
||||||
request_tick_callback(void) {
|
request_tick_callback(void) {
|
||||||
glfwRequestTickCallback();
|
glfwPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int min_width = 100, min_height = 100;
|
static int min_width = 100, min_height = 100;
|
||||||
@ -934,12 +934,7 @@ swap_window_buffers(OSWindow *os_window) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
wakeup_main_loop() {
|
wakeup_main_loop() {
|
||||||
request_tick_callback();
|
|
||||||
#ifndef __APPLE__
|
|
||||||
// On Cocoa request_tick_callback() uses performSelectorOnMainLoop which
|
|
||||||
// wakes up the main loop anyway
|
|
||||||
glfwPostEmptyEvent();
|
glfwPostEmptyEvent();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -25,8 +25,7 @@ static void* empty_thread_main(void* data UNUSED)
|
|||||||
while (running)
|
while (running)
|
||||||
{
|
{
|
||||||
nanosleep(&time, NULL);
|
nanosleep(&time, NULL);
|
||||||
glfwRequestTickCallback();
|
wakeup_main_loop();
|
||||||
glfwPostEmptyEvent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -43,7 +42,6 @@ static void key_callback(GLFWwindow *w UNUSED, int key, int scancode UNUSED, int
|
|||||||
static void
|
static void
|
||||||
window_close_callback(GLFWwindow* window) {
|
window_close_callback(GLFWwindow* window) {
|
||||||
glfwSetWindowShouldClose(window, true);
|
glfwSetWindowShouldClose(window, true);
|
||||||
glfwRequestTickCallback();
|
|
||||||
wakeup_main_loop();
|
wakeup_main_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user