pyglet 2.1.6__py3-none-any.whl → 2.1.9__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 (74) hide show
  1. pyglet/__init__.py +27 -42
  2. pyglet/app/base.py +2 -2
  3. pyglet/clock.py +1 -1
  4. pyglet/display/base.py +31 -21
  5. pyglet/display/cocoa.py +25 -1
  6. pyglet/display/headless.py +12 -1
  7. pyglet/display/win32.py +134 -18
  8. pyglet/display/xlib.py +285 -70
  9. pyglet/event.py +17 -1
  10. pyglet/experimental/README.md +1 -1
  11. pyglet/experimental/jobs.py +1 -1
  12. pyglet/experimental/multitexture_sprite.py +2 -2
  13. pyglet/font/__init__.py +1 -1
  14. pyglet/font/base.py +8 -5
  15. pyglet/font/dwrite/__init__.py +13 -8
  16. pyglet/font/dwrite/dwrite_lib.py +1 -1
  17. pyglet/font/user.py +1 -1
  18. pyglet/gl/base.py +8 -4
  19. pyglet/gl/cocoa.py +4 -0
  20. pyglet/gl/gl.py +4 -3
  21. pyglet/gl/gl.pyi +2320 -0
  22. pyglet/gl/gl_compat.py +7 -18
  23. pyglet/gl/gl_compat.pyi +3097 -0
  24. pyglet/gl/xlib.py +24 -0
  25. pyglet/graphics/shader.py +8 -1
  26. pyglet/graphics/vertexbuffer.py +1 -1
  27. pyglet/gui/frame.py +2 -2
  28. pyglet/gui/widgets.py +1 -1
  29. pyglet/image/__init__.py +3 -3
  30. pyglet/image/buffer.py +3 -3
  31. pyglet/input/base.py +22 -12
  32. pyglet/input/linux/evdev.py +96 -23
  33. pyglet/input/linux/evdev_constants.py +2 -1
  34. pyglet/input/win32/xinput.py +6 -3
  35. pyglet/libs/darwin/cocoapy/cocoalibs.py +3 -1
  36. pyglet/libs/ioctl.py +2 -2
  37. pyglet/libs/win32/__init__.py +12 -0
  38. pyglet/libs/win32/constants.py +4 -0
  39. pyglet/libs/win32/types.py +97 -0
  40. pyglet/libs/x11/xrandr.py +166 -0
  41. pyglet/libs/x11/xrender.py +43 -0
  42. pyglet/libs/x11/xsync.py +43 -0
  43. pyglet/math.py +65 -54
  44. pyglet/media/buffered_logger.py +1 -1
  45. pyglet/media/codecs/ffmpeg.py +18 -34
  46. pyglet/media/codecs/gstreamer.py +3 -3
  47. pyglet/media/codecs/pyogg.py +1 -1
  48. pyglet/media/codecs/wave.py +6 -0
  49. pyglet/media/codecs/wmf.py +33 -7
  50. pyglet/media/devices/win32.py +1 -1
  51. pyglet/media/drivers/base.py +1 -1
  52. pyglet/media/drivers/directsound/interface.py +4 -0
  53. pyglet/media/drivers/listener.py +2 -2
  54. pyglet/media/drivers/xaudio2/interface.py +6 -2
  55. pyglet/media/drivers/xaudio2/lib_xaudio2.py +1 -1
  56. pyglet/media/instrumentation.py +2 -2
  57. pyglet/media/player.py +2 -2
  58. pyglet/media/player_worker_thread.py +1 -1
  59. pyglet/media/synthesis.py +1 -1
  60. pyglet/model/codecs/gltf.py +1 -1
  61. pyglet/shapes.py +1 -1
  62. pyglet/sprite.py +1 -1
  63. pyglet/text/caret.py +44 -5
  64. pyglet/text/layout/base.py +3 -3
  65. pyglet/util.py +1 -1
  66. pyglet/window/__init__.py +54 -14
  67. pyglet/window/cocoa/__init__.py +27 -0
  68. pyglet/window/mouse.py +11 -1
  69. pyglet/window/win32/__init__.py +40 -14
  70. pyglet/window/xlib/__init__.py +21 -7
  71. {pyglet-2.1.6.dist-info → pyglet-2.1.9.dist-info}/METADATA +1 -1
  72. {pyglet-2.1.6.dist-info → pyglet-2.1.9.dist-info}/RECORD +74 -70
  73. {pyglet-2.1.6.dist-info → pyglet-2.1.9.dist-info}/LICENSE +0 -0
  74. {pyglet-2.1.6.dist-info → pyglet-2.1.9.dist-info}/WHEEL +0 -0
@@ -114,6 +114,8 @@ _user32.DestroyWindow.restype = BOOL
114
114
  _user32.DestroyWindow.argtypes = [HWND]
115
115
  _user32.DispatchMessageW.restype = LRESULT
116
116
  _user32.DispatchMessageW.argtypes = [LPMSG]
