pyglet 2.1.13__py3-none-any.whl → 3.0.dev1__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.
Files changed (267) hide show
  1. pyglet/__init__.py +67 -61
  2. pyglet/__init__.pyi +15 -8
  3. pyglet/app/__init__.py +22 -13
  4. pyglet/app/async_app.py +212 -0
  5. pyglet/app/base.py +2 -1
  6. pyglet/app/{xlib.py → linux.py} +3 -3
  7. pyglet/config/__init__.py +101 -0
  8. pyglet/config/gl/__init__.py +30 -0
  9. pyglet/config/gl/egl.py +120 -0
  10. pyglet/config/gl/macos.py +262 -0
  11. pyglet/config/gl/windows.py +267 -0
  12. pyglet/config/gl/x11.py +142 -0
  13. pyglet/customtypes.py +43 -2
  14. pyglet/display/__init__.py +8 -6
  15. pyglet/display/base.py +3 -63
  16. pyglet/display/cocoa.py +12 -17
  17. pyglet/display/emscripten.py +39 -0
  18. pyglet/display/headless.py +23 -30
  19. pyglet/display/wayland.py +157 -0
  20. pyglet/display/win32.py +5 -21
  21. pyglet/display/xlib.py +19 -27
  22. pyglet/display/xlib_vidmoderestore.py +2 -2
  23. pyglet/enums.py +183 -0
  24. pyglet/event.py +0 -1
  25. pyglet/experimental/geoshader_sprite.py +15 -13
  26. pyglet/experimental/hidraw.py +6 -15
  27. pyglet/experimental/multitexture_sprite.py +31 -19
  28. pyglet/experimental/particles.py +13 -35
  29. pyglet/font/__init__.py +251 -85
  30. pyglet/font/base.py +116 -61
  31. pyglet/font/dwrite/__init__.py +349 -204
  32. pyglet/font/dwrite/dwrite_lib.py +27 -5
  33. pyglet/font/fontconfig.py +14 -6
  34. pyglet/font/freetype.py +138 -87
  35. pyglet/font/freetype_lib.py +19 -0
  36. pyglet/font/group.py +179 -0
  37. pyglet/font/harfbuzz/__init__.py +3 -3
  38. pyglet/font/pyodide_js.py +310 -0
  39. pyglet/font/quartz.py +319 -126
  40. pyglet/font/ttf.py +45 -3
  41. pyglet/font/user.py +14 -19
  42. pyglet/font/win32.py +45 -21
  43. pyglet/graphics/__init__.py +8 -787
  44. pyglet/graphics/allocation.py +115 -1
  45. pyglet/graphics/api/__init__.py +77 -0
  46. pyglet/graphics/api/base.py +299 -0
  47. pyglet/graphics/api/gl/__init__.py +58 -0
  48. pyglet/graphics/api/gl/base.py +24 -0
  49. pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
  50. pyglet/graphics/api/gl/cocoa/context.py +76 -0
  51. pyglet/graphics/api/gl/context.py +391 -0
  52. pyglet/graphics/api/gl/default_shaders.py +0 -0
  53. pyglet/graphics/api/gl/draw.py +627 -0
  54. pyglet/graphics/api/gl/egl/__init__.py +0 -0
  55. pyglet/graphics/api/gl/egl/context.py +92 -0
  56. pyglet/graphics/api/gl/enums.py +76 -0
  57. pyglet/graphics/api/gl/framebuffer.py +315 -0
  58. pyglet/graphics/api/gl/gl.py +5463 -0
  59. pyglet/graphics/api/gl/gl_info.py +188 -0
  60. pyglet/graphics/api/gl/global_opengl.py +226 -0
  61. pyglet/{gl → graphics/api/gl}/lib.py +34 -18
  62. pyglet/graphics/api/gl/shader.py +1476 -0
  63. pyglet/graphics/api/gl/shapes.py +55 -0
  64. pyglet/graphics/api/gl/sprite.py +102 -0
  65. pyglet/graphics/api/gl/state.py +219 -0
  66. pyglet/graphics/api/gl/text.py +190 -0
  67. pyglet/graphics/api/gl/texture.py +1526 -0
  68. pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
  69. pyglet/graphics/api/gl/vertexdomain.py +751 -0
  70. pyglet/graphics/api/gl/win32/__init__.py +0 -0
  71. pyglet/graphics/api/gl/win32/context.py +108 -0
  72. pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
  73. pyglet/graphics/api/gl/xlib/__init__.py +0 -0
  74. pyglet/graphics/api/gl/xlib/context.py +174 -0
  75. pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
  76. pyglet/graphics/api/gl1/__init__.py +0 -0
  77. pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
  78. pyglet/graphics/api/gl2/__init__.py +0 -0
  79. pyglet/graphics/api/gl2/buffer.py +320 -0
  80. pyglet/graphics/api/gl2/draw.py +600 -0
  81. pyglet/graphics/api/gl2/global_opengl.py +122 -0
  82. pyglet/graphics/api/gl2/shader.py +200 -0
  83. pyglet/graphics/api/gl2/shapes.py +51 -0
  84. pyglet/graphics/api/gl2/sprite.py +79 -0
  85. pyglet/graphics/api/gl2/text.py +175 -0
  86. pyglet/graphics/api/gl2/vertexdomain.py +364 -0
  87. pyglet/graphics/api/webgl/__init__.py +233 -0
  88. pyglet/graphics/api/webgl/buffer.py +302 -0
  89. pyglet/graphics/api/webgl/context.py +234 -0
  90. pyglet/graphics/api/webgl/draw.py +590 -0
  91. pyglet/graphics/api/webgl/enums.py +76 -0
  92. pyglet/graphics/api/webgl/framebuffer.py +360 -0
  93. pyglet/graphics/api/webgl/gl.py +1537 -0
  94. pyglet/graphics/api/webgl/gl_info.py +130 -0
  95. pyglet/graphics/api/webgl/shader.py +1346 -0
  96. pyglet/graphics/api/webgl/shapes.py +92 -0
  97. pyglet/graphics/api/webgl/sprite.py +102 -0
  98. pyglet/graphics/api/webgl/state.py +227 -0
  99. pyglet/graphics/api/webgl/text.py +187 -0
  100. pyglet/graphics/api/webgl/texture.py +1227 -0
  101. pyglet/graphics/api/webgl/vertexarray.py +54 -0
  102. pyglet/graphics/api/webgl/vertexdomain.py +616 -0
  103. pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
  104. pyglet/{image → graphics}/atlas.py +33 -32
  105. pyglet/graphics/base.py +10 -0
  106. pyglet/graphics/buffer.py +245 -0
  107. pyglet/graphics/draw.py +578 -0
  108. pyglet/graphics/framebuffer.py +26 -0
  109. pyglet/graphics/instance.py +178 -69
  110. pyglet/graphics/shader.py +267 -1553
  111. pyglet/graphics/state.py +83 -0
  112. pyglet/graphics/texture.py +703 -0
  113. pyglet/graphics/vertexdomain.py +695 -538
  114. pyglet/gui/ninepatch.py +10 -10
  115. pyglet/gui/widgets.py +120 -10
  116. pyglet/image/__init__.py +20 -1973
  117. pyglet/image/animation.py +12 -12
  118. pyglet/image/base.py +730 -0
  119. pyglet/image/codecs/__init__.py +9 -0
  120. pyglet/image/codecs/bmp.py +53 -30
  121. pyglet/image/codecs/dds.py +53 -31
  122. pyglet/image/codecs/gdiplus.py +38 -14
  123. pyglet/image/codecs/gdkpixbuf2.py +0 -2
  124. pyglet/image/codecs/js_image.py +99 -0
  125. pyglet/image/codecs/ktx2.py +161 -0
  126. pyglet/image/codecs/pil.py +1 -1
  127. pyglet/image/codecs/png.py +1 -1
  128. pyglet/image/codecs/wic.py +11 -2
  129. pyglet/info.py +26 -24
  130. pyglet/input/__init__.py +8 -0
  131. pyglet/input/base.py +163 -105
  132. pyglet/input/controller.py +13 -19
  133. pyglet/input/controller_db.py +39 -24
  134. pyglet/input/emscripten/__init__.py +18 -0
  135. pyglet/input/emscripten/gamepad_js.py +397 -0
  136. pyglet/input/linux/__init__.py +11 -5
  137. pyglet/input/linux/evdev.py +10 -11
  138. pyglet/input/linux/x11_xinput.py +2 -2
  139. pyglet/input/linux/x11_xinput_tablet.py +1 -1
  140. pyglet/input/macos/__init__.py +7 -2
  141. pyglet/input/macos/darwin_gc.py +559 -0
  142. pyglet/input/win32/__init__.py +1 -1
  143. pyglet/input/win32/directinput.py +34 -29
  144. pyglet/input/win32/xinput.py +11 -61
  145. pyglet/lib.py +3 -3
  146. pyglet/libs/__init__.py +1 -1
  147. pyglet/{gl → libs/darwin}/agl.py +1 -1
  148. pyglet/libs/darwin/cocoapy/__init__.py +2 -2
  149. pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
  150. pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
  151. pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
  152. pyglet/libs/darwin/cocoapy/runtime.py +81 -45
  153. pyglet/libs/darwin/coreaudio.py +4 -4
  154. pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
  155. pyglet/libs/darwin/quartzkey.py +1 -3
  156. pyglet/libs/egl/__init__.py +2 -0
  157. pyglet/libs/egl/egl_lib.py +576 -0
  158. pyglet/libs/egl/eglext.py +51 -5
  159. pyglet/libs/linux/__init__.py +0 -0
  160. pyglet/libs/linux/egl/__init__.py +0 -0
  161. pyglet/libs/linux/egl/eglext.py +22 -0
  162. pyglet/libs/linux/glx/__init__.py +0 -0
  163. pyglet/{gl → libs/linux/glx}/glx.py +13 -14
  164. pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
  165. pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
  166. pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
  167. pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
  168. pyglet/libs/linux/wayland/__init__.py +0 -0
  169. pyglet/libs/linux/wayland/client.py +1068 -0
  170. pyglet/libs/linux/wayland/lib_wayland.py +207 -0
  171. pyglet/libs/linux/wayland/wayland_egl.py +38 -0
  172. pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
  173. pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
  174. pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
  175. pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
  176. pyglet/libs/linux/x11/xrandr.py +0 -0
  177. pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
  178. pyglet/libs/shared/__init__.py +0 -0
  179. pyglet/libs/shared/spirv/__init__.py +0 -0
  180. pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
  181. pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
  182. pyglet/libs/win32/__init__.py +28 -8
  183. pyglet/libs/win32/constants.py +59 -48
  184. pyglet/libs/win32/context_managers.py +20 -3
  185. pyglet/libs/win32/dinput.py +105 -88
  186. pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
  187. pyglet/libs/win32/types.py +58 -23
  188. pyglet/{gl → libs/win32}/wgl.py +32 -25
  189. pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
  190. pyglet/media/__init__.py +9 -10
  191. pyglet/media/codecs/__init__.py +12 -1
  192. pyglet/media/codecs/base.py +99 -96
  193. pyglet/media/codecs/ffmpeg.py +2 -2
  194. pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
  195. pyglet/media/codecs/webaudio_pyodide.py +111 -0
  196. pyglet/media/drivers/__init__.py +9 -4
  197. pyglet/media/drivers/base.py +4 -4
  198. pyglet/media/drivers/openal/__init__.py +1 -1
  199. pyglet/media/drivers/openal/adaptation.py +3 -3
  200. pyglet/media/drivers/pulse/__init__.py +1 -1
  201. pyglet/media/drivers/pulse/adaptation.py +3 -3
  202. pyglet/media/drivers/pyodide_js/__init__.py +8 -0
  203. pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
  204. pyglet/media/drivers/xaudio2/adaptation.py +3 -3
  205. pyglet/media/player.py +276 -193
  206. pyglet/media/player_worker_thread.py +1 -1
  207. pyglet/model/__init__.py +39 -29
  208. pyglet/model/codecs/base.py +4 -4
  209. pyglet/model/codecs/gltf.py +3 -3
  210. pyglet/model/codecs/obj.py +71 -43
  211. pyglet/resource.py +129 -78
  212. pyglet/shapes.py +154 -194
  213. pyglet/sprite.py +47 -164
  214. pyglet/text/__init__.py +44 -54
  215. pyglet/text/caret.py +12 -7
  216. pyglet/text/document.py +19 -17
  217. pyglet/text/formats/html.py +2 -2
  218. pyglet/text/formats/structured.py +10 -40
  219. pyglet/text/layout/__init__.py +20 -13
  220. pyglet/text/layout/base.py +176 -287
  221. pyglet/text/layout/incremental.py +9 -10
  222. pyglet/text/layout/scrolling.py +7 -95
  223. pyglet/window/__init__.py +183 -172
  224. pyglet/window/cocoa/__init__.py +62 -51
  225. pyglet/window/cocoa/pyglet_delegate.py +2 -25
  226. pyglet/window/cocoa/pyglet_view.py +9 -8
  227. pyglet/window/dialog/__init__.py +184 -0
  228. pyglet/window/dialog/base.py +99 -0
  229. pyglet/window/dialog/darwin.py +121 -0
  230. pyglet/window/dialog/linux.py +72 -0
  231. pyglet/window/dialog/windows.py +194 -0
  232. pyglet/window/emscripten/__init__.py +779 -0
  233. pyglet/window/headless/__init__.py +44 -28
  234. pyglet/window/key.py +2 -0
  235. pyglet/window/mouse.py +2 -2
  236. pyglet/window/wayland/__init__.py +377 -0
  237. pyglet/window/win32/__init__.py +101 -46
  238. pyglet/window/xlib/__init__.py +104 -66
  239. {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
  240. pyglet-3.0.dev1.dist-info/RECORD +322 -0
  241. {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
  242. pyglet/gl/__init__.py +0 -208
  243. pyglet/gl/base.py +0 -499
  244. pyglet/gl/cocoa.py +0 -309
  245. pyglet/gl/gl.py +0 -4625
  246. pyglet/gl/gl.pyi +0 -2320
  247. pyglet/gl/gl_compat.pyi +0 -3097
  248. pyglet/gl/gl_info.py +0 -190
  249. pyglet/gl/headless.py +0 -166
  250. pyglet/gl/wgl_info.py +0 -36
  251. pyglet/gl/wglext_nv.py +0 -1096
  252. pyglet/gl/win32.py +0 -268
  253. pyglet/gl/xlib.py +0 -295
  254. pyglet/image/buffer.py +0 -274
  255. pyglet/image/codecs/s3tc.py +0 -354
  256. pyglet/libs/x11/xrandr.py +0 -166
  257. pyglet-2.1.13.dist-info/RECORD +0 -234
  258. /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
  259. /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
  260. /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
  261. /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
  262. /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
  263. /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
  264. /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
  265. /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
  266. /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
  267. {pyglet-2.1.13.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
pyglet/window/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """Windowing and user-interface events.
2
2
 
3
- This module allows applications to create and display windows with an
4
- OpenGL context. Windows can be created with a variety of border styles
3
+ This module allows applications to create and display windows with a
4
+ graphical context. Windows can be created with a variety of border styles
5
5
  or set fullscreen.
6
6
 
7
7
  You can register event handlers for keyboard, mouse and window events.
@@ -62,50 +62,42 @@ opening a fullscreen window on each screen::
62
62
 
63
63
  Specifying a screen has no effect if the window is not fullscreen.
64
64
 
65
- Specifying the OpenGL context properties
65
+ Specifying the Graphical context properties
66
66
  ----------------------------------------
67
67
 
68
68
  Each window has its own context which is created when the window is created.
69
69
  You can specify the properties of the context before it is created
70
70
  by creating a "template" configuration::
71
71
 
72
- from pyglet import gl
72
+ from pyglet.graphics.api import get_config
73
73
  # Create template config
74
- config = gl.Config()
74
+ config = get_config()
75
75
  config.stencil_size = 8
76
76
  config.aux_buffers = 4
77
77
  # Create a window using this config
78
78
  win = window.Window(config=config)
79
-
80
- To determine if a given configuration is supported, query the screen (see
81
- above, "Working with multiple screens")::
82
-
83
- configs = screen.get_matching_configs(config)
84
- if not configs:
85
- # ... config is not supported
86
- else:
87
- win = window.Window(config=configs[0])
88
-
89
79
  """
90
80
  from __future__ import annotations
91
81
 
82
+ import atexit
92
83
  import sys
93
84
  from abc import abstractmethod
85
+ from collections.abc import Iterable
94
86
  from collections import deque
95
87
  from typing import TYPE_CHECKING, Any, Callable, Sequence
96
88
 
97
89
  import pyglet
98
90
  import pyglet.window.key
99
91
  import pyglet.window.mouse
100
- from pyglet import gl
92
+ from pyglet.config import UserConfig
101
93
  from pyglet.event import EVENT_HANDLE_STATE, EventDispatcher
102
- from pyglet.graphics import shader
94
+
103
95
  from pyglet.math import Mat4
104
- from pyglet.window import event, key
96
+ from pyglet.window import event, key, dialog
105
97
 
106
98
  if TYPE_CHECKING:
99
+ from pyglet.graphics.api.base import VerifiedGraphicsConfig, SurfaceContext, GraphicsConfig
107
100
  from pyglet.display.base import Display, Screen, ScreenMode
108
- from pyglet.gl import DisplayConfig, Config, Context
109
101
  from pyglet.text import Label
110
102
 
111
103
  _is_pyglet_doc_run = hasattr(sys, 'is_pyglet_doc_run') and sys.is_pyglet_doc_run
@@ -134,8 +126,8 @@ class MouseCursorException(WindowException):
134
126
  class MouseCursor:
135
127
  """An abstract mouse cursor."""
136
128
 
137
- #: Indicates if the cursor is drawn using OpenGL, or natively.
138
- gl_drawable: bool = True
129
+ #: Indicates if the cursor is drawn via the graphical api, or natively by the operating system.
130
+ api_drawable: bool = True
139
131
  hw_drawable: bool = False
140
132
 
141
133
  def draw(self, x: int, y: int) -> None:
@@ -157,7 +149,7 @@ class MouseCursor:
157
149
 
158
150
  class DefaultMouseCursor(MouseCursor):
159
151
  """The default mouse cursor set by the operating system."""
160
- gl_drawable: bool = False
152
+ api_drawable: bool = False
161
153
  hw_drawable: bool = True
162
154
 
163
155
 
@@ -165,14 +157,14 @@ class ImageMouseCursor(MouseCursor):
165
157
  """A user-defined mouse cursor created from an image.
166
158
 
167
159
  Use this class to create your own mouse cursors and assign them
168
- to windows. Cursors can be drawn by OpenGL, or optionally passed
160
+ to windows. Cursors can be drawn by the graphics API, or optionally passed
169
161
  to the OS to render natively. There are no restrictions on cursors
170
- drawn by OpenGL, but natively rendered cursors may have some
162
+ drawn by the graphical API, but natively rendered cursors may have some
171
163
  platform limitations (such as color depth, or size). In general,
172
164
  reasonably sized cursors will render correctly
173
165
  """
174
166
 
175
- def __init__(self, image: pyglet.image.AbstractImage, hot_x: int = 0, hot_y: int = 0,
167
+ def __init__(self, image: pyglet.image._AbstractImage, hot_x: int = 0, hot_y: int = 0,
176
168
  acceleration: bool = False) -> None:
177
169
  """Create a mouse cursor from an image.
178
170
 
@@ -186,10 +178,10 @@ class ImageMouseCursor(MouseCursor):
186
178
  Y coordinate of the "hot" spot in the image, relative to the image's anchor.
187
179
  May be clamped to the maximum image height if acceleration is enabled.
188
180
  acceleration:
189
- If ``True``, draw the cursor natively instead of using OpenGL.
181
+ If ``True``, draw the cursor natively instead of using the graphics API.
190
182
  The image may be downsampled or color reduced to fit the platform limitations.
191
183
  """
192
- self.texture = image.get_texture()
184
+ self.texture = image
193
185
  self.hot_x = hot_x
194
186
  self.hot_y = hot_y
195
187
  self.scaling = 1.0
@@ -198,10 +190,12 @@ class ImageMouseCursor(MouseCursor):
198
190
  self.hw_drawable = acceleration
199
191
 
200
192
  def draw(self, x: int, y: int) -> None:
201
- gl.glEnable(gl.GL_BLEND)
202
- gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
203
- self.texture.blit((x - self.hot_x) / self.scaling, (y - self.hot_y) / self.scaling, 0)
204
- gl.glDisable(gl.GL_BLEND)
193
+ pass
194
+ # Create agnostic version.
195
+ # gl.glEnable(gl.GL_BLEND)
196
+ # gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
197
+ # self.texture.blit((x - self.hot_x) / self.scaling, (y - self.hot_y) / self.scaling, 0)
198
+ # gl.glDisable(gl.GL_BLEND)
205
199
 
206
200
 
207
201
  def _PlatformEventHandler(data: Any) -> Callable: # noqa: N802
@@ -255,8 +249,8 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
255
249
 
256
250
  A window is a "heavyweight" object occupying operating system resources.
257
251
  The "client" or "content" area of a window is filled entirely with
258
- an OpenGL viewport. Applications have no access to operating system
259
- widgets or controls; all rendering must be done via OpenGL.
252
+ a graphical API's viewport, if enabled. Applications have no access to operating system
253
+ widgets or controls; all rendering must be done via a graphical API backend.
260
254
 
261
255
  Windows may appear as floating regions or can be set to fill an entire
262
256
  screen (fullscreen). When floating, windows may appear borderless or
@@ -268,7 +262,7 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
268
262
  conventions. This will ensure it is not obscured by other windows,
269
263
  and appears on an appropriate screen for the user.
270
264
 
271
- To render into a window, you must first call its :py:meth:`.switch_to`
265
+ For OpenGL, to render into a window, you must first call its :py:meth:`.switch_to`
272
266
  method to make it the active OpenGL context. If you use only one
273
267
  window in your application, you can skip this step as it will always
274
268
  be the active context.
@@ -372,8 +366,8 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
372
366
  _vsync: bool = False
373
367
  _file_drops: bool = False
374
368
  _screen: Screen | None = None
375
- _config: DisplayConfig | None = None
376
- _context: Context | None = None
369
+ _config: VerifiedGraphicsConfig | None = None
370
+ _context: SurfaceContext | None = None
377
371
  _projection_matrix: Mat4 = pyglet.math.Mat4()
378
372
  _view_matrix: Mat4 = pyglet.math.Mat4()
379
373
  _viewport: tuple[int, int, int, int] = 0, 0, 0, 0
@@ -408,31 +402,6 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
408
402
  _requested_width: int
409
403
  _requested_height: int
410
404
 
411
- # Create a default ShaderProgram, so the Window instance can
412
- # update the `WindowBlock` UBO shared by all default shaders.
413
- _default_vertex_source = """#version 150 core
414
- in vec4 position;
415
-
416
- uniform WindowBlock
417
- {
418
- mat4 projection;
419
- mat4 view;
420
- } window;
421
-
422
- void main()
423
- {
424
- gl_Position = window.projection * window.view * position;
425
- }
426
- """
427
- _default_fragment_source = """#version 150 core
428
- out vec4 color;
429
-
430
- void main()
431
- {
432
- color = vec4(1.0, 0.0, 0.0, 1.0);
433
- }
434
- """
435
-
436
405
  def __init__(self,
437
406
  width: int | None = None,
438
407
  height: int | None = None,
@@ -445,8 +414,8 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
445
414
  file_drops: bool = False,
446
415
  display: Display | None = None,
447
416
  screen: Screen | None = None,
448
- config: Config | None = None,
449
- context: Context | None = None,
417
+ config: UserConfig | Sequence[UserConfig] | None = None,
418
+ context: SurfaceContext | None = None,
450
419
  mode: ScreenMode | None = None) -> None:
451
420
  """Create a window.
452
421
 
@@ -460,8 +429,7 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
460
429
  created.
461
430
 
462
431
  ``config`` is a special case; it can be a template created by the
463
- user specifying the attributes desired, or it can be a complete
464
- ``config`` as returned from :py:meth:`~pyglet.display.Screen.get_matching_configs` or similar.
432
+ user specifying the attributes desired
465
433
 
466
434
  The context will be active as soon as the window is created, as if
467
435
  :py:meth:`~pyglet.window.Window.switch_to` was just called.
@@ -505,51 +473,15 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
505
473
  EventDispatcher.__init__(self)
506
474
  self._event_queue = deque()
507
475
 
476
+ self._config = config
477
+ self._context = context
478
+
508
479
  if not display:
509
480
  display = pyglet.display.get_display()
510
481
 
511
482
  if not screen:
512
483
  screen = display.get_default_screen()
513
484
 
514
- if not config:
515
- alpha_size = None
516
- transparent_fb = False
517
- # Override config settings if intention is transparency.
518
- if style in ('transparent', 'overlay'):
519
- # Ensure the framebuffer is large enough to support transparency.
520
- alpha_size = 8
521
- transparent_fb = True
522
-
523
- for template_config in [
524
- gl.Config(double_buffer=True, depth_size=24, major_version=3, minor_version=3,
525
- alpha_size=alpha_size, transparent_framebuffer=transparent_fb),
526
- gl.Config(double_buffer=True, depth_size=16, major_version=3, minor_version=3,
527
- alpha_size=alpha_size, transparent_framebuffer=transparent_fb),
528
- None,
529
- ]:
530
- try:
531
- config = screen.get_best_config(template_config)
532
- break
533
- except NoSuchConfigException:
534
- pass
535
- if not config:
536
- msg = 'No standard config is available.'
537
- raise NoSuchConfigException(msg)
538
- else:
539
- if style in ('transparent', 'overlay'):
540
- config.alpha_size = 8
541
- config.transparent_framebuffer = True
542
-
543
- if not config.is_complete():
544
- config = screen.get_best_config(config)
545
-
546
- if not context:
547
- context = config.create_context(gl.current_context)
548
-
549
- # Set these in reverse order as above, to ensure we get user preference
550
- self._context = context
551
- self._config = self._context.config
552
-
553
485
  # XXX deprecate config's being screen-specific
554
486
  if hasattr(self._config, 'screen'):
555
487
  self._screen = self._config.screen
@@ -577,8 +509,8 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
577
509
  self._resizable = resizable
578
510
  self._fullscreen = fullscreen
579
511
  self._style = style
580
- if pyglet.options['vsync'] is not None:
581
- self._vsync = pyglet.options['vsync']
512
+ if pyglet.options.vsync is not None:
513
+ self._vsync = pyglet.options.vsync
582
514
  else:
583
515
  self._vsync = vsync
584
516
 
@@ -589,26 +521,61 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
589
521
  app.windows.add(self)
590
522
  self._create()
591
523
 
592
- self.switch_to()
593
-
594
- self._create_projection()
524
+ if pyglet.options.backend and not self._shadow:
525
+ self.switch_to()
526
+ self._create_projection()
595
527
 
596
528
  if visible:
597
529
  self.set_visible(True)
598
530
  self.activate()
599
531
 
600
- def _create_projection(self) -> None:
601
- self._default_program = shader.ShaderProgram(
602
- shader.Shader(self._default_vertex_source, 'vertex'),
603
- shader.Shader(self._default_fragment_source, 'fragment'))
532
+ def _assign_config(self) -> None:
533
+ if pyglet.options.backend:
534
+ config = self._config
535
+ context = self._context
604
536
 
605
- self.ubo = self._default_program.uniform_blocks['WindowBlock'].create_ubo()
537
+ if not config:
538
+ for template_config in pyglet.graphics.api.get_default_configs():
539
+ if self._style in ('transparent', 'overlay'):
540
+ template_config.alpha_size = 8
541
+ template_config.transparent_framebuffer = True
542
+
543
+ if config := pyglet.config.match_surface_config(template_config, self):
544
+ break
545
+
546
+ if not config:
547
+ msg = 'No standard config is available.'
548
+ raise NoSuchConfigException(msg)
549
+
550
+ if isinstance(config, Iterable):
551
+ for cfg in config:
552
+ if cfg.is_finalized:
553
+ config = cfg
554
+ break
555
+
556
+ if config := pyglet.config.match_surface_config(cfg, self):
557
+ break
558
+ else:
559
+ if not config.is_finalized:
560
+ config = pyglet.config.match_surface_config(config, self)
606
561
 
607
- self._viewport = 0, 0, *self.get_framebuffer_size()
562
+ if not config:
563
+ msg = 'No standard config is available.'
564
+ raise NoSuchConfigException(msg)
565
+
566
+ if not context:
567
+ from pyglet.graphics.api import core
568
+ if core:
569
+ context = core.get_surface_context(self, config)
570
+
571
+ # Set these in reverse order as above, to ensure we get user preference
572
+ self._context = context
573
+ self._config = self._context.config
608
574
 
609
- width, height = self.get_size()
610
- self.view = Mat4()
611
- self.projection = Mat4.orthogonal_projection(0, width, 0, height, -8192, 8192)
575
+ def _create_projection(self) -> None:
576
+ self._matrices = self.context.core.initialize_matrices(self)
577
+
578
+ self._viewport = 0, 0, *self.get_framebuffer_size()
612
579
 
613
580
  def __del__(self) -> None:
614
581
  # Always try to clean up the window when it is dereferenced.
@@ -620,7 +587,7 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
620
587
  pass
621
588
 
622
589
  def __repr__(self) -> str:
623
- return f'{self.__class__.__name__}=(width={self.width}, height={self.height})'
590
+ return f'{self.__class__.__name__}(width={self.width}, height={self.height})'
624
591
 
625
592
  @abstractmethod
626
593
  def _create(self) -> None:
@@ -648,15 +615,14 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
648
615
  window's taskbar icon will flash, indicating it requires attention.
649
616
  """
650
617
 
651
- @staticmethod
652
- def clear() -> None:
618
+ def clear(self) -> None:
653
619
  """Clear the window.
654
620
 
655
621
  This is a convenience method for clearing the color and depth
656
622
  buffer. The window must be the active context (see
657
623
  :py:meth:`.switch_to`).
658
624
  """
659
- gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
625
+ self.context.clear()
660
626
 
661
627
  def close(self) -> None:
662
628
  """Close the window.
@@ -705,9 +671,9 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
705
671
  :py:meth:`~pyglet.window.Window.on_draw` and
706
672
  :py:meth:`~pyglet.window.Window.on_refresh`
707
673
  events. Finally, it calls the :py:meth:`~pyglet.window.Window.flip`
708
- method to swap the front and back OpenGL buffers.
674
+ method to swap the front and back buffers.
709
675
  """
710
- self.switch_to()
676
+ self.before_draw()
711
677
  self.dispatch_event('on_draw')
712
678
  self.dispatch_event('on_refresh', dt)
713
679
  self.flip()
@@ -724,13 +690,13 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
724
690
  """
725
691
  # Draw mouse cursor if set and visible.
726
692
 
727
- if self._mouse_cursor.gl_drawable and self._mouse_visible and self._mouse_in_window:
693
+ if self._mouse_cursor.api_drawable and self._mouse_visible and self._mouse_in_window:
728
694
  # TODO: consider projection differences
729
695
  self._mouse_cursor.draw(self._mouse_x, self._mouse_y)
730
696
 
731
697
  @abstractmethod
732
698
  def flip(self) -> None:
733
- """Swap the OpenGL front and back buffers.
699
+ """Swap the front and back buffers.
734
700
 
735
701
  Call this method on a double-buffered window to update the
736
702
  visible display with the back buffer. Windows are
@@ -869,17 +835,18 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
869
835
  self.dispatch_event('on_close')
870
836
 
871
837
  def _on_internal_resize(self, width: int, height: int) -> None:
872
- framebuffer_size = self.get_framebuffer_size()
873
- gl.glViewport(0, 0, max(framebuffer_size[0], 1), max(framebuffer_size[1], 1))
838
+ self.viewport = (0, 0, *self.get_framebuffer_size())
874
839
  w, h = self.get_size()
875
- self.projection = Mat4.orthogonal_projection(0, max(w, 1), 0, max(h, 1), -8192, 8192)
840
+ if self.context:
841
+ self.projection = Mat4.orthogonal_projection(0, w, 0, h, -8192, 8192)
876
842
  self.dispatch_event('on_resize', w, h)
843
+ #self.context.resized(w, h)
877
844
 
878
845
  def _on_internal_scale(self, scale: float, dpi: int) -> None:
879
- framebuffer_size = self.get_framebuffer_size()
880
- gl.glViewport(0, 0, max(framebuffer_size[0], 1), max(framebuffer_size[1], 1))
846
+ self.viewport = (0, 0, *self.get_framebuffer_size())
881
847
  w, h = self.get_size()
882
- self.projection = Mat4.orthogonal_projection(0, max(w, 1), 0, max(h, 1), -8192, 8192)
848
+ if self.context:
849
+ self.projection = Mat4.orthogonal_projection(0, max(w, 1), 0, max(h, 1), -8192, 8192)
883
850
  self._mouse_cursor.scaling = self._get_mouse_scale()
884
851
  self.dispatch_event('on_scale', scale, dpi)
885
852
 
@@ -1107,23 +1074,23 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1107
1074
  """
1108
1075
  self._vsync = vsync
1109
1076
 
1110
- def set_mouse_visible(self, visible: bool = True) -> None:
1077
+ def set_mouse_cursor_visible(self, visible: bool = True) -> None:
1111
1078
  """Show or hide the mouse cursor.
1112
1079
 
1113
1080
  The mouse cursor will only be hidden while it is positioned within
1114
1081
  this window. Mouse events will still be processed as usual.
1115
1082
  """
1116
1083
  self._mouse_visible = visible
1117
- self.set_mouse_platform_visible()
1084
+ self.set_mouse_cursor_platform_visible()
1118
1085
 
1119
- def set_mouse_platform_visible(self, platform_visible: bool | None = None) -> None:
1086
+ def set_mouse_cursor_platform_visible(self, platform_visible: bool | None = None) -> None:
1120
1087
  """Set the platform-drawn mouse cursor visibility.
1121
1088
 
1122
1089
  This is called automatically after changing the mouse cursor or exclusive mode.
1123
1090
 
1124
1091
  Applications should not normally need to call this method.
1125
1092
 
1126
- :see: :py:meth:`~pyglet.window.Window.set_mouse_visible` instead.
1093
+ :see: :py:meth:`~pyglet.window.Window.set_mouse_cursor_visible` instead.
1127
1094
 
1128
1095
  Args:
1129
1096
  platform_visible:
@@ -1149,9 +1116,9 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1149
1116
  cursor = DefaultMouseCursor()
1150
1117
  self._mouse_cursor = cursor
1151
1118
  self._mouse_cursor.scaling = self._get_mouse_scale()
1152
- self.set_mouse_platform_visible()
1119
+ self.set_mouse_cursor_platform_visible()
1153
1120
 
1154
- def _get_mouse_scale(self):
1121
+ def _get_mouse_scale(self) -> float:
1155
1122
  """The mouse scale factoring in the DPI.
1156
1123
 
1157
1124
  On Mac, this is always 1.0.
@@ -1179,7 +1146,7 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1179
1146
  """
1180
1147
  self._keyboard_exclusive = exclusive
1181
1148
 
1182
- def set_icon(self, *images: pyglet.image.AbstractImage) -> None:
1149
+ def set_icon(self, *images: pyglet.image._AbstractImage) -> None:
1183
1150
  """Set the window icon.
1184
1151
 
1185
1152
  If multiple images are provided, one with an appropriate size
@@ -1192,17 +1159,21 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1192
1159
 
1193
1160
  @abstractmethod
1194
1161
  def switch_to(self) -> None:
1195
- """Make this window the current OpenGL rendering context.
1162
+ """Make this window the current rendering context.
1196
1163
 
1197
1164
  Only one OpenGL context can be active at a time. This method
1198
1165
  sets the current window context as the active one.
1199
1166
 
1200
1167
  In most cases, you should use this method instead of directly
1201
- calling :py:meth:`~pyglet.gl.Context.set_current`. The latter
1168
+ calling :py:meth:`~pyglet.graphics.api.gl.Context.set_current`. The latter
1202
1169
  will not perform platform-specific state management tasks for
1203
1170
  you.
1204
1171
  """
1205
1172
 
1173
+ @abstractmethod
1174
+ def before_draw(self) -> None:
1175
+ ...
1176
+
1206
1177
  # Attributes (sort alphabetically):
1207
1178
  @property
1208
1179
  def caption(self) -> str:
@@ -1245,13 +1216,18 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1245
1216
  return self._screen
1246
1217
 
1247
1218
  @property
1248
- def config(self) -> DisplayConfig:
1249
- """A GL config describing the context of this window. Read-only."""
1219
+ def config(self) -> VerifiedGraphicsConfig:
1220
+ """A graphical config describing the context of this window. Read-only."""
1250
1221
  return self._config
1251
1222
 
1252
1223
  @property
1253
- def context(self) -> Context:
1254
- """The OpenGL context attached to this window. Read-only."""
1224
+ def context(self) -> SurfaceContext:
1225
+ """The graphical context attached to this window. Read-only."""
1226
+ return self._context
1227
+
1228
+ @property
1229
+ def ctx(self) -> SurfaceContext:
1230
+ """The graphical context attached to this window. Read-only."""
1255
1231
  return self._context
1256
1232
 
1257
1233
  # These are the only properties that can be set
@@ -1279,10 +1255,7 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1279
1255
 
1280
1256
  Read only.
1281
1257
  """
1282
- if pyglet.options.dpi_scaling != "real":
1283
- return self._dpi / 96
1284
-
1285
- return 1.0
1258
+ return self._dpi / 96
1286
1259
 
1287
1260
  @property
1288
1261
  def dpi(self) -> int:
@@ -1309,7 +1282,7 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1309
1282
 
1310
1283
  @property
1311
1284
  def projection(self) -> Mat4:
1312
- """The OpenGL window projection matrix. Read-write.
1285
+ """The window projection matrix. Read-write.
1313
1286
 
1314
1287
  This matrix is used to transform vertices when using any of the built-in
1315
1288
  drawable classes. `view` is done first, then `projection`.
@@ -1322,19 +1295,15 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1322
1295
  (2D), but can be changed to any 4x4 matrix desired.
1323
1296
  :see: :py:class:`~pyglet.math.Mat4`.
1324
1297
  """
1325
- return self._projection_matrix
1298
+ return self._matrices.projection
1326
1299
 
1327
1300
  @projection.setter
1328
1301
  def projection(self, matrix: Mat4) -> None:
1329
-
1330
- with self.ubo as window_block:
1331
- window_block.projection[:] = matrix
1332
-
1333
- self._projection_matrix = matrix
1302
+ self._matrices.projection = matrix
1334
1303
 
1335
1304
  @property
1336
1305
  def view(self) -> Mat4:
1337
- """The OpenGL window view matrix. Read-write.
1306
+ """The window view matrix. Read-write.
1338
1307
 
1339
1308
  This matrix is used to transform vertices when using any of the built-in
1340
1309
  drawable classes. `view` is done first, then `projection`.
@@ -1343,15 +1312,11 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1343
1312
  :py:class:`~pyglet.math.Mat4` instance can be set.
1344
1313
  Alternatively, you can supply a flat tuple of 16 values.
1345
1314
  """
1346
- return self._view_matrix
1315
+ return self._matrices.view
1347
1316
 
1348
1317
  @view.setter
1349
1318
  def view(self, matrix: Mat4) -> None:
1350
-
1351
- with self.ubo as window_block:
1352
- window_block.view[:] = matrix
1353
-
1354
- self._view_matrix = matrix
1319
+ self._matrices.view = matrix
1355
1320
 
1356
1321
  @property
1357
1322
  def viewport(self) -> tuple[int, int, int, int]:
@@ -1364,9 +1329,10 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
1364
1329
  @viewport.setter
1365
1330
  def viewport(self, values: tuple[int, int, int, int]) -> None:
1366
1331
  self._viewport = values
1367
- pr = self.scale
1332
+ pr = 1.0
1368
1333
  x, y, w, h = values
1369
- pyglet.gl.glViewport(int(x * pr), int(y * pr), int(w * pr), int(h * pr))
1334
+ if self.context:
1335
+ self.context.core.set_viewport(self, int(x * pr), int(y * pr), int(w * pr), int(h * pr))
1370
1336
 
1371
1337
  # If documenting, show the event methods. Otherwise, leave them out
1372
1338
  # as they are not really methods.
@@ -1825,7 +1791,7 @@ class FPSDisplay:
1825
1791
  label: Label
1826
1792
 
1827
1793
  def __init__(self, window: pyglet.window.Window, color: tuple[int, int, int, int] = (127, 127, 127, 127),
1828
- samples: int = 240) -> None:
1794
+ batch=None, samples: int = 240) -> None:
1829
1795
  """Create an FPS Display.
1830
1796
 
1831
1797
  Args:
@@ -1846,7 +1812,7 @@ class FPSDisplay:
1846
1812
 
1847
1813
  # Hook into the Window.flip method:
1848
1814
  self._window_flip, window.flip = window.flip, self._hook_flip
1849
- self.label = Label('', x=10, y=10, font_size=24, weight='bold', color=color)
1815
+ self.label = Label('', x=10, y=10, font_size=24, weight="bold", color=color, batch=batch)
1850
1816
 
1851
1817
  self._elapsed = 0.0
1852
1818
  self._last_time = time()
@@ -1890,25 +1856,70 @@ if _is_pyglet_doc_run:
1890
1856
 
1891
1857
  else:
1892
1858
  # Try to determine which platform to use.
1893
- if pyglet.options['headless']:
1859
+ if pyglet.options.headless:
1894
1860
  from pyglet.window.headless import HeadlessWindow as Window
1895
1861
  elif pyglet.compat_platform == 'darwin':
1896
1862
  from pyglet.window.cocoa import CocoaWindow as Window
1897
1863
  elif pyglet.compat_platform in ('win32', 'cygwin'):
1898
1864
  from pyglet.window.win32 import Win32Window as Window
1899
- else:
1865
+ elif pyglet.compat_platform == 'linux' and pyglet.options.wayland:
1866
+ from pyglet.window.wayland import WaylandWindow as Window
1867
+ elif pyglet.compat_platform == 'linux':
1900
1868
  from pyglet.window.xlib import XlibWindow as Window
1869
+ elif pyglet.compat_platform == 'emscripten':
1870
+ from pyglet.window.emscripten import EmscriptenWindow as Window
1871
+
1872
+
1873
+ class _ShadowWindow(Window):
1874
+ """Helper Window class for things that require a window.
1875
+
1876
+ For example, on some operating systems, input detection or clipboards are tied to windows or window events.
1877
+ """
1878
+ _shadow = True
1879
+
1880
+ def __init__(self) -> None:
1881
+ super().__init__(width=1, height=1, visible=False)
1882
+
1883
+ def switch_to(self) -> None:
1884
+ """Shadow window does not have a context to switch to."""
1885
+
1886
+ def _assign_config(self) -> None:
1887
+ """Shadow window does not need a config or context."""
1888
+
1889
+ def _create_projection(self) -> None:
1890
+ """Shadow window does not need a projection."""
1891
+
1892
+ def _on_internal_resize(self, width: int, height: int) -> None:
1893
+ """No projection and not required."""
1894
+
1895
+ def _on_internal_scale(self, scale: float, dpi: int) -> None:
1896
+ """No projection and not required."""
1897
+
1898
+
1899
+ def _create_shadow_window() -> Window | None:
1900
+ # MacOS and browsers don't need a shadow window.
1901
+ if pyglet.compat_platform not in ('darwin', 'emscripten'):
1902
+ shadow_window = _ShadowWindow()
1903
+
1904
+ from pyglet import app # noqa: PLC0415
1905
+ app.windows.remove(shadow_window)
1906
+
1907
+ atexit.register(shadow_window.close)
1908
+
1909
+ return shadow_window
1910
+ return None
1901
1911
 
1902
- # Create shadow window. (trickery is for circular import)
1903
1912
  if not _is_pyglet_doc_run:
1904
- pyglet.window = sys.modules[__name__]
1905
- gl._create_shadow_window() # noqa: SLF001
1913
+ _shadow_window = _create_shadow_window()
1914
+ else:
1915
+ _shadow_window = None
1906
1916
 
1907
1917
 
1908
1918
  __all__ = (
1909
1919
  # imported
1910
1920
  "event",
1911
1921
  "key",
1922
+ "mouse",
1912
1923
  # classes
1913
1924
  "BaseWindow",
1914
1925
  "Window",