mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-02-13 15:23:34 +00:00
wayland: Don't clear the cursor on leave events
Stop the frame callback and flag the cursor for a refresh when the pointer re-enters the surface, but don't set a null cursor, as it may have already been set after entering a surface that is part of the window decorations, resulting in an unwanted invisible cursor.
(cherry picked from commit 5e2977709b)
This commit is contained in:
@@ -73,7 +73,10 @@ typedef struct SDL_WaylandCursorState
|
||||
|
||||
Uint64 last_frame_callback_time_ms;
|
||||
Uint32 current_frame_time_ms;
|
||||
|
||||
// 0 or greater if a buffer is attached, -1 if in the reset state.
|
||||
int current_frame;
|
||||
|
||||
SDL_HitTestResult hit_test_result;
|
||||
} SDL_WaylandCursorState;
|
||||
|
||||
|
||||
@@ -900,7 +900,8 @@ static void Wayland_FreeCursorData(SDL_CursorData *d)
|
||||
if (seat->pointer.current_cursor == d) {
|
||||
Wayland_CursorStateDestroyFrameCallback(&seat->pointer.cursor_state);
|
||||
|
||||
if (seat->pointer.cursor_state.surface) {
|
||||
// Custom cursor buffers are about to be destroyed, so ensure they are detached.
|
||||
if (!d->is_system_cursor && seat->pointer.cursor_state.surface) {
|
||||
wl_surface_attach(seat->pointer.cursor_state.surface, NULL, 0, 0);
|
||||
}
|
||||
|
||||
@@ -1040,7 +1041,7 @@ static void Wayland_CursorStateSetCursor(SDL_WaylandCursorState *state, const Wa
|
||||
}
|
||||
|
||||
if (cursor) {
|
||||
if (cursor_data == state->current_cursor) {
|
||||
if (cursor_data == state->current_cursor && state->current_frame >= 0) {
|
||||
// Restart the animation sequence if the cursor didn't change.
|
||||
if (cursor_data->num_frames > 1) {
|
||||
Wayland_CursorStateResetAnimation(state, true);
|
||||
@@ -1075,6 +1076,7 @@ static void Wayland_CursorStateSetCursor(SDL_WaylandCursorState *state, const Wa
|
||||
const enum wp_cursor_shape_device_v1_shape shape = Wayland_GetSystemCursorShape(cursor_data->cursor_data.system.id);
|
||||
wp_cursor_shape_device_v1_set_shape(state->cursor_shape, serial, shape);
|
||||
state->current_cursor = cursor_data;
|
||||
state->current_frame = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1107,6 +1109,7 @@ static void Wayland_CursorStateSetCursor(SDL_WaylandCursorState *state, const Wa
|
||||
|
||||
struct wl_buffer *buffer = Wayland_CursorStateGetFrame(state, 0);
|
||||
wl_surface_attach(state->surface, buffer, 0, 0);
|
||||
state->current_frame = 0;
|
||||
|
||||
if (state->scale != 1.0) {
|
||||
if (!state->viewport) {
|
||||
@@ -1156,6 +1159,13 @@ static void Wayland_CursorStateSetCursor(SDL_WaylandCursorState *state, const Wa
|
||||
}
|
||||
}
|
||||
|
||||
static void Wayland_CursorStateResetCursor(SDL_WaylandCursorState *state)
|
||||
{
|
||||
// Stop the frame callback and set the reset status.
|
||||
Wayland_CursorStateDestroyFrameCallback(state);
|
||||
state->current_frame = -1;
|
||||
}
|
||||
|
||||
static bool Wayland_ShowCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
SDL_VideoDevice *vd = SDL_GetVideoDevice();
|
||||
@@ -1170,7 +1180,7 @@ static bool Wayland_ShowCursor(SDL_Cursor *cursor)
|
||||
if (mouse->focus && mouse->focus->internal == seat->pointer.focus) {
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, seat->pointer.focus, seat->pointer.enter_serial, cursor);
|
||||
} else if (!seat->pointer.focus) {
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, seat->pointer.focus, seat->pointer.enter_serial, NULL);
|
||||
Wayland_CursorStateResetCursor(&seat->pointer.cursor_state);
|
||||
}
|
||||
|
||||
SDL_WaylandPenTool *tool;
|
||||
@@ -1184,7 +1194,7 @@ static bool Wayland_ShowCursor(SDL_Cursor *cursor)
|
||||
if (tool->focus && (!mouse->focus || mouse->focus->internal == tool->focus)) {
|
||||
Wayland_CursorStateSetCursor(&tool->cursor_state, &obj, tool->focus, tool->proximity_serial, mouse->cur_cursor);
|
||||
} else if (!tool->focus) {
|
||||
Wayland_CursorStateSetCursor(&tool->cursor_state, &obj, tool->focus, tool->proximity_serial, NULL);
|
||||
Wayland_CursorStateResetCursor(&tool->cursor_state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1506,24 +1516,25 @@ void Wayland_SeatUpdatePointerCursor(SDL_WaylandSeat *seat)
|
||||
.is_pointer = true
|
||||
};
|
||||
|
||||
if (pointer_focus && mouse->cursor_visible) {
|
||||
if (!seat->pointer.relative_pointer || !mouse->relative_mode_hide_cursor) {
|
||||
const SDL_HitTestResult rc = pointer_focus->hit_test_result;
|
||||
if (pointer_focus) {
|
||||
if (mouse->cursor_visible) {
|
||||
if (!seat->pointer.relative_pointer || !mouse->relative_mode_hide_cursor) {
|
||||
const SDL_HitTestResult rc = pointer_focus->hit_test_result;
|
||||
|
||||
if (seat->pointer.relative_pointer || rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) {
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, pointer_focus, seat->pointer.enter_serial, mouse->cur_cursor);
|
||||
if (seat->pointer.relative_pointer || rc == SDL_HITTEST_NORMAL || rc == SDL_HITTEST_DRAGGABLE) {
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, pointer_focus, seat->pointer.enter_serial, mouse->cur_cursor);
|
||||
} else {
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, pointer_focus, seat->pointer.enter_serial, sys_cursors[rc]);
|
||||
}
|
||||
} else {
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, pointer_focus, seat->pointer.enter_serial, sys_cursors[rc]);
|
||||
// Hide the cursor in relative mode, unless requested otherwise by the hint.
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, pointer_focus, seat->pointer.enter_serial, NULL);
|
||||
}
|
||||
} else {
|
||||
// Hide the cursor in relative mode, unless requested otherwise by the hint.
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, pointer_focus, seat->pointer.enter_serial, NULL);
|
||||
}
|
||||
} else {
|
||||
/* The spec states "The cursor actually changes only if the input device focus is one of the
|
||||
* requesting client's surfaces", so just clear the cursor if the seat has no pointer focus.
|
||||
*/
|
||||
Wayland_CursorStateSetCursor(&seat->pointer.cursor_state, &obj, pointer_focus, seat->pointer.enter_serial, NULL);
|
||||
Wayland_CursorStateResetCursor(&seat->pointer.cursor_state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1536,18 +1547,22 @@ void Wayland_TabletToolUpdateCursor(SDL_WaylandPenTool *tool)
|
||||
.is_pointer = false
|
||||
};
|
||||
|
||||
if (tool_focus && mouse->cursor_visible) {
|
||||
// Relative mode is only relevant if the tool sends pointer events.
|
||||
const bool relative = mouse->pen_mouse_events && (tool_focus->sdlwindow->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE);
|
||||
if (tool_focus) {
|
||||
if (mouse->cursor_visible) {
|
||||
// Relative mode is only relevant if the tool sends pointer events.
|
||||
const bool relative = mouse->pen_mouse_events && (tool_focus->sdlwindow->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE);
|
||||
|
||||
if (!relative || !mouse->relative_mode_hide_cursor) {
|
||||
Wayland_CursorStateSetCursor(&tool->cursor_state, &obj, tool_focus, tool->proximity_serial, mouse->cur_cursor);
|
||||
if (!relative || !mouse->relative_mode_hide_cursor) {
|
||||
Wayland_CursorStateSetCursor(&tool->cursor_state, &obj, tool_focus, tool->proximity_serial, mouse->cur_cursor);
|
||||
} else {
|
||||
// Hide the cursor in relative mode, unless requested otherwise by the hint.
|
||||
Wayland_CursorStateSetCursor(&tool->cursor_state, &obj, tool_focus, tool->proximity_serial, NULL);
|
||||
}
|
||||
} else {
|
||||
// Hide the cursor in relative mode, unless requested otherwise by the hint.
|
||||
Wayland_CursorStateSetCursor(&tool->cursor_state, &obj, tool_focus, tool->proximity_serial, NULL);
|
||||
}
|
||||
} else {
|
||||
Wayland_CursorStateSetCursor(&tool->cursor_state, &obj, tool_focus, tool->proximity_serial, NULL);
|
||||
Wayland_CursorStateResetCursor(&tool->cursor_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user