1# ----------------------------------------------------------------------------
2# pyglet
3# Copyright (c) 2006-2008 Alex Holkner
4# Copyright (c) 2008-2020 pyglet contributors
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10#
11#  * Redistributions of source code must retain the above copyright
12#    notice, this list of conditions and the following disclaimer.
13#  * Redistributions in binary form must reproduce the above copyright
14#    notice, this list of conditions and the following disclaimer in
15#    the documentation and/or other materials provided with the
16#    distribution.
17#  * Neither the name of pyglet nor the names of its
18#    contributors may be used to endorse or promote products
19#    derived from this software without specific prior written
20#    permission.
21#
22# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33# POSSIBILITY OF SUCH DAMAGE.
34# ----------------------------------------------------------------------------
35
36import sys
37import ctypes
38from ctypes import *
39from ctypes.wintypes import *
40
41
42_int_types = (c_int16, c_int32)
43if hasattr(ctypes, 'c_int64'):
44    # Some builds of ctypes apparently do not have c_int64
45    # defined; it's a pretty good bet that these builds do not
46    # have 64-bit pointers.
47    _int_types += (c_int64,)
48for t in _int_types:
49    if sizeof(t) == sizeof(c_size_t):
50        c_ptrdiff_t = t
51del t
52del _int_types
53
54
55# PUINT is defined only from >= python 3.2
56if sys.version_info < (3, 2)[:2]:
57    PUINT = POINTER(UINT)
58
59
60class c_void(Structure):
61    # c_void_p is a buggy return type, converting to int, so
62    # POINTER(None) == c_void_p is actually written as
63    # POINTER(c_void), so it can be treated as a real pointer.
64    _fields_ = [('dummy', c_int)]
65
66
67def POINTER_(obj):
68    p = ctypes.POINTER(obj)
69
70    # Convert None to a real NULL pointer to work around bugs
71    # in how ctypes handles None on 64-bit platforms
72    if not isinstance(p.from_param, classmethod):
73        def from_param(cls, x):
74            if x is None:
75                return cls()
76            else:
77                return x
78        p.from_param = classmethod(from_param)
79
80    return p
81
82
83c_void_p = POINTER_(c_void)
84INT = c_int
85LPVOID = c_void_p
86HCURSOR = HANDLE
87LRESULT = LPARAM
88COLORREF = DWORD
89PVOID = c_void_p
90WCHAR = c_wchar
91BCHAR = c_wchar
92LPRECT = POINTER(RECT)
93LPPOINT = POINTER(POINT)
94LPMSG = POINTER(MSG)
95UINT_PTR = HANDLE
96LONG_PTR = HANDLE
97HDROP = HANDLE
98LPTSTR = LPWSTR
99
100LF_FACESIZE = 32
101CCHDEVICENAME = 32
102CCHFORMNAME = 32
103
104WNDPROC = WINFUNCTYPE(LRESULT, HWND, UINT, WPARAM, LPARAM)
105TIMERPROC = WINFUNCTYPE(None, HWND, UINT, POINTER(UINT), DWORD)
106TIMERAPCPROC = WINFUNCTYPE(None, PVOID, DWORD, DWORD)
107MONITORENUMPROC = WINFUNCTYPE(BOOL, HMONITOR, HDC, LPRECT, LPARAM)
108
109
110def MAKEINTRESOURCE(i):
111    return cast(ctypes.c_void_p(i & 0xFFFF), c_wchar_p)
112
113
114class WNDCLASS(Structure):
115    _fields_ = [
116        ('style', UINT),
117        ('lpfnWndProc', WNDPROC),
118        ('cbClsExtra', c_int),
119        ('cbWndExtra', c_int),
120        ('hInstance', HINSTANCE),
121        ('hIcon', HICON),
122        ('hCursor', HCURSOR),
123        ('hbrBackground', HBRUSH),
124        ('lpszMenuName', c_char_p),
125        ('lpszClassName', c_wchar_p)
126    ]
127
128
129class SECURITY_ATTRIBUTES(Structure):
130    _fields_ = [
131        ("nLength", DWORD),
132        ("lpSecurityDescriptor", c_void_p),
133        ("bInheritHandle", BOOL)
134    ]
135    __slots__ = [f[0] for f in _fields_]
136
137
138class PIXELFORMATDESCRIPTOR(Structure):
139    _fields_ = [
140        ('nSize', WORD),
141        ('nVersion', WORD),
142        ('dwFlags', DWORD),
143        ('iPixelType', BYTE),
144        ('cColorBits', BYTE),
145        ('cRedBits', BYTE),
146        ('cRedShift', BYTE),
147        ('cGreenBits', BYTE),
148        ('cGreenShift', BYTE),
149        ('cBlueBits', BYTE),
150        ('cBlueShift', BYTE),
151        ('cAlphaBits', BYTE),
152        ('cAlphaShift', BYTE),
153        ('cAccumBits', BYTE),
154        ('cAccumRedBits', BYTE),
155        ('cAccumGreenBits', BYTE),
156        ('cAccumBlueBits', BYTE),
157        ('cAccumAlphaBits', BYTE),
158        ('cDepthBits', BYTE),
159        ('cStencilBits', BYTE),
160        ('cAuxBuffers', BYTE),
161        ('iLayerType', BYTE),
162        ('bReserved', BYTE),
163        ('dwLayerMask', DWORD),
164        ('dwVisibleMask', DWORD),
165        ('dwDamageMask', DWORD)
166    ]
167
168
169class RGBQUAD(Structure):
170    _fields_ = [
171        ('rgbBlue', BYTE),
172        ('rgbGreen', BYTE),
173        ('rgbRed', BYTE),
174        ('rgbReserved', BYTE),
175    ]
176    __slots__ = [f[0] for f in _fields_]
177
178
179class CIEXYZ(Structure):
180    _fields_ = [
181        ('ciexyzX', DWORD),
182        ('ciexyzY', DWORD),
183        ('ciexyzZ', DWORD),
184    ]
185    __slots__ = [f[0] for f in _fields_]
186
187
188class CIEXYZTRIPLE(Structure):
189    _fields_ = [
190        ('ciexyzRed', CIEXYZ),
191        ('ciexyzBlue', CIEXYZ),
192        ('ciexyzGreen', CIEXYZ),
193    ]
194    __slots__ = [f[0] for f in _fields_]
195
196
197class BITMAPINFOHEADER(Structure):
198    _fields_ = [
199        ('biSize', DWORD),
200        ('biWidth', LONG),
201        ('biHeight', LONG),
202        ('biPlanes', WORD),
203        ('biBitCount', WORD),
204        ('biCompression', DWORD),
205        ('biSizeImage', DWORD),
206        ('biXPelsPerMeter', LONG),
207        ('biYPelsPerMeter', LONG),
208        ('biClrUsed', DWORD),
209        ('biClrImportant', DWORD),
210    ]
211
212
213class BITMAPV5HEADER(Structure):
214    _fields_ = [
215        ('bV5Size', DWORD),
216        ('bV5Width', LONG),
217        ('bV5Height', LONG),
218        ('bV5Planes', WORD),
219        ('bV5BitCount', WORD),
220        ('bV5Compression', DWORD),
221        ('bV5SizeImage', DWORD),
222        ('bV5XPelsPerMeter', LONG),
223        ('bV5YPelsPerMeter', LONG),
224        ('bV5ClrUsed', DWORD),
225        ('bV5ClrImportant', DWORD),
226        ('bV5RedMask', DWORD),
227        ('bV5GreenMask', DWORD),
228        ('bV5BlueMask', DWORD),
229        ('bV5AlphaMask', DWORD),
230        ('bV5CSType', DWORD),
231        ('bV5Endpoints', CIEXYZTRIPLE),
232        ('bV5GammaRed', DWORD),
233        ('bV5GammaGreen', DWORD),
234        ('bV5GammaBlue', DWORD),
235        ('bV5Intent', DWORD),
236        ('bV5ProfileData', DWORD),
237        ('bV5ProfileSize', DWORD),
238        ('bV5Reserved', DWORD),
239    ]
240
241
242class BITMAPINFO(Structure):
243    _fields_ = [
244        ('bmiHeader', BITMAPINFOHEADER),
245        ('bmiColors', RGBQUAD * 1)
246    ]
247    __slots__ = [f[0] for f in _fields_]
248
249
250class LOGFONT(Structure):
251    _fields_ = [
252        ('lfHeight', LONG),
253        ('lfWidth', LONG),
254        ('lfEscapement', LONG),
255        ('lfOrientation', LONG),
256        ('lfWeight', LONG),
257        ('lfItalic', BYTE),
258        ('lfUnderline', BYTE),
259        ('lfStrikeOut', BYTE),
260        ('lfCharSet', BYTE),
261        ('lfOutPrecision', BYTE),
262        ('lfClipPrecision', BYTE),
263        ('lfQuality', BYTE),
264        ('lfPitchAndFamily', BYTE),
265        ('lfFaceName', (c_char * LF_FACESIZE))  # Use ASCII
266    ]
267
268
269class TRACKMOUSEEVENT(Structure):
270    _fields_ = [
271        ('cbSize', DWORD),
272        ('dwFlags', DWORD),
273        ('hwndTrack', HWND),
274        ('dwHoverTime', DWORD)
275    ]
276    __slots__ = [f[0] for f in _fields_]
277
278
279class MINMAXINFO(Structure):
280    _fields_ = [
281        ('ptReserved', POINT),
282        ('ptMaxSize', POINT),
283        ('ptMaxPosition', POINT),
284        ('ptMinTrackSize', POINT),
285        ('ptMaxTrackSize', POINT)
286    ]
287    __slots__ = [f[0] for f in _fields_]
288
289
290class ABC(Structure):
291    _fields_ = [
292        ('abcA', c_int),
293        ('abcB', c_uint),
294        ('abcC', c_int)
295    ]
296    __slots__ = [f[0] for f in _fields_]
297
298
299class TEXTMETRIC(Structure):
300    _fields_ = [
301        ('tmHeight', c_long),
302        ('tmAscent', c_long),
303        ('tmDescent', c_long),
304        ('tmInternalLeading', c_long),
305        ('tmExternalLeading', c_long),
306        ('tmAveCharWidth', c_long),
307        ('tmMaxCharWidth', c_long),
308        ('tmWeight', c_long),
309        ('tmOverhang', c_long),
310        ('tmDigitizedAspectX', c_long),
311        ('tmDigitizedAspectY', c_long),
312        ('tmFirstChar', c_char),  # Use ASCII
313        ('tmLastChar', c_char),
314        ('tmDefaultChar', c_char),
315        ('tmBreakChar', c_char),
316        ('tmItalic', c_byte),
317        ('tmUnderlined', c_byte),
318        ('tmStruckOut', c_byte),
319        ('tmPitchAndFamily', c_byte),
320        ('tmCharSet', c_byte)
321    ]
322    __slots__ = [f[0] for f in _fields_]
323
324
325class MONITORINFOEX(Structure):
326    _fields_ = [
327        ('cbSize', DWORD),
328        ('rcMonitor', RECT),
329        ('rcWork', RECT),
330        ('dwFlags', DWORD),
331        ('szDevice', WCHAR * CCHDEVICENAME)
332    ]
333    __slots__ = [f[0] for f in _fields_]
334
335
336class DEVMODE(Structure):
337    _fields_ = [
338        ('dmDeviceName', BCHAR * CCHDEVICENAME),
339        ('dmSpecVersion', WORD),
340        ('dmDriverVersion', WORD),
341        ('dmSize', WORD),
342        ('dmDriverExtra', WORD),
343        ('dmFields', DWORD),
344        # Just using largest union member here
345        ('dmOrientation', c_short),
346        ('dmPaperSize', c_short),
347        ('dmPaperLength', c_short),
348        ('dmPaperWidth', c_short),
349        ('dmScale', c_short),
350        ('dmCopies', c_short),
351        ('dmDefaultSource', c_short),
352        ('dmPrintQuality', c_short),
353        # End union
354        ('dmColor', c_short),
355        ('dmDuplex', c_short),
356        ('dmYResolution', c_short),
357        ('dmTTOption', c_short),
358        ('dmCollate', c_short),
359        ('dmFormName', BCHAR * CCHFORMNAME),
360        ('dmLogPixels', WORD),
361        ('dmBitsPerPel', DWORD),
362        ('dmPelsWidth', DWORD),
363        ('dmPelsHeight', DWORD),
364        ('dmDisplayFlags', DWORD), # union with dmNup
365        ('dmDisplayFrequency', DWORD),
366        ('dmICMMethod', DWORD),
367        ('dmICMIntent', DWORD),
368        ('dmDitherType', DWORD),
369        ('dmReserved1', DWORD),
370        ('dmReserved2', DWORD),
371        ('dmPanningWidth', DWORD),
372        ('dmPanningHeight', DWORD),
373    ]
374
375
376class ICONINFO(Structure):
377    _fields_ = [
378        ('fIcon', BOOL),
379        ('xHotspot', DWORD),
380        ('yHotspot', DWORD),
381        ('hbmMask', HBITMAP),
382        ('hbmColor', HBITMAP)
383    ]
384    __slots__ = [f[0] for f in _fields_]
385
386
387class RAWINPUTDEVICE(Structure):
388    _fields_ = [
389        ('usUsagePage', USHORT),
390        ('usUsage', USHORT),
391        ('dwFlags', DWORD),
392        ('hwndTarget', HWND)
393    ]
394
395
396PCRAWINPUTDEVICE = POINTER(RAWINPUTDEVICE)
397HRAWINPUT = HANDLE
398
399
400class RAWINPUTHEADER(Structure):
401    _fields_ = [
402        ('dwType', DWORD),
403        ('dwSize', DWORD),
404        ('hDevice', HANDLE),
405        ('wParam', WPARAM),
406    ]
407
408
409class _Buttons(Structure):
410    _fields_ = [
411        ('usButtonFlags', USHORT),
412        ('usButtonData', USHORT),
413    ]
414
415
416class _U(Union):
417    _anonymous_ = ('_buttons',)
418    _fields_ = [
419        ('ulButtons', ULONG),
420        ('_buttons', _Buttons),
421    ]
422
423
424class RAWMOUSE(Structure):
425    _anonymous_ = ('u',)
426    _fields_ = [
427        ('usFlags', USHORT),
428        ('u', _U),
429        ('ulRawButtons', ULONG),
430        ('lLastX', LONG),
431        ('lLastY', LONG),
432        ('ulExtraInformation', ULONG),
433    ]
434
435
436class RAWKEYBOARD(Structure):
437    _fields_ = [
438        ('MakeCode', USHORT),
439        ('Flags', USHORT),
440        ('Reserved', USHORT),
441        ('VKey', USHORT),
442        ('Message', UINT),
443        ('ExtraInformation', ULONG),
444    ]
445
446
447class RAWHID(Structure):
448    _fields_ = [
449        ('dwSizeHid', DWORD),
450        ('dwCount', DWORD),
451        ('bRawData', POINTER(BYTE)),
452    ]
453
454
455class _RAWINPUTDEVICEUNION(Union):
456    _fields_ = [
457        ('mouse', RAWMOUSE),
458        ('keyboard', RAWKEYBOARD),
459        ('hid', RAWHID),
460    ]
461
462
463class RAWINPUT(Structure):
464    _fields_ = [
465        ('header', RAWINPUTHEADER),
466        ('data', _RAWINPUTDEVICEUNION),
467    ]
468