Skip to content

Commit 5de705d

Browse files
yunlineMyreMylar
andauthored
mouse.get/set_relative_mode() instead of _sdl2.Window.relative_mouse (#2076)
* add get_relative_mode and set_relative_mode * remove Window.relative_mouse --------- Co-authored-by: Dan Lawrence <[email protected]>
1 parent 9f054e1 commit 5de705d

File tree

8 files changed

+80
-41
lines changed

8 files changed

+80
-41
lines changed

buildconfig/stubs/pygame/mouse.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ def set_cursor(
3333
def set_cursor(hotspot: IntCoordinate, surface: Surface) -> None: ...
3434
def get_cursor() -> Cursor: ...
3535
def set_system_cursor(cursor: int) -> None: ...
36+
def get_relative_mode() -> bool: ...
37+
def set_relative_mode(enable: bool) -> None: ...

docs/reST/ref/mouse.rst

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,31 @@ scroll, such as ``which`` (it will tell you what exact mouse device trigger the
216216

217217
.. ## pygame.mouse.get_cursor ##
218218
219+
.. function:: get_relative_mode
220+
221+
| :sl:`query whether relative mouse mode is enabled`
222+
| :sg:`get_relative_mode() -> bool`
223+
224+
Query whether relative mouse mode is enabled.
225+
226+
.. ## pygame.mouse.get_relative_mode ##
227+
228+
.. function:: set_relative_mode
229+
230+
| :sl:`set relative mouse mode`
231+
| :sg:`set_relative_mode(enable) -> None`
232+
233+
Sets the relative mouse mode state.
234+
While the mouse is in relative mode, the cursor is hidden,
235+
the mouse position is constrained to the window, and pygame
236+
will report continuous relative mouse motion even if the
237+
mouse is at the edge of the window.
238+
239+
*This function will flush any pending mouse motion."*
240+
241+
Calling :func:`pygame.mouse.set_visible` with argument
242+
``True`` will exit relative mouse mode.
243+
244+
.. ## pygame.mouse.set_relative_mode ##
245+
219246
.. ## pygame.mouse ##

docs/reST/ref/sdl2_video.rst

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -179,22 +179,6 @@
179179

180180
.. versionadded:: 2.4.0
181181

182-
.. attribute:: relative_mouse
183-
184-
| :sl:`Get or set the window's relative mouse mode state`
185-
| :sg:`relative_mouse -> bool`
186-
187-
Gets or sets the window's relative mouse mode state.
188-
SDL2 docs: *"While the mouse is in relative mode, the cursor is hidden,
189-
the mouse position is constrained to the window, and SDL will report
190-
continuous relative mouse motion even if the mouse is at the edge of the
191-
window.*
192-
193-
*This function will flush any pending mouse motion."*
194-
195-
Calling :func:`pygame.mouse.set_visible` with argument
196-
``True`` will exit relative mouse mode.
197-
198182
.. attribute:: title
199183

200184
| :sl:`Get or set the window title`

src_c/doc/mouse_doc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@
99
#define DOC_MOUSE_GETFOCUSED "get_focused() -> bool\ncheck if the display is receiving mouse input"
1010
#define DOC_MOUSE_SETCURSOR "set_cursor(pygame.cursors.Cursor) -> None\nset_cursor(size, hotspot, xormasks, andmasks) -> None\nset_cursor(hotspot, surface) -> None\nset_cursor(constant) -> None\nset the mouse cursor to a new cursor"
1111
#define DOC_MOUSE_GETCURSOR "get_cursor() -> pygame.cursors.Cursor\nget the current mouse cursor"
12+
#define DOC_MOUSE_GETRELATIVEMODE "get_relative_mode() -> bool\nquery whether relative mouse mode is enabled"
13+
#define DOC_MOUSE_SETRELATIVEMODE "set_relative_mode(enable) -> None\nset relative mouse mode"

src_c/doc/sdl2_video_doc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
#define DOC_SDL2_VIDEO_WINDOW_GRABKEYBOARD "grab_keyboard -> bool\nGet or set the window's keyboard grab mode"
1010
#define DOC_SDL2_VIDEO_WINDOW_MOUSEGRABBED "mouse_grabbed -> bool\nGet if the mouse cursor is confined to the window (**read-only**)"
1111
#define DOC_SDL2_VIDEO_WINDOW_KEYBOARDGRABBED "keyboard_grabbed -> bool\nGet if the keyboard shortcuts are captured by the window (**read-only**)"
12-
#define DOC_SDL2_VIDEO_WINDOW_RELATIVEMOUSE "relative_mouse -> bool\nGet or set the window's relative mouse mode state"
1312
#define DOC_SDL2_VIDEO_WINDOW_TITLE "title -> str\nGet or set the window title"
1413
#define DOC_SDL2_VIDEO_WINDOW_RESIZABLE "resizable -> bool\nGet or set whether the window is resizable"
1514
#define DOC_SDL2_VIDEO_WINDOW_BORDERLESS "borderless -> bool\nGet or set whether the window is borderless"

src_c/mouse.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ mouse_get_visible(PyObject *self, PyObject *_null)
215215

216216
VIDEO_INIT_CHECK();
217217

218-
result = PG_CursorVisible();
218+
result = (PG_CursorVisible() && !SDL_GetRelativeMouseMode());
219219

220220
if (0 > result) {
221221
return RAISE(pgExc_SDLError, SDL_GetError());
@@ -472,6 +472,25 @@ mouse_get_cursor(PyObject *self, PyObject *_null)
472472
return RAISE(pgExc_SDLError, "Cursor not found");
473473
}
474474

475+
static PyObject *
476+
mouse_get_relative_mode(PyObject *self)
477+
{
478+
return PyBool_FromLong(SDL_GetRelativeMouseMode());
479+
}
480+
481+
static PyObject *
482+
mouse_set_relative_mode(PyObject *self, PyObject *arg)
483+
{
484+
int mode = PyObject_IsTrue(arg);
485+
if (mode == -1) {
486+
return NULL;
487+
}
488+
if (SDL_SetRelativeMouseMode((SDL_bool)mode)) {
489+
return RAISE(pgExc_SDLError, SDL_GetError());
490+
}
491+
Py_RETURN_NONE;
492+
}
493+
475494
static PyMethodDef _mouse_methods[] = {
476495
{"set_pos", mouse_set_pos, METH_VARARGS, DOC_MOUSE_SETPOS},
477496
{"get_pos", (PyCFunction)mouse_get_pos, METH_NOARGS, DOC_MOUSE_GETPOS},
@@ -485,6 +504,10 @@ static PyMethodDef _mouse_methods[] = {
485504
{"set_system_cursor", mouse_set_system_cursor, METH_VARARGS,
486505
"set_system_cursor(constant) -> None\nset the mouse cursor to a system "
487506
"variant"},
507+
{"get_relative_mode", (PyCFunction)mouse_get_relative_mode, METH_NOARGS,
508+
DOC_MOUSE_GETRELATIVEMODE},
509+
{"set_relative_mode", (PyCFunction)mouse_set_relative_mode, METH_O,
510+
DOC_MOUSE_SETRELATIVEMODE},
488511
{"_set_cursor", (PyCFunction)mouse_set_cursor,
489512
METH_VARARGS | METH_KEYWORDS, "Internal API for mouse.set_cursor"},
490513
{"_get_cursor", (PyCFunction)mouse_get_cursor, METH_NOARGS,

src_c/window.c

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -711,26 +711,6 @@ window_get_display_index(pgWindowObject *self, PyObject *_null)
711711
return PyLong_FromLong(index);
712712
}
713713

714-
static PyObject *
715-
mouse_get_relative_mode(pgWindowObject *self, void *v)
716-
{
717-
return PyBool_FromLong(SDL_GetRelativeMouseMode());
718-
}
719-
720-
static int
721-
mouse_set_relative_mode(pgWindowObject *self, PyObject *arg, void *v)
722-
{
723-
SDL_bool mode = SDL_FALSE;
724-
if (PyObject_IsTrue(arg)) {
725-
mode = SDL_TRUE;
726-
}
727-
if (SDL_SetRelativeMouseMode(mode)) {
728-
PyErr_SetString(pgExc_SDLError, SDL_GetError());
729-
return -1;
730-
}
731-
return 0;
732-
}
733-
734714
static void
735715
window_dealloc(pgWindowObject *self, PyObject *_null)
736716
{
@@ -1081,9 +1061,6 @@ static PyGetSetDef _window_getset[] = {
10811061
{"always_on_top", (getter)window_get_always_on_top,
10821062
(setter)window_set_always_on_top, DOC_SDL2_VIDEO_WINDOW_ALWAYSONTOP,
10831063
NULL},
1084-
{"relative_mouse", (getter)mouse_get_relative_mode,
1085-
(setter)mouse_set_relative_mode, DOC_SDL2_VIDEO_WINDOW_RELATIVEMOUSE,
1086-
NULL},
10871064
{"mouse_rect", (getter)window_get_mouse_rect,
10881065
(setter)window_set_mouse_rect, DOC_SDL2_VIDEO_WINDOW_MOUSERECT, NULL},
10891066
{"size", (getter)window_get_size, (setter)window_set_size,

test/mouse_test.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,31 @@ def test_set_visible__invalid_value(self):
341341
with self.assertRaises(TypeError):
342342
prev_visible = pygame.mouse.set_visible(invalid_value)
343343

344+
@unittest.skipIf(
345+
os.environ.get("SDL_VIDEODRIVER", "") == "dummy",
346+
"mouse.set_relative_mode requires non-null video driver",
347+
)
348+
def test_set_relative_mode(self):
349+
"""Tests that set_relative_mode hides the cursor."""
350+
pygame.mouse.set_visible(True)
351+
pygame.mouse.set_relative_mode(True) # sets the mouse invisible
352+
visible = pygame.mouse.get_visible()
353+
self.assertEqual(visible, False)
354+
pygame.mouse.set_relative_mode(False) # sets the mouse visible
355+
visible = pygame.mouse.get_visible()
356+
self.assertEqual(visible, True)
357+
358+
@unittest.skipIf(
359+
os.environ.get("SDL_VIDEODRIVER", "") == "dummy",
360+
"mouse.set_relative_mode requires non-null video driver",
361+
)
362+
def test_get_relative_mode(self):
363+
"""Tests that get_relative_mode correctly reports the relative mode"""
364+
pygame.mouse.set_relative_mode(True)
365+
self.assertEqual(pygame.mouse.get_relative_mode(), True)
366+
pygame.mouse.set_relative_mode(False)
367+
self.assertEqual(pygame.mouse.get_relative_mode(), False)
368+
344369

345370
################################################################################
346371

0 commit comments

Comments
 (0)