117
+ _user32.EnumDisplayDevicesW.restype = BOOL
118
+ _user32.EnumDisplayDevicesW.argtypes = [LPCWSTR, DWORD, POINTER(DISPLAY_DEVICEW), DWORD]
117
119
  _user32.EnumDisplayMonitors.restype = BOOL
118
120
  _user32.EnumDisplayMonitors.argtypes = [HDC, LPRECT, MONITORENUMPROC, LPARAM]
119
121
  _user32.EnumDisplaySettingsW.restype = BOOL
@@ -131,6 +133,8 @@ _user32.GetDesktopWindow.restype = HWND
131
133
  _user32.GetDesktopWindow.argtypes = []
132
134
  _user32.GetKeyState.restype = c_short
133
135
  _user32.GetKeyState.argtypes = [c_int]
136
+ _user32.GetLayeredWindowAttributes.restype = BOOL
137
+ _user32.GetLayeredWindowAttributes.argtypes = [HWND, POINTER(COLORREF), POINTER(BYTE), POINTER(DWORD)]
134
138
  _user32.GetMessageW.restype = BOOL
135
139
  _user32.GetMessageW.argtypes = [LPMSG, HWND, UINT, UINT]
136
140
  _user32.GetMonitorInfoW.restype = BOOL
@@ -139,6 +143,8 @@ _user32.GetQueueStatus.restype = DWORD
139
143
  _user32.GetQueueStatus.argtypes = [UINT]
140
144
  _user32.GetSystemMetrics.restype = c_int
141
145
  _user32.GetSystemMetrics.argtypes = [c_int]
146
+ _user32.GetWindowLongW.restype = LONG
147
+ _user32.GetWindowLongW.argtypes = [HWND, c_int]
142
148
  _user32.LoadCursorW.restype = HCURSOR
143
149
  _user32.LoadCursorW.argtypes = [HINSTANCE, c_wchar_p]
144
150
  _user32.LoadIconW.restype = HICON
@@ -183,6 +189,8 @@ _user32.SetFocus.restype = HWND
183
189
  _user32.SetFocus.argtypes = [HWND]
184
190
  _user32.SetForegroundWindow.restype = BOOL
185
191
  _user32.SetForegroundWindow.argtypes = [HWND]
192
+ _user32.SetLayeredWindowAttributes.restype = BOOL
193
+ _user32.SetLayeredWindowAttributes.argtypes = [HWND, COLORREF, BYTE, DWORD]
186
194
  _user32.SetTimer.restype = UINT_PTR
187
195
  _user32.SetTimer.argtypes = [HWND, UINT_PTR, UINT, TIMERPROC]
188
196
  _user32.KillTimer.restype = UINT_PTR
@@ -249,6 +257,10 @@ _dwmapi.DwmIsCompositionEnabled.restype = c_int
249
257
  _dwmapi.DwmIsCompositionEnabled.argtypes = [POINTER(INT)]
250
258
  _dwmapi.DwmFlush.restype = c_int
251
259
  _dwmapi.DwmFlush.argtypes = []
260
+ _dwmapi.DwmGetColorizationColor.restype = HRESULT
261
+ _dwmapi.DwmGetColorizationColor.argtypes = [POINTER(DWORD), POINTER(BOOL)]
262
+ _dwmapi.DwmEnableBlurBehindWindow.restype = HRESULT
263
+ _dwmapi.DwmEnableBlurBehindWindow.argtypes = [HWND, POINTER(DWM_BLURBEHIND)]
252
264
 
253
265
  # _shell32
254
266
  _shell32.DragAcceptFiles.restype = c_void
@@ -5083,3 +5083,7 @@ DEVICE_NOTIFY_WINDOW_HANDLE = 0
5083
5083
  DEVICE_NOTIFY_SERVICE_HANDLE = 1
5084
5084
 
5085
5085
  USER_DEFAULT_SCREEN_DPI = 96
5086
+
5087
+ QDC_ONLY_ACTIVE_PATHS = 0x00000002
5088
+ DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 0x00000001
5089
+ DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 0x00000002
@@ -676,3 +676,100 @@ class DEV_BROADCAST_DEVICEINTERFACE(Structure):
676
676
  ('dbcc_classguid', com.GUID),
677
677
  ('dbcc_name', ctypes.c_wchar * 256)
678
678
  )
