Fix T102346: Mouse escapes window during walk navigation

This is an alternative fix to [0] which kept the cursor centrally
located as part of GHOST cursor grabbing which caused T102792.

Now this is done as part of walk mode as it's the operator that most
often ran into this problem although ideally this would be handled by
GHOST - but that's a much bigger project.

[0]: 9fd6dae793
This commit is contained in:
Campbell Barton 2022-12-15 11:57:00 +11:00 committed by Thomas Dinges
parent a1e7d96801
commit b87bcd3f8f
Notes: blender-bot 2023-02-14 07:45:38 +01:00
Referenced by issue #102967, 3.4: Potential candidates for corrective releases
Referenced by issue #102667, Rendering an animation freezes at random frame
Referenced by issue #102346, Regression: Viewport Walk Navigation : mouse escapes window if it moves too fast
1 changed files with 51 additions and 2 deletions

View File

@ -55,6 +55,14 @@
#define USE_TABLET_SUPPORT
/**
* Use alternative behavior when cursor warp is supported
* to prevent the cursor escaping the window bounds, see: T102346.
*
* \note this is not needed if cursor positioning is not supported.
*/
#define USE_CURSOR_WARP_HACK
/* -------------------------------------------------------------------- */
/** \name Modal Key-map
* \{ */
@ -221,6 +229,10 @@ typedef struct WalkInfo {
bool need_rotation_keyframe;
bool need_translation_keyframe;
#ifdef USE_CURSOR_WARP_HACK
bool need_modal_cursor_warp_hack;
#endif
/** Previous 2D mouse values. */
int prev_mval[2];
/** Initial mouse location. */
@ -579,6 +591,10 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, const int
walk->need_rotation_keyframe = false;
walk->need_translation_keyframe = false;
#ifdef USE_CURSOR_WARP_HACK
walk->need_modal_cursor_warp_hack = false;
#endif
walk->time_lastdraw = PIL_check_seconds_timer();
walk->draw_handle_pixel = ED_region_draw_cb_activate(
@ -594,7 +610,31 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op, const int
copy_v2_v2_int(walk->init_mval, mval);
copy_v2_v2_int(walk->prev_mval, mval);
WM_cursor_grab_enable(win, 0, true, NULL);
#ifdef USE_CURSOR_WARP_HACK
if (WM_capabilities_flag() & WM_CAPABILITY_CURSOR_WARP) {
int bounds[4];
const rcti *rect = &walk->region->winrct;
const int center[2] = {BLI_rcti_cent_x(rect), BLI_rcti_cent_y(rect)};
const int size[2] = {BLI_rcti_size_x(rect), BLI_rcti_size_y(rect)};
const int div = 4; /* Where 2 is the region size. */
bounds[0] = center[0] - (size[0] / div); /* X-min. */
bounds[1] = center[1] + (size[1] / div); /* Y-max. */
bounds[2] = center[0] + (size[0] / div); /* X-max. */
bounds[3] = center[1] - (size[1] / div); /* Y-min. */
WM_cursor_grab_enable(win, WM_CURSOR_WRAP_XY, false, bounds);
/* Important to hide afterwards (not part of grabbing),
* since enabling cursor and hiding at the same time ignores bounds. */
WM_cursor_modal_set(win, WM_CURSOR_NONE);
walk->need_modal_cursor_warp_hack = true;
}
else
#endif /* USE_CURSOR_WARP_HACK */
{
WM_cursor_grab_enable(win, 0, true, NULL);
}
return 1;
}
@ -643,7 +683,16 @@ static int walkEnd(bContext *C, WalkInfo *walk)
}
#endif
WM_cursor_grab_enable(win, 0, true, NULL);
WM_cursor_grab_disable(win, NULL);
#ifdef USE_CURSOR_WARP_HACK
if (walk->need_modal_cursor_warp_hack) {
WM_cursor_warp(win,
walk->region->winrct.xmin + walk->init_mval[0],
walk->region->winrct.ymin + walk->init_mval[1]);
WM_cursor_modal_restore(win);
}
#endif
if (walk->state == WALK_CONFIRM) {
MEM_freeN(walk);