Skip to content

Commit

Permalink
Replace it with Window.handle
Browse files Browse the repository at this point in the history
  • Loading branch information
damusss committed Jan 5, 2025
1 parent 44c4184 commit ec3818d
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 203 deletions.
4 changes: 2 additions & 2 deletions buildconfig/stubs/pygame/window.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Tuple, Dict, Union
from typing import Optional, Tuple, Union
from typing_extensions import deprecated # added in 3.13

from pygame.typing import Point, RectLike
Expand Down Expand Up @@ -71,7 +71,7 @@ class Window:
@property
def opengl(self) -> bool: ...
@property
def wm_info(self) -> Dict[str, int]: ...
def handle(self) -> int: ...
@classmethod
@deprecated("since 2.4.0. Use either the display module or the Window class with get_surface and flip. Try not to mix display and Window")
def from_display_module(cls) -> Window: ...
15 changes: 8 additions & 7 deletions docs/reST/ref/window.rst
Original file line number Diff line number Diff line change
Expand Up @@ -289,15 +289,16 @@

.. versionadded:: 2.5.0

.. attribute:: wm_info
.. attribute:: handle

| :sl:`Get information about the current windowing system`
| :sg:`wm_info -> dict`
| :sl:`Get the window handle provided by the window manager if supported otherwise 0`
| :sg:`handle -> int`
Creates a dictionary filled with string keys. The strings and values are
arbitrarily created by the system. Some systems may have no information and
an empty dictionary will be returned. Most platforms will return a "window"
key with the value set to the system id for the window.
Returns the window handle provided by the window manager as an integer. If the operating
system is not supported or the window manager hides the handle the sentinel ``0`` is returned.

The handle is generally available with Windows, X11 (Linux), Cocoa (MacOS), UIKit (iOS),
Android and Vivante while unavailable under Wayland and everything else.

.. versionaddedold:: 2.5.3

Expand Down
2 changes: 1 addition & 1 deletion src_c/doc/window_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#define DOC_WINDOW_POSITION "position -> (int, int) or WINDOWPOS_CENTERED or WINDOWPOS_UNDEFINED\nGet or set the window position in screen coordinates"
#define DOC_WINDOW_OPACITY "opacity -> float\nGet or set the window opacity, between 0.0 (fully transparent) and 1.0 (fully opaque)"
#define DOC_WINDOW_OPENGL "opengl -> bool\nGet if the window supports OpenGL"
#define DOC_WINDOW_WMINFO "wm_info -> dict\nGet information about the current windowing system"
#define DOC_WINDOW_HANDLE "handle -> int\nGet the window handle provided by the window manager if supported otherwise 0"
#define DOC_WINDOW_FROMDISPLAYMODULE "from_display_module() -> Window\nCreate a Window object using window data from display module"
#define DOC_WINDOW_GETSURFACE "get_surface() -> Surface\nGet the window surface"
#define DOC_WINDOW_FLIP "flip() -> None\nUpdate the display surface to the window."
Expand Down
194 changes: 25 additions & 169 deletions src_c/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -784,129 +784,38 @@ window_get_opengl(pgWindowObject *self, void *v)
}

static PyObject *
window_get_wm_info(pgWindowObject *self, void *v)
window_get_handle(pgWindowObject *self, void *v)
{
PyObject *dict;
PyObject *tmp;

dict = PyDict_New();
if (!dict)
return NULL;

SDL_Window *win = self->_win;
size_t handle = 0;

#if SDL_VERSION_ATLEAST(3, 1, 3)
SDL_PropertiesID props = SDL_GetWindowProperties(window);

#if defined(SDL_VIDEO_DRIVER_WINDOWS)
tmp = PyLong_FromLongLong((long long)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL));
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLongLong((long long)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_WIN32_HDC_POINTER, NULL));
PyDict_SetItemString(dict, "hdc", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLongLong((long long)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_WIN32_INSTANCE_POINTER, NULL));
PyDict_SetItemString(dict, "hinstance", tmp);
Py_DECREF(tmp);
handle = (size_t)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, NULL);
#endif
#if defined(SDL_VIDEO_DRIVER_X11)
tmp = PyLong_FromLong((long)SDL_GetNumberProperty(
props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, NULL));
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)SDL_GetNumberProperty(
props, SDL_PROP_WINDOW_X11_SCREEN_NUMBER, NULL));
PyDict_SetItemString(dict, "screen", tmp);
Py_DECREF(tmp);

