mirror of
https://github.com/glfw/glfw.git
synced 2025-12-21 06:31:58 +00:00
Compare commits
9 Commits
b466a05df1
...
93f990712b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93f990712b | ||
|
|
161fb1b6f6 | ||
|
|
645a35a38e | ||
|
|
7523b0e6bd | ||
|
|
5190a30d8a | ||
|
|
ddbb8e0f2c | ||
|
|
5245180c56 | ||
|
|
a284523f9e | ||
|
|
8ef7bfdd2e |
@ -135,6 +135,9 @@ information on what to include when reporting a bug.
|
|||||||
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#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: Memory would leak if reading a data offer failed midway
|
||||||
- [Wayland] Bugfix: Keyboard leave event handler now processes key repeats (#2736)
|
- [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
|
||||||
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
|
- [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 Vulkan 'window' surface creation via `VK_EXT_headless_surface`
|
||||||
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
|
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`
|
||||||
|
|||||||
@ -35,6 +35,19 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
|
#include <BaseTsd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
typedef UINT64 QWORD; // Needed for NEXTRAWINPUTBLOCK()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef RI_MOUSE_HWHEEL
|
||||||
|
// MinGW may not have the define for RI_MOUSE_HWHEEL
|
||||||
|
#define RI_MOUSE_HWHEEL 0x0800
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Returns the window style for the specified window
|
// Returns the window style for the specified window
|
||||||
//
|
//
|
||||||
@ -265,7 +278,7 @@ static void releaseCursor(void)
|
|||||||
//
|
//
|
||||||
static void enableRawMouseMotion(_GLFWwindow* window)
|
static void enableRawMouseMotion(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
const RAWINPUTDEVICE rid = { 0x01, 0x02, 0, window->win32.handle };
|
const RAWINPUTDEVICE rid = { 0x01, 0x02, RIDEV_NOLEGACY, window->win32.handle };
|
||||||
|
|
||||||
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
if (!RegisterRawInputDevices(&rid, 1, sizeof(rid)))
|
||||||
{
|
{
|
||||||
@ -894,77 +907,6 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
case WM_INPUT:
|
|
||||||
{
|
|
||||||
UINT size = 0;
|
|
||||||
HRAWINPUT ri = (HRAWINPUT) lParam;
|
|
||||||
RAWINPUT* data = NULL;
|
|
||||||
int dx, dy;
|
|
||||||
|
|
||||||
if (_glfw.win32.disabledCursorWindow != window)
|
|
||||||
break;
|
|
||||||
if (!window->rawMouseMotion)
|
|
||||||
break;
|
|
||||||
|
|
||||||
GetRawInputData(ri, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER));
|
|
||||||
if (size > (UINT) _glfw.win32.rawInputSize)
|
|
||||||
{
|
|
||||||
_glfw_free(_glfw.win32.rawInput);
|
|
||||||
_glfw.win32.rawInput = _glfw_calloc(size, 1);
|
|
||||||
_glfw.win32.rawInputSize = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size = _glfw.win32.rawInputSize;
|
|
||||||
if (GetRawInputData(ri, RID_INPUT,
|
|
||||||
_glfw.win32.rawInput, &size,
|
|
||||||
sizeof(RAWINPUTHEADER)) == (UINT) -1)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Win32: Failed to retrieve raw input data");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = _glfw.win32.rawInput;
|
|
||||||
if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
|
|
||||||
{
|
|
||||||
POINT pos = {0};
|
|
||||||
int width, height;
|
|
||||||
|
|
||||||
if (data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP)
|
|
||||||
{
|
|
||||||
pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
|
|
||||||
pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
|
|
||||||
width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
|
||||||
height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
width = GetSystemMetrics(SM_CXSCREEN);
|
|
||||||
height = GetSystemMetrics(SM_CYSCREEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos.x += (int) ((data->data.mouse.lLastX / 65535.f) * width);
|
|
||||||
pos.y += (int) ((data->data.mouse.lLastY / 65535.f) * height);
|
|
||||||
ScreenToClient(window->win32.handle, &pos);
|
|
||||||
|
|
||||||
dx = pos.x - window->win32.lastCursorPosX;
|
|
||||||
dy = pos.y - window->win32.lastCursorPosY;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dx = data->data.mouse.lLastX;
|
|
||||||
dy = data->data.mouse.lLastY;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfwInputCursorPos(window,
|
|
||||||
window->virtualCursorPosX + dx,
|
|
||||||
window->virtualCursorPosY + dy);
|
|
||||||
|
|
||||||
window->win32.lastCursorPosX += dx;
|
|
||||||
window->win32.lastCursorPosY += dy;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case WM_MOUSELEAVE:
|
case WM_MOUSELEAVE:
|
||||||
{
|
{
|
||||||
window->win32.cursorTracked = GLFW_FALSE;
|
window->win32.cursorTracked = GLFW_FALSE;
|
||||||
@ -2086,11 +2028,215 @@ GLFWbool _glfwRawMouseMotionSupportedWin32(void)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void _processRawInput(void)
|
||||||
|
{
|
||||||
|
UINT size = 0;
|
||||||
|
UINT riSize = 0;
|
||||||
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
|
|
||||||
|
if (_glfw.win32.disabledCursorWindow != window)
|
||||||
|
return;
|
||||||
|
if (!window->rawMouseMotion)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// get the size of the raw input buffer
|
||||||
|
UINT result = GetRawInputBuffer(NULL, &riSize, sizeof(RAWINPUTHEADER));
|
||||||
|
if (result == (UINT)-1)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to retrieve raw input buffer size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT byteCount = riSize * 16;
|
||||||
|
|
||||||
|
if (byteCount > (UINT)_glfw.win32.rawInputSize)
|
||||||
|
{
|
||||||
|
_glfw_free(_glfw.win32.rawInput);
|
||||||
|
_glfw.win32.rawInput = _glfw_calloc(byteCount, 1);
|
||||||
|
_glfw.win32.rawInputSize = byteCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read it (actually) this time into the buffer
|
||||||
|
size = _glfw.win32.rawInputSize;
|
||||||
|
result = GetRawInputBuffer(_glfw.win32.rawInput, &size, sizeof(RAWINPUTHEADER));
|
||||||
|
if (result == (UINT)-1)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Win32: Failed to retrieve raw input buffer");
|
||||||
|
_glfw_free(_glfw.win32.rawInput);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// print msg count
|
||||||
|
//printf("raw input count: %u\n", result);
|
||||||
|
|
||||||
|
UINT riCount = result;
|
||||||
|
|
||||||
|
RAWINPUT* data = _glfw.win32.rawInput;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < riCount; ++i)
|
||||||
|
{
|
||||||
|
if (data->header.dwType == RIM_TYPEMOUSE) {
|
||||||
|
int dx = 0, dy = 0;
|
||||||
|
|
||||||
|
if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
|
||||||
|
{
|
||||||
|
POINT pos = {0};
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
if (data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP)
|
||||||
|
{
|
||||||
|
pos.x += GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||||
|
pos.y += GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||||
|
width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||||
|
height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
height = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.x += (int)((data->data.mouse.lLastX / 65535.f) * width);
|
||||||
|
pos.y += (int)((data->data.mouse.lLastY / 65535.f) * height);
|
||||||
|
ScreenToClient(window->win32.handle, &pos);
|
||||||
|
|
||||||
|
dx = pos.x - window->win32.lastCursorPosX;
|
||||||
|
dy = pos.y - window->win32.lastCursorPosY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (data->data.mouse.lLastX || data->data.mouse.lLastY)
|
||||||
|
{
|
||||||
|
dx = data->data.mouse.lLastX;
|
||||||
|
dy = data->data.mouse.lLastY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dx != 0 || dy != 0)
|
||||||
|
{
|
||||||
|
_glfwInputCursorPos(window,
|
||||||
|
window->virtualCursorPosX + dx,
|
||||||
|
window->virtualCursorPosY + dy);
|
||||||
|
|
||||||
|
window->win32.lastCursorPosX += dx;
|
||||||
|
window->win32.lastCursorPosY += dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Instead of reposting the events, we duplicate the button events' handlers here.
|
||||||
|
|
||||||
|
|
||||||
|
USHORT buttonFlags = data->data.mouse.usButtonFlags;
|
||||||
|
HWND hwnd = window->win32.handle;
|
||||||
|
|
||||||
|
// if any down or up button (anything except RI_MOUSE_WHEEL or RI_MOUSE_HWHEEL), process
|
||||||
|
if (buttonFlags & 0xFFFF & ~(RI_MOUSE_WHEEL | RI_MOUSE_HWHEEL))
|
||||||
|
{
|
||||||
|
int i, button = -1, action = -1;
|
||||||
|
|
||||||
|
if (buttonFlags & RI_MOUSE_LEFT_BUTTON_DOWN)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_LEFT;
|
||||||
|
action = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonFlags & RI_MOUSE_LEFT_BUTTON_UP)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_LEFT;
|
||||||
|
action = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_DOWN)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_RIGHT;
|
||||||
|
action = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
if (buttonFlags & RI_MOUSE_RIGHT_BUTTON_UP)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_RIGHT;
|
||||||
|
action = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_DOWN)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_MIDDLE;
|
||||||
|
action = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
if (buttonFlags & RI_MOUSE_MIDDLE_BUTTON_UP)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_MIDDLE;
|
||||||
|
action = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonFlags & RI_MOUSE_BUTTON_4_DOWN)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_4;
|
||||||
|
action = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
if (buttonFlags & RI_MOUSE_BUTTON_4_UP)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_4;
|
||||||
|
action = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonFlags & RI_MOUSE_BUTTON_5_DOWN)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_5;
|
||||||
|
action = GLFW_PRESS;
|
||||||
|
}
|
||||||
|
if (buttonFlags & RI_MOUSE_BUTTON_5_UP)
|
||||||
|
{
|
||||||
|
button = GLFW_MOUSE_BUTTON_5;
|
||||||
|
action = GLFW_RELEASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||||
|
{
|
||||||
|
if (window->mouseButtons[i] == GLFW_PRESS)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > GLFW_MOUSE_BUTTON_LAST)
|
||||||
|
SetCapture(hwnd);
|
||||||
|
|
||||||
|
_glfwInputMouseClick(window, button, action, getKeyMods());
|
||||||
|
|
||||||
|
for (i = 0; i <= GLFW_MOUSE_BUTTON_LAST; i++)
|
||||||
|
{
|
||||||
|
if (window->mouseButtons[i] == GLFW_PRESS)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > GLFW_MOUSE_BUTTON_LAST)
|
||||||
|
ReleaseCapture();
|
||||||
|
}
|
||||||
|
// Handle mouse wheel events
|
||||||
|
if (buttonFlags & RI_MOUSE_WHEEL)
|
||||||
|
{
|
||||||
|
SHORT wheelDelta = (SHORT)data->data.mouse.usButtonData;
|
||||||
|
_glfwInputScroll(window, 0.0, wheelDelta / (double) WHEEL_DELTA);
|
||||||
|
}
|
||||||
|
if (buttonFlags & RI_MOUSE_HWHEEL)
|
||||||
|
{
|
||||||
|
SHORT wheelDelta = (SHORT)data->data.mouse.usButtonData;
|
||||||
|
_glfwInputScroll(window, -wheelDelta / (double) WHEEL_DELTA, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = NEXTRAWINPUTBLOCK(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void _glfwPollEventsWin32(void)
|
void _glfwPollEventsWin32(void)
|
||||||
{
|
{
|
||||||
MSG msg;
|
MSG msg;
|
||||||
HWND handle;
|
HWND handle;
|
||||||
_GLFWwindow* window;
|
_GLFWwindow* window = _glfw.windowListHead;
|
||||||
|
|
||||||
|
_processRawInput(); // this does the whole `GetRawInputBuffer` thing
|
||||||
|
|
||||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
|
||||||
{
|
{
|
||||||
@ -2153,7 +2299,8 @@ void _glfwPollEventsWin32(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
window = _glfw.win32.disabledCursorWindow;
|
window = _glfw.win32.disabledCursorWindow;
|
||||||
if (window)
|
// Disable with raw mouse motion because that reports dx/dy directly
|
||||||
|
if (window && !window->rawMouseMotion)
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
_glfwGetWindowSizeWin32(window, &width, &height);
|
_glfwGetWindowSizeWin32(window, &width, &height);
|
||||||
|
|||||||
@ -413,6 +413,8 @@ typedef struct _GLFWwindowWayland
|
|||||||
struct wl_buffer* buffer;
|
struct wl_buffer* buffer;
|
||||||
_GLFWfallbackEdgeWayland top, left, right, bottom;
|
_GLFWfallbackEdgeWayland top, left, right, bottom;
|
||||||
struct wl_surface* focus;
|
struct wl_surface* focus;
|
||||||
|
wl_fixed_t pointerX, pointerY;
|
||||||
|
const char* cursorName;
|
||||||
} fallback;
|
} fallback;
|
||||||
} _GLFWwindowWayland;
|
} _GLFWwindowWayland;
|
||||||
|
|
||||||
@ -454,7 +456,6 @@ typedef struct _GLFWlibraryWayland
|
|||||||
struct wl_cursor_theme* cursorTheme;
|
struct wl_cursor_theme* cursorTheme;
|
||||||
struct wl_cursor_theme* cursorThemeHiDPI;
|
struct wl_cursor_theme* cursorThemeHiDPI;
|
||||||
struct wl_surface* cursorSurface;
|
struct wl_surface* cursorSurface;
|
||||||
const char* cursorPreviousName;
|
|
||||||
int cursorTimerfd;
|
int cursorTimerfd;
|
||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
uint32_t pointerEnterSerial;
|
uint32_t pointerEnterSerial;
|
||||||
|
|||||||
292
src/wl_window.c
292
src/wl_window.c
@ -275,6 +275,146 @@ static void destroyFallbackDecorations(_GLFWwindow* window)
|
|||||||
destroyFallbackEdge(&window->wl.fallback.bottom);
|
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,
|
static void xdgDecorationHandleConfigure(void* userData,
|
||||||
struct zxdg_toplevel_decoration_v1* decoration,
|
struct zxdg_toplevel_decoration_v1* decoration,
|
||||||
uint32_t mode)
|
uint32_t mode)
|
||||||
@ -1417,7 +1557,6 @@ static void pointerHandleLeave(void* userData,
|
|||||||
|
|
||||||
_glfw.wl.serial = serial;
|
_glfw.wl.serial = serial;
|
||||||
_glfw.wl.pointerFocus = NULL;
|
_glfw.wl.pointerFocus = NULL;
|
||||||
_glfw.wl.cursorPreviousName = NULL;
|
|
||||||
|
|
||||||
if (window->wl.hovered)
|
if (window->wl.hovered)
|
||||||
{
|
{
|
||||||
@ -1427,7 +1566,10 @@ static void pointerHandleLeave(void* userData,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (window->wl.fallback.decorations)
|
if (window->wl.fallback.decorations)
|
||||||
|
{
|
||||||
window->wl.fallback.focus = NULL;
|
window->wl.fallback.focus = NULL;
|
||||||
|
window->wl.fallback.cursorName = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1444,92 +1586,16 @@ static void pointerHandleMotion(void* userData,
|
|||||||
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
if (window->cursorMode == GLFW_CURSOR_DISABLED)
|
||||||
return;
|
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)
|
if (window->wl.hovered)
|
||||||
{
|
{
|
||||||
_glfw.wl.cursorPreviousName = NULL;
|
window->wl.cursorPosX = wl_fixed_to_double(sx);
|
||||||
_glfwInputCursorPos(window, xpos, ypos);
|
window->wl.cursorPosY = wl_fixed_to_double(sy);
|
||||||
return;
|
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (window->wl.fallback.decorations)
|
if (window->wl.fallback.decorations)
|
||||||
{
|
updateFallbackDecorationCursor(window, sx, 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 (_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1552,62 +1618,11 @@ static void pointerHandleButton(void* userData,
|
|||||||
button - BTN_LEFT,
|
button - BTN_LEFT,
|
||||||
state == WL_POINTER_BUTTON_STATE_PRESSED,
|
state == WL_POINTER_BUTTON_STATE_PRESSED,
|
||||||
_glfw.wl.xkb.modifiers);
|
_glfw.wl.xkb.modifiers);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (window->wl.fallback.decorations)
|
if (window->wl.fallback.decorations)
|
||||||
{
|
handleFallbackDecorationButton(window, serial, button);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1621,12 +1636,15 @@ static void pointerHandleAxis(void* userData,
|
|||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (window->wl.hovered)
|
||||||
|
{
|
||||||
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
|
// NOTE: 10 units of motion per mouse wheel step seems to be a common ratio
|
||||||
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL)
|
||||||
_glfwInputScroll(window, -wl_fixed_to_double(value) / 10.0, 0.0);
|
_glfwInputScroll(window, -wl_fixed_to_double(value) / 10.0, 0.0);
|
||||||
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
|
||||||
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
|
_glfwInputScroll(window, 0.0, -wl_fixed_to_double(value) / 10.0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wl_pointer_listener pointerListener =
|
static const struct wl_pointer_listener pointerListener =
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user