Skip to content

Commit

Permalink
Add Window.wm_info
Browse files Browse the repository at this point in the history
  • Loading branch information
damusss committed Nov 10, 2024
1 parent 6e24c38 commit 1d9f1f3
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 1 deletion.
4 changes: 3 additions & 1 deletion buildconfig/stubs/pygame/window.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Optional, Tuple, Union
from typing import Optional, Tuple, Dict, Union
from typing_extensions import deprecated # added in 3.13

from pygame.typing import Point, RectLike
Expand Down Expand Up @@ -70,6 +70,8 @@ class Window:
def position(self, value: Union[int, Point]) -> None: ...
@property
def opengl(self) -> bool: ...
@property
def wm_info(self) -> Dict[str, 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: ...
12 changes: 12 additions & 0 deletions docs/reST/ref/window.rst
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,18 @@

.. versionadded:: 2.5.0

.. attribute:: wm_info

| :sl:`Get information about the current windowing system`
| :sg:`wm_info -> dict`
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.

.. versionaddedold:: 2.5.3

.. classmethod:: from_display_module

| :sl:`Create a Window object using window data from display module`
Expand Down
1 change: 1 addition & 0 deletions src_c/doc/window_doc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +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_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
116 changes: 116 additions & 0 deletions src_c/window.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "doc/sdl2_video_doc.h"
#include "doc/window_doc.h"

#include <SDL_syswm.h>

static int is_window_mod_init = 0;

#if !defined(__APPLE__)
Expand Down Expand Up @@ -779,6 +781,119 @@ window_get_opengl(pgWindowObject *self, void *v)
return PyBool_FromLong(hasGL);
}

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

SDL_VERSION(&(info.version))
dict = PyDict_New();
if (!dict)
return NULL;

SDL_Window *win = self->_win;
if (!SDL_GetWindowWMInfo(win, &info))
return dict;

(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);
#endif
#if defined(SDL_VIDEO_DRIVER_WINRT)
tmp = PyCapsule_New(info.info.winrt.window, "window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);
#endif
#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);
#endif
#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
tmp = PyCapsule_New(info.info.dfb.dfb, "dfb", NULL);
PyDict_SetItemString(dict, "dfb", tmp);
Py_DECREF(tmp);

tmp = PyCapsule_New(info.info.dfb.window, "window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);

tmp = PyCapsule_New(info.info.dfb.surface, "surface", NULL);
PyDict_SetItemString(dict, "surface", tmp);
Py_DECREF(tmp);
#endif
#if defined(SDL_VIDEO_DRIVER_COCOA)
tmp = PyCapsule_New(info.info.cocoa.window, "window", NULL);
PyDict_SetItemString(dict, "window", tmp);
Py_DECREF(tmp);
#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);

tmp = PyCapsule_New(info.info.wl.shell_surface, "shell_surface", NULL);
PyDict_SetItemString(dict, "shell_surface", tmp);
Py_DECREF(tmp);
#endif
#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);
#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);
#endif

return dict;
}

static void
window_dealloc(pgWindowObject *self, PyObject *_null)
{
Expand Down Expand Up @@ -1195,6 +1310,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},
{NULL, 0, NULL, NULL, NULL} /* Sentinel */
};

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

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

wm_info_potential_keys = {
"colorbuffer",
"connection",
"data",
"dfb",
"display",
"framebuffer",
"fswindow",
"hdc",
"hglrc",
"hinstance",
"lock_func",
"resolveFramebuffer",
"shell_surface",
"surface",
"taskHandle",
"unlock_func",
"wimpVersion",
"window",
"wmwindow",
}

# 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)

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

Expand Down

0 comments on commit 1d9f1f3

Please sign in to comment.