From 47506fe1deeac84f6374a1438ba5dd0e18151bd7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 4 Dec 2017 20:37:01 -0800 Subject: [PATCH] Fixed bug 3974 - Fix SDL_WarpMouseInWindow on both KMSDRM and RaspberryPi drivers Manuel Alfayate Corchete This patch fixes SDL_WarpMouseInWindow() in both the KMSDRM and Raspberry Pi graphic backends. --- src/video/kmsdrm/SDL_kmsdrmmouse.c | 20 +++++++++- src/video/raspberry/SDL_rpimouse.c | 63 +++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c index f834339a0..80fa89f5f 100644 --- a/src/video/kmsdrm/SDL_kmsdrmmouse.c +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c @@ -423,8 +423,13 @@ KMSDRM_WarpMouseGlobal(int x, int y) SDL_Mouse *mouse = SDL_GetMouse(); if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) { + /* Update internal mouse position. */ + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y); + + /* And now update the cursor graphic position on screen. */ curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata; if (curdata->bo != NULL) { + if (curdata->crtc_id != 0) { int ret, drm_fd; drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo)); @@ -475,7 +480,20 @@ static void KMSDRM_MoveCursor(SDL_Cursor * cursor) { SDL_Mouse *mouse = SDL_GetMouse(); - KMSDRM_WarpMouse(mouse->focus, mouse->x, mouse->y); + KMSDRM_CursorData *curdata; + int drm_fd, ret; + + /* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity! + That's why we move the cursor graphic ONLY. */ + if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) { + curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata; + drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo)); + ret = KMSDRM_drmModeMoveCursor(drm_fd, curdata->crtc_id, mouse->x, mouse->y); + + if (ret) { + SDL_SetError("drmModeMoveCursor() failed."); + } + } } #endif /* SDL_VIDEO_DRIVER_KMSDRM */ diff --git a/src/video/raspberry/SDL_rpimouse.c b/src/video/raspberry/SDL_rpimouse.c index 026fbd2fe..4ab9c7788 100644 --- a/src/video/raspberry/SDL_rpimouse.c +++ b/src/video/raspberry/SDL_rpimouse.c @@ -247,6 +247,65 @@ RPI_WarpMouseGlobal(int x, int y) return 0; } + /* Update internal mouse position. */ + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y); + + curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata; + if (curdata->element == DISPMANX_NO_HANDLE) { + return 0; + } + + update = vc_dispmanx_update_start(10); + if (!update) { + return 0; + } + + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = curdata->w << 16; + src_rect.height = curdata->h << 16; + dst_rect.x = x; + dst_rect.y = y; + dst_rect.width = curdata->w; + dst_rect.height = curdata->h; + + ret = vc_dispmanx_element_change_attributes( + update, + curdata->element, + 0, + 0, + 0, + &dst_rect, + &src_rect, + DISPMANX_NO_HANDLE, + DISPMANX_NO_ROTATE); + if (ret != DISPMANX_SUCCESS) { + return SDL_SetError("vc_dispmanx_element_change_attributes() failed"); + } + + /* Submit asynchronously, otherwise the peformance suffers a lot */ + ret = vc_dispmanx_update_submit(update, 0, NULL); + if (ret != DISPMANX_SUCCESS) { + return SDL_SetError("vc_dispmanx_update_submit() failed"); + } + return 0; +} + +/* Warp the mouse to (x,y) */ +static int +RPI_WarpMouseGlobalGraphicOnly(int x, int y) +{ + RPI_CursorData *curdata; + DISPMANX_UPDATE_HANDLE_T update; + int ret; + VC_RECT_T dst_rect; + VC_RECT_T src_rect; + SDL_Mouse *mouse = SDL_GetMouse(); + + if (mouse == NULL || mouse->cur_cursor == NULL || mouse->cur_cursor->driverdata == NULL) { + return 0; + } + curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata; if (curdata->element == DISPMANX_NO_HANDLE) { return 0; @@ -317,7 +376,9 @@ static void RPI_MoveCursor(SDL_Cursor * cursor) { SDL_Mouse *mouse = SDL_GetMouse(); - RPI_WarpMouse(mouse->focus, mouse->x, mouse->y); + /* We must NOT call SDL_SendMouseMotion() on the next call or we will enter recursivity, + * so we create a version of WarpMouseGlobal without it. */ + RPI_WarpMouseGlobalGraphicOnly(mouse->x, mouse->y); } #endif /* SDL_VIDEO_DRIVER_RPI */