Skip to content

Commit

Permalink
mouse.get/set_relative_mode() instead of `_sdl2.Window.relative_mou…
Browse files Browse the repository at this point in the history
…se` (#2076)

* add get_relative_mode and set_relative_mode

* remove Window.relative_mouse


---------

Co-authored-by: Dan Lawrence <[email protected]>
  • Loading branch information
yunline and MyreMylar authored Nov 19, 2023
1 parent 9f054e1 commit 5de705d
Show file tree
Hide file tree
Showing 8 changed files with 80 additions and 41 deletions.
2 changes: 2 additions & 0 deletions buildconfig/stubs/pygame/mouse.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ def set_cursor(
def set_cursor(hotspot: IntCoordinate, surface: Surface) -> None: ...
def get_cursor() -> Cursor: ...
def set_system_cursor(cursor: int) -> None: ...
def get_relative_mode() -> bool: ...
def set_relative_mode(enable: bool) -> None: ...
27 changes: 27 additions & 0 deletions docs/reST/ref/mouse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,31 @@ scroll, such as ``which`` (it will tell you what exact mouse device trigger the

.. ## pygame.mouse.get_cursor ##
.. function:: get_relative_mode

| :sl:`query whether relative mouse mode is enabled`
| :sg:`get_relative_mode() -> bool`
Query whether relative mouse mode is enabled.

.. ## pygame.mouse.get_relative_mode ##
.. function:: set_relative_mode

| :sl:`set relative mouse mode`
| :sg:`set_relative_mode(enable) -> None`
Sets the relative mouse mode state.
While the mouse is in relative mode, the cursor is hidden,
the mouse position is constrained to the window, and pygame
will report continuous relative mouse motion even if the
mouse is at the edge of the window.

*This function will flush any pending mouse motion."*

Calling :func:`pygame.mouse.set_visible` with argument
``True`` will exit relative mouse mode.

.. ## pygame.mouse.set_relative_mode ##
.. ## pygame.mouse ##
16 changes: 0 additions & 16 deletions docs/reST/ref/sdl2_video.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,22 +179,6 @@

.. versionadded:: 2.4.0

.. attribute:: relative_mouse

| :sl:`Get or set the window's relative mouse mode state`
| :sg:`relative_mouse -> bool`
Gets or sets the window's relative mouse mode state.
SDL2 docs: *"While the mouse is in relative mode, the cursor is hidden,
the mouse position is constrained to the window, and SDL will report
continuous relative mouse motion even if the mouse is at the edge of the
window.*

*This function will flush any pending mouse motion."*

Calling :func:`pygame.mouse.set_visible` with argument
``True`` will exit relative mouse mode.

.. attribute:: title

| :sl:`Get or set the window title`
Expand Down
2 changes: 2 additions & 0 deletions src_c/doc/mouse_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@
#define DOC_MOUSE_GETFOCUSED "get_focused() -> bool\ncheck if the display is receiving mouse input"
#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"
#define DOC_MOUSE_GETCURSOR "get_cursor() -> pygame.cursors.Cursor\nget the current mouse cursor"
#define DOC_MOUSE_GETRELATIVEMODE "get_relative_mode() -> bool\nquery whether relative mouse mode is enabled"
#define DOC_MOUSE_SETRELATIVEMODE "set_relative_mode(enable) -> None\nset relative mouse mode"
1 change: 0 additions & 1 deletion src_c/doc/sdl2_video_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#define DOC_SDL2_VIDEO_WINDOW_GRABKEYBOARD "grab_keyboard -> bool\nGet or set the window's keyboard grab mode"
#define DOC_SDL2_VIDEO_WINDOW_MOUSEGRABBED "mouse_grabbed -> bool\nGet if the mouse cursor is confined to the window (**read-only**)"
#define DOC_SDL2_VIDEO_WINDOW_KEYBOARDGRABBED "keyboard_grabbed -> bool\nGet if the keyboard shortcuts are captured by the window (**read-only**)"
#define DOC_SDL2_VIDEO_WINDOW_RELATIVEMOUSE "relative_mouse -> bool\nGet or set the window's relative mouse mode state"
#define DOC_SDL2_VIDEO_WINDOW_TITLE "title -> str\nGet or set the window title"
#define DOC_SDL2_VIDEO_WINDOW_RESIZABLE "resizable -> bool\nGet or set whether the window is resizable"
#define DOC_SDL2_VIDEO_WINDOW_BORDERLESS "borderless -> bool\nGet or set whether the window is borderless"
Expand Down
25 changes: 24 additions & 1 deletion src_c/mouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ mouse_get_visible(PyObject *self, PyObject *_null)

VIDEO_INIT_CHECK();

result = PG_CursorVisible();
result = (PG_CursorVisible() && !SDL_GetRelativeMouseMode());

if (0 > result) {
return RAISE(pgExc_SDLError, SDL_GetError());
Expand Down Expand Up @@ -472,6 +472,25 @@ mouse_get_cursor(PyObject *self, PyObject *_null)
return RAISE(pgExc_SDLError, "Cursor not found");
}

static PyObject *
mouse_get_relative_mode(PyObject *self)
{
return PyBool_FromLong(SDL_GetRelativeMouseMode());
}

static PyObject *
mouse_set_relative_mode(PyObject *self, PyObject *arg)
{
int mode = PyObject_IsTrue(arg);
if (mode == -1) {
return NULL;
}
if (SDL_SetRelativeMouseMode((SDL_bool)mode)) {
return RAISE(pgExc_SDLError, SDL_GetError());
}
Py_RETURN_NONE;
}

static PyMethodDef _mouse_methods[] = {
{"set_pos", mouse_set_pos, METH_VARARGS, DOC_MOUSE_SETPOS},
{"get_pos", (PyCFunction)mouse_get_pos, METH_NOARGS, DOC_MOUSE_GETPOS},
Expand All @@ -485,6 +504,10 @@ static PyMethodDef _mouse_methods[] = {
{"set_system_cursor", mouse_set_system_cursor, METH_VARARGS,
"set_system_cursor(constant) -> None\nset the mouse cursor to a system "
"variant"},
{"get_relative_mode", (PyCFunction)mouse_get_relative_mode, METH_NOARGS,
DOC_MOUSE_GETRELATIVEMODE},
{"set_relative_mode", (PyCFunction)mouse_set_relative_mode, METH_O,
DOC_MOUSE_SETRELATIVEMODE},
{"_set_cursor", (PyCFunction)mouse_set_cursor,
METH_VARARGS | METH_KEYWORDS, "Internal API for mouse.set_cursor"},
{"_get_cursor", (PyCFunction)mouse_get_cursor, METH_NOARGS,
Expand Down
23 changes: 0 additions & 23 deletions src_c/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -711,26 +711,6 @@ window_get_display_index(pgWindowObject *self, PyObject *_null)
return PyLong_FromLong(index);
}

static PyObject *
mouse_get_relative_mode(pgWindowObject *self, void *v)
{
return PyBool_FromLong(SDL_GetRelativeMouseMode());
}

static int
mouse_set_relative_mode(pgWindowObject *self, PyObject *arg, void *v)
{
SDL_bool mode = SDL_FALSE;
if (PyObject_IsTrue(arg)) {
mode = SDL_TRUE;
}
if (SDL_SetRelativeMouseMode(mode)) {
PyErr_SetString(pgExc_SDLError, SDL_GetError());
return -1;
}
return 0;
}

static void
window_dealloc(pgWindowObject *self, PyObject *_null)
{
Expand Down Expand Up @@ -1081,9 +1061,6 @@ static PyGetSetDef _window_getset[] = {
{"always_on_top", (getter)window_get_always_on_top,
(setter)window_set_always_on_top, DOC_SDL2_VIDEO_WINDOW_ALWAYSONTOP,
NULL},
{"relative_mouse", (getter)mouse_get_relative_mode,
(setter)mouse_set_relative_mode, DOC_SDL2_VIDEO_WINDOW_RELATIVEMOUSE,
NULL},
{"mouse_rect", (getter)window_get_mouse_rect,
(setter)window_set_mouse_rect, DOC_SDL2_VIDEO_WINDOW_MOUSERECT, NULL},
{"size", (getter)window_get_size, (setter)window_set_size,
Expand Down
25 changes: 25 additions & 0 deletions test/mouse_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,31 @@ def test_set_visible__invalid_value(self):
with self.assertRaises(TypeError):
prev_visible = pygame.mouse.set_visible(invalid_value)

@unittest.skipIf(
os.environ.get("SDL_VIDEODRIVER", "") == "dummy",
"mouse.set_relative_mode requires non-null video driver",
)
def test_set_relative_mode(self):
"""Tests that set_relative_mode hides the cursor."""
pygame.mouse.set_visible(True)
pygame.mouse.set_relative_mode(True) # sets the mouse invisible
visible = pygame.mouse.get_visible()
self.assertEqual(visible, False)
pygame.mouse.set_relative_mode(False) # sets the mouse visible
visible = pygame.mouse.get_visible()
self.assertEqual(visible, True)

@unittest.skipIf(
os.environ.get("SDL_VIDEODRIVER", "") == "dummy",
"mouse.set_relative_mode requires non-null video driver",
)
def test_get_relative_mode(self):
"""Tests that get_relative_mode correctly reports the relative mode"""
pygame.mouse.set_relative_mode(True)
self.assertEqual(pygame.mouse.get_relative_mode(), True)
pygame.mouse.set_relative_mode(False)
self.assertEqual(pygame.mouse.get_relative_mode(), False)


################################################################################

Expand Down

0 comments on commit 5de705d

Please sign in to comment.