From 4647e9de53bbe1c54dc125fd6e7dfc6aa16baddc Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 13 Apr 2024 22:23:50 +0900 Subject: [PATCH] internal/glfw, internal/gamepad: update GLFW to v3.3.9 Updates #2960 --- internal/gamepad/gamepad_darwin.go | 11 +- internal/gamepad/gamepad_desktop_windows.go | 10 + internal/gamepad/gamepad_linux.go | 7 - internal/glfw/api_windows.go | 2 + internal/glfw/cocoa_init_darwin.m | 2 +- internal/glfw/cocoa_window_darwin.m | 15 +- internal/glfw/context_unix.c | 29 ++- internal/glfw/context_windows.go | 27 ++- internal/glfw/egl_context_unix.c | 100 +++++---- internal/glfw/glfw3_unix.h | 57 +++-- internal/glfw/glfw3native_unix.h | 4 +- internal/glfw/glx_context_linbsd.c | 4 + internal/glfw/glx_context_linbsd.h | 1 - internal/glfw/input_unix.c | 8 +- internal/glfw/input_windows.go | 3 + internal/glfw/nsgl_context_darwin.m | 9 +- internal/glfw/wgl_context_windows.go | 17 +- internal/glfw/win32_platform_windows.go | 2 + internal/glfw/win32_window_windows.go | 206 ++++++++++-------- internal/glfw/x11_window_linbsd.c | 101 +++++++-- .../opengl/gl/procaddr_linbsd.go | 3 + 21 files changed, 393 insertions(+), 225 deletions(-) diff --git a/internal/gamepad/gamepad_darwin.go b/internal/gamepad/gamepad_darwin.go index a571922b8..f3521c8b0 100644 --- a/internal/gamepad/gamepad_darwin.go +++ b/internal/gamepad/gamepad_darwin.go @@ -152,6 +152,14 @@ func (g *nativeGamepadsImpl) addDevice(device _IOHIDDeviceRef, gamepads *gamepad return } + elements := _IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone) + // It is reportedly possible for this to fail on macOS 13 Ventura + // if the application does not have input monitoring permissions + if elements == 0 { + return + } + defer _CFRelease(_CFTypeRef(elements)) + name := "Unknown" if prop := _IOHIDDeviceGetProperty(device, _CFStringCreateWithCString(kCFAllocatorDefault, kIOHIDProductKey, kCFStringEncodingUTF8)); prop != 0 { var cstr [256]byte @@ -189,9 +197,6 @@ func (g *nativeGamepadsImpl) addDevice(device _IOHIDDeviceRef, gamepads *gamepad bs[0], bs[1], bs[2], bs[3], bs[4], bs[5], bs[6], bs[7], bs[8], bs[9], bs[10], bs[11]) } - elements := _IOHIDDeviceCopyMatchingElements(device, 0, kIOHIDOptionsTypeNone) - defer _CFRelease(_CFTypeRef(elements)) - n := &nativeGamepadImpl{ device: device, } diff --git a/internal/gamepad/gamepad_desktop_windows.go b/internal/gamepad/gamepad_desktop_windows.go index 56f95cc82..4ee5e8d06 100644 --- a/internal/gamepad/gamepad_desktop_windows.go +++ b/internal/gamepad/gamepad_desktop_windows.go @@ -794,6 +794,16 @@ func (g *nativeGamepadDesktop) hatState(hat int) int { if g.xinputState.Gamepad.wButtons&_XINPUT_GAMEPAD_DPAD_LEFT != 0 { v |= hatLeft } + + // Treat invalid combinations as neither being pressed + // while preserving what data can be preserved + if (v&hatRight) != 0 && (v&hatLeft) != 0 { + v &^= hatRight | hatLeft + } + if (v&hatUp) != 0 && (v&hatDown) != 0 { + v &^= hatUp | hatDown + } + return v } diff --git a/internal/gamepad/gamepad_linux.go b/internal/gamepad/gamepad_linux.go index b9d5fb3f9..d97d43970 100644 --- a/internal/gamepad/gamepad_linux.go +++ b/internal/gamepad/gamepad_linux.go @@ -140,13 +140,6 @@ func (*nativeGamepadsImpl) openGamepad(gamepads *gamepads, path string) (err err return fmt.Errorf("gamepad: ioctl for an ID failed: %w", err) } - if !isBitSet(evBits, unix.EV_KEY) { - if err := unix.Close(fd); err != nil { - return err - } - - return nil - } if !isBitSet(evBits, unix.EV_ABS) { if err := unix.Close(fd); err != nil { return err diff --git a/internal/glfw/api_windows.go b/internal/glfw/api_windows.go index f114665bc..6255cd3fa 100644 --- a/internal/glfw/api_windows.go +++ b/internal/glfw/api_windows.go @@ -121,6 +121,7 @@ const ( _PFD_SUPPORT_OPENGL = 0x00000020 _PFD_TYPE_RGBA = 0 _QS_ALLEVENTS = _QS_INPUT | _QS_POSTMESSAGE | _QS_TIMER | _QS_PAINT | _QS_HOTKEY + _QS_ALLINPUT = _QS_INPUT | _QS_POSTMESSAGE | _QS_TIMER | _QS_PAINT | _QS_HOTKEY | _QS_SENDMESSAGE _QS_HOTKEY = 0x0080 _QS_INPUT = _QS_MOUSE | _QS_KEY | _QS_RAWINPUT _QS_KEY = 0x0001 @@ -130,6 +131,7 @@ const ( _QS_PAINT = 0x0020 _QS_POSTMESSAGE = 0x0008 _QS_RAWINPUT = 0x0400 + _QS_SENDMESSAGE = 0x0040 _QS_TIMER = 0x0010 _RID_INPUT = 0x10000003 _RIDEV_REMOVE = 0x00000001 diff --git a/internal/glfw/cocoa_init_darwin.m b/internal/glfw/cocoa_init_darwin.m index 177500d5c..a9780d165 100644 --- a/internal/glfw/cocoa_init_darwin.m +++ b/internal/glfw/cocoa_init_darwin.m @@ -227,7 +227,7 @@ static void createKeyTables(void) _glfw.ns.keycodes[0x6D] = GLFW_KEY_F10; _glfw.ns.keycodes[0x67] = GLFW_KEY_F11; _glfw.ns.keycodes[0x6F] = GLFW_KEY_F12; - _glfw.ns.keycodes[0x69] = GLFW_KEY_F13; + _glfw.ns.keycodes[0x69] = GLFW_KEY_PRINT_SCREEN; _glfw.ns.keycodes[0x6B] = GLFW_KEY_F14; _glfw.ns.keycodes[0x71] = GLFW_KEY_F15; _glfw.ns.keycodes[0x6A] = GLFW_KEY_F16; diff --git a/internal/glfw/cocoa_window_darwin.m b/internal/glfw/cocoa_window_darwin.m index 111a6d16b..1b1a7ebf1 100644 --- a/internal/glfw/cocoa_window_darwin.m +++ b/internal/glfw/cocoa_window_darwin.m @@ -285,10 +285,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; - (void)windowDidChangeOcclusionState:(NSNotification* )notification { - if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) - window->ns.occluded = GLFW_FALSE; - else - window->ns.occluded = GLFW_TRUE; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 + if ([window->ns.object respondsToSelector:@selector(occlusionState)]) + { + if ([window->ns.object occlusionState] & NSWindowOcclusionStateVisible) + window->ns.occluded = GLFW_FALSE; + else + window->ns.occluded = GLFW_TRUE; + } +#endif } @end @@ -1239,7 +1244,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, if (window->monitor) { - styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable); + styleMask &= ~(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable); styleMask |= NSWindowStyleMaskBorderless; } else diff --git a/internal/glfw/context_unix.c b/internal/glfw/context_unix.c index 3b01f86c4..58cba6951 100644 --- a/internal/glfw/context_unix.c +++ b/internal/glfw/context_unix.c @@ -26,16 +26,6 @@ // GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) { - if (ctxconfig->share) - { - if (ctxconfig->client == GLFW_NO_API || - ctxconfig->share->context.client == GLFW_NO_API) - { - _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); - return GLFW_FALSE; - } - } - if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API && ctxconfig->source != GLFW_EGL_CONTEXT_API && ctxconfig->source != GLFW_OSMESA_CONTEXT_API) @@ -56,6 +46,23 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) return GLFW_FALSE; } + if (ctxconfig->share) + { + if (ctxconfig->client == GLFW_NO_API || + ctxconfig->share->context.client == GLFW_NO_API) + { + _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); + return GLFW_FALSE; + } + + if (ctxconfig->source != ctxconfig->share->context.source) + { + _glfwInputError(GLFW_INVALID_ENUM, + "Context creation APIs do not match between contexts"); + return GLFW_FALSE; + } + } + if (ctxconfig->client == GLFW_OPENGL_API) { if ((ctxconfig->major < 1 || ctxconfig->minor < 0) || @@ -334,6 +341,8 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window, previous = _glfwPlatformGetTls(&_glfw.contextSlot); glfwMakeContextCurrent((GLFWwindow*) window); + if (_glfwPlatformGetTls(&_glfw.contextSlot) != window) + return GLFW_FALSE; window->context.GetIntegerv = (PFNGLGETINTEGERVPROC) window->context.getProcAddress("glGetIntegerv"); diff --git a/internal/glfw/context_windows.go b/internal/glfw/context_windows.go index 2f7ea8d10..49e0fdc4c 100644 --- a/internal/glfw/context_windows.go +++ b/internal/glfw/context_windows.go @@ -17,12 +17,6 @@ import ( ) func checkValidContextConfig(ctxconfig *ctxconfig) error { - if ctxconfig.share != nil { - if ctxconfig.client == NoAPI || ctxconfig.share.context.client == NoAPI { - return NoWindowContext - } - } - if ctxconfig.source != NativeContextAPI && ctxconfig.source != EGLContextAPI && ctxconfig.source != OSMesaContextAPI { @@ -35,6 +29,15 @@ func checkValidContextConfig(ctxconfig *ctxconfig) error { return fmt.Errorf("glfw: invalid client API 0x%08X: %w", ctxconfig.client, InvalidEnum) } + if ctxconfig.share != nil { + if ctxconfig.client == NoAPI || ctxconfig.share.context.client == NoAPI { + return NoWindowContext + } + if ctxconfig.source != ctxconfig.share.context.source { + return fmt.Errorf("glfw: context creation APIs do not match between contexts: %w", InvalidEnum) + } + } + if ctxconfig.client == OpenGLAPI { if (ctxconfig.major < 1 || ctxconfig.minor < 0) || (ctxconfig.major == 1 && ctxconfig.minor > 5) || @@ -249,11 +252,11 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) { w.context.source = ctxconfig.source w.context.client = OpenGLAPI - p, err := _glfw.contextSlot.get() + p1, err := _glfw.contextSlot.get() if err != nil { return err } - previous := (*Window)(unsafe.Pointer(p)) + previous := (*Window)(unsafe.Pointer(p1)) defer func() { err := previous.MakeContextCurrent() if ferr == nil { @@ -264,6 +267,14 @@ func (w *Window) refreshContextAttribs(ctxconfig *ctxconfig) (ferr error) { return err } + p2, err := _glfw.contextSlot.get() + if err != nil { + return err + } + if (*Window)(unsafe.Pointer(p2)) != w { + return nil + } + getIntegerv := w.context.getProcAddress("glGetIntegerv") getString := w.context.getProcAddress("glGetString") if getIntegerv == 0 || getString == 0 { diff --git a/internal/glfw/egl_context_unix.c b/internal/glfw/egl_context_unix.c index f415aef90..ba1fd9804 100644 --- a/internal/glfw/egl_context_unix.c +++ b/internal/glfw/egl_context_unix.c @@ -66,13 +66,30 @@ static int getEGLConfigAttrib(EGLConfig config, int attrib) // Return the EGLConfig most closely matching the specified hints // static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, - const _GLFWfbconfig* desired, + const _GLFWfbconfig* fbconfig, EGLConfig* result) { EGLConfig* nativeConfigs; _GLFWfbconfig* usableConfigs; const _GLFWfbconfig* closest; - int i, nativeCount, usableCount; + int i, nativeCount, usableCount, apiBit; + GLFWbool wrongApiAvailable = GLFW_FALSE; + + if (ctxconfig->client == GLFW_OPENGL_ES_API) + { + if (ctxconfig->major == 1) + apiBit = EGL_OPENGL_ES_BIT; + else + apiBit = EGL_OPENGL_ES2_BIT; + } + else + apiBit = EGL_OPENGL_BIT; + + if (fbconfig->stereo) + { + _glfwInputError(GLFW_FORMAT_UNAVAILABLE, "EGL: Stereo rendering not supported"); + return GLFW_FALSE; + } eglGetConfigs(_glfw.egl.display, NULL, 0, &nativeCount); if (!nativeCount) @@ -109,7 +126,7 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, if (!vi.visualid) continue; - if (desired->transparent) + if (fbconfig->transparent) { int count; XVisualInfo* vis = @@ -123,23 +140,10 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, } #endif // _GLFW_X11 - if (ctxconfig->client == GLFW_OPENGL_ES_API) + if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & apiBit)) { - if (ctxconfig->major == 1) - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT)) - continue; - } - else - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) - continue; - } - } - else if (ctxconfig->client == GLFW_OPENGL_API) - { - if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) - continue; + wrongApiAvailable = GLFW_TRUE; + continue; } u->redBits = getEGLConfigAttrib(n, EGL_RED_SIZE); @@ -151,15 +155,44 @@ static GLFWbool chooseEGLConfig(const _GLFWctxconfig* ctxconfig, u->stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); u->samples = getEGLConfigAttrib(n, EGL_SAMPLES); - u->doublebuffer = desired->doublebuffer; + u->doublebuffer = fbconfig->doublebuffer; u->handle = (uintptr_t) n; usableCount++; } - closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); + closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount); if (closest) *result = (EGLConfig) closest->handle; + else + { + if (wrongApiAvailable) + { + if (ctxconfig->client == GLFW_OPENGL_ES_API) + { + if (ctxconfig->major == 1) + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "EGL: Failed to find support for OpenGL ES 1.x"); + } + else + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "EGL: Failed to find support for OpenGL ES 2 or later"); + } + } + else + { + _glfwInputError(GLFW_API_UNAVAILABLE, + "EGL: Failed to find support for OpenGL"); + } + } + else + { + _glfwInputError(GLFW_FORMAT_UNAVAILABLE, + "EGL: Failed to find a suitable EGLConfig"); + } + } free(nativeConfigs); free(usableConfigs); @@ -231,6 +264,7 @@ static int extensionSupportedEGL(const char* extension) static GLFWglproc getProcAddressEGL(const char* procname) { _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); + assert(window != NULL); if (window->context.egl.client) { @@ -454,11 +488,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, share = ctxconfig->share->context.egl.handle; if (!chooseEGLConfig(ctxconfig, fbconfig, &config)) - { - _glfwInputError(GLFW_FORMAT_UNAVAILABLE, - "EGL: Failed to find a suitable EGLConfig"); return GLFW_FALSE; - } if (ctxconfig->client == GLFW_OPENGL_ES_API) { @@ -515,18 +545,18 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; } - if (ctxconfig->noerror) - { - if (_glfw.egl.KHR_create_context_no_error) - setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE); - } - if (ctxconfig->major != 1 || ctxconfig->minor != 0) { setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig->major); setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig->minor); } + if (ctxconfig->noerror) + { + if (_glfw.egl.KHR_create_context_no_error) + setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE); + } + if (mask) setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); @@ -578,9 +608,6 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, if (!fbconfig->doublebuffer) setAttrib(EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER); - if (_glfw.egl.EXT_present_opaque) - setAttrib(EGL_PRESENT_OPAQUE_EXT, !fbconfig->transparent); - setAttrib(EGL_NONE, EGL_NONE); window->context.egl.surface = @@ -640,6 +667,7 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, #elif defined(__OpenBSD__) || defined(__NetBSD__) "libGL.so", #else + "libOpenGL.so.0", "libGL.so.1", #endif NULL @@ -702,11 +730,7 @@ GLFWbool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, const long vimask = VisualScreenMask | VisualIDMask; if (!chooseEGLConfig(ctxconfig, fbconfig, &native)) - { - _glfwInputError(GLFW_FORMAT_UNAVAILABLE, - "EGL: Failed to find a suitable EGLConfig"); return GLFW_FALSE; - } eglGetConfigAttrib(_glfw.egl.display, native, EGL_NATIVE_VISUAL_ID, &visualID); diff --git a/internal/glfw/glfw3_unix.h b/internal/glfw/glfw3_unix.h index 2a7cff514..9070de920 100644 --- a/internal/glfw/glfw3_unix.h +++ b/internal/glfw/glfw3_unix.h @@ -249,7 +249,7 @@ extern "C" { * release is made that does not contain any API changes. * @ingroup init */ -#define GLFW_VERSION_REVISION 8 +#define GLFW_VERSION_REVISION 9 /*! @} */ /*! @brief One. @@ -296,8 +296,12 @@ extern "C" { #define GLFW_REPEAT 2 /*! @} */ -/*! @defgroup keys Keyboard keys - * @brief Keyboard key IDs. +/*! @ingroup input + */ +#define GLFW_KEY_UNKNOWN -1 + +/*! @defgroup keys Keyboard key tokens + * @brief Keyboard key tokens. * * See [key input](@ref input_key) for how these are used. * @@ -320,8 +324,6 @@ extern "C" { * @{ */ -/* The unknown key */ -#define GLFW_KEY_UNKNOWN -1 /* Printable keys */ #define GLFW_KEY_SPACE 32 @@ -4039,8 +4041,8 @@ GLFWAPI int glfwRawMouseMotionSupported(void); * @param[in] scancode The scancode of the key to query. * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. * * @remark The contents of the returned string may change when a keyboard * layout change event is received. @@ -4062,15 +4064,18 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode); * * This function returns the platform-specific scancode of the specified key. * - * If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this - * method will return `-1`. + * If the specified [key token](@ref keys) corresponds to a physical key not + * supported on the current platform then this method will return `-1`. + * Calling this function with anything other than a key token will return `-1` + * and generate a @ref GLFW_INVALID_ENUM error. * - * @param[in] key Any [named key](@ref keys). - * @return The platform-specific scancode for the key, or `-1` if an - * [error](@ref error_handling) occurred. + * @param[in] key Any [key token](@ref keys). + * @return The platform-specific scancode for the key, or `-1` if the key is + * not supported on the current platform or an [error](@ref error_handling) + * occurred. * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. * * @thread_safety This function may be called from any thread. * @@ -4354,10 +4359,9 @@ GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); * [character callback](@ref glfwSetCharCallback) instead. * * When a window loses input focus, it will generate synthetic key release - * events for all pressed keys. You can tell these events from user-generated - * events by the fact that the synthetic ones are generated after the focus - * loss event has been processed, i.e. after the - * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. + * events for all pressed keys with associated key tokens. You can tell these + * events from user-generated events by the fact that the synthetic ones are + * generated after the focus loss event has been processed, i.e. after the * * The scancode of a key is specific to that platform or sometimes even to that * machine. Scancodes are intended to allow users to bind keys that don't have @@ -4708,12 +4712,15 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); * thread. * * This function makes the OpenGL or OpenGL ES context of the specified window - * current on the calling thread. A context must only be made current on - * a single thread at a time and each thread can have only a single current - * context at a time. + * current on the calling thread. It can also detach the current context from + * the calling thread without making a new one current by passing in `NULL`. * - * When moving a context between threads, you must make it non-current on the - * old thread before making it current on the new one. + * A context must only be made current on a single thread at a time and each + * thread can have only a single current context at a time. Making a context + * current detaches any previously current context on the calling thread. + * + * When moving a context between threads, you must detach it (make it + * non-current) on the old thread before making it current on the new one. * * By default, making a context non-current implicitly forces a pipeline flush. * On machines that support `GL_KHR_context_flush_control`, you can control @@ -4728,6 +4735,10 @@ GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); * @param[in] window The window whose context to make current, or `NULL` to * detach the current context. * + * @remarks If the previously current context was created via a different + * context creation API than the one passed to this function, GLFW will still + * detach the previous one from its API before making the new one current. + * * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. * diff --git a/internal/glfw/glfw3native_unix.h b/internal/glfw/glfw3native_unix.h index 565eb7471..4dfd56871 100644 --- a/internal/glfw/glfw3native_unix.h +++ b/internal/glfw/glfw3native_unix.h @@ -99,7 +99,9 @@ extern "C" { #include #include #endif - #elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) + #endif + + #if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) #include #include #endif diff --git a/internal/glfw/glx_context_linbsd.c b/internal/glfw/glx_context_linbsd.c index 4de3fe2b0..33afbae19 100644 --- a/internal/glfw/glx_context_linbsd.c +++ b/internal/glfw/glx_context_linbsd.c @@ -168,6 +168,7 @@ static void swapBuffersGLX(_GLFWwindow* window) static void swapIntervalGLX(int interval) { _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); + assert(window != NULL); if (_glfw.glx.EXT_swap_control) { @@ -204,7 +205,10 @@ static GLFWglproc getProcAddressGLX(const char* procname) else if (_glfw.glx.GetProcAddressARB) return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); else + { + // NOTE: glvnd provides GLX 1.4, so this can only happen with libGL return _glfw_dlsym(_glfw.glx.handle, procname); + } } static void destroyContextGLX(_GLFWwindow* window) diff --git a/internal/glfw/glx_context_linbsd.h b/internal/glfw/glx_context_linbsd.h index 46f95bc2e..e11d718cf 100644 --- a/internal/glfw/glx_context_linbsd.h +++ b/internal/glfw/glx_context_linbsd.h @@ -107,7 +107,6 @@ typedef struct _GLFWlibraryGLX int eventBase; int errorBase; - // dlopen handle for libGL.so.1 void* handle; // GLX 1.3 functions diff --git a/internal/glfw/input_unix.c b/internal/glfw/input_unix.c index 9d51a4842..08ba0ed7e 100644 --- a/internal/glfw/input_unix.c +++ b/internal/glfw/input_unix.c @@ -280,6 +280,12 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode) if (key != GLFW_KEY_UNKNOWN) { + if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) + { + _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); + return NULL; + } + if (key != GLFW_KEY_KP_EQUAL && (key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) && (key < GLFW_KEY_APOSTROPHE || key > GLFW_KEY_WORLD_2)) @@ -300,7 +306,7 @@ GLFWAPI int glfwGetKeyScancode(int key) if (key < GLFW_KEY_SPACE || key > GLFW_KEY_LAST) { _glfwInputError(GLFW_INVALID_ENUM, "Invalid key %i", key); - return GLFW_RELEASE; + return -1; } return _glfwPlatformGetKeyScancode(key); diff --git a/internal/glfw/input_windows.go b/internal/glfw/input_windows.go index 4632c3189..f8c7c124c 100644 --- a/internal/glfw/input_windows.go +++ b/internal/glfw/input_windows.go @@ -246,6 +246,9 @@ func GetKeyName(key Key, scancode int) (string, error) { } if key != KeyUnknown { + if key < KeySpace || key > KeyLast { + return "", fmt.Errorf("glfw: invalid key %d: %w", key, InvalidEnum) + } if key != KeyKPEqual && (key < KeyKP0 || key > KeyKPAdd) && (key < KeyApostrophe || key > KeyWorld2) { return "", nil } diff --git a/internal/glfw/nsgl_context_darwin.m b/internal/glfw/nsgl_context_darwin.m index 637986531..6b8545d4c 100644 --- a/internal/glfw/nsgl_context_darwin.m +++ b/internal/glfw/nsgl_context_darwin.m @@ -57,11 +57,10 @@ static void swapIntervalNSGL(int interval) @autoreleasepool { _GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot); - if (window) - { - [window->context.nsgl.object setValues:&interval - forParameter:NSOpenGLContextParameterSwapInterval]; - } + assert(window != NULL); + + [window->context.nsgl.object setValues:&interval + forParameter:NSOpenGLContextParameterSwapInterval]; } // autoreleasepool } diff --git a/internal/glfw/wgl_context_windows.go b/internal/glfw/wgl_context_windows.go index f3aebfb70..e16ec0bf8 100644 --- a/internal/glfw/wgl_context_windows.go +++ b/internal/glfw/wgl_context_windows.go @@ -53,12 +53,13 @@ func (w *Window) choosePixelFormat(ctxconfig *ctxconfig, fbconfig_ *fbconfig) (i var nativeCount int32 var attribs []int32 - if _glfw.platformContext.ARB_pixel_format { - var attrib int32 = _WGL_NUMBER_PIXEL_FORMATS_ARB - if err := wglGetPixelFormatAttribivARB(w.context.platform.dc, 1, 0, 1, &attrib, &nativeCount); err != nil { - return 0, err - } + c, err := _DescribePixelFormat(w.context.platform.dc, 1, uint32(unsafe.Sizeof(_PIXELFORMATDESCRIPTOR{})), nil) + if err != nil { + return 0, err + } + nativeCount = c + if _glfw.platformContext.ARB_pixel_format { attribs = append(attribs, _WGL_SUPPORT_OPENGL_ARB, _WGL_DRAW_TO_WINDOW_ARB, @@ -96,12 +97,6 @@ func (w *Window) choosePixelFormat(ctxconfig *ctxconfig, fbconfig_ *fbconfig) (i attribs = append(attribs, _WGL_COLORSPACE_EXT) } } - } else { - c, err := _DescribePixelFormat(w.context.platform.dc, 1, uint32(unsafe.Sizeof(_PIXELFORMATDESCRIPTOR{})), nil) - if err != nil { - return 0, err - } - nativeCount = c } usableConfigs := make([]*fbconfig, 0, nativeCount) diff --git a/internal/glfw/win32_platform_windows.go b/internal/glfw/win32_platform_windows.go index f4f5bb3f4..7c1e50e1f 100644 --- a/internal/glfw/win32_platform_windows.go +++ b/internal/glfw/win32_platform_windows.go @@ -72,6 +72,8 @@ type platformLibraryWindowState struct { // The window whose disabled cursor mode is active disabledCursorWindow *Window + // The window the cursor is captured in + capturedCursorWindow *Window rawInput []byte mouseTrailSize uint32 } diff --git a/internal/glfw/win32_window_windows.go b/internal/glfw/win32_window_windows.go index e1f8ef101..92ecbd173 100644 --- a/internal/glfw/win32_window_windows.go +++ b/internal/glfw/win32_window_windows.go @@ -127,48 +127,29 @@ func createIcon(image *Image, xhot, yhot int, icon bool) (_HICON, error) { return handle, nil } -func getFullWindowSize(style uint32, exStyle uint32, contentWidth, contentHeight int, dpi uint32) (fullWidth, fullHeight int, err error) { - if microsoftgdk.IsXbox() { - return contentWidth, contentHeight, nil - } +func (w *Window) applyAspectRatio(edge int, area *_RECT) error { + var frame _RECT + + ratio := float32(w.numer) / float32(w.denom) + style := w.getWindowStyle() + exStyle := w.getWindowExStyle() - rect := _RECT{ - left: 0, - top: 0, - right: int32(contentWidth), - bottom: int32(contentHeight), - } if winver.IsWindows10AnniversaryUpdateOrGreater() { - if err := _AdjustWindowRectExForDpi(&rect, style, false, exStyle, dpi); err != nil { - return 0, 0, err + if err := _AdjustWindowRectExForDpi(&frame, style, false, exStyle, _GetDpiForWindow(w.platform.handle)); err != nil { + return err } } else { - if err := _AdjustWindowRectEx(&rect, style, false, exStyle); err != nil { - return 0, 0, err + if err := _AdjustWindowRectEx(&frame, style, false, exStyle); err != nil { + return err } } - return int(rect.right - rect.left), int(rect.bottom - rect.top), nil -} - -func (w *Window) applyAspectRatio(edge int, area *_RECT) error { - ratio := float32(w.numer) / float32(w.denom) - - var dpi uint32 = _USER_DEFAULT_SCREEN_DPI - if winver.IsWindows10AnniversaryUpdateOrGreater() { - dpi = _GetDpiForWindow(w.platform.handle) - } - - xoff, yoff, err := getFullWindowSize(w.getWindowStyle(), w.getWindowExStyle(), 0, 0, dpi) - if err != nil { - return err - } if edge == _WMSZ_LEFT || edge == _WMSZ_BOTTOMLEFT || edge == _WMSZ_RIGHT || edge == _WMSZ_BOTTOMRIGHT { - area.bottom = area.top + int32(yoff) + int32(float32(area.right-area.left-int32(xoff))/ratio) + area.bottom = area.top + int32(frame.bottom-frame.top) + int32(float32(area.right-area.left-int32(frame.right-frame.left))/ratio) } else if edge == _WMSZ_TOPLEFT || edge == _WMSZ_TOPRIGHT { - area.top = area.bottom - int32(yoff) - int32(float32(area.right-area.left-int32(xoff))/ratio) + area.top = area.bottom - int32(frame.bottom-frame.top) - int32(float32(area.right-area.left-int32(frame.right-frame.left))/ratio) } else if edge == _WMSZ_TOP || edge == _WMSZ_BOTTOM { - area.right = area.left + int32(xoff) + int32(float32(area.bottom-area.top-int32(yoff))*ratio) + area.right = area.left + int32(frame.right-frame.left) + int32(float32(area.bottom-area.top-int32(frame.bottom-frame.top))*ratio) } return nil @@ -214,26 +195,27 @@ func (w *Window) clientToScreen(rect _RECT) (_RECT, error) { return rect, nil } -func updateClipRect(window *Window) error { - if window != nil { - clipRect, err := _GetClientRect(window.platform.handle) - if err != nil { - return err - } - - clipRect, err = window.clientToScreen(clipRect) - if err != nil { - return err - } - - if err := _ClipCursor(&clipRect); err != nil { - return err - } - } else { - if err := _ClipCursor(nil); err != nil { - return err - } +func captureCursor(window *Window) error { + clipRect, err := _GetClientRect(window.platform.handle) + if err != nil { + return err } + clipRect, err = window.clientToScreen(clipRect) + if err != nil { + return err + } + if err := _ClipCursor(&clipRect); err != nil { + return err + } + _glfw.platformWindow.capturedCursorWindow = window + return nil +} + +func releaseCursor() error { + if err := _ClipCursor(nil); err != nil { + return err + } + _glfw.platformWindow.capturedCursorWindow = nil return nil } @@ -274,7 +256,7 @@ func (w *Window) disableCursor() error { if err := w.centerCursorInContentArea(); err != nil { return err } - if err := updateClipRect(w); err != nil { + if err := captureCursor(w); err != nil { return err } if w.rawMouseMotion { @@ -292,7 +274,7 @@ func (w *Window) enableCursor() error { } } _glfw.platformWindow.disabledCursorWindow = nil - if err := updateClipRect(nil); err != nil { + if err := releaseCursor(); err != nil { return err } if err := w.platformSetCursorPos(_glfw.platformWindow.restoreCursorPosX, _glfw.platformWindow.restoreCursorPosY); err != nil { @@ -986,8 +968,8 @@ func windowProc(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) iconified := wParam == _SIZE_MINIMIZED maximized := wParam == _SIZE_MAXIMIZED || (window.platform.maximized && wParam != _SIZE_RESTORED) - if _glfw.platformWindow.disabledCursorWindow == window { - if err := updateClipRect(window); err != nil { + if _glfw.platformWindow.capturedCursorWindow == window { + if err := captureCursor(window); err != nil { _glfw.errors = append(_glfw.errors, err) return 0 } @@ -1032,8 +1014,8 @@ func windowProc(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) return 0 case _WM_MOVE: - if _glfw.platformWindow.disabledCursorWindow == window { - if err := updateClipRect(window); err != nil { + if _glfw.platformWindow.capturedCursorWindow == window { + if err := captureCursor(window); err != nil { _glfw.errors = append(_glfw.errors, err) return 0 } @@ -1056,31 +1038,35 @@ func windowProc(hWnd windows.HWND, uMsg uint32, wParam _WPARAM, lParam _LPARAM) return 1 case _WM_GETMINMAXINFO: - var dpi uint32 = _USER_DEFAULT_SCREEN_DPI + var frame _RECT mmi := (*_MINMAXINFO)(unsafe.Pointer(lParam)) + style := window.getWindowStyle() + exStyle := window.getWindowExStyle() if window.monitor != nil { break } if winver.IsWindows10AnniversaryUpdateOrGreater() { - dpi = _GetDpiForWindow(window.platform.handle) - } - - xoff, yoff, err := getFullWindowSize(window.getWindowStyle(), window.getWindowExStyle(), 0, 0, dpi) - if err != nil { - _glfw.errors = append(_glfw.errors, err) - return 0 + if err := _AdjustWindowRectExForDpi(&frame, style, false, exStyle, _GetDpiForWindow(window.platform.handle)); err != nil { + _glfw.errors = append(_glfw.errors, err) + return 0 + } + } else { + if err := _AdjustWindowRectEx(&frame, style, false, exStyle); err != nil { + _glfw.errors = append(_glfw.errors, err) + return 0 + } } if window.minwidth != DontCare && window.minheight != DontCare { - mmi.ptMinTrackSize.x = int32(window.minwidth + xoff) - mmi.ptMinTrackSize.y = int32(window.minheight + yoff) + mmi.ptMinTrackSize.x = int32(window.minwidth) + (frame.right - frame.left) + mmi.ptMinTrackSize.y = int32(window.minheight) + (frame.bottom - frame.top) } if window.maxwidth != DontCare && window.maxheight != DontCare { - mmi.ptMaxTrackSize.x = int32(window.maxwidth + xoff) - mmi.ptMaxTrackSize.y = int32(window.maxheight + yoff) + mmi.ptMaxTrackSize.x = int32(window.maxwidth) + (frame.right - frame.left) + mmi.ptMaxTrackSize.y = int32(window.maxheight) + (frame.bottom - frame.top) } if !window.decorated { @@ -1205,7 +1191,7 @@ func (w *Window) createNativeWindow(wndconfig *wndconfig, fbconfig *fbconfig) er style := w.getWindowStyle() exStyle := w.getWindowExStyle() - var xpos, ypos, fullWidth, fullHeight int32 + var frameX, frameY, frameWidth, frameHeight int32 if w.monitor != nil { mi, ok := _GetMonitorInfoW(w.monitor.platform.handle) if !ok { @@ -1214,27 +1200,29 @@ func (w *Window) createNativeWindow(wndconfig *wndconfig, fbconfig *fbconfig) er // NOTE: This window placement is temporary and approximate, as the // correct position and size cannot be known until the monitor // video mode has been picked in _glfwSetVideoModeWin32 - xpos = mi.rcMonitor.left - ypos = mi.rcMonitor.top - fullWidth = mi.rcMonitor.right - mi.rcMonitor.left - fullHeight = mi.rcMonitor.bottom - mi.rcMonitor.top + frameX = mi.rcMonitor.left + frameY = mi.rcMonitor.top + frameWidth = mi.rcMonitor.right - mi.rcMonitor.left + frameHeight = mi.rcMonitor.bottom - mi.rcMonitor.top } else { - xpos = _CW_USEDEFAULT - ypos = _CW_USEDEFAULT + rect := _RECT{0, 0, int32(wndconfig.width), int32(wndconfig.height)} w.platform.maximized = wndconfig.maximized if wndconfig.maximized { style |= _WS_MAXIMIZE } - w, h, err := getFullWindowSize(style, exStyle, wndconfig.width, wndconfig.height, _USER_DEFAULT_SCREEN_DPI) - if err != nil { + if err := _AdjustWindowRectEx(&rect, style, false, exStyle); err != nil { return err } - fullWidth, fullHeight = int32(w), int32(h) + + frameX = _CW_USEDEFAULT + frameY = _CW_USEDEFAULT + frameWidth = rect.right - rect.left + frameHeight = rect.bottom - rect.top } - h, err := _CreateWindowExW(exStyle, _GLFW_WNDCLASSNAME, wndconfig.title, style, xpos, ypos, fullWidth, fullHeight, + h, err := _CreateWindowExW(exStyle, _GLFW_WNDCLASSNAME, wndconfig.title, style, frameX, frameY, frameWidth, frameHeight, 0, // No parent window 0, // No window menu _glfw.platformWindow.instance, unsafe.Pointer(wndconfig)) @@ -1459,7 +1447,15 @@ func (w *Window) platformDestroyWindow() error { } if _glfw.platformWindow.disabledCursorWindow == w { - _glfw.platformWindow.disabledCursorWindow = nil + if err := w.enableCursor(); err != nil { + return err + } + } + + if _glfw.platformWindow.capturedCursorWindow == w { + if err := releaseCursor(); err != nil { + return err + } } if w.platform.handle != 0 { @@ -2184,7 +2180,7 @@ func platformWaitEvents() error { } func platformWaitEventsTimeout(timeout float64) error { - if _, err := _MsgWaitForMultipleObjects(0, nil, false, uint32(timeout*1e3), _QS_ALLEVENTS); err != nil { + if _, err := _MsgWaitForMultipleObjects(0, nil, false, uint32(timeout*1e3), _QS_ALLINPUT); err != nil { return err } if err := platformPollEvents(); err != nil { @@ -2235,20 +2231,48 @@ func (w *Window) platformSetCursorPos(xpos, ypos float64) error { } func (w *Window) platformSetCursorMode(mode int) error { - if mode == CursorDisabled { - if w.platformWindowFocused() { - if err := w.disableCursor(); err != nil { + if w.platformWindowFocused() { + if mode == CursorDisabled { + xpos, ypos, err := w.platformGetCursorPos() + if err != nil { + return err + } + _glfw.platformWindow.restoreCursorPosX = xpos + _glfw.platformWindow.restoreCursorPosY = ypos + if err := w.centerCursorInContentArea(); err != nil { + return err + } + if w.rawMouseMotion { + if err := w.enableRawMouseMotion(); err != nil { + return err + } + } + } else if _glfw.platformWindow.disabledCursorWindow == w { + if w.rawMouseMotion { + if err := w.disableRawMouseMotion(); err != nil { + return err + } + } + } + + if mode == CursorDisabled { + if err := captureCursor(w); err != nil { + return err + } + } else { + if err := releaseCursor(); err != nil { return err } } - return nil - } - if _glfw.platformWindow.disabledCursorWindow == w { - if err := w.enableCursor(); err != nil { - return err + if mode == CursorDisabled { + _glfw.platformWindow.disabledCursorWindow = w + } else { + _glfw.platformWindow.disabledCursorWindow = nil + if err := w.platformSetCursorPos(_glfw.platformWindow.restoreCursorPosX, _glfw.platformWindow.restoreCursorPosY); err != nil { + return err + } } - return nil } in, err := w.cursorInContentArea() diff --git a/internal/glfw/x11_window_linbsd.c b/internal/glfw/x11_window_linbsd.c index b221823ac..3e72d4e3d 100644 --- a/internal/glfw/x11_window_linbsd.c +++ b/internal/glfw/x11_window_linbsd.c @@ -357,6 +357,11 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height) { XSizeHints* hints = XAllocSizeHints(); + long supplied; + XGetWMNormalHints(_glfw.x11.display, window->x11.handle, hints, &supplied); + + hints->flags &= ~(PMinSize | PMaxSize | PAspect); + if (!window->monitor) { if (window->resizable) @@ -393,9 +398,6 @@ static void updateNormalHints(_GLFWwindow* window, int width, int height) } } - hints->flags |= PWinGravity; - hints->win_gravity = StaticGravity; - XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); XFree(hints); @@ -561,6 +563,25 @@ static void updateCursorImage(_GLFWwindow* window) } } +// Grabs the cursor and confines it to the window +// +static void captureCursor(_GLFWwindow* window) +{ + XGrabPointer(_glfw.x11.display, window->x11.handle, True, + ButtonPressMask | ButtonReleaseMask | PointerMotionMask, + GrabModeAsync, GrabModeAsync, + window->x11.handle, + None, + CurrentTime); +} + +// Ungrabs the cursor +// +static void releaseCursor(void) +{ + XUngrabPointer(_glfw.x11.display, CurrentTime); +} + // Enable XI2 raw mouse motion events // static void enableRawMouseMotion(_GLFWwindow* window) @@ -603,12 +624,7 @@ static void disableCursor(_GLFWwindow* window) &_glfw.x11.restoreCursorPosY); updateCursorImage(window); _glfwCenterCursorInContentArea(window); - XGrabPointer(_glfw.x11.display, window->x11.handle, True, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, - window->x11.handle, - _glfw.x11.hiddenCursorHandle, - CurrentTime); + captureCursor(window); } // Exit disabled cursor mode for the specified window @@ -619,7 +635,7 @@ static void enableCursor(_GLFWwindow* window) disableRawMouseMotion(window); _glfw.x11.disabledCursorWindow = NULL; - XUngrabPointer(_glfw.x11.display, CurrentTime); + releaseCursor(); _glfwPlatformSetCursorPos(window, _glfw.x11.restoreCursorPosX, _glfw.x11.restoreCursorPosY); @@ -764,7 +780,28 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, XFree(hints); } - updateNormalHints(window, width, height); + // Set ICCCM WM_NORMAL_HINTS property + { + XSizeHints* hints = XAllocSizeHints(); + if (!hints) + { + _glfwInputError(GLFW_OUT_OF_MEMORY, "X11: Failed to allocate size hints"); + return GLFW_FALSE; + } + + if (!wndconfig->resizable) + { + hints->flags |= (PMinSize | PMaxSize); + hints->min_width = hints->max_width = width; + hints->min_height = hints->max_height = height; + } + + hints->flags |= PWinGravity; + hints->win_gravity = StaticGravity; + + XSetWMNormalHints(_glfw.x11.display, window->x11.handle, hints); + XFree(hints); + } // Set ICCCM WM_CLASS property { @@ -2085,7 +2122,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, void _glfwPlatformDestroyWindow(_GLFWwindow* window) { if (_glfw.x11.disabledCursorWindow == window) - _glfw.x11.disabledCursorWindow = NULL; + enableCursor(window); if (window->monitor) releaseMonitor(window); @@ -2891,16 +2928,40 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) { - if (mode == GLFW_CURSOR_DISABLED) + if (_glfwPlatformWindowFocused(window)) { - if (_glfwPlatformWindowFocused(window)) - disableCursor(window); - } - else if (_glfw.x11.disabledCursorWindow == window) - enableCursor(window); - else - updateCursorImage(window); + if (mode == GLFW_CURSOR_DISABLED) + { + _glfwPlatformGetCursorPos(window, + &_glfw.x11.restoreCursorPosX, + &_glfw.x11.restoreCursorPosY); + _glfwCenterCursorInContentArea(window); + if (window->rawMouseMotion) + enableRawMouseMotion(window); + } + else if (_glfw.x11.disabledCursorWindow == window) + { + if (window->rawMouseMotion) + disableRawMouseMotion(window); + } + if (mode == GLFW_CURSOR_DISABLED) + captureCursor(window); + else + releaseCursor(); + + if (mode == GLFW_CURSOR_DISABLED) + _glfw.x11.disabledCursorWindow = window; + else if (_glfw.x11.disabledCursorWindow == window) + { + _glfw.x11.disabledCursorWindow = NULL; + _glfwPlatformSetCursorPos(window, + _glfw.x11.restoreCursorPosX, + _glfw.x11.restoreCursorPosY); + } + } + + updateCursorImage(window); XFlush(_glfw.x11.display); } diff --git a/internal/graphicsdriver/opengl/gl/procaddr_linbsd.go b/internal/graphicsdriver/opengl/gl/procaddr_linbsd.go index 3047376c6..a7b40dac4 100644 --- a/internal/graphicsdriver/opengl/gl/procaddr_linbsd.go +++ b/internal/graphicsdriver/opengl/gl/procaddr_linbsd.go @@ -68,6 +68,9 @@ func (c *defaultContext) init() error { // Try OpenGL first. OpenGL is preferable as this doesn't cause context losses. if !preferES { // Usually libGL.so or libGL.so.1 is used. libGL.so.2 might exist only on NetBSD. + // TODO: Should "libOpenGL.so.0" [1] and "libGLX.so.0" [2] be added? These were added as of GLFW 3.3.9. + // [1] https://github.com/glfw/glfw/commit/55aad3c37b67f17279378db52da0a3ab81bbf26d + // [2] https://github.com/glfw/glfw/commit/c18851f52ec9704eb06464058a600845ec1eada1 for _, name := range []string{"libGL.so", "libGL.so.2", "libGL.so.1", "libGL.so.0"} { cname := C.CString(name) lib := C.dlopen(cname, C.RTLD_LAZY|C.RTLD_GLOBAL)