mirror of
https://github.com/glfw/glfw.git
synced 2024-11-29 15:44:35 +00:00
Wayland: Add support for animated standard cursors
This commit is contained in:
parent
dede6d6886
commit
5ea6e6cda2
@ -137,6 +137,7 @@ static void setCursor(const char* name)
|
|||||||
"Wayland: Standard cursor not found");
|
"Wayland: Standard cursor not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// TODO: handle animated cursors too.
|
||||||
image = cursor->images[0];
|
image = cursor->images[0];
|
||||||
|
|
||||||
if (!image)
|
if (!image)
|
||||||
|
@ -333,10 +333,11 @@ typedef struct _GLFWmonitorWayland
|
|||||||
//
|
//
|
||||||
typedef struct _GLFWcursorWayland
|
typedef struct _GLFWcursorWayland
|
||||||
{
|
{
|
||||||
struct wl_cursor_image* image;
|
struct wl_cursor* cursor;
|
||||||
struct wl_buffer* buffer;
|
struct wl_buffer* buffer;
|
||||||
int width, height;
|
int width, height;
|
||||||
int xhot, yhot;
|
int xhot, yhot;
|
||||||
|
int currentImage;
|
||||||
} _GLFWcursorWayland;
|
} _GLFWcursorWayland;
|
||||||
|
|
||||||
|
|
||||||
|
103
src/wl_window.c
103
src/wl_window.c
@ -690,6 +690,60 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setCursorImage(_GLFWcursorWayland* cursorWayland)
|
||||||
|
{
|
||||||
|
struct itimerspec timer = {};
|
||||||
|
struct wl_cursor_image* image;
|
||||||
|
struct wl_buffer* buffer;
|
||||||
|
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
||||||
|
|
||||||
|
if (!cursorWayland->cursor)
|
||||||
|
buffer = cursorWayland->buffer;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
image = cursorWayland->cursor->images[cursorWayland->currentImage];
|
||||||
|
buffer = wl_cursor_image_get_buffer(image);
|
||||||
|
if (!buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
timer.it_value.tv_sec = image->delay / 1000;
|
||||||
|
timer.it_value.tv_nsec = (image->delay % 1000) * 1000000;
|
||||||
|
timerfd_settime(_glfw.wl.cursorTimerfd, 0, &timer, NULL);
|
||||||
|
|
||||||
|
cursorWayland->width = image->width;
|
||||||
|
cursorWayland->height = image->height;
|
||||||
|
cursorWayland->xhot = image->hotspot_x;
|
||||||
|
cursorWayland->yhot = image->hotspot_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
||||||
|
surface,
|
||||||
|
cursorWayland->xhot,
|
||||||
|
cursorWayland->yhot);
|
||||||
|
wl_surface_attach(surface, buffer, 0, 0);
|
||||||
|
wl_surface_damage(surface, 0, 0,
|
||||||
|
cursorWayland->width, cursorWayland->height);
|
||||||
|
wl_surface_commit(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
incrementCursorImage(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
_GLFWcursor* cursor;
|
||||||
|
|
||||||
|
if (!window || window->wl.decorations.focus != mainWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cursor = window->wl.currentCursor;
|
||||||
|
if (cursor && cursor->wl.cursor)
|
||||||
|
{
|
||||||
|
cursor->wl.currentImage += 1;
|
||||||
|
cursor->wl.currentImage %= cursor->wl.cursor->image_count;
|
||||||
|
setCursorImage(&cursor->wl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleEvents(int timeout)
|
handleEvents(int timeout)
|
||||||
{
|
{
|
||||||
@ -750,7 +804,7 @@ handleEvents(int timeout)
|
|||||||
if (read_ret != 8)
|
if (read_ret != 8)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: implement!
|
incrementCursorImage(_glfw.wl.pointerFocus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1267,14 +1321,15 @@ int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor->wl.image = standardCursor->images[0];
|
cursor->wl.cursor = standardCursor;
|
||||||
|
cursor->wl.currentImage = 0;
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
// If it's a standard cursor we don't need to do anything here
|
// If it's a standard cursor we don't need to do anything here
|
||||||
if (cursor->wl.image)
|
if (cursor->wl.cursor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cursor->wl.buffer)
|
if (cursor->wl.buffer)
|
||||||
@ -1380,10 +1435,7 @@ static GLFWbool isPointerLocked(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
||||||
{
|
{
|
||||||
struct wl_buffer* buffer;
|
|
||||||
struct wl_cursor* defaultCursor;
|
struct wl_cursor* defaultCursor;
|
||||||
struct wl_cursor_image* image;
|
|
||||||
struct wl_surface* surface = _glfw.wl.cursorSurface;
|
|
||||||
|
|
||||||
if (!_glfw.wl.pointer)
|
if (!_glfw.wl.pointer)
|
||||||
return;
|
return;
|
||||||
@ -1392,7 +1444,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
|
|
||||||
// If we're not in the correct window just save the cursor
|
// If we're not in the correct window just save the cursor
|
||||||
// the next time the pointer enters the window the cursor will change
|
// the next time the pointer enters the window the cursor will change
|
||||||
if (window != _glfw.wl.pointerFocus)
|
if (window != _glfw.wl.pointerFocus || window->wl.decorations.focus != mainWindow)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Unlock possible pointer lock if no longer disabled.
|
// Unlock possible pointer lock if no longer disabled.
|
||||||
@ -1402,7 +1454,7 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
if (window->cursorMode == GLFW_CURSOR_NORMAL)
|
||||||
{
|
{
|
||||||
if (cursor)
|
if (cursor)
|
||||||
image = cursor->wl.image;
|
setCursorImage(&cursor->wl);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
|
defaultCursor = wl_cursor_theme_get_cursor(_glfw.wl.cursorTheme,
|
||||||
@ -1413,33 +1465,14 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
"Wayland: Standard cursor not found");
|
"Wayland: Standard cursor not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
image = defaultCursor->images[0];
|
_GLFWcursorWayland cursorWayland = {
|
||||||
}
|
defaultCursor,
|
||||||
|
NULL,
|
||||||
if (image)
|
0, 0,
|
||||||
{
|
0, 0,
|
||||||
buffer = wl_cursor_image_get_buffer(image);
|
0
|
||||||
if (!buffer)
|
};
|
||||||
return;
|
setCursorImage(&cursorWayland);
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
|
||||||
surface,
|
|
||||||
image->hotspot_x,
|
|
||||||
image->hotspot_y);
|
|
||||||
wl_surface_attach(surface, buffer, 0, 0);
|
|
||||||
wl_surface_damage(surface, 0, 0,
|
|
||||||
image->width, image->height);
|
|
||||||
wl_surface_commit(surface);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wl_pointer_set_cursor(_glfw.wl.pointer, _glfw.wl.pointerSerial,
|
|
||||||
surface,
|
|
||||||
cursor->wl.xhot,
|
|
||||||
cursor->wl.yhot);
|
|
||||||
wl_surface_attach(surface, cursor->wl.buffer, 0, 0);
|
|
||||||
wl_surface_damage(surface, 0, 0,
|
|
||||||
cursor->wl.width, cursor->wl.height);
|
|
||||||
wl_surface_commit(surface);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
else if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
|
Loading…
Reference in New Issue
Block a user