Merge branch 'glfw:master' into master

This commit is contained in:
KhankNyo 2026-02-16 00:49:34 -08:00 • committed by GitHub
commit 52beeee6fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 281 additions and 242 deletions

View file

@ -79,6 +79,7 @@ video tutorials.
- Jason Francis
- Gerald Franz
- Mário Freitas
- Friz64
- GeO4d
- Marcus Geelnard
- Gegy

View file

@ -148,12 +148,17 @@ information on what to include when reporting a bug.
potential segmentation fault (#2744)
- [Wayland] Bugfix: Confining or disabling the cursor could segfault on
compositors without `pointer-constraints-unstable-v1`
- [Wayland] Bugfix: Key repeat did not function on very old compositors
- [Wayland] Bugfix: The `libwayland-client` library was not unloaded at termination
- [Wayland] Bugfix: Scroll events were sent twice on some versions of GNOME (#2494)
- [Wayland] Bugfix: Two-dimensional scroll input was emitted as separate axes
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [X11] Bugfix: Occasional crash when an idle display awakes (#2766)
- [X11] Bugfix: Prevent BadWindow when creating small windows with a content scale
less than 1 (#2754)
- [X11] Bugfix: Clamp width and height to >= 1 to prevent BadValue error and app exit
- [X11] Bugfix: Floating windows silently became non-floating when hidden (#2276)
- [X11] Bugfix: The `libXext` library was not unloaded at termination
- [Linux] Bugfix: The header for `ioctl` was only implicitly included (#2778)
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`

View file

@ -688,6 +688,8 @@ void _glfwTerminateCocoa(void)
_glfwTerminateEGL();
_glfwTerminateOSMesa();
memset(&_glfw.ns, 0, sizeof(_glfw.ns));
} // autoreleasepool
}

View file

@ -312,18 +312,19 @@ static int extensionSupportedEGL(const char* extension)
static GLFWglproc getProcAddressEGL(const char* procname)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
const GLFWglproc proc = (GLFWglproc) eglGetProcAddress(procname);
if (proc)
return proc;
if (window->context.egl.client)
if (!_glfw.egl.KHR_get_all_proc_addresses)
{
GLFWglproc proc = (GLFWglproc)
_glfwPlatformGetModuleSymbol(window->context.egl.client, procname);
if (proc)
return proc;
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
assert(window != NULL);
return _glfwPlatformGetModuleSymbol(window->context.egl.client, procname);
}
return eglGetProcAddress(procname);
return NULL;
}
static void destroyContextEGL(_GLFWwindow* window)
@ -333,11 +334,8 @@ static void destroyContextEGL(_GLFWwindow* window)
if (_glfw.platform.platformID != GLFW_PLATFORM_X11 ||
window->context.client != GLFW_OPENGL_API)
{
if (window->context.egl.client)
{
_glfwPlatformFreeModule(window->context.egl.client);
window->context.egl.client = NULL;
}
_glfwPlatformFreeModule(window->context.egl.client);
window->context.egl.client = NULL;
}
if (window->context.egl.surface)
@ -358,8 +356,6 @@ static void destroyContextEGL(_GLFWwindow* window)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize EGL
//
GLFWbool _glfwInitEGL(void)
{
int i;
@ -369,10 +365,10 @@ GLFWbool _glfwInitEGL(void)
{
#if defined(_GLFW_EGL_LIBRARY)
_GLFW_EGL_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
"libEGL.dll",
"EGL.dll",
#elif defined(_GLFW_COCOA)
#elif defined(__APPLE__)
"libEGL.dylib",
#elif defined(__CYGWIN__)
"libEGL-1.so",
@ -545,8 +541,6 @@ GLFWbool _glfwInitEGL(void)
return GLFW_TRUE;
}
// Terminate EGL
//
void _glfwTerminateEGL(void)
{
if (_glfw.egl.display)
@ -556,7 +550,7 @@ void _glfwTerminateEGL(void)
}
// Free modules only after all wayland termination functions are called
if (_glfw.egl.handle && _glfw.platform.platformID != GLFW_PLATFORM_WAYLAND)
if (_glfw.platform.platformID != GLFW_PLATFORM_WAYLAND)
{
_glfwPlatformFreeModule(_glfw.egl.handle);
_glfw.egl.handle = NULL;
@ -570,8 +564,6 @@ void _glfwTerminateEGL(void)
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
@ -769,10 +761,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
#if defined(_GLFW_GLESV1_LIBRARY)
_GLFW_GLESV1_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
"GLESv1_CM.dll",
"libGLES_CM.dll",
#elif defined(_GLFW_COCOA)
#elif defined(__APPLE__)
"libGLESv1_CM.dylib",
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGLESv1_CM.so",
@ -786,10 +778,10 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
#if defined(_GLFW_GLESV2_LIBRARY)
_GLFW_GLESV2_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
"GLESv2.dll",
"libGLESv2.dll",
#elif defined(_GLFW_COCOA)
#elif defined(__APPLE__)
"libGLESv2.dylib",
#elif defined(__CYGWIN__)
"libGLESv2-2.so",
@ -804,8 +796,8 @@ GLFWbool _glfwCreateContextEGL(_GLFWwindow* window,
{
#if defined(_GLFW_OPENGL_LIBRARY)
_GLFW_OPENGL_LIBRARY,
#elif defined(_GLFW_WIN32)
#elif defined(_GLFW_COCOA)
#elif defined(_WIN32)
#elif defined(__APPLE__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
"libGL.so",
#else

View file

@ -253,8 +253,6 @@ static void destroyContextGLX(_GLFWwindow* window)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize GLX
//
GLFWbool _glfwInitGLX(void)
{
const char* sonames[] =
@ -426,18 +424,13 @@ GLFWbool _glfwInitGLX(void)
return GLFW_TRUE;
}
// Terminate GLX
//
void _glfwTerminateGLX(void)
{
// NOTE: This function must not call any X11 functions, as it is called
// after XCloseDisplay (see _glfwTerminateX11 for details)
if (_glfw.glx.handle)
{
_glfwPlatformFreeModule(_glfw.glx.handle);
_glfw.glx.handle = NULL;
}
_glfwPlatformFreeModule(_glfw.glx.handle);
_glfw.glx.handle = NULL;
}
#define SET_ATTRIB(a, v) \
@ -447,8 +440,6 @@ void _glfwTerminateGLX(void)
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextGLX(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)

View file

@ -128,8 +128,6 @@ static void destroyContextNSGL(_GLFWwindow* window)
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize OpenGL support
//
GLFWbool _glfwInitNSGL(void)
{
if (_glfw.nsgl.framework)
@ -147,14 +145,10 @@ GLFWbool _glfwInitNSGL(void)
return GLFW_TRUE;
}
// Terminate OpenGL support
//
void _glfwTerminateNSGL(void)
{
}
// Create the OpenGL context
//
GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)

View file

@ -260,5 +260,6 @@ void _glfwTerminateNull(void)
free(_glfw.null.clipboardString);
_glfwTerminateOSMesa();
_glfwTerminateEGL();
memset(&_glfw.null, 0, sizeof(_glfw.null));
}

View file

@ -180,11 +180,8 @@ GLFWbool _glfwInitOSMesa(void)
void _glfwTerminateOSMesa(void)
{
if (_glfw.osmesa.handle)
{
_glfwPlatformFreeModule(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL;
}
_glfwPlatformFreeModule(_glfw.osmesa.handle);
_glfw.osmesa.handle = NULL;
}
#define SET_ATTRIB(a, v) \

View file

@ -41,7 +41,8 @@ void* _glfwPlatformLoadModule(const char* path)
void _glfwPlatformFreeModule(void* module)
{
dlclose(module);
if (module)
dlclose(module);
}
GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)

View file

@ -55,12 +55,13 @@ GLFWbool _glfwInitVulkan(int mode)
{
#if defined(_GLFW_VULKAN_LIBRARY)
_glfw.vk.handle = _glfwPlatformLoadModule(_GLFW_VULKAN_LIBRARY);
#elif defined(_GLFW_WIN32)
#elif defined(_WIN32)
_glfw.vk.handle = _glfwPlatformLoadModule("vulkan-1.dll");
#elif defined(_GLFW_COCOA)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.1.dylib");
if (!_glfw.vk.handle)
_glfw.vk.handle = _glfwLoadLocalVulkanLoaderCocoa();
#elif defined(__APPLE__)
#elif defined(__OpenBSD__) || defined(__NetBSD__)
_glfw.vk.handle = _glfwPlatformLoadModule("libvulkan.so");
#else
@ -157,8 +158,8 @@ GLFWbool _glfwInitVulkan(int mode)
void _glfwTerminateVulkan(void)
{
if (_glfw.vk.handle)
_glfwPlatformFreeModule(_glfw.vk.handle);
_glfwPlatformFreeModule(_glfw.vk.handle);
_glfw.vk.handle = NULL;
}
const char* _glfwGetVulkanResultString(VkResult result)

View file

@ -401,8 +401,6 @@ static void destroyContextWGL(_GLFWwindow* window)
}
}
// Initialize WGL
//
GLFWbool _glfwInitWGL(void)
{
PIXELFORMATDESCRIPTOR pfd;
@ -521,12 +519,10 @@ GLFWbool _glfwInitWGL(void)
return GLFW_TRUE;
}
// Terminate WGL
//
void _glfwTerminateWGL(void)
{
if (_glfw.wgl.instance)
_glfwPlatformFreeModule(_glfw.wgl.instance);
_glfwPlatformFreeModule(_glfw.wgl.instance);
_glfw.wgl.instance = NULL;
}
#define SET_ATTRIB(a, v) \
@ -536,8 +532,6 @@ void _glfwTerminateWGL(void)
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
//
GLFWbool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)

View file

@ -166,29 +166,6 @@ static GLFWbool loadLibraries(void)
return GLFW_TRUE;
}
// Unload used libraries (DLLs)
//
static void freeLibraries(void)
{
if (_glfw.win32.xinput.instance)
_glfwPlatformFreeModule(_glfw.win32.xinput.instance);
if (_glfw.win32.dinput8.instance)
_glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
if (_glfw.win32.user32.instance)
_glfwPlatformFreeModule(_glfw.win32.user32.instance);
if (_glfw.win32.dwmapi.instance)
_glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
if (_glfw.win32.shcore.instance)
_glfwPlatformFreeModule(_glfw.win32.shcore.instance);
if (_glfw.win32.ntdll.instance)
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
}
// Create key code translation tables
//
static void createKeyTables(void)
@ -721,7 +698,14 @@ void _glfwTerminateWin32(void)
_glfwTerminateEGL();
_glfwTerminateOSMesa();
freeLibraries();
_glfwPlatformFreeModule(_glfw.win32.xinput.instance);
_glfwPlatformFreeModule(_glfw.win32.dinput8.instance);
_glfwPlatformFreeModule(_glfw.win32.user32.instance);
_glfwPlatformFreeModule(_glfw.win32.dwmapi.instance);
_glfwPlatformFreeModule(_glfw.win32.shcore.instance);
_glfwPlatformFreeModule(_glfw.win32.ntdll.instance);
memset(&_glfw.win32, 0, sizeof(_glfw.win32));
}
#endif // _GLFW_WIN32

View file

@ -39,7 +39,8 @@ void* _glfwPlatformLoadModule(const char* path)
void _glfwPlatformFreeModule(void* module)
{
FreeLibrary((HMODULE) module);
if (module)
FreeLibrary((HMODULE) module);
}
GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)

View file

@ -135,15 +135,8 @@ static void registryHandleGlobal(void* userData,
{
_glfw.wl.seat =
wl_registry_bind(registry, name, &wl_seat_interface,
_glfw_min(4, version));
_glfw_min(5, version));
_glfwAddSeatListenerWayland(_glfw.wl.seat);
if (wl_seat_get_version(_glfw.wl.seat) >=
WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
{
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
}
}
}
else if (strcmp(interface, "wl_data_device_manager") == 0)
@ -834,6 +827,16 @@ int _glfwInitWayland(void)
createKeyTables();
_glfw.wl.keyRepeatTimerfd =
timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
if (_glfw.wl.keyRepeatTimerfd == -1)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to create timerfd: %s",
strerror(errno));
return GLFW_FALSE;
}
_glfw.wl.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!_glfw.wl.xkb.context)
{
@ -981,37 +984,16 @@ void _glfwTerminateWayland(void)
// Free modules only after all Wayland termination functions are called
if (_glfw.egl.handle)
{
_glfwPlatformFreeModule(_glfw.egl.handle);
_glfw.egl.handle = NULL;
}
if (_glfw.wl.libdecor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfw.wl.libdecor.handle = NULL;
}
if (_glfw.wl.egl.handle)
{
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfw.wl.egl.handle = NULL;
}
if (_glfw.wl.xkb.handle)
{
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfw.wl.xkb.handle = NULL;
}
if (_glfw.wl.cursor.handle)
{
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfw.wl.cursor.handle = NULL;
}
_glfwPlatformFreeModule(_glfw.egl.handle);
_glfwPlatformFreeModule(_glfw.wl.libdecor.handle);
_glfwPlatformFreeModule(_glfw.wl.egl.handle);
_glfwPlatformFreeModule(_glfw.wl.xkb.handle);
_glfwPlatformFreeModule(_glfw.wl.cursor.handle);
_glfwPlatformFreeModule(_glfw.wl.client.handle);
_glfw_free(_glfw.wl.clipboardString);
memset(&_glfw.wl, 0, sizeof(_glfw.wl));
}
#endif // _GLFW_WAYLAND

View file

@ -414,7 +414,8 @@ typedef struct _GLFWwindowWayland
GLFWbool decorations;
struct wl_buffer* buffer;
_GLFWfallbackEdgeWayland top, left, right, bottom;
wl_fixed_t pointerX, pointerY;
double pointerX, pointerY;
uint32_t buttonPressSerial;
const char* cursorName;
} fallback;
} _GLFWwindowWayland;
@ -472,6 +473,17 @@ typedef struct _GLFWlibraryWayland
short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5];
struct {
struct wl_surface* pointerSurface;
unsigned int events;
double pointerX;
double pointerY;
double scrollX;
double scrollY;
int button;
int action;
} pending;
struct {
void* handle;
struct xkb_context* context;

View file

@ -55,6 +55,11 @@
#define GLFW_BORDER_SIZE 4
#define GLFW_CAPTION_HEIGHT 24
#define GLFW_PENDING_SURFACE 1
#define GLFW_PENDING_BUTTON 2
#define GLFW_PENDING_MOTION 4
#define GLFW_PENDING_SCROLL 8
static int createTmpfileCloexec(char* tmpname)
{
int fd;
@ -278,15 +283,11 @@ static void destroyFallbackDecorations(_GLFWwindow* window)
destroyFallbackEdge(&window->wl.fallback.bottom);
}
static void updateFallbackDecorationCursor(_GLFWwindow* window,
wl_fixed_t sx,
wl_fixed_t sy)
static void updateFallbackDecorationCursor(_GLFWwindow* window, double xpos, double ypos)
{
window->wl.fallback.pointerX = sx;
window->wl.fallback.pointerY = sy;
window->wl.fallback.pointerX = xpos;
window->wl.fallback.pointerY = ypos;
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
const char* cursorName = "left_ptr";
if (window->resizable)
@ -361,18 +362,16 @@ static void updateFallbackDecorationCursor(_GLFWwindow* window,
}
}
static void handleFallbackDecorationButton(_GLFWwindow* window,
uint32_t serial,
uint32_t button,
uint32_t state)
static void handleFallbackDecorationButton(_GLFWwindow* window, int button, int action)
{
if (state != WL_POINTER_BUTTON_STATE_PRESSED)
if (action != GLFW_PRESS)
return;
const double xpos = wl_fixed_to_double(window->wl.fallback.pointerX);
const double ypos = wl_fixed_to_double(window->wl.fallback.pointerY);
const double xpos = window->wl.fallback.pointerX;
const double ypos = window->wl.fallback.pointerY;
const uint32_t serial = window->wl.fallback.buttonPressSerial;
if (button == BTN_LEFT)
if (button == GLFW_MOUSE_BUTTON_LEFT)
{
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
@ -410,7 +409,7 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges);
}
else if (button == BTN_RIGHT)
else if (button == GLFW_MOUSE_BUTTON_RIGHT)
{
if (!window->wl.xdg.toplevel)
return;
@ -421,10 +420,8 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
if (ypos < GLFW_BORDER_SIZE)
return;
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
xpos,
ypos - GLFW_CAPTION_HEIGHT - GLFW_BORDER_SIZE);
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel, _glfw.wl.seat, serial,
xpos, ypos - GLFW_CAPTION_HEIGHT - GLFW_BORDER_SIZE);
}
}
@ -1522,6 +1519,70 @@ static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mime
return string;
}
static void processPointerEnterSurface(struct wl_surface* surface)
{
_glfw.wl.pointerSurface = surface;
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
{
_glfwSetCursorWayland(window, window->cursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
}
}
static void processPointerLeaveSurface(struct wl_surface* surface)
{
_glfw.wl.pointerSurface = NULL;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
_glfwInputCursorEnter(window, GLFW_FALSE);
else
{
if (window->wl.fallback.decorations)
window->wl.fallback.cursorName = NULL;
}
}
static void processPointerMotion(double xpos, double ypos)
{
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
{
if (window->cursorMode != GLFW_CURSOR_DISABLED)
{
window->wl.cursorPosX = xpos;
window->wl.cursorPosY = ypos;
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
}
}
else
{
if (window->wl.fallback.decorations)
updateFallbackDecorationCursor(window, xpos, ypos);
}
}
static void processPointerButton(int button, int action)
{
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
_glfwInputMouseClick(window, button, action, _glfw.wl.xkb.modifiers);
else
{
if (window->wl.fallback.decorations)
handleFallbackDecorationButton(window, button, action);
}
}
static void processPointerScroll(double xoffset, double yoffset)
{
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
_glfwInputScroll(window, xoffset, yoffset);
}
static void pointerHandleEnter(void* userData,
struct wl_pointer* pointer,
uint32_t serial,
@ -1538,25 +1599,21 @@ static void pointerHandleEnter(void* userData,
_glfw.wl.serial = serial;
_glfw.wl.pointerEnterSerial = serial;
_glfw.wl.pointerSurface = surface;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
_glfwSetCursorWayland(window, window->cursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
if (window->cursorMode != GLFW_CURSOR_DISABLED)
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
}
_glfw.wl.pending.events |= (GLFW_PENDING_SURFACE | GLFW_PENDING_MOTION);
_glfw.wl.pending.pointerSurface = surface;
_glfw.wl.pending.pointerX = xpos;
_glfw.wl.pending.pointerY = ypos;
}
else
{
if (window->wl.fallback.decorations)
updateFallbackDecorationCursor(window, sx, sy);
processPointerEnterSurface(surface);
processPointerMotion(xpos, ypos);
}
}
@ -1572,16 +1629,14 @@ static void pointerHandleLeave(void* userData,
return;
_glfw.wl.serial = serial;
_glfw.wl.pointerSurface = NULL;
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (window->wl.surface == surface)
_glfwInputCursorEnter(window, GLFW_FALSE);
else
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
if (window->wl.fallback.decorations)
window->wl.fallback.cursorName = NULL;
_glfw.wl.pending.events |= GLFW_PENDING_SURFACE;
_glfw.wl.pending.pointerSurface = NULL;
}
else
processPointerLeaveSurface(surface);
}
static void pointerHandleMotion(void* userData,
@ -1593,50 +1648,49 @@ static void pointerHandleMotion(void* userData,
if (!_glfw.wl.pointerSurface)
return;
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
if (window->cursorMode == GLFW_CURSOR_DISABLED)
return;
if (window->wl.surface == _glfw.wl.pointerSurface)
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
_glfw.wl.pending.events |= GLFW_PENDING_MOTION;
_glfw.wl.pending.pointerX = xpos;
_glfw.wl.pending.pointerY = ypos;
}
else
{
if (window->wl.fallback.decorations)
updateFallbackDecorationCursor(window, sx, sy);
}
processPointerMotion(xpos, ypos);
}
static void pointerHandleButton(void* userData,
struct wl_pointer* pointer,
uint32_t serial,
uint32_t time,
uint32_t button,
uint32_t buttonID,
uint32_t state)
{
if (!_glfw.wl.pointerSurface)
return;
_glfw.wl.serial = serial;
const int button = buttonID - BTN_LEFT;
const int action = (state == WL_POINTER_BUTTON_STATE_PRESSED);
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
if (window->wl.fallback.decorations)
{
_glfw.wl.serial = serial;
if (action == GLFW_PRESS)
window->wl.fallback.buttonPressSerial = serial;
}
_glfwInputMouseClick(window,
button - BTN_LEFT,
state == WL_POINTER_BUTTON_STATE_PRESSED,
_glfw.wl.xkb.modifiers);
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
_glfw.wl.pending.events |= GLFW_PENDING_BUTTON;
_glfw.wl.pending.button = button;
_glfw.wl.pending.action = action;
}
else
{
if (window->wl.fallback.decorations)
handleFallbackDecorationButton(window, serial, button, state);
}
processPointerButton(button, action);
}
static void pointerHandleAxis(void* userData,
@ -1648,18 +1702,70 @@ static void pointerHandleAxis(void* userData,
if (!_glfw.wl.pointerSurface)
return;
_GLFWwindow* window = wl_surface_get_user_data(_glfw.wl.pointerSurface);
if (window->wl.surface == _glfw.wl.pointerSurface)
if (wl_pointer_get_version(pointer) >= WL_POINTER_FRAME_SINCE_VERSION)
{
_glfw.wl.pending.events |= GLFW_PENDING_SCROLL;
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfw.wl.pending.scrollX = -wl_fixed_to_double(value) / 10.0;
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfw.wl.pending.scrollY = -wl_fixed_to_double(value) / 10.0;
}
else
{
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
_glfwInputScroll(window, -wl_fixed_to_double(value) / 10.0, 0.0);
processPointerScroll(-wl_fixed_to_double(value) / 10.0, 0.0);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
processPointerScroll(0.0, -wl_fixed_to_double(value) / 10.0);
}
}
static void pointerHandleFrame(void* userData, struct wl_pointer* pointer)
{
if (_glfw.wl.pending.events & GLFW_PENDING_SURFACE)
{
if (_glfw.wl.pointerSurface)
processPointerLeaveSurface(_glfw.wl.pointerSurface);
if (_glfw.wl.pending.pointerSurface)
processPointerEnterSurface(_glfw.wl.pending.pointerSurface);
}
if (!_glfw.wl.pointerSurface)
return;
if (_glfw.wl.pending.events & GLFW_PENDING_MOTION)
processPointerMotion(_glfw.wl.pending.pointerX, _glfw.wl.pending.pointerY);
if (_glfw.wl.pending.events & GLFW_PENDING_BUTTON)
processPointerButton(_glfw.wl.pending.button, _glfw.wl.pending.action);
if (_glfw.wl.pending.events & GLFW_PENDING_SCROLL)
processPointerScroll(_glfw.wl.pending.scrollX, _glfw.wl.pending.scrollY);
memset(&_glfw.wl.pending, 0, sizeof(_glfw.wl.pending));
}
static void pointerHandleAxisSource(void* userData,
struct wl_pointer* pointer,
uint32_t axisSource)
{
}
static void pointerHandleAxisStop(void* userData,
struct wl_pointer* pointer,
uint32_t time,
uint32_t axis)
{
}
static void pointerHandleAxisDiscrete(void* userData,
struct wl_pointer* pointer,
uint32_t axis,
int32_t discrete)
{
}
static const struct wl_pointer_listener pointerListener =
{
pointerHandleEnter,
@ -1667,6 +1773,10 @@ static const struct wl_pointer_listener pointerListener =
pointerHandleMotion,
pointerHandleButton,
pointerHandleAxis,
pointerHandleFrame,
pointerHandleAxisSource,
pointerHandleAxisStop,
pointerHandleAxisDiscrete
};
static void keyboardHandleKeymap(void* userData,
@ -1942,6 +2052,13 @@ static void seatHandleCapabilities(void* userData,
{
_glfw.wl.keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(_glfw.wl.keyboard, &keyboardListener, NULL);
if (wl_keyboard_get_version(_glfw.wl.keyboard) <
WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
{
_glfw.wl.keyRepeatRate = 4;
_glfw.wl.keyRepeatDelay = 500;
}
}
else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && _glfw.wl.keyboard)
{

View file

@ -1592,65 +1592,29 @@ void _glfwTerminateX11(void)
_glfw.x11.display = NULL;
}
if (_glfw.x11.x11xcb.handle)
{
_glfwPlatformFreeModule(_glfw.x11.x11xcb.handle);
_glfw.x11.x11xcb.handle = NULL;
}
if (_glfw.x11.xcursor.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xcursor.handle);
_glfw.x11.xcursor.handle = NULL;
}
if (_glfw.x11.randr.handle)
{
_glfwPlatformFreeModule(_glfw.x11.randr.handle);
_glfw.x11.randr.handle = NULL;
}
if (_glfw.x11.xinerama.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xinerama.handle);
_glfw.x11.xinerama.handle = NULL;
}
if (_glfw.x11.xrender.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xrender.handle);
_glfw.x11.xrender.handle = NULL;
}
if (_glfw.x11.vidmode.handle)
{
_glfwPlatformFreeModule(_glfw.x11.vidmode.handle);
_glfw.x11.vidmode.handle = NULL;
}
if (_glfw.x11.xi.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xi.handle);
_glfw.x11.xi.handle = NULL;
}
_glfwTerminateOSMesa();
// NOTE: These need to be unloaded after XCloseDisplay, as they register
// cleanup callbacks that get called by that function
_glfwTerminateEGL();
_glfwTerminateGLX();
if (_glfw.x11.xlib.handle)
{
_glfwPlatformFreeModule(_glfw.x11.xlib.handle);
_glfw.x11.xlib.handle = NULL;
}
_glfwPlatformFreeModule(_glfw.x11.x11xcb.handle);
_glfwPlatformFreeModule(_glfw.x11.xcursor.handle);
_glfwPlatformFreeModule(_glfw.x11.randr.handle);
_glfwPlatformFreeModule(_glfw.x11.xinerama.handle);
_glfwPlatformFreeModule(_glfw.x11.xrender.handle);
_glfwPlatformFreeModule(_glfw.x11.xshape.handle);
_glfwPlatformFreeModule(_glfw.x11.vidmode.handle);
_glfwPlatformFreeModule(_glfw.x11.xi.handle);
_glfwPlatformFreeModule(_glfw.x11.xlib.handle);
if (_glfw.x11.emptyEventPipe[0] || _glfw.x11.emptyEventPipe[1])
{
close(_glfw.x11.emptyEventPipe[0]);
close(_glfw.x11.emptyEventPipe[1]);
}
memset(&_glfw.x11, 0, sizeof(_glfw.x11));
}
#endif // _GLFW_X11