Fix #107594: Phantom cursor motion when resizing windows under Wayland
Resizing a window in Wayland caused cursor motion events in the window which could be seen as buttons flashing when the cursor was detected as hovering over buttons. This was caused by two bugs: - Missing checks for failure to access the cursor location before converting the coordinates from GHOST to screen-space meant the wmWindow::eventstate location would move each time the location was updated. - Resizing the window wasn't detecting state changes and would continuously send window activation events. Window activation set wmWindpw::addmousemove which triggered the previous bug, making the cursor flicker during resize. This commit only addresses the first issue, where failure to access the cursor location wasn't accounted for (window activation will be fixed separately). All GHOST_GetCursorPosition & wm_cursor_position_get calls now account for failure, resolving uninitialized stack memory use in some cases. This resolves similar issues for macOS, WIN32 & X11 although it seems likely these platforms rarely fail to access the cursor location.
This commit is contained in:
parent
c801c73d79
commit
35edcf2ed6
|
@ -314,8 +314,9 @@ static void wm_cursor_warp_relative(wmWindow *win, int x, int y)
|
|||
{
|
||||
/* NOTE: don't use wmEvent coords because of continuous grab #36409. */
|
||||
int cx, cy;
|
||||
wm_cursor_position_get(win, &cx, &cy);
|
||||
WM_cursor_warp(win, cx + x, cy + y);
|
||||
if (wm_cursor_position_get(win, &cx, &cy)) {
|
||||
WM_cursor_warp(win, cx + x, cy + y);
|
||||
}
|
||||
}
|
||||
|
||||
bool wm_cursor_arrow_move(wmWindow *win, const wmEvent *event)
|
||||
|
|
|
@ -1005,13 +1005,13 @@ void WM_drag_draw_default_fn(bContext *C, wmWindow *win, wmDrag *drag, const int
|
|||
|
||||
void wm_drags_draw(bContext *C, wmWindow *win)
|
||||
{
|
||||
int xy[2];
|
||||
if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide)) {
|
||||
wm_cursor_position_get(win, &xy[0], &xy[1]);
|
||||
}
|
||||
else {
|
||||
xy[0] = win->eventstate->xy[0];
|
||||
xy[1] = win->eventstate->xy[1];
|
||||
const int *xy = win->eventstate->xy;
|
||||
|
||||
int xy_buf[2];
|
||||
if (ELEM(win->grabcursor, GHOST_kGrabWrap, GHOST_kGrabHide) &&
|
||||
wm_cursor_position_get(win, &xy_buf[0], &xy_buf[1]))
|
||||
{
|
||||
xy = xy_buf;
|
||||
}
|
||||
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
|
|
|
@ -140,16 +140,16 @@ static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
|
|||
* 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: #102792. */
|
||||
const int *xy = win->eventstate->xy;
|
||||
int xy_buf[2];
|
||||
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);
|
||||
}
|
||||
else {
|
||||
pc->draw(C, win->eventstate->xy[0], win->eventstate->xy[1], pc->customdata);
|
||||
wm_window_grab_warp_region_is_set(win) &&
|
||||
wm_cursor_position_get(win, &xy_buf[0], &xy_buf[1]))
|
||||
{
|
||||
xy = xy_buf;
|
||||
}
|
||||
|
||||
pc->draw(C, xy[0], xy[1], pc->customdata);
|
||||
GPU_scissor_test(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2738,7 +2738,10 @@ static eHandlerActionFlag wm_handler_fileselect_do(bContext *C,
|
|||
wm_window_make_drawable(wm, root_win);
|
||||
/* Ensure correct cursor position, otherwise, popups may close immediately after
|
||||
* opening (#UI_BLOCK_MOVEMOUSE_QUIT). */
|
||||
wm_cursor_position_get(root_win, &eventstate->xy[0], &eventstate->xy[1]);
|
||||
int xy[2];
|
||||
if (wm_cursor_position_get(root_win, &xy[0], &xy[1])) {
|
||||
copy_v2_v2_int(eventstate->xy, xy);
|
||||
}
|
||||
wm->winactive = root_win; /* Reports use this... */
|
||||
}
|
||||
else if (file_area->full) {
|
||||
|
|
|
@ -1326,12 +1326,12 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
|
|||
case GHOST_kEventButtonUp: {
|
||||
GHOST_TEventButtonData *bd = reinterpret_cast<GHOST_TEventButtonData *>(
|
||||
GHOST_GetEventData(evt));
|
||||
int cx, cy, sizex, sizey, inside_window;
|
||||
|
||||
GHOST_GetCursorPosition(ghost_system, ghost_window, &cx, &cy);
|
||||
int cx, cy, sizex, sizey;
|
||||
playanim_window_get_size(ghost_window, &sizex, &sizey);
|
||||
|
||||
inside_window = (cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey);
|
||||
const bool inside_window = (GHOST_GetCursorPosition(ghost_system, ghost_window, &cx, &cy) ==
|
||||
GHOST_kSuccess) &&
|
||||
(cx >= 0 && cx < sizex && cy >= 0 && cy <= sizey);
|
||||
|
||||
if (bd->button == GHOST_kButtonMaskLeft) {
|
||||
if (type == GHOST_kEventButtonDown) {
|
||||
|
@ -1378,12 +1378,12 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void)
|
|||
* however the API currently doesn't support this. */
|
||||
{
|
||||
int x_test, y_test;
|
||||
GHOST_GetCursorPosition(ghost_system, ghost_window, &cx, &cy);
|
||||
GHOST_ScreenToClient(ghost_window, cd->x, cd->y, &x_test, &y_test);
|
||||
|
||||
if (cx != x_test || cy != y_test) {
|
||||
/* we're not the last event... skipping */
|
||||
break;
|
||||
if (GHOST_GetCursorPosition(ghost_system, ghost_window, &cx, &cy) == GHOST_kSuccess) {
|
||||
GHOST_ScreenToClient(ghost_window, cd->x, cd->y, &x_test, &y_test);
|
||||
if (cx != x_test || cy != y_test) {
|
||||
/* we're not the last event... skipping */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -663,7 +663,10 @@ static void wm_window_update_eventstate_modifiers_clear(wmWindowManager *wm, wmW
|
|||
static void wm_window_update_eventstate(wmWindow *win)
|
||||
{
|
||||
/* Update mouse position when a window is activated. */
|
||||
wm_cursor_position_get(win, &win->eventstate->xy[0], &win->eventstate->xy[1]);
|
||||
int xy[2];
|
||||
if (wm_cursor_position_get(win, &xy[0], &xy[1])) {
|
||||
copy_v2_v2_int(win->eventstate->xy, xy);
|
||||
}
|
||||
}
|
||||
|
||||
static void wm_window_ensure_eventstate(wmWindow *win)
|
||||
|
@ -1181,15 +1184,22 @@ void wm_cursor_position_to_ghost_screen_coords(wmWindow *win, int *x, int *y)
|
|||
GHOST_ClientToScreen(static_cast<GHOST_WindowHandle>(win->ghostwin), *x, *y, x, y);
|
||||
}
|
||||
|
||||
void wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y)
|
||||
bool wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y)
|
||||
{
|
||||
if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) {
|
||||
*r_x = win->eventstate->xy[0];
|
||||
*r_y = win->eventstate->xy[1];
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
GHOST_GetCursorPosition(g_system, static_cast<GHOST_WindowHandle>(win->ghostwin), r_x, r_y);
|
||||
wm_cursor_position_from_ghost_client_coords(win, r_x, r_y);
|
||||
|
||||
if (GHOST_GetCursorPosition(
|
||||
g_system, static_cast<GHOST_WindowHandle>(win->ghostwin), r_x, r_y) == GHOST_kSuccess)
|
||||
{
|
||||
wm_cursor_position_from_ghost_client_coords(win, r_x, r_y);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Check if specified modifier key type is pressed. */
|
||||
|
|
|
@ -104,7 +104,7 @@ void wm_window_swap_buffers(wmWindow *win);
|
|||
void wm_window_set_swap_interval(wmWindow *win, int interval);
|
||||
bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
|
||||
|
||||
void wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y);
|
||||
bool wm_cursor_position_get(wmWindow *win, int *r_x, int *r_y) ATTR_WARN_UNUSED_RESULT;
|
||||
void wm_cursor_position_from_ghost_screen_coords(wmWindow *win, int *r_x, int *r_y);
|
||||
void wm_cursor_position_to_ghost_screen_coords(wmWindow *win, int *x, int *y);
|
||||
|
||||
|
|
Loading…
Reference in New Issue