Wayland: Fix GLFW_HOVERED for fallback decorations

When using the fallback decorations, GLFW_HOVERED was true also when the
cursor was over one of the window decorations.

This also disentangles the GLFW_HOVERED state from the fallback
decorations.  Because GLFW_HOVERED should have had the same behavior as
GLFW_MAIN_WINDOW, the latter has been removed.
This commit is contained in:
Camilla Löwy 2024-02-07 22:21:52 +01:00
parent 5e97447dd5
commit ea6dd72c71
3 changed files with 44 additions and 43 deletions

View File

@ -181,6 +181,8 @@ information on what to include when reporting a bug.
- [Wayland] Added support for `glfwFocusWindow`
- [Wayland] Added dynamic loading of all Wayland libraries
- [Wayland] Bugfix: `CLOCK_MONOTONIC` was not correctly enabled
- [Wayland] Bugfix: `GLFW_HOVERED` was true when the cursor was over any
fallback window decoration
- [X11] Bugfix: Termination would segfault if the IM had been destroyed
- [X11] Bugfix: Any IM started after initialization would not be detected
- [POSIX] Removed use of deprecated function `gettimeofday`

View File

@ -325,7 +325,6 @@ typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
typedef enum _GLFWdecorationSideWayland
{
GLFW_MAIN_WINDOW,
GLFW_TOP_DECORATION,
GLFW_LEFT_DECORATION,
GLFW_RIGHT_DECORATION,

View File

@ -1025,7 +1025,7 @@ static void incrementCursorImage(_GLFWwindow* window)
{
_GLFWcursor* cursor;
if (!window || window->wl.fallback.focus != GLFW_MAIN_WINDOW)
if (!window || !window->wl.hovered)
return;
cursor = window->wl.currentCursor;
@ -1276,7 +1276,9 @@ static void pointerHandleEnter(void* userData,
_GLFWwindow* window = wl_surface_get_user_data(surface);
if (surface == window->wl.fallback.top.surface)
if (surface == window->wl.surface)
window->wl.hovered = GLFW_TRUE;
else if (surface == window->wl.fallback.top.surface)
window->wl.fallback.focus = GLFW_TOP_DECORATION;
else if (surface == window->wl.fallback.left.surface)
window->wl.fallback.focus = GLFW_LEFT_DECORATION;
@ -1284,17 +1286,16 @@ static void pointerHandleEnter(void* userData,
window->wl.fallback.focus = GLFW_RIGHT_DECORATION;
else if (surface == window->wl.fallback.bottom.surface)
window->wl.fallback.focus = GLFW_BOTTOM_DECORATION;
else
window->wl.fallback.focus = GLFW_MAIN_WINDOW;
_glfw.wl.serial = serial;
_glfw.wl.pointerEnterSerial = serial;
_glfw.wl.pointerFocus = window;
window->wl.hovered = GLFW_TRUE;
_glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
if (window->wl.hovered)
{
_glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
}
}
static void pointerHandleLeave(void* userData,
@ -1312,12 +1313,15 @@ static void pointerHandleLeave(void* userData,
if (!window)
return;
window->wl.hovered = GLFW_FALSE;
_glfw.wl.serial = serial;
_glfw.wl.pointerFocus = NULL;
_glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorEnter(window, GLFW_FALSE);
if (window->wl.hovered)
{
window->wl.hovered = GLFW_FALSE;
_glfwInputCursorEnter(window, GLFW_FALSE);
}
}
static void pointerHandleMotion(void* userData,
@ -1338,14 +1342,17 @@ static void pointerHandleMotion(void* userData,
window->wl.cursorPosX = xpos;
window->wl.cursorPosY = ypos;
if (window->wl.hovered)
{
_glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorPos(window, xpos, ypos);
return;
}
const char* cursorName = NULL;
switch (window->wl.fallback.focus)
{
case GLFW_MAIN_WINDOW:
_glfw.wl.cursorPreviousName = NULL;
_glfwInputCursorPos(window, xpos, ypos);
return;
case GLFW_TOP_DECORATION:
if (ypos < GLFW_BORDER_SIZE)
cursorName = "n-resize";
@ -1429,12 +1436,28 @@ static void pointerHandleButton(void* userData,
if (!window)
return;
if (window->wl.hovered)
{
_glfw.wl.serial = serial;
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
* codes. */
glfwButton = button - BTN_LEFT;
_glfwInputMouseClick(window,
glfwButton,
state == WL_POINTER_BUTTON_STATE_PRESSED
? GLFW_PRESS
: GLFW_RELEASE,
_glfw.wl.xkb.modifiers);
return;
}
if (button == BTN_LEFT)
{
switch (window->wl.fallback.focus)
{
case GLFW_MAIN_WINDOW:
break;
case GLFW_TOP_DECORATION:
if (window->wl.cursorPosY < GLFW_BORDER_SIZE)
edges = XDG_TOPLEVEL_RESIZE_EDGE_TOP;
@ -1468,38 +1491,18 @@ static void pointerHandleButton(void* userData,
{
xdg_toplevel_resize(window->wl.xdg.toplevel, _glfw.wl.seat,
serial, edges);
return;
}
}
else if (button == BTN_RIGHT)
{
if (window->wl.fallback.focus != GLFW_MAIN_WINDOW &&
window->wl.xdg.toplevel)
if (window->wl.xdg.toplevel)
{
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
window->wl.cursorPosX,
window->wl.cursorPosY);
return;
}
}
// Dont pass the button to the user if it was related to a decoration.
if (window->wl.fallback.focus != GLFW_MAIN_WINDOW)
return;
_glfw.wl.serial = serial;
/* Makes left, right and middle 0, 1 and 2. Overall order follows evdev
* codes. */
glfwButton = button - BTN_LEFT;
_glfwInputMouseClick(window,
glfwButton,
state == WL_POINTER_BUTTON_STATE_PRESSED
? GLFW_PRESS
: GLFW_RELEASE,
_glfw.wl.xkb.modifiers);
}
static void pointerHandleAxis(void* userData,
@ -2925,11 +2928,8 @@ void _glfwSetCursorWayland(_GLFWwindow* window, _GLFWcursor* 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
if (window != _glfw.wl.pointerFocus ||
window->wl.fallback.focus != GLFW_MAIN_WINDOW)
{
if (!window->wl.hovered)
return;
}
// Update pointer lock to match cursor mode
if (window->cursorMode == GLFW_CURSOR_DISABLED)