Added a hint to capture the mouse when mouse buttons are pressed, defaulting on Fixes https://github.com/libsdl-org/SDL/issues/5301
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index ec324f9..25383b1 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -970,6 +970,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.
*
* This hint only applies to Unix-like platforms, and should set before
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 0e6de72..2e88ee7 100644
--- a/src/events/SDL_mouse.c
+++ b/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
diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h
index b7fb9fd..7b02044 100644
--- a/src/events/SDL_mouse_c.h
+++ b/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;