679
+
680
+
681
+ class DISPLAY_DEVICEW(ctypes.Structure):
682
+ _fields_ = [
683
+ ('cb', DWORD),
684
+ ('DeviceName', WCHAR * 32),
685
+ ('DeviceString', WCHAR * 128),
686
+ ('StateFlags', DWORD),
687
+ ('DeviceID', WCHAR * 128),
688
+ ('DeviceKey', WCHAR * 128),
689
+ ]
690
+
691
+
692
+ # Structures below are to retrieve a monitor name...
693
+ class LUID(ctypes.Structure):
694
+ _fields_ = [('LowPart', DWORD), ('HighPart', LONG)]
695
+
696
+
697
+ class _SourceInfoStruct(ctypes.Structure):
698
+ _fields_ = [('cloneGroupId', UINT32, 16), ('sourceModeInfoIdx', UINT32, 16)]
699
+
700
+
701
+ class _DisplayUnion(ctypes.Union):
702
+ _fields_ = [('modeInfoIdx', UINT32), ('DUMMYSTRUCTNAME', _SourceInfoStruct)]
703
+
704
+
705
+ class DISPLAYCONFIG_PATH_SOURCE_INFO(ctypes.Structure):
706
+ _fields_ = [('adapterId', LUID), ('id', UINT32), ('DUMMYUNIONNAME', _DisplayUnion), ('statusFlags', UINT32)]
707
+
708
+
709
+ class _DummyStructTarget(ctypes.Structure):
710
+ _fields_ = [
711
+ ('desktopModeInfoIdx', UINT32, 16),
712
+ ('targetModeInfoIdx', UINT32, 16),
713
+ ]
714
+
715
+
716
+ class _DummyUnionTarget(ctypes.Union):
717
+ _fields_ = [('modeInfoIdx', UINT32), ('DUMMYSTRUCTNAME', _DummyStructTarget)]
718
+
719
+
720
+ class DISPLAYCONFIG_RATIONAL(ctypes.Structure):
721
+ _fields_ = [('Numerator', UINT32), ('Denominator', UINT32)]
722
+
723
+ def __repr__(self):
724
+ return f"DISPLAYCONFIG_RATIONAL(num={self.Numerator}, denom={self.Denominator})"
725
+
726
+
727
+ class DISPLAYCONFIG_PATH_TARGET_INFO(ctypes.Structure):
728
+ _fields_ = [
729
+ ('adapterId', LUID),
730
+ ('id', UINT32),
731
+ ('DUMMYUNIONNAME', _DummyUnionTarget),
732
+ ('outputTechnology', UINT32),
733
+ ('rotation', UINT32),
734
+ ('scaling', UINT32),
735
+ ('refreshRate', DISPLAYCONFIG_RATIONAL),
736
+ ('scanLineOrdering', UINT32),
737
+ ('targetAvailable', BOOL),
738
+ ('statusFlags', UINT32),
739
+ ]
740
+
741
+
742
+ class DISPLAYCONFIG_PATH_INFO(ctypes.Structure):
743
+ _fields_ = [
744
+ ('sourceInfo', DISPLAYCONFIG_PATH_SOURCE_INFO),
745
+ ('targetInfo', DISPLAYCONFIG_PATH_TARGET_INFO),
746
+ ('flags', UINT32),
747
+ ]
748
+
749
+
750
+ class DISPLAYCONFIG_DEVICE_INFO_HEADER(ctypes.Structure):
751
+ _fields_ = [('type', UINT32),
752
+ ('size', UINT32),
753
+ ('adapterId', LUID),
754
+ ('id', UINT32)
755
+ ]
756
+
757
+
758
+ class DISPLAYCONFIG_SOURCE_DEVICE_NAME(ctypes.Structure):
759
+ _fields_ = [
760
+ ('header', DISPLAYCONFIG_DEVICE_INFO_HEADER),
761
+ ('viewGdiDeviceName', WCHAR * 32)
762
+ ]
763
+
764
+
765
+ class DISPLAYCONFIG_TARGET_DEVICE_NAME(ctypes.Structure):
766
+ _fields_ = [
767
+ ('header', DISPLAYCONFIG_DEVICE_INFO_HEADER),
768
+ ('flags', UINT32),
769
+ ('outputTechnology', UINT32),
770
+ ('edidManufactureId', UINT16),
771
+ ('edidProductCodeId', UINT16),
772
+ ('connectorInstance', UINT32),
773
+ ('monitorFriendlyDeviceName', WCHAR * 64),
774
+ ('monitorDevicePath', WCHAR * 128),
775
+ ]
@@ -0,0 +1,166 @@
1
+ import warnings
2
+ from ctypes import c_ulong, c_int, POINTER, Structure, c_char_p, c_uint, c_ushort
3
+
4
+ import pyglet
5
+ from pyglet.libs.x11.xlib import (
6
+ Time,
7
+ Window,
8
+ Display,
9
+ XCloseDisplay,
10
+ XDefaultRootWindow,
11
+ XOpenDisplay,
12
+ )
13
+
14
+ lib = None
15
+ try:
16
+ lib = pyglet.lib.load_library("Xrandr")
17
+ except ImportError:
18
+ if pyglet.options.debug_lib:
19
+ warnings.warn("Xrandr could not be loaded.")
20
+ raise ImportError
21
+
22
+ RRCrtc = c_ulong # typedef XID
23
+ RROutput = c_ulong # typedef XID
24
+ RRMode = c_ulong # typedef XID
25
+ Connection = c_ushort # Connection in Xrandr.h
26
+ SubpixelOrder = c_ushort # SubpixelOrder in Xrandr.h
27
+ XRRModeFlags = c_ulong
28
+
29
+ class XRRModeInfo(Structure):
30
+ _fields_ = [
31
+ ("id", RRMode), # mode ID
32
+ ("width", c_uint), # horizontal resolution
33
+ ("height", c_uint), # vertical resolution
34
+ ("dotClock", c_ulong), # pixel clock (in Hz)
35
+ ("hSyncStart", c_uint),
36
+ ("hSyncEnd", c_uint),
37
+ ("hTotal", c_uint),
38
+ ("hSkew", c_uint),
39
+ ("vSyncStart", c_uint),
40
+ ("vSyncEnd", c_uint),
41
+ ("vTotal", c_uint),
42
+ ("name", c_char_p),
43
+ ("nameLength", c_uint),
44
+ ("modeFlags", XRRModeFlags),
45
+ ]
46
+
47
+
48
+ class XRRScreenResources(Structure):
49
+ _fields_ = [
50
+ ("timestamp", Time),
51
+ ("configTimestamp", Time),
52
+ ("ncrtc", c_int),
53
+ ("crtcs", POINTER(RRCrtc)),
54
+ ("noutput", c_int),
55
+ ("outputs", POINTER(RROutput)),
56
+ ("nmode", c_int),
57
+ ("modes", POINTER(XRRModeInfo)),
58
+ ]
59
+
60
+
61
+ class XRROutputInfo(Structure):
62
+ _fields_ = [
63
+ ("timestamp", Time),
64
+ ("crtc", RRCrtc),
65
+ ("name", c_char_p),
66
+ ("nameLen", c_int),
67
+ ("mm_width", c_ulong),
68
+ ("mm_height", c_ulong),
69
+ ("connection", Connection),
70
+ ("subpixel_order", SubpixelOrder),
71
+ ("ncrtc", c_int),
72
+ ("crtcs", POINTER(RRCrtc)),
73
+ ("nclone", c_int),
74
+ ("clones", POINTER(RROutput)),
75
+ ("nmode", c_int),
76
+ ("npreferred", c_int),
77
+ ("modes", POINTER(RRMode)),
78
+ ]
79
+
80
+ class XRRCrtcInfo(Structure):
81
+ _fields_ = [
82
+ ("timestamp", Time),
83
+ ("x", c_int),
84
+ ("y", c_int),
85
+ ("width", c_uint),
86
+ ("height", c_uint),
87
+ ("mode", RRMode),
88
+ ("rotation", c_int),
89
+ ("noutput", c_int),
90
+ ("outputs", POINTER(RROutput)),
91
+ ("rotations", c_ushort),
92
+ ("npossible", c_int),
93
+ ("possible", POINTER(RROutput)),
94
+ ]
95
+
96
+
97
+ if lib:
98
+ XRRQueryVersion = lib.XRRQueryVersion
99
+ XRRQueryVersion.argtypes = [POINTER(Display), POINTER(c_int), POINTER(c_int)]
100
+ XRRQueryVersion.restype = c_int
101
+
102
+ XRRGetScreenResources = lib.XRRGetScreenResources
103
+ XRRGetScreenResources.argtypes = [POINTER(Display), Window]
104
+ XRRGetScreenResources.restype = POINTER(XRRScreenResources)
105
+
106
+ XRRGetOutputPrimary = lib.XRRGetOutputPrimary
107
+ XRRGetOutputPrimary.argtypes = [POINTER(Display), Window]
108
+ XRRGetOutputPrimary.restype = RROutput
109
+
110
+ XRRGetScreenResourcesCurrent = lib.XRRGetScreenResourcesCurrent
111
+ XRRGetScreenResourcesCurrent.argtypes = [POINTER(Display), Window]
112
+ XRRGetScreenResourcesCurrent.restype = POINTER(XRRScreenResources)
113
+
114
+ XRRFreeScreenResources = lib.XRRFreeScreenResources
115
+ XRRFreeScreenResources.argtypes = [POINTER(XRRScreenResources)]
116
+ XRRFreeScreenResources.restype = None
117
+
118
+ XRRGetOutputInfo = lib.XRRGetOutputInfo
119
+ XRRGetOutputInfo.argtypes = [POINTER(Display), POINTER(XRRScreenResources), RROutput]
120
+ XRRGetOutputInfo.restype = POINTER(XRROutputInfo)
121
+
122
+ XRRFreeOutputInfo = lib.XRRFreeOutputInfo
123
+ XRRFreeOutputInfo.argtypes = [POINTER(XRROutputInfo)]
124
+ XRRFreeOutputInfo.restype = None
125
+
126
+ XRRGetCrtcInfo = lib.XRRGetCrtcInfo
127
+ XRRGetCrtcInfo.argtypes = [POINTER(Display), POINTER(XRRScreenResources), RRCrtc]
128
+ XRRGetCrtcInfo.restype = POINTER(XRRCrtcInfo)
129
+
130
+ XRRSetCrtcConfig = lib.XRRSetCrtcConfig
131
+ XRRSetCrtcConfig.argtypes = argtypes = [POINTER(Display), POINTER(XRRScreenResources), RRCrtc, Time, c_int, c_int, RRMode, c_int, POINTER(RROutput), c_int]
132
+ XRRSetCrtcConfig.restype = c_int
133
+
134
+ XRRFreeCrtcInfo = lib.XRRFreeCrtcInfo
135
+ XRRFreeCrtcInfo.argtypes = [POINTER(XRRCrtcInfo)]
136
+ XRRFreeCrtcInfo.restype = None
137
+
138
+ def list_connected_outputs():
139
+ dpy = XOpenDisplay(None)
140
+ if not dpy:
141
+ raise RuntimeError("Cannot open DISPLAY")
142
+
143
+ root = XDefaultRootWindow(dpy)
144
+ res_p = XRRGetScreenResources(dpy, root)
145
+ if not res_p:
146
+ XCloseDisplay(dpy)
147
+ raise RuntimeError("Failed to get screen resources")
148
+
149
+ res = res_p.contents
150
+ outputs = []
151
+ for i in range(res.noutput):
152
+ out_id = res.outputs[i]
153
+ info_p = XRRGetOutputInfo(dpy, res_p, out_id)
154
+ if info_p:
155
+ info = info_p.contents
156
+ if info.connection == 0: # Connected.
157
+ outputs.append(info.name.decode())
158
+ XRRFreeOutputInfo(info_p)
159
+
160
+ XRRFreeScreenResources(res_p)
161
+ XCloseDisplay(dpy)
162
+ return outputs
163
+
164
+ if __name__ == "__main__":
165
+ for name in list_connected_outputs():
166
+ print(name)
@@ -0,0 +1,43 @@
1
+ from __future__ import annotations
2
+
3
+ import warnings
4
+ from ctypes import Structure, c_ushort, c_ulong, c_int, c_void_p, POINTER
5
+ import pyglet.lib
6
+ from pyglet.libs.x11.xlib import Visual
7
+
8
+ lib = None
9
+ try:
10
+ lib = pyglet.lib.load_library("Xrender")
11
+ except ImportError:
12
+ if pyglet.options.debug_lib:
13
+ warnings.warn("XRender could not be loaded.")
14
+
15
+
16
+ class XRenderDirectFormat(Structure):
17
+ _fields_ = [
18
+ ('red', c_ushort),
19
+ ('redMask', c_ushort),
20
+ ('green', c_ushort),
21
+ ('greenMask', c_ushort),
22
+ ('blue', c_ushort),
23
+ ('blueMask', c_ushort),
24
+ ('alpha', c_ushort),
25
+ ('alphaMask', c_ushort),
26
+ ]
27
+
28
+ class XRenderPictFormat(Structure):
29
+ _fields_ = [
30
+ ('id', c_ulong),
31
+ ('type', c_int),
32
+ ('depth', c_int),
33
+ ('direct', XRenderDirectFormat),
34
+ ('colormap', c_ulong),
35
+ ]
36
+
37
+ # XRenderFindVisualFormat(Display *dpy, Visual *visual)
38
+ try:
39
+ XRenderFindVisualFormat = lib.XRenderFindVisualFormat
40
+ XRenderFindVisualFormat.argtypes = [c_void_p, POINTER(Visual)]
41
+ XRenderFindVisualFormat.restype = POINTER(XRenderPictFormat)
42
+ except ValueError:
43
+ XRenderFindVisualFormat = None
pyglet/libs/x11/xsync.py CHANGED
@@ -406,6 +406,49 @@ XSyncGetPriority = _lib.XSyncGetPriority
406
406
  XSyncGetPriority.restype = c_int
