Fix software cursor being used with absolute events in Wayland

The software cursor was being enabled with absolute events,
causing a problem with absolute tablet events.

This caused both cursors to be visible at once when using a tablet
(with D15152 applied).
This commit is contained in:
Campbell Barton 2022-06-09 10:02:15 +10:00
parent 8a02696724
commit 8b8fbffeea
6 changed files with 56 additions and 41 deletions

View File

@ -402,9 +402,10 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
int32_t x,
int32_t y);
GHOST_TSuccess GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle,
GHOST_TAxisFlag *r_wrap_axis,
int r_bounds[4]);
void GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle,
GHOST_TGrabCursorMode *r_mode,
GHOST_TAxisFlag *r_wrap_axis,
int r_bounds[4]);
/**
* Grabs the cursor for a modal operation, to keep receiving

View File

@ -256,7 +256,9 @@ class GHOST_IWindow {
virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) = 0;
virtual GHOST_TSuccess getCursorGrabState(GHOST_TAxisFlag &axis_flag, GHOST_Rect &bounds) = 0;
virtual void getCursorGrabState(GHOST_TGrabCursorMode &mode,
GHOST_TAxisFlag &axis_flag,
GHOST_Rect &bounds) = 0;
/**
* Test if the standard cursor shape is supported by current platform.

View File

@ -376,21 +376,18 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
mode, wrap_axis, bounds ? &bounds_rect : nullptr, mouse_ungrab_xy ? mouse_xy : nullptr);
}
GHOST_TSuccess GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle,
GHOST_TAxisFlag *r_axis_flag,
int r_bounds[4])
void GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle,
GHOST_TGrabCursorMode *r_mode,
GHOST_TAxisFlag *r_axis_flag,
int r_bounds[4])
{
GHOST_IWindow *window = (GHOST_IWindow *)windowhandle;
GHOST_Rect bounds_rect;
if (!window->getCursorGrabState(*r_axis_flag, bounds_rect)) {
return GHOST_kFailure;
}
window->getCursorGrabState(*r_mode, *r_axis_flag, bounds_rect);
r_bounds[0] = bounds_rect.m_l;
r_bounds[1] = bounds_rect.m_t;
r_bounds[2] = bounds_rect.m_r;
r_bounds[3] = bounds_rect.m_b;
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle,

View File

@ -162,12 +162,11 @@ GHOST_TSuccess GHOST_Window::getCursorGrabBounds(GHOST_Rect &bounds)
return (bounds.m_l == -1 && bounds.m_r == -1) ? GHOST_kFailure : GHOST_kSuccess;
}
GHOST_TSuccess GHOST_Window::getCursorGrabState(GHOST_TAxisFlag &wrap_axis, GHOST_Rect &bounds)
void GHOST_Window::getCursorGrabState(GHOST_TGrabCursorMode &mode,
GHOST_TAxisFlag &wrap_axis,
GHOST_Rect &bounds)
{
if (m_cursorGrab == GHOST_kGrabDisable) {
return GHOST_kFailure;
}
mode = m_cursorGrab;
if (m_cursorGrab == GHOST_kGrabWrap) {
bounds = m_cursorGrabBounds;
wrap_axis = m_cursorGrabAxis;
@ -179,7 +178,6 @@ GHOST_TSuccess GHOST_Window::getCursorGrabState(GHOST_TAxisFlag &wrap_axis, GHOS
bounds.m_b = -1;
wrap_axis = GHOST_kGrabAxisNone;
}
return GHOST_kSuccess;
}
GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape)

View File

@ -152,7 +152,9 @@ class GHOST_Window : public GHOST_IWindow {
*/
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds);
GHOST_TSuccess getCursorGrabState(GHOST_TAxisFlag &axis_flag, GHOST_Rect &bounds);
void getCursorGrabState(GHOST_TGrabCursorMode &mode,
GHOST_TAxisFlag &axis_flag,
GHOST_Rect &bounds);
/**
* Sets the progress bar value displayed in the window/application icon

View File

@ -137,6 +137,13 @@ static struct {
.winid = -1,
};
/** Reuse the result from #GHOST_GetCursorGrabState. */
struct GrabState {
GHOST_TGrabCursorMode mode;
GHOST_TAxisFlag wrap_axis;
int bounds[4];
};
static bool wm_software_cursor_needed(void)
{
if (UNLIKELY(g_software_cursor.enabled == -1)) {
@ -145,10 +152,19 @@ static bool wm_software_cursor_needed(void)
return g_software_cursor.enabled;
}
static bool wm_software_cursor_needed_for_window(const wmWindow *win)
static bool wm_software_cursor_needed_for_window(const wmWindow *win, struct GrabState *grab_state)
{
BLI_assert(wm_software_cursor_needed());
return (win->grabcursor == GHOST_kGrabWrap) && GHOST_GetCursorVisibility(win->ghostwin);
if (GHOST_GetCursorVisibility(win->ghostwin)) {
/* NOTE: The value in `win->grabcursor` can't be used as it
* doesn't always match GHOST's value in the case of tablet events. */
GHOST_GetCursorGrabState(
win->ghostwin, &grab_state->mode, &grab_state->wrap_axis, grab_state->bounds);
if (grab_state->mode == GHOST_kGrabWrap) {
return true;
}
}
return false;
}
static bool wm_software_cursor_motion_test(const wmWindow *win)
@ -173,28 +189,24 @@ static void wm_software_cursor_motion_clear(void)
g_software_cursor.xy[1] = -1;
}
static void wm_software_cursor_draw(wmWindow *win)
static void wm_software_cursor_draw(wmWindow *win, const struct GrabState *grab_state)
{
int x = win->eventstate->xy[0];
int y = win->eventstate->xy[1];
int bounds[4];
GHOST_TAxisFlag wrap_axis = 0;
if (GHOST_GetCursorGrabState(win->ghostwin, &wrap_axis, bounds) != GHOST_kFailure) {
if (wrap_axis & GHOST_kAxisX) {
const int min = bounds[0];
const int max = bounds[2];
if (min != max) {
x = mod_i(x - min, max - min) + min;
}
if (grab_state->wrap_axis & GHOST_kAxisX) {
const int min = grab_state->bounds[0];
const int max = grab_state->bounds[2];
if (min != max) {
x = mod_i(x - min, max - min) + min;
}
if (wrap_axis & GHOST_kGrabAxisY) {
const int height = WM_window_pixels_y(win);
const int min = height - bounds[1];
const int max = height - bounds[3];
if (min != max) {
y = mod_i(y - max, min - max) + max;
}
}
if (grab_state->wrap_axis & GHOST_kGrabAxisY) {
const int height = WM_window_pixels_y(win);
const int min = height - grab_state->bounds[1];
const int max = height - grab_state->bounds[3];
if (min != max) {
y = mod_i(y - max, min - max) + max;
}
}
@ -979,8 +991,9 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
}
if (wm_software_cursor_needed()) {
if (wm_software_cursor_needed_for_window(win)) {
wm_software_cursor_draw(win);
struct GrabState grab_state;
if (wm_software_cursor_needed_for_window(win, &grab_state)) {
wm_software_cursor_draw(win, &grab_state);
wm_software_cursor_motion_update(win);
}
else {
@ -1139,7 +1152,9 @@ static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win)
}
if (wm_software_cursor_needed()) {
if (wm_software_cursor_needed_for_window(win) && wm_software_cursor_motion_test(win)) {
struct GrabState grab_state;
if (wm_software_cursor_needed_for_window(win, &grab_state) &&
wm_software_cursor_motion_test(win)) {
return true;
}
}