ソースを参照

Added a hint to capture the mouse when mouse buttons are pressed, defaulting on

Fixes https://github.com/libsdl-org/SDL/issues/5301
Sam Lantinga 3 年 前
コミット
5ff42438e3
3 ファイル変更58 行追加14 行削除
  1. 13 0
      include/SDL_hints.h
  2. 44 14
      src/events/SDL_mouse.c
  3. 1 0
      src/events/SDL_mouse_c.h

+ 13 - 0
include/SDL_hints.h

@@ -969,6 +969,19 @@ extern "C" {
  */
 #define SDL_HINT_MOUSE_TOUCH_EVENTS    "SDL_MOUSE_TOUCH_EVENTS"
 
+/**
+ *  \brief  A variable controlling whether the mouse is captured while mouse buttons are pressed
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - The mouse is not captured while mouse buttons are pressed
+ *    "1"       - The mouse is captured while mouse buttons are pressed
+ *
+ *  By default the mouse is captured while mouse buttons are pressed so if the mouse is dragged
+ *  outside the window, the application continues to receive mouse events until the button is
+ *  released.
+ */
+#define SDL_HINT_MOUSE_AUTO_CAPTURE    "SDL_MOUSE_AUTO_CAPTURE"
+
 /**
  *  \brief Tell SDL not to catch the SIGINT or SIGTERM signals.
  *

+ 44 - 14
src/events/SDL_mouse.c

@@ -127,6 +127,22 @@ SDL_MouseTouchEventsChanged(void *userdata, const char *name, const char *oldVal
     }
 }
 
+static void SDLCALL
+SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+    SDL_Mouse *mouse = (SDL_Mouse *)userdata;
+    SDL_bool auto_capture = SDL_GetStringBoolean(hint, SDL_TRUE);
+
+    if (auto_capture != mouse->auto_capture) {
+        /* Turn off mouse capture if it's currently active because of button presses */
+        if (!auto_capture && SDL_GetMouseState(NULL, NULL) != 0) {
+            SDL_CaptureMouse(SDL_FALSE);
+        }
+
+        mouse->auto_capture = auto_capture;
+    }
+}
+
 /* Public functions */
 int
 SDL_MouseInit(void)
@@ -153,6 +169,9 @@ SDL_MouseInit(void)
     SDL_AddHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
                         SDL_MouseTouchEventsChanged, mouse);
 
+    SDL_AddHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
+                        SDL_MouseAutoCaptureChanged, mouse);
+
     mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */
 
     mouse->cursor_shown = SDL_TRUE;
@@ -248,20 +267,7 @@ SDL_UpdateMouseFocus(SDL_Window * window, int x, int y, Uint32 buttonstate, SDL_
         }
     }
 
-/* Linux doesn't give you mouse events outside your window unless you grab
-   the pointer.
-
-   Windows doesn't give you mouse events outside your window unless you call
-   SetCapture().
-
-   Both of these are slightly scary changes, so for now we'll punt and if the
-   mouse leaves the window you'll lose mouse focus and reset button state.
-*/
-#ifdef SUPPORT_DRAG_OUTSIDE_WINDOW
-    if (!inWindow && !buttonstate) {
-#else
     if (!inWindow) {
-#endif
         if (window == mouse->focus) {
 #ifdef DEBUG_MOUSE
             SDL_Log("Mouse left window, synthesizing move & focus lost event\n");
@@ -534,7 +540,8 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
     Uint32 type;
     Uint32 buttonstate;
     SDL_MouseInputSource *source;
-   
+    SDL_bool had_buttons_pressed = (SDL_GetMouseState(NULL, NULL) ? SDL_TRUE : SDL_FALSE);
+
     source = GetMouseInputSource(mouse, mouseID);
     if (!source) {
         return 0;
@@ -634,6 +641,14 @@ SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state
         SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate, SDL_TRUE);
     }
 
+    /* Automatically capture the mouse while buttons are pressed */
+    if (mouse->auto_capture) {
+        SDL_bool has_buttons_pressed = (SDL_GetMouseState(NULL, NULL) ? SDL_TRUE : SDL_FALSE);
+        if (has_buttons_pressed != had_buttons_pressed) {
+            SDL_CaptureMouse(has_buttons_pressed);
+        }
+    }
+
     return posted;
 }
 
@@ -758,11 +773,26 @@ SDL_MouseQuit(void)
     }
     mouse->num_clickstates = 0;
 
+    SDL_DelHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME,
+                        SDL_MouseDoubleClickTimeChanged, mouse);
+
+    SDL_DelHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS,
+                        SDL_MouseDoubleClickRadiusChanged, mouse);
+
     SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE,
                         SDL_MouseNormalSpeedScaleChanged, mouse);
 
     SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE,
                         SDL_MouseRelativeSpeedScaleChanged, mouse);
+
+    SDL_DelHintCallback(SDL_HINT_TOUCH_MOUSE_EVENTS,
+                        SDL_TouchMouseEventsChanged, mouse);
+
+    SDL_DelHintCallback(SDL_HINT_MOUSE_TOUCH_EVENTS,
+                        SDL_MouseTouchEventsChanged, mouse);
+
+    SDL_DelHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
+                        SDL_MouseAutoCaptureChanged, mouse);
 }
 
 Uint32

+ 1 - 0
src/events/SDL_mouse_c.h

@@ -100,6 +100,7 @@ typedef struct
     SDL_bool touch_mouse_events;
     SDL_bool mouse_touch_events;
     SDL_bool was_touch_mouse_events; /* Was a touch-mouse event pending? */
+    SDL_bool auto_capture;
 
     /* Data for input source state */
     int num_sources;