Skip to content

Commit 582b639

Browse files
authored
Merge pull request #2816 from Damus666/display-getset-window-pos
Add pygame.display.get/set_window_position()
2 parents 235b675 + cc4f6bb commit 582b639

File tree

5 files changed

+73
-0
lines changed

5 files changed

+73
-0
lines changed

buildconfig/stubs/pygame/display.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ def get_caption() -> Tuple[str, str]: ...
8282
def set_palette(palette: Sequence[ColorValue], /) -> None: ...
8383
def get_num_displays() -> int: ...
8484
def get_window_size() -> Tuple[int, int]: ...
85+
def get_window_position() -> Tuple[int, int]:...
86+
def set_window_position(position: Coordinate) -> None:...
8587
def get_allow_screensaver() -> bool: ...
8688
def set_allow_screensaver(value: bool = True) -> None: ...
8789
def get_desktop_sizes() -> List[Tuple[int, int]]: ...

docs/reST/ref/display.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -724,6 +724,31 @@ required).
724724

725725
.. ## pygame.display.get_window_size ##
726726
727+
.. function:: get_window_position
728+
729+
| :sl:`Return the position of the window or screen`
730+
| :sg:`get_window_position() -> tuple`
731+
732+
Returns the position of the window initialized with :func:`pygame.display.set_mode()`.
733+
The position will change when the user moves the window or when the position is set manually with :func:`pygame.display.set_window_position()`.
734+
Coordinates could be negative or outside the desktop size bounds.
735+
The position is relative to the topleft of the primary monitor and the y coordinate ignores the window frame.
736+
737+
.. ## pygame.display.get_window_position ##
738+
739+
.. function:: set_window_position
740+
741+
| :sl:`Set the current window position`
742+
| :sg:`set_window_position((x, y)) -> None`
743+
744+
Sets the position of the window initialized with :func:`pygame.display.set_mode()`.
745+
This differs from updating environment variables as this function can be called after the display has been initialised.
746+
The position is expected to be relative to the topleft of the primary monitor.
747+
The y coordinate will ignore the window frame (y = 0 means the frame is hidden).
748+
The user will still be able to move the window after this call. See also :func:`pygame.display.get_window_position()`.
749+
750+
.. ## pygame.display.set_window_position ##
751+
727752
.. function:: get_allow_screensaver
728753

729754
| :sl:`Return whether the screensaver is allowed to run.`

src_c/display.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,39 @@ pg_window_size(PyObject *self, PyObject *_null)
14301430
return pg_tuple_couple_from_values_int(w, h);
14311431
}
14321432

1433+
static PyObject *
1434+
pg_get_window_position(PyObject *self, PyObject *_null)
1435+
{
1436+
SDL_Window *win = pg_GetDefaultWindow();
1437+
int x, y = 0;
1438+
if (!win)
1439+
return RAISE(pgExc_SDLError, "No open window");
1440+
SDL_GetWindowPosition(win, &x, &y);
1441+
return pg_tuple_couple_from_values_int(x, y);
1442+
}
1443+
1444+
static PyObject *
1445+
pg_set_window_position(PyObject *self, PyObject *arg)
1446+
{
1447+
SDL_Window *win = pg_GetDefaultWindow();
1448+
PyObject *pos = NULL;
1449+
int x, y = 0;
1450+
1451+
if (!PyArg_ParseTuple(arg, "O", &pos))
1452+
return NULL;
1453+
1454+
if (pos != NULL) {
1455+
if (!pg_TwoIntsFromObj(pos, &x, &y))
1456+
return RAISE(PyExc_TypeError, "position must be two numbers");
1457+
}
1458+
1459+
if (win)
1460+
/* Will raise errors with SDL 3, deal with it during the porting */
1461+
SDL_SetWindowPosition(win, x, y);
1462+
1463+
Py_RETURN_NONE;
1464+
}
1465+
14331466
static PyObject *
14341467
pg_mode_ok(PyObject *self, PyObject *args, PyObject *kwds)
14351468
{
@@ -2888,6 +2921,10 @@ static PyMethodDef _pg_display_methods[] = {
28882921
DOC_DISPLAY_GETSURFACE},
28892922
{"get_window_size", (PyCFunction)pg_window_size, METH_NOARGS,
28902923
DOC_DISPLAY_GETWINDOWSIZE},
2924+
{"set_window_position", pg_set_window_position, METH_VARARGS,
2925+
DOC_DISPLAY_SETWINDOWPOSITION},
2926+
{"get_window_position", (PyCFunction)pg_get_window_position, METH_NOARGS,
2927+
DOC_DISPLAY_GETWINDOWPOSITION},
28912928

28922929
{"set_mode", (PyCFunction)pg_set_mode, METH_VARARGS | METH_KEYWORDS,
28932930
DOC_DISPLAY_SETMODE},

src_c/doc/display_doc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
#define DOC_DISPLAY_SETPALETTE "set_palette(palette=None, /) -> None\nSet the display color palette for indexed displays"
2727
#define DOC_DISPLAY_GETNUMDISPLAYS "get_num_displays() -> int\nReturn the number of displays"
2828
#define DOC_DISPLAY_GETWINDOWSIZE "get_window_size() -> tuple\nReturn the size of the window or screen"
29+
#define DOC_DISPLAY_GETWINDOWPOSITION "get_window_position() -> tuple\nReturn the position of the window or screen"
30+
#define DOC_DISPLAY_SETWINDOWPOSITION "set_window_position((x, y)) -> None\nSet the current window position"
2931
#define DOC_DISPLAY_GETALLOWSCREENSAVER "get_allow_screensaver() -> bool\nReturn whether the screensaver is allowed to run."
3032
#define DOC_DISPLAY_SETALLOWSCREENSAVER "set_allow_screensaver(bool) -> None\nSet whether the screensaver may run"
3133
#define DOC_DISPLAY_ISFULLSCREEN "is_fullscreen() -> bool\nReturns True if the pygame window created by pygame.display.set_mode() is in full-screen mode"

test/display_test.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,13 @@ def test_toggle_fullscreen(self):
679679
(test_surf.get_width(), test_surf.get_height()), width_height
680680
)
681681

682+
def test_get_set_window_position(self):
683+
pygame.display.set_mode((500, 500))
684+
pygame.display.set_window_position((420, 360))
685+
position = pygame.display.get_window_position()
686+
self.assertEqual(position[0], 420)
687+
self.assertEqual(position[1], 360)
688+
682689

683690
class DisplayUpdateTest(unittest.TestCase):
684691
def question(self, qstr):

0 commit comments

Comments
 (0)