tmp = PyCapsule_New(SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_X11_DISPLAY_POINTER, NULL),
"display", NULL);
PyDict_SetItemString(dict, "display", tmp);
Py_DECREF(tmp);
handle = (size_t)SDL_GetNumberProperty(
props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, NULL);
#endif
#if defined(SDL_VIDEO_DRIVER_COCOA)
tmp = PyCapsule_New(SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL),
"window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);
handle = (size_t)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, NULL);
#endif
#if defined(SDL_VIDEO_DRIVER_UIKIT)
tmp = PyCapsule_New(SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL),
"window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)SDL_GetNumberProperty(
props, SDL_PROP_WINDOW_UIKIT_OPENGL_FRAMEBUFFER_NUMBER, NULL));
PyDict_SetItemString(dict, "framebuffer", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)SDL_GetNumberProperty(
props, SDL_PROP_WINDOW_UIKIT_OPENGL_RENDERBUFFER_NUMBER, NULL));
PyDict_SetItemString(dict, "colorbuffer", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)SDL_GetNumberProperty(
props, SDL_PROP_WINDOW_UIKIT_OPENGL_RESOLVE_FRAMEBUFFER_NUMBER, NULL));
PyDict_SetItemString(dict, "resolveFramebuffer", tmp);
Py_DECREF(tmp);
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND)
tmp = PyCapsule_New(SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL),
"display", NULL);
PyDict_SetItemString(dict, "display", tmp);
Py_DECREF(tmp);

tmp = PyCapsule_New(SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL),
"surface", NULL);
PyDict_SetItemString(dict, "surface", tmp);
Py_DECREF(tmp);

tmp = PyCapsule_New(
SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_VIEWPORT_POINTER,
NULL),
"viewport", NULL);
PyDict_SetItemString(dict, "viewport", tmp);
Py_DECREF(tmp);
handle = (size_t)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL);
#endif
// wayland does not support window handle
#if defined(SDL_VIDEO_DRIVER_ANDROID)
tmp = PyCapsule_New(SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL),
"window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_ANDROID_SURFACE_POINTER, NULL));
PyDict_SetItemString(dict, "surface", tmp);
Py_DECREF(tmp);
handle = (size_t)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, NULL);
#endif
#if defined(SDL_VIDEO_DRIVER_VIVANTE)
tmp = PyLong_FromLong((long)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_VIVANTE_DISPLAY_POINTER, NULL));
PyDict_SetItemString(dict, "display", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER, NULL));
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_VIVANTE_SURFACE_POINTER, NULL));
PyDict_SetItemString(dict, "surface", tmp);
Py_DECREF(tmp);
handle = (size_t)SDL_GetPointerProperty(
props, SDL_PROP_WINDOW_VIVANTE_WINDOW_POINTER, NULL);
#endif

#else // sdl 2
Expand All @@ -915,85 +824,32 @@ window_get_wm_info(pgWindowObject *self, void *v)
SDL_VERSION(&(info.version))

if (!SDL_GetWindowWMInfo(win, &info))
return dict;
return PyLong_FromLong(0);