407
407
  XSyncGetPriority.argtypes = [POINTER(Display), XID, POINTER(c_int)]
408
408
 
409
+ # Shape kind
410
+ ShapeBounding = 0
411
+ ShapeClip = 1
412
+ ShapeInput = 2
413
+
414
+ # Shape operation
415
+ ShapeSet = 0
416
+ ShapeUnion = 1
417
+ ShapeIntersect = 2
418
+ ShapeSubtract = 3
419
+ ShapeInvert = 4
420
+
421
+ XShapeCombineRegion = _lib.XShapeCombineRegion
422
+ XShapeCombineRegion.argtypes = [
423
+ POINTER(Display),
424
+ c_void_p,
425
+ ctypes.c_int, # shape kind
426
+ ctypes.c_int, ctypes.c_int, # x, y offset
427
+ c_void_p,
428
+ ctypes.c_int # ShapeOp
429
+ ]
430
+
431
+ XShapeCombineMask = _lib.XShapeCombineMask
432
+ XShapeCombineMask.argtypes = [
433
+ Display, # *display
434
+ c_void_p, # dest window
435
+ ctypes.c_int, # shape_kind (e.g., ShapeInput)
436
+ ctypes.c_int, # x offset
437
+ ctypes.c_int, # y offset
438
+ ctypes.c_ulong, # Pixmap (can be 0 for None)
439
+ ctypes.c_int # ShapeOp (e.g., ShapeSet)
440
+ ]
441
+ XShapeCombineMask.restype = None
442
+
443
+ XShapeQueryExtension = _lib.XShapeQueryExtension
444
+ XShapeQueryExtension.argtypes = [Display, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int)]
445
+ XShapeQueryExtension.restype = Bool
446
+
447
+ def has_shape_support(display: Display) -> bool:
448
+ event_base = ctypes.c_int()
449
+ error_base = ctypes.c_int()
450
+ return XShapeQueryExtension(display, ctypes.byref(event_base), ctypes.byref(error_base))
451
+
409
452
 
