pyglet 3.0.dev10__py3-none-any.whl → 3.0.dev11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyglet/__init__.py +3 -1
- pyglet/__init__.pyi +2 -0
- pyglet/app/__init__.py +7 -3
- pyglet/app/base.py +2 -3
- pyglet/config/__init__.py +10 -2
- pyglet/config/gl/__init__.py +20 -16
- pyglet/display/__init__.py +2 -3
- pyglet/display/base.py +23 -12
- pyglet/display/cocoa.py +4 -0
- pyglet/display/emscripten.py +11 -1
- pyglet/display/headless.py +4 -0
- pyglet/display/ios.py +4 -0
- pyglet/display/wayland.py +15 -8
- pyglet/display/win32.py +13 -15
- pyglet/display/xlib.py +17 -14
- pyglet/event.py +5 -5
- pyglet/experimental/geoshader_sprite.py +4 -7
- pyglet/experimental/particles.py +3 -5
- pyglet/font/__init__.py +1 -2
- pyglet/font/base.py +27 -22
- pyglet/font/dwrite/__init__.py +3 -3
- pyglet/font/freetype.py +51 -76
- pyglet/font/freetype_lib.py +1 -1
- pyglet/font/group.py +18 -4
- pyglet/font/harfbuzz.py +3 -3
- pyglet/font/quartz.py +3 -3
- pyglet/font/user.py +26 -12
- pyglet/graphics/__init__.py +10 -4
- pyglet/graphics/allocation.py +109 -2
- pyglet/graphics/api/__init__.py +10 -8
- pyglet/graphics/api/base.py +58 -4
- pyglet/graphics/api/gl/__init__.py +0 -3
- pyglet/graphics/api/gl/buffer.py +5 -5
- pyglet/graphics/api/gl/context.py +25 -0
- pyglet/graphics/api/gl/framebuffer.py +161 -26
- pyglet/graphics/api/gl/gl_info.py +4 -0
- pyglet/graphics/api/gl/global_opengl.py +8 -9
- pyglet/graphics/api/gl/shader.py +16 -43
- pyglet/graphics/api/gl/shapes.py +1 -1
- pyglet/graphics/api/gl/sprite.py +3 -5
- pyglet/graphics/api/gl/state.py +4 -0
- pyglet/graphics/api/gl/text.py +168 -42
- pyglet/graphics/api/gl/vertexdomain.py +142 -59
- pyglet/graphics/api/gl2/buffer.py +3 -3
- pyglet/graphics/api/gl2/framebuffer.py +7 -2
- pyglet/graphics/api/gl2/global_opengl.py +7 -9
- pyglet/graphics/api/gl2/shader.py +4 -4
- pyglet/graphics/api/gl2/shapes.py +1 -1
- pyglet/graphics/api/gl2/sprite.py +2 -4
- pyglet/graphics/api/gl2/text.py +154 -41
- pyglet/graphics/api/gl2/vertexdomain.py +93 -49
- pyglet/graphics/api/webgl/__init__.py +13 -14
- pyglet/graphics/api/webgl/buffer.py +17 -17
- pyglet/graphics/api/webgl/context.py +3 -3
- pyglet/graphics/api/webgl/draw.py +2 -2
- pyglet/graphics/api/webgl/framebuffer.py +37 -12
- pyglet/graphics/api/webgl/shader.py +21 -59
- pyglet/graphics/api/webgl/shapes.py +1 -1
- pyglet/graphics/api/webgl/sprite.py +3 -5
- pyglet/graphics/api/webgl/state.py +4 -0
- pyglet/graphics/api/webgl/text.py +98 -89
- pyglet/graphics/api/webgl/texture.py +16 -16
- pyglet/graphics/api/webgl/vertexarray.py +3 -3
- pyglet/graphics/api/webgl/vertexdomain.py +134 -58
- pyglet/graphics/api/webgl/webgl_js.pyi +3 -0
- pyglet/graphics/atlas.py +8 -7
- pyglet/graphics/attributes.py +221 -0
- pyglet/graphics/draw.py +660 -200
- pyglet/graphics/framebuffer.py +162 -4
- pyglet/graphics/instance.py +2 -1
- pyglet/graphics/resource.py +2 -2
- pyglet/graphics/shader.py +142 -318
- pyglet/graphics/texture.py +17 -16
- pyglet/graphics/vertexdomain.py +188 -325
- pyglet/graphics/vertexstorage.py +555 -0
- pyglet/gui/__init__.py +6 -2
- pyglet/gui/layout.py +806 -0
- pyglet/gui/manager.py +348 -0
- pyglet/gui/ninepatch.py +68 -41
- pyglet/gui/styles.py +130 -0
- pyglet/gui/widgets.py +607 -113
- pyglet/image/animation.py +1 -1
- pyglet/image/base.py +50 -23
- pyglet/image/codecs/__init__.py +8 -0
- pyglet/image/codecs/qoi.py +275 -0
- pyglet/input/__init__.py +2 -3
- pyglet/input/base.py +10 -11
- pyglet/lib.py +8 -8
- pyglet/math.py +8 -8
- pyglet/media/codecs/__init__.py +1 -3
- pyglet/media/codecs/base.py +15 -6
- pyglet/media/codecs/ffmpeg_lib/compat.py +1 -1
- pyglet/media/drivers/__init__.py +1 -3
- pyglet/media/synthesis.py +64 -44
- pyglet/model/__init__.py +2 -4
- pyglet/model/codecs/obj.py +3 -4
- pyglet/resource.py +148 -40
- pyglet/shapes.py +1 -1
- pyglet/sprite.py +36 -39
- pyglet/text/__init__.py +12 -10
- pyglet/text/caret.py +14 -6
- pyglet/text/document.py +7 -5
- pyglet/text/formats/attributed.py +3 -2
- pyglet/text/formats/html.py +18 -14
- pyglet/text/formats/structured.py +56 -26
- pyglet/text/layout/base.py +111 -36
- pyglet/text/layout/boxes.py +23 -22
- pyglet/text/layout/flow.py +81 -61
- pyglet/text/layout/incremental.py +39 -21
- pyglet/text/layout/scrolling.py +37 -13
- pyglet/text/runlist.py +8 -7
- pyglet/util.py +2 -2
- pyglet/window/__init__.py +71 -48
- pyglet/window/apple/cocoa/pyglet_textview.py +4 -0
- pyglet/window/camera/base.py +30 -10
- pyglet/window/camera/camera2d.py +8 -7
- pyglet/window/camera/camera3d.py +4 -3
- pyglet/window/dialog/__init__.py +3 -4
- pyglet/window/emscripten/__init__.py +1 -0
- pyglet/window/key.py +1 -0
- pyglet/window/wayland/__init__.py +1 -0
- pyglet/window/win32/__init__.py +1 -0
- pyglet/window/xlib/__init__.py +5 -4
- {pyglet-3.0.dev10.dist-info → pyglet-3.0.dev11.dist-info}/METADATA +3 -2
- {pyglet-3.0.dev10.dist-info → pyglet-3.0.dev11.dist-info}/RECORD +378 -373
- {pyglet-3.0.dev10.dist-info → pyglet-3.0.dev11.dist-info}/WHEEL +1 -1
- pyglet/gui/frame.py +0 -205
- {pyglet-3.0.dev10.dist-info → pyglet-3.0.dev11.dist-info}/licenses/LICENSE +0 -0
pyglet/__init__.py
CHANGED
|
@@ -8,6 +8,8 @@ import os
|
|
|
8
8
|
import sys
|
|
9
9
|
import warnings
|
|
10
10
|
|
|
11
|
+
IS_DOC_BUILD = os.environ.get("PYGLET_DOC_BUILD") == "1"
|
|
12
|
+
|
|
11
13
|
from dataclasses import dataclass, field
|
|
12
14
|
from typing import TYPE_CHECKING, Literal, Sequence
|
|
13
15
|
|
|
@@ -18,7 +20,7 @@ if TYPE_CHECKING:
|
|
|
18
20
|
from typing import Any, Callable, ItemsView, Sized
|
|
19
21
|
|
|
20
22
|
#: The release version
|
|
21
|
-
version = '3.0.
|
|
23
|
+
version = '3.0.dev11'
|
|
22
24
|
__version__ = version
|
|
23
25
|
|
|
24
26
|
MIN_PYTHON_VERSION = 3, 10
|
pyglet/__init__.pyi
CHANGED
pyglet/app/__init__.py
CHANGED
|
@@ -31,17 +31,17 @@ default policy is to wait until all windows are closed)::
|
|
|
31
31
|
|
|
32
32
|
from __future__ import annotations
|
|
33
33
|
|
|
34
|
-
import platform
|
|
35
34
|
import sys
|
|
35
|
+
import signal
|
|
36
|
+
import platform
|
|
36
37
|
import weakref
|
|
37
38
|
|
|
38
39
|
import pyglet
|
|
39
40
|
from pyglet import compat_platform
|
|
40
41
|
from pyglet.app.base import EventLoop
|
|
41
42
|
|
|
42
|
-
_is_pyglet_doc_run = hasattr(sys, "is_pyglet_doc_run") and sys.is_pyglet_doc_run
|
|
43
43
|
|
|
44
|
-
if
|
|
44
|
+
if pyglet.IS_DOC_BUILD:
|
|
45
45
|
from pyglet.app.base import PlatformEventLoop
|
|
46
46
|
else:
|
|
47
47
|
if compat_platform == 'darwin':
|
|
@@ -82,7 +82,11 @@ def run(interval: float | None = 1 / 60) -> None:
|
|
|
82
82
|
|
|
83
83
|
pyglet.app.event_loop.run(interval)
|
|
84
84
|
|
|
85
|
+
..note: This convenience function also adds a SIGINT signal handler
|
|
86
|
+
to automatically call ``pyglet.app.exit`` when this signal
|
|
87
|
+
is detected.
|
|
85
88
|
"""
|
|
89
|
+
signal.signal(signal.SIGINT, lambda _s, _f: event_loop.exit())
|
|
86
90
|
event_loop.run(interval)
|
|
87
91
|
|
|
88
92
|
|
pyglet/app/base.py
CHANGED
|
@@ -7,13 +7,12 @@ from abc import ABC, abstractmethod
|
|
|
7
7
|
from queue import Queue
|
|
8
8
|
from typing import TYPE_CHECKING, Any, Callable
|
|
9
9
|
|
|
10
|
-
from pyglet import app, clock, event
|
|
10
|
+
from pyglet import app, clock, event, IS_DOC_BUILD
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from pyglet.event import EventDispatcher
|
|
14
14
|
from pyglet.window import BaseWindow
|
|
15
15
|
|
|
16
|
-
_is_pyglet_doc_run = hasattr(sys, "is_pyglet_doc_run") and sys.is_pyglet_doc_run
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class WindowDrawSource(ABC):
|
|
@@ -406,7 +405,7 @@ class EventLoop(event.EventDispatcher):
|
|
|
406
405
|
if len(app.windows) == 0:
|
|
407
406
|
self.exit()
|
|
408
407
|
|
|
409
|
-
if
|
|
408
|
+
if IS_DOC_BUILD:
|
|
410
409
|
# Events
|
|
411
410
|
|
|
412
411
|
def on_window_close(self, window: BaseWindow) -> None:
|
pyglet/config/__init__.py
CHANGED
|
@@ -4,6 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import TYPE_CHECKING, NamedTuple
|
|
6
6
|
|
|
7
|
+
import pyglet
|
|
8
|
+
|
|
7
9
|
from pyglet.enums import GraphicsAPI
|
|
8
10
|
|
|
9
11
|
from .base import SurfaceConfig, UserConfig # noqa: TC001
|
|
@@ -23,7 +25,7 @@ class Config:
|
|
|
23
25
|
|
|
24
26
|
__slots__ = 'gl2', 'gles2', 'gles3', 'opengl', 'vulkan', 'webgl'
|
|
25
27
|
|
|
26
|
-
def __init__(self):
|
|
28
|
+
def __init__(self) -> None: # noqa: D107
|
|
27
29
|
self.opengl: OpenGLUserConfig = OpenGLUserConfig(major_version=3, minor_version=3, api=GraphicsAPI.OPENGL)
|
|
28
30
|
self.gl2: OpenGLUserConfig = OpenGLUserConfig(major_version=2, minor_version=0, api=GraphicsAPI.OPENGL_2)
|
|
29
31
|
self.gles2: OpenGLUserConfig = OpenGLUserConfig(major_version=2, minor_version=0, api=GraphicsAPI.OPENGL_ES_2)
|
|
@@ -33,9 +35,15 @@ class Config:
|
|
|
33
35
|
|
|
34
36
|
|
|
35
37
|
def match_surface_config(config: UserConfig, surface: Window) -> SurfaceConfig | None:
|
|
36
|
-
if isinstance(config,
|
|
38
|
+
if isinstance(config, OpenGLUserConfig):
|
|
37
39
|
from pyglet.config.gl import get_surface_config # noqa: PLC0415
|
|
38
40
|
return get_surface_config(config, surface)
|
|
39
41
|
|
|
42
|
+
if isinstance(config, WebGLUserConfig):
|
|
43
|
+
if pyglet.compat_platform == 'emscripten':
|
|
44
|
+
from pyglet.config.gl.webgl import match # noqa: PLC0415
|
|
45
|
+
return match(config, surface)
|
|
46
|
+
return None
|
|
47
|
+
|
|
40
48
|
msg = f"Matching for '{config.__class__}' is not yet implemented."
|
|
41
49
|
raise NotImplementedError(msg)
|
pyglet/config/gl/__init__.py
CHANGED
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
+
from typing import TYPE_CHECKING, cast
|
|
4
5
|
|
|
5
6
|
import pyglet
|
|
6
7
|
|
|
7
8
|
from pyglet.enums import GraphicsAPI
|
|
8
9
|
from pyglet.config.base import UserConfig, SurfaceConfig
|
|
9
10
|
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from pyglet.window.apple.cocoa import CocoaWindow
|
|
13
|
+
from pyglet.window.apple.ios import IOSWindow
|
|
14
|
+
from pyglet.window.headless import HeadlessWindow
|
|
15
|
+
from pyglet.window.wayland import WaylandWindow
|
|
16
|
+
from pyglet.window.win32 import Win32Window
|
|
17
|
+
from pyglet.window.xlib import XlibWindow
|
|
18
|
+
|
|
10
19
|
|
|
11
20
|
class GLSurfaceConfig(SurfaceConfig):
|
|
12
21
|
config: OpenGLUserConfig
|
|
@@ -98,36 +107,31 @@ class WebGLUserConfig(UserConfig):
|
|
|
98
107
|
return False
|
|
99
108
|
|
|
100
109
|
|
|
101
|
-
def get_surface_config(user_config:
|
|
110
|
+
def get_surface_config(user_config: OpenGLUserConfig, surface: pyglet.window.Window) -> SurfaceConfig | None:
|
|
102
111
|
|
|
103
112
|
if pyglet.options.headless or pyglet.options.wayland:
|
|
104
|
-
from pyglet.config.gl.egl import match
|
|
113
|
+
from pyglet.config.gl.egl import match as match_egl # noqa: PLC0415
|
|
105
114
|
|
|
106
|
-
return
|
|
115
|
+
return match_egl(user_config, cast("HeadlessWindow | WaylandWindow", surface))
|
|
107
116
|
|
|
108
117
|
if pyglet.compat_platform == "win32":
|
|
109
|
-
from pyglet.config.gl.windows import match # noqa: PLC0415
|
|
118
|
+
from pyglet.config.gl.windows import match as match_windows # noqa: PLC0415
|
|
110
119
|
|
|
111
|
-
return
|
|
120
|
+
return match_windows(user_config, cast("Win32Window", surface))
|
|
112
121
|
|
|
113
122
|
if pyglet.compat_platform.startswith("linux"):
|
|
114
|
-
from pyglet.config.gl.x11 import match # noqa: PLC0415
|
|
123
|
+
from pyglet.config.gl.x11 import match as match_x11 # noqa: PLC0415
|
|
115
124
|
|
|
116
|
-
return
|
|
125
|
+
return match_x11(user_config, cast("XlibWindow", surface))
|
|
117
126
|
|
|
118
127
|
if pyglet.compat_platform == "darwin":
|
|
119
|
-
from pyglet.config.gl.macos import match # noqa: PLC0415
|
|
128
|
+
from pyglet.config.gl.macos import match as match_macos # noqa: PLC0415
|
|
120
129
|
|
|
121
|
-
return
|
|
130
|
+
return match_macos(user_config, cast("CocoaWindow", surface))
|
|
122
131
|
|
|
123
132
|
if pyglet.compat_platform == "ios":
|
|
124
|
-
from pyglet.config.gl.ios import match # noqa: PLC0415
|
|
125
|
-
|
|
126
|
-
return match(user_config, surface)
|
|
127
|
-
|
|
128
|
-
if pyglet.compat_platform == "emscripten":
|
|
129
|
-
from pyglet.config.gl.webgl import match # noqa: PLC0415
|
|
133
|
+
from pyglet.config.gl.ios import match as match_ios # noqa: PLC0415
|
|
130
134
|
|
|
131
|
-
return
|
|
135
|
+
return match_ios(user_config, cast("IOSWindow", surface))
|
|
132
136
|
|
|
133
137
|
return None
|
pyglet/display/__init__.py
CHANGED
|
@@ -22,13 +22,12 @@ by the application; see the documentation for :class:`Screen`.
|
|
|
22
22
|
.. versionadded:: 1.2
|
|
23
23
|
""" # noqa: I002
|
|
24
24
|
|
|
25
|
-
import sys
|
|
26
25
|
import weakref
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
from pyglet import IS_DOC_BUILD
|
|
29
28
|
|
|
30
29
|
|
|
31
|
-
if
|
|
30
|
+
if IS_DOC_BUILD:
|
|
32
31
|
from pyglet.display.base import Display, Screen, ScreenMode
|
|
33
32
|
else:
|
|
34
33
|
from pyglet import compat_platform, options
|
pyglet/display/base.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import abc
|
|
4
|
-
from typing import TYPE_CHECKING, Literal
|
|
4
|
+
from typing import TYPE_CHECKING, Literal, Sequence
|
|
5
5
|
|
|
6
6
|
from pyglet import app, display
|
|
7
7
|
|
|
@@ -12,10 +12,10 @@ if TYPE_CHECKING:
|
|
|
12
12
|
class Display:
|
|
13
13
|
"""A display device supporting one or more screens."""
|
|
14
14
|
|
|
15
|
-
name: str = None
|
|
15
|
+
name: str | None = None
|
|
16
16
|
"""Name of this display, if applicable."""
|
|
17
17
|
|
|
18
|
-
x_screen: int = None
|
|
18
|
+
x_screen: int | None = None
|
|
19
19
|
"""The X11 screen number of this display, if applicable."""
|
|
20
20
|
|
|
21
21
|
def __init__(self, name: str | None = None, x_screen: int | None = None) -> None:
|
|
@@ -35,7 +35,7 @@ class Display:
|
|
|
35
35
|
On platforms other than X11, :attr:`name` and :attr:`x_screen` are
|
|
36
36
|
ignored; there is only a single display device on these systems.
|
|
37
37
|
"""
|
|
38
|
-
display._displays.add(self)
|
|
38
|
+
display._displays.add(self) # type: ignore[attr-defined] # noqa: SLF001
|
|
39
39
|
|
|
40
40
|
def get_screens(self) -> list[Screen]:
|
|
41
41
|
"""Get the available screens.
|
|
@@ -55,7 +55,7 @@ class Display:
|
|
|
55
55
|
"""Get the default (primary) screen as specified by the user's operating system preferences."""
|
|
56
56
|
screens = self.get_screens()
|
|
57
57
|
for screen in screens:
|
|
58
|
-
if screen.
|
|
58
|
+
if screen.is_primary:
|
|
59
59
|
return screen
|
|
60
60
|
|
|
61
61
|
# No Primary screen found?
|
|
@@ -96,24 +96,31 @@ class Screen(abc.ABC):
|
|
|
96
96
|
self.height = height
|
|
97
97
|
"""Height of the screen, in pixels."""
|
|
98
98
|
|
|
99
|
+
@property
|
|
100
|
+
@abc.abstractmethod
|
|
101
|
+
def is_primary(self) -> bool:
|
|
102
|
+
"""Whether this is the operating system's primary screen."""
|
|
103
|
+
|
|
99
104
|
def __repr__(self) -> str:
|
|
100
105
|
return f"{self.__class__.__name__}(x={self.x}, y={self.y}, width={self.width}, height={self.height})"
|
|
101
106
|
|
|
102
|
-
|
|
107
|
+
@abc.abstractmethod
|
|
108
|
+
def get_modes(self) -> Sequence[ScreenMode]:
|
|
103
109
|
"""Get a list of screen modes supported by this screen.
|
|
104
110
|
|
|
105
111
|
.. versionadded:: 1.2
|
|
106
112
|
"""
|
|
107
113
|
raise NotImplementedError('abstract')
|
|
108
114
|
|
|
109
|
-
|
|
115
|
+
@abc.abstractmethod
|
|
116
|
+
def get_mode(self) -> ScreenMode | None:
|
|
110
117
|
"""Get the current display mode for this screen.
|
|
111
118
|
|
|
112
119
|
.. versionadded:: 1.2
|
|
113
120
|
"""
|
|
114
121
|
raise NotImplementedError('abstract')
|
|
115
122
|
|
|
116
|
-
def get_closest_mode(self, width: int, height: int) -> ScreenMode:
|
|
123
|
+
def get_closest_mode(self, width: int, height: int) -> ScreenMode | None:
|
|
117
124
|
"""Get the screen mode that best matches a given size.
|
|
118
125
|
|
|
119
126
|
If no supported mode exactly equals the requested size, a larger one
|
|
@@ -154,6 +161,7 @@ class Screen(abc.ABC):
|
|
|
154
161
|
best = mode
|
|
155
162
|
return best
|
|
156
163
|
|
|
164
|
+
@abc.abstractmethod
|
|
157
165
|
def set_mode(self, mode: ScreenMode) -> None:
|
|
158
166
|
"""Set the display mode for this screen.
|
|
159
167
|
|
|
@@ -162,14 +170,17 @@ class Screen(abc.ABC):
|
|
|
162
170
|
"""
|
|
163
171
|
raise NotImplementedError('abstract')
|
|
164
172
|
|
|
173
|
+
@abc.abstractmethod
|
|
165
174
|
def restore_mode(self) -> None:
|
|
166
175
|
"""Restore the screen mode to the user's default."""
|
|
167
176
|
raise NotImplementedError('abstract')
|
|
168
177
|
|
|
178
|
+
@abc.abstractmethod
|
|
169
179
|
def get_dpi(self) -> int:
|
|
170
180
|
"""Get the DPI of the screen."""
|
|
171
181
|
raise NotImplementedError('abstract')
|
|
172
182
|
|
|
183
|
+
@abc.abstractmethod
|
|
173
184
|
def get_scale(self) -> float:
|
|
174
185
|
"""Get the pixel scale ratio of the screen."""
|
|
175
186
|
raise NotImplementedError('abstract')
|
|
@@ -208,16 +219,16 @@ class ScreenMode:
|
|
|
208
219
|
.. versionadded:: 1.2
|
|
209
220
|
"""
|
|
210
221
|
|
|
211
|
-
width: int
|
|
222
|
+
width: int
|
|
212
223
|
"""Width of screen, in pixels."""
|
|
213
224
|
|
|
214
|
-
height: int
|
|
225
|
+
height: int
|
|
215
226
|
"""Height of screen, in pixels."""
|
|
216
227
|
|
|
217
|
-
depth: int
|
|
228
|
+
depth: int | None
|
|
218
229
|
"""Pixel color depth, in bits per pixel."""
|
|
219
230
|
|
|
220
|
-
rate: int
|
|
231
|
+
rate: int | None
|
|
221
232
|
"""Screen refresh rate in Hz."""
|
|
222
233
|
|
|
223
234
|
def __init__(self, screen: Screen) -> None:
|
pyglet/display/cocoa.py
CHANGED
|
@@ -54,6 +54,10 @@ class CocoaScreen(Screen):
|
|
|
54
54
|
if screen_name:
|
|
55
55
|
self._friendly_name = cfstring_to_string(screen_name)
|
|
56
56
|
|
|
57
|
+
@property
|
|
58
|
+
def is_primary(self) -> bool:
|
|
59
|
+
return self._cg_display_id == quartz.CGMainDisplayID()
|
|
60
|
+
|
|
57
61
|
def get_nsscreen(self):
|
|
58
62
|
"""Return the current NSScreen associated with this display framebuffer."""
|
|
59
63
|
# Get a list of all currently active NSScreens and then search through
|
pyglet/display/emscripten.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from typing import Literal
|
|
4
4
|
|
|
5
5
|
from pyglet.display.base import Display, Screen
|
|
6
|
-
import js # noqa: F821
|
|
6
|
+
import js # type: ignore[import-not-found] # noqa: F821
|
|
7
7
|
|
|
8
8
|
class EmscriptenDisplay(Display):
|
|
9
9
|
|
|
@@ -20,6 +20,10 @@ class EmscriptenScreen(Screen):
|
|
|
20
20
|
height = js.window.screen.height
|
|
21
21
|
super().__init__(display, 0, 0, width, height)
|
|
22
22
|
|
|
23
|
+
@property
|
|
24
|
+
def is_primary(self) -> bool:
|
|
25
|
+
return True
|
|
26
|
+
|
|
23
27
|
def get_display_id(self) -> int:
|
|
24
28
|
return 0
|
|
25
29
|
|
|
@@ -37,3 +41,9 @@ class EmscriptenScreen(Screen):
|
|
|
37
41
|
|
|
38
42
|
def restore_mode(self):
|
|
39
43
|
pass
|
|
44
|
+
|
|
45
|
+
def get_dpi(self) -> int:
|
|
46
|
+
return round(96 * self.get_scale())
|
|
47
|
+
|
|
48
|
+
def get_scale(self) -> float:
|
|
49
|
+
return js.window.devicePixelRatio
|
pyglet/display/headless.py
CHANGED
pyglet/display/ios.py
CHANGED
|
@@ -22,6 +22,10 @@ class IOSScreen(Screen):
|
|
|
22
22
|
scale = ui_screen.nativeScale()
|
|
23
23
|
super().__init__(display, 0, 0, round(bounds.size.width * scale), round(bounds.size.height * scale))
|
|
24
24
|
|
|
25
|
+
@property
|
|
26
|
+
def is_primary(self) -> bool:
|
|
27
|
+
return True
|
|
28
|
+
|
|
25
29
|
def get_modes(self) -> list[ScreenMode]:
|
|
26
30
|
return [self.get_mode()]
|
|
27
31
|
|
pyglet/display/wayland.py
CHANGED
|
@@ -69,7 +69,9 @@ class WaylandDisplay(Display):
|
|
|
69
69
|
self.client.sync()
|
|
70
70
|
self._query_done.wait()
|
|
71
71
|
# Make Screen instance with the now-filled-in values:
|
|
72
|
-
self._screens.append(
|
|
72
|
+
self._screens.append(
|
|
73
|
+
WaylandScreen(self, self._geo, self._modes, self._scale, self._name, self._descript, i == 0),
|
|
74
|
+
)
|
|
73
75
|
wl_output.release()
|
|
74
76
|
|
|
75
77
|
# Start Wayland Event handlers
|
|
@@ -106,13 +108,8 @@ class WaylandDisplay(Display):
|
|
|
106
108
|
|
|
107
109
|
class WaylandScreen(Screen):
|
|
108
110
|
|
|
109
|
-
def
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def get_monitor_name(self) -> str | Literal["Unknown"]:
|
|
113
|
-
return self.description
|
|
114
|
-
|
|
115
|
-
def __init__(self, display, geometry, modes, scale, name, description):
|
|
111
|
+
def __init__(self, display, geometry, modes, scale, name, description, is_primary):
|
|
112
|
+
self._is_primary = is_primary
|
|
116
113
|
self.name = name
|
|
117
114
|
self.description = description
|
|
118
115
|
self._scale = scale
|
|
@@ -132,6 +129,16 @@ class WaylandScreen(Screen):
|
|
|
132
129
|
|
|
133
130
|
super().__init__(display, self._geo.x, self._geo.y, _width_pixels, _height_pixels)
|
|
134
131
|
|
|
132
|
+
@property
|
|
133
|
+
def is_primary(self) -> bool:
|
|
134
|
+
return self._is_primary
|
|
135
|
+
|
|
136
|
+
def get_display_id(self) -> str | int:
|
|
137
|
+
return self.name
|
|
138
|
+
|
|
139
|
+
def get_monitor_name(self) -> str | Literal["Unknown"]:
|
|
140
|
+
return self.description
|
|
141
|
+
|
|
135
142
|
def get_modes(self):
|
|
136
143
|
return self._modes
|
|
137
144
|
|
pyglet/display/win32.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import ctypes
|
|
4
4
|
from ctypes import byref, sizeof
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, Sequence
|
|
6
6
|
|
|
7
7
|
from pyglet.libs.win32 import _gdi32, _user32
|
|
8
8
|
from pyglet.libs.win32.constants import (
|
|
@@ -42,9 +42,6 @@ if TYPE_CHECKING:
|
|
|
42
42
|
if WINDOWS_8_1_OR_GREATER:
|
|
43
43
|
from pyglet.libs.win32 import _shcore
|
|
44
44
|
|
|
45
|
-
if TYPE_CHECKING:
|
|
46
|
-
from ctypes.wintypes import HDC, HMONITOR, LPARAM, LPRECT
|
|
47
|
-
|
|
48
45
|
|
|
49
46
|
def set_dpi_awareness() -> None:
|
|
50
47
|
"""Setting DPI varies per Windows version.
|
|
@@ -66,13 +63,13 @@ class Win32Display(Display): # noqa: D101
|
|
|
66
63
|
def get_default_screen(self) -> Screen:
|
|
67
64
|
screens = self.get_screens()
|
|
68
65
|
for screen in screens:
|
|
69
|
-
if screen.is_primary:
|
|
66
|
+
if isinstance(screen, Win32Screen) and screen.is_primary:
|
|
70
67
|
return screen
|
|
71
68
|
|
|
72
69
|
return screens[0]
|
|
73
70
|
|
|
74
|
-
def get_screens(self) -> list[
|
|
75
|
-
screens = []
|
|
71
|
+
def get_screens(self) -> list[Screen]:
|
|
72
|
+
screens: list[Screen] = []
|
|
76
73
|
|
|
77
74
|
def enum_proc(hMonitor: HMONITOR, hdcMonitor: HDC, lprcMonitor: LPRECT, dwData: LPARAM) -> bool: # noqa: N803, ARG001
|
|
78
75
|
r = lprcMonitor.contents
|
|
@@ -89,7 +86,7 @@ class Win32Display(Display): # noqa: D101
|
|
|
89
86
|
|
|
90
87
|
class Win32Screen(Screen): # noqa: D101
|
|
91
88
|
_handle: HMONITOR
|
|
92
|
-
_initial_mode = None
|
|
89
|
+
_initial_mode: Win32ScreenMode | None = None
|
|
93
90
|
|
|
94
91
|
def __init__(self, display: Win32Display, handle: HMONITOR, x: int, y: int, width: int, height: int) -> None: # noqa: D107
|
|
95
92
|
super().__init__(display, x, y, width, height)
|
|
@@ -101,7 +98,7 @@ class Win32Screen(Screen): # noqa: D101
|
|
|
101
98
|
def is_primary(self) -> bool:
|
|
102
99
|
"""If the screen is considered the primary according to the operating system."""
|
|
103
100
|
info = self._get_monitor_info()
|
|
104
|
-
return info.dwFlags & MONITORINFOF_PRIMARY
|
|
101
|
+
return bool(info.dwFlags & MONITORINFOF_PRIMARY)
|
|
105
102
|
|
|
106
103
|
def _get_friendly_name_display_config_api(self) -> str:
|
|
107
104
|
"""Get the friendly name of a monitor using the newer Display Configuration API.
|
|
@@ -188,23 +185,23 @@ class Win32Screen(Screen): # noqa: D101
|
|
|
188
185
|
|
|
189
186
|
def get_dpi(self) -> int:
|
|
190
187
|
if WINDOWS_8_1_OR_GREATER:
|
|
191
|
-
|
|
188
|
+
xdpi_value = UINT()
|
|
192
189
|
ydpi = UINT()
|
|
193
|
-
_shcore.GetDpiForMonitor(self._handle, 0, byref(
|
|
194
|
-
xdpi
|
|
190
|
+
_shcore.GetDpiForMonitor(self._handle, 0, byref(xdpi_value), byref(ydpi))
|
|
191
|
+
xdpi = xdpi_value.value
|
|
195
192
|
else:
|
|
196
193
|
dc = _user32.GetDC(None)
|
|
197
194
|
xdpi = _gdi32.GetDeviceCaps(dc, LOGPIXELSX)
|
|
198
195
|
ydpi = _gdi32.GetDeviceCaps(dc, LOGPIXELSY)
|
|
199
196
|
_user32.ReleaseDC(0, dc)
|
|
200
197
|
|
|
201
|
-
return xdpi
|
|
198
|
+
return int(xdpi)
|
|
202
199
|
|
|
203
200
|
def get_scale(self) -> float:
|
|
204
201
|
xdpi = self.get_dpi()
|
|
205
202
|
return xdpi / USER_DEFAULT_SCREEN_DPI
|
|
206
203
|
|
|
207
|
-
def get_modes(self) ->
|
|
204
|
+
def get_modes(self) -> Sequence[Win32ScreenMode]:
|
|
208
205
|
device_name = self.get_device_name()
|
|
209
206
|
i = 0
|
|
210
207
|
modes = []
|
|
@@ -228,7 +225,8 @@ class Win32Screen(Screen): # noqa: D101
|
|
|
228
225
|
byref(mode))
|
|
229
226
|
return Win32ScreenMode(self, mode)
|
|
230
227
|
|
|
231
|
-
def set_mode(self, mode:
|
|
228
|
+
def set_mode(self, mode: ScreenMode) -> None:
|
|
229
|
+
assert isinstance(mode, Win32ScreenMode)
|
|
232
230
|
assert mode.screen is self
|
|
233
231
|
|
|
234
232
|
if not self._initial_mode:
|
pyglet/display/xlib.py
CHANGED
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import ctypes
|
|
4
4
|
import warnings
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
5
|
from ctypes import POINTER, byref, c_buffer, c_char_p, c_int, cast
|
|
7
6
|
|
|
8
7
|
import pyglet
|
|
@@ -22,8 +21,6 @@ class NoSuchDisplayException(Exception):
|
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
from pyglet.libs.linux.x11 import xlib
|
|
25
|
-
if TYPE_CHECKING:
|
|
26
|
-
from pyglet.gl import Config
|
|
27
24
|
|
|
28
25
|
try:
|
|
29
26
|
from pyglet.libs.linux.x11 import xinerama
|
|
@@ -47,17 +44,13 @@ except:
|
|
|
47
44
|
_have_xf86vmode = False
|
|
48
45
|
|
|
49
46
|
try:
|
|
50
|
-
from pyglet.libs.x11 import xrandr
|
|
47
|
+
from pyglet.libs.x11 import xrandr # type: ignore[import-not-found]
|
|
51
48
|
|
|
52
49
|
_have_xrandr = True
|
|
53
50
|
except ImportError:
|
|
54
51
|
_have_xrandr = False
|
|
55
52
|
|
|
56
53
|
|
|
57
|
-
class NoSuchDisplayException(Exception):
|
|
58
|
-
pass
|
|
59
|
-
|
|
60
|
-
|
|
61
54
|
# Set up error handler
|
|
62
55
|
def _error_handler(display, event):
|
|
63
56
|
# By default, all errors are silently ignored: this has a better chance
|
|
@@ -94,7 +87,7 @@ class XlibDisplay(LinuxSelectDevice, Display):
|
|
|
94
87
|
_x_im = None # X input method
|
|
95
88
|
# TODO close _x_im when display connection closed.
|
|
96
89
|
_enable_xsync = False
|
|
97
|
-
_screens: list[
|
|
90
|
+
_screens: list[Screen]
|
|
98
91
|
|
|
99
92
|
def __init__(self, name=None, x_screen=None):
|
|
100
93
|
self._screens = []
|
|
@@ -143,7 +136,7 @@ class XlibDisplay(LinuxSelectDevice, Display):
|
|
|
143
136
|
# Couldn't find a default screen, use the first in the list.
|
|
144
137
|
return self._screens[0]
|
|
145
138
|
|
|
146
|
-
def get_screens(self) -> list[
|
|
139
|
+
def get_screens(self) -> list[Screen]:
|
|
147
140
|
self._screens = []
|
|
148
141
|
|
|
149
142
|
# Use XRandr if available, as it appears more maintained and widely supported.
|
|
@@ -240,6 +233,10 @@ class XlibScreen(Screen):
|
|
|
240
233
|
def __init__(self, display: XlibDisplay, x: int, y: int, width: int, height: int):
|
|
241
234
|
super().__init__(display, x, y, width, height)
|
|
242
235
|
|
|
236
|
+
@property
|
|
237
|
+
def is_primary(self) -> bool:
|
|
238
|
+
return True
|
|
239
|
+
|
|
243
240
|
def get_dpi(self) -> int:
|
|
244
241
|
resource = xlib.XResourceManagerString(self.display._display)
|
|
245
242
|
dpi = 96
|
|
@@ -288,13 +285,14 @@ class XlibScreen(Screen):
|
|
|
288
285
|
|
|
289
286
|
return modes
|
|
290
287
|
|
|
291
|
-
def get_mode(self) -> XlibScreenMode:
|
|
288
|
+
def get_mode(self) -> XlibScreenMode | None:
|
|
292
289
|
modes = self.get_modes()
|
|
293
290
|
if modes:
|
|
294
291
|
return modes[0]
|
|
295
292
|
return None
|
|
296
293
|
|
|
297
|
-
def set_mode(self, mode:
|
|
294
|
+
def set_mode(self, mode: ScreenMode) -> None:
|
|
295
|
+
assert isinstance(mode, XlibScreenModeXF86)
|
|
298
296
|
assert mode.screen is self
|
|
299
297
|
|
|
300
298
|
if not self._initial_mode:
|
|
@@ -334,6 +332,10 @@ class XlibScreenXinerama(XlibScreen):
|
|
|
334
332
|
self._xinerama = using_xinerama
|
|
335
333
|
self.idx = idx
|
|
336
334
|
|
|
335
|
+
@property
|
|
336
|
+
def is_primary(self) -> bool:
|
|
337
|
+
return self.idx == 0
|
|
338
|
+
|
|
337
339
|
def get_display_id(self) -> int:
|
|
338
340
|
# No real unique ID is available, just hash together the properties.
|
|
339
341
|
return hash((self.idx, self.x, self.y, self.width, self.height))
|
|
@@ -369,7 +371,7 @@ class XlibScreenXrandr(XlibScreen):
|
|
|
369
371
|
self._is_primary = is_primary
|
|
370
372
|
|
|
371
373
|
@property
|
|
372
|
-
def is_primary(self):
|
|
374
|
+
def is_primary(self) -> bool:
|
|
373
375
|
return self._is_primary
|
|
374
376
|
|
|
375
377
|
@staticmethod
|
|
@@ -380,7 +382,8 @@ class XlibScreenXrandr(XlibScreen):
|
|
|
380
382
|
|
|
381
383
|
return None
|
|
382
384
|
|
|
383
|
-
def set_mode(self, mode:
|
|
385
|
+
def set_mode(self, mode: ScreenMode) -> None:
|
|
386
|
+
assert isinstance(mode, XlibScreenModeXrandr)
|
|
384
387
|
assert mode.screen is self
|
|
385
388
|
|
|
386
389
|
if not self._initial_mode:
|
pyglet/event.py
CHANGED
|
@@ -159,8 +159,8 @@ class EventDispatcher:
|
|
|
159
159
|
for suitable handlers.
|
|
160
160
|
"""
|
|
161
161
|
if not hasattr(cls, 'event_types'):
|
|
162
|
-
cls.event_types = [] # type: ignore
|
|
163
|
-
cls.event_types.append(name) # type: ignore
|
|
162
|
+
cls.event_types = [] # type: ignore[attr-defined]
|
|
163
|
+
cls.event_types.append(name) # type: ignore[attr-defined]
|
|
164
164
|
return name
|
|
165
165
|
|
|
166
166
|
def push_handlers(self, *args: Any, **kwargs: Any) -> None:
|
|
@@ -179,10 +179,10 @@ class EventDispatcher:
|
|
|
179
179
|
self._event_stack = []
|
|
180
180
|
|
|
181
181
|
# Place dict full of new handlers at beginning of stack
|
|
182
|
-
self._event_stack.insert(0, {}) # type: ignore
|
|
182
|
+
self._event_stack.insert(0, {}) # type: ignore[attr-defined]
|
|
183
183
|
self.set_handlers(*args, **kwargs)
|
|
184
184
|
|
|
185
|
-
def _get_handlers(self, args: list, kwargs: dict) -> Generator[tuple[str, Callable], None, None]:
|
|
185
|
+
def _get_handlers(self, args: tuple[Any, ...] | list[Any], kwargs: dict) -> Generator[tuple[str, Callable], None, None]:
|
|
186
186
|
"""Implement handler matching on arguments for set_handlers and remove_handlers."""
|
|
187
187
|
for obj in args:
|
|
188
188
|
if inspect.isroutine(obj):
|
|
@@ -371,7 +371,7 @@ class EventDispatcher:
|
|
|
371
371
|
|
|
372
372
|
return False
|
|
373
373
|
|
|
374
|
-
def post_event(self, event_type: str, *args: Any) ->
|
|
374
|
+
def post_event(self, event_type: str, *args: Any) -> None:
|
|
375
375
|
"""Post an event to the main application thread.
|
|
376
376
|
|
|
377
377
|
Unlike the :py:meth:`~pyglet.event.EventDispatcher.dispatch_event`
|