(void)tmp;
#if defined(SDL_VIDEO_DRIVER_WINDOWS)
tmp = PyLong_FromLongLong((long long)info.info.win.window);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLongLong((long long)info.info.win.hdc);
PyDict_SetItemString(dict, "hdc", tmp);
Py_DECREF(tmp);
tmp = PyLong_FromLongLong((long long)info.info.win.hinstance);
PyDict_SetItemString(dict, "hinstance", tmp);
Py_DECREF(tmp);
handle = (size_t)info.info.win.window;
#endif
// WINRT window handle not supported in SDL3
#if defined(SDL_VIDEO_DRIVER_X11)
tmp = PyLong_FromLong(info.info.x11.window);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyCapsule_New(info.info.x11.display, "display", NULL);
PyDict_SetItemString(dict, "display", tmp);
Py_DECREF(tmp);
handle = (size_t)info.info.x11.window;
#endif
// DIRECTFB wm info not supported in SDL3
#if defined(SDL_VIDEO_DRIVER_COCOA)
tmp = PyCapsule_New(info.info.cocoa.window, "window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);
handle = (size_t)info.info.cocoa.window;
#endif
#if defined(SDL_VIDEO_DRIVER_UIKIT)
tmp = PyCapsule_New(info.info.uikit.window, "window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong(info.info.uikit.framebuffer);
PyDict_SetItemString(dict, "framebuffer", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong(info.info.uikit.colorbuffer);
PyDict_SetItemString(dict, "colorbuffer", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong(info.info.uikit.resolveFramebuffer);
PyDict_SetItemString(dict, "resolveFramebuffer", tmp);
Py_DECREF(tmp);
#endif
#if defined(SDL_VIDEO_DRIVER_WAYLAND)
tmp = PyCapsule_New(info.info.wl.display, "display", NULL);
PyDict_SetItemString(dict, "display", tmp);
Py_DECREF(tmp);

tmp = PyCapsule_New(info.info.wl.surface, "surface", NULL);
PyDict_SetItemString(dict, "surface", tmp);
Py_DECREF(tmp);
// shell_surface deprecated in SDL3
handle = (size_t)info.info.uikit.window;
#endif
// wayland does not support window handle
#if defined(SDL_VIDEO_DRIVER_ANDROID)
tmp = PyCapsule_New(info.info.android.window, "window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)info.info.android.surface);
PyDict_SetItemString(dict, "surface", tmp);
Py_DECREF(tmp);
handle = (size_t)info.info.android.window;
#endif
#if defined(SDL_VIDEO_DRIVER_VIVANTE)
tmp = PyLong_FromLong((long)info.info.vivante.display);
PyDict_SetItemString(dict, "display", tmp);
Py_DECREF(tmp);

tmp = PyLong_FromLong((long)info.info.vivante.window);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);
handle = (size_t)info.info.vivante.window;
#endif
#endif // sdl 3

return dict;
return PyLong_FromSize_t(handle);
}

static void
Expand Down Expand Up @@ -1412,7 +1268,7 @@ static PyGetSetDef _window_getset[] = {
DOC_WINDOW_OPACITY, NULL},
{"id", (getter)window_get_window_id, NULL, DOC_WINDOW_ID, NULL},
{"opengl", (getter)window_get_opengl, NULL, DOC_WINDOW_OPENGL, NULL},
{"wm_info", (getter)window_get_wm_info, NULL, DOC_WINDOW_WMINFO, NULL},
{"handle", (getter)window_get_handle, NULL, DOC_WINDOW_HANDLE, NULL},
{NULL, 0, NULL, NULL, NULL} /* Sentinel */
};

Expand Down
26 changes: 2 additions & 24 deletions test/window_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,31 +453,9 @@ def test_window_focused(self):
window = pygame.Window()
self.assertIsInstance(window.focused, bool)

def test_wm_info(self):
def test_handle(self):
window = pygame.Window()
wm_info = window.wm_info
self.assertIsInstance(wm_info, dict)

wm_info_potential_keys = {
"colorbuffer",
"display",
"framebuffer",
"hdc",
"hinstance",
"resolveFramebuffer",
"surface",
"window",
"viewport",
"screen",
}

# If any unexpected dict keys are present, they
# will be stored in set wm_info_remaining_keys
wm_info_remaining_keys = set(wm_info.keys()).difference(wm_info_potential_keys)

# Assert set is empty (& therefore does not
# contain unexpected dict keys)
self.assertFalse(wm_info_remaining_keys)
self.assertIsInstance(window.handle, int)

def tearDown(self):
self.win.destroy()
Expand Down

0 comments on commit ec3818d

Please sign in to comment.