Compare commits

...

17 Commits

Author SHA1 Message Date
Marco Lizza
18370523f4
Merge cdcd9c194a into 0d2d85d19c 2025-08-18 12:02:13 +00:00
Doug Binks
0d2d85d19c Revert "Wayland: Keyboard leave event handler now processes key repeats" 2025-08-15 11:27:59 +02:00
Jan Hendrik Farr
768e81a0eb Wayland: Fix key repeat halting
Key repeat shoud only be halted when the repeating key
is released, not when another key is released.
2025-08-14 15:35:04 +02:00
Camilla Löwy
161fb1b6f6 Wayland: Fix fallback decoration scroll events
The fallback decorations would emit scroll events as if scrolling had
occurred over the content area of the window.
2025-08-12 17:11:27 +02:00
Camilla Löwy
645a35a38e Wayland: Cleanup 2025-08-12 17:11:27 +02:00
Camilla Löwy
7523b0e6bd Wayland: Move fallback decoration pointer logic
Decluttered the wl_pointer handlers by moving the bulk of fallback
decoration related logic to separate functions.
2025-08-12 17:11:26 +02:00
Camilla Löwy
5190a30d8a Wayland: Move fallback decoration struct member
The cursorPreviousName member was only used for the fallback decorations
but was not grouped with other related members.
2025-08-12 17:11:26 +02:00
Camilla Löwy
ddbb8e0f2c Wayland: Fix fallback decoration cursor position
If fallback decorations were in use, pointer motion over a decoration
surface would cause glfwGetCursorPos to provide incorrect cursor
positions.

The cursor position is now only updated when the pointer is over the
content area of the window, similar to libdecor and XDG decorations.
2025-08-12 17:11:24 +02:00
Camilla Löwy
5245180c56 Formatting 2025-08-12 17:10:43 +02:00
Doug Binks
7b51a8eb31 Wayland: Keyboard leave event handler now processes key repeats
- Fixes #2736
2025-08-10 18:27:44 +02:00
Camilla Löwy
ac10768495 Wayland: Fix memory leaks in data offer reading
The buffer storing the contents of the data offer being read could leak
if buffer reallocation or reading from the pipe failed.
2025-07-18 12:31:07 +02:00
Doug Binks
feb2a6b728 Wayland: Reset key repeat timer on window destruction
Windows with keyboard focus may have an active key repeat timer.
This should be reset when the window is closed, or key repeat events
could be sent to a NULL window were it not for the quickfix in PR #2732.

Fixes #2741
Probably the source of #2727
2025-07-17 17:24:19 +02:00
Marco Lizza
cdcd9c194a Fixing dlsym cast warning. 2024-02-29 01:57:41 +01:00
Marco Lizza
596cabbe58 Tweaking GLFW_ANY_POSITION to int32_t max value to avoid signed/unsigned warnings. 2024-02-29 01:51:48 +01:00
Marco Lizza
a02b287b1d Fixing signed/unsigned mismatch warnings. 2024-02-29 01:50:49 +01:00
Marco Lizza
7c2e8c7c5a Using designated initializers to avoid warnings. 2024-02-29 01:50:21 +01:00
Marco Lizza
58f2aab759 Fixing constant pointers. 2024-02-29 01:49:48 +01:00
20 changed files with 274 additions and 232 deletions

View File

@ -68,6 +68,7 @@ video tutorials.
- Jan Ekström
- Siavash Eliasi
- er-azh
- Jan Hendrik Farr
- Ahmad Fatoum
- Nikita Fediuchin
- Felipe Ferreira

View File