410
453
  __all__ = ['SYNC_MAJOR_VERSION', 'SYNC_MINOR_VERSION', 'X_SyncInitialize',
411
454
  'X_SyncListSystemCounters', 'X_SyncCreateCounter', 'X_SyncSetCounter',
pyglet/math.py CHANGED
@@ -191,7 +191,7 @@ class Vec2(_typing.NamedTuple):
191
191
  )
192
192
 
193
193
  def __lt__(self, other: tuple[float, float]) -> bool:
194
- return self[0] ** 2 + self[0] ** 2 < other[0] ** 2 + other[1] ** 2
194
+ return self[0] ** 2 + self[1] ** 2 < other[0] ** 2 + other[1] ** 2
195
195
 
196
196
  @staticmethod
197
197
  def from_heading(heading: float, length: float = 1.0) -> Vec2:
@@ -301,8 +301,7 @@ class Vec2(_typing.NamedTuple):
301
301
  This simply means the vector will have a length of 1.0. If the vector
302
302
  has a length of 0, the original vector will be returned.
303
303
  """
304
- d = _math.sqrt(self[0] ** 2 + self[1] ** 2)
305
- if d:
304
+ if d := _math.sqrt(self[0] ** 2 + self[1] ** 2):
306
305
  return Vec2(self[0] / d, self[1] / d)
307
306
  return self
308
307
 
@@ -823,7 +822,8 @@ class Vec4(_typing.NamedTuple):
823
822
  )
824
823
 
825
824
  def __lt__(self, other: Vec4 | tuple[float, float, float, float]) -> bool:
826
- return self[0] ** 2 + self[1] ** 2 + self[2] ** 2 < other[0] ** 2 + other[1] ** 2 + other[2] ** 2
825
+ return (self[0] ** 2 + self[1] ** 2 + self[2] ** 2 + self[3] ** 2 <
826
+ other[0] ** 2 + other[1] ** 2 + other[2] ** 2 + other[3] ** 2)
827
827
 
828
828
  def length(self) -> float:
829
829
  """Calculate the length of the vector: ``sqrt(x ** 2 + y ** 2 + z ** 2 + w ** 2)``."""
@@ -872,8 +872,7 @@ class Vec4(_typing.NamedTuple):
872
872
  This means that the vector will have the same direction, but a length of 1.0.
873
873
  If the vector has a length of 0, the original vector will be returned.
874
874
  """
