From 78efefcea1e3e3b8f900c9d80a10f7fafbc56cf1 Mon Sep 17 00:00:00 2001 From: Luflosi Date: Thu, 23 Jul 2020 13:32:52 +0200 Subject: [PATCH 1/4] Revert "Linux: Fix slow startup on some systems caused by GLFW searching for joysticks. Since kitty does not use joysticks, disable joystick support." This reverts commit ab960ea12d3e1e3489898b663f8d678ece8b2409. --- glfw/glfw3.h | 1 - glfw/init.c | 4 ---- glfw/internal.h | 1 - glfw/wl_init.c | 6 ++---- glfw/x11_init.c | 10 ++++------ glfw/x11_window.c | 2 +- kitty/glfw-wrapper.h | 1 - kitty/glfw.c | 3 --- 8 files changed, 7 insertions(+), 21 deletions(-) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 4215dcf32..601dbeef8 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1202,7 +1202,6 @@ typedef enum { */ #define GLFW_ANGLE_PLATFORM_TYPE 0x00050002 #define GLFW_DEBUG_KEYBOARD 0x00050003 -#define GLFW_ENABLE_JOYSTICKS 0x00050004 /*! @brief macOS specific init hint. * * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint). diff --git a/glfw/init.c b/glfw/init.c index ca3af4d0c..80d1d9387 100644 --- a/glfw/init.c +++ b/glfw/init.c @@ -55,7 +55,6 @@ static _GLFWinitconfig _glfwInitHints = true, // hat buttons GLFW_ANGLE_PLATFORM_TYPE_NONE, // ANGLE backend false, // debug keyboard - true, // enable joystick { true, // macOS menu bar true // macOS bundle chdir @@ -276,9 +275,6 @@ GLFWAPI void glfwInitHint(int hint, int value) { switch (hint) { - case GLFW_ENABLE_JOYSTICKS: - _glfwInitHints.enableJoysticks = value; - return; case GLFW_JOYSTICK_HAT_BUTTONS: _glfwInitHints.hatButtons = value; return; diff --git a/glfw/internal.h b/glfw/internal.h index f6f849d16..feb150d0c 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -276,7 +276,6 @@ struct _GLFWinitconfig bool hatButtons; int angleType; bool debugKeyboard; - bool enableJoysticks; struct { bool menubar; bool chdir; diff --git a/glfw/wl_init.c b/glfw/wl_init.c index 1db1b8b79..ae78fcbac 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -772,10 +772,8 @@ int _glfwPlatformInit(void) wl_display_roundtrip(_glfw.wl.display); #ifdef __linux__ - if (_glfw.hints.init.enableJoysticks) { - if (!_glfwInitJoysticksLinux()) - return false; - } + if (!_glfwInitJoysticksLinux()) + return false; #endif if (!_glfw.wl.wmBase) diff --git a/glfw/x11_init.c b/glfw/x11_init.c index 4252f4490..c9dfa252d 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -654,12 +654,10 @@ int _glfwPlatformInit(void) _glfw.x11.hiddenCursorHandle = createHiddenCursor(); #if defined(__linux__) - if (_glfw.hints.init.enableJoysticks) { - if (!_glfwInitJoysticksLinux()) - return false; - if (_glfw.linjs.inotify > 0) - addWatch(&_glfw.x11.eventLoopData, "joystick", _glfw.linjs.inotify, POLLIN, 1, NULL, NULL); - } + if (!_glfwInitJoysticksLinux()) + return false; + if (_glfw.linjs.inotify > 0) + addWatch(&_glfw.x11.eventLoopData, "joystick", _glfw.linjs.inotify, POLLIN, 1, NULL, NULL); #endif _glfwPollMonitorsX11(); diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 15d2f1c6f..f8dce617f 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2653,7 +2653,7 @@ _glfwDispatchX11Events(void) { unsigned dispatched = 0; #if defined(__linux__) - if (_glfw.hints.init.enableJoysticks) _glfwDetectJoystickConnectionLinux(); + _glfwDetectJoystickConnectionLinux(); #endif dispatched += dispatch_x11_queued_events(XEventsQueued(_glfw.x11.display, QueuedAfterFlush)); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 61762bf13..8ee395f63 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -940,7 +940,6 @@ typedef enum { */ #define GLFW_ANGLE_PLATFORM_TYPE 0x00050002 #define GLFW_DEBUG_KEYBOARD 0x00050003 -#define GLFW_ENABLE_JOYSTICKS 0x00050004 /*! @brief macOS specific init hint. * * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint). diff --git a/kitty/glfw.c b/kitty/glfw.c index 72208ae71..9587bdcb9 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -814,9 +814,6 @@ glfw_init(PyObject UNUSED *self, PyObject *args) { if (err) { PyErr_SetString(PyExc_RuntimeError, err); return NULL; } glfwSetErrorCallback(error_callback); glfwInitHint(GLFW_DEBUG_KEYBOARD, debug_keyboard); - // Joysticks cause slow startup on some linux systems, see - // https://github.com/kovidgoyal/kitty/issues/830 - glfwInitHint(GLFW_ENABLE_JOYSTICKS, 0); OPT(debug_keyboard) = debug_keyboard != 0; #ifdef __APPLE__ glfwInitHint(GLFW_COCOA_CHDIR_RESOURCES, 0); From 785973bb5e55bfb3b81793785e5411f0bb029fa7 Mon Sep 17 00:00:00 2001 From: Luflosi Date: Thu, 23 Jul 2020 13:46:55 +0200 Subject: [PATCH 2/4] GLFW: Make joystick platform code init on demand From upstream: https://github.com/glfw/glfw/commit/782e6b6cefc9ac2a2b6779f9e658ab948809253b. --- glfw/cocoa_init.m | 3 --- glfw/cocoa_joystick.h | 4 ---- glfw/cocoa_joystick.m | 14 ++++++++----- glfw/init.c | 1 + glfw/input.c | 47 +++++++++++++++++++++++++++++++++++++++++++ glfw/internal.h | 3 +++ glfw/linux_joystick.c | 7 +++---- glfw/linux_joystick.h | 3 --- glfw/null_joystick.c | 9 +++++++++ glfw/wl_init.c | 8 -------- glfw/x11_init.c | 10 --------- 11 files changed, 72 insertions(+), 37 deletions(-) diff --git a/glfw/cocoa_init.m b/glfw/cocoa_init.m index 29e087a13..5ae1052ff 100644 --- a/glfw/cocoa_init.m +++ b/glfw/cocoa_init.m @@ -669,8 +669,6 @@ int _glfwPlatformInit(void) if (!initializeTIS()) return false; - _glfwInitJoysticksNS(); - _glfwPollMonitorsNS(); return true; @@ -723,7 +721,6 @@ void _glfwPlatformTerminate(void) free(_glfw.ns.clipboardString); _glfwTerminateNSGL(); - _glfwTerminateJoysticksNS(); } // autoreleasepool } diff --git a/glfw/cocoa_joystick.h b/glfw/cocoa_joystick.h index ce98221ae..4775342eb 100644 --- a/glfw/cocoa_joystick.h +++ b/glfw/cocoa_joystick.h @@ -44,7 +44,3 @@ typedef struct _GLFWjoystickNS CFMutableArrayRef hats; } _GLFWjoystickNS; - -void _glfwInitJoysticksNS(void); -void _glfwTerminateJoysticksNS(void); - diff --git a/glfw/cocoa_joystick.m b/glfw/cocoa_joystick.m index 1425599d3..5049b6ebf 100644 --- a/glfw/cocoa_joystick.m +++ b/glfw/cocoa_joystick.m @@ -296,7 +296,7 @@ static void removeCallback(void* context UNUSED, // Initialize joystick interface // -void _glfwInitJoysticksNS(void) +bool _glfwPlatformInitJoysticks(void) { CFMutableArrayRef matching; const long usages[] = @@ -315,7 +315,7 @@ void _glfwInitJoysticksNS(void) if (!matching) { _glfwInputError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create array"); - return; + return false; } for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++) @@ -370,19 +370,23 @@ void _glfwInitJoysticksNS(void) // Execute the run loop once in order to register any initially-attached // joysticks CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false); + return true; } // Close all opened joystick handles // -void _glfwTerminateJoysticksNS(void) +void _glfwPlatformTerminateJoysticks(void) { int jid; for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) closeJoystick(_glfw.joysticks + jid); - CFRelease(_glfw.ns.hidManager); - _glfw.ns.hidManager = NULL; + if (_glfw.ns.hidManager) + { + CFRelease(_glfw.ns.hidManager); + _glfw.ns.hidManager = NULL; + } } diff --git a/glfw/init.c b/glfw/init.c index 80d1d9387..2ed62d5c1 100644 --- a/glfw/init.c +++ b/glfw/init.c @@ -92,6 +92,7 @@ static void terminate(void) _glfw.mappingCount = 0; _glfwTerminateVulkan(); + _glfwPlatformTerminateJoysticks(); _glfwPlatformTerminate(); _glfw.initialized = false; diff --git a/glfw/input.c b/glfw/input.c index a08fd1097..bc0a66d8f 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -44,6 +44,22 @@ #define _GLFW_JOYSTICK_BUTTON 2 #define _GLFW_JOYSTICK_HATBIT 3 +// Initializes the platform joystick API if it has not been already +// +static bool initJoysticks(void) +{ + if (!_glfw.joysticksInitialized) + { + if (!_glfwPlatformInitJoysticks()) + { + _glfwPlatformTerminateJoysticks(); + return false; + } + } + + return _glfw.joysticksInitialized = true; +} + // Finds a mapping based on joystick GUID // static _GLFWmapping* findMapping(const char* guid) @@ -1101,6 +1117,9 @@ GLFWAPI int glfwJoystickPresent(int jid) return false; } + if (!initJoysticks()) + return false; + js = _glfw.joysticks + jid; if (!js->present) return false; @@ -1126,6 +1145,9 @@ GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1155,6 +1177,9 @@ GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1188,6 +1213,9 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1214,6 +1242,9 @@ GLFWAPI const char* glfwGetJoystickName(int jid) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1239,6 +1270,9 @@ GLFWAPI const char* glfwGetJoystickGUID(int jid) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1284,6 +1318,10 @@ GLFWAPI void* glfwGetJoystickUserPointer(int jid) GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun cbfun) { _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + + if (!initJoysticks()) + return NULL; + _GLFW_SWAP_POINTERS(_glfw.callbacks.joystick, cbfun); return cbfun; } @@ -1363,6 +1401,9 @@ GLFWAPI int glfwJoystickIsGamepad(int jid) return false; } + if (!initJoysticks()) + return false; + js = _glfw.joysticks + jid; if (!js->present) return false; @@ -1388,6 +1429,9 @@ GLFWAPI const char* glfwGetGamepadName(int jid) return NULL; } + if (!initJoysticks()) + return NULL; + js = _glfw.joysticks + jid; if (!js->present) return NULL; @@ -1420,6 +1464,9 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state) return false; } + if (!initJoysticks()) + return false; + js = _glfw.joysticks + jid; if (!js->present) return false; diff --git a/glfw/internal.h b/glfw/internal.h index feb150d0c..e020f6557 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -574,6 +574,7 @@ struct _GLFWlibrary _GLFWmonitor** monitors; int monitorCount; + bool joysticksInitialized; _GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1]; _GLFWmapping* mappings; int mappingCount; @@ -667,6 +668,8 @@ void _glfwPlatformSetPrimarySelectionString(const char* string); const char* _glfwPlatformGetPrimarySelectionString(void); #endif +bool _glfwPlatformInitJoysticks(void); +void _glfwPlatformTerminateJoysticks(void); int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode); void _glfwPlatformUpdateGamepadGUID(char* guid); diff --git a/glfw/linux_joystick.c b/glfw/linux_joystick.c index d29471b38..0cde579ae 100644 --- a/glfw/linux_joystick.c +++ b/glfw/linux_joystick.c @@ -266,7 +266,7 @@ static int compareJoysticks(const void* fp, const void* sp) // Initialize joystick interface // -bool _glfwInitJoysticksLinux(void) +bool _glfwPlatformInitJoysticks(void) { const char* dirname = "/dev/input"; @@ -322,7 +322,7 @@ bool _glfwInitJoysticksLinux(void) // Close all opened joystick handles // -void _glfwTerminateJoysticksLinux(void) +void _glfwPlatformTerminateJoysticks(void) { int jid; @@ -333,14 +333,13 @@ void _glfwTerminateJoysticksLinux(void) closeJoystick(js); } - regfree(&_glfw.linjs.regex); - if (_glfw.linjs.inotify > 0) { if (_glfw.linjs.watch > 0) inotify_rm_watch(_glfw.linjs.inotify, _glfw.linjs.watch); close(_glfw.linjs.inotify); + regfree(&_glfw.linjs.regex); } } diff --git a/glfw/linux_joystick.h b/glfw/linux_joystick.h index 4870e5fcf..3a5c3300d 100644 --- a/glfw/linux_joystick.h +++ b/glfw/linux_joystick.h @@ -55,7 +55,4 @@ typedef struct _GLFWlibraryLinux bool dropped; } _GLFWlibraryLinux; - -bool _glfwInitJoysticksLinux(void); -void _glfwTerminateJoysticksLinux(void); void _glfwDetectJoystickConnectionLinux(void); diff --git a/glfw/null_joystick.c b/glfw/null_joystick.c index 2ed780b70..f3d8528f6 100644 --- a/glfw/null_joystick.c +++ b/glfw/null_joystick.c @@ -33,6 +33,15 @@ ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// +int _glfwPlatformInitJoysticks(void) +{ + return true; +} + +void _glfwPlatformTerminateJoysticks(void) +{ +} + int _glfwPlatformPollJoystick(_GLFWjoystick* js UNUSED, int mode UNUSED) { return false; diff --git a/glfw/wl_init.c b/glfw/wl_init.c index ae78fcbac..ed06f2d48 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -771,11 +771,6 @@ int _glfwPlatformInit(void) // Sync so we got all initial output events wl_display_roundtrip(_glfw.wl.display); -#ifdef __linux__ - if (!_glfwInitJoysticksLinux()) - return false; -#endif - if (!_glfw.wl.wmBase) { _glfwInputError(GLFW_PLATFORM_ERROR, @@ -799,9 +794,6 @@ int _glfwPlatformInit(void) void _glfwPlatformTerminate(void) { -#ifdef __linux__ - _glfwTerminateJoysticksLinux(); -#endif _glfwTerminateEGL(); if (_glfw.wl.egl.handle) { diff --git a/glfw/x11_init.c b/glfw/x11_init.c index c9dfa252d..80ab1601e 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -653,13 +653,6 @@ int _glfwPlatformInit(void) _glfw.x11.helperWindowHandle = createHelperWindow(); _glfw.x11.hiddenCursorHandle = createHiddenCursor(); -#if defined(__linux__) - if (!_glfwInitJoysticksLinux()) - return false; - if (_glfw.linjs.inotify > 0) - addWatch(&_glfw.x11.eventLoopData, "joystick", _glfw.linjs.inotify, POLLIN, 1, NULL, NULL); -#endif - _glfwPollMonitorsX11(); return true; } @@ -738,9 +731,6 @@ void _glfwPlatformTerminate(void) _glfwTerminateEGL(); _glfwTerminateGLX(); -#if defined(__linux__) - _glfwTerminateJoysticksLinux(); -#endif finalizePollData(&_glfw.x11.eventLoopData); } From 06b30d1cc3d4ff823f6baa3bf5612198bbef55b7 Mon Sep 17 00:00:00 2001 From: Luflosi Date: Thu, 23 Jul 2020 13:52:28 +0200 Subject: [PATCH 3/4] GLFW: Cleanup From upstream: https://github.com/glfw/glfw/commit/f771d412925f64c351167e7a1e6a7d35770d3ecf. --- glfw/cocoa_joystick.m | 10 +---- glfw/linux_joystick.c | 91 ++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 57 deletions(-) diff --git a/glfw/cocoa_joystick.m b/glfw/cocoa_joystick.m index 5049b6ebf..25588af45 100644 --- a/glfw/cocoa_joystick.m +++ b/glfw/cocoa_joystick.m @@ -291,11 +291,9 @@ static void removeCallback(void* context UNUSED, ////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// +////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -// Initialize joystick interface -// bool _glfwPlatformInitJoysticks(void) { CFMutableArrayRef matching; @@ -373,8 +371,6 @@ bool _glfwPlatformInitJoysticks(void) return true; } -// Close all opened joystick handles -// void _glfwPlatformTerminateJoysticks(void) { int jid; @@ -390,10 +386,6 @@ void _glfwPlatformTerminateJoysticks(void) } -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) { if (mode & _GLFW_POLL_AXES) diff --git a/glfw/linux_joystick.c b/glfw/linux_joystick.c index 0cde579ae..09952c6d3 100644 --- a/glfw/linux_joystick.c +++ b/glfw/linux_joystick.c @@ -264,8 +264,49 @@ static int compareJoysticks(const void* fp, const void* sp) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// -// Initialize joystick interface -// +void _glfwDetectJoystickConnectionLinux(void) +{ + if (_glfw.linjs.inotify <= 0) + return; + + ssize_t offset = 0; + char buffer[16384]; + const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer)); + + while (size > offset) + { + regmatch_t match; + const struct inotify_event* e = (struct inotify_event*) (buffer + offset); + + offset += sizeof(struct inotify_event) + e->len; + + if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0) + continue; + + char path[PATH_MAX]; + snprintf(path, sizeof(path), "/dev/input/%s", e->name); + + if (e->mask & (IN_CREATE | IN_ATTRIB)) + openJoystickDevice(path); + else if (e->mask & IN_DELETE) + { + for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) + { + if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) + { + closeJoystick(_glfw.joysticks + jid); + break; + } + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// + bool _glfwPlatformInitJoysticks(void) { const char* dirname = "/dev/input"; @@ -320,8 +361,6 @@ bool _glfwPlatformInitJoysticks(void) return true; } -// Close all opened joystick handles -// void _glfwPlatformTerminateJoysticks(void) { int jid; @@ -343,50 +382,6 @@ void _glfwPlatformTerminateJoysticks(void) } } -void _glfwDetectJoystickConnectionLinux(void) -{ - - if (_glfw.linjs.inotify <= 0) - return; - - ssize_t offset = 0; - char buffer[16384]; - const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer)); - - while (size > offset) - { - regmatch_t match; - const struct inotify_event* e = (struct inotify_event*) (buffer + offset); - - offset += sizeof(struct inotify_event) + e->len; - - if (regexec(&_glfw.linjs.regex, e->name, 1, &match, 0) != 0) - continue; - - char path[PATH_MAX]; - snprintf(path, sizeof(path), "/dev/input/%s", e->name); - - if (e->mask & (IN_CREATE | IN_ATTRIB)) - openJoystickDevice(path); - else if (e->mask & IN_DELETE) - { - for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) - { - if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) - { - closeJoystick(_glfw.joysticks + jid); - break; - } - } - } - } -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW platform API ////// -////////////////////////////////////////////////////////////////////////// - int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode UNUSED) { // Read all queued events (non-blocking) From bc61a81d7a7ff735021c40a8493d5eda5b6c6152 Mon Sep 17 00:00:00 2001 From: Luflosi Date: Thu, 23 Jul 2020 23:57:03 +0200 Subject: [PATCH 4/4] GLFW: X11: Fix joystick detection before joystick init From upstream: https://github.com/glfw/glfw/commit/c01acc267ad7f5e016d905276ba38917a1fa64bb. --- glfw/x11_window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/glfw/x11_window.c b/glfw/x11_window.c index f8dce617f..1aebae797 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -2653,7 +2653,8 @@ _glfwDispatchX11Events(void) { unsigned dispatched = 0; #if defined(__linux__) - _glfwDetectJoystickConnectionLinux(); + if (_glfw.joysticksInitialized) + _glfwDetectJoystickConnectionLinux(); #endif dispatched += dispatch_x11_queued_events(XEventsQueued(_glfw.x11.display, QueuedAfterFlush));