From ba89f640fe6566437f8aaf4974dcda473671c7f4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 16 Dec 2022 18:37:47 +1100 Subject: [PATCH] Fix T102792: Sculpt cursor jumps to random place Restrict the condition under which paint cursors read use the cursor location from the the operating-system. This caused a glitch when dragging UI elements in painting context popup. Since the paint cursor would display using mouse motion which was clamped to the window center - an internal detail of hidden cursor grabbing. Now only read the cursor coordinates when clamped to a region which is used for the transform cursor to stay visible even when the cursor wraps around. --- source/blender/windowmanager/intern/wm_draw.c | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index cbbd0eb3a4f..15826af32fa 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -63,6 +63,31 @@ # include "BKE_subsurf.h" #endif +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ + +/** + * Return true when the cursor is grabbed and wrapped within a region. + */ +static bool wm_window_grab_warp_region_is_set(const wmWindow *win) +{ + if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) { + GHOST_TGrabCursorMode mode_dummy; + GHOST_TAxisFlag wrap_axis_dummy; + int bounds[4] = {0}; + bool use_software_cursor_dummy = false; + GHOST_GetCursorGrabState( + win->ghostwin, &mode_dummy, &wrap_axis_dummy, bounds, &use_software_cursor_dummy); + if ((bounds[0] != bounds[2]) || (bounds[1] != bounds[3])) { + return true; + } + } + return false; +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Draw Paint Cursor * \{ */ @@ -102,8 +127,14 @@ static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region) region->winrct.ymin, BLI_rcti_size_x(®ion->winrct) + 1, BLI_rcti_size_y(®ion->winrct) + 1); - - if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) { + /* Reading the cursor location from the operating-system while the cursor is grabbed + * conflicts with grabbing logic that hides the cursor, then keeps it centered to accumulate + * deltas without it escaping from the window. In this case we never want to show the actual + * cursor coordinates so limit reading the cursor location to when the cursor is grabbed and + * wrapping in a region since this is the case when it would otherwise attempt to draw the + * cursor outside the view/window. See: T102792. */ + if ((WM_capabilities_flag() & WM_CAPABILITY_CURSOR_WARP) && + wm_window_grab_warp_region_is_set(win)) { int x = 0, y = 0; wm_cursor_position_get(win, &x, &y); pc->draw(C, x, y, pc->customdata);