875
- d = _math.sqrt(self[0] ** 2 + self[1] ** 2 + self[2] ** 2 + self[3] ** 2)
876
- if d:
875
+ if d := _math.sqrt(self[0] ** 2 + self[1] ** 2 + self[2] ** 2 + self[3] ** 2):
877
876
  return Vec4(self[0] / d, self[1] / d, self[2] / d, self[3] / d)
878
877
  return self
879
878
 
@@ -1053,7 +1052,21 @@ class Mat3(_typing.NamedTuple):
1053
1052
  def __matmul__(self, other: Mat3) -> Mat3: ...
1054
1053
 
1055
1054
  def __matmul__(self, other) -> Vec3 | Mat3:
1056
- if isinstance(other, Vec3):
1055
+ try:
1056
+ # extract the elements in row-column form. (matrix is stored column first)
1057
+ a11, a12, a13, a21, a22, a23, a31, a32, a33 = self
1058
+ b11, b12, b13, b21, b22, b23, b31, b32, b33 = other
1059
+
1060
+ # Multiply and sum rows * columns
1061
+ return Mat3(
1062
+ # Column 1
1063
+ a11 * b11 + a21 * b12 + a31 * b13, a12 * b11 + a22 * b12 + a32 * b13, a13 * b11 + a23 * b12 + a33 * b13,
1064
+ # Column 2
1065
+ a11 * b21 + a21 * b22 + a31 * b23, a12 * b21 + a22 * b22 + a32 * b23, a13 * b21 + a23 * b22 + a33 * b23,
1066
+ # Column 3
1067
+ a11 * b31 + a21 * b32 + a31 * b33, a12 * b31 + a22 * b32 + a32 * b33, a13 * b31 + a23 * b32 + a33 * b33,
1068
+ )
1069
+ except ValueError:
1057
1070
  x, y, z = other
