Fixed bug 3974 - Fix SDL_WarpMouseInWindow on both KMSDRM and RaspberryPi drivers
authorSam Lantinga <slouken@libsdl.org>
Mon, 04 Dec 2017 20:37:01 -0800
changeset 1172473826bd39748
parent 11723 bc7ca7cfa6ca
child 11725 5dc2ef223b08
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
src/video/raspberry/SDL_rpimouse.c
     1.1 --- a/src/video/kmsdrm/SDL_kmsdrmmouse.c	Mon Dec 04 20:35:01 2017 -0800
     1.2 +++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c	Mon Dec 04 20:37:01 2017 -0800
     1.3 @@ -423,8 +423,13 @@
     1.4      SDL_Mouse *mouse = SDL_GetMouse();
     1.5  
     1.6      if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
     1.7 +        /* Update internal mouse position. */
     1.8 +        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);
     1.9 +
    1.10 +        /* And now update the cursor graphic position on screen. */
    1.11          curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
    1.12          if (curdata->bo != NULL) {
    1.13 +
    1.14              if (curdata->crtc_id != 0) {
    1.15                  int ret, drm_fd;
    1.16                  drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo));
    1.17 @@ -475,7 +480,20 @@
    1.18  KMSDRM_MoveCursor(SDL_Cursor * cursor)
    1.19  {
    1.20      SDL_Mouse *mouse = SDL_GetMouse();
    1.21 -    KMSDRM_WarpMouse(mouse->focus, mouse->x, mouse->y);
    1.22 +    KMSDRM_CursorData *curdata;
    1.23 +    int drm_fd, ret;
    1.24 +
    1.25 +    /* We must NOT call SDL_SendMouseMotion() here or we will enter recursivity!
    1.26 +       That's why we move the cursor graphic ONLY. */
    1.27 +    if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
    1.28 +        curdata = (KMSDRM_CursorData *) mouse->cur_cursor->driverdata;
    1.29 +	drm_fd = KMSDRM_gbm_device_get_fd(KMSDRM_gbm_bo_get_device(curdata->bo));
    1.30 +	ret = KMSDRM_drmModeMoveCursor(drm_fd, curdata->crtc_id, mouse->x, mouse->y);
    1.31 +
    1.32 +	if (ret) {
    1.33 +	    SDL_SetError("drmModeMoveCursor() failed.");
    1.34 +	}
    1.35 +    }
    1.36  }
    1.37  
    1.38  #endif /* SDL_VIDEO_DRIVER_KMSDRM */
     2.1 --- a/src/video/raspberry/SDL_rpimouse.c	Mon Dec 04 20:35:01 2017 -0800
     2.2 +++ b/src/video/raspberry/SDL_rpimouse.c	Mon Dec 04 20:37:01 2017 -0800
     2.3 @@ -247,6 +247,65 @@
     2.4          return 0;
     2.5      }
     2.6  
     2.7 +    /* Update internal mouse position. */
     2.8 +    SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);
     2.9 +
    2.10 +    curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
    2.11 +    if (curdata->element == DISPMANX_NO_HANDLE) {
    2.12 +        return 0;
    2.13 +    }
    2.14 +
    2.15 +    update = vc_dispmanx_update_start(10);
    2.16 +    if (!update) {
    2.17 +        return 0;
    2.18 +    }
    2.19 +
    2.20 +    src_rect.x = 0;
    2.21 +    src_rect.y = 0;
    2.22 +    src_rect.width  = curdata->w << 16;
    2.23 +    src_rect.height = curdata->h << 16;
    2.24 +    dst_rect.x = x;
    2.25 +    dst_rect.y = y;
    2.26 +    dst_rect.width  = curdata->w;
    2.27 +    dst_rect.height = curdata->h;
    2.28 +
    2.29 +    ret = vc_dispmanx_element_change_attributes(
    2.30 +        update,
    2.31 +        curdata->element,
    2.32 +        0,
    2.33 +        0,
    2.34 +        0,
    2.35 +        &dst_rect,
    2.36 +        &src_rect,
    2.37 +        DISPMANX_NO_HANDLE,
    2.38 +        DISPMANX_NO_ROTATE);
    2.39 +    if (ret != DISPMANX_SUCCESS) {
    2.40 +        return SDL_SetError("vc_dispmanx_element_change_attributes() failed");
    2.41 +    }
    2.42 +
    2.43 +    /* Submit asynchronously, otherwise the peformance suffers a lot */
    2.44 +    ret = vc_dispmanx_update_submit(update, 0, NULL);
    2.45 +    if (ret != DISPMANX_SUCCESS) {
    2.46 +        return SDL_SetError("vc_dispmanx_update_submit() failed");
    2.47 +    }
    2.48 +    return 0;
    2.49 +}
    2.50 +
    2.51 +/* Warp the mouse to (x,y) */
    2.52 +static int
    2.53 +RPI_WarpMouseGlobalGraphicOnly(int x, int y)
    2.54 +{
    2.55 +    RPI_CursorData *curdata;
    2.56 +    DISPMANX_UPDATE_HANDLE_T update;
    2.57 +    int ret;
    2.58 +    VC_RECT_T dst_rect;
    2.59 +    VC_RECT_T src_rect;
    2.60 +    SDL_Mouse *mouse = SDL_GetMouse();
    2.61 +    
    2.62 +    if (mouse == NULL || mouse->cur_cursor == NULL || mouse->cur_cursor->driverdata == NULL) {
    2.63 +        return 0;
    2.64 +    }
    2.65 +
    2.66      curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
    2.67      if (curdata->element == DISPMANX_NO_HANDLE) {
    2.68          return 0;
    2.69 @@ -317,7 +376,9 @@
    2.70  RPI_MoveCursor(SDL_Cursor * cursor)
    2.71  {
    2.72      SDL_Mouse *mouse = SDL_GetMouse();
    2.73 -    RPI_WarpMouse(mouse->focus, mouse->x, mouse->y);
    2.74 +    /* We must NOT call SDL_SendMouseMotion() on the next call or we will enter recursivity, 
    2.75 +     * so we create a version of WarpMouseGlobal without it. */
    2.76 +    RPI_WarpMouseGlobalGraphicOnly(mouse->x, mouse->y);
    2.77  }
    2.78  
    2.79  #endif /* SDL_VIDEO_DRIVER_RPI */