@ -132,6 +132,13 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: `glfwInit` would segfault on compositor with no seat (#2517)
- [Wayland] Bugfix: A drag entering a non-GLFW surface could cause a segfault
- [Wayland] Bugfix: Ignore key repeat events when no window has keyboard focus (#2727)
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
- [Wayland] Bugfix: Keyboard leave event handler now processes key repeats (#2736)
- [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over
fallback decorations
- [Wayland] Bugfix: Fallback decorations would report scroll events
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [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

@ -1180,7 +1180,7 @@ extern "C" {
#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001
#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002
#define GLFW_ANY_POSITION 0x80000000
#define GLFW_ANY_POSITION 0x7FFFFFFF
/*! @defgroup shapes Standard cursor shapes
* @brief Standard system cursor shapes.

View File

@ -272,7 +272,7 @@ EGLenum _glfwGetEGLPlatformCocoa(EGLint** attribs);
EGLNativeDisplayType _glfwGetEGLNativeDisplayCocoa(void);
EGLNativeWindowType _glfwGetEGLNativeWindowCocoa(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions);
void _glfwGetRequiredInstanceExtensionsCocoa(const char** extensions);
GLFWbool _glfwGetPhysicalDevicePresentationSupportCocoa(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceCocoa(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);

View File

@ -1922,7 +1922,7 @@ EGLNativeWindowType _glfwGetEGLNativeWindowCocoa(_GLFWwindow* window)
return window->ns.layer;
}
void _glfwGetRequiredInstanceExtensionsCocoa(char** extensions)
void _glfwGetRequiredInstanceExtensionsCocoa(const char** extensions)
{
if (_glfw.vk.KHR_surface && _glfw.vk.EXT_metal_surface)
{

View File

@ -1289,7 +1289,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
const size_t length = strcspn(c, "\r\n");
if (length < sizeof(line))
{
_GLFWmapping mapping = {{0}};
_GLFWmapping mapping = { .name = {0} };
memcpy(line, c, length);
line[length] = '\0';

View File

@ -756,7 +756,7 @@ struct _GLFWplatform
EGLNativeDisplayType (*getEGLNativeDisplay)(void);
EGLNativeWindowType (*getEGLNativeWindow)(_GLFWwindow*);
// vulkan
void (*getRequiredInstanceExtensions)(char**);
void (*getRequiredInstanceExtensions)(const char**);
GLFWbool (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t);
VkResult (*createWindowSurface)(VkInstance,_GLFWwindow*,const VkAllocationCallbacks*,VkSurfaceKHR*);
};
@ -863,7 +863,7 @@ struct _GLFWlibrary
struct {
GLFWbool available;
void* handle;
char* extensions[2];
const char* extensions[2];
PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
GLFWbool KHR_surface;
GLFWbool KHR_win32_surface;

View File

@ -274,7 +274,7 @@ EGLenum _glfwGetEGLPlatformNull(EGLint** attribs);
EGLNativeDisplayType _glfwGetEGLNativeDisplayNull(void);
EGLNativeWindowType _glfwGetEGLNativeWindowNull(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsNull(char** extensions);
void _glfwGetRequiredInstanceExtensionsNull(const char** extensions);
GLFWbool _glfwGetPhysicalDevicePresentationSupportNull(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceNull(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);

View File

@ -701,7 +701,7 @@ int _glfwGetKeyScancodeNull(int key)
return _glfw.null.scancodes[key];
}
void _glfwGetRequiredInstanceExtensionsNull(char** extensions)
void _glfwGetRequiredInstanceExtensionsNull(const char** extensions)
{
if (!_glfw.vk.KHR_surface || !_glfw.vk.EXT_headless_surface)
return;

View File

@ -44,10 +44,17 @@ void _glfwPlatformFreeModule(void* module)
dlclose(module);
}
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
{
return dlsym(module, name);
return (GLFWproc)dlsym(module, name);
}
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
#endif // GLFW_BUILD_POSIX_MODULE

View File

@ -150,7 +150,7 @@ GLFWbool _glfwInitVulkan(int mode)
_glfw.vk.available = GLFW_TRUE;
_glfw.platform.getRequiredInstanceExtensions(_glfw.vk.extensions);
_glfw.platform.getRequiredInstanceExtensions((const char **)_glfw.vk.extensions);
return GLFW_TRUE;
}

View File

@ -540,7 +540,7 @@ EGLenum _glfwGetEGLPlatformWin32(EGLint** attribs);
EGLNativeDisplayType _glfwGetEGLNativeDisplayWin32(void);
EGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsWin32(char** extensions);
void _glfwGetRequiredInstanceExtensionsWin32(const char** extensions);
GLFWbool _glfwGetPhysicalDevicePresentationSupportWin32(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceWin32(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);

View File

@ -2501,7 +2501,7 @@ EGLNativeWindowType _glfwGetEGLNativeWindowWin32(_GLFWwindow* window)
return window->win32.handle;
}
void _glfwGetRequiredInstanceExtensionsWin32(char** extensions)
void _glfwGetRequiredInstanceExtensionsWin32(const char** extensions)
{
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_win32_surface)
return;

View File

@ -243,7 +243,7 @@ void libdecorHandleError(struct libdecor* context,
static const struct libdecor_interface libdecorInterface =
{
libdecorHandleError
.error = libdecorHandleError
};
static void libdecorReadyCallback(void* userData,

View File

@ -217,62 +217,62 @@ struct libdecor_configuration;
enum libdecor_error
{
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
};
enum libdecor_window_state
{
LIBDECOR_WINDOW_STATE_NONE = 0,
LIBDECOR_WINDOW_STATE_ACTIVE = 1,
LIBDECOR_WINDOW_STATE_MAXIMIZED = 2,
LIBDECOR_WINDOW_STATE_FULLSCREEN = 4,
LIBDECOR_WINDOW_STATE_TILED_LEFT = 8,
LIBDECOR_WINDOW_STATE_TILED_RIGHT = 16,
LIBDECOR_WINDOW_STATE_TILED_TOP = 32,
LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 64
LIBDECOR_WINDOW_STATE_NONE = 0,
LIBDECOR_WINDOW_STATE_ACTIVE = 1,
LIBDECOR_WINDOW_STATE_MAXIMIZED = 2,
LIBDECOR_WINDOW_STATE_FULLSCREEN = 4,
LIBDECOR_WINDOW_STATE_TILED_LEFT = 8,
LIBDECOR_WINDOW_STATE_TILED_RIGHT = 16,
LIBDECOR_WINDOW_STATE_TILED_TOP = 32,
LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 64
};
enum libdecor_capabilities
{
LIBDECOR_ACTION_MOVE = 1,
LIBDECOR_ACTION_RESIZE = 2,
LIBDECOR_ACTION_MINIMIZE = 4,
LIBDECOR_ACTION_FULLSCREEN = 8,
LIBDECOR_ACTION_CLOSE = 16
LIBDECOR_ACTION_MOVE = 1,
LIBDECOR_ACTION_RESIZE = 2,
LIBDECOR_ACTION_MINIMIZE = 4,
LIBDECOR_ACTION_FULLSCREEN = 8,
LIBDECOR_ACTION_CLOSE = 16
};
struct libdecor_interface
{
void (* error)(struct libdecor*,enum libdecor_error,const char*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
void (* error)(struct libdecor*,enum libdecor_error,const char*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
};
struct libdecor_frame_interface
{
void (* configure)(struct libdecor_frame*,struct libdecor_configuration*,void*);
void (* close)(struct libdecor_frame*,void*);
void (* commit)(struct libdecor_frame*,void*);
void (* dismiss_popup)(struct libdecor_frame*,const char*,void*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
void (* configure)(struct libdecor_frame*,struct libdecor_configuration*,void*);
void (* close)(struct libdecor_frame*,void*);
void (* commit)(struct libdecor_frame*,void*);
void (* dismiss_popup)(struct libdecor_frame*,const char*,void*);
void (* reserved0)(void);
void (* reserved1)(void);
void (* reserved2)(void);
void (* reserved3)(void);
void (* reserved4)(void);
void (* reserved5)(void);
void (* reserved6)(void);
void (* reserved7)(void);
void (* reserved8)(void);
void (* reserved9)(void);
};
typedef struct libdecor* (* PFN_libdecor_new)(struct wl_display*,const struct libdecor_interface*);
@ -413,6 +413,8 @@ typedef struct _GLFWwindowWayland
struct wl_buffer* buffer;
_GLFWfallbackEdgeWayland top, left, right, bottom;
struct wl_surface* focus;
wl_fixed_t pointerX, pointerY;
const char* cursorName;
} fallback;
} _GLFWwindowWayland;
@ -454,7 +456,6 @@ typedef struct _GLFWlibraryWayland
struct wl_cursor_theme* cursorTheme;
struct wl_cursor_theme* cursorThemeHiDPI;
struct wl_surface* cursorSurface;
const char* cursorPreviousName;
int cursorTimerfd;
uint32_t serial;
uint32_t pointerEnterSerial;
@ -673,7 +674,7 @@ EGLenum _glfwGetEGLPlatformWayland(EGLint** attribs);
EGLNativeDisplayType _glfwGetEGLNativeDisplayWayland(void);
EGLNativeWindowType _glfwGetEGLNativeWindowWayland(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsWayland(char** extensions);
void _glfwGetRequiredInstanceExtensionsWayland(const char** extensions);
GLFWbool _glfwGetPhysicalDevicePresentationSupportWayland(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceWayland(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);

View File

@ -275,6 +275,146 @@ static void destroyFallbackDecorations(_GLFWwindow* window)
destroyFallbackEdge(&window->wl.fallback.bottom);
}
static void updateFallbackDecorationCursor(_GLFWwindow* window,
wl_fixed_t sx,
wl_fixed_t sy)
{
window->wl.fallback.pointerX = sx;
window->wl.fallback.pointerY = sy;
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
const char* cursorName = "left_ptr";
if (window->resizable)
{
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "n-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "nw-resize";
else
cursorName = "w-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "ne-resize";
else
cursorName = "e-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
{
if (xpos < GLFW_BORDER_SIZE)
cursorName = "sw-resize";
else if (xpos > window->wl.width + GLFW_BORDER_SIZE)
cursorName = "se-resize";
else
cursorName = "s-resize";
}
}
if (window->wl.fallback.cursorName != cursorName)
{
struct wl_surface* surface = _glfw.wl.cursorSurface;
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
int scale = 1;
if (window->wl.bufferScale > 1 && _glfw.wl.cursorThemeHiDPI)
{
// We only support up to scale=2 for now, since libwayland-cursor
// requires us to load a different theme for each size.
scale = 2;
theme = _glfw.wl.cursorThemeHiDPI;
}
struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName);
if (!cursor)
return;
// TODO: handle animated cursors too.
struct wl_cursor_image* image = cursor->images[0];
if (!image)
return;
struct wl_buffer* buffer = wl_cursor_image_get_buffer(image);
if (!buffer)
return;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
surface,
image->hotspot_x / scale,
image->hotspot_y / scale);
wl_surface_set_buffer_scale(surface, scale);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_damage(surface, 0, 0, image->width, image->height);
wl_surface_commit(surface);
window->wl.fallback.cursorName = cursorName;
}
}
static void handleFallbackDecorationButton(_GLFWwindow* window,
uint32_t serial,
uint32_t button)
{
const double xpos = wl_fixed_to_double(window->wl.fallback.pointerX);
const double ypos = wl_fixed_to_double(window->wl.fallback.pointerY);
if (button == BTN_LEFT)
{
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
{
if (ypos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
{
if (xpos < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
else if (xpos > window->wl.width + GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
}
if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat, serial, edges);
}
else if (button == BTN_RIGHT)
{
if (window->wl.xdg.toplevel)
{
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
window->wl.cursorPosX,
window->wl.cursorPosY);
}
}
}
static void xdgDecorationHandleConfigure(void* userData,
struct zxdg_toplevel_decoration_v1* decoration,
uint32_t mode)
@ -474,8 +614,8 @@ static void surfaceHandleLeave(void* userData,
static const struct wl_surface_listener surfaceListener =
{
surfaceHandleEnter,
surfaceHandleLeave
.enter = surfaceHandleEnter,
.leave = surfaceHandleLeave
};
static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
@ -616,8 +756,8 @@ static void xdgToplevelHandleClose(void* userData,
static const struct xdg_toplevel_listener xdgToplevelListener =
{
xdgToplevelHandleConfigure,
xdgToplevelHandleClose
.configure = xdgToplevelHandleConfigure,
.close = xdgToplevelHandleClose
};
static void xdgSurfaceHandleConfigure(void* userData,
@ -791,10 +931,10 @@ void libdecorFrameHandleDismissPopup(struct libdecor_frame* frame,
static const struct libdecor_frame_interface libdecorFrameInterface =
{
libdecorFrameHandleConfigure,
libdecorFrameHandleClose,
libdecorFrameHandleCommit,
libdecorFrameHandleDismissPopup
.configure = libdecorFrameHandleConfigure,
.close = libdecorFrameHandleClose,
.commit = libdecorFrameHandleCommit,
.dismiss_popup = libdecorFrameHandleDismissPopup
};
static GLFWbool createLibdecorFrame(_GLFWwindow* window)
@ -1144,7 +1284,7 @@ static GLFWbool flushDisplay(void)
if (errno != EAGAIN)
return GLFW_FALSE;
struct pollfd fd = { wl_display_get_fd(_glfw.wl.display), POLLOUT };
struct pollfd fd = { .fd = wl_display_get_fd(_glfw.wl.display), POLLOUT };
while (poll(&fd, 1, -1) == -1)
{
@ -1333,6 +1473,7 @@ static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mime
if (!longer)
{
_glfwInputError(GLFW_OUT_OF_MEMORY, NULL);
_glfw_free(string);
close(fds[0]);
return NULL;
}
@ -1352,6 +1493,7 @@ static char* readDataOfferAsString(struct wl_data_offer* offer, const char* mime
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to read from data offer pipe: %s",
strerror(errno));
_glfw_free(string);
close(fds[0]);
return NULL;
}
@ -1415,7 +1557,6 @@ static void pointerHandleLeave(void* userData,
_glfw.wl.serial = serial;
_glfw.wl.pointerFocus = NULL;
_glfw.wl.cursorPreviousName = NULL;
if (window->wl.hovered)
{
@ -1425,7 +1566,10 @@ static void pointerHandleLeave(void* userData,
else
{
if (window->wl.fallback.decorations)
{
window->wl.fallback.focus = NULL;
window->wl.fallback.cursorName = NULL;
}
}
}
@ -1442,92 +1586,16 @@ static void pointerHandleMotion(void* userData,
if (window->cursorMode == GLFW_CURSOR_DISABLED)
return;
const double xpos = wl_fixed_to_double(sx);
const double ypos = wl_fixed_to_double(sy);
window->wl.cursorPosX = xpos;
window->wl.cursorPosY = ypos;
if (window->wl.hovered)
{
_glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorPos(window, xpos, ypos);
return;
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
}
if (window->wl.fallback.decorations)
else
{
const char* cursorName = "left_ptr";
if (window->resizable)
{
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "n-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "nw-resize";
else
cursorName = "w-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
{
if (ypos < GLFW_BORDER_SIZE)
cursorName = "ne-resize";
else
cursorName = "e-resize";
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
{
if (xpos < GLFW_BORDER_SIZE)
cursorName = "sw-resize";
else if (xpos > window->wl.width + GLFW_BORDER_SIZE)
cursorName = "se-resize";
else
cursorName = "s-resize";
}
}
if (_glfw.wl.cursorPreviousName != cursorName)
{
struct wl_surface* surface = _glfw.wl.cursorSurface;
struct wl_cursor_theme* theme = _glfw.wl.cursorTheme;
int scale = 1;
if (window->wl.bufferScale > 1 && _glfw.wl.cursorThemeHiDPI)
{
// We only support up to scale=2 for now, since libwayland-cursor
// requires us to load a different theme for each size.
scale = 2;
theme = _glfw.wl.cursorThemeHiDPI;
}
struct wl_cursor* cursor = wl_cursor_theme_get_cursor(theme, cursorName);
if (!cursor)
return;
// TODO: handle animated cursors too.
struct wl_cursor_image* image = cursor->images[0];
if (!image)
return;
struct wl_buffer* buffer = wl_cursor_image_get_buffer(image);
if (!buffer)
return;
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerEnterSerial,
surface,
image->hotspot_x / scale,
image->hotspot_y / scale);
wl_surface_set_buffer_scale(surface, scale);
wl_surface_attach(surface, buffer, 0, 0);
wl_surface_damage(surface, 0, 0, image->width, image->height);
wl_surface_commit(surface);
_glfw.wl.cursorPreviousName = cursorName;
}
if (window->wl.fallback.decorations)
updateFallbackDecorationCursor(window, sx, sy);
}
}
@ -1550,62 +1618,11 @@ static void pointerHandleButton(void* userData,
button - BTN_LEFT,
state == WL_POINTER_BUTTON_STATE_PRESSED,
_glfw.wl.xkb.modifiers);
return;
}
if (window->wl.fallback.decorations)
else
{
if (button == BTN_LEFT)
{
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
if (window->wl.fallback.focus == window->wl.fallback.top.surface)
{
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
else
xdg_toplevel_move(window->wl.xdg.toplevel, _glfw.wl.seat, serial);
}
else if (window->wl.fallback.focus == window->wl.fallback.left.surface)
{
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
}
else if (window->wl.fallback.focus == window->wl.fallback.right.surface)
{
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
}
else if (window->wl.fallback.focus == window->wl.fallback.bottom.surface)
{
if (window->wl.cursorPosX < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
else if (window->wl.cursorPosX > window->wl.width + GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
else
edges = XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
}
if (edges != XDG_TOPLEVEL_RESIZE_EDGE_NONE)
{
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
serial, edges);
}
}
else if (button == BTN_RIGHT)
{
if (window->wl.xdg.toplevel)
{
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
window->wl.cursorPosX,
window->wl.cursorPosY);
}
}
if (window->wl.fallback.decorations)
handleFallbackDecorationButton(window, serial, button);
}
}
@ -1619,20 +1636,23 @@ static void pointerHandleAxis(void* userData,
if (!window)
return;
// 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);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
if (window->wl.hovered)
{
// 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);
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
}
}
static const struct wl_pointer_listener pointerListener =
{
pointerHandleEnter,
pointerHandleLeave,
pointerHandleMotion,
pointerHandleButton,
pointerHandleAxis,
.enter = pointerHandleEnter,
.leave = pointerHandleLeave,
.motion = pointerHandleMotion,
.button = pointerHandleButton,
.axis = pointerHandleAxis,
};
static void keyboardHandleKeymap(void* userData,
@ -1800,11 +1820,12 @@ static void keyboardHandleKey(void* userData,
timer.it_value.tv_sec = _glfw.wl.keyRepeatDelay / 1000;
timer.it_value.tv_nsec = (_glfw.wl.keyRepeatDelay % 1000) * 1000000;
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
}
} else if (scancode == _glfw.wl.keyRepeatScancode) {
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
}
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
_glfwInputKey(window, key, scancode, action, _glfw.wl.xkb.modifiers);
if (action == GLFW_PRESS)
@ -1940,7 +1961,7 @@ static void dataOfferHandleOffer(void* userData,
static const struct wl_data_offer_listener dataOfferListener =
{
dataOfferHandleOffer
.offer = dataOfferHandleOffer
};
static void dataDeviceHandleDataOffer(void* userData,
@ -1959,7 +1980,7 @@ static void dataDeviceHandleDataOffer(void* userData,
_glfw.wl.offers = offers;
_glfw.wl.offerCount++;
_glfw.wl.offers[_glfw.wl.offerCount - 1] = (_GLFWofferWayland) { offer };
_glfw.wl.offers[_glfw.wl.offerCount - 1] = (_GLFWofferWayland) { .offer = offer };
wl_data_offer_add_listener(offer, &dataOfferListener, NULL);
}
@ -2187,7 +2208,12 @@ void _glfwDestroyWindowWayland(_GLFWwindow* window)
_glfw.wl.pointerFocus = NULL;
if (window == _glfw.wl.keyboardFocus)
{
struct itimerspec timer = {0};
timerfd_settime(_glfw.wl.keyRepeatTimerfd, 0, &timer, NULL);
_glfw.wl.keyboardFocus = NULL;
}
if (window->wl.fractionalScale)
wp_fractional_scale_v1_destroy(window->wl.fractionalScale);
@ -3143,9 +3169,9 @@ static void dataSourceHandleCancelled(void* userData,
static const struct wl_data_source_listener dataSourceListener =
{
dataSourceHandleTarget,
dataSourceHandleSend,
dataSourceHandleCancelled,
.target = dataSourceHandleTarget,
.send = dataSourceHandleSend,
.cancelled = dataSourceHandleCancelled,
};
void _glfwSetClipboardStringWayland(const char* string)
@ -3219,7 +3245,7 @@ EGLNativeWindowType _glfwGetEGLNativeWindowWayland(_GLFWwindow* window)
return window->wl.egl.window;
}
void _glfwGetRequiredInstanceExtensionsWayland(char** extensions)
void _glfwGetRequiredInstanceExtensionsWayland(const char** extensions)
{
if (!_glfw.vk.KHR_surface || !_glfw.vk.KHR_wayland_surface)
return;

View File

@ -231,7 +231,7 @@ static void createKeyTables(void)
const struct
{
int key;
char* name;
const char* name;
} keymap[] =
{
{ GLFW_KEY_GRAVE_ACCENT, "TLDE" },
@ -366,7 +366,7 @@ static void createKeyTables(void)
// keyboard layout. Because function keys aren't mapped correctly
// when using traditional KeySym translations, they are mapped
// here instead.
for (int i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++)
for (size_t i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++)
{
if (strncmp(desc->names->keys[scancode].name,
keymap[i].name,
@ -390,7 +390,7 @@ static void createKeyTables(void)
continue;
}
for (int j = 0; j < sizeof(keymap) / sizeof(keymap[0]); j++)
for (size_t j = 0; j < sizeof(keymap) / sizeof(keymap[0]); j++)
{
if (strncmp(desc->names->key_aliases[i].alias,
keymap[j].name,

View File

@ -180,8 +180,8 @@ void _glfwPollMonitorsX11(void)
{
if (screens[j].x_org == ci->x &&
screens[j].y_org == ci->y &&
screens[j].width == ci->width &&
screens[j].height == ci->height)
screens[j].width == (int)ci->width &&
screens[j].height == (int)ci->height)
{
monitor->x11.index = j;
break;
@ -573,7 +573,7 @@ void _glfwSetGammaRampX11(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
{
if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size)
if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != (int)ramp->size)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Gamma ramp size must match current ramp size");

View File

@ -959,7 +959,7 @@ EGLenum _glfwGetEGLPlatformX11(EGLint** attribs);
EGLNativeDisplayType _glfwGetEGLNativeDisplayX11(void);
EGLNativeWindowType _glfwGetEGLNativeWindowX11(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsX11(char** extensions);
void _glfwGetRequiredInstanceExtensionsX11(const char** extensions);
GLFWbool _glfwGetPhysicalDevicePresentationSupportX11(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceX11(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);

View File

@ -62,7 +62,7 @@
//
static GLFWbool waitForX11Event(double* timeout)
{
struct pollfd fd = { ConnectionNumber(_glfw.x11.display), POLLIN };
struct pollfd fd = { .fd = ConnectionNumber(_glfw.x11.display), .events = POLLIN };
while (!XPending(_glfw.x11.display))
{
@ -97,7 +97,7 @@ static GLFWbool waitForAnyEvent(double* timeout)
if (!_glfwPollPOSIX(fds, sizeof(fds) / sizeof(fds[0]), timeout))
return GLFW_FALSE;
for (int i = 1; i < sizeof(fds) / sizeof(fds[0]); i++)
for (size_t i = 1; i < sizeof(fds) / sizeof(fds[0]); i++)
{
if (fds[i].revents & POLLIN)
return GLFW_TRUE;
@ -235,10 +235,10 @@ static int translateState(int state)
// Translates an X11 key code to a GLFW key token
//
static int translateKey(int scancode)
static int translateKey(unsigned int scancode)
{
// Use the pre-filled LUT (see createKeyTables() in x11_init.c)
if (scancode < 0 || scancode > 255)
if (scancode > 255)
return GLFW_KEY_UNKNOWN;
return _glfw.x11.keycodes[scancode];
@ -1145,7 +1145,7 @@ static void releaseMonitor(_GLFWwindow* window)
//
static void processEvent(XEvent *event)
{
int keycode = 0;
unsigned int keycode = 0;
Bool filtered = False;
// HACK: Save scancode as some IMs clear the field in XFilterEvent
@ -3133,7 +3133,7 @@ EGLNativeWindowType _glfwGetEGLNativeWindowX11(_GLFWwindow* window)
return (EGLNativeWindowType) window->x11.handle;
}
void _glfwGetRequiredInstanceExtensionsX11(char** extensions)
void _glfwGetRequiredInstanceExtensionsX11(const char** extensions)
{
if (!_glfw.vk.KHR_surface)
return;