1058
1071
  # extract the elements in row-column form. (matrix is stored column first)
1059
1072
  a11, a12, a13, a21, a22, a23, a31, a32, a33 = self
@@ -1063,24 +1076,6 @@ class Mat3(_typing.NamedTuple):
1063
1076
  a13 * x + a23 * y + a33 * z,
1064
1077
  )
1065
1078
 
1066
- if not isinstance(other, Mat3):
1067
- msg = "Can only multiply with Mat3 or Vec3 types"
1068
- raise TypeError(msg)
1069
-
1070
- # extract the elements in row-column form. (matrix is stored column first)
1071
- a11, a12, a13, a21, a22, a23, a31, a32, a33 = self
1072
- b11, b12, b13, b21, b22, b23, b31, b32, b33 = other
1073
-
1074
- # Multiply and sum rows * columns
1075
- return Mat3(
1076
- # Column 1
1077
- a11 * b11 + a21 * b12 + a31 * b13, a12 * b11 + a22 * b12 + a32 * b13, a13 * b11 + a23 * b12 + a33 * b13,
1078
- # Column 2
1079
- a11 * b21 + a21 * b22 + a31 * b23, a12 * b21 + a22 * b22 + a32 * b23, a13 * b21 + a23 * b22 + a33 * b23,
1080
- # Column 3
1081
- a11 * b31 + a21 * b32 + a31 * b33, a12 * b31 + a22 * b32 + a32 * b33, a13 * b31 + a23 * b32 + a33 * b33,
1082
- )
1083
-
1084
1079
  def __repr__(self) -> str:
1085
1080
  return f"{self.__class__.__name__}{self[0:3]}\n {self[3:6]}\n {self[6:9]}"
1086
1081
 
@@ -1357,7 +1352,26 @@ class Mat4(_typing.NamedTuple):
1357
1352
  def __matmul__(self, other: Mat4) -> Mat4: ...
1358
1353
 
1359
1354
  def __matmul__(self, other):
1360
- if isinstance(other, Vec4):
1355
+ try:
1356
+ # extract the elements in row-column form. (matrix is stored column first)
1357
+ a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44 = self
1358
+ b11, b12, b13, b14, b21, b22, b23, b24, b31, b32, b33, b34, b41, b42, b43, b44 = other
1359
+ # Multiply and sum rows * columns:
1360
+ return Mat4(
1361
+ # Column 1
1362
+ a11 * b11 + a21 * b12 + a31 * b13 + a41 * b14, a12 * b11 + a22 * b12 + a32 * b13 + a42 * b14,
1363
+ a13 * b11 + a23 * b12 + a33 * b13 + a43 * b14, a14 * b11 + a24 * b12 + a34 * b13 + a44 * b14,
1364
+ # Column 2
1365
+ a11 * b21 + a21 * b22 + a31 * b23 + a41 * b24, a12 * b21 + a22 * b22 + a32 * b23 + a42 * b24,
1366
+ a13 * b21 + a23 * b22 + a33 * b23 + a43 * b24, a14 * b21 + a24 * b22 + a34 * b23 + a44 * b24,
1367
+ # Column 3
1368
+ a11 * b31 + a21 * b32 + a31 * b33 + a41 * b34, a12 * b31 + a22 * b32 + a32 * b33 + a42 * b34,
1369
+ a13 * b31 + a23 * b32 + a33 * b33 + a43 * b34, a14 * b31 + a24 * b32 + a34 * b33 + a44 * b34,
1370
+ # Column 4
1371
+ a11 * b41 + a21 * b42 + a31 * b43 + a41 * b44, a12 * b41 + a22 * b42 + a32 * b43 + a42 * b44,
1372
+ a13 * b41 + a23 * b42 + a33 * b43 + a43 * b44, a14 * b41 + a24 * b42 + a34 * b43 + a44 * b44,
1373
+ )
1374
+ except ValueError:
1361
1375
  x, y, z, w = other
1362
1376
  # extract the elements in row-column form. (matrix is stored column first)
1363
1377
  a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44 = self
@@ -1368,35 +1382,15 @@ class Mat4(_typing.NamedTuple):
1368
1382
  x * a14 + y * a24 + z * a34 + w * a44,
1369
1383
  )
1370
1384
 
