mirror of
https://github.com/glfw/glfw
synced 2026-09-26 16:18:21 +03:00
Merge branch 'glfw:master' into master
This commit is contained in:
commit
52beeee6fd
17 changed files with 281 additions and 242 deletions
|
|
@ -79,6 +79,7 @@ video tutorials.
|
|||
- Jason Francis
|
||||
- Gerald Franz
|
||||
- Mário Freitas
|
||||
- Friz64
|
||||
- GeO4d
|
||||
- Marcus Geelnard
|
||||
- Gegy
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -688,6 +688,8 @@ void _glfwTerminateCocoa(void)
|
|||
_glfwTerminateEGL();
|
||||
_glfwTerminateOSMesa();
|
||||
|
||||
memset(&_glfw.ns, 0, sizeof(_glfw.ns));
|
||||
|
||||
} // autoreleasepool
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -260,5 +260,6 @@ void _glfwTerminateNull(void)
|
|||
free(_glfw.null.clipboardString);
|
||||
_glfwTerminateOSMesa();
|
||||
_glfwTerminateEGL();
|
||||
memset(&_glfw.null, 0, sizeof(_glfw.null));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
257
src/wl_window.c
257
src/wl_window.c
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue