src/events/SDL_mouse.c
changeset 8071 1ac2db4abe11
parent 8066 658b461d81be
child 8093 b43765095a6f
     1.1 --- a/src/events/SDL_mouse.c	Mon Dec 23 17:15:32 2013 -0800
     1.2 +++ b/src/events/SDL_mouse.c	Mon Dec 23 17:37:22 2013 -0800
     1.3 @@ -23,6 +23,7 @@
     1.4  /* General mouse handling code for SDL */
     1.5  
     1.6  #include "SDL_assert.h"
     1.7 +#include "SDL_hints.h"
     1.8  #include "SDL_timer.h"
     1.9  #include "SDL_events.h"
    1.10  #include "SDL_events_c.h"
    1.11 @@ -205,12 +206,24 @@
    1.12      int yrel;
    1.13      int x_max = 0, y_max = 0;
    1.14  
    1.15 -    /* relative motion is calculated regarding the system cursor last position */
    1.16 +    if (mouse->relative_mode_warp) {
    1.17 +        int center_x = 0, center_y = 0;
    1.18 +        SDL_GetWindowSize(window, &center_x, &center_y);
    1.19 +        center_x /= 2;
    1.20 +        center_y /= 2;
    1.21 +        if (x == center_x && y == center_y) {
    1.22 +            mouse->last_x = center_x;
    1.23 +            mouse->last_y = center_y;
    1.24 +            return 0;
    1.25 +        }
    1.26 +        SDL_WarpMouseInWindow(window, center_x, center_y);
    1.27 +    }
    1.28 +
    1.29      if (relative) {
    1.30          xrel = x;
    1.31          yrel = y;
    1.32 -        x = (mouse->last_x + x);
    1.33 -        y = (mouse->last_y + y);
    1.34 +        x = (mouse->last_x + xrel);
    1.35 +        y = (mouse->last_y + yrel);
    1.36      } else {
    1.37          xrel = x - mouse->last_x;
    1.38          yrel = y - mouse->last_y;
    1.39 @@ -225,7 +238,7 @@
    1.40      }
    1.41  
    1.42      /* Update internal mouse coordinates */
    1.43 -    if (mouse->relative_mode == SDL_FALSE) {
    1.44 +    if (!mouse->relative_mode) {
    1.45          mouse->x = x;
    1.46          mouse->y = y;
    1.47      } else {
    1.48 @@ -481,21 +494,36 @@
    1.49      }
    1.50  }
    1.51  
    1.52 +static SDL_bool
    1.53 +ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
    1.54 +{
    1.55 +    const char *hint;
    1.56 +
    1.57 +    if (!mouse->SetRelativeMouseMode) {
    1.58 +        return SDL_TRUE;
    1.59 +    }
    1.60 +
    1.61 +    hint = SDL_GetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP);
    1.62 +    if (hint) {
    1.63 +        if (*hint == '0') {
    1.64 +            return SDL_FALSE;
    1.65 +        } else {
    1.66 +            return SDL_TRUE;
    1.67 +        }
    1.68 +    }
    1.69 +    return SDL_FALSE;
    1.70 +}
    1.71 +
    1.72  int
    1.73  SDL_SetRelativeMouseMode(SDL_bool enabled)
    1.74  {
    1.75      SDL_Mouse *mouse = SDL_GetMouse();
    1.76      SDL_Window *focusWindow = SDL_GetKeyboardFocus();
    1.77 -    int original_x = mouse->x, original_y = mouse->y;
    1.78  
    1.79      if (enabled == mouse->relative_mode) {
    1.80          return 0;
    1.81      }
    1.82  
    1.83 -    if (!mouse->SetRelativeMouseMode) {
    1.84 -        return SDL_Unsupported();
    1.85 -    }
    1.86 -
    1.87      if (enabled && focusWindow) {
    1.88          /* Center it in the focused window to prevent clicks from going through
    1.89           * to background windows.
    1.90 @@ -504,23 +532,26 @@
    1.91          SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
    1.92      }
    1.93  
    1.94 -    if (mouse->SetRelativeMouseMode(enabled) < 0) {
    1.95 +    /* Set the relative mode */
    1.96 +    if (!enabled && mouse->relative_mode_warp) {
    1.97 +        mouse->relative_mode_warp = SDL_FALSE;
    1.98 +    } else if (enabled && ShouldUseRelativeModeWarp(mouse)) {
    1.99 +        mouse->relative_mode_warp = SDL_TRUE;
   1.100 +    } else if (mouse->SetRelativeMouseMode(enabled) < 0) {
   1.101          return -1;
   1.102      }
   1.103 -
   1.104 -    /* Set the relative mode */
   1.105      mouse->relative_mode = enabled;
   1.106  
   1.107 -    if (enabled) {
   1.108 -        /* Save the expected mouse position */
   1.109 -        mouse->original_x = original_x;
   1.110 -        mouse->original_y = original_y;
   1.111 -    } else if (mouse->focus) {
   1.112 -        /* Restore the expected mouse position */
   1.113 -        SDL_WarpMouseInWindow(mouse->focus, mouse->original_x, mouse->original_y);
   1.114 +    if (mouse->focus) {
   1.115 +        SDL_UpdateWindowGrab(mouse->focus);
   1.116 +
   1.117 +        /* Put the cursor back to where the application expects it */
   1.118 +        if (!enabled) {
   1.119 +            SDL_WarpMouseInWindow(mouse->focus, mouse->x, mouse->y);
   1.120 +        }
   1.121      }
   1.122  
   1.123 -    /* Flush pending mouse motion */
   1.124 +    /* Flush pending mouse motion - ideally we would pump events, but that's not always safe */
   1.125      SDL_FlushEvent(SDL_MOUSEMOTION);
   1.126  
   1.127      /* Update cursor visibility */