1371
- if not isinstance(other, Mat4):
1372
- msg = "Can only multiply with Mat4 or Vec4 types"
1373
- raise TypeError(msg)
1374
-
1375
- # extract the elements in row-column form. (matrix is stored column first)
1376
- a11, a12, a13, a14, a21, a22, a23, a24, a31, a32, a33, a34, a41, a42, a43, a44 = self
1377
- b11, b12, b13, b14, b21, b22, b23, b24, b31, b32, b33, b34, b41, b42, b43, b44 = other
1378
- # Multiply and sum rows * columns:
1379
- return Mat4(
1380
- # Column 1
1381
- a11 * b11 + a21 * b12 + a31 * b13 + a41 * b14, a12 * b11 + a22 * b12 + a32 * b13 + a42 * b14,
1382
- a13 * b11 + a23 * b12 + a33 * b13 + a43 * b14, a14 * b11 + a24 * b12 + a34 * b13 + a44 * b14,
1383
- # Column 2
1384
- a11 * b21 + a21 * b22 + a31 * b23 + a41 * b24, a12 * b21 + a22 * b22 + a32 * b23 + a42 * b24,
1385
- a13 * b21 + a23 * b22 + a33 * b23 + a43 * b24, a14 * b21 + a24 * b22 + a34 * b23 + a44 * b24,
1386
- # Column 3
1387
- a11 * b31 + a21 * b32 + a31 * b33 + a41 * b34, a12 * b31 + a22 * b32 + a32 * b33 + a42 * b34,
1388
- a13 * b31 + a23 * b32 + a33 * b33 + a43 * b34, a14 * b31 + a24 * b32 + a34 * b33 + a44 * b34,
1389
- # Column 4
1390
- a11 * b41 + a21 * b42 + a31 * b43 + a41 * b44, a12 * b41 + a22 * b42 + a32 * b43 + a42 * b44,
1391
- a13 * b41 + a23 * b42 + a33 * b43 + a43 * b44, a14 * b41 + a24 * b42 + a34 * b43 + a44 * b44,
1392
- )
1393
-
1394
1385
  def __repr__(self) -> str:
1395
1386
  return f"{self.__class__.__name__}{self[0:4]}\n {self[4:8]}\n {self[8:12]}\n {self[12:16]}"
1396
1387
 
1397
1388
 
1398
1389
  class Quaternion(_typing.NamedTuple):
1399
- """Quaternion."""
1390
+ """Quaternion.
1391
+
1392
+ Quaternions are 4-dimensional complex numbers, useful for describing 3D rotations.
1393
+ """
1400
1394
 
1401
1395
  w: float = 1.0
1402
1396
  x: float = 0.0
@@ -1412,6 +1406,8 @@ class Quaternion(_typing.NamedTuple):
1412
1406
  raise NotImplementedError
1413
1407
 
1414
1408
  def to_mat4(self) -> Mat4:
1409
+ """Calculate a 4x4 transform matrix which applies a rotation."""
1410
+
1415
1411
  w = self.w
1416
1412
  x = self.x
1417
1413
  y = self.y
@@ -1437,6 +1433,8 @@ class Quaternion(_typing.NamedTuple):
1437
1433
  return Mat4(a, b, c, 0.0, e, f, g, 0.0, i, j, k, 0.0, 0.0, 0.0, 0.0, 1.0)
1438
1434
 
1439
1435
  def to_mat3(self) -> Mat3:
1436
+ """Create a 3x3 rotation matrix."""
1437
+
1440
1438
  w = self.w
1441
1439
  x = self.x
1442
1440
  y = self.y
@@ -1462,21 +1460,34 @@ class Quaternion(_typing.NamedTuple):
1462
1460
  return Mat3(*(a, b, c, e, f, g, i, j, k))
1463
1461
 
1464
1462
  def length(self) -> float:
1465
- """Calculate the length of the Quaternion.
1466
-
1467
- The distance between the coordinates and the origin.
1468
- """
1463
+ """Calculate the length of the quaternion from the origin."""
1469
1464
  return _math.sqrt(self.w**2 + self.x**2 + self.y**2 + self.z**2)
1470
1465
 
1471
1466
  def conjugate(self) -> Quaternion:
1467
+ """Calculate the conjugate of this quaternion.
1468
+
1469
+ This operation:
1470
+ #. leaves the :py:attr:`.w` component alone
1471
+ #. inverts the sign of the :py:attr:`.x`, :py:attr:`.y`, and :py:attr:`.z` components
1472
+
1473
+ """
1472
1474
  return Quaternion(self.w, -self.x, -self.y, -self.z)
1473
1475
 
1474
1476
  def dot(self, other: Quaternion) -> float:
1477
+ """Calculate the dot product with another quaternion."""
1475
1478
  a, b, c, d = self
1476
1479
  e, f, g, h = other
1477
1480
  return a * e + b * f + c * g + d * h
1478
1481
 
1479
1482
  def normalize(self) -> Quaternion:
1483
+ """Calculate a unit quaternion from the instance.
1484
+
1485
+ The returned quaternion will be a scaled-down version
1486
+ of the instance which has:
1487
+
1488
+ * a length of ``1``
1489
+ * the same relative of its components
1490
+ """
1480
1491
  m = self.length()
1481
1492
  if m == 0:
1482
1493
  return self
@@ -1,5 +1,5 @@
1
1
  """
2
- Responsabilities
2
+ Responsibilities
3
3
 
4
4
  Handles accumulation of debug events while playing media_player and saves
5
5
  when sample's play ends.