From 6ad21fc98f4d70ce648285a866fbbd3efcacd51a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 29 Jan 2018 12:30:05 +0530 Subject: [PATCH] Update bundled glfw --- glfw/cocoa_monitor.m | 2 +- glfw/cocoa_window.m | 4 +- glfw/context.c | 12 ++ glfw/glfw3.h | 19 +- glfw/glx_context.c | 36 ++-- glfw/init.c | 20 +- glfw/input.c | 30 ++- glfw/internal.h | 421 +++++++----------------------------------- glfw/monitor.c | 21 ++- glfw/source-info.json | 3 +- glfw/win32_platform.h | 5 - glfw/window.c | 24 +++ glfw/wl_init.c | 115 +++++++++--- glfw/wl_monitor.c | 2 +- glfw/wl_platform.h | 55 ++++++ glfw/wl_window.c | 311 ++++++++++++++++++++++++++----- glfw/x11_init.c | 90 ++++----- glfw/x11_window.c | 6 +- kitty/glfw-wrapper.h | 4 + 19 files changed, 671 insertions(+), 509 deletions(-) diff --git a/glfw/cocoa_monitor.m b/glfw/cocoa_monitor.m index 6108342c0..bfcf45106 100644 --- a/glfw/cocoa_monitor.m +++ b/glfw/cocoa_monitor.m @@ -264,7 +264,7 @@ void _glfwPollMonitorsNS(void) const CGSize size = CGDisplayScreenSize(displays[i]); char* name = getDisplayName(displays[i]); if (!name) - name = strdup("Unknown"); + name = _glfw_strdup("Unknown"); monitor = _glfwAllocMonitor(name, size.width, size.height); monitor->ns.displayID = displays[i]; diff --git a/glfw/cocoa_window.m b/glfw/cocoa_window.m index 70167e45d..6048e2f61 100644 --- a/glfw/cocoa_window.m +++ b/glfw/cocoa_window.m @@ -707,7 +707,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 }; NSUInteger i; for (i = 0; i < count; i++) - paths[i] = strdup([[e nextObject] UTF8String]); + paths[i] = _glfw_strdup([[e nextObject] UTF8String]); _glfwInputDrop(window, (int) count, (const char**) paths); @@ -1813,7 +1813,7 @@ const char* _glfwPlatformGetClipboardString(void) } free(_glfw.ns.clipboardString); - _glfw.ns.clipboardString = strdup([object UTF8String]); + _glfw.ns.clipboardString = _glfw_strdup([object UTF8String]); return _glfw.ns.clipboardString; } diff --git a/glfw/context.c b/glfw/context.c index 212b34f9d..1ef1104a7 100644 --- a/glfw/context.c +++ b/glfw/context.c @@ -38,6 +38,12 @@ ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +// Checks whether the desired context attributes are valid +// +// This function checks things like whether the specified client API version +// exists and whether all relevant options have supported and non-conflicting +// values +// GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) { if (ctxconfig->source != GLFW_NATIVE_CONTEXT_API && @@ -155,6 +161,8 @@ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig) return GLFW_TRUE; } +// Chooses the framebuffer config that best matches the desired one +// const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, const _GLFWfbconfig* alternatives, unsigned int count) @@ -321,6 +329,8 @@ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, return closest; } +// Retrieves the attributes of the current context +// GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig) { @@ -555,6 +565,8 @@ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window, return GLFW_TRUE; } +// Searches an extension string for the specified extension +// GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions) { const char* start = extensions; diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 597e861cd..1913502dc 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -814,6 +814,10 @@ extern "C" { * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib). */ #define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A +/*! @brief Mouse cursor hover window attribute. + * + * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). + */ #define GLFW_HOVERED 0x0002000B /*! @brief Framebuffer bit depth hint. @@ -2455,10 +2459,6 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value); * @remark @wayland A full screen window will not attempt to change the mode, * no matter what the requested size or refresh rate. * - * @remark @wayland The wl_shell protocol does not support window - * icons, the window will inherit the one defined in the application's - * desktop file, so this function emits @ref GLFW_PLATFORM_ERROR. - * * @remark @wayland Screensaver inhibition requires the idle-inhibit protocol * to be implemented in the user's compositor. * @@ -2602,9 +2602,9 @@ GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) * in the Mac Developer Library. * - * @remark @wayland The wl_shell protocol does not support icons, the window - * will inherit the one defined in the application's desktop file, so this - * function emits @ref GLFW_PLATFORM_ERROR. + * @remark @wayland There is no existing protocol to change an icon, the + * window will thus inherit the one defined in the application's desktop file. + * This function always emits @ref GLFW_PLATFORM_ERROR. * * @thread_safety This function must only be called from the main thread. * @@ -3012,7 +3012,8 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity); * GLFW_PLATFORM_ERROR. * * @remark @wayland There is no concept of iconification in wl_shell, this - * function will always emit @ref GLFW_PLATFORM_ERROR. + * function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated + * protocol. * * @thread_safety This function must only be called from the main thread. * @@ -3564,7 +3565,7 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. * * @remark @wayland The wl_shell protocol has no concept of iconification, - * this callback will never be called. + * this callback will never be called when using this deprecated protocol. * * @thread_safety This function must only be called from the main thread. * diff --git a/glfw/glx_context.c b/glfw/glx_context.c index 40da6c2fd..adace82d9 100644 --- a/glfw/glx_context.c +++ b/glfw/glx_context.c @@ -223,7 +223,7 @@ static GLFWglproc getProcAddressGLX(const char* procname) else if (_glfw.glx.GetProcAddressARB) return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); else - return dlsym(_glfw.glx.handle, procname); + return _glfw_dlsym(_glfw.glx.handle, procname); } // Destroy the OpenGL context @@ -271,7 +271,7 @@ GLFWbool _glfwInitGLX(void) for (i = 0; sonames[i]; i++) { - _glfw.glx.handle = dlopen(sonames[i], RTLD_LAZY | RTLD_GLOBAL); + _glfw.glx.handle = _glfw_dlopen(sonames[i]); if (_glfw.glx.handle) break; } @@ -283,35 +283,35 @@ GLFWbool _glfwInitGLX(void) } _glfw.glx.GetFBConfigs = - dlsym(_glfw.glx.handle, "glXGetFBConfigs"); + _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs"); _glfw.glx.GetFBConfigAttrib = - dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib"); + _glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib"); _glfw.glx.GetClientString = - dlsym(_glfw.glx.handle, "glXGetClientString"); + _glfw_dlsym(_glfw.glx.handle, "glXGetClientString"); _glfw.glx.QueryExtension = - dlsym(_glfw.glx.handle, "glXQueryExtension"); + _glfw_dlsym(_glfw.glx.handle, "glXQueryExtension"); _glfw.glx.QueryVersion = - dlsym(_glfw.glx.handle, "glXQueryVersion"); + _glfw_dlsym(_glfw.glx.handle, "glXQueryVersion"); _glfw.glx.DestroyContext = - dlsym(_glfw.glx.handle, "glXDestroyContext"); + _glfw_dlsym(_glfw.glx.handle, "glXDestroyContext"); _glfw.glx.MakeCurrent = - dlsym(_glfw.glx.handle, "glXMakeCurrent"); + _glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent"); _glfw.glx.SwapBuffers = - dlsym(_glfw.glx.handle, "glXSwapBuffers"); + _glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers"); _glfw.glx.QueryExtensionsString = - dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); + _glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString"); _glfw.glx.CreateNewContext = - dlsym(_glfw.glx.handle, "glXCreateNewContext"); + _glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext"); _glfw.glx.CreateWindow = - dlsym(_glfw.glx.handle, "glXCreateWindow"); + _glfw_dlsym(_glfw.glx.handle, "glXCreateWindow"); _glfw.glx.DestroyWindow = - dlsym(_glfw.glx.handle, "glXDestroyWindow"); + _glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow"); _glfw.glx.GetProcAddress = - dlsym(_glfw.glx.handle, "glXGetProcAddress"); + _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress"); _glfw.glx.GetProcAddressARB = - dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); + _glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB"); _glfw.glx.GetVisualFromFBConfig = - dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); + _glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig"); if (!_glfw.glx.GetFBConfigs || !_glfw.glx.GetFBConfigAttrib || @@ -428,7 +428,7 @@ void _glfwTerminateGLX(void) if (_glfw.glx.handle) { - dlclose(_glfw.glx.handle); + _glfw_dlclose(_glfw.glx.handle); _glfw.glx.handle = NULL; } } diff --git a/glfw/init.c b/glfw/init.c index 99080b113..4ed929511 100644 --- a/glfw/init.c +++ b/glfw/init.c @@ -35,8 +35,9 @@ #include -// The global variables below comprise all global data in GLFW. -// Any other global variable is a bug. +// The global variables below comprise all mutable global data in GLFW +// +// Any other global variable is a bug // Global state shared between compilation units of GLFW // @@ -137,10 +138,25 @@ static void terminate(void) } +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +char* _glfw_strdup(const char* source) +{ + const size_t length = strlen(source); + char* result = calloc(length + 1, 1); + strcpy(result, source); + return result; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// +// Notifies shared code of an error +// void _glfwInputError(int code, const char* format, ...) { _GLFWerror* error; diff --git a/glfw/input.c b/glfw/input.c index 7d81cd57f..d70b4a603 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -224,6 +224,8 @@ static GLFWbool parseMapping(_GLFWmapping* mapping, const char* string) ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// +// Notifies shared code of a physical key event +// void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods) { if (key >= 0 && key <= GLFW_KEY_LAST) @@ -252,6 +254,9 @@ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int m window->callbacks.key((GLFWwindow*) window, key, scancode, action, mods); } +// Notifies shared code of a Unicode codepoint input event +// The 'plain' parameter determines whether to emit a regular character event +// void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain) { if (codepoint < 32 || (codepoint > 126 && codepoint < 160)) @@ -270,12 +275,16 @@ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWb } } +// Notifies shared code of a scroll event +// void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset) { if (window->callbacks.scroll) window->callbacks.scroll((GLFWwindow*) window, xoffset, yoffset); } +// Notifies shared code of a mouse button click event +// void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) { if (button < 0 || button > GLFW_MOUSE_BUTTON_LAST) @@ -293,6 +302,9 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods) window->callbacks.mouseButton((GLFWwindow*) window, button, action, mods); } +// Notifies shared code of a cursor motion event +// The position is specified in client-area relative screen coordinates +// void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) { if (window->virtualCursorPosX == xpos && window->virtualCursorPosY == ypos) @@ -305,18 +317,24 @@ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos) window->callbacks.cursorPos((GLFWwindow*) window, xpos, ypos); } +// Notifies shared code of a cursor enter/leave event +// void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered) { if (window->callbacks.cursorEnter) window->callbacks.cursorEnter((GLFWwindow*) window, entered); } +// Notifies shared code of files or directories dropped on a window +// void _glfwInputDrop(_GLFWwindow* window, int count, const char** paths) { if (window->callbacks.drop) window->callbacks.drop((GLFWwindow*) window, count, paths); } +// Notifies shared code of a joystick connection or disconnection +// void _glfwInputJoystick(_GLFWjoystick* js, int event) { const int jid = (int) (js - _glfw.joysticks); @@ -325,16 +343,22 @@ void _glfwInputJoystick(_GLFWjoystick* js, int event) _glfw.callbacks.joystick(jid, event); } +// Notifies shared code of the new value of a joystick axis +// void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value) { js->axes[axis] = value; } +// Notifies shared code of the new value of a joystick button +// void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value) { js->buttons[button] = value; } +// Notifies shared code of the new value of a joystick hat +// void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) { const int base = js->buttonCount + hat * 4; @@ -352,6 +376,8 @@ void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +// Returns an available joystick object with arrays and name allocated +// _GLFWjoystick* _glfwAllocJoystick(const char* name, const char* guid, int axisCount, @@ -372,7 +398,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, js = _glfw.joysticks + jid; js->present = GLFW_TRUE; - js->name = strdup(name); + js->name = _glfw_strdup(name); js->axes = calloc(axisCount, sizeof(float)); js->buttons = calloc(buttonCount + hatCount * 4, 1); js->hats = calloc(hatCount, 1); @@ -386,6 +412,8 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name, return js; } +// Frees arrays and name and flags the joystick object as unused +// void _glfwFreeJoystick(_GLFWjoystick* js) { free(js->name); diff --git a/glfw/internal.h b/glfw/internal.h index f44834f3e..448131e36 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -196,38 +196,6 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void); #error "No supported window creation API selected" #endif - -//======================================================================== -// Doxygen group definitions -//======================================================================== - -/*! @defgroup platform Platform interface - * @brief The interface implemented by the platform-specific code. - * - * The platform API is the interface exposed by the platform-specific code for - * each platform and is called by the shared code of the public API It mirrors - * the public API except it uses objects instead of handles. - */ -/*! @defgroup event Event interface - * @brief The interface used by the platform-specific code to report events. - * - * The event API is used by the platform-specific code to notify the shared - * code of events that can be translated into state changes and/or callback - * calls. - */ -/*! @defgroup utility Utility functions - * @brief Various utility functions for internal use. - * - * These functions are shared code and may be used by any part of GLFW - * Each platform may add its own utility functions, but those must only be - * called by the platform-specific code - */ - - -//======================================================================== -// Helper macros -//======================================================================== - // Constructs a version number string from the public header macros #define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r #define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r) @@ -258,11 +226,8 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void); y = t; \ } - -//======================================================================== -// Platform-independent structures -//======================================================================== - +// Per-thread error structure +// struct _GLFWerror { _GLFWerror* next; @@ -270,10 +235,10 @@ struct _GLFWerror char description[_GLFW_MESSAGE_SIZE]; }; -/*! @brief Initialization configuration. - * - * Parameters relating to the initialization of the library. - */ +// Initialization configuration +// +// Parameters relating to the initialization of the library +// struct _GLFWinitconfig { GLFWbool hatButtons; @@ -283,12 +248,12 @@ struct _GLFWinitconfig } ns; }; -/*! @brief Window configuration. - * - * Parameters relating to the creation of the window but not directly related - * to the framebuffer. This is used to pass window creation parameters from - * shared code to the platform API. - */ +// Window configuration +// +// Parameters relating to the creation of the window but not directly related +// to the framebuffer. This is used to pass window creation parameters from +// shared code to the platform API. +// struct _GLFWwndconfig { int width; @@ -312,12 +277,12 @@ struct _GLFWwndconfig } x11; }; -/*! @brief Context configuration. - * - * Parameters relating to the creation of the context but not directly related - * to the framebuffer. This is used to pass context creation parameters from - * shared code to the platform API. - */ +// Context configuration +// +// Parameters relating to the creation of the context but not directly related +// to the framebuffer. This is used to pass context creation parameters from +// shared code to the platform API. +// struct _GLFWctxconfig { int client; @@ -336,14 +301,14 @@ struct _GLFWctxconfig } nsgl; }; -/*! @brief Framebuffer configuration. - * - * This describes buffers and their sizes. It also contains - * a platform-specific ID used to map back to the backend API object. - * - * It is used to pass framebuffer parameters from shared code to the platform - * API and also to enumerate and select available framebuffer configs. - */ +// Framebuffer configuration +// +// This describes buffers and their sizes. It also contains +// a platform-specific ID used to map back to the backend API object. +// +// It is used to pass framebuffer parameters from shared code to the platform +// API and also to enumerate and select available framebuffer configs. +// struct _GLFWfbconfig { int redBits; @@ -365,8 +330,8 @@ struct _GLFWfbconfig uintptr_t handle; }; -/*! @brief Context structure. - */ +// Context structure +// struct _GLFWcontext { int client; @@ -396,8 +361,8 @@ struct _GLFWcontext _GLFW_OSMESA_CONTEXT_STATE; }; -/*! @brief Window and context structure. - */ +// Window and context structure +// struct _GLFWwindow { struct _GLFWwindow* next; @@ -452,8 +417,8 @@ struct _GLFWwindow _GLFW_PLATFORM_WINDOW_STATE; }; -/*! @brief Monitor structure. - */ +// Monitor structure +// struct _GLFWmonitor { char* name; @@ -476,8 +441,8 @@ struct _GLFWmonitor _GLFW_PLATFORM_MONITOR_STATE; }; -/*! @brief Cursor structure - */ +// Cursor structure +// struct _GLFWcursor { _GLFWcursor* next; @@ -486,16 +451,16 @@ struct _GLFWcursor _GLFW_PLATFORM_CURSOR_STATE; }; -/*! @brief Gamepad mapping element structure - */ +// Gamepad mapping element structure +// struct _GLFWmapelement { uint8_t type; uint8_t value; }; -/*! @brief Gamepad mapping structure - */ +// Gamepad mapping structure +// struct _GLFWmapping { char name[128]; @@ -504,8 +469,8 @@ struct _GLFWmapping _GLFWmapelement axes[6]; }; -/*! @brief Joystick structure - */ +// Joystick structure +// struct _GLFWjoystick { GLFWbool present; @@ -524,24 +489,24 @@ struct _GLFWjoystick _GLFW_PLATFORM_JOYSTICK_STATE; }; -/*! @brief Thread local storage structure. - */ +// Thread local storage structure +// struct _GLFWtls { // This is defined in the platform's thread.h _GLFW_PLATFORM_TLS_STATE; }; -/*! @brief Mutex structure. - */ +// Mutex structure +// struct _GLFWmutex { // This is defined in the platform's thread.h _GLFW_PLATFORM_MUTEX_STATE; }; -/*! @brief Library global data. - */ +// Library global data +// struct _GLFWlibrary { GLFWbool initialized; @@ -615,21 +580,14 @@ struct _GLFWlibrary _GLFW_OSMESA_LIBRARY_CONTEXT_STATE; }; - -//======================================================================== // Global state shared between compilation units of GLFW -//======================================================================== - -/*! @brief All global data shared between compilation units. - */ +// extern _GLFWlibrary _glfw; -//======================================================================== -// Platform API functions -//======================================================================== - -/*! @addtogroup platform @{ */ +////////////////////////////////////////////////////////////////////////// +////// GLFW platform API ////// +////////////////////////////////////////////////////////////////////////// int _glfwPlatformInit(void); void _glfwPlatformTerminate(void); @@ -718,316 +676,75 @@ void _glfwPlatformDestroyMutex(_GLFWmutex* mutex); void _glfwPlatformLockMutex(_GLFWmutex* mutex); void _glfwPlatformUnlockMutex(_GLFWmutex* mutex); -/*! @} */ +////////////////////////////////////////////////////////////////////////// +////// GLFW event API ////// +////////////////////////////////////////////////////////////////////////// -//======================================================================== -// Event API functions -//======================================================================== - -/*! @brief Notifies shared code that a window has lost or received input focus. - * @param[in] window The window that received the event. - * @param[in] focused `GLFW_TRUE` if the window received focus, or `GLFW_FALSE` - * if it lost focus. - * @ingroup event - */ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused); - -/*! @brief Notifies shared code that a window has moved. - * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate of the client area of the window. - * @param[in] ypos The new y-coordinate of the client area of the window. - * @ingroup event - */ void _glfwInputWindowPos(_GLFWwindow* window, int xpos, int ypos); - -/*! @brief Notifies shared code that a window has been resized. - * @param[in] window The window that received the event. - * @param[in] width The new width of the client area of the window. - * @param[in] height The new height of the client area of the window. - * @ingroup event - */ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height); - -/*! @brief Notifies shared code that a window framebuffer has been resized. - * @param[in] window The window that received the event. - * @param[in] width The new width, in pixels, of the framebuffer. - * @param[in] height The new height, in pixels, of the framebuffer. - * @ingroup event - */ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height); - -/*! @brief Notifies shared code that a window content scale has changed. - * @param[in] window The window that received the event. - * @param[in] xscale The new x-axis content scale of the window. - * @param[in] yscale The new y-axis content scale of the window. - * @ingroup event - */ void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale); - -/*! @brief Notifies shared code that a window has been iconified or restored. - * @param[in] window The window that received the event. - * @param[in] iconified `GLFW_TRUE` if the window was iconified, or - * `GLFW_FALSE` if it was restored. - * @ingroup event - */ void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified); - -/*! @brief Notifies shared code that a window has been maximized or restored. - * @param[in] window The window that received the event. - * @param[in] maximized `GLFW_TRUE` if the window was maximized, or - * `GLFW_FALSE` if it was restored. - * @ingroup event - */ void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized); - -/*! @brief Notifies shared code that a window's contents needs updating. - * @param[in] window The window that received the event. - */ void _glfwInputWindowDamage(_GLFWwindow* window); - -/*! @brief Notifies shared code that the user wishes to close a window. - * @param[in] window The window that received the event. - * @ingroup event - */ void _glfwInputWindowCloseRequest(_GLFWwindow* window); - -/*! @brief Notifies shared code that a window has changed its desired monitor. - * @param[in] window The window that received the event. - * @param[in] monitor The new desired monitor, or `NULL`. - * @ingroup event - */ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); -/*! @brief Notifies shared code of a physical key event. - * @param[in] window The window that received the event. - * @param[in] key The key that was pressed or released. - * @param[in] scancode The system-specific scan code of the key. - * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE. - * @param[in] mods The modifiers pressed when the event was generated. - * @ingroup event - */ void _glfwInputKey(_GLFWwindow* window, int key, int scancode, int action, int mods); - -/*! @brief Notifies shared code of a Unicode character input event. - * @param[in] window The window that received the event. - * @param[in] codepoint The Unicode code point of the input character. - * @param[in] mods Bit field describing which modifier keys were held down. - * @param[in] plain `GLFW_TRUE` if the character is regular text input, or - * `GLFW_FALSE` otherwise. - * @ingroup event - */ void _glfwInputChar(_GLFWwindow* window, unsigned int codepoint, int mods, GLFWbool plain); - -/*! @brief Notifies shared code of a scroll event. - * @param[in] window The window that received the event. - * @param[in] xoffset The scroll offset along the x-axis. - * @param[in] yoffset The scroll offset along the y-axis. - * @ingroup event - */ void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset); - -/*! @brief Notifies shared code of a mouse button click event. - * @param[in] window The window that received the event. - * @param[in] button The button that was pressed or released. - * @param[in] action @ref GLFW_PRESS or @ref GLFW_RELEASE. - * @param[in] mods The modifiers pressed when the event was generated. - * @ingroup event - */ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); - -/*! @brief Notifies shared code of a cursor motion event. - * @param[in] window The window that received the event. - * @param[in] xpos The new x-coordinate of the cursor, relative to the left - * edge of the client area of the window. - * @param[in] ypos The new y-coordinate of the cursor, relative to the top edge - * of the client area of the window. - * @ingroup event - */ void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); - -/*! @brief Notifies shared code of a cursor enter/leave event. - * @param[in] window The window that received the event. - * @param[in] entered `GLFW_TRUE` if the cursor entered the client area of the - * window, or `GLFW_FALSE` if it left it. - * @ingroup event - */ void _glfwInputCursorEnter(_GLFWwindow* window, GLFWbool entered); +void _glfwInputDrop(_GLFWwindow* window, int count, const char** names); +void _glfwInputJoystick(_GLFWjoystick* js, int event); +void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value); +void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value); +void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value); -/*! @brief Notifies shared code of a monitor connection or disconnection. - * @param[in] monitor The monitor that was connected or disconnected. - * @param[in] action One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. - * @param[in] placement `_GLFW_INSERT_FIRST` or `_GLFW_INSERT_LAST`. - * @ingroup event - */ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement); - -/*! @brief Notifies shared code that a full screen window has acquired or - * released a monitor. - * @param[in] monitor The monitor that was acquired or released. - * @param[in] window The window that acquired the monitor, or `NULL`. - * @ingroup event - */ void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window); -/*! @brief Notifies shared code of an error. - * @param[in] code The error code most suitable for the error. - * @param[in] format The `printf` style format string of the error - * description. - * @ingroup event - */ #if defined(__GNUC__) void _glfwInputError(int code, const char* format, ...) __attribute__((format(printf, 2, 3))); #else void _glfwInputError(int code, const char* format, ...); #endif -/*! @brief Notifies shared code of files or directories dropped on a window. - * @param[in] window The window that received the event. - * @param[in] count The number of dropped objects. - * @param[in] names The names of the dropped objects. - * @ingroup event - */ -void _glfwInputDrop(_GLFWwindow* window, int count, const char** names); -/*! @brief Notifies shared code of a joystick connection or disconnection. - * @param[in] js The joystick that was connected or disconnected. - * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. - * @ingroup event - */ -void _glfwInputJoystick(_GLFWjoystick* js, int event); +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// -/*! @brief Notifies shared code of the new value of a joystick axis. - * @param[in] js The joystick whose axis to update. - * @param[in] axis The index of the axis to update. - * @param[in] value The new value of the axis. - */ -void _glfwInputJoystickAxis(_GLFWjoystick* js, int axis, float value); - -/*! @brief Notifies shared code of the new value of a joystick button. - * @param[in] js The joystick whose button to update. - * @param[in] button The index of the button to update. - * @param[in] value The new value of the button. - */ -void _glfwInputJoystickButton(_GLFWjoystick* js, int button, char value); - -/*! @brief Notifies shared code of the new value of a joystick hat. - * @param[in] js The joystick whose hat to update. - * @param[in] button The index of the hat to update. - * @param[in] value The new value of the hat. - */ -void _glfwInputJoystickHat(_GLFWjoystick* js, int hat, char value); - - -//======================================================================== -// Utility functions -//======================================================================== - -/*! @brief Chooses the video mode most closely matching the desired one. - * @ingroup utility - */ -const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, - const GLFWvidmode* desired); - -/*! @brief Performs lexical comparison between two @ref GLFWvidmode structures. - * @ingroup utility - */ -int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second); - -/*! @brief Splits a color depth into red, green and blue bit depths. - * @ingroup utility - */ -void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); - -/*! @brief Searches an extension string for the specified extension. - * @param[in] string The extension string to search. - * @param[in] extensions The extension to search for. - * @return `GLFW_TRUE` if the extension was found, or `GLFW_FALSE` otherwise. - * @ingroup utility - */ GLFWbool _glfwStringInExtensionString(const char* string, const char* extensions); - -/*! @brief Chooses the framebuffer config that best matches the desired one. - * @param[in] desired The desired framebuffer config. - * @param[in] alternatives The framebuffer configs supported by the system. - * @param[in] count The number of entries in the alternatives array. - * @return The framebuffer config most closely matching the desired one, or @c - * NULL if none fulfilled the hard constraints of the desired values. - * @ingroup utility - */ const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, const _GLFWfbconfig* alternatives, unsigned int count); - -/*! @brief Retrieves the attributes of the current context. - * @param[in] ctxconfig The desired context attributes. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if the context is - * unusable. - * @ingroup utility - */ GLFWbool _glfwRefreshContextAttribs(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig); - -/*! @brief Checks whether the desired context attributes are valid. - * @param[in] ctxconfig The context attributes to check. - * @return `GLFW_TRUE` if the context attributes are valid, or `GLFW_FALSE` - * otherwise. - * @ingroup utility - * - * This function checks things like whether the specified client API version - * exists and whether all relevant options have supported and non-conflicting - * values. - */ GLFWbool _glfwIsValidContextConfig(const _GLFWctxconfig* ctxconfig); -/*! @brief Allocates red, green and blue value arrays of the specified size. - * @ingroup utility - */ -void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size); - -/*! @brief Frees the red, green and blue value arrays and clears the struct. - * @ingroup utility - */ -void _glfwFreeGammaArrays(GLFWgammaramp* ramp); - -/*! @brief Allocates and returns a monitor object with the specified name - * and dimensions. - * @param[in] name The name of the monitor. - * @param[in] widthMM The width, in mm, of the monitor's display area. - * @param[in] heightMM The height, in mm, of the monitor's display area. - * @return The newly created object. - * @ingroup utility - */ +const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, + const GLFWvidmode* desired); +int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second); _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM); - -/*! @brief Frees a monitor object and any data associated with it. - * @ingroup utility - */ void _glfwFreeMonitor(_GLFWmonitor* monitor); +void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size); +void _glfwFreeGammaArrays(GLFWgammaramp* ramp); +void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); -/*! @brief Returns an available joystick object with arrays and name allocated. - * @ingroup utility - */ _GLFWjoystick* _glfwAllocJoystick(const char* name, const char* guid, int axisCount, int buttonCount, int hatCount); - -/*! @brief Frees arrays and name and flags the joystick object as unused. - * @ingroup utility - */ void _glfwFreeJoystick(_GLFWjoystick* js); -/*! @ingroup utility - */ GLFWbool _glfwInitVulkan(int mode); - -/*! @ingroup utility - */ void _glfwTerminateVulkan(void); - -/*! @ingroup utility - */ const char* _glfwGetVulkanResultString(VkResult result); +char* _glfw_strdup(const char* source); + diff --git a/glfw/monitor.c b/glfw/monitor.c index 21e52723a..050a046c0 100644 --- a/glfw/monitor.c +++ b/glfw/monitor.c @@ -86,6 +86,8 @@ static GLFWbool refreshVideoModes(_GLFWmonitor* monitor) ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// +// Notifies shared code of a monitor connection or disconnection +// void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) { if (action == GLFW_CONNECTED) @@ -141,6 +143,9 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement) _glfwFreeMonitor(monitor); } +// Notifies shared code that a full screen window has acquired or released +// a monitor +// void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window) { monitor->window = window; @@ -151,6 +156,8 @@ void _glfwInputMonitorWindow(_GLFWmonitor* monitor, _GLFWwindow* window) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +// Allocates and returns a monitor object with the specified name and dimensions +// _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM) { _GLFWmonitor* monitor = calloc(1, sizeof(_GLFWmonitor)); @@ -158,11 +165,13 @@ _GLFWmonitor* _glfwAllocMonitor(const char* name, int widthMM, int heightMM) monitor->heightMM = heightMM; if (name) - monitor->name = strdup(name); + monitor->name = _glfw_strdup(name); return monitor; } +// Frees a monitor object and any data associated with it +// void _glfwFreeMonitor(_GLFWmonitor* monitor) { if (monitor == NULL) @@ -176,6 +185,8 @@ void _glfwFreeMonitor(_GLFWmonitor* monitor) free(monitor); } +// Allocates red, green and blue value arrays of the specified size +// void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size) { ramp->red = calloc(size, sizeof(unsigned short)); @@ -184,6 +195,8 @@ void _glfwAllocGammaArrays(GLFWgammaramp* ramp, unsigned int size) ramp->size = size; } +// Frees the red, green and blue value arrays and clears the struct +// void _glfwFreeGammaArrays(GLFWgammaramp* ramp) { free(ramp->red); @@ -193,6 +206,8 @@ void _glfwFreeGammaArrays(GLFWgammaramp* ramp) memset(ramp, 0, sizeof(GLFWgammaramp)); } +// Chooses the video mode most closely matching the desired one +// const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, const GLFWvidmode* desired) { @@ -243,11 +258,15 @@ const GLFWvidmode* _glfwChooseVideoMode(_GLFWmonitor* monitor, return closest; } +// Performs lexical comparison between two @ref GLFWvidmode structures +// int _glfwCompareVideoModes(const GLFWvidmode* fm, const GLFWvidmode* sm) { return compareVideoModes(fm, sm); } +// Splits a color depth into red, green and blue bit depths +// void _glfwSplitBPP(int bpp, int* red, int* green, int* blue) { int delta; diff --git a/glfw/source-info.json b/glfw/source-info.json index cf608bfa5..38b1cb63f 100644 --- a/glfw/source-info.json +++ b/glfw/source-info.json @@ -63,6 +63,7 @@ "osmesa_context.h" ], "protocols": [ + "stable/xdg-shell/xdg-shell.xml", "unstable/relative-pointer/relative-pointer-unstable-v1.xml", "unstable/pointer-constraints/pointer-constraints-unstable-v1.xml", "unstable/idle-inhibit/idle-inhibit-unstable-v1.xml" @@ -81,7 +82,7 @@ }, "wayland_protocols": [ 1, - 6 + 12 ], "win32": { "headers": [ diff --git a/glfw/win32_platform.h b/glfw/win32_platform.h index 958a31375..72718ada4 100644 --- a/glfw/win32_platform.h +++ b/glfw/win32_platform.h @@ -67,11 +67,6 @@ #include #include -#if defined(_MSC_VER) - #include - #define strdup _strdup -#endif - // HACK: Define macros that some windows.h variants don't #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E diff --git a/glfw/window.c b/glfw/window.c index ba2aaeb35..c163dfc96 100644 --- a/glfw/window.c +++ b/glfw/window.c @@ -38,6 +38,8 @@ ////// GLFW event API ////// ////////////////////////////////////////////////////////////////////////// +// Notifies shared code that a window has lost or received input focus +// void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) { if (window->callbacks.focus) @@ -64,48 +66,68 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLFWbool focused) } } +// Notifies shared code that a window has moved +// The position is specified in client-area relative screen coordinates +// void _glfwInputWindowPos(_GLFWwindow* window, int x, int y) { if (window->callbacks.pos) window->callbacks.pos((GLFWwindow*) window, x, y); } +// Notifies shared code that a window has been resized +// The size is specified in screen coordinates +// void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) { if (window->callbacks.size) window->callbacks.size((GLFWwindow*) window, width, height); } +// Notifies shared code that a window has been iconified or restored +// void _glfwInputWindowIconify(_GLFWwindow* window, GLFWbool iconified) { if (window->callbacks.iconify) window->callbacks.iconify((GLFWwindow*) window, iconified); } +// Notifies shared code that a window has been maximized or restored +// void _glfwInputWindowMaximize(_GLFWwindow* window, GLFWbool maximized) { if (window->callbacks.maximize) window->callbacks.maximize((GLFWwindow*) window, maximized); } +// Notifies shared code that a window framebuffer has been resized +// The size is specified in pixels +// void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) { if (window->callbacks.fbsize) window->callbacks.fbsize((GLFWwindow*) window, width, height); } +// Notifies shared code that a window content scale has changed +// The scale is specified as the ratio between the current and default DPI +// void _glfwInputWindowContentScale(_GLFWwindow* window, float xscale, float yscale) { if (window->callbacks.scale) window->callbacks.scale((GLFWwindow*) window, xscale, yscale); } +// Notifies shared code that the window contents needs updating +// void _glfwInputWindowDamage(_GLFWwindow* window) { if (window->callbacks.refresh) window->callbacks.refresh((GLFWwindow*) window); } +// Notifies shared code that the user wishes to close a window +// void _glfwInputWindowCloseRequest(_GLFWwindow* window) { window->shouldClose = GLFW_TRUE; @@ -114,6 +136,8 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window) window->callbacks.close((GLFWwindow*) window); } +// Notifies shared code that a window has changed its desired monitor +// void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor) { window->monitor = monitor; diff --git a/glfw/wl_init.c b/glfw/wl_init.c index f7fad8d27..f7c4d4b18 100644 --- a/glfw/wl_init.c +++ b/glfw/wl_init.c @@ -34,7 +34,6 @@ #include #include #include -#include static inline int min(int n1, int n2) @@ -49,6 +48,10 @@ static void pointerHandleEnter(void* data, wl_fixed_t sx, wl_fixed_t sy) { + // Happens in the case we just destroyed the surface. + if (!surface) + return; + _GLFWwindow* window = wl_surface_get_user_data(surface); _glfw.wl.pointerSerial = serial; @@ -280,6 +283,10 @@ static void keyboardHandleEnter(void* data, struct wl_surface* surface, struct wl_array* keys) { + // Happens in the case we just destroyed the surface. + if (!surface) + return; + _GLFWwindow* window = wl_surface_get_user_data(surface); _glfw.wl.keyboardFocus = window; @@ -463,6 +470,17 @@ static const struct wl_seat_listener seatListener = { seatHandleCapabilities }; +static void wmBaseHandlePing(void* data, + struct xdg_wm_base* wmBase, + uint32_t serial) +{ + xdg_wm_base_pong(wmBase, serial); +} + +static const struct xdg_wm_base_listener wmBaseListener = { + wmBaseHandlePing +}; + static void registryHandleGlobal(void* data, struct wl_registry* registry, uint32_t name, @@ -499,6 +517,12 @@ static void registryHandleGlobal(void* data, wl_seat_add_listener(_glfw.wl.seat, &seatListener, NULL); } } + else if (strcmp(interface, "xdg_wm_base") == 0) + { + _glfw.wl.wmBase = + wl_registry_bind(registry, name, &xdg_wm_base_interface, 1); + xdg_wm_base_add_listener(_glfw.wl.wmBase, &wmBaseListener, NULL); + } else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) { _glfw.wl.relativePointerManager = @@ -675,50 +699,82 @@ static void createKeyTables(void) int _glfwPlatformInit(void) { - _glfw.wl.xkb.handle = dlopen("libxkbcommon.so.0", RTLD_LAZY | RTLD_GLOBAL); + _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0"); + if (!_glfw.wl.cursor.handle) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to open libwayland-cursor"); + return GLFW_FALSE; + } + + _glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load) + _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load"); + _glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy) + _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy"); + _glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor) + _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor"); + _glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer) + _glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer"); + + _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1"); + if (!_glfw.wl.egl.handle) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Failed to open libwayland-egl"); + return GLFW_FALSE; + } + + _glfw.wl.egl.window_create = (PFN_wl_egl_window_create) + _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create"); + _glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy) + _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy"); + _glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize) + _glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize"); + + _glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0"); if (!_glfw.wl.xkb.handle) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Failed to open libxkbcommon."); + "Wayland: Failed to open libxkbcommon"); return GLFW_FALSE; } _glfw.wl.xkb.context_new = (PFN_xkb_context_new) - dlsym(_glfw.wl.xkb.handle, "xkb_context_new"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new"); _glfw.wl.xkb.context_unref = (PFN_xkb_context_unref) - dlsym(_glfw.wl.xkb.handle, "xkb_context_unref"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref"); _glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string) - dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string"); _glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref) - dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref"); _glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index) - dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index"); _glfw.wl.xkb.state_new = (PFN_xkb_state_new) - dlsym(_glfw.wl.xkb.handle, "xkb_state_new"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new"); _glfw.wl.xkb.state_unref = (PFN_xkb_state_unref) - dlsym(_glfw.wl.xkb.handle, "xkb_state_unref"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref"); _glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms) - dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms"); _glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask) - dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask"); _glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods) - dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods"); #ifdef HAVE_XKBCOMMON_COMPOSE_H _glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale) - dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale"); _glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref) - dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref"); _glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new) - dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new"); _glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref) - dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref"); _glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed) - dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed"); _glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status) - dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status"); _glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym) - dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); + _glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym"); #endif _glfw.wl.display = wl_display_connect(NULL); @@ -759,7 +815,7 @@ int _glfwPlatformInit(void) if (!_glfw.wl.cursorTheme) { _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Unable to load default cursor theme\n"); + "Wayland: Unable to load default cursor theme"); return GLFW_FALSE; } _glfw.wl.cursorSurface = @@ -771,21 +827,24 @@ int _glfwPlatformInit(void) void _glfwPlatformTerminate(void) { - _glfwTerminateEGL(); _glfwTerminateJoysticksLinux(); + _glfwTerminateEGL(); + if (_glfw.wl.egl.handle) + { + _glfw_dlclose(_glfw.wl.egl.handle); + _glfw.wl.egl.handle = NULL; + } #ifdef HAVE_XKBCOMMON_COMPOSE_H if (_glfw.wl.xkb.composeState) xkb_compose_state_unref(_glfw.wl.xkb.composeState); #endif - if (_glfw.wl.xkb.keymap) xkb_keymap_unref(_glfw.wl.xkb.keymap); if (_glfw.wl.xkb.state) xkb_state_unref(_glfw.wl.xkb.state); if (_glfw.wl.xkb.context) xkb_context_unref(_glfw.wl.xkb.context); - if (_glfw.wl.xkb.handle) { _glfw_dlclose(_glfw.wl.xkb.handle); @@ -794,6 +853,12 @@ void _glfwPlatformTerminate(void) if (_glfw.wl.cursorTheme) wl_cursor_theme_destroy(_glfw.wl.cursorTheme); + if (_glfw.wl.cursor.handle) + { + _glfw_dlclose(_glfw.wl.cursor.handle); + _glfw.wl.cursor.handle = NULL; + } + if (_glfw.wl.cursorSurface) wl_surface_destroy(_glfw.wl.cursorSurface); if (_glfw.wl.compositor) @@ -802,6 +867,8 @@ void _glfwPlatformTerminate(void) wl_shm_destroy(_glfw.wl.shm); if (_glfw.wl.shell) wl_shell_destroy(_glfw.wl.shell); + if (_glfw.wl.wmBase) + xdg_wm_base_destroy(_glfw.wl.wmBase); if (_glfw.wl.pointer) wl_pointer_destroy(_glfw.wl.pointer); if (_glfw.wl.keyboard) diff --git a/glfw/wl_monitor.c b/glfw/wl_monitor.c index 10ef0e128..ed351e768 100644 --- a/glfw/wl_monitor.c +++ b/glfw/wl_monitor.c @@ -52,7 +52,7 @@ static void geometry(void* data, monitor->heightMM = physicalHeight; snprintf(name, sizeof(name), "%s %s", make, model); - monitor->name = strdup(name); + monitor->name = _glfw_strdup(name); } static void mode(void* data, diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index 534998124..1eaf4d2a2 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -52,6 +52,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #include "egl_context.h" #include "osmesa_context.h" +#include "wayland-xdg-shell-client-protocol.h" #include "wayland-relative-pointer-unstable-v1-client-protocol.h" #include "wayland-pointer-constraints-unstable-v1-client-protocol.h" #include "wayland-idle-inhibit-unstable-v1-client-protocol.h" @@ -71,6 +72,34 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR #define _GLFW_PLATFORM_CONTEXT_STATE #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE +struct wl_cursor_image { + uint32_t width; + uint32_t height; + uint32_t hotspot_x; + uint32_t hotspot_y; + uint32_t delay; +}; +struct wl_cursor { + unsigned int image_count; + struct wl_cursor_image** images; + char* name; +}; +typedef struct wl_cursor_theme* (* PFN_wl_cursor_theme_load)(const char*, int, struct wl_shm*); +typedef void (* PFN_wl_cursor_theme_destroy)(struct wl_cursor_theme*); +typedef struct wl_cursor* (* PFN_wl_cursor_theme_get_cursor)(struct wl_cursor_theme*, const char*); +typedef struct wl_buffer* (* PFN_wl_cursor_image_get_buffer)(struct wl_cursor_image*); +#define wl_cursor_theme_load _glfw.wl.cursor.theme_load +#define wl_cursor_theme_destroy _glfw.wl.cursor.theme_destroy +#define wl_cursor_theme_get_cursor _glfw.wl.cursor.theme_get_cursor +#define wl_cursor_image_get_buffer _glfw.wl.cursor.image_get_buffer + +typedef struct wl_egl_window* (* PFN_wl_egl_window_create)(struct wl_surface*, int, int); +typedef void (* PFN_wl_egl_window_destroy)(struct wl_egl_window*); +typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int, int); +#define wl_egl_window_create _glfw.wl.egl.window_create +#define wl_egl_window_destroy _glfw.wl.egl.window_destroy +#define wl_egl_window_resize _glfw.wl.egl.window_resize + typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags); typedef void (* PFN_xkb_context_unref)(struct xkb_context*); typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags); @@ -124,6 +153,11 @@ typedef struct _GLFWwindowWayland struct wl_shell_surface* shellSurface; struct wl_callback* callback; + struct { + struct xdg_surface* surface; + struct xdg_toplevel* toplevel; + } xdg; + _GLFWcursor* currentCursor; double cursorPosX, cursorPosY; @@ -143,6 +177,9 @@ typedef struct _GLFWwindowWayland struct zwp_idle_inhibitor_v1* idleInhibitor; + // This is a hack to prevent auto-iconification on creation. + GLFWbool justCreated; + } _GLFWwindowWayland; // Wayland-specific global data @@ -157,6 +194,7 @@ typedef struct _GLFWlibraryWayland struct wl_seat* seat; struct wl_pointer* pointer; struct wl_keyboard* keyboard; + struct xdg_wm_base* wmBase; struct zwp_relative_pointer_manager_v1* relativePointerManager; struct zwp_pointer_constraints_v1* pointerConstraints; struct zwp_idle_inhibit_manager_v1* idleInhibitManager; @@ -213,6 +251,23 @@ typedef struct _GLFWlibraryWayland _GLFWwindow* pointerFocus; _GLFWwindow* keyboardFocus; + struct { + void* handle; + + PFN_wl_cursor_theme_load theme_load; + PFN_wl_cursor_theme_destroy theme_destroy; + PFN_wl_cursor_theme_get_cursor theme_get_cursor; + PFN_wl_cursor_image_get_buffer image_get_buffer; + } cursor; + + struct { + void* handle; + + PFN_wl_egl_window_create window_create; + PFN_wl_egl_window_destroy window_destroy; + PFN_wl_egl_window_resize window_resize; + } egl; + } _GLFWlibraryWayland; // Wayland-specific per-monitor data diff --git a/glfw/wl_window.c b/glfw/wl_window.c index a16826dce..aec6aed52 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -37,9 +37,6 @@ #include #include -#include -#include - static void handlePing(void* data, struct wl_shell_surface* shellSurface, @@ -239,10 +236,21 @@ static GLFWbool createSurface(_GLFWwindow* window, static GLFWbool createShellSurface(_GLFWwindow* window) { + if (!_glfw.wl.shell) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: wl_shell protocol not available"); + return GLFW_FALSE; + } + window->wl.shellSurface = wl_shell_get_shell_surface(_glfw.wl.shell, window->wl.surface); if (!window->wl.shellSurface) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Shell surface creation failed"); return GLFW_FALSE; + } wl_shell_surface_add_listener(window->wl.shellSurface, &shellSurfaceListener, @@ -276,6 +284,146 @@ static GLFWbool createShellSurface(_GLFWwindow* window) return GLFW_TRUE; } +static void xdgToplevelHandleConfigure(void* data, + struct xdg_toplevel* toplevel, + int32_t width, + int32_t height, + struct wl_array* states) +{ + _GLFWwindow* window = data; + float aspectRatio; + float targetRatio; + uint32_t* state; + GLFWbool maximized = GLFW_FALSE; + GLFWbool fullscreen = GLFW_FALSE; + GLFWbool activated = GLFW_FALSE; + + wl_array_for_each(state, states) + { + switch (*state) + { + case XDG_TOPLEVEL_STATE_MAXIMIZED: + maximized = GLFW_TRUE; + break; + case XDG_TOPLEVEL_STATE_FULLSCREEN: + fullscreen = GLFW_TRUE; + break; + case XDG_TOPLEVEL_STATE_RESIZING: + break; + case XDG_TOPLEVEL_STATE_ACTIVATED: + activated = GLFW_TRUE; + break; + } + } + + if (width != 0 && height != 0) + { + if (!maximized && !fullscreen) + { + if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) + { + aspectRatio = (float)width / (float)height; + targetRatio = (float)window->numer / (float)window->denom; + if (aspectRatio < targetRatio) + height = width / targetRatio; + else if (aspectRatio > targetRatio) + width = height * targetRatio; + } + } + + _glfwInputWindowSize(window, width, height); + _glfwPlatformSetWindowSize(window, width, height); + _glfwInputWindowDamage(window); + } + + if (!window->wl.justCreated && !activated && window->autoIconify) + _glfwPlatformIconifyWindow(window); + _glfwInputWindowFocus(window, activated); + window->wl.justCreated = GLFW_FALSE; +} + +static void xdgToplevelHandleClose(void* data, + struct xdg_toplevel* toplevel) +{ + _GLFWwindow* window = data; + _glfwInputWindowCloseRequest(window); +} + +static const struct xdg_toplevel_listener xdgToplevelListener = { + xdgToplevelHandleConfigure, + xdgToplevelHandleClose +}; + +static void xdgSurfaceHandleConfigure(void* data, + struct xdg_surface* surface, + uint32_t serial) +{ + xdg_surface_ack_configure(surface, serial); +} + +static const struct xdg_surface_listener xdgSurfaceListener = { + xdgSurfaceHandleConfigure +}; + +static GLFWbool createXdgSurface(_GLFWwindow* window) +{ + window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase, + window->wl.surface); + if (!window->wl.xdg.surface) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: xdg-surface creation failed"); + return GLFW_FALSE; + } + + xdg_surface_add_listener(window->wl.xdg.surface, + &xdgSurfaceListener, + window); + + window->wl.xdg.toplevel = xdg_surface_get_toplevel(window->wl.xdg.surface); + if (!window->wl.xdg.toplevel) + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: xdg-toplevel creation failed"); + return GLFW_FALSE; + } + + xdg_toplevel_add_listener(window->wl.xdg.toplevel, + &xdgToplevelListener, + window); + + if (window->wl.title) + xdg_toplevel_set_title(window->wl.xdg.toplevel, window->wl.title); + + if (window->minwidth != GLFW_DONT_CARE && window->minheight != GLFW_DONT_CARE) + xdg_toplevel_set_min_size(window->wl.xdg.toplevel, + window->minwidth, window->minheight); + if (window->maxwidth != GLFW_DONT_CARE && window->maxheight != GLFW_DONT_CARE) + xdg_toplevel_set_max_size(window->wl.xdg.toplevel, + window->maxwidth, window->maxheight); + + if (window->monitor) + { + xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel, + window->monitor->wl.output); + setIdleInhibitor(window, GLFW_TRUE); + } + else if (window->wl.maximized) + { + xdg_toplevel_set_maximized(window->wl.xdg.toplevel); + setIdleInhibitor(window, GLFW_FALSE); + } + else + { + setIdleInhibitor(window, GLFW_FALSE); + } + + wl_surface_commit(window->wl.surface); + wl_display_roundtrip(_glfw.wl.display); + + return GLFW_TRUE; +} + static int createTmpfileCloexec(char* tmpname) { @@ -412,6 +560,7 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { + window->wl.justCreated = GLFW_TRUE; window->wl.transparent = fbconfig->transparent; if (!createSurface(window, wndconfig)) @@ -437,17 +586,27 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window, } if (wndconfig->title) - window->wl.title = strdup(wndconfig->title); + window->wl.title = _glfw_strdup(wndconfig->title); if (wndconfig->visible) { - if (!createShellSurface(window)) - return GLFW_FALSE; + if (_glfw.wl.wmBase) + { + if (!createXdgSurface(window)) + return GLFW_FALSE; + } + else + { + if (!createShellSurface(window)) + return GLFW_FALSE; + } window->wl.visible = GLFW_TRUE; } else { + window->wl.xdg.surface = NULL; + window->wl.xdg.toplevel = NULL; window->wl.shellSurface = NULL; window->wl.visible = GLFW_FALSE; } @@ -486,6 +645,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window) if (window->wl.shellSurface) wl_shell_surface_destroy(window->wl.shellSurface); + if (window->wl.xdg.toplevel) + xdg_toplevel_destroy(window->wl.xdg.toplevel); + + if (window->wl.xdg.surface) + xdg_surface_destroy(window->wl.xdg.surface); + if (window->wl.surface) wl_surface_destroy(window->wl.surface); @@ -497,8 +662,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) { if (window->wl.title) free(window->wl.title); - window->wl.title = strdup(title); - if (window->wl.shellSurface) + window->wl.title = _glfw_strdup(title); + if (window->wl.xdg.toplevel) + xdg_toplevel_set_title(window->wl.xdg.toplevel, title); + else if (window->wl.shellSurface) wl_shell_surface_set_title(window->wl.shellSurface, title); } @@ -550,8 +717,24 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight) { - // TODO: find out how to trigger a resize. - // The actual limits are checked in the wl_shell_surface::configure handler. + if (_glfw.wl.wmBase) + { + if (window->wl.xdg.toplevel) + { + if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE) + minwidth = minheight = 0; + if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE) + maxwidth = maxheight = 0; + xdg_toplevel_set_min_size(window->wl.xdg.toplevel, minwidth, minheight); + xdg_toplevel_set_max_size(window->wl.xdg.toplevel, maxwidth, maxheight); + wl_surface_commit(window->wl.surface); + } + } + else + { + // TODO: find out how to trigger a resize. + // The actual limits are checked in the wl_shell_surface::configure handler. + } } void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) @@ -586,41 +769,59 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, void _glfwPlatformIconifyWindow(_GLFWwindow* window) { - // TODO: move to xdg_shell instead of wl_shell. - _glfwInputError(GLFW_PLATFORM_ERROR, - "Wayland: Iconify window not supported"); + if (_glfw.wl.wmBase) + { + if (window->wl.xdg.toplevel) + xdg_toplevel_set_minimized(window->wl.xdg.toplevel); + } + else + { + _glfwInputError(GLFW_PLATFORM_ERROR, + "Wayland: Iconify window not supported on wl_shell"); + } } void _glfwPlatformRestoreWindow(_GLFWwindow* window) { - // TODO: also do the same for iconified. - if (window->monitor || window->wl.maximized) + if (window->wl.xdg.toplevel) { - if (window->wl.shellSurface) - wl_shell_surface_set_toplevel(window->wl.shellSurface); - - window->wl.maximized = GLFW_FALSE; + if (window->monitor) + xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); + if (window->wl.maximized) + xdg_toplevel_unset_maximized(window->wl.xdg.toplevel); + // There is no way to unset minimized, or even to know if we are + // minimized, so there is nothing to do here. } + else if (window->wl.shellSurface) + { + if (window->monitor || window->wl.maximized) + wl_shell_surface_set_toplevel(window->wl.shellSurface); + } + _glfwInputWindowMonitor(window, NULL); + window->wl.maximized = GLFW_FALSE; } void _glfwPlatformMaximizeWindow(_GLFWwindow* window) { - if (!window->monitor && !window->wl.maximized) + if (window->wl.xdg.toplevel) { - if (window->wl.shellSurface) - { - // Let the compositor select the best output. - wl_shell_surface_set_maximized(window->wl.shellSurface, NULL); - } - window->wl.maximized = GLFW_TRUE; + xdg_toplevel_set_maximized(window->wl.xdg.toplevel); } + else if (window->wl.shellSurface) + { + // Let the compositor select the best output. + wl_shell_surface_set_maximized(window->wl.shellSurface, NULL); + } + window->wl.maximized = GLFW_TRUE; } void _glfwPlatformShowWindow(_GLFWwindow* window) { - if (!window->monitor) + if (!window->wl.visible) { - if (!window->wl.shellSurface) + if (_glfw.wl.wmBase) + createXdgSurface(window); + else if (!window->wl.shellSurface) createShellSurface(window); window->wl.visible = GLFW_TRUE; } @@ -628,12 +829,19 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformHideWindow(_GLFWwindow* window) { - if (!window->monitor) + if (window->wl.xdg.toplevel) { - if (window->wl.shellSurface) - wl_shell_surface_destroy(window->wl.shellSurface); - window->wl.visible = GLFW_FALSE; + xdg_toplevel_destroy(window->wl.xdg.toplevel); + xdg_surface_destroy(window->wl.xdg.surface); + window->wl.xdg.toplevel = NULL; + window->wl.xdg.surface = NULL; } + else if (window->wl.shellSurface) + { + wl_shell_surface_destroy(window->wl.shellSurface); + window->wl.shellSurface = NULL; + } + window->wl.visible = GLFW_FALSE; } void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) @@ -663,20 +871,35 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, int width, int height, int refreshRate) { - if (monitor) + if (window->wl.xdg.toplevel) { - wl_shell_surface_set_fullscreen( - window->wl.shellSurface, - WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, - refreshRate * 1000, // Convert Hz to mHz. - monitor->wl.output); - setIdleInhibitor(window, GLFW_TRUE); + if (monitor) + { + xdg_toplevel_set_fullscreen( + window->wl.xdg.toplevel, + monitor->wl.output); + } + else + { + xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel); + } } - else + else if (window->wl.shellSurface) { - wl_shell_surface_set_toplevel(window->wl.shellSurface); - setIdleInhibitor(window, GLFW_FALSE); + if (monitor) + { + wl_shell_surface_set_fullscreen( + window->wl.shellSurface, + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, + refreshRate * 1000, // Convert Hz to mHz. + monitor->wl.output); + } + else + { + wl_shell_surface_set_toplevel(window->wl.shellSurface); + } } + setIdleInhibitor(window, monitor ? GLFW_TRUE : GLFW_FALSE); _glfwInputWindowMonitor(window, monitor); } @@ -687,7 +910,8 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window) int _glfwPlatformWindowIconified(_GLFWwindow* window) { - // TODO: move to xdg_shell, wl_shell doesn't have any iconified concept. + // wl_shell doesn't have any iconified concept, and xdg-shell doesn’t give + // any way to request whether a surface is iconified. return GLFW_FALSE; } @@ -1152,4 +1376,3 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle) _GLFW_REQUIRE_INIT_OR_RETURN(NULL); return window->wl.surface; } - diff --git a/glfw/x11_init.c b/glfw/x11_init.c index 6786231c8..af4fb7ed6 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -461,17 +461,17 @@ static void detectEWMH(void) // static GLFWbool initExtensions(void) { - _glfw.x11.vidmode.handle = dlopen("libXxf86vm.so.1", RTLD_LAZY | RTLD_GLOBAL); + _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1"); if (_glfw.x11.vidmode.handle) { _glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) - dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); + _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); _glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) - dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); + _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); _glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp) - dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); + _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp"); _glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize) - dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); + _glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize"); _glfw.x11.vidmode.available = XF86VidModeQueryExtension(_glfw.x11.display, @@ -479,13 +479,13 @@ static GLFWbool initExtensions(void) &_glfw.x11.vidmode.errorBase); } - _glfw.x11.xi.handle = dlopen("libXi.so.6", RTLD_LAZY | RTLD_GLOBAL); + _glfw.x11.xi.handle = _glfw_dlopen("libXi.so.6"); if (_glfw.x11.xi.handle) { _glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) - dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); + _glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); _glfw.x11.xi.SelectEvents = (PFN_XISelectEvents) - dlsym(_glfw.x11.xi.handle, "XISelectEvents"); + _glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents"); if (XQueryExtension(_glfw.x11.display, "XInputExtension", @@ -505,45 +505,45 @@ static GLFWbool initExtensions(void) } } - _glfw.x11.randr.handle = dlopen("libXrandr.so.2", RTLD_LAZY | RTLD_GLOBAL); + _glfw.x11.randr.handle = _glfw_dlopen("libXrandr.so.2"); if (_glfw.x11.randr.handle) { _glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) - dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) - dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) - dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); _glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) - dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); _glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) - dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); _glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) - dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); _glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) - dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); _glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) - dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); _glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) - dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); _glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo) - dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo"); _glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary) - dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary"); _glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent) - dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent"); _glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension) - dlsym(_glfw.x11.randr.handle, "XRRQueryExtension"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension"); _glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion) - dlsym(_glfw.x11.randr.handle, "XRRQueryVersion"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion"); _glfw.x11.randr.SelectInput = (PFN_XRRSelectInput) - dlsym(_glfw.x11.randr.handle, "XRRSelectInput"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput"); _glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig) - dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig"); _glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma) - dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma"); _glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration) - dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); + _glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration"); if (XRRQueryExtension(_glfw.x11.display, &_glfw.x11.randr.eventBase, @@ -593,26 +593,26 @@ static GLFWbool initExtensions(void) RROutputChangeNotifyMask); } - _glfw.x11.xcursor.handle = dlopen("libXcursor.so.1", RTLD_LAZY | RTLD_GLOBAL); + _glfw.x11.xcursor.handle = _glfw_dlopen("libXcursor.so.1"); if (_glfw.x11.xcursor.handle) { _glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) - dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); + _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); _glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) - dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); + _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy"); _glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor) - dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); + _glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor"); } - _glfw.x11.xinerama.handle = dlopen("libXinerama.so.1", RTLD_LAZY | RTLD_GLOBAL); + _glfw.x11.xinerama.handle = _glfw_dlopen("libXinerama.so.1"); if (_glfw.x11.xinerama.handle) { _glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) - dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); + _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); _glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) - dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); + _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension"); _glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens) - dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); + _glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens"); if (XineramaQueryExtension(_glfw.x11.display, &_glfw.x11.xinerama.major, @@ -644,22 +644,22 @@ static GLFWbool initExtensions(void) } } - _glfw.x11.x11xcb.handle = dlopen("libX11-xcb.so.1", RTLD_LAZY | RTLD_GLOBAL); + _glfw.x11.x11xcb.handle = _glfw_dlopen("libX11-xcb.so.1"); if (_glfw.x11.x11xcb.handle) { _glfw.x11.x11xcb.GetXCBConnection = (PFN_XGetXCBConnection) - dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); + _glfw_dlsym(_glfw.x11.x11xcb.handle, "XGetXCBConnection"); } - _glfw.x11.xrender.handle = dlopen("libXrender.so.1", RTLD_LAZY | RTLD_GLOBAL); + _glfw.x11.xrender.handle = _glfw_dlopen("libXrender.so.1"); if (_glfw.x11.xrender.handle) { _glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) - dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); + _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); _glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) - dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion"); + _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion"); _glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat) - dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); + _glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat"); if (XRenderQueryExtension(_glfw.x11.display, &_glfw.x11.xrender.errorBase, @@ -1002,25 +1002,25 @@ void _glfwPlatformTerminate(void) if (_glfw.x11.x11xcb.handle) { - dlclose(_glfw.x11.x11xcb.handle); + _glfw_dlclose(_glfw.x11.x11xcb.handle); _glfw.x11.x11xcb.handle = NULL; } if (_glfw.x11.xcursor.handle) { - dlclose(_glfw.x11.xcursor.handle); + _glfw_dlclose(_glfw.x11.xcursor.handle); _glfw.x11.xcursor.handle = NULL; } if (_glfw.x11.randr.handle) { - dlclose(_glfw.x11.randr.handle); + _glfw_dlclose(_glfw.x11.randr.handle); _glfw.x11.randr.handle = NULL; } if (_glfw.x11.xinerama.handle) { - dlclose(_glfw.x11.xinerama.handle); + _glfw_dlclose(_glfw.x11.xinerama.handle); _glfw.x11.xinerama.handle = NULL; } diff --git a/glfw/x11_window.c b/glfw/x11_window.c index 2b151c5a2..5f22d6dfd 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -1056,7 +1056,7 @@ static const char* getSelectionString(Atom selection) if (targets[i] == XA_STRING) *selectionString = convertLatin1toUTF8(data); else - *selectionString = strdup(data); + *selectionString = _glfw_strdup(data); } XFree(data); @@ -2839,7 +2839,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwPlatformSetClipboardString(const char* string) { free(_glfw.x11.clipboardString); - _glfw.x11.clipboardString = strdup(string); + _glfw.x11.clipboardString = _glfw_strdup(string); XSetSelectionOwner(_glfw.x11.display, _glfw.x11.CLIPBOARD, @@ -3031,7 +3031,7 @@ GLFWAPI void glfwSetX11SelectionString(const char* string) _GLFW_REQUIRE_INIT(); free(_glfw.x11.primarySelectionString); - _glfw.x11.primarySelectionString = strdup(string); + _glfw.x11.primarySelectionString = _glfw_strdup(string); XSetSelectionOwner(_glfw.x11.display, _glfw.x11.PRIMARY, diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index fbc45b28c..f5ff30016 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -572,6 +572,10 @@ * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib). */ #define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A +/*! @brief Mouse cursor hover window attribute. + * + * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). + */ #define GLFW_HOVERED 0x0002000B /*! @brief Framebuffer bit depth hint.