summaryrefslogtreecommitdiff
path: root/source/3rd-party/SDL2/src/video/windows
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2019-05-11 22:54:56 +0800
committerchai <chaifix@163.com>2019-05-11 22:54:56 +0800
commit9645be0af1b1d5cb0ad5892d5464e1b23c51b550 (patch)
tree129c716bed8e93312421c3adb2f8e7c4f811602d /source/3rd-party/SDL2/src/video/windows
Diffstat (limited to 'source/3rd-party/SDL2/src/video/windows')
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_msctf.h242
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_vkeys.h76
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.c160
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.h36
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.c1236
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.h36
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.c127
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.h27
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.c1579
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.h40
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.c905
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.h29
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c407
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.h47
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.c320
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.h33
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.c895
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.h142
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.c131
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.h49
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.c110
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.h40
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowstaskdialog.h156
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.c452
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.h199
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.c176
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.h52
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.c996
-rw-r--r--source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.h87
-rw-r--r--source/3rd-party/SDL2/src/video/windows/wmmsg.h1052
30 files changed, 9837 insertions, 0 deletions
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_msctf.h b/source/3rd-party/SDL2/src/video/windows/SDL_msctf.h
new file mode 100644
index 0000000..53cec3d
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_msctf.h
@@ -0,0 +1,242 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_msctf_h_
+#define SDL_msctf_h_
+
+#include <unknwn.h>
+
+#define TF_INVALID_COOKIE (0xffffffff)
+#define TF_IPSINK_FLAG_ACTIVE 0x0001
+#define TF_TMAE_UIELEMENTENABLEDONLY 0x00000004
+
+typedef struct ITfThreadMgr ITfThreadMgr;
+typedef struct ITfDocumentMgr ITfDocumentMgr;
+typedef struct ITfClientId ITfClientId;
+
+typedef struct IEnumTfDocumentMgrs IEnumTfDocumentMgrs;
+typedef struct IEnumTfFunctionProviders IEnumTfFunctionProviders;
+typedef struct ITfFunctionProvider ITfFunctionProvider;
+typedef struct ITfCompartmentMgr ITfCompartmentMgr;
+typedef struct ITfContext ITfContext;
+typedef struct IEnumTfContexts IEnumTfContexts;
+typedef struct ITfUIElementSink ITfUIElementSink;
+typedef struct ITfUIElement ITfUIElement;
+typedef struct ITfUIElementMgr ITfUIElementMgr;
+typedef struct IEnumTfUIElements IEnumTfUIElements;
+typedef struct ITfThreadMgrEx ITfThreadMgrEx;
+typedef struct ITfCandidateListUIElement ITfCandidateListUIElement;
+typedef struct ITfReadingInformationUIElement ITfReadingInformationUIElement;
+typedef struct ITfInputProcessorProfileActivationSink ITfInputProcessorProfileActivationSink;
+typedef struct ITfSource ITfSource;
+
+typedef DWORD TfClientId;
+typedef DWORD TfEditCookie;
+
+typedef struct ITfThreadMgrVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfThreadMgr *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfThreadMgr *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfThreadMgr *);
+ HRESULT (STDMETHODCALLTYPE *Activate)(ITfThreadMgr *, TfClientId *);
+ HRESULT (STDMETHODCALLTYPE *Deactivate)(ITfThreadMgr *);
+ HRESULT (STDMETHODCALLTYPE *CreateDocumentMgr)(ITfThreadMgr *);
+ HRESULT (STDMETHODCALLTYPE *EnumDocumentMgrs)(ITfThreadMgr *, IEnumTfDocumentMgrs **);
+ HRESULT (STDMETHODCALLTYPE *GetFocus)(ITfThreadMgr *, ITfDocumentMgr **);
+ HRESULT (STDMETHODCALLTYPE *SetFocus)(ITfThreadMgr *, ITfDocumentMgr *);
+ HRESULT (STDMETHODCALLTYPE *AssociateFocus)(ITfThreadMgr *, HWND, ITfDocumentMgr *, ITfDocumentMgr **);
+ HRESULT (STDMETHODCALLTYPE *IsThreadFocus)(ITfThreadMgr *, BOOL *);
+ HRESULT (STDMETHODCALLTYPE *GetFunctionProvider)(ITfThreadMgr *, REFCLSID, ITfFunctionProvider **);
+ HRESULT (STDMETHODCALLTYPE *EnumFunctionProviders)(ITfThreadMgr *, IEnumTfFunctionProviders **);
+ HRESULT (STDMETHODCALLTYPE *GetGlobalCompartment)(ITfThreadMgr *, ITfCompartmentMgr **);
+} ITfThreadMgrVtbl;
+
+struct ITfThreadMgr
+{
+ const struct ITfThreadMgrVtbl *lpVtbl;
+};
+
+typedef struct ITfThreadMgrExVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfThreadMgrEx *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfThreadMgrEx *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfThreadMgrEx *);
+ HRESULT (STDMETHODCALLTYPE *Activate)(ITfThreadMgrEx *, TfClientId *);
+ HRESULT (STDMETHODCALLTYPE *Deactivate)(ITfThreadMgrEx *);
+ HRESULT (STDMETHODCALLTYPE *CreateDocumentMgr)(ITfThreadMgrEx *, ITfDocumentMgr **);
+ HRESULT (STDMETHODCALLTYPE *EnumDocumentMgrs)(ITfThreadMgrEx *, IEnumTfDocumentMgrs **);
+ HRESULT (STDMETHODCALLTYPE *GetFocus)(ITfThreadMgrEx *, ITfDocumentMgr **);
+ HRESULT (STDMETHODCALLTYPE *SetFocus)(ITfThreadMgrEx *, ITfDocumentMgr *);
+ HRESULT (STDMETHODCALLTYPE *AssociateFocus)(ITfThreadMgrEx *, ITfDocumentMgr *, ITfDocumentMgr **);
+ HRESULT (STDMETHODCALLTYPE *IsThreadFocus)(ITfThreadMgrEx *, BOOL *);
+ HRESULT (STDMETHODCALLTYPE *GetFunctionProvider)(ITfThreadMgrEx *, REFCLSID, ITfFunctionProvider **);
+ HRESULT (STDMETHODCALLTYPE *EnumFunctionProviders)(ITfThreadMgrEx *, IEnumTfFunctionProviders **);
+ HRESULT (STDMETHODCALLTYPE *GetGlobalCompartment)(ITfThreadMgrEx *, ITfCompartmentMgr **);
+ HRESULT (STDMETHODCALLTYPE *ActivateEx)(ITfThreadMgrEx *, TfClientId *, DWORD);
+ HRESULT (STDMETHODCALLTYPE *GetActiveFlags)(ITfThreadMgrEx *, DWORD *);
+} ITfThreadMgrExVtbl;
+
+struct ITfThreadMgrEx
+{
+ const struct ITfThreadMgrExVtbl *lpVtbl;
+};
+
+typedef struct ITfDocumentMgrVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfDocumentMgr *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfDocumentMgr *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfDocumentMgr *);
+ HRESULT (STDMETHODCALLTYPE *CreateContext)(ITfDocumentMgr *, TfClientId, DWORD, IUnknown *, ITfContext **, TfEditCookie *);
+ HRESULT (STDMETHODCALLTYPE *Push)(ITfDocumentMgr *, ITfContext *);
+ HRESULT (STDMETHODCALLTYPE *Pop)(ITfDocumentMgr *);
+ HRESULT (STDMETHODCALLTYPE *GetTop)(ITfDocumentMgr *, ITfContext **);
+ HRESULT (STDMETHODCALLTYPE *GetBase)(ITfDocumentMgr *, ITfContext **);
+ HRESULT (STDMETHODCALLTYPE *EnumContexts)(ITfDocumentMgr *, IEnumTfContexts **);
+} ITfDocumentMgrVtbl;
+
+struct ITfDocumentMgr
+{
+ const struct ITfDocumentMgrVtbl *lpVtbl;
+};
+
+typedef struct ITfUIElementSinkVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfUIElementSink *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfUIElementSink *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfUIElementSink *);
+ HRESULT (STDMETHODCALLTYPE *BeginUIElement)(ITfUIElementSink *, DWORD, BOOL *);
+ HRESULT (STDMETHODCALLTYPE *UpdateUIElement)(ITfUIElementSink *, DWORD);
+ HRESULT (STDMETHODCALLTYPE *EndUIElement)(ITfUIElementSink *, DWORD);
+} ITfUIElementSinkVtbl;
+
+struct ITfUIElementSink
+{
+ const struct ITfUIElementSinkVtbl *lpVtbl;
+};
+
+typedef struct ITfUIElementMgrVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfUIElementMgr *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfUIElementMgr *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfUIElementMgr *);
+ HRESULT (STDMETHODCALLTYPE *BeginUIElement)(ITfUIElementMgr *, ITfUIElement *, BOOL *, DWORD *);
+ HRESULT (STDMETHODCALLTYPE *UpdateUIElement)(ITfUIElementMgr *, DWORD);
+ HRESULT (STDMETHODCALLTYPE *EndUIElement)(ITfUIElementMgr *, DWORD);
+ HRESULT (STDMETHODCALLTYPE *GetUIElement)(ITfUIElementMgr *, DWORD, ITfUIElement **);
+ HRESULT (STDMETHODCALLTYPE *EnumUIElements)(ITfUIElementMgr *, IEnumTfUIElements **);
+} ITfUIElementMgrVtbl;
+
+struct ITfUIElementMgr
+{
+ const struct ITfUIElementMgrVtbl *lpVtbl;
+};
+
+typedef struct ITfCandidateListUIElementVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfCandidateListUIElement *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfCandidateListUIElement *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfCandidateListUIElement *);
+ HRESULT (STDMETHODCALLTYPE *GetDescription)(ITfCandidateListUIElement *, BSTR *);
+ HRESULT (STDMETHODCALLTYPE *GetGUID)(ITfCandidateListUIElement *, GUID *);
+ HRESULT (STDMETHODCALLTYPE *Show)(ITfCandidateListUIElement *, BOOL);
+ HRESULT (STDMETHODCALLTYPE *IsShown)(ITfCandidateListUIElement *, BOOL *);
+ HRESULT (STDMETHODCALLTYPE *GetUpdatedFlags)(ITfCandidateListUIElement *, DWORD *);
+ HRESULT (STDMETHODCALLTYPE *GetDocumentMgr)(ITfCandidateListUIElement *, ITfDocumentMgr **);
+ HRESULT (STDMETHODCALLTYPE *GetCount)(ITfCandidateListUIElement *, UINT *);
+ HRESULT (STDMETHODCALLTYPE *GetSelection)(ITfCandidateListUIElement *, UINT *);
+ HRESULT (STDMETHODCALLTYPE *GetString)(ITfCandidateListUIElement *, UINT, BSTR *);
+ HRESULT (STDMETHODCALLTYPE *GetPageIndex)(ITfCandidateListUIElement *, UINT *, UINT, UINT *);
+ HRESULT (STDMETHODCALLTYPE *SetPageIndex)(ITfCandidateListUIElement *, UINT *, UINT);
+ HRESULT (STDMETHODCALLTYPE *GetCurrentPage)(ITfCandidateListUIElement *, UINT *);
+} ITfCandidateListUIElementVtbl;
+
+struct ITfCandidateListUIElement
+{
+ const struct ITfCandidateListUIElementVtbl *lpVtbl;
+};
+
+typedef struct ITfReadingInformationUIElementVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfReadingInformationUIElement *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfReadingInformationUIElement *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfReadingInformationUIElement *);
+ HRESULT (STDMETHODCALLTYPE *GetDescription)(ITfReadingInformationUIElement *, BSTR *);
+ HRESULT (STDMETHODCALLTYPE *GetGUID)(ITfReadingInformationUIElement *, GUID *);
+ HRESULT (STDMETHODCALLTYPE *Show)(ITfReadingInformationUIElement *, BOOL);
+ HRESULT (STDMETHODCALLTYPE *IsShown)(ITfReadingInformationUIElement *, BOOL *);
+ HRESULT (STDMETHODCALLTYPE *GetUpdatedFlags)(ITfReadingInformationUIElement *, DWORD *);
+ HRESULT (STDMETHODCALLTYPE *GetContext)(ITfReadingInformationUIElement *, ITfContext **);
+ HRESULT (STDMETHODCALLTYPE *GetString)(ITfReadingInformationUIElement *, BSTR *);
+ HRESULT (STDMETHODCALLTYPE *GetMaxReadingStringLength)(ITfReadingInformationUIElement *, UINT *);
+ HRESULT (STDMETHODCALLTYPE *GetErrorIndex)(ITfReadingInformationUIElement *, UINT *);
+ HRESULT (STDMETHODCALLTYPE *IsVerticalOrderPreferred)(ITfReadingInformationUIElement *, BOOL *);
+} ITfReadingInformationUIElementVtbl;
+
+struct ITfReadingInformationUIElement
+{
+ const struct ITfReadingInformationUIElementVtbl *lpVtbl;
+};
+
+typedef struct ITfUIElementVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfUIElement *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfUIElement *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfUIElement *);
+ HRESULT (STDMETHODCALLTYPE *GetDescription)(ITfUIElement *, BSTR *);
+ HRESULT (STDMETHODCALLTYPE *GetGUID)(ITfUIElement *, GUID *);
+ HRESULT (STDMETHODCALLTYPE *Show)(ITfUIElement *, BOOL);
+ HRESULT (STDMETHODCALLTYPE *IsShown)(ITfUIElement *, BOOL *);
+} ITfUIElementVtbl;
+
+struct ITfUIElement
+{
+ const struct ITfUIElementVtbl *lpVtbl;
+};
+
+typedef struct ITfInputProcessorProfileActivationSinkVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfInputProcessorProfileActivationSink *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfInputProcessorProfileActivationSink *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfInputProcessorProfileActivationSink *);
+ HRESULT (STDMETHODCALLTYPE *OnActivated)(ITfInputProcessorProfileActivationSink *, DWORD, LANGID, REFCLSID, REFGUID, REFGUID, HKL, DWORD);
+
+} ITfInputProcessorProfileActivationSinkVtbl;
+
+struct ITfInputProcessorProfileActivationSink
+{
+ const struct ITfInputProcessorProfileActivationSinkVtbl *lpVtbl;
+};
+
+typedef struct ITfSourceVtbl
+{
+ HRESULT (STDMETHODCALLTYPE *QueryInterface)(ITfSource *, REFIID, void **);
+ ULONG (STDMETHODCALLTYPE *AddRef)(ITfSource *);
+ ULONG (STDMETHODCALLTYPE *Release)(ITfSource *);
+ HRESULT (STDMETHODCALLTYPE *AdviseSink)(ITfSource *, REFIID, IUnknown *, DWORD *);
+ HRESULT (STDMETHODCALLTYPE *UnadviseSink)(ITfSource *, DWORD);
+} ITfSourceVtbl;
+
+struct ITfSource
+{
+ const struct ITfSourceVtbl *lpVtbl;
+};
+
+#endif /* SDL_msctf_h_ */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_vkeys.h b/source/3rd-party/SDL2/src/video/windows/SDL_vkeys.h
new file mode 100644
index 0000000..a38e3a2
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_vkeys.h
@@ -0,0 +1,76 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef VK_0
+#define VK_0 '0'
+#define VK_1 '1'
+#define VK_2 '2'
+#define VK_3 '3'
+#define VK_4 '4'
+#define VK_5 '5'
+#define VK_6 '6'
+#define VK_7 '7'
+#define VK_8 '8'
+#define VK_9 '9'
+#define VK_A 'A'
+#define VK_B 'B'
+#define VK_C 'C'
+#define VK_D 'D'
+#define VK_E 'E'
+#define VK_F 'F'
+#define VK_G 'G'
+#define VK_H 'H'
+#define VK_I 'I'
+#define VK_J 'J'
+#define VK_K 'K'
+#define VK_L 'L'
+#define VK_M 'M'
+#define VK_N 'N'
+#define VK_O 'O'
+#define VK_P 'P'
+#define VK_Q 'Q'
+#define VK_R 'R'
+#define VK_S 'S'
+#define VK_T 'T'
+#define VK_U 'U'
+#define VK_V 'V'
+#define VK_W 'W'
+#define VK_X 'X'
+#define VK_Y 'Y'
+#define VK_Z 'Z'
+#endif /* VK_0 */
+
+/* These keys haven't been defined, but were experimentally determined */
+#define VK_SEMICOLON 0xBA
+#define VK_EQUALS 0xBB
+#define VK_COMMA 0xBC
+#define VK_MINUS 0xBD
+#define VK_PERIOD 0xBE
+#define VK_SLASH 0xBF
+#define VK_GRAVE 0xC0
+#define VK_LBRACKET 0xDB
+#define VK_BACKSLASH 0xDC
+#define VK_RBRACKET 0xDD
+#define VK_APOSTROPHE 0xDE
+#define VK_BACKTICK 0xDF
+#define VK_OEM_102 0xE2
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.c
new file mode 100644
index 0000000..4e61d7a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.c
@@ -0,0 +1,160 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_windowsvideo.h"
+#include "SDL_windowswindow.h"
+#include "../../events/SDL_clipboardevents_c.h"
+
+
+#ifdef UNICODE
+#define TEXT_FORMAT CF_UNICODETEXT
+#else
+#define TEXT_FORMAT CF_TEXT
+#endif
+
+
+/* Get any application owned window handle for clipboard association */
+static HWND
+GetWindowHandle(_THIS)
+{
+ SDL_Window *window;
+
+ window = _this->windows;
+ if (window) {
+ return ((SDL_WindowData *) window->driverdata)->hwnd;
+ }
+ return NULL;
+}
+
+int
+WIN_SetClipboardText(_THIS, const char *text)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ int result = 0;
+
+ if (OpenClipboard(GetWindowHandle(_this))) {
+ HANDLE hMem;
+ LPTSTR tstr;
+ SIZE_T i, size;
+
+ /* Convert the text from UTF-8 to Windows Unicode */
+ tstr = WIN_UTF8ToString(text);
+ if (!tstr) {
+ return -1;
+ }
+
+ /* Find out the size of the data */
+ for (size = 0, i = 0; tstr[i]; ++i, ++size) {
+ if (tstr[i] == '\n' && (i == 0 || tstr[i-1] != '\r')) {
+ /* We're going to insert a carriage return */
+ ++size;
+ }
+ }
+ size = (size+1)*sizeof(*tstr);
+
+ /* Save the data to the clipboard */
+ hMem = GlobalAlloc(GMEM_MOVEABLE, size);
+ if (hMem) {
+ LPTSTR dst = (LPTSTR)GlobalLock(hMem);
+ if (dst) {
+ /* Copy the text over, adding carriage returns as necessary */
+ for (i = 0; tstr[i]; ++i) {
+ if (tstr[i] == '\n' && (i == 0 || tstr[i-1] != '\r')) {
+ *dst++ = '\r';
+ }
+ *dst++ = tstr[i];
+ }
+ *dst = 0;
+ GlobalUnlock(hMem);
+ }
+
+ EmptyClipboard();
+ if (!SetClipboardData(TEXT_FORMAT, hMem)) {
+ result = WIN_SetError("Couldn't set clipboard data");
+ }
+ data->clipboard_count = GetClipboardSequenceNumber();
+ }
+ SDL_free(tstr);
+
+ CloseClipboard();
+ } else {
+ result = WIN_SetError("Couldn't open clipboard");
+ }
+ return result;
+}
+
+char *
+WIN_GetClipboardText(_THIS)
+{
+ char *text;
+
+ text = NULL;
+ if (IsClipboardFormatAvailable(TEXT_FORMAT) &&
+ OpenClipboard(GetWindowHandle(_this))) {
+ HANDLE hMem;
+ LPTSTR tstr;
+
+ hMem = GetClipboardData(TEXT_FORMAT);
+ if (hMem) {
+ tstr = (LPTSTR)GlobalLock(hMem);
+ text = WIN_StringToUTF8(tstr);
+ GlobalUnlock(hMem);
+ } else {
+ WIN_SetError("Couldn't get clipboard data");
+ }
+ CloseClipboard();
+ }
+ if (!text) {
+ text = SDL_strdup("");
+ }
+ return text;
+}
+
+SDL_bool
+WIN_HasClipboardText(_THIS)
+{
+ SDL_bool result = SDL_FALSE;
+ char *text = WIN_GetClipboardText(_this);
+ if (text) {
+ result = text[0] != '\0' ? SDL_TRUE : SDL_FALSE;
+ SDL_free(text);
+ }
+ return result;
+}
+
+void
+WIN_CheckClipboardUpdate(struct SDL_VideoData * data)
+{
+ const DWORD count = GetClipboardSequenceNumber();
+ if (count != data->clipboard_count) {
+ if (data->clipboard_count) {
+ SDL_SendClipboardUpdate();
+ }
+ data->clipboard_count = count;
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.h
new file mode 100644
index 0000000..937b7d0
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsclipboard.h
@@ -0,0 +1,36 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsclipboard_h_
+#define SDL_windowsclipboard_h_
+
+/* Forward declaration */
+struct SDL_VideoData;
+
+extern int WIN_SetClipboardText(_THIS, const char *text);
+extern char *WIN_GetClipboardText(_THIS);
+extern SDL_bool WIN_HasClipboardText(_THIS);
+extern void WIN_CheckClipboardUpdate(struct SDL_VideoData * data);
+
+#endif /* SDL_windowsclipboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.c
new file mode 100644
index 0000000..e961cf5
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.c
@@ -0,0 +1,1236 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_windowsvideo.h"
+#include "SDL_windowsshape.h"
+#include "SDL_system.h"
+#include "SDL_syswm.h"
+#include "SDL_timer.h"
+#include "SDL_vkeys.h"
+#include "SDL_hints.h"
+#include "../../events/SDL_events_c.h"
+#include "../../events/SDL_touch_c.h"
+#include "../../events/scancodes_windows.h"
+#include "SDL_assert.h"
+#include "SDL_hints.h"
+
+/* Dropfile support */
+#include <shellapi.h>
+
+/* For GET_X_LPARAM, GET_Y_LPARAM. */
+#include <windowsx.h>
+
+/* #define WMMSG_DEBUG */
+#ifdef WMMSG_DEBUG
+#include <stdio.h>
+#include "wmmsg.h"
+#endif
+
+/* For processing mouse WM_*BUTTON* and WM_MOUSEMOVE message-data from GetMessageExtraInfo() */
+#define MOUSEEVENTF_FROMTOUCH 0xFF515700
+
+/* Masks for processing the windows KEYDOWN and KEYUP messages */
+#define REPEATED_KEYMASK (1<<30)
+#define EXTENDED_KEYMASK (1<<24)
+
+#define VK_ENTER 10 /* Keypad Enter ... no VKEY defined? */
+#ifndef VK_OEM_NEC_EQUAL
+#define VK_OEM_NEC_EQUAL 0x92
+#endif
+
+/* Make sure XBUTTON stuff is defined that isn't in older Platform SDKs... */
+#ifndef WM_XBUTTONDOWN
+#define WM_XBUTTONDOWN 0x020B
+#endif
+#ifndef WM_XBUTTONUP
+#define WM_XBUTTONUP 0x020C
+#endif
+#ifndef GET_XBUTTON_WPARAM
+#define GET_XBUTTON_WPARAM(w) (HIWORD(w))
+#endif
+#ifndef WM_INPUT
+#define WM_INPUT 0x00ff
+#endif
+#ifndef WM_TOUCH
+#define WM_TOUCH 0x0240
+#endif
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif
+#ifndef WM_UNICHAR
+#define WM_UNICHAR 0x0109
+#endif
+
+static SDL_Scancode
+VKeytoScancode(WPARAM vkey)
+{
+ switch (vkey) {
+ case VK_CLEAR: return SDL_SCANCODE_CLEAR;
+ case VK_MODECHANGE: return SDL_SCANCODE_MODE;
+ case VK_SELECT: return SDL_SCANCODE_SELECT;
+ case VK_EXECUTE: return SDL_SCANCODE_EXECUTE;
+ case VK_HELP: return SDL_SCANCODE_HELP;
+ case VK_PAUSE: return SDL_SCANCODE_PAUSE;
+ case VK_NUMLOCK: return SDL_SCANCODE_NUMLOCKCLEAR;
+
+ case VK_F13: return SDL_SCANCODE_F13;
+ case VK_F14: return SDL_SCANCODE_F14;
+ case VK_F15: return SDL_SCANCODE_F15;
+ case VK_F16: return SDL_SCANCODE_F16;
+ case VK_F17: return SDL_SCANCODE_F17;
+ case VK_F18: return SDL_SCANCODE_F18;
+ case VK_F19: return SDL_SCANCODE_F19;
+ case VK_F20: return SDL_SCANCODE_F20;
+ case VK_F21: return SDL_SCANCODE_F21;
+ case VK_F22: return SDL_SCANCODE_F22;
+ case VK_F23: return SDL_SCANCODE_F23;
+ case VK_F24: return SDL_SCANCODE_F24;
+
+ case VK_OEM_NEC_EQUAL: return SDL_SCANCODE_KP_EQUALS;
+ case VK_BROWSER_BACK: return SDL_SCANCODE_AC_BACK;
+ case VK_BROWSER_FORWARD: return SDL_SCANCODE_AC_FORWARD;
+ case VK_BROWSER_REFRESH: return SDL_SCANCODE_AC_REFRESH;
+ case VK_BROWSER_STOP: return SDL_SCANCODE_AC_STOP;
+ case VK_BROWSER_SEARCH: return SDL_SCANCODE_AC_SEARCH;
+ case VK_BROWSER_FAVORITES: return SDL_SCANCODE_AC_BOOKMARKS;
+ case VK_BROWSER_HOME: return SDL_SCANCODE_AC_HOME;
+ case VK_VOLUME_MUTE: return SDL_SCANCODE_AUDIOMUTE;
+ case VK_VOLUME_DOWN: return SDL_SCANCODE_VOLUMEDOWN;
+ case VK_VOLUME_UP: return SDL_SCANCODE_VOLUMEUP;
+
+ case VK_MEDIA_NEXT_TRACK: return SDL_SCANCODE_AUDIONEXT;
+ case VK_MEDIA_PREV_TRACK: return SDL_SCANCODE_AUDIOPREV;
+ case VK_MEDIA_STOP: return SDL_SCANCODE_AUDIOSTOP;
+ case VK_MEDIA_PLAY_PAUSE: return SDL_SCANCODE_AUDIOPLAY;
+ case VK_LAUNCH_MAIL: return SDL_SCANCODE_MAIL;
+ case VK_LAUNCH_MEDIA_SELECT: return SDL_SCANCODE_MEDIASELECT;
+
+ case VK_OEM_102: return SDL_SCANCODE_NONUSBACKSLASH;
+
+ case VK_ATTN: return SDL_SCANCODE_SYSREQ;
+ case VK_CRSEL: return SDL_SCANCODE_CRSEL;
+ case VK_EXSEL: return SDL_SCANCODE_EXSEL;
+ case VK_OEM_CLEAR: return SDL_SCANCODE_CLEAR;
+
+ case VK_LAUNCH_APP1: return SDL_SCANCODE_APP1;
+ case VK_LAUNCH_APP2: return SDL_SCANCODE_APP2;
+
+ default: return SDL_SCANCODE_UNKNOWN;
+ }
+}
+
+static SDL_Scancode
+WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
+{
+ SDL_Scancode code;
+ int nScanCode = (lParam >> 16) & 0xFF;
+ SDL_bool bIsExtended = (lParam & (1 << 24)) != 0;
+
+ code = VKeytoScancode(wParam);
+
+ if (code == SDL_SCANCODE_UNKNOWN && nScanCode <= 127) {
+ code = windows_scancode_table[nScanCode];
+
+ if (bIsExtended) {
+ switch (code) {
+ case SDL_SCANCODE_RETURN:
+ code = SDL_SCANCODE_KP_ENTER;
+ break;
+ case SDL_SCANCODE_LALT:
+ code = SDL_SCANCODE_RALT;
+ break;
+ case SDL_SCANCODE_LCTRL:
+ code = SDL_SCANCODE_RCTRL;
+ break;
+ case SDL_SCANCODE_SLASH:
+ code = SDL_SCANCODE_KP_DIVIDE;
+ break;
+ case SDL_SCANCODE_CAPSLOCK:
+ code = SDL_SCANCODE_KP_PLUS;
+ break;
+ default:
+ break;
+ }
+ } else {
+ switch (code) {
+ case SDL_SCANCODE_HOME:
+ code = SDL_SCANCODE_KP_7;
+ break;
+ case SDL_SCANCODE_UP:
+ code = SDL_SCANCODE_KP_8;
+ break;
+ case SDL_SCANCODE_PAGEUP:
+ code = SDL_SCANCODE_KP_9;
+ break;
+ case SDL_SCANCODE_LEFT:
+ code = SDL_SCANCODE_KP_4;
+ break;
+ case SDL_SCANCODE_RIGHT:
+ code = SDL_SCANCODE_KP_6;
+ break;
+ case SDL_SCANCODE_END:
+ code = SDL_SCANCODE_KP_1;
+ break;
+ case SDL_SCANCODE_DOWN:
+ code = SDL_SCANCODE_KP_2;
+ break;
+ case SDL_SCANCODE_PAGEDOWN:
+ code = SDL_SCANCODE_KP_3;
+ break;
+ case SDL_SCANCODE_INSERT:
+ code = SDL_SCANCODE_KP_0;
+ break;
+ case SDL_SCANCODE_DELETE:
+ code = SDL_SCANCODE_KP_PERIOD;
+ break;
+ case SDL_SCANCODE_PRINTSCREEN:
+ code = SDL_SCANCODE_KP_MULTIPLY;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ return code;
+}
+
+static SDL_bool
+WIN_ShouldIgnoreFocusClick()
+{
+ return !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
+}
+
+static void
+WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID)
+{
+ if (data->focus_click_pending & SDL_BUTTON(button)) {
+ /* Ignore the button click for activation */
+ if (!bwParamMousePressed) {
+ data->focus_click_pending &= ~SDL_BUTTON(button);
+ WIN_UpdateClipCursor(data->window);
+ }
+ if (WIN_ShouldIgnoreFocusClick()) {
+ return;
+ }
+ }
+
+ if (bwParamMousePressed && !bSDLMousePressed) {
+ SDL_SendMouseButton(data->window, mouseID, SDL_PRESSED, button);
+ } else if (!bwParamMousePressed && bSDLMousePressed) {
+ SDL_SendMouseButton(data->window, mouseID, SDL_RELEASED, button);
+ }
+}
+
+/*
+* Some windows systems fail to send a WM_LBUTTONDOWN sometimes, but each mouse move contains the current button state also
+* so this funciton reconciles our view of the world with the current buttons reported by windows
+*/
+static void
+WIN_CheckWParamMouseButtons(WPARAM wParam, SDL_WindowData *data, SDL_MouseID mouseID)
+{
+ if (wParam != data->mouse_button_flags) {
+ Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
+ WIN_CheckWParamMouseButton((wParam & MK_LBUTTON), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, mouseID);
+ WIN_CheckWParamMouseButton((wParam & MK_MBUTTON), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, mouseID);
+ WIN_CheckWParamMouseButton((wParam & MK_RBUTTON), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, mouseID);
+ WIN_CheckWParamMouseButton((wParam & MK_XBUTTON1), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, mouseID);
+ WIN_CheckWParamMouseButton((wParam & MK_XBUTTON2), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, mouseID);
+ data->mouse_button_flags = wParam;
+ }
+}
+
+
+static void
+WIN_CheckRawMouseButtons(ULONG rawButtons, SDL_WindowData *data)
+{
+ if (rawButtons != data->mouse_button_flags) {
+ Uint32 mouseFlags = SDL_GetMouseState(NULL, NULL);
+ if ((rawButtons & RI_MOUSE_BUTTON_1_DOWN))
+ WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_1_DOWN), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_1_UP))
+ WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_1_UP), (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_2_DOWN))
+ WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_2_DOWN), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_2_UP))
+ WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_2_UP), (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_3_DOWN))
+ WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_3_DOWN), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_3_UP))
+ WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_3_UP), (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_4_DOWN))
+ WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_4_DOWN), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_4_UP))
+ WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_4_UP), (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_5_DOWN))
+ WIN_CheckWParamMouseButton((rawButtons & RI_MOUSE_BUTTON_5_DOWN), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
+ if ((rawButtons & RI_MOUSE_BUTTON_5_UP))
+ WIN_CheckWParamMouseButton(!(rawButtons & RI_MOUSE_BUTTON_5_UP), (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
+ data->mouse_button_flags = rawButtons;
+ }
+}
+
+static void
+WIN_CheckAsyncMouseRelease(SDL_WindowData *data)
+{
+ Uint32 mouseFlags;
+ SHORT keyState;
+
+ /* mouse buttons may have changed state here, we need to resync them,
+ but we will get a WM_MOUSEMOVE right away which will fix things up if in non raw mode also
+ */
+ mouseFlags = SDL_GetMouseState(NULL, NULL);
+
+ keyState = GetAsyncKeyState(VK_LBUTTON);
+ if (!(keyState & 0x8000)) {
+ WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_LMASK), data, SDL_BUTTON_LEFT, 0);
+ }
+ keyState = GetAsyncKeyState(VK_RBUTTON);
+ if (!(keyState & 0x8000)) {
+ WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_RMASK), data, SDL_BUTTON_RIGHT, 0);
+ }
+ keyState = GetAsyncKeyState(VK_MBUTTON);
+ if (!(keyState & 0x8000)) {
+ WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_MMASK), data, SDL_BUTTON_MIDDLE, 0);
+ }
+ keyState = GetAsyncKeyState(VK_XBUTTON1);
+ if (!(keyState & 0x8000)) {
+ WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X1MASK), data, SDL_BUTTON_X1, 0);
+ }
+ keyState = GetAsyncKeyState(VK_XBUTTON2);
+ if (!(keyState & 0x8000)) {
+ WIN_CheckWParamMouseButton(SDL_FALSE, (mouseFlags & SDL_BUTTON_X2MASK), data, SDL_BUTTON_X2, 0);
+ }
+ data->mouse_button_flags = 0;
+}
+
+static BOOL
+WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
+{
+ if (codepoint <= 0x7F) {
+ text[0] = (char) codepoint;
+ text[1] = '\0';
+ } else if (codepoint <= 0x7FF) {
+ text[0] = 0xC0 | (char) ((codepoint >> 6) & 0x1F);
+ text[1] = 0x80 | (char) (codepoint & 0x3F);
+ text[2] = '\0';
+ } else if (codepoint <= 0xFFFF) {
+ text[0] = 0xE0 | (char) ((codepoint >> 12) & 0x0F);
+ text[1] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
+ text[2] = 0x80 | (char) (codepoint & 0x3F);
+ text[3] = '\0';
+ } else if (codepoint <= 0x10FFFF) {
+ text[0] = 0xF0 | (char) ((codepoint >> 18) & 0x0F);
+ text[1] = 0x80 | (char) ((codepoint >> 12) & 0x3F);
+ text[2] = 0x80 | (char) ((codepoint >> 6) & 0x3F);
+ text[3] = 0x80 | (char) (codepoint & 0x3F);
+ text[4] = '\0';
+ } else {
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+}
+
+static SDL_bool
+ShouldGenerateWindowCloseOnAltF4(void)
+{
+ return !SDL_GetHintBoolean(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, SDL_FALSE);
+}
+
+/* Win10 "Fall Creators Update" introduced the bug that SetCursorPos() (as used by SDL_WarpMouseInWindow())
+ doesn't reliably generate WM_MOUSEMOVE events anymore (see #3931) which breaks relative mouse mode via warping.
+ This is used to implement a workaround.. */
+static SDL_bool isWin10FCUorNewer = SDL_FALSE;
+
+LRESULT CALLBACK
+WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ SDL_WindowData *data;
+ LRESULT returnCode = -1;
+
+ /* Send a SDL_SYSWMEVENT if the application wants them */
+ if (SDL_GetEventState(SDL_SYSWMEVENT) == SDL_ENABLE) {
+ SDL_SysWMmsg wmmsg;
+
+ SDL_VERSION(&wmmsg.version);
+ wmmsg.subsystem = SDL_SYSWM_WINDOWS;
+ wmmsg.msg.win.hwnd = hwnd;
+ wmmsg.msg.win.msg = msg;
+ wmmsg.msg.win.wParam = wParam;
+ wmmsg.msg.win.lParam = lParam;
+ SDL_SendSysWMEvent(&wmmsg);
+ }
+
+ /* Get the window data for the window */
+ data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData"));
+ if (!data) {
+ return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
+ }
+
+#ifdef WMMSG_DEBUG
+ {
+ char message[1024];
+ if (msg > MAX_WMMSG) {
+ SDL_snprintf(message, sizeof(message), "Received windows message: %p UNKNOWN (%d) -- 0x%X, 0x%X\n", hwnd, msg, wParam, lParam);
+ } else {
+ SDL_snprintf(message, sizeof(message), "Received windows message: %p %s -- 0x%X, 0x%X\n", hwnd, wmtab[msg], wParam, lParam);
+ }
+ OutputDebugStringA(message);
+ }
+#endif /* WMMSG_DEBUG */
+
+ if (IME_HandleMessage(hwnd, msg, wParam, &lParam, data->videodata))
+ return 0;
+
+ switch (msg) {
+
+ case WM_SHOWWINDOW:
+ {
+ if (wParam) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
+ } else {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
+ }
+ }
+ break;
+
+ case WM_NCACTIVATE:
+ {
+ /* Don't immediately clip the cursor in case we're clicking minimize/maximize buttons */
+ data->skip_update_clipcursor = SDL_TRUE;
+ }
+ break;
+
+ case WM_ACTIVATE:
+ {
+ POINT cursorPos;
+ BOOL minimized;
+
+ /* Don't mark the window as shown if it's activated before being shown */
+ if (!IsWindowVisible(hwnd)) {
+ break;
+ }
+
+ minimized = HIWORD(wParam);
+ if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
+ if (LOWORD(wParam) == WA_CLICKACTIVE) {
+ if (GetAsyncKeyState(VK_LBUTTON)) {
+ data->focus_click_pending |= SDL_BUTTON_LMASK;
+ }
+ if (GetAsyncKeyState(VK_RBUTTON)) {
+ data->focus_click_pending |= SDL_BUTTON_RMASK;
+ }
+ if (GetAsyncKeyState(VK_MBUTTON)) {
+ data->focus_click_pending |= SDL_BUTTON_MMASK;
+ }
+ if (GetAsyncKeyState(VK_XBUTTON1)) {
+ data->focus_click_pending |= SDL_BUTTON_X1MASK;
+ }
+ if (GetAsyncKeyState(VK_XBUTTON2)) {
+ data->focus_click_pending |= SDL_BUTTON_X2MASK;
+ }
+ }
+
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
+ if (SDL_GetKeyboardFocus() != data->window) {
+ SDL_SetKeyboardFocus(data->window);
+ }
+
+ GetCursorPos(&cursorPos);
+ ScreenToClient(hwnd, &cursorPos);
+ SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
+
+ WIN_CheckAsyncMouseRelease(data);
+
+ /*
+ * FIXME: Update keyboard state
+ */
+ WIN_CheckClipboardUpdate(data->videodata);
+
+ SDL_ToggleModState(KMOD_CAPS, (GetKeyState(VK_CAPITAL) & 0x0001) != 0);
+ SDL_ToggleModState(KMOD_NUM, (GetKeyState(VK_NUMLOCK) & 0x0001) != 0);
+ } else {
+ RECT rect;
+
+ data->in_window_deactivation = SDL_TRUE;
+
+ if (SDL_GetKeyboardFocus() == data->window) {
+ SDL_SetKeyboardFocus(NULL);
+ WIN_ResetDeadKeys();
+ }
+
+ if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect) == 0)) {
+ ClipCursor(NULL);
+ SDL_zero(data->cursor_clipped_rect);
+ }
+
+ data->in_window_deactivation = SDL_FALSE;
+ }
+ }
+ returnCode = 0;
+ break;
+
+ case WM_MOUSEMOVE:
+ {
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if (!mouse->relative_mode || mouse->relative_mode_warp) {
+ SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
+ SDL_SendMouseMotion(data->window, mouseID, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ if (isWin10FCUorNewer && mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
+ /* To work around #3931, Win10 bug introduced in Fall Creators Update, where
+ SetCursorPos() (SDL_WarpMouseInWindow()) doesn't reliably generate mouse events anymore,
+ after each windows mouse event generate a fake event for the middle of the window
+ if relative_mode_warp is used */
+ int center_x = 0, center_y = 0;
+ SDL_GetWindowSize(data->window, &center_x, &center_y);
+ center_x /= 2;
+ center_y /= 2;
+ SDL_SendMouseMotion(data->window, mouseID, 0, center_x, center_y);
+ }
+ }
+ }
+ /* don't break here, fall through to check the wParam like the button presses */
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ case WM_XBUTTONUP:
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDOWN:
+ case WM_MBUTTONDBLCLK:
+ case WM_XBUTTONDOWN:
+ case WM_XBUTTONDBLCLK:
+ {
+ SDL_Mouse *mouse = SDL_GetMouse();
+ if (!mouse->relative_mode || mouse->relative_mode_warp) {
+ SDL_MouseID mouseID = (((GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH) ? SDL_TOUCH_MOUSEID : 0);
+ WIN_CheckWParamMouseButtons(wParam, data, mouseID);
+ }
+ }
+ break;
+
+ case WM_INPUT:
+ {
+ SDL_Mouse *mouse = SDL_GetMouse();
+ HRAWINPUT hRawInput = (HRAWINPUT)lParam;
+ RAWINPUT inp;
+ UINT size = sizeof(inp);
+ const SDL_bool isRelative = mouse->relative_mode || mouse->relative_mode_warp;
+ const SDL_bool isCapture = ((data->window->flags & SDL_WINDOW_MOUSE_CAPTURE) != 0);
+
+ if (!isRelative || mouse->focus != data->window) {
+ if (!isCapture) {
+ break;
+ }
+ }
+
+ GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER));
+
+ /* Mouse data */
+ if (inp.header.dwType == RIM_TYPEMOUSE) {
+ if (isRelative) {
+ RAWMOUSE* rawmouse = &inp.data.mouse;
+
+ if ((rawmouse->usFlags & 0x01) == MOUSE_MOVE_RELATIVE) {
+ SDL_SendMouseMotion(data->window, 0, 1, (int)rawmouse->lLastX, (int)rawmouse->lLastY);
+ } else {
+ /* synthesize relative moves from the abs position */
+ static SDL_Point initialMousePoint;
+ if (initialMousePoint.x == 0 && initialMousePoint.y == 0) {
+ initialMousePoint.x = rawmouse->lLastX;
+ initialMousePoint.y = rawmouse->lLastY;
+ }
+
+ SDL_SendMouseMotion(data->window, 0, 1, (int)(rawmouse->lLastX-initialMousePoint.x), (int)(rawmouse->lLastY-initialMousePoint.y));
+
+ initialMousePoint.x = rawmouse->lLastX;
+ initialMousePoint.y = rawmouse->lLastY;
+ }
+ WIN_CheckRawMouseButtons(rawmouse->usButtonFlags, data);
+ } else if (isCapture) {
+ /* we check for where Windows thinks the system cursor lives in this case, so we don't really lose mouse accel, etc. */
+ POINT pt;
+ RECT hwndRect;
+ HWND currentHnd;
+
+ GetCursorPos(&pt);
+ currentHnd = WindowFromPoint(pt);
+ ScreenToClient(hwnd, &pt);
+ GetClientRect(hwnd, &hwndRect);
+
+ /* if in the window, WM_MOUSEMOVE, etc, will cover it. */
+ if(currentHnd != hwnd || pt.x < 0 || pt.y < 0 || pt.x > hwndRect.right || pt.y > hwndRect.right) {
+ SDL_SendMouseMotion(data->window, 0, 0, (int)pt.x, (int)pt.y);
+ SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_LEFT);
+ SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_RIGHT);
+ SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_MIDDLE);
+ SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X1);
+ SDL_SendMouseButton(data->window, 0, GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_PRESSED : SDL_RELEASED, SDL_BUTTON_X2);
+ }
+ } else {
+ SDL_assert(0 && "Shouldn't happen");
+ }
+ }
+ }
+ break;
+
+ case WM_MOUSEWHEEL:
+ case WM_MOUSEHWHEEL:
+ {
+ short amount = GET_WHEEL_DELTA_WPARAM(wParam);
+ float fAmount = (float) amount / WHEEL_DELTA;
+ if (msg == WM_MOUSEWHEEL)
+ SDL_SendMouseWheel(data->window, 0, 0.0f, fAmount, SDL_MOUSEWHEEL_NORMAL);
+ else
+ SDL_SendMouseWheel(data->window, 0, fAmount, 0.0f, SDL_MOUSEWHEEL_NORMAL);
+ }
+ break;
+
+#ifdef WM_MOUSELEAVE
+ case WM_MOUSELEAVE:
+ if (SDL_GetMouseFocus() == data->window && !SDL_GetMouse()->relative_mode && !(data->window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
+ if (!IsIconic(hwnd)) {
+ POINT cursorPos;
+ GetCursorPos(&cursorPos);
+ ScreenToClient(hwnd, &cursorPos);
+ SDL_SendMouseMotion(data->window, 0, 0, cursorPos.x, cursorPos.y);
+ }
+ SDL_SetMouseFocus(NULL);
+ }
+ returnCode = 0;
+ break;
+#endif /* WM_MOUSELEAVE */
+
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ {
+ SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
+ const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
+
+ /* Detect relevant keyboard shortcuts */
+ if (keyboardState[SDL_SCANCODE_LALT] == SDL_PRESSED || keyboardState[SDL_SCANCODE_RALT] == SDL_PRESSED) {
+ /* ALT+F4: Close window */
+ if (code == SDL_SCANCODE_F4 && ShouldGenerateWindowCloseOnAltF4()) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
+ }
+ }
+
+ if (code != SDL_SCANCODE_UNKNOWN) {
+ SDL_SendKeyboardKey(SDL_PRESSED, code);
+ }
+ }
+
+ returnCode = 0;
+ break;
+
+ case WM_SYSKEYUP:
+ case WM_KEYUP:
+ {
+ SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam);
+ const Uint8 *keyboardState = SDL_GetKeyboardState(NULL);
+
+ if (code != SDL_SCANCODE_UNKNOWN) {
+ if (code == SDL_SCANCODE_PRINTSCREEN &&
+ keyboardState[code] == SDL_RELEASED) {
+ SDL_SendKeyboardKey(SDL_PRESSED, code);
+ }
+ SDL_SendKeyboardKey(SDL_RELEASED, code);
+ }
+ }
+ returnCode = 0;
+ break;
+
+ case WM_UNICHAR:
+ if (wParam == UNICODE_NOCHAR) {
+ returnCode = 1;
+ break;
+ }
+ /* otherwise fall through to below */
+ case WM_CHAR:
+ {
+ char text[5];
+ if (WIN_ConvertUTF32toUTF8((UINT32)wParam, text)) {
+ SDL_SendKeyboardText(text);
+ }
+ }
+ returnCode = 0;
+ break;
+
+#ifdef WM_INPUTLANGCHANGE
+ case WM_INPUTLANGCHANGE:
+ {
+ WIN_UpdateKeymap();
+ SDL_SendKeymapChangedEvent();
+ }
+ returnCode = 1;
+ break;
+#endif /* WM_INPUTLANGCHANGE */
+
+ case WM_NCLBUTTONDOWN:
+ {
+ data->in_title_click = SDL_TRUE;
+ }
+ break;
+
+ case WM_CAPTURECHANGED:
+ {
+ data->in_title_click = SDL_FALSE;
+
+ /* The mouse may have been released during a modal loop */
+ WIN_CheckAsyncMouseRelease(data);
+ }
+ break;
+
+#ifdef WM_GETMINMAXINFO
+ case WM_GETMINMAXINFO:
+ {
+ MINMAXINFO *info;
+ RECT size;
+ int x, y;
+ int w, h;
+ int min_w, min_h;
+ int max_w, max_h;
+ BOOL constrain_max_size;
+
+ if (SDL_IsShapedWindow(data->window))
+ Win32_ResizeWindowShape(data->window);
+
+ /* If this is an expected size change, allow it */
+ if (data->expected_resize) {
+ break;
+ }
+
+ /* Get the current position of our window */
+ GetWindowRect(hwnd, &size);
+ x = size.left;
+ y = size.top;
+
+ /* Calculate current size of our window */
+ SDL_GetWindowSize(data->window, &w, &h);
+ SDL_GetWindowMinimumSize(data->window, &min_w, &min_h);
+ SDL_GetWindowMaximumSize(data->window, &max_w, &max_h);
+
+ /* Store in min_w and min_h difference between current size and minimal
+ size so we don't need to call AdjustWindowRectEx twice */
+ min_w -= w;
+ min_h -= h;
+ if (max_w && max_h) {
+ max_w -= w;
+ max_h -= h;
+ constrain_max_size = TRUE;
+ } else {
+ constrain_max_size = FALSE;
+ }
+
+ if (!(SDL_GetWindowFlags(data->window) & SDL_WINDOW_BORDERLESS)) {
+ LONG style = GetWindowLong(hwnd, GWL_STYLE);
+ /* DJM - according to the docs for GetMenu(), the
+ return value is undefined if hwnd is a child window.
+ Apparently it's too difficult for MS to check
+ inside their function, so I have to do it here.
+ */
+ BOOL menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
+ size.top = 0;
+ size.left = 0;
+ size.bottom = h;
+ size.right = w;
+
+ AdjustWindowRectEx(&size, style, menu, 0);
+ w = size.right - size.left;
+ h = size.bottom - size.top;
+ }
+
+ /* Fix our size to the current size */
+ info = (MINMAXINFO *) lParam;
+ if (SDL_GetWindowFlags(data->window) & SDL_WINDOW_RESIZABLE) {
+ info->ptMinTrackSize.x = w + min_w;
+ info->ptMinTrackSize.y = h + min_h;
+ if (constrain_max_size) {
+ info->ptMaxTrackSize.x = w + max_w;
+ info->ptMaxTrackSize.y = h + max_h;
+ }
+ } else {
+ info->ptMaxSize.x = w;
+ info->ptMaxSize.y = h;
+ info->ptMaxPosition.x = x;
+ info->ptMaxPosition.y = y;
+ info->ptMinTrackSize.x = w;
+ info->ptMinTrackSize.y = h;
+ info->ptMaxTrackSize.x = w;
+ info->ptMaxTrackSize.y = h;
+ }
+ }
+ returnCode = 0;
+ break;
+#endif /* WM_GETMINMAXINFO */
+
+ case WM_WINDOWPOSCHANGING:
+
+ if (data->expected_resize) {
+ returnCode = 0;
+ }
+ break;
+
+ case WM_WINDOWPOSCHANGED:
+ {
+ RECT rect;
+ int x, y;
+ int w, h;
+
+ if (data->initializing || data->in_border_change) {
+ break;
+ }
+
+ if (!GetClientRect(hwnd, &rect) || IsRectEmpty(&rect)) {
+ break;
+ }
+ ClientToScreen(hwnd, (LPPOINT) & rect);
+ ClientToScreen(hwnd, (LPPOINT) & rect + 1);
+
+ WIN_UpdateClipCursor(data->window);
+
+ x = rect.left;
+ y = rect.top;
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED, x, y);
+
+ w = rect.right - rect.left;
+ h = rect.bottom - rect.top;
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
+ h);
+
+ /* Forces a WM_PAINT event */
+ InvalidateRect(hwnd, NULL, FALSE);
+ }
+ break;
+
+ case WM_SIZE:
+ {
+ switch (wParam) {
+ case SIZE_MAXIMIZED:
+ SDL_SendWindowEvent(data->window,
+ SDL_WINDOWEVENT_RESTORED, 0, 0);
+ SDL_SendWindowEvent(data->window,
+ SDL_WINDOWEVENT_MAXIMIZED, 0, 0);
+ break;
+ case SIZE_MINIMIZED:
+ SDL_SendWindowEvent(data->window,
+ SDL_WINDOWEVENT_MINIMIZED, 0, 0);
+ break;
+ default:
+ SDL_SendWindowEvent(data->window,
+ SDL_WINDOWEVENT_RESTORED, 0, 0);
+ break;
+ }
+ }
+ break;
+
+ case WM_SETCURSOR:
+ {
+ Uint16 hittest;
+
+ hittest = LOWORD(lParam);
+ if (hittest == HTCLIENT) {
+ SetCursor(SDL_cursor);
+ returnCode = TRUE;
+ } else if (!g_WindowFrameUsableWhileCursorHidden && !SDL_cursor) {
+ SetCursor(NULL);
+ returnCode = TRUE;
+ }
+ }
+ break;
+
+ /* We were occluded, refresh our display */
+ case WM_PAINT:
+ {
+ RECT rect;
+ if (GetUpdateRect(hwnd, &rect, FALSE)) {
+ ValidateRect(hwnd, NULL);
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED,
+ 0, 0);
+ }
+ }
+ returnCode = 0;
+ break;
+
+ /* We'll do our own drawing, prevent flicker */
+ case WM_ERASEBKGND:
+ {
+ }
+ return (1);
+
+ case WM_SYSCOMMAND:
+ {
+ if ((wParam & 0xFFF0) == SC_KEYMENU) {
+ return (0);
+ }
+
+#if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)
+ /* Don't start the screensaver or blank the monitor in fullscreen apps */
+ if ((wParam & 0xFFF0) == SC_SCREENSAVE ||
+ (wParam & 0xFFF0) == SC_MONITORPOWER) {
+ if (SDL_GetVideoDevice()->suspend_screensaver) {
+ return (0);
+ }
+ }
+#endif /* System has screensaver support */
+ }
+ break;
+
+ case WM_CLOSE:
+ {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
+ }
+ returnCode = 0;
+ break;
+
+ case WM_TOUCH:
+ if (data->videodata->GetTouchInputInfo && data->videodata->CloseTouchInputHandle) {
+ UINT i, num_inputs = LOWORD(wParam);
+ PTOUCHINPUT inputs = SDL_stack_alloc(TOUCHINPUT, num_inputs);
+ if (data->videodata->GetTouchInputInfo((HTOUCHINPUT)lParam, num_inputs, inputs, sizeof(TOUCHINPUT))) {
+ RECT rect;
+ float x, y;
+
+ if (!GetClientRect(hwnd, &rect) ||
+ (rect.right == rect.left && rect.bottom == rect.top)) {
+ if (inputs) {
+ SDL_stack_free(inputs);
+ }
+ break;
+ }
+ ClientToScreen(hwnd, (LPPOINT) & rect);
+ ClientToScreen(hwnd, (LPPOINT) & rect + 1);
+ rect.top *= 100;
+ rect.left *= 100;
+ rect.bottom *= 100;
+ rect.right *= 100;
+
+ for (i = 0; i < num_inputs; ++i) {
+ PTOUCHINPUT input = &inputs[i];
+
+ const SDL_TouchID touchId = (SDL_TouchID)((size_t)input->hSource);
+ if (SDL_AddTouch(touchId, "") < 0) {
+ continue;
+ }
+
+ /* Get the normalized coordinates for the window */
+ x = (float)(input->x - rect.left)/(rect.right - rect.left);
+ y = (float)(input->y - rect.top)/(rect.bottom - rect.top);
+
+ if (input->dwFlags & TOUCHEVENTF_DOWN) {
+ SDL_SendTouch(touchId, input->dwID, SDL_TRUE, x, y, 1.0f);
+ }
+ if (input->dwFlags & TOUCHEVENTF_MOVE) {
+ SDL_SendTouchMotion(touchId, input->dwID, x, y, 1.0f);
+ }
+ if (input->dwFlags & TOUCHEVENTF_UP) {
+ SDL_SendTouch(touchId, input->dwID, SDL_FALSE, x, y, 1.0f);
+ }
+ }
+ }
+ SDL_stack_free(inputs);
+
+ data->videodata->CloseTouchInputHandle((HTOUCHINPUT)lParam);
+ return 0;
+ }
+ break;
+
+ case WM_DROPFILES:
+ {
+ UINT i;
+ HDROP drop = (HDROP) wParam;
+ UINT count = DragQueryFile(drop, 0xFFFFFFFF, NULL, 0);
+ for (i = 0; i < count; ++i) {
+ UINT size = DragQueryFile(drop, i, NULL, 0) + 1;
+ LPTSTR buffer = SDL_stack_alloc(TCHAR, size);
+ if (buffer) {
+ if (DragQueryFile(drop, i, buffer, size)) {
+ char *file = WIN_StringToUTF8(buffer);
+ SDL_SendDropFile(data->window, file);
+ SDL_free(file);
+ }
+ SDL_stack_free(buffer);
+ }
+ }
+ SDL_SendDropComplete(data->window);
+ DragFinish(drop);
+ return 0;
+ }
+ break;
+
+ case WM_NCCALCSIZE:
+ {
+ Uint32 window_flags = SDL_GetWindowFlags(data->window);
+ if (wParam == TRUE && (window_flags & SDL_WINDOW_BORDERLESS) && !(window_flags & SDL_WINDOW_FULLSCREEN)) {
+ /* When borderless, need to tell windows that the size of the non-client area is 0 */
+ if (!(window_flags & SDL_WINDOW_RESIZABLE)) {
+ int w, h;
+ NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS *)lParam;
+ w = data->window->windowed.w;
+ h = data->window->windowed.h;
+ params->rgrc[0].right = params->rgrc[0].left + w;
+ params->rgrc[0].bottom = params->rgrc[0].top + h;
+ }
+ return 0;
+ }
+ }
+ break;
+
+ case WM_NCHITTEST:
+ {
+ SDL_Window *window = data->window;
+ if (window->hit_test) {
+ POINT winpoint = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
+ if (ScreenToClient(hwnd, &winpoint)) {
+ const SDL_Point point = { (int) winpoint.x, (int) winpoint.y };
+ const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
+ switch (rc) {
+ #define POST_HIT_TEST(ret) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); return ret; }
+ case SDL_HITTEST_DRAGGABLE: POST_HIT_TEST(HTCAPTION);
+ case SDL_HITTEST_RESIZE_TOPLEFT: POST_HIT_TEST(HTTOPLEFT);
+ case SDL_HITTEST_RESIZE_TOP: POST_HIT_TEST(HTTOP);
+ case SDL_HITTEST_RESIZE_TOPRIGHT: POST_HIT_TEST(HTTOPRIGHT);
+ case SDL_HITTEST_RESIZE_RIGHT: POST_HIT_TEST(HTRIGHT);
+ case SDL_HITTEST_RESIZE_BOTTOMRIGHT: POST_HIT_TEST(HTBOTTOMRIGHT);
+ case SDL_HITTEST_RESIZE_BOTTOM: POST_HIT_TEST(HTBOTTOM);
+ case SDL_HITTEST_RESIZE_BOTTOMLEFT: POST_HIT_TEST(HTBOTTOMLEFT);
+ case SDL_HITTEST_RESIZE_LEFT: POST_HIT_TEST(HTLEFT);
+ #undef POST_HIT_TEST
+ case SDL_HITTEST_NORMAL: return HTCLIENT;
+ }
+ }
+ /* If we didn't return, this will call DefWindowProc below. */
+ }
+ }
+ break;
+ }
+
+ /* If there's a window proc, assume it's going to handle messages */
+ if (data->wndproc) {
+ return CallWindowProc(data->wndproc, hwnd, msg, wParam, lParam);
+ } else if (returnCode >= 0) {
+ return returnCode;
+ } else {
+ return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam);
+ }
+}
+
+static void WIN_UpdateClipCursorForWindows()
+{
+ SDL_VideoDevice *_this = SDL_GetVideoDevice();
+ SDL_Window *window;
+
+ if (_this) {
+ for (window = _this->windows; window; window = window->next) {
+ if (window->driverdata) {
+ WIN_UpdateClipCursor(window);
+ }
+ }
+ }
+}
+
+/* A message hook called before TranslateMessage() */
+static SDL_WindowsMessageHook g_WindowsMessageHook = NULL;
+static void *g_WindowsMessageHookData = NULL;
+
+void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata)
+{
+ g_WindowsMessageHook = callback;
+ g_WindowsMessageHookData = userdata;
+}
+
+void
+WIN_PumpEvents(_THIS)
+{
+ const Uint8 *keystate;
+ MSG msg;
+ DWORD start_ticks = GetTickCount();
+
+ if (g_WindowsEnableMessageLoop) {
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ if (g_WindowsMessageHook) {
+ g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam);
+ }
+
+ /* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+
+ /* Make sure we don't busy loop here forever if there are lots of events coming in */
+ if (SDL_TICKS_PASSED(msg.time, start_ticks)) {
+ break;
+ }
+ }
+ }
+
+ /* Windows loses a shift KEYUP event when you have both pressed at once and let go of one.
+ You won't get a KEYUP until both are released, and that keyup will only be for the second
+ key you released. Take heroic measures and check the keystate as of the last handled event,
+ and if we think a key is pressed when Windows doesn't, unstick it in SDL's state. */
+ keystate = SDL_GetKeyboardState(NULL);
+ if ((keystate[SDL_SCANCODE_LSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_LSHIFT) & 0x8000)) {
+ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_LSHIFT);
+ }
+ if ((keystate[SDL_SCANCODE_RSHIFT] == SDL_PRESSED) && !(GetKeyState(VK_RSHIFT) & 0x8000)) {
+ SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_RSHIFT);
+ }
+
+ /* Update the clipping rect in case someone else has stolen it */
+ WIN_UpdateClipCursorForWindows();
+}
+
+/* to work around #3931, a bug introduced in Win10 Fall Creators Update (build nr. 16299)
+ we need to detect the windows version. this struct and the function below does that.
+ usually this struct and the corresponding function (RtlGetVersion) are in <Ntddk.h>
+ but here we just load it dynamically */
+struct SDL_WIN_OSVERSIONINFOW {
+ ULONG dwOSVersionInfoSize;
+ ULONG dwMajorVersion;
+ ULONG dwMinorVersion;
+ ULONG dwBuildNumber;
+ ULONG dwPlatformId;
+ WCHAR szCSDVersion[128];
+};
+
+static SDL_bool
+IsWin10FCUorNewer(void)
+{
+ HMODULE handle = GetModuleHandleW(L"ntdll.dll");
+ if (handle) {
+ typedef LONG(WINAPI* RtlGetVersionPtr)(struct SDL_WIN_OSVERSIONINFOW*);
+ RtlGetVersionPtr getVersionPtr = (RtlGetVersionPtr)GetProcAddress(handle, "RtlGetVersion");
+ if (getVersionPtr != NULL) {
+ struct SDL_WIN_OSVERSIONINFOW info;
+ SDL_zero(info);
+ info.dwOSVersionInfoSize = sizeof(info);
+ if (getVersionPtr(&info) == 0) { /* STATUS_SUCCESS == 0 */
+ if ((info.dwMajorVersion == 10 && info.dwMinorVersion == 0 && info.dwBuildNumber >= 16299) ||
+ (info.dwMajorVersion == 10 && info.dwMinorVersion > 0) ||
+ (info.dwMajorVersion > 10))
+ {
+ return SDL_TRUE;
+ }
+ }
+ }
+ }
+ return SDL_FALSE;
+}
+
+static int app_registered = 0;
+LPTSTR SDL_Appname = NULL;
+Uint32 SDL_Appstyle = 0;
+HINSTANCE SDL_Instance = NULL;
+
+/* Register the class for this application */
+int
+SDL_RegisterApp(char *name, Uint32 style, void *hInst)
+{
+ const char *hint;
+ WNDCLASSEX wcex;
+ TCHAR path[MAX_PATH];
+
+ /* Only do this once... */
+ if (app_registered) {
+ ++app_registered;
+ return (0);
+ }
+ if (!name && !SDL_Appname) {
+ name = "SDL_app";
+#if defined(CS_BYTEALIGNCLIENT) || defined(CS_OWNDC)
+ SDL_Appstyle = (CS_BYTEALIGNCLIENT | CS_OWNDC);
+#endif
+ SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
+ }
+
+ if (name) {
+ SDL_Appname = WIN_UTF8ToString(name);
+ SDL_Appstyle = style;
+ SDL_Instance = hInst ? hInst : GetModuleHandle(NULL);
+ }
+
+ /* Register the application class */
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.hCursor = NULL;
+ wcex.hIcon = NULL;
+ wcex.hIconSm = NULL;
+ wcex.lpszMenuName = NULL;
+ wcex.lpszClassName = SDL_Appname;
+ wcex.style = SDL_Appstyle;
+ wcex.hbrBackground = NULL;
+ wcex.lpfnWndProc = WIN_WindowProc;
+ wcex.hInstance = SDL_Instance;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+
+ hint = SDL_GetHint(SDL_HINT_WINDOWS_INTRESOURCE_ICON);
+ if (hint && *hint) {
+ wcex.hIcon = LoadIcon(SDL_Instance, MAKEINTRESOURCE(SDL_atoi(hint)));
+
+ hint = SDL_GetHint(SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL);
+ if (hint && *hint) {
+ wcex.hIconSm = LoadIcon(SDL_Instance, MAKEINTRESOURCE(SDL_atoi(hint)));
+ }
+ } else {
+ /* Use the first icon as a default icon, like in the Explorer */
+ GetModuleFileName(SDL_Instance, path, MAX_PATH);
+ ExtractIconEx(path, 0, &wcex.hIcon, &wcex.hIconSm, 1);
+ }
+
+ if (!RegisterClassEx(&wcex)) {
+ return SDL_SetError("Couldn't register application class");
+ }
+
+ isWin10FCUorNewer = IsWin10FCUorNewer();
+
+ app_registered = 1;
+ return 0;
+}
+
+/* Unregisters the windowclass registered in SDL_RegisterApp above. */
+void
+SDL_UnregisterApp()
+{
+ WNDCLASSEX wcex;
+
+ /* SDL_RegisterApp might not have been called before */
+ if (!app_registered) {
+ return;
+ }
+ --app_registered;
+ if (app_registered == 0) {
+ /* Check for any registered window classes. */
+ if (GetClassInfoEx(SDL_Instance, SDL_Appname, &wcex)) {
+ UnregisterClass(SDL_Appname, SDL_Instance);
+ if (wcex.hIcon) DestroyIcon(wcex.hIcon);
+ if (wcex.hIconSm) DestroyIcon(wcex.hIconSm);
+ }
+ SDL_free(SDL_Appname);
+ SDL_Appname = NULL;
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.h
new file mode 100644
index 0000000..1ce2fb4
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsevents.h
@@ -0,0 +1,36 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsevents_h_
+#define SDL_windowsevents_h_
+
+extern LPTSTR SDL_Appname;
+extern Uint32 SDL_Appstyle;
+extern HINSTANCE SDL_Instance;
+
+extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam,
+ LPARAM lParam);
+extern void WIN_PumpEvents(_THIS);
+
+#endif /* SDL_windowsevents_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.c
new file mode 100644
index 0000000..e07d9c4
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.c
@@ -0,0 +1,127 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_windowsvideo.h"
+
+int WIN_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ size_t size;
+ LPBITMAPINFO info;
+ HBITMAP hbm;
+
+ /* Free the old framebuffer surface */
+ if (data->mdc) {
+ DeleteDC(data->mdc);
+ }
+ if (data->hbm) {
+ DeleteObject(data->hbm);
+ }
+
+ /* Find out the format of the screen */
+ size = sizeof(BITMAPINFOHEADER) + 256 * sizeof (RGBQUAD);
+ info = (LPBITMAPINFO)SDL_stack_alloc(Uint8, size);
+ if (!info) {
+ return SDL_OutOfMemory();
+ }
+
+ SDL_memset(info, 0, size);
+ info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+
+ /* The second call to GetDIBits() fills in the bitfields */
+ hbm = CreateCompatibleBitmap(data->hdc, 1, 1);
+ GetDIBits(data->hdc, hbm, 0, 0, NULL, info, DIB_RGB_COLORS);
+ GetDIBits(data->hdc, hbm, 0, 0, NULL, info, DIB_RGB_COLORS);
+ DeleteObject(hbm);
+
+ *format = SDL_PIXELFORMAT_UNKNOWN;
+ if (info->bmiHeader.biCompression == BI_BITFIELDS) {
+ int bpp;
+ Uint32 *masks;
+
+ bpp = info->bmiHeader.biPlanes * info->bmiHeader.biBitCount;
+ masks = (Uint32*)((Uint8*)info + info->bmiHeader.biSize);
+ *format = SDL_MasksToPixelFormatEnum(bpp, masks[0], masks[1], masks[2], 0);
+ }
+ if (*format == SDL_PIXELFORMAT_UNKNOWN)
+ {
+ /* We'll use RGB format for now */
+ *format = SDL_PIXELFORMAT_RGB888;
+
+ /* Create a new one */
+ SDL_memset(info, 0, size);
+ info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ info->bmiHeader.biPlanes = 1;
+ info->bmiHeader.biBitCount = 32;
+ info->bmiHeader.biCompression = BI_RGB;
+ }
+
+ /* Fill in the size information */
+ *pitch = (((window->w * SDL_BYTESPERPIXEL(*format)) + 3) & ~3);
+ info->bmiHeader.biWidth = window->w;
+ info->bmiHeader.biHeight = -window->h; /* negative for topdown bitmap */
+ info->bmiHeader.biSizeImage = window->h * (*pitch);
+
+ data->mdc = CreateCompatibleDC(data->hdc);
+ data->hbm = CreateDIBSection(data->hdc, info, DIB_RGB_COLORS, pixels, NULL, 0);
+ SDL_stack_free(info);
+
+ if (!data->hbm) {
+ return WIN_SetError("Unable to create DIB");
+ }
+ SelectObject(data->mdc, data->hbm);
+
+ return 0;
+}
+
+int WIN_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ BitBlt(data->hdc, 0, 0, window->w, window->h, data->mdc, 0, 0, SRCCOPY);
+ return 0;
+}
+
+void WIN_DestroyWindowFramebuffer(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (!data) {
+ /* The window wasn't fully initialized */
+ return;
+ }
+
+ if (data->mdc) {
+ DeleteDC(data->mdc);
+ data->mdc = NULL;
+ }
+ if (data->hbm) {
+ DeleteObject(data->hbm);
+ data->hbm = NULL;
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.h
new file mode 100644
index 0000000..a83cca5
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsframebuffer.h
@@ -0,0 +1,27 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+extern int WIN_CreateWindowFramebuffer(_THIS, SDL_Window * window, Uint32 * format, void ** pixels, int *pitch);
+extern int WIN_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects);
+extern void WIN_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.c
new file mode 100644
index 0000000..c7f357b
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.c
@@ -0,0 +1,1579 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_windowsvideo.h"
+
+#include "../../events/SDL_keyboard_c.h"
+#include "../../events/scancodes_windows.h"
+
+#include <imm.h>
+#include <oleauto.h>
+
+#ifndef SDL_DISABLE_WINDOWS_IME
+static void IME_Init(SDL_VideoData *videodata, HWND hwnd);
+static void IME_Enable(SDL_VideoData *videodata, HWND hwnd);
+static void IME_Disable(SDL_VideoData *videodata, HWND hwnd);
+static void IME_Quit(SDL_VideoData *videodata);
+#endif /* !SDL_DISABLE_WINDOWS_IME */
+
+#ifndef MAPVK_VK_TO_VSC
+#define MAPVK_VK_TO_VSC 0
+#endif
+#ifndef MAPVK_VSC_TO_VK
+#define MAPVK_VSC_TO_VK 1
+#endif
+#ifndef MAPVK_VK_TO_CHAR
+#define MAPVK_VK_TO_CHAR 2
+#endif
+
+/* Alphabetic scancodes for PC keyboards */
+void
+WIN_InitKeyboard(_THIS)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+ data->ime_com_initialized = SDL_FALSE;
+ data->ime_threadmgr = 0;
+ data->ime_initialized = SDL_FALSE;
+ data->ime_enabled = SDL_FALSE;
+ data->ime_available = SDL_FALSE;
+ data->ime_hwnd_main = 0;
+ data->ime_hwnd_current = 0;
+ data->ime_himc = 0;
+ data->ime_composition[0] = 0;
+ data->ime_readingstring[0] = 0;
+ data->ime_cursor = 0;
+
+ data->ime_candlist = SDL_FALSE;
+ SDL_memset(data->ime_candidates, 0, sizeof(data->ime_candidates));
+ data->ime_candcount = 0;
+ data->ime_candref = 0;
+ data->ime_candsel = 0;
+ data->ime_candpgsize = 0;
+ data->ime_candlistindexbase = 0;
+ data->ime_candvertical = SDL_TRUE;
+
+ data->ime_dirty = SDL_FALSE;
+ SDL_memset(&data->ime_rect, 0, sizeof(data->ime_rect));
+ SDL_memset(&data->ime_candlistrect, 0, sizeof(data->ime_candlistrect));
+ data->ime_winwidth = 0;
+ data->ime_winheight = 0;
+
+ data->ime_hkl = 0;
+ data->ime_himm32 = 0;
+ data->GetReadingString = 0;
+ data->ShowReadingWindow = 0;
+ data->ImmLockIMC = 0;
+ data->ImmUnlockIMC = 0;
+ data->ImmLockIMCC = 0;
+ data->ImmUnlockIMCC = 0;
+ data->ime_uiless = SDL_FALSE;
+ data->ime_threadmgrex = 0;
+ data->ime_uielemsinkcookie = TF_INVALID_COOKIE;
+ data->ime_alpnsinkcookie = TF_INVALID_COOKIE;
+ data->ime_openmodesinkcookie = TF_INVALID_COOKIE;
+ data->ime_convmodesinkcookie = TF_INVALID_COOKIE;
+ data->ime_uielemsink = 0;
+ data->ime_ippasink = 0;
+
+ WIN_UpdateKeymap();
+
+ SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");
+ SDL_SetScancodeName(SDL_SCANCODE_LGUI, "Left Windows");
+ SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Windows");
+
+ /* Are system caps/num/scroll lock active? Set our state to match. */
+ SDL_ToggleModState(KMOD_CAPS, (GetKeyState(VK_CAPITAL) & 0x0001) != 0);
+ SDL_ToggleModState(KMOD_NUM, (GetKeyState(VK_NUMLOCK) & 0x0001) != 0);
+}
+
+void
+WIN_UpdateKeymap()
+{
+ int i;
+ SDL_Scancode scancode;
+ SDL_Keycode keymap[SDL_NUM_SCANCODES];
+
+ SDL_GetDefaultKeymap(keymap);
+
+ for (i = 0; i < SDL_arraysize(windows_scancode_table); i++) {
+ int vk;
+ /* Make sure this scancode is a valid character scancode */
+ scancode = windows_scancode_table[i];
+ if (scancode == SDL_SCANCODE_UNKNOWN ) {
+ continue;
+ }
+
+ /* If this key is one of the non-mappable keys, ignore it */
+ /* Not mapping numbers fixes the French layout, giving numeric keycodes for the number keys, which is the expected behavior */
+ if ((keymap[scancode] & SDLK_SCANCODE_MASK) ||
+ /* scancode == SDL_SCANCODE_GRAVE || */ /* Uncomment this line to re-enable the behavior of not mapping the "`"(grave) key to the users actual keyboard layout */
+ (scancode >= SDL_SCANCODE_1 && scancode <= SDL_SCANCODE_0) ) {
+ continue;
+ }
+
+ vk = MapVirtualKey(i, MAPVK_VSC_TO_VK);
+ if ( vk ) {
+ int ch = (MapVirtualKey( vk, MAPVK_VK_TO_CHAR ) & 0x7FFF);
+ if ( ch ) {
+ if ( ch >= 'A' && ch <= 'Z' ) {
+ keymap[scancode] = SDLK_a + ( ch - 'A' );
+ } else {
+ keymap[scancode] = ch;
+ }
+ }
+ }
+ }
+
+ SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);
+}
+
+void
+WIN_QuitKeyboard(_THIS)
+{
+#ifndef SDL_DISABLE_WINDOWS_IME
+ IME_Quit((SDL_VideoData *)_this->driverdata);
+#endif
+}
+
+void
+WIN_ResetDeadKeys()
+{
+ /*
+ if a deadkey has been typed, but not the next character (which the deadkey might modify),
+ this tries to undo the effect pressing the deadkey.
+ see: http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
+ */
+ BYTE keyboardState[256];
+ WCHAR buffer[16];
+ int keycode, scancode, result, i;
+
+ GetKeyboardState(keyboardState);
+
+ keycode = VK_SPACE;
+ scancode = MapVirtualKey(keycode, MAPVK_VK_TO_VSC);
+ if (scancode == 0) {
+ /* the keyboard doesn't have this key */
+ return;
+ }
+
+ for (i = 0; i < 5; i++) {
+ result = ToUnicode(keycode, scancode, keyboardState, (LPWSTR)buffer, 16, 0);
+ if (result > 0) {
+ /* success */
+ return;
+ }
+ }
+}
+
+void
+WIN_StartTextInput(_THIS)
+{
+#ifndef SDL_DISABLE_WINDOWS_IME
+ SDL_Window *window;
+#endif
+
+ WIN_ResetDeadKeys();
+
+#ifndef SDL_DISABLE_WINDOWS_IME
+ window = SDL_GetKeyboardFocus();
+ if (window) {
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
+ SDL_GetWindowSize(window, &videodata->ime_winwidth, &videodata->ime_winheight);
+ IME_Init(videodata, hwnd);
+ IME_Enable(videodata, hwnd);
+ }
+#endif /* !SDL_DISABLE_WINDOWS_IME */
+}
+
+void
+WIN_StopTextInput(_THIS)
+{
+#ifndef SDL_DISABLE_WINDOWS_IME
+ SDL_Window *window;
+#endif
+
+ WIN_ResetDeadKeys();
+
+#ifndef SDL_DISABLE_WINDOWS_IME
+ window = SDL_GetKeyboardFocus();
+ if (window) {
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
+ IME_Init(videodata, hwnd);
+ IME_Disable(videodata, hwnd);
+ }
+#endif /* !SDL_DISABLE_WINDOWS_IME */
+}
+
+void
+WIN_SetTextInputRect(_THIS, SDL_Rect *rect)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
+ HIMC himc = 0;
+
+ if (!rect) {
+ SDL_InvalidParamError("rect");
+ return;
+ }
+
+ videodata->ime_rect = *rect;
+
+ himc = ImmGetContext(videodata->ime_hwnd_current);
+ if (himc)
+ {
+ COMPOSITIONFORM cf;
+ cf.ptCurrentPos.x = videodata->ime_rect.x;
+ cf.ptCurrentPos.y = videodata->ime_rect.y;
+ cf.dwStyle = CFS_FORCE_POSITION;
+ ImmSetCompositionWindow(himc, &cf);
+ ImmReleaseContext(videodata->ime_hwnd_current, himc);
+ }
+}
+
+#ifdef SDL_DISABLE_WINDOWS_IME
+
+
+SDL_bool
+IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
+{
+ return SDL_FALSE;
+}
+
+void IME_Present(SDL_VideoData *videodata)
+{
+}
+
+#else
+
+#ifdef SDL_msctf_h_
+#define USE_INIT_GUID
+#elif defined(__GNUC__)
+#define USE_INIT_GUID
+#endif
+#ifdef USE_INIT_GUID
+#undef DEFINE_GUID
+#define DEFINE_GUID(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) static const GUID n = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
+DEFINE_GUID(IID_ITfInputProcessorProfileActivationSink, 0x71C6E74E,0x0F28,0x11D8,0xA8,0x2A,0x00,0x06,0x5B,0x84,0x43,0x5C);
+DEFINE_GUID(IID_ITfUIElementSink, 0xEA1EA136,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
+DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD, 0x34745C63,0xB2F0,0x4784,0x8B,0x67,0x5E,0x12,0xC8,0x70,0x1A,0x31);
+DEFINE_GUID(IID_ITfSource, 0x4EA48A35,0x60AE,0x446F,0x8F,0xD6,0xE6,0xA8,0xD8,0x24,0x59,0xF7);
+DEFINE_GUID(IID_ITfUIElementMgr, 0xEA1EA135,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
+DEFINE_GUID(IID_ITfCandidateListUIElement, 0xEA1EA138,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
+DEFINE_GUID(IID_ITfReadingInformationUIElement, 0xEA1EA139,0x19DF,0x11D7,0xA6,0xD2,0x00,0x06,0x5B,0x84,0x43,0x5C);
+DEFINE_GUID(IID_ITfThreadMgr, 0xAA80E801,0x2021,0x11D2,0x93,0xE0,0x00,0x60,0xB0,0x67,0xB8,0x6E);
+DEFINE_GUID(CLSID_TF_ThreadMgr, 0x529A9E6B,0x6587,0x4F23,0xAB,0x9E,0x9C,0x7D,0x68,0x3E,0x3C,0x50);
+DEFINE_GUID(IID_ITfThreadMgrEx, 0x3E90ADE3,0x7594,0x4CB0,0xBB,0x58,0x69,0x62,0x8F,0x5F,0x45,0x8C);
+#endif
+
+#define LANG_CHT MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
+#define LANG_CHS MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
+
+#define MAKEIMEVERSION(major,minor) ((DWORD) (((BYTE)(major) << 24) | ((BYTE)(minor) << 16) ))
+#define IMEID_VER(id) ((id) & 0xffff0000)
+#define IMEID_LANG(id) ((id) & 0x0000ffff)
+
+#define CHT_HKL_DAYI ((HKL)(UINT_PTR)0xE0060404)
+#define CHT_HKL_NEW_PHONETIC ((HKL)(UINT_PTR)0xE0080404)
+#define CHT_HKL_NEW_CHANG_JIE ((HKL)(UINT_PTR)0xE0090404)
+#define CHT_HKL_NEW_QUICK ((HKL)(UINT_PTR)0xE00A0404)
+#define CHT_HKL_HK_CANTONESE ((HKL)(UINT_PTR)0xE00B0404)
+#define CHT_IMEFILENAME1 "TINTLGNT.IME"
+#define CHT_IMEFILENAME2 "CINTLGNT.IME"
+#define CHT_IMEFILENAME3 "MSTCIPHA.IME"
+#define IMEID_CHT_VER42 (LANG_CHT | MAKEIMEVERSION(4, 2))
+#define IMEID_CHT_VER43 (LANG_CHT | MAKEIMEVERSION(4, 3))
+#define IMEID_CHT_VER44 (LANG_CHT | MAKEIMEVERSION(4, 4))
+#define IMEID_CHT_VER50 (LANG_CHT | MAKEIMEVERSION(5, 0))
+#define IMEID_CHT_VER51 (LANG_CHT | MAKEIMEVERSION(5, 1))
+#define IMEID_CHT_VER52 (LANG_CHT | MAKEIMEVERSION(5, 2))
+#define IMEID_CHT_VER60 (LANG_CHT | MAKEIMEVERSION(6, 0))
+#define IMEID_CHT_VER_VISTA (LANG_CHT | MAKEIMEVERSION(7, 0))
+
+#define CHS_HKL ((HKL)(UINT_PTR)0xE00E0804)
+#define CHS_IMEFILENAME1 "PINTLGNT.IME"
+#define CHS_IMEFILENAME2 "MSSCIPYA.IME"
+#define IMEID_CHS_VER41 (LANG_CHS | MAKEIMEVERSION(4, 1))
+#define IMEID_CHS_VER42 (LANG_CHS | MAKEIMEVERSION(4, 2))
+#define IMEID_CHS_VER53 (LANG_CHS | MAKEIMEVERSION(5, 3))
+
+#define LANG() LOWORD((videodata->ime_hkl))
+#define PRIMLANG() ((WORD)PRIMARYLANGID(LANG()))
+#define SUBLANG() SUBLANGID(LANG())
+
+static void IME_UpdateInputLocale(SDL_VideoData *videodata);
+static void IME_ClearComposition(SDL_VideoData *videodata);
+static void IME_SetWindow(SDL_VideoData* videodata, HWND hwnd);
+static void IME_SetupAPI(SDL_VideoData *videodata);
+static DWORD IME_GetId(SDL_VideoData *videodata, UINT uIndex);
+static void IME_SendEditingEvent(SDL_VideoData *videodata);
+static void IME_DestroyTextures(SDL_VideoData *videodata);
+
+static SDL_bool UILess_SetupSinks(SDL_VideoData *videodata);
+static void UILess_ReleaseSinks(SDL_VideoData *videodata);
+static void UILess_EnableUIUpdates(SDL_VideoData *videodata);
+static void UILess_DisableUIUpdates(SDL_VideoData *videodata);
+
+static void
+IME_Init(SDL_VideoData *videodata, HWND hwnd)
+{
+ if (videodata->ime_initialized)
+ return;
+
+ videodata->ime_hwnd_main = hwnd;
+ if (SUCCEEDED(WIN_CoInitialize())) {
+ videodata->ime_com_initialized = SDL_TRUE;
+ CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (LPVOID *)&videodata->ime_threadmgr);
+ }
+ videodata->ime_initialized = SDL_TRUE;
+ videodata->ime_himm32 = SDL_LoadObject("imm32.dll");
+ if (!videodata->ime_himm32) {
+ videodata->ime_available = SDL_FALSE;
+ SDL_ClearError();
+ return;
+ }
+ videodata->ImmLockIMC = (LPINPUTCONTEXT2 (WINAPI *)(HIMC))SDL_LoadFunction(videodata->ime_himm32, "ImmLockIMC");
+ videodata->ImmUnlockIMC = (BOOL (WINAPI *)(HIMC))SDL_LoadFunction(videodata->ime_himm32, "ImmUnlockIMC");
+ videodata->ImmLockIMCC = (LPVOID (WINAPI *)(HIMCC))SDL_LoadFunction(videodata->ime_himm32, "ImmLockIMCC");
+ videodata->ImmUnlockIMCC = (BOOL (WINAPI *)(HIMCC))SDL_LoadFunction(videodata->ime_himm32, "ImmUnlockIMCC");
+
+ IME_SetWindow(videodata, hwnd);
+ videodata->ime_himc = ImmGetContext(hwnd);
+ ImmReleaseContext(hwnd, videodata->ime_himc);
+ if (!videodata->ime_himc) {
+ videodata->ime_available = SDL_FALSE;
+ IME_Disable(videodata, hwnd);
+ return;
+ }
+ videodata->ime_available = SDL_TRUE;
+ IME_UpdateInputLocale(videodata);
+ IME_SetupAPI(videodata);
+ videodata->ime_uiless = UILess_SetupSinks(videodata);
+ IME_UpdateInputLocale(videodata);
+ IME_Disable(videodata, hwnd);
+}
+
+static void
+IME_Enable(SDL_VideoData *videodata, HWND hwnd)
+{
+ if (!videodata->ime_initialized || !videodata->ime_hwnd_current)
+ return;
+
+ if (!videodata->ime_available) {
+ IME_Disable(videodata, hwnd);
+ return;
+ }
+ if (videodata->ime_hwnd_current == videodata->ime_hwnd_main)
+ ImmAssociateContext(videodata->ime_hwnd_current, videodata->ime_himc);
+
+ videodata->ime_enabled = SDL_TRUE;
+ IME_UpdateInputLocale(videodata);
+ UILess_EnableUIUpdates(videodata);
+}
+
+static void
+IME_Disable(SDL_VideoData *videodata, HWND hwnd)
+{
+ if (!videodata->ime_initialized || !videodata->ime_hwnd_current)
+ return;
+
+ IME_ClearComposition(videodata);
+ if (videodata->ime_hwnd_current == videodata->ime_hwnd_main)
+ ImmAssociateContext(videodata->ime_hwnd_current, (HIMC)0);
+
+ videodata->ime_enabled = SDL_FALSE;
+ UILess_DisableUIUpdates(videodata);
+}
+
+static void
+IME_Quit(SDL_VideoData *videodata)
+{
+ if (!videodata->ime_initialized)
+ return;
+
+ UILess_ReleaseSinks(videodata);
+ if (videodata->ime_hwnd_main)
+ ImmAssociateContext(videodata->ime_hwnd_main, videodata->ime_himc);
+
+ videodata->ime_hwnd_main = 0;
+ videodata->ime_himc = 0;
+ if (videodata->ime_himm32) {
+ SDL_UnloadObject(videodata->ime_himm32);
+ videodata->ime_himm32 = 0;
+ }
+ if (videodata->ime_threadmgr) {
+ videodata->ime_threadmgr->lpVtbl->Release(videodata->ime_threadmgr);
+ videodata->ime_threadmgr = 0;
+ }
+ if (videodata->ime_com_initialized) {
+ WIN_CoUninitialize();
+ videodata->ime_com_initialized = SDL_FALSE;
+ }
+ IME_DestroyTextures(videodata);
+ videodata->ime_initialized = SDL_FALSE;
+}
+
+static void
+IME_GetReadingString(SDL_VideoData *videodata, HWND hwnd)
+{
+ DWORD id = 0;
+ HIMC himc = 0;
+ WCHAR buffer[16];
+ WCHAR *s = buffer;
+ DWORD len = 0;
+ INT err = 0;
+ BOOL vertical = FALSE;
+ UINT maxuilen = 0;
+
+ if (videodata->ime_uiless)
+ return;
+
+ videodata->ime_readingstring[0] = 0;
+
+ id = IME_GetId(videodata, 0);
+ if (!id)
+ return;
+
+ himc = ImmGetContext(hwnd);
+ if (!himc)
+ return;
+
+ if (videodata->GetReadingString) {
+ len = videodata->GetReadingString(himc, 0, 0, &err, &vertical, &maxuilen);
+ if (len) {
+ if (len > SDL_arraysize(buffer))
+ len = SDL_arraysize(buffer);
+
+ len = videodata->GetReadingString(himc, len, s, &err, &vertical, &maxuilen);
+ }
+ SDL_wcslcpy(videodata->ime_readingstring, s, len);
+ }
+ else {
+ LPINPUTCONTEXT2 lpimc = videodata->ImmLockIMC(himc);
+ LPBYTE p = 0;
+ s = 0;
+ switch (id)
+ {
+ case IMEID_CHT_VER42:
+ case IMEID_CHT_VER43:
+ case IMEID_CHT_VER44:
+ p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 24);
+ if (!p)
+ break;
+
+ len = *(DWORD *)(p + 7*4 + 32*4);
+ s = (WCHAR *)(p + 56);
+ break;
+ case IMEID_CHT_VER51:
+ case IMEID_CHT_VER52:
+ case IMEID_CHS_VER53:
+ p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 4);
+ if (!p)
+ break;
+
+ p = *(LPBYTE *)((LPBYTE)p + 1*4 + 5*4);
+ if (!p)
+ break;
+
+ len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
+ s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4);
+ break;
+ case IMEID_CHS_VER41:
+ {
+ int offset = (IME_GetId(videodata, 1) >= 0x00000002) ? 8 : 7;
+ p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + offset * 4);
+ if (!p)
+ break;
+
+ len = *(DWORD *)(p + 7*4 + 16*2*4);
+ s = (WCHAR *)(p + 6*4 + 16*2*1);
+ }
+ break;
+ case IMEID_CHS_VER42:
+ p = *(LPBYTE *)((LPBYTE)videodata->ImmLockIMCC(lpimc->hPrivate) + 1*4 + 1*4 + 6*4);
+ if (!p)
+ break;
+
+ len = *(DWORD *)(p + 1*4 + (16*2+2*4) + 5*4 + 16*2);
+ s = (WCHAR *)(p + 1*4 + (16*2+2*4) + 5*4);
+ break;
+ }
+ if (s) {
+ size_t size = SDL_min((size_t)(len + 1), SDL_arraysize(videodata->ime_readingstring));
+ SDL_wcslcpy(videodata->ime_readingstring, s, size);
+ }
+
+ videodata->ImmUnlockIMCC(lpimc->hPrivate);
+ videodata->ImmUnlockIMC(himc);
+ }
+ ImmReleaseContext(hwnd, himc);
+ IME_SendEditingEvent(videodata);
+}
+
+static void
+IME_InputLangChanged(SDL_VideoData *videodata)
+{
+ UINT lang = PRIMLANG();
+ IME_UpdateInputLocale(videodata);
+ if (!videodata->ime_uiless)
+ videodata->ime_candlistindexbase = (videodata->ime_hkl == CHT_HKL_DAYI) ? 0 : 1;
+
+ IME_SetupAPI(videodata);
+ if (lang != PRIMLANG()) {
+ IME_ClearComposition(videodata);
+ }
+}
+
+static DWORD
+IME_GetId(SDL_VideoData *videodata, UINT uIndex)
+{
+ static HKL hklprev = 0;
+ static DWORD dwRet[2] = {0};
+ DWORD dwVerSize = 0;
+ DWORD dwVerHandle = 0;
+ LPVOID lpVerBuffer = 0;
+ LPVOID lpVerData = 0;
+ UINT cbVerData = 0;
+ char szTemp[256];
+ HKL hkl = 0;
+ DWORD dwLang = 0;
+ if (uIndex >= sizeof(dwRet) / sizeof(dwRet[0]))
+ return 0;
+
+ hkl = videodata->ime_hkl;
+ if (hklprev == hkl)
+ return dwRet[uIndex];
+
+ hklprev = hkl;
+ dwLang = ((DWORD_PTR)hkl & 0xffff);
+ if (videodata->ime_uiless && LANG() == LANG_CHT) {
+ dwRet[0] = IMEID_CHT_VER_VISTA;
+ dwRet[1] = 0;
+ return dwRet[0];
+ }
+ if (hkl != CHT_HKL_NEW_PHONETIC
+ && hkl != CHT_HKL_NEW_CHANG_JIE
+ && hkl != CHT_HKL_NEW_QUICK
+ && hkl != CHT_HKL_HK_CANTONESE
+ && hkl != CHS_HKL) {
+ dwRet[0] = dwRet[1] = 0;
+ return dwRet[uIndex];
+ }
+ if (ImmGetIMEFileNameA(hkl, szTemp, sizeof(szTemp) - 1) <= 0) {
+ dwRet[0] = dwRet[1] = 0;
+ return dwRet[uIndex];
+ }
+ if (!videodata->GetReadingString) {
+ #define LCID_INVARIANT MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)
+ if (CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME1, -1) != 2
+ && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME2, -1) != 2
+ && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHT_IMEFILENAME3, -1) != 2
+ && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME1, -1) != 2
+ && CompareStringA(LCID_INVARIANT, NORM_IGNORECASE, szTemp, -1, CHS_IMEFILENAME2, -1) != 2) {
+ dwRet[0] = dwRet[1] = 0;
+ return dwRet[uIndex];
+ }
+ #undef LCID_INVARIANT
+ dwVerSize = GetFileVersionInfoSizeA(szTemp, &dwVerHandle);
+ if (dwVerSize) {
+ lpVerBuffer = SDL_malloc(dwVerSize);
+ if (lpVerBuffer) {
+ if (GetFileVersionInfoA(szTemp, dwVerHandle, dwVerSize, lpVerBuffer)) {
+ if (VerQueryValueA(lpVerBuffer, "\\", &lpVerData, &cbVerData)) {
+ #define pVerFixedInfo ((VS_FIXEDFILEINFO FAR*)lpVerData)
+ DWORD dwVer = pVerFixedInfo->dwFileVersionMS;
+ dwVer = (dwVer & 0x00ff0000) << 8 | (dwVer & 0x000000ff) << 16;
+ if ((videodata->GetReadingString) ||
+ ((dwLang == LANG_CHT) && (
+ dwVer == MAKEIMEVERSION(4, 2) ||
+ dwVer == MAKEIMEVERSION(4, 3) ||
+ dwVer == MAKEIMEVERSION(4, 4) ||
+ dwVer == MAKEIMEVERSION(5, 0) ||
+ dwVer == MAKEIMEVERSION(5, 1) ||
+ dwVer == MAKEIMEVERSION(5, 2) ||
+ dwVer == MAKEIMEVERSION(6, 0)))
+ ||
+ ((dwLang == LANG_CHS) && (
+ dwVer == MAKEIMEVERSION(4, 1) ||
+ dwVer == MAKEIMEVERSION(4, 2) ||
+ dwVer == MAKEIMEVERSION(5, 3)))) {
+ dwRet[0] = dwVer | dwLang;
+ dwRet[1] = pVerFixedInfo->dwFileVersionLS;
+ SDL_free(lpVerBuffer);
+ return dwRet[0];
+ }
+ #undef pVerFixedInfo
+ }
+ }
+ }
+ SDL_free(lpVerBuffer);
+ }
+ }
+ dwRet[0] = dwRet[1] = 0;
+ return dwRet[uIndex];
+}
+
+static void
+IME_SetupAPI(SDL_VideoData *videodata)
+{
+ char ime_file[MAX_PATH + 1];
+ void* hime = 0;
+ HKL hkl = 0;
+ videodata->GetReadingString = 0;
+ videodata->ShowReadingWindow = 0;
+ if (videodata->ime_uiless)
+ return;
+
+ hkl = videodata->ime_hkl;
+ if (ImmGetIMEFileNameA(hkl, ime_file, sizeof(ime_file) - 1) <= 0)
+ return;
+
+ hime = SDL_LoadObject(ime_file);
+ if (!hime)
+ return;
+
+ videodata->GetReadingString = (UINT (WINAPI *)(HIMC, UINT, LPWSTR, PINT, BOOL*, PUINT))
+ SDL_LoadFunction(hime, "GetReadingString");
+ videodata->ShowReadingWindow = (BOOL (WINAPI *)(HIMC, BOOL))
+ SDL_LoadFunction(hime, "ShowReadingWindow");
+
+ if (videodata->ShowReadingWindow) {
+ HIMC himc = ImmGetContext(videodata->ime_hwnd_current);
+ if (himc) {
+ videodata->ShowReadingWindow(himc, FALSE);
+ ImmReleaseContext(videodata->ime_hwnd_current, himc);
+ }
+ }
+}
+
+static void
+IME_SetWindow(SDL_VideoData* videodata, HWND hwnd)
+{
+ videodata->ime_hwnd_current = hwnd;
+ if (videodata->ime_threadmgr) {
+ struct ITfDocumentMgr *document_mgr = 0;
+ if (SUCCEEDED(videodata->ime_threadmgr->lpVtbl->AssociateFocus(videodata->ime_threadmgr, hwnd, NULL, &document_mgr))) {
+ if (document_mgr)
+ document_mgr->lpVtbl->Release(document_mgr);
+ }
+ }
+}
+
+static void
+IME_UpdateInputLocale(SDL_VideoData *videodata)
+{
+ static HKL hklprev = 0;
+ videodata->ime_hkl = GetKeyboardLayout(0);
+ if (hklprev == videodata->ime_hkl)
+ return;
+
+ hklprev = videodata->ime_hkl;
+ switch (PRIMLANG()) {
+ case LANG_CHINESE:
+ videodata->ime_candvertical = SDL_TRUE;
+ if (SUBLANG() == SUBLANG_CHINESE_SIMPLIFIED)
+ videodata->ime_candvertical = SDL_FALSE;
+
+ break;
+ case LANG_JAPANESE:
+ videodata->ime_candvertical = SDL_TRUE;
+ break;
+ case LANG_KOREAN:
+ videodata->ime_candvertical = SDL_FALSE;
+ break;
+ }
+}
+
+static void
+IME_ClearComposition(SDL_VideoData *videodata)
+{
+ HIMC himc = 0;
+ if (!videodata->ime_initialized)
+ return;
+
+ himc = ImmGetContext(videodata->ime_hwnd_current);
+ if (!himc)
+ return;
+
+ ImmNotifyIME(himc, NI_COMPOSITIONSTR, CPS_CANCEL, 0);
+ if (videodata->ime_uiless)
+ ImmSetCompositionString(himc, SCS_SETSTR, TEXT(""), sizeof(TCHAR), TEXT(""), sizeof(TCHAR));
+
+ ImmNotifyIME(himc, NI_CLOSECANDIDATE, 0, 0);
+ ImmReleaseContext(videodata->ime_hwnd_current, himc);
+ SDL_SendEditingText("", 0, 0);
+}
+
+static void
+IME_GetCompositionString(SDL_VideoData *videodata, HIMC himc, DWORD string)
+{
+ LONG length = ImmGetCompositionStringW(himc, string, videodata->ime_composition, sizeof(videodata->ime_composition) - sizeof(videodata->ime_composition[0]));
+ if (length < 0)
+ length = 0;
+
+ length /= sizeof(videodata->ime_composition[0]);
+ videodata->ime_cursor = LOWORD(ImmGetCompositionStringW(himc, GCS_CURSORPOS, 0, 0));
+ if (videodata->ime_cursor < SDL_arraysize(videodata->ime_composition) && videodata->ime_composition[videodata->ime_cursor] == 0x3000) {
+ int i;
+ for (i = videodata->ime_cursor + 1; i < length; ++i)
+ videodata->ime_composition[i - 1] = videodata->ime_composition[i];
+
+ --length;
+ }
+ videodata->ime_composition[length] = 0;
+}
+
+static void
+IME_SendInputEvent(SDL_VideoData *videodata)
+{
+ char *s = 0;
+ s = WIN_StringToUTF8(videodata->ime_composition);
+ SDL_SendKeyboardText(s);
+ SDL_free(s);
+
+ videodata->ime_composition[0] = 0;
+ videodata->ime_readingstring[0] = 0;
+ videodata->ime_cursor = 0;
+}
+
+static void
+IME_SendEditingEvent(SDL_VideoData *videodata)
+{
+ char *s = 0;
+ WCHAR buffer[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
+ const size_t size = SDL_arraysize(buffer);
+ buffer[0] = 0;
+ if (videodata->ime_readingstring[0]) {
+ size_t len = SDL_min(SDL_wcslen(videodata->ime_composition), (size_t)videodata->ime_cursor);
+ SDL_wcslcpy(buffer, videodata->ime_composition, len + 1);
+ SDL_wcslcat(buffer, videodata->ime_readingstring, size);
+ SDL_wcslcat(buffer, &videodata->ime_composition[len], size);
+ }
+ else {
+ SDL_wcslcpy(buffer, videodata->ime_composition, size);
+ }
+ s = WIN_StringToUTF8(buffer);
+ SDL_SendEditingText(s, videodata->ime_cursor + (int)SDL_wcslen(videodata->ime_readingstring), 0);
+ SDL_free(s);
+}
+
+static void
+IME_AddCandidate(SDL_VideoData *videodata, UINT i, LPCWSTR candidate)
+{
+ LPWSTR dst = videodata->ime_candidates[i];
+ *dst++ = (WCHAR)(TEXT('0') + ((i + videodata->ime_candlistindexbase) % 10));
+ if (videodata->ime_candvertical)
+ *dst++ = TEXT(' ');
+
+ while (*candidate && (SDL_arraysize(videodata->ime_candidates[i]) > (dst - videodata->ime_candidates[i])))
+ *dst++ = *candidate++;
+
+ *dst = (WCHAR)'\0';
+}
+
+static void
+IME_GetCandidateList(HIMC himc, SDL_VideoData *videodata)
+{
+ LPCANDIDATELIST cand_list = 0;
+ DWORD size = ImmGetCandidateListW(himc, 0, 0, 0);
+ if (size) {
+ cand_list = (LPCANDIDATELIST)SDL_malloc(size);
+ if (cand_list) {
+ size = ImmGetCandidateListW(himc, 0, cand_list, size);
+ if (size) {
+ UINT i, j;
+ UINT page_start = 0;
+ videodata->ime_candsel = cand_list->dwSelection;
+ videodata->ime_candcount = cand_list->dwCount;
+
+ if (LANG() == LANG_CHS && IME_GetId(videodata, 0)) {
+ const UINT maxcandchar = 18;
+ size_t cchars = 0;
+
+ for (i = 0; i < videodata->ime_candcount; ++i) {
+ size_t len = SDL_wcslen((LPWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[i])) + 1;
+ if (len + cchars > maxcandchar) {
+ if (i > cand_list->dwSelection)
+ break;
+
+ page_start = i;
+ cchars = len;
+ }
+ else {
+ cchars += len;
+ }
+ }
+ videodata->ime_candpgsize = i - page_start;
+ } else {
+ videodata->ime_candpgsize = SDL_min(cand_list->dwPageSize, MAX_CANDLIST);
+ if (videodata->ime_candpgsize > 0) {
+ page_start = (cand_list->dwSelection / videodata->ime_candpgsize) * videodata->ime_candpgsize;
+ } else {
+ page_start = 0;
+ }
+ }
+ SDL_memset(&videodata->ime_candidates, 0, sizeof(videodata->ime_candidates));
+ for (i = page_start, j = 0; (DWORD)i < cand_list->dwCount && j < (int)videodata->ime_candpgsize; i++, j++) {
+ LPCWSTR candidate = (LPCWSTR)((DWORD_PTR)cand_list + cand_list->dwOffset[i]);
+ IME_AddCandidate(videodata, j, candidate);
+ }
+ if (PRIMLANG() == LANG_KOREAN || (PRIMLANG() == LANG_CHT && !IME_GetId(videodata, 0)))
+ videodata->ime_candsel = -1;
+
+ }
+ SDL_free(cand_list);
+ }
+ }
+}
+
+static void
+IME_ShowCandidateList(SDL_VideoData *videodata)
+{
+ videodata->ime_dirty = SDL_TRUE;
+ videodata->ime_candlist = SDL_TRUE;
+ IME_DestroyTextures(videodata);
+ IME_SendEditingEvent(videodata);
+}
+
+static void
+IME_HideCandidateList(SDL_VideoData *videodata)
+{
+ videodata->ime_dirty = SDL_FALSE;
+ videodata->ime_candlist = SDL_FALSE;
+ IME_DestroyTextures(videodata);
+ IME_SendEditingEvent(videodata);
+}
+
+SDL_bool
+IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, SDL_VideoData *videodata)
+{
+ SDL_bool trap = SDL_FALSE;
+ HIMC himc = 0;
+ if (!videodata->ime_initialized || !videodata->ime_available || !videodata->ime_enabled)
+ return SDL_FALSE;
+
+ switch (msg) {
+ case WM_INPUTLANGCHANGE:
+ IME_InputLangChanged(videodata);
+ break;
+ case WM_IME_SETCONTEXT:
+ *lParam = 0;
+ break;
+ case WM_IME_STARTCOMPOSITION:
+ trap = SDL_TRUE;
+ break;
+ case WM_IME_COMPOSITION:
+ trap = SDL_TRUE;
+ himc = ImmGetContext(hwnd);
+ if (*lParam & GCS_RESULTSTR) {
+ IME_GetCompositionString(videodata, himc, GCS_RESULTSTR);
+ IME_SendInputEvent(videodata);
+ }
+ if (*lParam & GCS_COMPSTR) {
+ if (!videodata->ime_uiless)
+ videodata->ime_readingstring[0] = 0;
+
+ IME_GetCompositionString(videodata, himc, GCS_COMPSTR);
+ IME_SendEditingEvent(videodata);
+ }
+ ImmReleaseContext(hwnd, himc);
+ break;
+ case WM_IME_ENDCOMPOSITION:
+ videodata->ime_composition[0] = 0;
+ videodata->ime_readingstring[0] = 0;
+ videodata->ime_cursor = 0;
+ SDL_SendEditingText("", 0, 0);
+ break;
+ case WM_IME_NOTIFY:
+ switch (wParam) {
+ case IMN_SETCONVERSIONMODE:
+ case IMN_SETOPENSTATUS:
+ IME_UpdateInputLocale(videodata);
+ break;
+ case IMN_OPENCANDIDATE:
+ case IMN_CHANGECANDIDATE:
+ if (videodata->ime_uiless)
+ break;
+
+ trap = SDL_TRUE;
+ IME_ShowCandidateList(videodata);
+ himc = ImmGetContext(hwnd);
+ if (!himc)
+ break;
+
+ IME_GetCandidateList(himc, videodata);
+ ImmReleaseContext(hwnd, himc);
+ break;
+ case IMN_CLOSECANDIDATE:
+ trap = SDL_TRUE;
+ IME_HideCandidateList(videodata);
+ break;
+ case IMN_PRIVATE:
+ {
+ DWORD dwId = IME_GetId(videodata, 0);
+ IME_GetReadingString(videodata, hwnd);
+ switch (dwId)
+ {
+ case IMEID_CHT_VER42:
+ case IMEID_CHT_VER43:
+ case IMEID_CHT_VER44:
+ case IMEID_CHS_VER41:
+ case IMEID_CHS_VER42:
+ if (*lParam == 1 || *lParam == 2)
+ trap = SDL_TRUE;
+
+ break;
+ case IMEID_CHT_VER50:
+ case IMEID_CHT_VER51:
+ case IMEID_CHT_VER52:
+ case IMEID_CHT_VER60:
+ case IMEID_CHS_VER53:
+ if (*lParam == 16
+ || *lParam == 17
+ || *lParam == 26
+ || *lParam == 27
+ || *lParam == 28)
+ trap = SDL_TRUE;
+ break;
+ }
+ }
+ break;
+ default:
+ trap = SDL_TRUE;
+ break;
+ }
+ break;
+ }
+ return trap;
+}
+
+static void
+IME_CloseCandidateList(SDL_VideoData *videodata)
+{
+ IME_HideCandidateList(videodata);
+ videodata->ime_candcount = 0;
+ SDL_memset(videodata->ime_candidates, 0, sizeof(videodata->ime_candidates));
+}
+
+static void
+UILess_GetCandidateList(SDL_VideoData *videodata, ITfCandidateListUIElement *pcandlist)
+{
+ UINT selection = 0;
+ UINT count = 0;
+ UINT page = 0;
+ UINT pgcount = 0;
+ DWORD pgstart = 0;
+ DWORD pgsize = 0;
+ UINT i, j;
+ pcandlist->lpVtbl->GetSelection(pcandlist, &selection);
+ pcandlist->lpVtbl->GetCount(pcandlist, &count);
+ pcandlist->lpVtbl->GetCurrentPage(pcandlist, &page);
+
+ videodata->ime_candsel = selection;
+ videodata->ime_candcount = count;
+ IME_ShowCandidateList(videodata);
+
+ pcandlist->lpVtbl->GetPageIndex(pcandlist, 0, 0, &pgcount);
+ if (pgcount > 0) {
+ UINT *idxlist = SDL_malloc(sizeof(UINT) * pgcount);
+ if (idxlist) {
+ pcandlist->lpVtbl->GetPageIndex(pcandlist, idxlist, pgcount, &pgcount);
+ pgstart = idxlist[page];
+ if (page < pgcount - 1)
+ pgsize = SDL_min(count, idxlist[page + 1]) - pgstart;
+ else
+ pgsize = count - pgstart;
+
+ SDL_free(idxlist);
+ }
+ }
+ videodata->ime_candpgsize = SDL_min(pgsize, MAX_CANDLIST);
+ videodata->ime_candsel = videodata->ime_candsel - pgstart;
+
+ SDL_memset(videodata->ime_candidates, 0, sizeof(videodata->ime_candidates));
+ for (i = pgstart, j = 0; (DWORD)i < count && j < videodata->ime_candpgsize; i++, j++) {
+ BSTR bstr;
+ if (SUCCEEDED(pcandlist->lpVtbl->GetString(pcandlist, i, &bstr))) {
+ if (bstr) {
+ IME_AddCandidate(videodata, j, bstr);
+ SysFreeString(bstr);
+ }
+ }
+ }
+ if (PRIMLANG() == LANG_KOREAN)
+ videodata->ime_candsel = -1;
+}
+
+STDMETHODIMP_(ULONG) TSFSink_AddRef(TSFSink *sink)
+{
+ return ++sink->refcount;
+}
+
+STDMETHODIMP_(ULONG) TSFSink_Release(TSFSink *sink)
+{
+ --sink->refcount;
+ if (sink->refcount == 0) {
+ SDL_free(sink);
+ return 0;
+ }
+ return sink->refcount;
+}
+
+STDMETHODIMP UIElementSink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = 0;
+ if (WIN_IsEqualIID(riid, &IID_IUnknown))
+ *ppv = (IUnknown *)sink;
+ else if (WIN_IsEqualIID(riid, &IID_ITfUIElementSink))
+ *ppv = (ITfUIElementSink *)sink;
+
+ if (*ppv) {
+ TSFSink_AddRef(sink);
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+ITfUIElement *UILess_GetUIElement(SDL_VideoData *videodata, DWORD dwUIElementId)
+{
+ ITfUIElementMgr *puiem = 0;
+ ITfUIElement *pelem = 0;
+ ITfThreadMgrEx *threadmgrex = videodata->ime_threadmgrex;
+
+ if (SUCCEEDED(threadmgrex->lpVtbl->QueryInterface(threadmgrex, &IID_ITfUIElementMgr, (LPVOID *)&puiem))) {
+ puiem->lpVtbl->GetUIElement(puiem, dwUIElementId, &pelem);
+ puiem->lpVtbl->Release(puiem);
+ }
+ return pelem;
+}
+
+STDMETHODIMP UIElementSink_BeginUIElement(TSFSink *sink, DWORD dwUIElementId, BOOL *pbShow)
+{
+ ITfUIElement *element = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
+ ITfReadingInformationUIElement *preading = 0;
+ ITfCandidateListUIElement *pcandlist = 0;
+ SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
+ if (!element)
+ return E_INVALIDARG;
+
+ *pbShow = FALSE;
+ if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
+ BSTR bstr;
+ if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
+ SysFreeString(bstr);
+ }
+ preading->lpVtbl->Release(preading);
+ }
+ else if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
+ videodata->ime_candref++;
+ UILess_GetCandidateList(videodata, pcandlist);
+ pcandlist->lpVtbl->Release(pcandlist);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP UIElementSink_UpdateUIElement(TSFSink *sink, DWORD dwUIElementId)
+{
+ ITfUIElement *element = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
+ ITfReadingInformationUIElement *preading = 0;
+ ITfCandidateListUIElement *pcandlist = 0;
+ SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
+ if (!element)
+ return E_INVALIDARG;
+
+ if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
+ BSTR bstr;
+ if (SUCCEEDED(preading->lpVtbl->GetString(preading, &bstr)) && bstr) {
+ WCHAR *s = (WCHAR *)bstr;
+ SDL_wcslcpy(videodata->ime_readingstring, s, SDL_arraysize(videodata->ime_readingstring));
+ IME_SendEditingEvent(videodata);
+ SysFreeString(bstr);
+ }
+ preading->lpVtbl->Release(preading);
+ }
+ else if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
+ UILess_GetCandidateList(videodata, pcandlist);
+ pcandlist->lpVtbl->Release(pcandlist);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP UIElementSink_EndUIElement(TSFSink *sink, DWORD dwUIElementId)
+{
+ ITfUIElement *element = UILess_GetUIElement((SDL_VideoData *)sink->data, dwUIElementId);
+ ITfReadingInformationUIElement *preading = 0;
+ ITfCandidateListUIElement *pcandlist = 0;
+ SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
+ if (!element)
+ return E_INVALIDARG;
+
+ if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfReadingInformationUIElement, (LPVOID *)&preading))) {
+ videodata->ime_readingstring[0] = 0;
+ IME_SendEditingEvent(videodata);
+ preading->lpVtbl->Release(preading);
+ }
+ if (SUCCEEDED(element->lpVtbl->QueryInterface(element, &IID_ITfCandidateListUIElement, (LPVOID *)&pcandlist))) {
+ videodata->ime_candref--;
+ if (videodata->ime_candref == 0)
+ IME_CloseCandidateList(videodata);
+
+ pcandlist->lpVtbl->Release(pcandlist);
+ }
+ return S_OK;
+}
+
+STDMETHODIMP IPPASink_QueryInterface(TSFSink *sink, REFIID riid, PVOID *ppv)
+{
+ if (!ppv)
+ return E_INVALIDARG;
+
+ *ppv = 0;
+ if (WIN_IsEqualIID(riid, &IID_IUnknown))
+ *ppv = (IUnknown *)sink;
+ else if (WIN_IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink))
+ *ppv = (ITfInputProcessorProfileActivationSink *)sink;
+
+ if (*ppv) {
+ TSFSink_AddRef(sink);
+ return S_OK;
+ }
+ return E_NOINTERFACE;
+}
+
+STDMETHODIMP IPPASink_OnActivated(TSFSink *sink, DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, REFGUID guidProfile, HKL hkl, DWORD dwFlags)
+{
+ static const GUID TF_PROFILE_DAYI = { 0x037B2C25, 0x480C, 0x4D7F, { 0xB0, 0x27, 0xD6, 0xCA, 0x6B, 0x69, 0x78, 0x8A } };
+ SDL_VideoData *videodata = (SDL_VideoData *)sink->data;
+ videodata->ime_candlistindexbase = WIN_IsEqualGUID(&TF_PROFILE_DAYI, guidProfile) ? 0 : 1;
+ if (WIN_IsEqualIID(catid, &GUID_TFCAT_TIP_KEYBOARD) && (dwFlags & TF_IPSINK_FLAG_ACTIVE))
+ IME_InputLangChanged((SDL_VideoData *)sink->data);
+
+ IME_HideCandidateList(videodata);
+ return S_OK;
+}
+
+static void *vtUIElementSink[] = {
+ (void *)(UIElementSink_QueryInterface),
+ (void *)(TSFSink_AddRef),
+ (void *)(TSFSink_Release),
+ (void *)(UIElementSink_BeginUIElement),
+ (void *)(UIElementSink_UpdateUIElement),
+ (void *)(UIElementSink_EndUIElement)
+};
+
+static void *vtIPPASink[] = {
+ (void *)(IPPASink_QueryInterface),
+ (void *)(TSFSink_AddRef),
+ (void *)(TSFSink_Release),
+ (void *)(IPPASink_OnActivated)
+};
+
+static void
+UILess_EnableUIUpdates(SDL_VideoData *videodata)
+{
+ ITfSource *source = 0;
+ if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie != TF_INVALID_COOKIE)
+ return;
+
+ if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
+ source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie);
+ source->lpVtbl->Release(source);
+ }
+}
+
+static void
+UILess_DisableUIUpdates(SDL_VideoData *videodata)
+{
+ ITfSource *source = 0;
+ if (!videodata->ime_threadmgrex || videodata->ime_uielemsinkcookie == TF_INVALID_COOKIE)
+ return;
+
+ if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
+ source->lpVtbl->UnadviseSink(source, videodata->ime_uielemsinkcookie);
+ videodata->ime_uielemsinkcookie = TF_INVALID_COOKIE;
+ source->lpVtbl->Release(source);
+ }
+}
+
+static SDL_bool
+UILess_SetupSinks(SDL_VideoData *videodata)
+{
+ TfClientId clientid = 0;
+ SDL_bool result = SDL_FALSE;
+ ITfSource *source = 0;
+ if (FAILED(CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, (LPVOID *)&videodata->ime_threadmgrex)))
+ return SDL_FALSE;
+
+ if (FAILED(videodata->ime_threadmgrex->lpVtbl->ActivateEx(videodata->ime_threadmgrex, &clientid, TF_TMAE_UIELEMENTENABLEDONLY)))
+ return SDL_FALSE;
+
+ videodata->ime_uielemsink = SDL_malloc(sizeof(TSFSink));
+ videodata->ime_ippasink = SDL_malloc(sizeof(TSFSink));
+
+ videodata->ime_uielemsink->lpVtbl = vtUIElementSink;
+ videodata->ime_uielemsink->refcount = 1;
+ videodata->ime_uielemsink->data = videodata;
+
+ videodata->ime_ippasink->lpVtbl = vtIPPASink;
+ videodata->ime_ippasink->refcount = 1;
+ videodata->ime_ippasink->data = videodata;
+
+ if (SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
+ if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie))) {
+ if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfInputProcessorProfileActivationSink, (IUnknown *)videodata->ime_ippasink, &videodata->ime_alpnsinkcookie))) {
+ result = SDL_TRUE;
+ }
+ }
+ source->lpVtbl->Release(source);
+ }
+ return result;
+}
+
+#define SAFE_RELEASE(p) \
+{ \
+ if (p) { \
+ (p)->lpVtbl->Release((p)); \
+ (p) = 0; \
+ } \
+}
+
+static void
+UILess_ReleaseSinks(SDL_VideoData *videodata)
+{
+ ITfSource *source = 0;
+ if (videodata->ime_threadmgrex && SUCCEEDED(videodata->ime_threadmgrex->lpVtbl->QueryInterface(videodata->ime_threadmgrex, &IID_ITfSource, (LPVOID *)&source))) {
+ source->lpVtbl->UnadviseSink(source, videodata->ime_uielemsinkcookie);
+ source->lpVtbl->UnadviseSink(source, videodata->ime_alpnsinkcookie);
+ SAFE_RELEASE(source);
+ videodata->ime_threadmgrex->lpVtbl->Deactivate(videodata->ime_threadmgrex);
+ SAFE_RELEASE(videodata->ime_threadmgrex);
+ TSFSink_Release(videodata->ime_uielemsink);
+ videodata->ime_uielemsink = 0;
+ TSFSink_Release(videodata->ime_ippasink);
+ videodata->ime_ippasink = 0;
+ }
+}
+
+static void *
+StartDrawToBitmap(HDC hdc, HBITMAP *hhbm, int width, int height)
+{
+ BITMAPINFO info;
+ BITMAPINFOHEADER *infoHeader = &info.bmiHeader;
+ BYTE *bits = NULL;
+ if (hhbm) {
+ SDL_zero(info);
+ infoHeader->biSize = sizeof(BITMAPINFOHEADER);
+ infoHeader->biWidth = width;
+ infoHeader->biHeight = -1 * SDL_abs(height);
+ infoHeader->biPlanes = 1;
+ infoHeader->biBitCount = 32;
+ infoHeader->biCompression = BI_RGB;
+ *hhbm = CreateDIBSection(hdc, &info, DIB_RGB_COLORS, (void **)&bits, 0, 0);
+ if (*hhbm)
+ SelectObject(hdc, *hhbm);
+ }
+ return bits;
+}
+
+static void
+StopDrawToBitmap(HDC hdc, HBITMAP *hhbm)
+{
+ if (hhbm && *hhbm) {
+ DeleteObject(*hhbm);
+ *hhbm = NULL;
+ }
+}
+
+/* This draws only within the specified area and fills the entire region. */
+static void
+DrawRect(HDC hdc, int left, int top, int right, int bottom, int pensize)
+{
+ /* The case of no pen (PenSize = 0) is automatically taken care of. */
+ const int penadjust = (int)SDL_floor(pensize / 2.0f - 0.5f);
+ left += pensize / 2;
+ top += pensize / 2;
+ right -= penadjust;
+ bottom -= penadjust;
+ Rectangle(hdc, left, top, right, bottom);
+}
+
+static void
+IME_DestroyTextures(SDL_VideoData *videodata)
+{
+}
+
+#define SDL_swap(a,b) { \
+ int c = (a); \
+ (a) = (b); \
+ (b) = c; \
+ }
+
+static void
+IME_PositionCandidateList(SDL_VideoData *videodata, SIZE size)
+{
+ int left, top, right, bottom;
+ SDL_bool ok = SDL_FALSE;
+ int winw = videodata->ime_winwidth;
+ int winh = videodata->ime_winheight;
+
+ /* Bottom */
+ left = videodata->ime_rect.x;
+ top = videodata->ime_rect.y + videodata->ime_rect.h;
+ right = left + size.cx;
+ bottom = top + size.cy;
+ if (right >= winw) {
+ left -= right - winw;
+ right = winw;
+ }
+ if (bottom < winh)
+ ok = SDL_TRUE;
+
+ /* Top */
+ if (!ok) {
+ left = videodata->ime_rect.x;
+ top = videodata->ime_rect.y - size.cy;
+ right = left + size.cx;
+ bottom = videodata->ime_rect.y;
+ if (right >= winw) {
+ left -= right - winw;
+ right = winw;
+ }
+ if (top >= 0)
+ ok = SDL_TRUE;
+ }
+
+ /* Right */
+ if (!ok) {
+ left = videodata->ime_rect.x + size.cx;
+ top = 0;
+ right = left + size.cx;
+ bottom = size.cy;
+ if (right < winw)
+ ok = SDL_TRUE;
+ }
+
+ /* Left */
+ if (!ok) {
+ left = videodata->ime_rect.x - size.cx;
+ top = 0;
+ right = videodata->ime_rect.x;
+ bottom = size.cy;
+ if (right >= 0)
+ ok = SDL_TRUE;
+ }
+
+ /* Window too small, show at (0,0) */
+ if (!ok) {
+ left = 0;
+ top = 0;
+ right = size.cx;
+ bottom = size.cy;
+ }
+
+ videodata->ime_candlistrect.x = left;
+ videodata->ime_candlistrect.y = top;
+ videodata->ime_candlistrect.w = right - left;
+ videodata->ime_candlistrect.h = bottom - top;
+}
+
+static void
+IME_RenderCandidateList(SDL_VideoData *videodata, HDC hdc)
+{
+ int i, j;
+ SIZE size = {0};
+ SIZE candsizes[MAX_CANDLIST];
+ SIZE maxcandsize = {0};
+ HBITMAP hbm = NULL;
+ const int candcount = SDL_min(SDL_min(MAX_CANDLIST, videodata->ime_candcount), videodata->ime_candpgsize);
+ SDL_bool vertical = videodata->ime_candvertical;
+
+ const int listborder = 1;
+ const int listpadding = 0;
+ const int listbordercolor = RGB(0xB4, 0xC7, 0xAA);
+ const int listfillcolor = RGB(255, 255, 255);
+
+ const int candborder = 1;
+ const int candpadding = 0;
+ const int candmargin = 1;
+ const COLORREF candbordercolor = RGB(255, 255, 255);
+ const COLORREF candfillcolor = RGB(255, 255, 255);
+ const COLORREF candtextcolor = RGB(0, 0, 0);
+ const COLORREF selbordercolor = RGB(0x84, 0xAC, 0xDD);
+ const COLORREF selfillcolor = RGB(0xD2, 0xE6, 0xFF);
+ const COLORREF seltextcolor = RGB(0, 0, 0);
+ const int horzcandspacing = 5;
+
+ HPEN listpen = listborder != 0 ? CreatePen(PS_SOLID, listborder, listbordercolor) : (HPEN)GetStockObject(NULL_PEN);
+ HBRUSH listbrush = CreateSolidBrush(listfillcolor);
+ HPEN candpen = candborder != 0 ? CreatePen(PS_SOLID, candborder, candbordercolor) : (HPEN)GetStockObject(NULL_PEN);
+ HBRUSH candbrush = CreateSolidBrush(candfillcolor);
+ HPEN selpen = candborder != 0 ? CreatePen(PS_DOT, candborder, selbordercolor) : (HPEN)GetStockObject(NULL_PEN);
+ HBRUSH selbrush = CreateSolidBrush(selfillcolor);
+ HFONT font = CreateFont((int)(1 + videodata->ime_rect.h * 0.75f), 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, VARIABLE_PITCH | FF_SWISS, TEXT("Microsoft Sans Serif"));
+
+ SetBkMode(hdc, TRANSPARENT);
+ SelectObject(hdc, font);
+
+ for (i = 0; i < candcount; ++i) {
+ const WCHAR *s = videodata->ime_candidates[i];
+ if (!*s)
+ break;
+
+ GetTextExtentPoint32W(hdc, s, (int)SDL_wcslen(s), &candsizes[i]);
+ maxcandsize.cx = SDL_max(maxcandsize.cx, candsizes[i].cx);
+ maxcandsize.cy = SDL_max(maxcandsize.cy, candsizes[i].cy);
+
+ }
+ if (vertical) {
+ size.cx =
+ (listborder * 2) +
+ (listpadding * 2) +
+ (candmargin * 2) +
+ (candborder * 2) +
+ (candpadding * 2) +
+ (maxcandsize.cx)
+ ;
+ size.cy =
+ (listborder * 2) +
+ (listpadding * 2) +
+ ((candcount + 1) * candmargin) +
+ (candcount * candborder * 2) +
+ (candcount * candpadding * 2) +
+ (candcount * maxcandsize.cy)
+ ;
+ }
+ else {
+ size.cx =
+ (listborder * 2) +
+ (listpadding * 2) +
+ ((candcount + 1) * candmargin) +
+ (candcount * candborder * 2) +
+ (candcount * candpadding * 2) +
+ ((candcount - 1) * horzcandspacing);
+ ;
+
+ for (i = 0; i < candcount; ++i)
+ size.cx += candsizes[i].cx;
+
+ size.cy =
+ (listborder * 2) +
+ (listpadding * 2) +
+ (candmargin * 2) +
+ (candborder * 2) +
+ (candpadding * 2) +
+ (maxcandsize.cy)
+ ;
+ }
+
+ StartDrawToBitmap(hdc, &hbm, size.cx, size.cy);
+
+ SelectObject(hdc, listpen);
+ SelectObject(hdc, listbrush);
+ DrawRect(hdc, 0, 0, size.cx, size.cy, listborder);
+
+ SelectObject(hdc, candpen);
+ SelectObject(hdc, candbrush);
+ SetTextColor(hdc, candtextcolor);
+ SetBkMode(hdc, TRANSPARENT);
+
+ for (i = 0; i < candcount; ++i) {
+ const WCHAR *s = videodata->ime_candidates[i];
+ int left, top, right, bottom;
+ if (!*s)
+ break;
+
+ if (vertical) {
+ left = listborder + listpadding + candmargin;
+ top = listborder + listpadding + (i * candborder * 2) + (i * candpadding * 2) + ((i + 1) * candmargin) + (i * maxcandsize.cy);
+ right = size.cx - listborder - listpadding - candmargin;
+ bottom = top + maxcandsize.cy + (candpadding * 2) + (candborder * 2);
+ }
+ else {
+ left = listborder + listpadding + (i * candborder * 2) + (i * candpadding * 2) + ((i + 1) * candmargin) + (i * horzcandspacing);
+
+ for (j = 0; j < i; ++j)
+ left += candsizes[j].cx;
+
+ top = listborder + listpadding + candmargin;
+ right = left + candsizes[i].cx + (candpadding * 2) + (candborder * 2);
+ bottom = size.cy - listborder - listpadding - candmargin;
+ }
+
+ if (i == videodata->ime_candsel) {
+ SelectObject(hdc, selpen);
+ SelectObject(hdc, selbrush);
+ SetTextColor(hdc, seltextcolor);
+ }
+ else {
+ SelectObject(hdc, candpen);
+ SelectObject(hdc, candbrush);
+ SetTextColor(hdc, candtextcolor);
+ }
+
+ DrawRect(hdc, left, top, right, bottom, candborder);
+ ExtTextOutW(hdc, left + candborder + candpadding, top + candborder + candpadding, 0, NULL, s, (int)SDL_wcslen(s), NULL);
+ }
+ StopDrawToBitmap(hdc, &hbm);
+
+ DeleteObject(listpen);
+ DeleteObject(listbrush);
+ DeleteObject(candpen);
+ DeleteObject(candbrush);
+ DeleteObject(selpen);
+ DeleteObject(selbrush);
+ DeleteObject(font);
+
+ IME_PositionCandidateList(videodata, size);
+}
+
+static void
+IME_Render(SDL_VideoData *videodata)
+{
+ HDC hdc = CreateCompatibleDC(NULL);
+
+ if (videodata->ime_candlist)
+ IME_RenderCandidateList(videodata, hdc);
+
+ DeleteDC(hdc);
+
+ videodata->ime_dirty = SDL_FALSE;
+}
+
+void IME_Present(SDL_VideoData *videodata)
+{
+ if (videodata->ime_dirty)
+ IME_Render(videodata);
+
+ /* FIXME: Need to show the IME bitmap */
+}
+
+#endif /* SDL_DISABLE_WINDOWS_IME */
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.h
new file mode 100644
index 0000000..49a1b87
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowskeyboard.h
@@ -0,0 +1,40 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowskeyboard_h_
+#define SDL_windowskeyboard_h_
+
+extern void WIN_InitKeyboard(_THIS);
+extern void WIN_UpdateKeymap(void);
+extern void WIN_QuitKeyboard(_THIS);
+
+extern void WIN_ResetDeadKeys(void);
+
+extern void WIN_StartTextInput(_THIS);
+extern void WIN_StopTextInput(_THIS);
+extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect);
+
+extern SDL_bool IME_HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM *lParam, struct SDL_VideoData *videodata);
+
+#endif /* SDL_windowskeyboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.c
new file mode 100644
index 0000000..9ddb9e2
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.c
@@ -0,0 +1,905 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#ifndef SIZE_MAX
+#define SIZE_MAX ((size_t)-1)
+#endif
+#endif
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "SDL_assert.h"
+#include "SDL_windowsvideo.h"
+#include "SDL_windowstaskdialog.h"
+
+#ifndef SS_EDITCONTROL
+#define SS_EDITCONTROL 0x2000
+#endif
+
+#ifndef IDOK
+#define IDOK 1
+#endif
+
+#ifndef IDCANCEL
+#define IDCANCEL 2
+#endif
+
+/* Custom dialog return codes */
+#define IDCLOSED 20
+#define IDINVALPTRINIT 50
+#define IDINVALPTRCOMMAND 51
+#define IDINVALPTRSETFOCUS 52
+#define IDINVALPTRDLGITEM 53
+/* First button ID */
+#define IDBUTTONINDEX0 100
+
+#define DLGITEMTYPEBUTTON 0x0080
+#define DLGITEMTYPESTATIC 0x0082
+
+/* Windows only sends the lower 16 bits of the control ID when a button
+ * gets clicked. There are also some predefined and custom IDs that lower
+ * the available number further. 2^16 - 101 buttons should be enough for
+ * everyone, no need to make the code more complex.
+ */
+#define MAX_BUTTONS (0xffff - 100)
+
+
+/* Display a Windows message box */
+
+#pragma pack(push, 1)
+
+typedef struct
+{
+ WORD dlgVer;
+ WORD signature;
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ WORD cDlgItems;
+ short x;
+ short y;
+ short cx;
+ short cy;
+} DLGTEMPLATEEX;
+
+typedef struct
+{
+ DWORD helpID;
+ DWORD exStyle;
+ DWORD style;
+ short x;
+ short y;
+ short cx;
+ short cy;
+ DWORD id;
+} DLGITEMTEMPLATEEX;
+
+#pragma pack(pop)
+
+typedef struct
+{
+ DLGTEMPLATEEX* lpDialog;
+ Uint8 *data;
+ size_t size;
+ size_t used;
+ WORD numbuttons;
+} WIN_DialogData;
+
+static SDL_bool GetButtonIndex(const SDL_MessageBoxData *messageboxdata, Uint32 flags, size_t *i)
+{
+ for (*i = 0; *i < (size_t)messageboxdata->numbuttons; ++*i) {
+ if (messageboxdata->buttons[*i].flags & flags) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+static INT_PTR MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam)
+{
+ const SDL_MessageBoxData *messageboxdata;
+ size_t buttonindex;
+
+ switch ( iMessage ) {
+ case WM_INITDIALOG:
+ if (lParam == 0) {
+ EndDialog(hDlg, IDINVALPTRINIT);
+ return TRUE;
+ }
+ messageboxdata = (const SDL_MessageBoxData *)lParam;
+ SetWindowLongPtr(hDlg, GWLP_USERDATA, lParam);
+
+ if (GetButtonIndex(messageboxdata, SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, &buttonindex)) {
+ /* Focus on the first default return-key button */
+ HWND buttonctl = GetDlgItem(hDlg, (int)(IDBUTTONINDEX0 + buttonindex));
+ if (buttonctl == NULL) {
+ EndDialog(hDlg, IDINVALPTRDLGITEM);
+ }
+ PostMessage(hDlg, WM_NEXTDLGCTL, (WPARAM)buttonctl, TRUE);
+ } else {
+ /* Give the focus to the dialog window instead */
+ SetFocus(hDlg);
+ }
+ return FALSE;
+ case WM_SETFOCUS:
+ messageboxdata = (const SDL_MessageBoxData *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
+ if (messageboxdata == NULL) {
+ EndDialog(hDlg, IDINVALPTRSETFOCUS);
+ return TRUE;
+ }
+
+ /* Let the default button be focused if there is one. Otherwise, prevent any initial focus. */
+ if (GetButtonIndex(messageboxdata, SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, &buttonindex)) {
+ return FALSE;
+ }
+ return TRUE;
+ case WM_COMMAND:
+ messageboxdata = (const SDL_MessageBoxData *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
+ if (messageboxdata == NULL) {
+ EndDialog(hDlg, IDINVALPTRCOMMAND);
+ return TRUE;
+ }
+
+ /* Return the ID of the button that was pushed */
+ if (wParam == IDOK) {
+ if (GetButtonIndex(messageboxdata, SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, &buttonindex)) {
+ EndDialog(hDlg, IDBUTTONINDEX0 + buttonindex);
+ }
+ } else if (wParam == IDCANCEL) {
+ if (GetButtonIndex(messageboxdata, SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, &buttonindex)) {
+ EndDialog(hDlg, IDBUTTONINDEX0 + buttonindex);
+ } else {
+ /* Closing of window was requested by user or system. It would be rude not to comply. */
+ EndDialog(hDlg, IDCLOSED);
+ }
+ } else if (wParam >= IDBUTTONINDEX0 && (int)wParam - IDBUTTONINDEX0 < messageboxdata->numbuttons) {
+ EndDialog(hDlg, wParam);
+ }
+ return TRUE;
+
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog, size_t space)
+{
+ /* Growing memory in 64 KiB steps. */
+ const size_t sizestep = 0x10000;
+ size_t size = dialog->size;
+
+ if (size == 0) {
+ /* Start with 4 KiB or a multiple of 64 KiB to fit the data. */
+ size = 0x1000;
+ if (SIZE_MAX - sizestep < space) {
+ size = space;
+ } else if (space > size) {
+ size = (space + sizestep) & ~(sizestep - 1);
+ }
+ } else if (SIZE_MAX - dialog->used < space) {
+ SDL_OutOfMemory();
+ return SDL_FALSE;
+ } else if (SIZE_MAX - (dialog->used + space) < sizestep) {
+ /* Close to the maximum. */
+ size = dialog->used + space;
+ } else if (size < dialog->used + space) {
+ /* Round up to the next 64 KiB block. */
+ size = dialog->used + space;
+ size += sizestep - size % sizestep;
+ }
+
+ if (size > dialog->size) {
+ void *data = SDL_realloc(dialog->data, size);
+ if (!data) {
+ SDL_OutOfMemory();
+ return SDL_FALSE;
+ }
+ dialog->data = data;
+ dialog->size = size;
+ dialog->lpDialog = (DLGTEMPLATEEX*)dialog->data;
+ }
+ return SDL_TRUE;
+}
+
+static SDL_bool AlignDialogData(WIN_DialogData *dialog, size_t size)
+{
+ size_t padding = (dialog->used % size);
+
+ if (!ExpandDialogSpace(dialog, padding)) {
+ return SDL_FALSE;
+ }
+
+ dialog->used += padding;
+
+ return SDL_TRUE;
+}
+
+static SDL_bool AddDialogData(WIN_DialogData *dialog, const void *data, size_t size)
+{
+ if (!ExpandDialogSpace(dialog, size)) {
+ return SDL_FALSE;
+ }
+
+ SDL_memcpy(dialog->data+dialog->used, data, size);
+ dialog->used += size;
+
+ return SDL_TRUE;
+}
+
+static SDL_bool AddDialogString(WIN_DialogData *dialog, const char *string)
+{
+ WCHAR *wstring;
+ WCHAR *p;
+ size_t count;
+ SDL_bool status;
+
+ if (!string) {
+ string = "";
+ }
+
+ wstring = WIN_UTF8ToString(string);
+ if (!wstring) {
+ return SDL_FALSE;
+ }
+
+ /* Find out how many characters we have, including null terminator */
+ count = 0;
+ for (p = wstring; *p; ++p) {
+ ++count;
+ }
+ ++count;
+
+ status = AddDialogData(dialog, wstring, count*sizeof(WCHAR));
+ SDL_free(wstring);
+ return status;
+}
+
+static int s_BaseUnitsX;
+static int s_BaseUnitsY;
+static void Vec2ToDLU(short *x, short *y)
+{
+ SDL_assert(s_BaseUnitsX != 0); /* we init in WIN_ShowMessageBox(), which is the only public function... */
+
+ *x = MulDiv(*x, 4, s_BaseUnitsX);
+ *y = MulDiv(*y, 8, s_BaseUnitsY);
+}
+
+
+static SDL_bool AddDialogControl(WIN_DialogData *dialog, WORD type, DWORD style, DWORD exStyle, int x, int y, int w, int h, int id, const char *caption, WORD ordinal)
+{
+ DLGITEMTEMPLATEEX item;
+ WORD marker = 0xFFFF;
+ WORD extraData = 0;
+
+ SDL_zero(item);
+ item.style = style;
+ item.exStyle = exStyle;
+ item.x = x;
+ item.y = y;
+ item.cx = w;
+ item.cy = h;
+ item.id = id;
+
+ Vec2ToDLU(&item.x, &item.y);
+ Vec2ToDLU(&item.cx, &item.cy);
+
+ if (!AlignDialogData(dialog, sizeof(DWORD))) {
+ return SDL_FALSE;
+ }
+ if (!AddDialogData(dialog, &item, sizeof(item))) {
+ return SDL_FALSE;
+ }
+ if (!AddDialogData(dialog, &marker, sizeof(marker))) {
+ return SDL_FALSE;
+ }
+ if (!AddDialogData(dialog, &type, sizeof(type))) {
+ return SDL_FALSE;
+ }
+ if (type == DLGITEMTYPEBUTTON || (type == DLGITEMTYPESTATIC && caption != NULL)) {
+ if (!AddDialogString(dialog, caption)) {
+ return SDL_FALSE;
+ }
+ } else {
+ if (!AddDialogData(dialog, &marker, sizeof(marker))) {
+ return SDL_FALSE;
+ }
+ if (!AddDialogData(dialog, &ordinal, sizeof(ordinal))) {
+ return SDL_FALSE;
+ }
+ }
+ if (!AddDialogData(dialog, &extraData, sizeof(extraData))) {
+ return SDL_FALSE;
+ }
+ if (type == DLGITEMTYPEBUTTON) {
+ dialog->numbuttons++;
+ }
+ ++dialog->lpDialog->cDlgItems;
+
+ return SDL_TRUE;
+}
+
+static SDL_bool AddDialogStaticText(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text)
+{
+ DWORD style = WS_VISIBLE | WS_CHILD | SS_LEFT | SS_NOPREFIX | SS_EDITCONTROL | WS_GROUP;
+ return AddDialogControl(dialog, DLGITEMTYPESTATIC, style, 0, x, y, w, h, -1, text, 0);
+}
+
+static SDL_bool AddDialogStaticIcon(WIN_DialogData *dialog, int x, int y, int w, int h, Uint16 ordinal)
+{
+ DWORD style = WS_VISIBLE | WS_CHILD | SS_ICON | WS_GROUP;
+ return AddDialogControl(dialog, DLGITEMTYPESTATIC, style, 0, x, y, w, h, -2, NULL, ordinal);
+}
+
+static SDL_bool AddDialogButton(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text, int id, SDL_bool isDefault)
+{
+ DWORD style = WS_VISIBLE | WS_CHILD | WS_TABSTOP;
+ if (isDefault) {
+ style |= BS_DEFPUSHBUTTON;
+ } else {
+ style |= BS_PUSHBUTTON;
+ }
+ /* The first button marks the start of the group. */
+ if (dialog->numbuttons == 0) {
+ style |= WS_GROUP;
+ }
+ return AddDialogControl(dialog, DLGITEMTYPEBUTTON, style, 0, x, y, w, h, IDBUTTONINDEX0 + dialog->numbuttons, text, 0);
+}
+
+static void FreeDialogData(WIN_DialogData *dialog)
+{
+ SDL_free(dialog->data);
+ SDL_free(dialog);
+}
+
+static WIN_DialogData *CreateDialogData(int w, int h, const char *caption)
+{
+ WIN_DialogData *dialog;
+ DLGTEMPLATEEX dialogTemplate;
+ WORD WordToPass;
+
+ SDL_zero(dialogTemplate);
+ dialogTemplate.dlgVer = 1;
+ dialogTemplate.signature = 0xffff;
+ dialogTemplate.style = (WS_CAPTION | DS_CENTER | DS_SHELLFONT);
+ dialogTemplate.x = 0;
+ dialogTemplate.y = 0;
+ dialogTemplate.cx = w;
+ dialogTemplate.cy = h;
+ Vec2ToDLU(&dialogTemplate.cx, &dialogTemplate.cy);
+
+ dialog = (WIN_DialogData *)SDL_calloc(1, sizeof(*dialog));
+ if (!dialog) {
+ return NULL;
+ }
+
+ if (!AddDialogData(dialog, &dialogTemplate, sizeof(dialogTemplate))) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* No menu */
+ WordToPass = 0;
+ if (!AddDialogData(dialog, &WordToPass, 2)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* No custom class */
+ if (!AddDialogData(dialog, &WordToPass, 2)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* title */
+ if (!AddDialogString(dialog, caption)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* Font stuff */
+ {
+ /*
+ * We want to use the system messagebox font.
+ */
+ BYTE ToPass;
+
+ NONCLIENTMETRICSA NCM;
+ NCM.cbSize = sizeof(NCM);
+ SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
+
+ /* Font size - convert to logical font size for dialog parameter. */
+ {
+ HDC ScreenDC = GetDC(NULL);
+ int LogicalPixelsY = GetDeviceCaps(ScreenDC, LOGPIXELSY);
+ if (!LogicalPixelsY) /* This can happen if the application runs out of GDI handles */
+ LogicalPixelsY = 72;
+ WordToPass = (WORD)(-72 * NCM.lfMessageFont.lfHeight / LogicalPixelsY);
+ ReleaseDC(NULL, ScreenDC);
+ }
+
+ if (!AddDialogData(dialog, &WordToPass, 2)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* Font weight */
+ WordToPass = (WORD)NCM.lfMessageFont.lfWeight;
+ if (!AddDialogData(dialog, &WordToPass, 2)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* italic? */
+ ToPass = NCM.lfMessageFont.lfItalic;
+ if (!AddDialogData(dialog, &ToPass, 1)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* charset? */
+ ToPass = NCM.lfMessageFont.lfCharSet;
+ if (!AddDialogData(dialog, &ToPass, 1)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+
+ /* font typeface. */
+ if (!AddDialogString(dialog, NCM.lfMessageFont.lfFaceName)) {
+ FreeDialogData(dialog);
+ return NULL;
+ }
+ }
+
+ return dialog;
+}
+
+/* Escaping ampersands is necessary to disable mnemonics in dialog controls.
+ * The caller provides a char** for dst and a size_t* for dstlen where the
+ * address of the work buffer and its size will be stored. Their values must be
+ * NULL and 0 on the first call. src is the string to be escaped. On error, the
+ * function returns NULL and, on success, returns a pointer to the escaped
+ * sequence as a read-only string that is valid until the next call or until the
+ * work buffer is freed. Once all strings have been processed, it's the caller's
+ * responsibilty to free the work buffer with SDL_free, even on errors.
+ */
+static const char *EscapeAmpersands(char **dst, size_t *dstlen, const char *src)
+{
+ char *newdst;
+ size_t ampcount = 0;
+ size_t srclen = 0;
+
+ if (src == NULL) {
+ return NULL;
+ }
+
+ while (src[srclen]) {
+ if (src[srclen] == '&') {
+ ampcount++;
+ }
+ srclen++;
+ }
+ srclen++;
+
+ if (ampcount == 0) {
+ /* Nothing to do. */
+ return src;
+ }
+ if (SIZE_MAX - srclen < ampcount) {
+ return NULL;
+ }
+ if (*dst == NULL || *dstlen < srclen + ampcount) {
+ /* Allocating extra space in case the next strings are a bit longer. */
+ size_t extraspace = SIZE_MAX - (srclen + ampcount);
+ if (extraspace > 512) {
+ extraspace = 512;
+ }
+ *dstlen = srclen + ampcount + extraspace;
+ SDL_free(*dst);
+ *dst = NULL;
+ newdst = SDL_malloc(*dstlen);
+ if (newdst == NULL) {
+ return NULL;
+ }
+ *dst = newdst;
+ } else {
+ newdst = *dst;
+ }
+
+ /* The escape character is the ampersand itself. */
+ while (srclen--) {
+ if (*src == '&') {
+ *newdst++ = '&';
+ }
+ *newdst++ = *src++;
+ }
+
+ return *dst;
+}
+
+/* This function is called if a Task Dialog is unsupported. */
+static int
+WIN_ShowOldMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+ WIN_DialogData *dialog;
+ int i, x, y, retval;
+ const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons;
+ HFONT DialogFont;
+ SIZE Size;
+ RECT TextSize;
+ wchar_t* wmessage;
+ TEXTMETRIC TM;
+ HDC FontDC;
+ INT_PTR result;
+ char *ampescape = NULL;
+ size_t ampescapesize = 0;
+ Uint16 defbuttoncount = 0;
+ Uint16 icon = 0;
+
+ HWND ParentWindow = NULL;
+
+ const int ButtonWidth = 88;
+ const int ButtonHeight = 26;
+ const int TextMargin = 16;
+ const int ButtonMargin = 12;
+ const int IconWidth = GetSystemMetrics(SM_CXICON);
+ const int IconHeight = GetSystemMetrics(SM_CYICON);
+ const int IconMargin = 20;
+
+ if (messageboxdata->numbuttons > MAX_BUTTONS) {
+ return SDL_SetError("Number of butons exceeds limit of %d", MAX_BUTTONS);
+ }
+
+ switch (messageboxdata->flags) {
+ case SDL_MESSAGEBOX_ERROR:
+ icon = (Uint16)(size_t)IDI_ERROR;
+ break;
+ case SDL_MESSAGEBOX_WARNING:
+ icon = (Uint16)(size_t)IDI_WARNING;
+ break;
+ case SDL_MESSAGEBOX_INFORMATION:
+ icon = (Uint16)(size_t)IDI_INFORMATION;
+ break;
+ }
+
+ /* Jan 25th, 2013 - dant@fleetsa.com
+ *
+ *
+ * I've tried to make this more reasonable, but I've run in to a lot
+ * of nonsense.
+ *
+ * The original issue is the code was written in pixels and not
+ * dialog units (DLUs). All DialogBox functions use DLUs, which
+ * vary based on the selected font (yay).
+ *
+ * According to MSDN, the most reliable way to convert is via
+ * MapDialogUnits, which requires an HWND, which we don't have
+ * at time of template creation.
+ *
+ * We do however have:
+ * The system font (DLU width 8 for me)
+ * The font we select for the dialog (DLU width 6 for me)
+ *
+ * Based on experimentation, *neither* of these return the value
+ * actually used. Stepping in to MapDialogUnits(), the conversion
+ * is fairly clear, and uses 7 for me.
+ *
+ * As a result, some of this is hacky to ensure the sizing is
+ * somewhat correct.
+ *
+ * Honestly, a long term solution is to use CreateWindow, not CreateDialog.
+ *
+
+ *
+ * In order to get text dimensions we need to have a DC with the desired font.
+ * I'm assuming a dialog box in SDL is rare enough we can to the create.
+ */
+ FontDC = CreateCompatibleDC(0);
+
+ {
+ /* Create a duplicate of the font used in system message boxes. */
+ LOGFONT lf;
+ NONCLIENTMETRICS NCM;
+ NCM.cbSize = sizeof(NCM);
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &NCM, 0);
+ lf = NCM.lfMessageFont;
+ DialogFont = CreateFontIndirect(&lf);
+ }
+
+ /* Select the font in to our DC */
+ SelectObject(FontDC, DialogFont);
+
+ {
+ /* Get the metrics to try and figure our DLU conversion. */
+ GetTextMetrics(FontDC, &TM);
+
+ /* Calculation from the following documentation:
+ * https://support.microsoft.com/en-gb/help/125681/how-to-calculate-dialog-base-units-with-non-system-based-font
+ * This fixes bug 2137, dialog box calculation with a fixed-width system font
+ */
+ {
+ SIZE extent;
+ GetTextExtentPoint32A(FontDC, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 52, &extent);
+ s_BaseUnitsX = (extent.cx / 26 + 1) / 2;
+ }
+ /*s_BaseUnitsX = TM.tmAveCharWidth + 1;*/
+ s_BaseUnitsY = TM.tmHeight;
+ }
+
+ /* Measure the *pixel* size of the string. */
+ wmessage = WIN_UTF8ToString(messageboxdata->message);
+ SDL_zero(TextSize);
+ DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT | DT_LEFT | DT_NOPREFIX | DT_EDITCONTROL);
+
+ /* Add margins and some padding for hangs, etc. */
+ TextSize.left += TextMargin;
+ TextSize.right += TextMargin + 2;
+ TextSize.top += TextMargin;
+ TextSize.bottom += TextMargin + 2;
+
+ /* Done with the DC, and the string */
+ DeleteDC(FontDC);
+ SDL_free(wmessage);
+
+ /* Increase the size of the dialog by some border spacing around the text. */
+ Size.cx = TextSize.right - TextSize.left;
+ Size.cy = TextSize.bottom - TextSize.top;
+ Size.cx += TextMargin * 2;
+ Size.cy += TextMargin * 2;
+
+ /* Make dialog wider and shift text over for the icon. */
+ if (icon) {
+ Size.cx += IconMargin + IconWidth;
+ TextSize.left += IconMargin + IconWidth;
+ TextSize.right += IconMargin + IconWidth;
+ }
+
+ /* Ensure the size is wide enough for all of the buttons. */
+ if (Size.cx < messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin)
+ Size.cx = messageboxdata->numbuttons * (ButtonWidth + ButtonMargin) + ButtonMargin;
+
+ /* Reset the height to the icon size if it is actually bigger than the text. */
+ if (icon && Size.cy < IconMargin * 2 + IconHeight) {
+ Size.cy = IconMargin * 2 + IconHeight;
+ }
+
+ /* Add vertical space for the buttons and border. */
+ Size.cy += ButtonHeight + TextMargin;
+
+ dialog = CreateDialogData(Size.cx, Size.cy, messageboxdata->title);
+ if (!dialog) {
+ return -1;
+ }
+
+ if (icon && ! AddDialogStaticIcon(dialog, IconMargin, IconMargin, IconWidth, IconHeight, icon)) {
+ FreeDialogData(dialog);
+ return -1;
+ }
+
+ if (!AddDialogStaticText(dialog, TextSize.left, TextSize.top, TextSize.right - TextSize.left, TextSize.bottom - TextSize.top, messageboxdata->message)) {
+ FreeDialogData(dialog);
+ return -1;
+ }
+
+ /* Align the buttons to the right/bottom. */
+ x = Size.cx - (ButtonWidth + ButtonMargin) * messageboxdata->numbuttons;
+ y = Size.cy - ButtonHeight - ButtonMargin;
+ for (i = messageboxdata->numbuttons - 1; i >= 0; --i) {
+ SDL_bool isdefault = SDL_FALSE;
+ const char *buttontext;
+
+ if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
+ defbuttoncount++;
+ if (defbuttoncount == 1) {
+ isdefault = SDL_TRUE;
+ }
+ }
+
+ buttontext = EscapeAmpersands(&ampescape, &ampescapesize, buttons[i].text);
+ if (buttontext == NULL || !AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttontext, buttons[i].buttonid, isdefault)) {
+ FreeDialogData(dialog);
+ SDL_free(ampescape);
+ return -1;
+ }
+ x += ButtonWidth + ButtonMargin;
+ }
+ SDL_free(ampescape);
+
+ /* If we have a parent window, get the Instance and HWND for them
+ * so that our little dialog gets exclusive focus at all times. */
+ if (messageboxdata->window) {
+ ParentWindow = ((SDL_WindowData*)messageboxdata->window->driverdata)->hwnd;
+ }
+
+ result = DialogBoxIndirectParam(NULL, (DLGTEMPLATE*)dialog->lpDialog, ParentWindow, (DLGPROC)MessageBoxDialogProc, (LPARAM)messageboxdata);
+ if (result >= IDBUTTONINDEX0 && result - IDBUTTONINDEX0 < messageboxdata->numbuttons) {
+ *buttonid = messageboxdata->buttons[(messageboxdata->numbuttons - 1) - (result - IDBUTTONINDEX0)].buttonid;
+ retval = 0;
+ } else if (result == IDCLOSED) {
+ /* Dialog window closed by user or system. */
+ /* This could use a special return code. */
+ retval = 0;
+ *buttonid = -1;
+ } else {
+ if (result == 0) {
+ SDL_SetError("Invalid parent window handle");
+ } else if (result == -1) {
+ SDL_SetError("The message box encountered an error.");
+ } else if (result == IDINVALPTRINIT || result == IDINVALPTRSETFOCUS || result == IDINVALPTRCOMMAND) {
+ SDL_SetError("Invalid message box pointer in dialog procedure");
+ } else if (result == IDINVALPTRDLGITEM) {
+ SDL_SetError("Couldn't find dialog control of the default enter-key button");
+ } else {
+ SDL_SetError("An unknown error occured");
+ }
+ retval = -1;
+ }
+
+ FreeDialogData(dialog);
+ return retval;
+}
+
+/* TaskDialogIndirect procedure
+ * This is because SDL targets Windows XP (0x501), so this is not defined in the platform SDK.
+ */
+typedef HRESULT(FAR WINAPI *TASKDIALOGINDIRECTPROC)(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton, int *pnRadioButton, BOOL *pfVerificationFlagChecked);
+
+int
+WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
+{
+ HWND ParentWindow = NULL;
+ wchar_t *wmessage;
+ wchar_t *wtitle;
+ TASKDIALOGCONFIG TaskConfig;
+ TASKDIALOG_BUTTON *pButtons;
+ TASKDIALOG_BUTTON *pButton;
+ HMODULE hComctl32;
+ TASKDIALOGINDIRECTPROC pfnTaskDialogIndirect;
+ HRESULT hr;
+ char *ampescape = NULL;
+ size_t ampescapesize = 0;
+ int nButton;
+ int nCancelButton;
+ int i;
+
+ if (SIZE_MAX / sizeof(TASKDIALOG_BUTTON) < messageboxdata->numbuttons) {
+ return SDL_OutOfMemory();
+ }
+
+ /* If we cannot load comctl32.dll use the old messagebox! */
+ hComctl32 = LoadLibrary(TEXT("Comctl32.dll"));
+ if (hComctl32 == NULL) {
+ return WIN_ShowOldMessageBox(messageboxdata, buttonid);
+ }
+
+ /* If TaskDialogIndirect doesn't exist use the old messagebox!
+ This will fail prior to Windows Vista.
+ The manifest file in the application may require targeting version 6 of comctl32.dll, even
+ when we use LoadLibrary here!
+ If you don't want to bother with manifests, put this #pragma in your app's source code somewhere:
+ pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
+ */
+ pfnTaskDialogIndirect = (TASKDIALOGINDIRECTPROC) GetProcAddress(hComctl32, "TaskDialogIndirect");
+ if (pfnTaskDialogIndirect == NULL) {
+ FreeLibrary(hComctl32);
+ return WIN_ShowOldMessageBox(messageboxdata, buttonid);
+ }
+
+ /* If we have a parent window, get the Instance and HWND for them
+ so that our little dialog gets exclusive focus at all times. */
+ if (messageboxdata->window) {
+ ParentWindow = ((SDL_WindowData *) messageboxdata->window->driverdata)->hwnd;
+ }
+
+ wmessage = WIN_UTF8ToString(messageboxdata->message);
+ wtitle = WIN_UTF8ToString(messageboxdata->title);
+
+ SDL_zero(TaskConfig);
+ TaskConfig.cbSize = sizeof (TASKDIALOGCONFIG);
+ TaskConfig.hwndParent = ParentWindow;
+ TaskConfig.dwFlags = TDF_SIZE_TO_CONTENT;
+ TaskConfig.pszWindowTitle = wtitle;
+ if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) {
+ TaskConfig.pszMainIcon = TD_ERROR_ICON;
+ } else if (messageboxdata->flags & SDL_MESSAGEBOX_WARNING) {
+ TaskConfig.pszMainIcon = TD_WARNING_ICON;
+ } else if (messageboxdata->flags & SDL_MESSAGEBOX_INFORMATION) {
+ TaskConfig.pszMainIcon = TD_INFORMATION_ICON;
+ } else {
+ TaskConfig.pszMainIcon = NULL;
+ }
+
+ TaskConfig.pszContent = wmessage;
+ TaskConfig.cButtons = messageboxdata->numbuttons;
+ pButtons = SDL_malloc(sizeof (TASKDIALOG_BUTTON) * messageboxdata->numbuttons);
+ TaskConfig.nDefaultButton = 0;
+ nCancelButton = 0;
+ for (i = 0; i < messageboxdata->numbuttons; i++)
+ {
+ const char *buttontext;
+ pButton = &pButtons[messageboxdata->numbuttons-1-i];
+ if (messageboxdata->buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) {
+ nCancelButton = messageboxdata->buttons[i].buttonid;
+ pButton->nButtonID = 2;
+ } else {
+ pButton->nButtonID = messageboxdata->buttons[i].buttonid + 1;
+ if (pButton->nButtonID >= 2) {
+ pButton->nButtonID++;
+ }
+ }
+ buttontext = EscapeAmpersands(&ampescape, &ampescapesize, messageboxdata->buttons[i].text);
+ if (buttontext == NULL) {
+ int j;
+ FreeLibrary(hComctl32);
+ SDL_free(ampescape);
+ SDL_free(wmessage);
+ SDL_free(wtitle);
+ for (j = 0; j < i; j++) {
+ SDL_free((wchar_t *) pButtons[j].pszButtonText);
+ }
+ SDL_free(pButtons);
+ return -1;
+ }
+ pButton->pszButtonText = WIN_UTF8ToString(buttontext);
+ if (messageboxdata->buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
+ TaskConfig.nDefaultButton = pButton->nButtonID;
+ }
+ }
+ TaskConfig.pButtons = pButtons;
+
+ /* Show the Task Dialog */
+ hr = pfnTaskDialogIndirect(&TaskConfig, &nButton, NULL, NULL);
+
+ /* Free everything */
+ FreeLibrary(hComctl32);
+ SDL_free(ampescape);
+ SDL_free(wmessage);
+ SDL_free(wtitle);
+ for (i = 0; i < messageboxdata->numbuttons; i++) {
+ SDL_free((wchar_t *) pButtons[i].pszButtonText);
+ }
+ SDL_free(pButtons);
+
+ /* Check the Task Dialog was successful and give the result */
+ if (SUCCEEDED(hr)) {
+ if (nButton == 2) {
+ *buttonid = nCancelButton;
+ } else if (nButton > 2) {
+ *buttonid = nButton-1-1;
+ } else {
+ *buttonid = nButton-1;
+ }
+ return 0;
+ }
+
+ /* We failed showing the Task Dialog, use the old message box! */
+ return WIN_ShowOldMessageBox(messageboxdata, buttonid);
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.h
new file mode 100644
index 0000000..2cb29be
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmessagebox.h
@@ -0,0 +1,29 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+extern int WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c
new file mode 100644
index 0000000..7425d9a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.c
@@ -0,0 +1,407 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_windowsvideo.h"
+#include "../../../include/SDL_assert.h"
+#include "../../../include/SDL_log.h"
+
+/* Windows CE compatibility */
+#ifndef CDS_FULLSCREEN
+#define CDS_FULLSCREEN 0
+#endif
+
+/* #define DEBUG_MODES */
+
+static void
+WIN_UpdateDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
+{
+ SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
+ HDC hdc;
+
+ data->DeviceMode.dmFields =
+ (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY |
+ DM_DISPLAYFLAGS);
+
+ if (index == ENUM_CURRENT_SETTINGS
+ && (hdc = CreateDC(deviceName, NULL, NULL, NULL)) != NULL) {
+ char bmi_data[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
+ LPBITMAPINFO bmi;
+ HBITMAP hbm;
+ int logical_width = GetDeviceCaps( hdc, HORZRES );
+ int logical_height = GetDeviceCaps( hdc, VERTRES );
+
+ mode->w = logical_width;
+ mode->h = logical_height;
+
+ SDL_zero(bmi_data);
+ bmi = (LPBITMAPINFO) bmi_data;
+ bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+
+ hbm = CreateCompatibleBitmap(hdc, 1, 1);
+ GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
+ GetDIBits(hdc, hbm, 0, 1, NULL, bmi, DIB_RGB_COLORS);
+ DeleteObject(hbm);
+ DeleteDC(hdc);
+ if (bmi->bmiHeader.biCompression == BI_BITFIELDS) {
+ switch (*(Uint32 *) bmi->bmiColors) {
+ case 0x00FF0000:
+ mode->format = SDL_PIXELFORMAT_RGB888;
+ break;
+ case 0x000000FF:
+ mode->format = SDL_PIXELFORMAT_BGR888;
+ break;
+ case 0xF800:
+ mode->format = SDL_PIXELFORMAT_RGB565;
+ break;
+ case 0x7C00:
+ mode->format = SDL_PIXELFORMAT_RGB555;
+ break;
+ }
+ } else if (bmi->bmiHeader.biBitCount == 8) {
+ mode->format = SDL_PIXELFORMAT_INDEX8;
+ } else if (bmi->bmiHeader.biBitCount == 4) {
+ mode->format = SDL_PIXELFORMAT_INDEX4LSB;
+ }
+ } else if (mode->format == SDL_PIXELFORMAT_UNKNOWN) {
+ /* FIXME: Can we tell what this will be? */
+ if ((data->DeviceMode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
+ switch (data->DeviceMode.dmBitsPerPel) {
+ case 32:
+ mode->format = SDL_PIXELFORMAT_RGB888;
+ break;
+ case 24:
+ mode->format = SDL_PIXELFORMAT_RGB24;
+ break;
+ case 16:
+ mode->format = SDL_PIXELFORMAT_RGB565;
+ break;
+ case 15:
+ mode->format = SDL_PIXELFORMAT_RGB555;
+ break;
+ case 8:
+ mode->format = SDL_PIXELFORMAT_INDEX8;
+ break;
+ case 4:
+ mode->format = SDL_PIXELFORMAT_INDEX4LSB;
+ break;
+ }
+ }
+ }
+}
+
+static SDL_bool
+WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
+{
+ SDL_DisplayModeData *data;
+ DEVMODE devmode;
+
+ devmode.dmSize = sizeof(devmode);
+ devmode.dmDriverExtra = 0;
+ if (!EnumDisplaySettings(deviceName, index, &devmode)) {
+ return SDL_FALSE;
+ }
+
+ data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
+ if (!data) {
+ return SDL_FALSE;
+ }
+
+ mode->driverdata = data;
+ data->DeviceMode = devmode;
+
+ mode->format = SDL_PIXELFORMAT_UNKNOWN;
+ mode->w = data->DeviceMode.dmPelsWidth;
+ mode->h = data->DeviceMode.dmPelsHeight;
+ mode->refresh_rate = data->DeviceMode.dmDisplayFrequency;
+
+ /* Fill in the mode information */
+ WIN_UpdateDisplayMode(_this, deviceName, index, mode);
+ return SDL_TRUE;
+}
+
+static SDL_bool
+WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEX *info)
+{
+ SDL_VideoDisplay display;
+ SDL_DisplayData *displaydata;
+ SDL_DisplayMode mode;
+ DISPLAY_DEVICE device;
+
+#ifdef DEBUG_MODES
+ SDL_Log("Display: %s\n", WIN_StringToUTF8(info->szDevice));
+#endif
+
+ if (!WIN_GetDisplayMode(_this, info->szDevice, ENUM_CURRENT_SETTINGS, &mode)) {
+ return SDL_FALSE;
+ }
+
+ displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
+ if (!displaydata) {
+ return SDL_FALSE;
+ }
+ SDL_memcpy(displaydata->DeviceName, info->szDevice,
+ sizeof(displaydata->DeviceName));
+ displaydata->MonitorHandle = hMonitor;
+
+ SDL_zero(display);
+ device.cb = sizeof(device);
+ if (EnumDisplayDevices(info->szDevice, 0, &device, 0)) {
+ display.name = WIN_StringToUTF8(device.DeviceString);
+ }
+ display.desktop_mode = mode;
+ display.current_mode = mode;
+ display.driverdata = displaydata;
+ SDL_AddVideoDisplay(&display);
+ SDL_free(display.name);
+ return SDL_TRUE;
+}
+
+typedef struct _WIN_AddDisplaysData {
+ SDL_VideoDevice *video_device;
+ SDL_bool want_primary;
+} WIN_AddDisplaysData;
+
+static BOOL CALLBACK
+WIN_AddDisplaysCallback(HMONITOR hMonitor,
+ HDC hdcMonitor,
+ LPRECT lprcMonitor,
+ LPARAM dwData)
+{
+ WIN_AddDisplaysData *data = (WIN_AddDisplaysData*)dwData;
+ MONITORINFOEX info;
+
+ SDL_zero(info);
+ info.cbSize = sizeof(info);
+
+ if (GetMonitorInfo(hMonitor, (LPMONITORINFO)&info) != 0) {
+ const SDL_bool is_primary = ((info.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY);
+
+ if (is_primary == data->want_primary) {
+ WIN_AddDisplay(data->video_device, hMonitor, &info);
+ }
+ }
+
+ // continue enumeration
+ return TRUE;
+}
+
+static void
+WIN_AddDisplays(_THIS)
+{
+ WIN_AddDisplaysData callback_data;
+ callback_data.video_device = _this;
+
+ callback_data.want_primary = SDL_TRUE;
+ EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data);
+
+ callback_data.want_primary = SDL_FALSE;
+ EnumDisplayMonitors(NULL, NULL, WIN_AddDisplaysCallback, (LPARAM)&callback_data);
+}
+
+int
+WIN_InitModes(_THIS)
+{
+ WIN_AddDisplays(_this);
+
+ if (_this->num_displays == 0) {
+ return SDL_SetError("No displays available");
+ }
+ return 0;
+}
+
+int
+WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ const SDL_DisplayData *data = (const SDL_DisplayData *)display->driverdata;
+ MONITORINFO minfo;
+ BOOL rc;
+
+ SDL_zero(minfo);
+ minfo.cbSize = sizeof(MONITORINFO);
+ rc = GetMonitorInfo(data->MonitorHandle, &minfo);
+
+ if (!rc) {
+ return SDL_SetError("Couldn't find monitor data");
+ }
+
+ rect->x = minfo.rcMonitor.left;
+ rect->y = minfo.rcMonitor.top;
+ rect->w = minfo.rcMonitor.right - minfo.rcMonitor.left;
+ rect->h = minfo.rcMonitor.bottom - minfo.rcMonitor.top;
+
+ return 0;
+}
+
+int
+WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi_out, float * hdpi_out, float * vdpi_out)
+{
+ const SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
+ const SDL_VideoData *videodata = (SDL_VideoData *)display->device->driverdata;
+ float hdpi = 0, vdpi = 0, ddpi = 0;
+
+ if (videodata->GetDpiForMonitor) {
+ UINT hdpi_uint, vdpi_uint;
+ // Windows 8.1+ codepath
+ if (videodata->GetDpiForMonitor(displaydata->MonitorHandle, MDT_EFFECTIVE_DPI, &hdpi_uint, &vdpi_uint) == S_OK) {
+ // GetDpiForMonitor docs promise to return the same hdpi/vdpi
+ hdpi = (float)hdpi_uint;
+ vdpi = (float)hdpi_uint;
+ ddpi = (float)hdpi_uint;
+ } else {
+ return SDL_SetError("GetDpiForMonitor failed");
+ }
+ } else {
+ // Window 8.0 and below: same DPI for all monitors.
+ HDC hdc;
+ int hdpi_int, vdpi_int, hpoints, vpoints, hpix, vpix;
+ float hinches, vinches;
+
+ hdc = GetDC(NULL);
+ if (hdc == NULL) {
+ return SDL_SetError("GetDC failed");
+ }
+ hdpi_int = GetDeviceCaps(hdc, LOGPIXELSX);
+ vdpi_int = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(NULL, hdc);
+
+ hpoints = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+ vpoints = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+
+ hpix = MulDiv(hpoints, hdpi_int, 96);
+ vpix = MulDiv(vpoints, vdpi_int, 96);
+
+ hinches = (float)hpoints / 96.0f;
+ vinches = (float)vpoints / 96.0f;
+
+ hdpi = (float)hdpi_int;
+ vdpi = (float)vdpi_int;
+ ddpi = SDL_ComputeDiagonalDPI(hpix, vpix, hinches, vinches);
+ }
+
+ if (ddpi_out) {
+ *ddpi_out = ddpi;
+ }
+ if (hdpi_out) {
+ *hdpi_out = hdpi;
+ }
+ if (vdpi_out) {
+ *vdpi_out = vdpi;
+ }
+
+ return ddpi != 0.0f ? 0 : SDL_SetError("Couldn't get DPI");
+}
+
+int
+WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ const SDL_DisplayData *data = (const SDL_DisplayData *)display->driverdata;
+ MONITORINFO minfo;
+ BOOL rc;
+
+ SDL_zero(minfo);
+ minfo.cbSize = sizeof(MONITORINFO);
+ rc = GetMonitorInfo(data->MonitorHandle, &minfo);
+
+ if (!rc) {
+ return SDL_SetError("Couldn't find monitor data");
+ }
+
+ rect->x = minfo.rcWork.left;
+ rect->y = minfo.rcWork.top;
+ rect->w = minfo.rcWork.right - minfo.rcWork.left;
+ rect->h = minfo.rcWork.bottom - minfo.rcWork.top;
+
+ return 0;
+}
+
+void
+WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
+{
+ SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+ DWORD i;
+ SDL_DisplayMode mode;
+
+ for (i = 0;; ++i) {
+ if (!WIN_GetDisplayMode(_this, data->DeviceName, i, &mode)) {
+ break;
+ }
+ if (SDL_ISPIXELFORMAT_INDEXED(mode.format)) {
+ /* We don't support palettized modes now */
+ SDL_free(mode.driverdata);
+ continue;
+ }
+ if (mode.format != SDL_PIXELFORMAT_UNKNOWN) {
+ if (!SDL_AddDisplayMode(display, &mode)) {
+ SDL_free(mode.driverdata);
+ }
+ } else {
+ SDL_free(mode.driverdata);
+ }
+ }
+}
+
+int
+WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
+{
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
+ SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
+ LONG status;
+
+ if (mode->driverdata == display->desktop_mode.driverdata) {
+ status = ChangeDisplaySettingsEx(displaydata->DeviceName, NULL, NULL, CDS_FULLSCREEN, NULL);
+ } else {
+ status = ChangeDisplaySettingsEx(displaydata->DeviceName, &data->DeviceMode, NULL, CDS_FULLSCREEN, NULL);
+ }
+ if (status != DISP_CHANGE_SUCCESSFUL) {
+ const char *reason = "Unknown reason";
+ switch (status) {
+ case DISP_CHANGE_BADFLAGS:
+ reason = "DISP_CHANGE_BADFLAGS";
+ break;
+ case DISP_CHANGE_BADMODE:
+ reason = "DISP_CHANGE_BADMODE";
+ break;
+ case DISP_CHANGE_BADPARAM:
+ reason = "DISP_CHANGE_BADPARAM";
+ break;
+ case DISP_CHANGE_FAILED:
+ reason = "DISP_CHANGE_FAILED";
+ break;
+ }
+ return SDL_SetError("ChangeDisplaySettingsEx() failed: %s", reason);
+ }
+ EnumDisplaySettings(displaydata->DeviceName, ENUM_CURRENT_SETTINGS, &data->DeviceMode);
+ WIN_UpdateDisplayMode(_this, displaydata->DeviceName, ENUM_CURRENT_SETTINGS, mode);
+ return 0;
+}
+
+void
+WIN_QuitModes(_THIS)
+{
+ /* All fullscreen windows should have restored modes by now */
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.h
new file mode 100644
index 0000000..a5c19b7
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmodes.h
@@ -0,0 +1,47 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsmodes_h_
+#define SDL_windowsmodes_h_
+
+typedef struct
+{
+ TCHAR DeviceName[32];
+ HMONITOR MonitorHandle;
+} SDL_DisplayData;
+
+typedef struct
+{
+ DEVMODE DeviceMode;
+} SDL_DisplayModeData;
+
+extern int WIN_InitModes(_THIS);
+extern int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
+extern int WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
+extern int WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
+extern void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
+extern int WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
+extern void WIN_QuitModes(_THIS);
+
+#endif /* SDL_windowsmodes_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.c
new file mode 100644
index 0000000..eff3160
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.c
@@ -0,0 +1,320 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_assert.h"
+#include "SDL_windowsvideo.h"
+
+#include "../../events/SDL_mouse_c.h"
+
+
+HCURSOR SDL_cursor = NULL;
+
+static int rawInputEnableCount = 0;
+
+static int
+ToggleRawInput(SDL_bool enabled)
+{
+ RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */
+
+ if (enabled) {
+ rawInputEnableCount++;
+ if (rawInputEnableCount > 1) {
+ return 0; /* already done. */
+ }
+ } else {
+ if (rawInputEnableCount == 0) {
+ return 0; /* already done. */
+ }
+ rawInputEnableCount--;
+ if (rawInputEnableCount > 0) {
+ return 0; /* not time to disable yet */
+ }
+ }
+
+ if (!enabled) {
+ rawMouse.dwFlags |= RIDEV_REMOVE;
+ }
+
+ /* (Un)register raw input for mice */
+ if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) {
+
+ /* Only return an error when registering. If we unregister and fail,
+ then it's probably that we unregistered twice. That's OK. */
+ if (enabled) {
+ return SDL_Unsupported();
+ }
+ }
+ return 0;
+}
+
+
+static SDL_Cursor *
+WIN_CreateDefaultCursor()
+{
+ SDL_Cursor *cursor;
+
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ cursor->driverdata = LoadCursor(NULL, IDC_ARROW);
+ } else {
+ SDL_OutOfMemory();
+ }
+
+ return cursor;
+}
+
+static SDL_Cursor *
+WIN_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
+{
+ /* msdn says cursor mask has to be padded out to word alignment. Not sure
+ if that means machine word or WORD, but this handles either case. */
+ const size_t pad = (sizeof (size_t) * 8); /* 32 or 64, or whatever. */
+ SDL_Cursor *cursor;
+ HICON hicon;
+ HDC hdc;
+ BITMAPV4HEADER bmh;
+ LPVOID pixels;
+ LPVOID maskbits;
+ size_t maskbitslen;
+ ICONINFO ii;
+
+ SDL_zero(bmh);
+ bmh.bV4Size = sizeof(bmh);
+ bmh.bV4Width = surface->w;
+ bmh.bV4Height = -surface->h; /* Invert the image */
+ bmh.bV4Planes = 1;
+ bmh.bV4BitCount = 32;
+ bmh.bV4V4Compression = BI_BITFIELDS;
+ bmh.bV4AlphaMask = 0xFF000000;
+ bmh.bV4RedMask = 0x00FF0000;
+ bmh.bV4GreenMask = 0x0000FF00;
+ bmh.bV4BlueMask = 0x000000FF;
+
+ maskbitslen = ((surface->w + (pad - (surface->w % pad))) / 8) * surface->h;
+ maskbits = SDL_stack_alloc(Uint8,maskbitslen);
+ if (maskbits == NULL) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+
+ /* AND the cursor against full bits: no change. We already have alpha. */
+ SDL_memset(maskbits, 0xFF, maskbitslen);
+
+ hdc = GetDC(NULL);
+ SDL_zero(ii);
+ ii.fIcon = FALSE;
+ ii.xHotspot = (DWORD)hot_x;
+ ii.yHotspot = (DWORD)hot_y;
+ ii.hbmColor = CreateDIBSection(hdc, (BITMAPINFO*)&bmh, DIB_RGB_COLORS, &pixels, NULL, 0);
+ ii.hbmMask = CreateBitmap(surface->w, surface->h, 1, 1, maskbits);
+ ReleaseDC(NULL, hdc);
+ SDL_stack_free(maskbits);
+
+ SDL_assert(surface->format->format == SDL_PIXELFORMAT_ARGB8888);
+ SDL_assert(surface->pitch == surface->w * 4);
+ SDL_memcpy(pixels, surface->pixels, surface->h * surface->pitch);
+
+ hicon = CreateIconIndirect(&ii);
+
+ DeleteObject(ii.hbmColor);
+ DeleteObject(ii.hbmMask);
+
+ if (!hicon) {
+ WIN_SetError("CreateIconIndirect()");
+ return NULL;
+ }
+
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ cursor->driverdata = hicon;
+ } else {
+ DestroyIcon(hicon);
+ SDL_OutOfMemory();
+ }
+
+ return cursor;
+}
+
+static SDL_Cursor *
+WIN_CreateSystemCursor(SDL_SystemCursor id)
+{
+ SDL_Cursor *cursor;
+ LPCTSTR name;
+
+ switch(id)
+ {
+ default:
+ SDL_assert(0);
+ return NULL;
+ case SDL_SYSTEM_CURSOR_ARROW: name = IDC_ARROW; break;
+ case SDL_SYSTEM_CURSOR_IBEAM: name = IDC_IBEAM; break;
+ case SDL_SYSTEM_CURSOR_WAIT: name = IDC_WAIT; break;
+ case SDL_SYSTEM_CURSOR_CROSSHAIR: name = IDC_CROSS; break;
+ case SDL_SYSTEM_CURSOR_WAITARROW: name = IDC_WAIT; break;
+ case SDL_SYSTEM_CURSOR_SIZENWSE: name = IDC_SIZENWSE; break;
+ case SDL_SYSTEM_CURSOR_SIZENESW: name = IDC_SIZENESW; break;
+ case SDL_SYSTEM_CURSOR_SIZEWE: name = IDC_SIZEWE; break;
+ case SDL_SYSTEM_CURSOR_SIZENS: name = IDC_SIZENS; break;
+ case SDL_SYSTEM_CURSOR_SIZEALL: name = IDC_SIZEALL; break;
+ case SDL_SYSTEM_CURSOR_NO: name = IDC_NO; break;
+ case SDL_SYSTEM_CURSOR_HAND: name = IDC_HAND; break;
+ }
+
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (cursor) {
+ HICON hicon;
+
+ hicon = LoadCursor(NULL, name);
+
+ cursor->driverdata = hicon;
+ } else {
+ SDL_OutOfMemory();
+ }
+
+ return cursor;
+}
+
+static void
+WIN_FreeCursor(SDL_Cursor * cursor)
+{
+ HICON hicon = (HICON)cursor->driverdata;
+
+ DestroyIcon(hicon);
+ SDL_free(cursor);
+}
+
+static int
+WIN_ShowCursor(SDL_Cursor * cursor)
+{
+ if (cursor) {
+ SDL_cursor = (HCURSOR)cursor->driverdata;
+ } else {
+ SDL_cursor = NULL;
+ }
+ if (SDL_GetMouseFocus() != NULL) {
+ SetCursor(SDL_cursor);
+ }
+ return 0;
+}
+
+static void
+WIN_WarpMouse(SDL_Window * window, int x, int y)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ POINT pt;
+
+ /* Don't warp the mouse while we're doing a modal interaction */
+ if (data->in_title_click || data->focus_click_pending) {
+ return;
+ }
+
+ pt.x = x;
+ pt.y = y;
+ ClientToScreen(hwnd, &pt);
+ SetCursorPos(pt.x, pt.y);
+}
+
+static int
+WIN_WarpMouseGlobal(int x, int y)
+{
+ POINT pt;
+
+ pt.x = x;
+ pt.y = y;
+ SetCursorPos(pt.x, pt.y);
+ return 0;
+}
+
+static int
+WIN_SetRelativeMouseMode(SDL_bool enabled)
+{
+ return ToggleRawInput(enabled);
+}
+
+static int
+WIN_CaptureMouse(SDL_Window *window)
+{
+ if (!window) {
+ SDL_Window *focusWin = SDL_GetKeyboardFocus();
+ if (focusWin) {
+ WIN_OnWindowEnter(SDL_GetVideoDevice(), focusWin); /* make sure WM_MOUSELEAVE messages are (re)enabled. */
+ }
+ }
+
+ /* While we were thinking of SetCapture() when designing this API in SDL,
+ we didn't count on the fact that SetCapture() only tracks while the
+ left mouse button is held down! Instead, we listen for raw mouse input
+ and manually query the mouse when it leaves the window. :/ */
+ return ToggleRawInput(window != NULL);
+}
+
+static Uint32
+WIN_GetGlobalMouseState(int *x, int *y)
+{
+ Uint32 retval = 0;
+ POINT pt = { 0, 0 };
+ GetCursorPos(&pt);
+ *x = (int) pt.x;
+ *y = (int) pt.y;
+
+ retval |= GetAsyncKeyState(VK_LBUTTON) & 0x8000 ? SDL_BUTTON_LMASK : 0;
+ retval |= GetAsyncKeyState(VK_RBUTTON) & 0x8000 ? SDL_BUTTON_RMASK : 0;
+ retval |= GetAsyncKeyState(VK_MBUTTON) & 0x8000 ? SDL_BUTTON_MMASK : 0;
+ retval |= GetAsyncKeyState(VK_XBUTTON1) & 0x8000 ? SDL_BUTTON_X1MASK : 0;
+ retval |= GetAsyncKeyState(VK_XBUTTON2) & 0x8000 ? SDL_BUTTON_X2MASK : 0;
+
+ return retval;
+}
+
+void
+WIN_InitMouse(_THIS)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ mouse->CreateCursor = WIN_CreateCursor;
+ mouse->CreateSystemCursor = WIN_CreateSystemCursor;
+ mouse->ShowCursor = WIN_ShowCursor;
+ mouse->FreeCursor = WIN_FreeCursor;
+ mouse->WarpMouse = WIN_WarpMouse;
+ mouse->WarpMouseGlobal = WIN_WarpMouseGlobal;
+ mouse->SetRelativeMouseMode = WIN_SetRelativeMouseMode;
+ mouse->CaptureMouse = WIN_CaptureMouse;
+ mouse->GetGlobalMouseState = WIN_GetGlobalMouseState;
+
+ SDL_SetDefaultCursor(WIN_CreateDefaultCursor());
+}
+
+void
+WIN_QuitMouse(_THIS)
+{
+ if (rawInputEnableCount) { /* force RAWINPUT off here. */
+ rawInputEnableCount = 1;
+ ToggleRawInput(SDL_FALSE);
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.h
new file mode 100644
index 0000000..775c32c
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsmouse.h
@@ -0,0 +1,33 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsmouse_h_
+#define SDL_windowsmouse_h_
+
+extern HCURSOR SDL_cursor;
+
+extern void WIN_InitMouse(_THIS);
+extern void WIN_QuitMouse(_THIS);
+
+#endif /* SDL_windowsmouse_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.c
new file mode 100644
index 0000000..c3ba56c
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.c
@@ -0,0 +1,895 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_assert.h"
+#include "SDL_loadso.h"
+#include "SDL_windowsvideo.h"
+#include "SDL_windowsopengles.h"
+#include "SDL_hints.h"
+
+/* WGL implementation of SDL OpenGL support */
+
+#if SDL_VIDEO_OPENGL_WGL
+#include "SDL_opengl.h"
+
+#define DEFAULT_OPENGL "OPENGL32.DLL"
+
+#ifndef WGL_ARB_create_context
+#define WGL_ARB_create_context
+#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
+#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
+#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
+#define WGL_CONTEXT_FLAGS_ARB 0x2094
+#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
+#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002
+
+#ifndef WGL_ARB_create_context_profile
+#define WGL_ARB_create_context_profile
+#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
+#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
+#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
+#endif
+
+#ifndef WGL_ARB_create_context_robustness
+#define WGL_ARB_create_context_robustness
+#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
+#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
+#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
+#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#endif
+#endif
+
+#ifndef WGL_EXT_create_context_es2_profile
+#define WGL_EXT_create_context_es2_profile
+#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
+#endif
+
+#ifndef WGL_EXT_create_context_es_profile
+#define WGL_EXT_create_context_es_profile
+#define WGL_CONTEXT_ES_PROFILE_BIT_EXT 0x00000004
+#endif
+
+#ifndef WGL_ARB_framebuffer_sRGB
+#define WGL_ARB_framebuffer_sRGB
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20A9
+#endif
+
+#ifndef WGL_ARB_context_flush_control
+#define WGL_ARB_context_flush_control
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0x0000
+#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
+#endif
+
+#ifndef WGL_ARB_create_context_no_error
+#define WGL_ARB_create_context_no_error
+#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31B3
+#endif
+
+typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC hDC,
+ HGLRC
+ hShareContext,
+ const int
+ *attribList);
+
+int
+WIN_GL_LoadLibrary(_THIS, const char *path)
+{
+ void *handle;
+
+ if (path == NULL) {
+ path = SDL_getenv("SDL_OPENGL_LIBRARY");
+ }
+ if (path == NULL) {
+ path = DEFAULT_OPENGL;
+ }
+ _this->gl_config.dll_handle = SDL_LoadObject(path);
+ if (!_this->gl_config.dll_handle) {
+ return -1;
+ }
+ SDL_strlcpy(_this->gl_config.driver_path, path,
+ SDL_arraysize(_this->gl_config.driver_path));
+
+ /* Allocate OpenGL memory */
+ _this->gl_data = (struct SDL_GLDriverData *) SDL_calloc(1, sizeof(struct SDL_GLDriverData));
+ if (!_this->gl_data) {
+ return SDL_OutOfMemory();
+ }
+
+ /* Load function pointers */
+ handle = _this->gl_config.dll_handle;
+ _this->gl_data->wglGetProcAddress = (void *(WINAPI *) (const char *))
+ SDL_LoadFunction(handle, "wglGetProcAddress");
+ _this->gl_data->wglCreateContext = (HGLRC(WINAPI *) (HDC))
+ SDL_LoadFunction(handle, "wglCreateContext");
+ _this->gl_data->wglDeleteContext = (BOOL(WINAPI *) (HGLRC))
+ SDL_LoadFunction(handle, "wglDeleteContext");
+ _this->gl_data->wglMakeCurrent = (BOOL(WINAPI *) (HDC, HGLRC))
+ SDL_LoadFunction(handle, "wglMakeCurrent");
+ _this->gl_data->wglShareLists = (BOOL(WINAPI *) (HGLRC, HGLRC))
+ SDL_LoadFunction(handle, "wglShareLists");
+
+ if (!_this->gl_data->wglGetProcAddress ||
+ !_this->gl_data->wglCreateContext ||
+ !_this->gl_data->wglDeleteContext ||
+ !_this->gl_data->wglMakeCurrent) {
+ return SDL_SetError("Could not retrieve OpenGL functions");
+ }
+
+ /* XXX Too sleazy? WIN_GL_InitExtensions looks for certain OpenGL
+ extensions via SDL_GL_DeduceMaxSupportedESProfile. This uses
+ SDL_GL_ExtensionSupported which in turn calls SDL_GL_GetProcAddress.
+ However SDL_GL_GetProcAddress will fail if the library is not
+ loaded; it checks for gl_config.driver_loaded > 0. To avoid this
+ test failing, increment driver_loaded around the call to
+ WIN_GLInitExtensions.
+
+ Successful loading of the library is normally indicated by
+ SDL_GL_LoadLibrary incrementing driver_loaded immediately after
+ this function returns 0 to it.
+
+ Alternatives to this are:
+ - moving SDL_GL_DeduceMaxSupportedESProfile to both the WIN and
+ X11 platforms while adding a function equivalent to
+ SDL_GL_ExtensionSupported but which directly calls
+ glGetProcAddress(). Having 3 copies of the
+ SDL_GL_ExtensionSupported makes this alternative unattractive.
+ - moving SDL_GL_DeduceMaxSupportedESProfile to a new file shared
+ by the WIN and X11 platforms while adding a function equivalent
+ to SDL_GL_ExtensionSupported. This is unattractive due to the
+ number of project files that will need updating, plus there
+ will be 2 copies of the SDL_GL_ExtensionSupported code.
+ - Add a private equivalent of SDL_GL_ExtensionSupported to
+ SDL_video.c.
+ - Move the call to WIN_GL_InitExtensions back to WIN_CreateWindow
+ and add a flag to gl_data to avoid multiple calls to this
+ expensive function. This is probably the least objectionable
+ alternative if this increment/decrement trick is unacceptable.
+
+ Note that the driver_loaded > 0 check needs to remain in
+ SDL_GL_ExtensionSupported and SDL_GL_GetProcAddress as they are
+ public API functions.
+ */
+ ++_this->gl_config.driver_loaded;
+ WIN_GL_InitExtensions(_this);
+ --_this->gl_config.driver_loaded;
+
+ return 0;
+}
+
+void *
+WIN_GL_GetProcAddress(_THIS, const char *proc)
+{
+ void *func;
+
+ /* This is to pick up extensions */
+ func = _this->gl_data->wglGetProcAddress(proc);
+ if (!func) {
+ /* This is probably a normal GL function */
+ func = GetProcAddress(_this->gl_config.dll_handle, proc);
+ }
+ return func;
+}
+
+void
+WIN_GL_UnloadLibrary(_THIS)
+{
+ SDL_UnloadObject(_this->gl_config.dll_handle);
+ _this->gl_config.dll_handle = NULL;
+
+ /* Free OpenGL memory */
+ SDL_free(_this->gl_data);
+ _this->gl_data = NULL;
+}
+
+static void
+WIN_GL_SetupPixelFormat(_THIS, PIXELFORMATDESCRIPTOR * pfd)
+{
+ SDL_zerop(pfd);
+ pfd->nSize = sizeof(*pfd);
+ pfd->nVersion = 1;
+ pfd->dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
+ if (_this->gl_config.double_buffer) {
+ pfd->dwFlags |= PFD_DOUBLEBUFFER;
+ }
+ if (_this->gl_config.stereo) {
+ pfd->dwFlags |= PFD_STEREO;
+ }
+ pfd->iLayerType = PFD_MAIN_PLANE;
+ pfd->iPixelType = PFD_TYPE_RGBA;
+ pfd->cRedBits = _this->gl_config.red_size;
+ pfd->cGreenBits = _this->gl_config.green_size;
+ pfd->cBlueBits = _this->gl_config.blue_size;
+ pfd->cAlphaBits = _this->gl_config.alpha_size;
+ if (_this->gl_config.buffer_size) {
+ pfd->cColorBits =
+ _this->gl_config.buffer_size - _this->gl_config.alpha_size;
+ } else {
+ pfd->cColorBits = (pfd->cRedBits + pfd->cGreenBits + pfd->cBlueBits);
+ }
+ pfd->cAccumRedBits = _this->gl_config.accum_red_size;
+ pfd->cAccumGreenBits = _this->gl_config.accum_green_size;
+ pfd->cAccumBlueBits = _this->gl_config.accum_blue_size;
+ pfd->cAccumAlphaBits = _this->gl_config.accum_alpha_size;
+ pfd->cAccumBits =
+ (pfd->cAccumRedBits + pfd->cAccumGreenBits + pfd->cAccumBlueBits +
+ pfd->cAccumAlphaBits);
+ pfd->cDepthBits = _this->gl_config.depth_size;
+ pfd->cStencilBits = _this->gl_config.stencil_size;
+}
+
+/* Choose the closest pixel format that meets or exceeds the target.
+ FIXME: Should we weight any particular attribute over any other?
+*/
+static int
+WIN_GL_ChoosePixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR * target)
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ int count, index, best = 0;
+ unsigned int dist, best_dist = ~0U;
+
+ count = DescribePixelFormat(hdc, 1, sizeof(pfd), NULL);
+
+ for (index = 1; index <= count; index++) {
+
+ if (!DescribePixelFormat(hdc, index, sizeof(pfd), &pfd)) {
+ continue;
+ }
+
+ if ((pfd.dwFlags & target->dwFlags) != target->dwFlags) {
+ continue;
+ }
+
+ if (pfd.iLayerType != target->iLayerType) {
+ continue;
+ }
+ if (pfd.iPixelType != target->iPixelType) {
+ continue;
+ }
+
+ dist = 0;
+
+ if (pfd.cColorBits < target->cColorBits) {
+ continue;
+ } else {
+ dist += (pfd.cColorBits - target->cColorBits);
+ }
+ if (pfd.cRedBits < target->cRedBits) {
+ continue;
+ } else {
+ dist += (pfd.cRedBits - target->cRedBits);
+ }
+ if (pfd.cGreenBits < target->cGreenBits) {
+ continue;
+ } else {
+ dist += (pfd.cGreenBits - target->cGreenBits);
+ }
+ if (pfd.cBlueBits < target->cBlueBits) {
+ continue;
+ } else {
+ dist += (pfd.cBlueBits - target->cBlueBits);
+ }
+ if (pfd.cAlphaBits < target->cAlphaBits) {
+ continue;
+ } else {
+ dist += (pfd.cAlphaBits - target->cAlphaBits);
+ }
+ if (pfd.cAccumBits < target->cAccumBits) {
+ continue;
+ } else {
+ dist += (pfd.cAccumBits - target->cAccumBits);
+ }
+ if (pfd.cAccumRedBits < target->cAccumRedBits) {
+ continue;
+ } else {
+ dist += (pfd.cAccumRedBits - target->cAccumRedBits);
+ }
+ if (pfd.cAccumGreenBits < target->cAccumGreenBits) {
+ continue;
+ } else {
+ dist += (pfd.cAccumGreenBits - target->cAccumGreenBits);
+ }
+ if (pfd.cAccumBlueBits < target->cAccumBlueBits) {
+ continue;
+ } else {
+ dist += (pfd.cAccumBlueBits - target->cAccumBlueBits);
+ }
+ if (pfd.cAccumAlphaBits < target->cAccumAlphaBits) {
+ continue;
+ } else {
+ dist += (pfd.cAccumAlphaBits - target->cAccumAlphaBits);
+ }
+ if (pfd.cDepthBits < target->cDepthBits) {
+ continue;
+ } else {
+ dist += (pfd.cDepthBits - target->cDepthBits);
+ }
+ if (pfd.cStencilBits < target->cStencilBits) {
+ continue;
+ } else {
+ dist += (pfd.cStencilBits - target->cStencilBits);
+ }
+
+ if (dist < best_dist) {
+ best = index;
+ best_dist = dist;
+ }
+ }
+
+ return best;
+}
+
+static SDL_bool
+HasExtension(const char *extension, const char *extensions)
+{
+ const char *start;
+ const char *where, *terminator;
+
+ /* Extension names should not have spaces. */
+ where = SDL_strchr(extension, ' ');
+ if (where || *extension == '\0')
+ return SDL_FALSE;
+
+ if (!extensions)
+ return SDL_FALSE;
+
+ /* It takes a bit of care to be fool-proof about parsing the
+ * OpenGL extensions string. Don't be fooled by sub-strings,
+ * etc. */
+
+ start = extensions;
+
+ for (;;) {
+ where = SDL_strstr(start, extension);
+ if (!where)
+ break;
+
+ terminator = where + SDL_strlen(extension);
+ if (where == start || *(where - 1) == ' ')
+ if (*terminator == ' ' || *terminator == '\0')
+ return SDL_TRUE;
+
+ start = terminator;
+ }
+ return SDL_FALSE;
+}
+
+void
+WIN_GL_InitExtensions(_THIS)
+{
+ const char *(WINAPI * wglGetExtensionsStringARB) (HDC) = 0;
+ const char *extensions;
+ HWND hwnd;
+ HDC hdc;
+ HGLRC hglrc;
+ PIXELFORMATDESCRIPTOR pfd;
+
+ if (!_this->gl_data) {
+ return;
+ }
+
+ hwnd =
+ CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
+ 10, 10, NULL, NULL, SDL_Instance, NULL);
+ if (!hwnd) {
+ return;
+ }
+ WIN_PumpEvents(_this);
+
+ hdc = GetDC(hwnd);
+
+ WIN_GL_SetupPixelFormat(_this, &pfd);
+
+ SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
+
+ hglrc = _this->gl_data->wglCreateContext(hdc);
+ if (!hglrc) {
+ return;
+ }
+ _this->gl_data->wglMakeCurrent(hdc, hglrc);
+
+ wglGetExtensionsStringARB = (const char *(WINAPI *) (HDC))
+ _this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
+ if (wglGetExtensionsStringARB) {
+ extensions = wglGetExtensionsStringARB(hdc);
+ } else {
+ extensions = NULL;
+ }
+
+ /* Check for WGL_ARB_pixel_format */
+ _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_FALSE;
+ if (HasExtension("WGL_ARB_pixel_format", extensions)) {
+ _this->gl_data->wglChoosePixelFormatARB = (BOOL(WINAPI *)
+ (HDC, const int *,
+ const FLOAT *, UINT,
+ int *, UINT *))
+ WIN_GL_GetProcAddress(_this, "wglChoosePixelFormatARB");
+ _this->gl_data->wglGetPixelFormatAttribivARB =
+ (BOOL(WINAPI *) (HDC, int, int, UINT, const int *, int *))
+ WIN_GL_GetProcAddress(_this, "wglGetPixelFormatAttribivARB");
+
+ if ((_this->gl_data->wglChoosePixelFormatARB != NULL) &&
+ (_this->gl_data->wglGetPixelFormatAttribivARB != NULL)) {
+ _this->gl_data->HAS_WGL_ARB_pixel_format = SDL_TRUE;
+ }
+ }
+
+ /* Check for WGL_EXT_swap_control */
+ _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_FALSE;
+ if (HasExtension("WGL_EXT_swap_control", extensions)) {
+ _this->gl_data->wglSwapIntervalEXT =
+ WIN_GL_GetProcAddress(_this, "wglSwapIntervalEXT");
+ _this->gl_data->wglGetSwapIntervalEXT =
+ WIN_GL_GetProcAddress(_this, "wglGetSwapIntervalEXT");
+ if (HasExtension("WGL_EXT_swap_control_tear", extensions)) {
+ _this->gl_data->HAS_WGL_EXT_swap_control_tear = SDL_TRUE;
+ }
+ } else {
+ _this->gl_data->wglSwapIntervalEXT = NULL;
+ _this->gl_data->wglGetSwapIntervalEXT = NULL;
+ }
+
+ /* Check for WGL_EXT_create_context_es2_profile */
+ if (HasExtension("WGL_EXT_create_context_es2_profile", extensions)) {
+ SDL_GL_DeduceMaxSupportedESProfile(
+ &_this->gl_data->es_profile_max_supported_version.major,
+ &_this->gl_data->es_profile_max_supported_version.minor
+ );
+ }
+
+ /* Check for WGL_ARB_context_flush_control */
+ if (HasExtension("WGL_ARB_context_flush_control", extensions)) {
+ _this->gl_data->HAS_WGL_ARB_context_flush_control = SDL_TRUE;
+ }
+
+ /* Check for WGL_ARB_create_context_robustness */
+ if (HasExtension("WGL_ARB_create_context_robustness", extensions)) {
+ _this->gl_data->HAS_WGL_ARB_create_context_robustness = SDL_TRUE;
+ }
+
+ /* Check for WGL_ARB_create_context_no_error */
+ if (HasExtension("WGL_ARB_create_context_no_error", extensions)) {
+ _this->gl_data->HAS_WGL_ARB_create_context_no_error = SDL_TRUE;
+ }
+
+ _this->gl_data->wglMakeCurrent(hdc, NULL);
+ _this->gl_data->wglDeleteContext(hglrc);
+ ReleaseDC(hwnd, hdc);
+ DestroyWindow(hwnd);
+ WIN_PumpEvents(_this);
+}
+
+static int
+WIN_GL_ChoosePixelFormatARB(_THIS, int *iAttribs, float *fAttribs)
+{
+ HWND hwnd;
+ HDC hdc;
+ PIXELFORMATDESCRIPTOR pfd;
+ HGLRC hglrc;
+ int pixel_format = 0;
+ unsigned int matching;
+
+ hwnd =
+ CreateWindow(SDL_Appname, SDL_Appname, (WS_POPUP | WS_DISABLED), 0, 0,
+ 10, 10, NULL, NULL, SDL_Instance, NULL);
+ WIN_PumpEvents(_this);
+
+ hdc = GetDC(hwnd);
+
+ WIN_GL_SetupPixelFormat(_this, &pfd);
+
+ SetPixelFormat(hdc, ChoosePixelFormat(hdc, &pfd), &pfd);
+
+ hglrc = _this->gl_data->wglCreateContext(hdc);
+ if (hglrc) {
+ _this->gl_data->wglMakeCurrent(hdc, hglrc);
+
+ if (_this->gl_data->HAS_WGL_ARB_pixel_format) {
+ _this->gl_data->wglChoosePixelFormatARB(hdc, iAttribs, fAttribs,
+ 1, &pixel_format,
+ &matching);
+ }
+
+ _this->gl_data->wglMakeCurrent(hdc, NULL);
+ _this->gl_data->wglDeleteContext(hglrc);
+ }
+ ReleaseDC(hwnd, hdc);
+ DestroyWindow(hwnd);
+ WIN_PumpEvents(_this);
+
+ return pixel_format;
+}
+
+/* actual work of WIN_GL_SetupWindow() happens here. */
+static int
+WIN_GL_SetupWindowInternal(_THIS, SDL_Window * window)
+{
+ HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
+ PIXELFORMATDESCRIPTOR pfd;
+ int pixel_format = 0;
+ int iAttribs[64];
+ int *iAttr;
+ int *iAccelAttr;
+ float fAttribs[1] = { 0 };
+
+ WIN_GL_SetupPixelFormat(_this, &pfd);
+
+ /* setup WGL_ARB_pixel_format attribs */
+ iAttr = &iAttribs[0];
+
+ *iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
+ *iAttr++ = GL_TRUE;
+ *iAttr++ = WGL_RED_BITS_ARB;
+ *iAttr++ = _this->gl_config.red_size;
+ *iAttr++ = WGL_GREEN_BITS_ARB;
+ *iAttr++ = _this->gl_config.green_size;
+ *iAttr++ = WGL_BLUE_BITS_ARB;
+ *iAttr++ = _this->gl_config.blue_size;
+
+ if (_this->gl_config.alpha_size) {
+ *iAttr++ = WGL_ALPHA_BITS_ARB;
+ *iAttr++ = _this->gl_config.alpha_size;
+ }
+
+ *iAttr++ = WGL_DOUBLE_BUFFER_ARB;
+ *iAttr++ = _this->gl_config.double_buffer;
+
+ *iAttr++ = WGL_DEPTH_BITS_ARB;
+ *iAttr++ = _this->gl_config.depth_size;
+
+ if (_this->gl_config.stencil_size) {
+ *iAttr++ = WGL_STENCIL_BITS_ARB;
+ *iAttr++ = _this->gl_config.stencil_size;
+ }
+
+ if (_this->gl_config.accum_red_size) {
+ *iAttr++ = WGL_ACCUM_RED_BITS_ARB;
+ *iAttr++ = _this->gl_config.accum_red_size;
+ }
+
+ if (_this->gl_config.accum_green_size) {
+ *iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
+ *iAttr++ = _this->gl_config.accum_green_size;
+ }
+
+ if (_this->gl_config.accum_blue_size) {
+ *iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
+ *iAttr++ = _this->gl_config.accum_blue_size;
+ }
+
+ if (_this->gl_config.accum_alpha_size) {
+ *iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
+ *iAttr++ = _this->gl_config.accum_alpha_size;
+ }
+
+ if (_this->gl_config.stereo) {
+ *iAttr++ = WGL_STEREO_ARB;
+ *iAttr++ = GL_TRUE;
+ }
+
+ if (_this->gl_config.multisamplebuffers) {
+ *iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
+ *iAttr++ = _this->gl_config.multisamplebuffers;
+ }
+
+ if (_this->gl_config.multisamplesamples) {
+ *iAttr++ = WGL_SAMPLES_ARB;
+ *iAttr++ = _this->gl_config.multisamplesamples;
+ }
+
+ if (_this->gl_config.framebuffer_srgb_capable) {
+ *iAttr++ = WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB;
+ *iAttr++ = _this->gl_config.framebuffer_srgb_capable;
+ }
+
+ /* We always choose either FULL or NO accel on Windows, because of flaky
+ drivers. If the app didn't specify, we use FULL, because that's
+ probably what they wanted (and if you didn't care and got FULL, that's
+ a perfectly valid result in any case). */
+ *iAttr++ = WGL_ACCELERATION_ARB;
+ iAccelAttr = iAttr;
+ if (_this->gl_config.accelerated) {
+ *iAttr++ = WGL_FULL_ACCELERATION_ARB;
+ } else {
+ *iAttr++ = WGL_NO_ACCELERATION_ARB;
+ }
+
+ *iAttr = 0;
+
+ /* Choose and set the closest available pixel format */
+ pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
+
+ /* App said "don't care about accel" and FULL accel failed. Try NO. */
+ if ( ( !pixel_format ) && ( _this->gl_config.accelerated < 0 ) ) {
+ *iAccelAttr = WGL_NO_ACCELERATION_ARB;
+ pixel_format = WIN_GL_ChoosePixelFormatARB(_this, iAttribs, fAttribs);
+ *iAccelAttr = WGL_FULL_ACCELERATION_ARB; /* if we try again. */
+ }
+ if (!pixel_format) {
+ pixel_format = WIN_GL_ChoosePixelFormat(hdc, &pfd);
+ }
+ if (!pixel_format) {
+ return SDL_SetError("No matching GL pixel format available");
+ }
+ if (!SetPixelFormat(hdc, pixel_format, &pfd)) {
+ return WIN_SetError("SetPixelFormat()");
+ }
+ return 0;
+}
+
+int
+WIN_GL_SetupWindow(_THIS, SDL_Window * window)
+{
+ /* The current context is lost in here; save it and reset it. */
+ SDL_Window *current_win = SDL_GL_GetCurrentWindow();
+ SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
+ const int retval = WIN_GL_SetupWindowInternal(_this, window);
+ WIN_GL_MakeCurrent(_this, current_win, current_ctx);
+ return retval;
+}
+
+SDL_bool
+WIN_GL_UseEGL(_THIS)
+{
+ SDL_assert(_this->gl_data != NULL);
+ SDL_assert(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES);
+
+ return (SDL_GetHintBoolean(SDL_HINT_OPENGL_ES_DRIVER, SDL_FALSE)
+ || _this->gl_config.major_version == 1 /* No WGL extension for OpenGL ES 1.x profiles. */
+ || _this->gl_config.major_version > _this->gl_data->es_profile_max_supported_version.major
+ || (_this->gl_config.major_version == _this->gl_data->es_profile_max_supported_version.major
+ && _this->gl_config.minor_version > _this->gl_data->es_profile_max_supported_version.minor));
+}
+
+SDL_GLContext
+WIN_GL_CreateContext(_THIS, SDL_Window * window)
+{
+ HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
+ HGLRC context, share_context;
+
+ if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES && WIN_GL_UseEGL(_this)) {
+#if SDL_VIDEO_OPENGL_EGL
+ /* Switch to EGL based functions */
+ WIN_GL_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = WIN_GLES_LoadLibrary;
+ _this->GL_GetProcAddress = WIN_GLES_GetProcAddress;
+ _this->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
+ _this->GL_CreateContext = WIN_GLES_CreateContext;
+ _this->GL_MakeCurrent = WIN_GLES_MakeCurrent;
+ _this->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
+ _this->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
+ _this->GL_SwapWindow = WIN_GLES_SwapWindow;
+ _this->GL_DeleteContext = WIN_GLES_DeleteContext;
+
+ if (WIN_GLES_LoadLibrary(_this, NULL) != 0) {
+ return NULL;
+ }
+
+ return WIN_GLES_CreateContext(_this, window);
+#else
+ SDL_SetError("SDL not configured with EGL support");
+ return NULL;
+#endif
+ }
+
+ if (_this->gl_config.share_with_current_context) {
+ share_context = (HGLRC)SDL_GL_GetCurrentContext();
+ } else {
+ share_context = 0;
+ }
+
+ if (_this->gl_config.major_version < 3 &&
+ _this->gl_config.profile_mask == 0 &&
+ _this->gl_config.flags == 0) {
+ /* Create legacy context */
+ context = _this->gl_data->wglCreateContext(hdc);
+ if( share_context != 0 ) {
+ _this->gl_data->wglShareLists(share_context, context);
+ }
+ } else {
+ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB;
+ HGLRC temp_context = _this->gl_data->wglCreateContext(hdc);
+ if (!temp_context) {
+ SDL_SetError("Could not create GL context");
+ return NULL;
+ }
+
+ /* Make the context current */
+ if (WIN_GL_MakeCurrent(_this, window, temp_context) < 0) {
+ WIN_GL_DeleteContext(_this, temp_context);
+ return NULL;
+ }
+
+ wglCreateContextAttribsARB =
+ (PFNWGLCREATECONTEXTATTRIBSARBPROC) _this->gl_data->
+ wglGetProcAddress("wglCreateContextAttribsARB");
+ if (!wglCreateContextAttribsARB) {
+ SDL_SetError("GL 3.x is not supported");
+ context = temp_context;
+ } else {
+ int attribs[15]; /* max 14 attributes plus terminator */
+ int iattr = 0;
+
+ attribs[iattr++] = WGL_CONTEXT_MAJOR_VERSION_ARB;
+ attribs[iattr++] = _this->gl_config.major_version;
+ attribs[iattr++] = WGL_CONTEXT_MINOR_VERSION_ARB;
+ attribs[iattr++] = _this->gl_config.minor_version;
+
+ /* SDL profile bits match WGL profile bits */
+ if (_this->gl_config.profile_mask != 0) {
+ attribs[iattr++] = WGL_CONTEXT_PROFILE_MASK_ARB;
+ attribs[iattr++] = _this->gl_config.profile_mask;
+ }
+
+ /* SDL flags match WGL flags */
+ if (_this->gl_config.flags != 0) {
+ attribs[iattr++] = WGL_CONTEXT_FLAGS_ARB;
+ attribs[iattr++] = _this->gl_config.flags;
+ }
+
+ /* only set if wgl extension is available */
+ if (_this->gl_data->HAS_WGL_ARB_context_flush_control) {
+ attribs[iattr++] = WGL_CONTEXT_RELEASE_BEHAVIOR_ARB;
+ attribs[iattr++] = _this->gl_config.release_behavior ?
+ WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB :
+ WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB;
+ }
+
+ /* only set if wgl extension is available */
+ if (_this->gl_data->HAS_WGL_ARB_create_context_robustness) {
+ attribs[iattr++] = WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB;
+ attribs[iattr++] = _this->gl_config.reset_notification ?
+ WGL_LOSE_CONTEXT_ON_RESET_ARB :
+ WGL_NO_RESET_NOTIFICATION_ARB;
+ }
+
+ /* only set if wgl extension is available */
+ if (_this->gl_data->HAS_WGL_ARB_create_context_no_error) {
+ attribs[iattr++] = WGL_CONTEXT_OPENGL_NO_ERROR_ARB;
+ attribs[iattr++] = _this->gl_config.no_error;
+ }
+
+ attribs[iattr++] = 0;
+
+ /* Create the GL 3.x context */
+ context = wglCreateContextAttribsARB(hdc, share_context, attribs);
+ /* Delete the GL 2.x context */
+ _this->gl_data->wglDeleteContext(temp_context);
+ }
+ }
+
+ if (!context) {
+ WIN_SetError("Could not create GL context");
+ return NULL;
+ }
+
+ if (WIN_GL_MakeCurrent(_this, window, context) < 0) {
+ WIN_GL_DeleteContext(_this, context);
+ return NULL;
+ }
+
+ return context;
+}
+
+int
+WIN_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
+{
+ HDC hdc;
+
+ if (!_this->gl_data) {
+ return SDL_SetError("OpenGL not initialized");
+ }
+
+ /* sanity check that higher level handled this. */
+ SDL_assert(window || (!window && !context));
+
+ /* Some Windows drivers freak out if hdc is NULL, even when context is
+ NULL, against spec. Since hdc is _supposed_ to be ignored if context
+ is NULL, we either use the current GL window, or do nothing if we
+ already have no current context. */
+ if (!window) {
+ window = SDL_GL_GetCurrentWindow();
+ if (!window) {
+ SDL_assert(SDL_GL_GetCurrentContext() == NULL);
+ return 0; /* already done. */
+ }
+ }
+
+ hdc = ((SDL_WindowData *) window->driverdata)->hdc;
+ if (!_this->gl_data->wglMakeCurrent(hdc, (HGLRC) context)) {
+ return WIN_SetError("wglMakeCurrent()");
+ }
+ return 0;
+}
+
+int
+WIN_GL_SetSwapInterval(_THIS, int interval)
+{
+ if ((interval < 0) && (!_this->gl_data->HAS_WGL_EXT_swap_control_tear)) {
+ return SDL_SetError("Negative swap interval unsupported in this GL");
+ } else if (_this->gl_data->wglSwapIntervalEXT) {
+ if (_this->gl_data->wglSwapIntervalEXT(interval) != TRUE) {
+ return WIN_SetError("wglSwapIntervalEXT()");
+ }
+ } else {
+ return SDL_Unsupported();
+ }
+ return 0;
+}
+
+int
+WIN_GL_GetSwapInterval(_THIS)
+{
+ int retval = 0;
+ if (_this->gl_data->wglGetSwapIntervalEXT) {
+ retval = _this->gl_data->wglGetSwapIntervalEXT();
+ }
+ return retval;
+}
+
+int
+WIN_GL_SwapWindow(_THIS, SDL_Window * window)
+{
+ HDC hdc = ((SDL_WindowData *) window->driverdata)->hdc;
+
+ if (!SwapBuffers(hdc)) {
+ return WIN_SetError("SwapBuffers()");
+ }
+ return 0;
+}
+
+void
+WIN_GL_DeleteContext(_THIS, SDL_GLContext context)
+{
+ if (!_this->gl_data) {
+ return;
+ }
+ _this->gl_data->wglDeleteContext((HGLRC) context);
+}
+
+
+SDL_bool
+WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow)
+{
+ HDC hfromdc = ((SDL_WindowData *) fromWindow->driverdata)->hdc;
+ HDC htodc = ((SDL_WindowData *) toWindow->driverdata)->hdc;
+ BOOL result;
+
+ /* get the pixel format of the fromWindow */
+ int pixel_format = GetPixelFormat(hfromdc);
+ PIXELFORMATDESCRIPTOR pfd;
+ SDL_memset(&pfd, 0, sizeof(pfd));
+ DescribePixelFormat(hfromdc, pixel_format, sizeof(pfd), &pfd);
+
+ /* set the pixel format of the toWindow */
+ result = SetPixelFormat(htodc, pixel_format, &pfd);
+
+ return result ? SDL_TRUE : SDL_FALSE;
+}
+
+#endif /* SDL_VIDEO_OPENGL_WGL */
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.h
new file mode 100644
index 0000000..8704411
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengl.h
@@ -0,0 +1,142 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsopengl_h_
+#define SDL_windowsopengl_h_
+
+#if SDL_VIDEO_OPENGL_WGL
+
+struct SDL_GLDriverData
+{
+ SDL_bool HAS_WGL_ARB_pixel_format;
+ SDL_bool HAS_WGL_EXT_swap_control_tear;
+ SDL_bool HAS_WGL_ARB_context_flush_control;
+ SDL_bool HAS_WGL_ARB_create_context_robustness;
+ SDL_bool HAS_WGL_ARB_create_context_no_error;
+
+ /* Max version of OpenGL ES context that can be created if the
+ implementation supports WGL_EXT_create_context_es2_profile.
+ major = minor = 0 when unsupported.
+ */
+ struct {
+ int major;
+ int minor;
+ } es_profile_max_supported_version;
+
+ void *(WINAPI * wglGetProcAddress) (const char *proc);
+ HGLRC(WINAPI * wglCreateContext) (HDC hdc);
+ BOOL(WINAPI * wglDeleteContext) (HGLRC hglrc);
+ BOOL(WINAPI * wglMakeCurrent) (HDC hdc, HGLRC hglrc);
+ BOOL(WINAPI * wglShareLists) (HGLRC hglrc1, HGLRC hglrc2);
+ BOOL(WINAPI * wglChoosePixelFormatARB) (HDC hdc,
+ const int *piAttribIList,
+ const FLOAT * pfAttribFList,
+ UINT nMaxFormats,
+ int *piFormats,
+ UINT * nNumFormats);
+ BOOL(WINAPI * wglGetPixelFormatAttribivARB) (HDC hdc, int iPixelFormat,
+ int iLayerPlane,
+ UINT nAttributes,
+ const int *piAttributes,
+ int *piValues);
+ BOOL (WINAPI * wglSwapIntervalEXT) (int interval);
+ int (WINAPI * wglGetSwapIntervalEXT) (void);
+};
+
+/* OpenGL functions */
+extern int WIN_GL_LoadLibrary(_THIS, const char *path);
+extern void *WIN_GL_GetProcAddress(_THIS, const char *proc);
+extern void WIN_GL_UnloadLibrary(_THIS);
+extern SDL_bool WIN_GL_UseEGL(_THIS);
+extern int WIN_GL_SetupWindow(_THIS, SDL_Window * window);
+extern SDL_GLContext WIN_GL_CreateContext(_THIS, SDL_Window * window);
+extern int WIN_GL_MakeCurrent(_THIS, SDL_Window * window,
+ SDL_GLContext context);
+extern int WIN_GL_SetSwapInterval(_THIS, int interval);
+extern int WIN_GL_GetSwapInterval(_THIS);
+extern int WIN_GL_SwapWindow(_THIS, SDL_Window * window);
+extern void WIN_GL_DeleteContext(_THIS, SDL_GLContext context);
+extern void WIN_GL_InitExtensions(_THIS);
+extern SDL_bool WIN_GL_SetPixelFormatFrom(_THIS, SDL_Window * fromWindow, SDL_Window * toWindow);
+
+#ifndef WGL_ARB_pixel_format
+#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
+#define WGL_DRAW_TO_WINDOW_ARB 0x2001
+#define WGL_DRAW_TO_BITMAP_ARB 0x2002
+#define WGL_ACCELERATION_ARB 0x2003
+#define WGL_NEED_PALETTE_ARB 0x2004
+#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005
+#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006
+#define WGL_SWAP_METHOD_ARB 0x2007
+#define WGL_NUMBER_OVERLAYS_ARB 0x2008
+#define WGL_NUMBER_UNDERLAYS_ARB 0x2009
+#define WGL_TRANSPARENT_ARB 0x200A
+#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037
+#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038
+#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039
+#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A
+#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B
+#define WGL_SHARE_DEPTH_ARB 0x200C
+#define WGL_SHARE_STENCIL_ARB 0x200D
+#define WGL_SHARE_ACCUM_ARB 0x200E
+#define WGL_SUPPORT_GDI_ARB 0x200F
+#define WGL_SUPPORT_OPENGL_ARB 0x2010
+#define WGL_DOUBLE_BUFFER_ARB 0x2011
+#define WGL_STEREO_ARB 0x2012
+#define WGL_PIXEL_TYPE_ARB 0x2013
+#define WGL_COLOR_BITS_ARB 0x2014
+#define WGL_RED_BITS_ARB 0x2015
+#define WGL_RED_SHIFT_ARB 0x2016
+#define WGL_GREEN_BITS_ARB 0x2017
+#define WGL_GREEN_SHIFT_ARB 0x2018
+#define WGL_BLUE_BITS_ARB 0x2019
+#define WGL_BLUE_SHIFT_ARB 0x201A
+#define WGL_ALPHA_BITS_ARB 0x201B
+#define WGL_ALPHA_SHIFT_ARB 0x201C
+#define WGL_ACCUM_BITS_ARB 0x201D
+#define WGL_ACCUM_RED_BITS_ARB 0x201E
+#define WGL_ACCUM_GREEN_BITS_ARB 0x201F
+#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
+#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
+#define WGL_DEPTH_BITS_ARB 0x2022
+#define WGL_STENCIL_BITS_ARB 0x2023
+#define WGL_AUX_BUFFERS_ARB 0x2024
+#define WGL_NO_ACCELERATION_ARB 0x2025
+#define WGL_GENERIC_ACCELERATION_ARB 0x2026
+#define WGL_FULL_ACCELERATION_ARB 0x2027
+#define WGL_SWAP_EXCHANGE_ARB 0x2028
+#define WGL_SWAP_COPY_ARB 0x2029
+#define WGL_SWAP_UNDEFINED_ARB 0x202A
+#define WGL_TYPE_RGBA_ARB 0x202B
+#define WGL_TYPE_COLORINDEX_ARB 0x202C
+#endif
+
+#ifndef WGL_ARB_multisample
+#define WGL_SAMPLE_BUFFERS_ARB 0x2041
+#define WGL_SAMPLES_ARB 0x2042
+#endif
+
+#endif /* SDL_VIDEO_OPENGL_WGL */
+
+#endif /* SDL_windowsopengl_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.c
new file mode 100644
index 0000000..0ff61c3
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.c
@@ -0,0 +1,131 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS && SDL_VIDEO_OPENGL_EGL
+
+#include "SDL_windowsvideo.h"
+#include "SDL_windowsopengles.h"
+#include "SDL_windowsopengl.h"
+#include "SDL_log.h"
+
+/* EGL implementation of SDL OpenGL support */
+
+int
+WIN_GLES_LoadLibrary(_THIS, const char *path) {
+
+ /* If the profile requested is not GL ES, switch over to WIN_GL functions */
+ if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
+#if SDL_VIDEO_OPENGL_WGL
+ WIN_GLES_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = WIN_GL_LoadLibrary;
+ _this->GL_GetProcAddress = WIN_GL_GetProcAddress;
+ _this->GL_UnloadLibrary = WIN_GL_UnloadLibrary;
+ _this->GL_CreateContext = WIN_GL_CreateContext;
+ _this->GL_MakeCurrent = WIN_GL_MakeCurrent;
+ _this->GL_SetSwapInterval = WIN_GL_SetSwapInterval;
+ _this->GL_GetSwapInterval = WIN_GL_GetSwapInterval;
+ _this->GL_SwapWindow = WIN_GL_SwapWindow;
+ _this->GL_DeleteContext = WIN_GL_DeleteContext;
+ return WIN_GL_LoadLibrary(_this, path);
+#else
+ return SDL_SetError("SDL not configured with OpenGL/WGL support");
+#endif
+ }
+
+ if (_this->egl_data == NULL) {
+ return SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0);
+ }
+
+ return 0;
+}
+
+SDL_GLContext
+WIN_GLES_CreateContext(_THIS, SDL_Window * window)
+{
+ SDL_GLContext context;
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+
+#if SDL_VIDEO_OPENGL_WGL
+ if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) {
+ /* Switch to WGL based functions */
+ WIN_GLES_UnloadLibrary(_this);
+ _this->GL_LoadLibrary = WIN_GL_LoadLibrary;
+ _this->GL_GetProcAddress = WIN_GL_GetProcAddress;
+ _this->GL_UnloadLibrary = WIN_GL_UnloadLibrary;
+ _this->GL_CreateContext = WIN_GL_CreateContext;
+ _this->GL_MakeCurrent = WIN_GL_MakeCurrent;
+ _this->GL_SetSwapInterval = WIN_GL_SetSwapInterval;
+ _this->GL_GetSwapInterval = WIN_GL_GetSwapInterval;
+ _this->GL_SwapWindow = WIN_GL_SwapWindow;
+ _this->GL_DeleteContext = WIN_GL_DeleteContext;
+
+ if (WIN_GL_LoadLibrary(_this, NULL) != 0) {
+ return NULL;
+ }
+
+ return WIN_GL_CreateContext(_this, window);
+ }
+#endif
+
+ context = SDL_EGL_CreateContext(_this, data->egl_surface);
+ return context;
+}
+
+void
+WIN_GLES_DeleteContext(_THIS, SDL_GLContext context)
+{
+ SDL_EGL_DeleteContext(_this, context);
+ WIN_GLES_UnloadLibrary(_this);
+}
+
+SDL_EGL_SwapWindow_impl(WIN)
+SDL_EGL_MakeCurrent_impl(WIN)
+
+int
+WIN_GLES_SetupWindow(_THIS, SDL_Window * window)
+{
+ /* The current context is lost in here; save it and reset it. */
+ SDL_WindowData *windowdata = (SDL_WindowData *) window->driverdata;
+ SDL_Window *current_win = SDL_GL_GetCurrentWindow();
+ SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
+
+
+ if (_this->egl_data == NULL) {
+ if (SDL_EGL_LoadLibrary(_this, NULL, EGL_DEFAULT_DISPLAY, 0) < 0) {
+ SDL_EGL_UnloadLibrary(_this);
+ return -1;
+ }
+ }
+
+ /* Create the GLES window surface */
+ windowdata->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType)windowdata->hwnd);
+
+ if (windowdata->egl_surface == EGL_NO_SURFACE) {
+ return SDL_SetError("Could not create GLES window surface");
+ }
+
+ return WIN_GLES_MakeCurrent(_this, current_win, current_ctx);
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS && SDL_VIDEO_OPENGL_EGL */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.h
new file mode 100644
index 0000000..8684429
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsopengles.h
@@ -0,0 +1,49 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_winopengles_h_
+#define SDL_winopengles_h_
+
+#if SDL_VIDEO_OPENGL_EGL
+
+#include "../SDL_sysvideo.h"
+#include "../SDL_egl_c.h"
+
+/* OpenGLES functions */
+#define WIN_GLES_GetAttribute SDL_EGL_GetAttribute
+#define WIN_GLES_GetProcAddress SDL_EGL_GetProcAddress
+#define WIN_GLES_UnloadLibrary SDL_EGL_UnloadLibrary
+#define WIN_GLES_GetSwapInterval SDL_EGL_GetSwapInterval
+#define WIN_GLES_SetSwapInterval SDL_EGL_SetSwapInterval
+
+extern int WIN_GLES_LoadLibrary(_THIS, const char *path);
+extern SDL_GLContext WIN_GLES_CreateContext(_THIS, SDL_Window * window);
+extern int WIN_GLES_SwapWindow(_THIS, SDL_Window * window);
+extern int WIN_GLES_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context);
+extern void WIN_GLES_DeleteContext(_THIS, SDL_GLContext context);
+extern int WIN_GLES_SetupWindow(_THIS, SDL_Window * window);
+
+#endif /* SDL_VIDEO_OPENGL_EGL */
+
+#endif /* SDL_winopengles_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.c
new file mode 100644
index 0000000..bed4588
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.c
@@ -0,0 +1,110 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_assert.h"
+#include "SDL_windowsshape.h"
+#include "SDL_windowsvideo.h"
+
+SDL_WindowShaper*
+Win32_CreateShaper(SDL_Window * window) {
+ int resized_properly;
+ SDL_WindowShaper* result = (SDL_WindowShaper *)SDL_malloc(sizeof(SDL_WindowShaper));
+ result->window = window;
+ result->mode.mode = ShapeModeDefault;
+ result->mode.parameters.binarizationCutoff = 1;
+ result->userx = result->usery = 0;
+ result->driverdata = (SDL_ShapeData*)SDL_malloc(sizeof(SDL_ShapeData));
+ ((SDL_ShapeData*)result->driverdata)->mask_tree = NULL;
+ /* Put some driver-data here. */
+ window->shaper = result;
+ resized_properly = Win32_ResizeWindowShape(window);
+ if (resized_properly != 0)
+ return NULL;
+
+ return result;
+}
+
+static void
+CombineRectRegions(SDL_ShapeTree* node,void* closure) {
+ HRGN mask_region = *((HRGN*)closure),temp_region = NULL;
+ if(node->kind == OpaqueShape) {
+ /* Win32 API regions exclude their outline, so we widen the region by one pixel in each direction to include the real outline. */
+ temp_region = CreateRectRgn(node->data.shape.x,node->data.shape.y,node->data.shape.x + node->data.shape.w + 1,node->data.shape.y + node->data.shape.h + 1);
+ if(mask_region != NULL) {
+ CombineRgn(mask_region,mask_region,temp_region,RGN_OR);
+ DeleteObject(temp_region);
+ }
+ else
+ *((HRGN*)closure) = temp_region;
+ }
+}
+
+int
+Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode) {
+ SDL_ShapeData *data;
+ HRGN mask_region = NULL;
+
+ if( (shaper == NULL) ||
+ (shape == NULL) ||
+ ((shape->format->Amask == 0) && (shape_mode->mode != ShapeModeColorKey)) ||
+ (shape->w != shaper->window->w) ||
+ (shape->h != shaper->window->h) ) {
+ return SDL_INVALID_SHAPE_ARGUMENT;
+ }
+
+ data = (SDL_ShapeData*)shaper->driverdata;
+ if(data->mask_tree != NULL)
+ SDL_FreeShapeTree(&data->mask_tree);
+ data->mask_tree = SDL_CalculateShapeTree(*shape_mode,shape);
+
+ SDL_TraverseShapeTree(data->mask_tree,&CombineRectRegions,&mask_region);
+ SDL_assert(mask_region != NULL);
+
+ SetWindowRgn(((SDL_WindowData *)(shaper->window->driverdata))->hwnd, mask_region, TRUE);
+
+ return 0;
+}
+
+int
+Win32_ResizeWindowShape(SDL_Window *window) {
+ SDL_ShapeData* data;
+
+ if (window == NULL)
+ return -1;
+ data = (SDL_ShapeData *)window->shaper->driverdata;
+ if (data == NULL)
+ return -1;
+
+ if(data->mask_tree != NULL)
+ SDL_FreeShapeTree(&data->mask_tree);
+ if(window->shaper->hasshape == SDL_TRUE) {
+ window->shaper->userx = window->x;
+ window->shaper->usery = window->y;
+ SDL_SetWindowPosition(window,-1000,-1000);
+ }
+
+ return 0;
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.h
new file mode 100644
index 0000000..eb1a887
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsshape.h
@@ -0,0 +1,40 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsshape_h_
+#define SDL_windowsshape_h_
+
+#include "SDL_video.h"
+#include "SDL_shape.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_shape_internals.h"
+
+typedef struct {
+ SDL_ShapeTree *mask_tree;
+} SDL_ShapeData;
+
+extern SDL_WindowShaper* Win32_CreateShaper(SDL_Window * window);
+extern int Win32_SetWindowShape(SDL_WindowShaper *shaper,SDL_Surface *shape,SDL_WindowShapeMode *shape_mode);
+extern int Win32_ResizeWindowShape(SDL_Window *window);
+
+#endif /* SDL_windowsshape_h_ */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowstaskdialog.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowstaskdialog.h
new file mode 100644
index 0000000..a2a9e8a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowstaskdialog.h
@@ -0,0 +1,156 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include <pshpack1.h>
+
+typedef HRESULT(CALLBACK *PFTASKDIALOGCALLBACK)(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, LONG_PTR lpRefData);
+
+enum _TASKDIALOG_FLAGS
+{
+ TDF_ENABLE_HYPERLINKS = 0x0001,
+ TDF_USE_HICON_MAIN = 0x0002,
+ TDF_USE_HICON_FOOTER = 0x0004,
+ TDF_ALLOW_DIALOG_CANCELLATION = 0x0008,
+ TDF_USE_COMMAND_LINKS = 0x0010,
+ TDF_USE_COMMAND_LINKS_NO_ICON = 0x0020,
+ TDF_EXPAND_FOOTER_AREA = 0x0040,
+ TDF_EXPANDED_BY_DEFAULT = 0x0080,
+ TDF_VERIFICATION_FLAG_CHECKED = 0x0100,
+ TDF_SHOW_PROGRESS_BAR = 0x0200,
+ TDF_SHOW_MARQUEE_PROGRESS_BAR = 0x0400,
+ TDF_CALLBACK_TIMER = 0x0800,
+ TDF_POSITION_RELATIVE_TO_WINDOW = 0x1000,
+ TDF_RTL_LAYOUT = 0x2000,
+ TDF_NO_DEFAULT_RADIO_BUTTON = 0x4000,
+ TDF_CAN_BE_MINIMIZED = 0x8000,
+ //#if (NTDDI_VERSION >= NTDDI_WIN8)
+ TDF_NO_SET_FOREGROUND = 0x00010000, // Don't call SetForegroundWindow() when activating the dialog
+ //#endif // (NTDDI_VERSION >= NTDDI_WIN8)
+ TDF_SIZE_TO_CONTENT = 0x01000000 // used by ShellMessageBox to emulate MessageBox sizing behavior
+};
+typedef int TASKDIALOG_FLAGS; // Note: _TASKDIALOG_FLAGS is an int
+
+typedef enum _TASKDIALOG_MESSAGES
+{
+ TDM_NAVIGATE_PAGE = WM_USER + 101,
+ TDM_CLICK_BUTTON = WM_USER + 102, // wParam = Button ID
+ TDM_SET_MARQUEE_PROGRESS_BAR = WM_USER + 103, // wParam = 0 (nonMarque) wParam != 0 (Marquee)
+ TDM_SET_PROGRESS_BAR_STATE = WM_USER + 104, // wParam = new progress state
+ TDM_SET_PROGRESS_BAR_RANGE = WM_USER + 105, // lParam = MAKELPARAM(nMinRange, nMaxRange)
+ TDM_SET_PROGRESS_BAR_POS = WM_USER + 106, // wParam = new position
+ TDM_SET_PROGRESS_BAR_MARQUEE = WM_USER + 107, // wParam = 0 (stop marquee), wParam != 0 (start marquee), lparam = speed (milliseconds between repaints)
+ TDM_SET_ELEMENT_TEXT = WM_USER + 108, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
+ TDM_CLICK_RADIO_BUTTON = WM_USER + 110, // wParam = Radio Button ID
+ TDM_ENABLE_BUTTON = WM_USER + 111, // lParam = 0 (disable), lParam != 0 (enable), wParam = Button ID
+ TDM_ENABLE_RADIO_BUTTON = WM_USER + 112, // lParam = 0 (disable), lParam != 0 (enable), wParam = Radio Button ID
+ TDM_CLICK_VERIFICATION = WM_USER + 113, // wParam = 0 (unchecked), 1 (checked), lParam = 1 (set key focus)
+ TDM_UPDATE_ELEMENT_TEXT = WM_USER + 114, // wParam = element (TASKDIALOG_ELEMENTS), lParam = new element text (LPCWSTR)
+ TDM_SET_BUTTON_ELEVATION_REQUIRED_STATE = WM_USER + 115, // wParam = Button ID, lParam = 0 (elevation not required), lParam != 0 (elevation required)
+ TDM_UPDATE_ICON = WM_USER + 116 // wParam = icon element (TASKDIALOG_ICON_ELEMENTS), lParam = new icon (hIcon if TDF_USE_HICON_* was set, PCWSTR otherwise)
+} TASKDIALOG_MESSAGES;
+
+typedef enum _TASKDIALOG_NOTIFICATIONS
+{
+ TDN_CREATED = 0,
+ TDN_NAVIGATED = 1,
+ TDN_BUTTON_CLICKED = 2, // wParam = Button ID
+ TDN_HYPERLINK_CLICKED = 3, // lParam = (LPCWSTR)pszHREF
+ TDN_TIMER = 4, // wParam = Milliseconds since dialog created or timer reset
+ TDN_DESTROYED = 5,
+ TDN_RADIO_BUTTON_CLICKED = 6, // wParam = Radio Button ID
+ TDN_DIALOG_CONSTRUCTED = 7,
+ TDN_VERIFICATION_CLICKED = 8, // wParam = 1 if checkbox checked, 0 if not, lParam is unused and always 0
+ TDN_HELP = 9,
+ TDN_EXPANDO_BUTTON_CLICKED = 10 // wParam = 0 (dialog is now collapsed), wParam != 0 (dialog is now expanded)
+} TASKDIALOG_NOTIFICATIONS;
+
+typedef struct _TASKDIALOG_BUTTON
+{
+ int nButtonID;
+ PCWSTR pszButtonText;
+} TASKDIALOG_BUTTON;
+
+typedef enum _TASKDIALOG_ELEMENTS
+{
+ TDE_CONTENT,
+ TDE_EXPANDED_INFORMATION,
+ TDE_FOOTER,
+ TDE_MAIN_INSTRUCTION
+} TASKDIALOG_ELEMENTS;
+
+typedef enum _TASKDIALOG_ICON_ELEMENTS
+{
+ TDIE_ICON_MAIN,
+ TDIE_ICON_FOOTER
+} TASKDIALOG_ICON_ELEMENTS;
+
+#define TD_WARNING_ICON MAKEINTRESOURCEW(-1)
+#define TD_ERROR_ICON MAKEINTRESOURCEW(-2)
+#define TD_INFORMATION_ICON MAKEINTRESOURCEW(-3)
+#define TD_SHIELD_ICON MAKEINTRESOURCEW(-4)
+
+enum _TASKDIALOG_COMMON_BUTTON_FLAGS
+{
+ TDCBF_OK_BUTTON = 0x0001, // selected control return value IDOK
+ TDCBF_YES_BUTTON = 0x0002, // selected control return value IDYES
+ TDCBF_NO_BUTTON = 0x0004, // selected control return value IDNO
+ TDCBF_CANCEL_BUTTON = 0x0008, // selected control return value IDCANCEL
+ TDCBF_RETRY_BUTTON = 0x0010, // selected control return value IDRETRY
+ TDCBF_CLOSE_BUTTON = 0x0020 // selected control return value IDCLOSE
+};
+typedef int TASKDIALOG_COMMON_BUTTON_FLAGS; // Note: _TASKDIALOG_COMMON_BUTTON_FLAGS is an int
+
+typedef struct _TASKDIALOGCONFIG
+{
+ UINT cbSize;
+ HWND hwndParent; // incorrectly named, this is the owner window, not a parent.
+ HINSTANCE hInstance; // used for MAKEINTRESOURCE() strings
+ TASKDIALOG_FLAGS dwFlags; // TASKDIALOG_FLAGS (TDF_XXX) flags
+ TASKDIALOG_COMMON_BUTTON_FLAGS dwCommonButtons; // TASKDIALOG_COMMON_BUTTON (TDCBF_XXX) flags
+ PCWSTR pszWindowTitle; // string or MAKEINTRESOURCE()
+ union
+ {
+ HICON hMainIcon;
+ PCWSTR pszMainIcon;
+ } /*DUMMYUNIONNAME*/;
+ PCWSTR pszMainInstruction;
+ PCWSTR pszContent;
+ UINT cButtons;
+ const TASKDIALOG_BUTTON *pButtons;
+ int nDefaultButton;
+ UINT cRadioButtons;
+ const TASKDIALOG_BUTTON *pRadioButtons;
+ int nDefaultRadioButton;
+ PCWSTR pszVerificationText;
+ PCWSTR pszExpandedInformation;
+ PCWSTR pszExpandedControlText;
+ PCWSTR pszCollapsedControlText;
+ union
+ {
+ HICON hFooterIcon;
+ PCWSTR pszFooterIcon;
+ } /*DUMMYUNIONNAME2*/;
+ PCWSTR pszFooter;
+ PFTASKDIALOGCALLBACK pfCallback;
+ LONG_PTR lpCallbackData;
+ UINT cxWidth; // width of the Task Dialog's client area in DLU's. If 0, Task Dialog will calculate the ideal width.
+} TASKDIALOGCONFIG;
+
+#include <poppack.h>
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.c
new file mode 100644
index 0000000..358ab23
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.c
@@ -0,0 +1,452 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_main.h"
+#include "SDL_video.h"
+#include "SDL_hints.h"
+#include "SDL_mouse.h"
+#include "SDL_system.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+
+#include "SDL_windowsvideo.h"
+#include "SDL_windowsframebuffer.h"
+#include "SDL_windowsshape.h"
+#include "SDL_windowsvulkan.h"
+
+/* Initialization/Query functions */
+static int WIN_VideoInit(_THIS);
+static void WIN_VideoQuit(_THIS);
+
+/* Hints */
+SDL_bool g_WindowsEnableMessageLoop = SDL_TRUE;
+SDL_bool g_WindowFrameUsableWhileCursorHidden = SDL_TRUE;
+
+static void SDLCALL
+UpdateWindowsEnableMessageLoop(void *userdata, const char *name, const char *oldValue, const char *newValue)
+{
+ if (newValue && *newValue == '0') {
+ g_WindowsEnableMessageLoop = SDL_FALSE;
+ } else {
+ g_WindowsEnableMessageLoop = SDL_TRUE;
+ }
+}
+
+static void SDLCALL
+UpdateWindowFrameUsableWhileCursorHidden(void *userdata, const char *name, const char *oldValue, const char *newValue)
+{
+ if (newValue && *newValue == '0') {
+ g_WindowFrameUsableWhileCursorHidden = SDL_FALSE;
+ } else {
+ g_WindowFrameUsableWhileCursorHidden = SDL_TRUE;
+ }
+}
+
+static void WIN_SuspendScreenSaver(_THIS)
+{
+ if (_this->suspend_screensaver) {
+ SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED);
+ } else {
+ SetThreadExecutionState(ES_CONTINUOUS);
+ }
+}
+
+
+/* Windows driver bootstrap functions */
+
+static int
+WIN_Available(void)
+{
+ return (1);
+}
+
+static void
+WIN_DeleteDevice(SDL_VideoDevice * device)
+{
+ SDL_VideoData *data = (SDL_VideoData *) device->driverdata;
+
+ SDL_UnregisterApp();
+ if (data->userDLL) {
+ SDL_UnloadObject(data->userDLL);
+ }
+ if (data->shcoreDLL) {
+ SDL_UnloadObject(data->shcoreDLL);
+ }
+
+ SDL_free(device->driverdata);
+ SDL_free(device);
+}
+
+static SDL_VideoDevice *
+WIN_CreateDevice(int devindex)
+{
+ SDL_VideoDevice *device;
+ SDL_VideoData *data;
+
+ SDL_RegisterApp(NULL, 0, NULL);
+
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+ if (device) {
+ data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
+ } else {
+ data = NULL;
+ }
+ if (!data) {
+ SDL_free(device);
+ SDL_OutOfMemory();
+ return NULL;
+ }
+ device->driverdata = data;
+
+ data->userDLL = SDL_LoadObject("USER32.DLL");
+ if (data->userDLL) {
+ data->CloseTouchInputHandle = (BOOL (WINAPI *)(HTOUCHINPUT)) SDL_LoadFunction(data->userDLL, "CloseTouchInputHandle");
+ data->GetTouchInputInfo = (BOOL (WINAPI *)(HTOUCHINPUT, UINT, PTOUCHINPUT, int)) SDL_LoadFunction(data->userDLL, "GetTouchInputInfo");
+ data->RegisterTouchWindow = (BOOL (WINAPI *)(HWND, ULONG)) SDL_LoadFunction(data->userDLL, "RegisterTouchWindow");
+ } else {
+ SDL_ClearError();
+ }
+
+ data->shcoreDLL = SDL_LoadObject("SHCORE.DLL");
+ if (data->shcoreDLL) {
+ data->GetDpiForMonitor = (HRESULT (WINAPI *)(HMONITOR, MONITOR_DPI_TYPE, UINT *, UINT *)) SDL_LoadFunction(data->shcoreDLL, "GetDpiForMonitor");
+ } else {
+ SDL_ClearError();
+ }
+
+ /* Set the function pointers */
+ device->VideoInit = WIN_VideoInit;
+ device->VideoQuit = WIN_VideoQuit;
+ device->GetDisplayBounds = WIN_GetDisplayBounds;
+ device->GetDisplayUsableBounds = WIN_GetDisplayUsableBounds;
+ device->GetDisplayDPI = WIN_GetDisplayDPI;
+ device->GetDisplayModes = WIN_GetDisplayModes;
+ device->SetDisplayMode = WIN_SetDisplayMode;
+ device->PumpEvents = WIN_PumpEvents;
+ device->SuspendScreenSaver = WIN_SuspendScreenSaver;
+
+ device->CreateSDLWindow = WIN_CreateWindow;
+ device->CreateSDLWindowFrom = WIN_CreateWindowFrom;
+ device->SetWindowTitle = WIN_SetWindowTitle;
+ device->SetWindowIcon = WIN_SetWindowIcon;
+ device->SetWindowPosition = WIN_SetWindowPosition;
+ device->SetWindowSize = WIN_SetWindowSize;
+ device->GetWindowBordersSize = WIN_GetWindowBordersSize;
+ device->SetWindowOpacity = WIN_SetWindowOpacity;
+ device->ShowWindow = WIN_ShowWindow;
+ device->HideWindow = WIN_HideWindow;
+ device->RaiseWindow = WIN_RaiseWindow;
+ device->MaximizeWindow = WIN_MaximizeWindow;
+ device->MinimizeWindow = WIN_MinimizeWindow;
+ device->RestoreWindow = WIN_RestoreWindow;
+ device->SetWindowBordered = WIN_SetWindowBordered;
+ device->SetWindowResizable = WIN_SetWindowResizable;
+ device->SetWindowFullscreen = WIN_SetWindowFullscreen;
+ device->SetWindowGammaRamp = WIN_SetWindowGammaRamp;
+ device->GetWindowGammaRamp = WIN_GetWindowGammaRamp;
+ device->SetWindowGrab = WIN_SetWindowGrab;
+ device->DestroyWindow = WIN_DestroyWindow;
+ device->GetWindowWMInfo = WIN_GetWindowWMInfo;
+ device->CreateWindowFramebuffer = WIN_CreateWindowFramebuffer;
+ device->UpdateWindowFramebuffer = WIN_UpdateWindowFramebuffer;
+ device->DestroyWindowFramebuffer = WIN_DestroyWindowFramebuffer;
+ device->OnWindowEnter = WIN_OnWindowEnter;
+ device->SetWindowHitTest = WIN_SetWindowHitTest;
+ device->AcceptDragAndDrop = WIN_AcceptDragAndDrop;
+
+ device->shape_driver.CreateShaper = Win32_CreateShaper;
+ device->shape_driver.SetWindowShape = Win32_SetWindowShape;
+ device->shape_driver.ResizeWindowShape = Win32_ResizeWindowShape;
+
+#if SDL_VIDEO_OPENGL_WGL
+ device->GL_LoadLibrary = WIN_GL_LoadLibrary;
+ device->GL_GetProcAddress = WIN_GL_GetProcAddress;
+ device->GL_UnloadLibrary = WIN_GL_UnloadLibrary;
+ device->GL_CreateContext = WIN_GL_CreateContext;
+ device->GL_MakeCurrent = WIN_GL_MakeCurrent;
+ device->GL_SetSwapInterval = WIN_GL_SetSwapInterval;
+ device->GL_GetSwapInterval = WIN_GL_GetSwapInterval;
+ device->GL_SwapWindow = WIN_GL_SwapWindow;
+ device->GL_DeleteContext = WIN_GL_DeleteContext;
+#elif SDL_VIDEO_OPENGL_EGL
+ /* Use EGL based functions */
+ device->GL_LoadLibrary = WIN_GLES_LoadLibrary;
+ device->GL_GetProcAddress = WIN_GLES_GetProcAddress;
+ device->GL_UnloadLibrary = WIN_GLES_UnloadLibrary;
+ device->GL_CreateContext = WIN_GLES_CreateContext;
+ device->GL_MakeCurrent = WIN_GLES_MakeCurrent;
+ device->GL_SetSwapInterval = WIN_GLES_SetSwapInterval;
+ device->GL_GetSwapInterval = WIN_GLES_GetSwapInterval;
+ device->GL_SwapWindow = WIN_GLES_SwapWindow;
+ device->GL_DeleteContext = WIN_GLES_DeleteContext;
+#endif
+#if SDL_VIDEO_VULKAN
+ device->Vulkan_LoadLibrary = WIN_Vulkan_LoadLibrary;
+ device->Vulkan_UnloadLibrary = WIN_Vulkan_UnloadLibrary;
+ device->Vulkan_GetInstanceExtensions = WIN_Vulkan_GetInstanceExtensions;
+ device->Vulkan_CreateSurface = WIN_Vulkan_CreateSurface;
+#endif
+
+ device->StartTextInput = WIN_StartTextInput;
+ device->StopTextInput = WIN_StopTextInput;
+ device->SetTextInputRect = WIN_SetTextInputRect;
+
+ device->SetClipboardText = WIN_SetClipboardText;
+ device->GetClipboardText = WIN_GetClipboardText;
+ device->HasClipboardText = WIN_HasClipboardText;
+
+ device->free = WIN_DeleteDevice;
+
+ return device;
+}
+
+
+VideoBootStrap WINDOWS_bootstrap = {
+ "windows", "SDL Windows video driver", WIN_Available, WIN_CreateDevice
+};
+
+int
+WIN_VideoInit(_THIS)
+{
+ if (WIN_InitModes(_this) < 0) {
+ return -1;
+ }
+
+ WIN_InitKeyboard(_this);
+ WIN_InitMouse(_this);
+
+ SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL);
+ SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL);
+
+ return 0;
+}
+
+void
+WIN_VideoQuit(_THIS)
+{
+ WIN_QuitModes(_this);
+ WIN_QuitKeyboard(_this);
+ WIN_QuitMouse(_this);
+}
+
+
+#define D3D_DEBUG_INFO
+#include <d3d9.h>
+
+SDL_bool
+D3D_LoadDLL(void **pD3DDLL, IDirect3D9 **pDirect3D9Interface)
+{
+ *pD3DDLL = SDL_LoadObject("D3D9.DLL");
+ if (*pD3DDLL) {
+ typedef IDirect3D9 *(WINAPI *Direct3DCreate9_t) (UINT SDKVersion);
+ Direct3DCreate9_t Direct3DCreate9Func;
+
+#ifdef USE_D3D9EX
+ typedef HRESULT (WINAPI *Direct3DCreate9Ex_t)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
+ Direct3DCreate9Ex_t Direct3DCreate9ExFunc;
+
+ Direct3DCreate9ExFunc = (Direct3DCreate9Ex_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9Ex");
+ if (Direct3DCreate9ExFunc) {
+ IDirect3D9Ex *pDirect3D9ExInterface;
+ HRESULT hr = Direct3DCreate9ExFunc(D3D_SDK_VERSION, &pDirect3D9ExInterface);
+ if (SUCCEEDED(hr)) {
+ const GUID IDirect3D9_GUID = { 0x81bdcbca, 0x64d4, 0x426d, { 0xae, 0x8d, 0xad, 0x1, 0x47, 0xf4, 0x27, 0x5c } };
+ hr = IDirect3D9Ex_QueryInterface(pDirect3D9ExInterface, &IDirect3D9_GUID, (void**)pDirect3D9Interface);
+ IDirect3D9Ex_Release(pDirect3D9ExInterface);
+ if (SUCCEEDED(hr)) {
+ return SDL_TRUE;
+ }
+ }
+ }
+#endif /* USE_D3D9EX */
+
+ Direct3DCreate9Func = (Direct3DCreate9_t)SDL_LoadFunction(*pD3DDLL, "Direct3DCreate9");
+ if (Direct3DCreate9Func) {
+ *pDirect3D9Interface = Direct3DCreate9Func(D3D_SDK_VERSION);
+ if (*pDirect3D9Interface) {
+ return SDL_TRUE;
+ }
+ }
+
+ SDL_UnloadObject(*pD3DDLL);
+ *pD3DDLL = NULL;
+ }
+ *pDirect3D9Interface = NULL;
+ return SDL_FALSE;
+}
+
+
+int
+SDL_Direct3D9GetAdapterIndex(int displayIndex)
+{
+ void *pD3DDLL;
+ IDirect3D9 *pD3D;
+ if (!D3D_LoadDLL(&pD3DDLL, &pD3D)) {
+ SDL_SetError("Unable to create Direct3D interface");
+ return D3DADAPTER_DEFAULT;
+ } else {
+ SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex);
+ int adapterIndex = D3DADAPTER_DEFAULT;
+
+ if (!pData) {
+ SDL_SetError("Invalid display index");
+ adapterIndex = -1; /* make sure we return something invalid */
+ } else {
+ char *displayName = WIN_StringToUTF8(pData->DeviceName);
+ unsigned int count = IDirect3D9_GetAdapterCount(pD3D);
+ unsigned int i;
+ for (i=0; i<count; i++) {
+ D3DADAPTER_IDENTIFIER9 id;
+ IDirect3D9_GetAdapterIdentifier(pD3D, i, 0, &id);
+
+ if (SDL_strcmp(id.DeviceName, displayName) == 0) {
+ adapterIndex = i;
+ break;
+ }
+ }
+ SDL_free(displayName);
+ }
+
+ /* free up the D3D stuff we inited */
+ IDirect3D9_Release(pD3D);
+ SDL_UnloadObject(pD3DDLL);
+
+ return adapterIndex;
+ }
+}
+
+#if HAVE_DXGI_H
+#define CINTERFACE
+#define COBJMACROS
+#include <dxgi.h>
+
+static SDL_bool
+DXGI_LoadDLL(void **pDXGIDLL, IDXGIFactory **pDXGIFactory)
+{
+ *pDXGIDLL = SDL_LoadObject("DXGI.DLL");
+ if (*pDXGIDLL) {
+ HRESULT (WINAPI *CreateDXGI)(REFIID riid, void **ppFactory);
+
+ CreateDXGI =
+ (HRESULT (WINAPI *) (REFIID, void**)) SDL_LoadFunction(*pDXGIDLL,
+ "CreateDXGIFactory");
+ if (CreateDXGI) {
+ GUID dxgiGUID = {0x7b7166ec,0x21c7,0x44ae,{0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69}};
+ if (!SUCCEEDED(CreateDXGI(&dxgiGUID, (void**)pDXGIFactory))) {
+ *pDXGIFactory = NULL;
+ }
+ }
+ if (!*pDXGIFactory) {
+ SDL_UnloadObject(*pDXGIDLL);
+ *pDXGIDLL = NULL;
+ return SDL_FALSE;
+ }
+
+ return SDL_TRUE;
+ } else {
+ *pDXGIFactory = NULL;
+ return SDL_FALSE;
+ }
+}
+#endif
+
+
+SDL_bool
+SDL_DXGIGetOutputInfo(int displayIndex, int *adapterIndex, int *outputIndex)
+{
+#if !HAVE_DXGI_H
+ if (adapterIndex) *adapterIndex = -1;
+ if (outputIndex) *outputIndex = -1;
+ SDL_SetError("SDL was compiled without DXGI support due to missing dxgi.h header");
+ return SDL_FALSE;
+#else
+ SDL_DisplayData *pData = (SDL_DisplayData *)SDL_GetDisplayDriverData(displayIndex);
+ void *pDXGIDLL;
+ char *displayName;
+ int nAdapter, nOutput;
+ IDXGIFactory *pDXGIFactory;
+ IDXGIAdapter *pDXGIAdapter;
+ IDXGIOutput* pDXGIOutput;
+
+ if (!adapterIndex) {
+ SDL_InvalidParamError("adapterIndex");
+ return SDL_FALSE;
+ }
+
+ if (!outputIndex) {
+ SDL_InvalidParamError("outputIndex");
+ return SDL_FALSE;
+ }
+
+ *adapterIndex = -1;
+ *outputIndex = -1;
+
+ if (!pData) {
+ SDL_SetError("Invalid display index");
+ return SDL_FALSE;
+ }
+
+ if (!DXGI_LoadDLL(&pDXGIDLL, &pDXGIFactory)) {
+ SDL_SetError("Unable to create DXGI interface");
+ return SDL_FALSE;
+ }
+
+ displayName = WIN_StringToUTF8(pData->DeviceName);
+ nAdapter = 0;
+ while (*adapterIndex == -1 && SUCCEEDED(IDXGIFactory_EnumAdapters(pDXGIFactory, nAdapter, &pDXGIAdapter))) {
+ nOutput = 0;
+ while (*adapterIndex == -1 && SUCCEEDED(IDXGIAdapter_EnumOutputs(pDXGIAdapter, nOutput, &pDXGIOutput))) {
+ DXGI_OUTPUT_DESC outputDesc;
+ if (SUCCEEDED(IDXGIOutput_GetDesc(pDXGIOutput, &outputDesc))) {
+ char *outputName = WIN_StringToUTF8(outputDesc.DeviceName);
+ if (SDL_strcmp(outputName, displayName) == 0) {
+ *adapterIndex = nAdapter;
+ *outputIndex = nOutput;
+ }
+ SDL_free(outputName);
+ }
+ IDXGIOutput_Release(pDXGIOutput);
+ nOutput++;
+ }
+ IDXGIAdapter_Release(pDXGIAdapter);
+ nAdapter++;
+ }
+ SDL_free(displayName);
+
+ /* free up the DXGI factory */
+ IDXGIFactory_Release(pDXGIFactory);
+ SDL_UnloadObject(pDXGIDLL);
+
+ if (*adapterIndex == -1) {
+ return SDL_FALSE;
+ } else {
+ return SDL_TRUE;
+ }
+#endif
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vim: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.h
new file mode 100644
index 0000000..1303754
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvideo.h
@@ -0,0 +1,199 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsvideo_h_
+#define SDL_windowsvideo_h_
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "../SDL_sysvideo.h"
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1500)
+#include <msctf.h>
+#else
+#include "SDL_msctf.h"
+#endif
+
+#include <imm.h>
+
+#define MAX_CANDLIST 10
+#define MAX_CANDLENGTH 256
+
+#include "SDL_windowsclipboard.h"
+#include "SDL_windowsevents.h"
+#include "SDL_windowskeyboard.h"
+#include "SDL_windowsmodes.h"
+#include "SDL_windowsmouse.h"
+#include "SDL_windowsopengl.h"
+#include "SDL_windowsopengles.h"
+#include "SDL_windowswindow.h"
+#include "SDL_events.h"
+#include "SDL_loadso.h"
+
+
+#if WINVER < 0x0601
+/* Touch input definitions */
+#define TWF_FINETOUCH 1
+#define TWF_WANTPALM 2
+
+#define TOUCHEVENTF_MOVE 0x0001
+#define TOUCHEVENTF_DOWN 0x0002
+#define TOUCHEVENTF_UP 0x0004
+
+DECLARE_HANDLE(HTOUCHINPUT);
+
+typedef struct _TOUCHINPUT {
+ LONG x;
+ LONG y;
+ HANDLE hSource;
+ DWORD dwID;
+ DWORD dwFlags;
+ DWORD dwMask;
+ DWORD dwTime;
+ ULONG_PTR dwExtraInfo;
+ DWORD cxContact;
+ DWORD cyContact;
+} TOUCHINPUT, *PTOUCHINPUT;
+
+#endif /* WINVER < 0x0601 */
+
+#if WINVER < 0x0603
+
+typedef enum MONITOR_DPI_TYPE {
+ MDT_EFFECTIVE_DPI = 0,
+ MDT_ANGULAR_DPI = 1,
+ MDT_RAW_DPI = 2,
+ MDT_DEFAULT = MDT_EFFECTIVE_DPI
+} MONITOR_DPI_TYPE;
+
+#endif /* WINVER < 0x0603 */
+
+typedef BOOL (*PFNSHFullScreen)(HWND, DWORD);
+typedef void (*PFCoordTransform)(SDL_Window*, POINT*);
+
+typedef struct
+{
+ void **lpVtbl;
+ int refcount;
+ void *data;
+} TSFSink;
+
+/* Definition from Win98DDK version of IMM.H */
+typedef struct tagINPUTCONTEXT2 {
+ HWND hWnd;
+ BOOL fOpen;
+ POINT ptStatusWndPos;
+ POINT ptSoftKbdPos;
+ DWORD fdwConversion;
+ DWORD fdwSentence;
+ union {
+ LOGFONTA A;
+ LOGFONTW W;
+ } lfFont;
+ COMPOSITIONFORM cfCompForm;
+ CANDIDATEFORM cfCandForm[4];
+ HIMCC hCompStr;
+ HIMCC hCandInfo;
+ HIMCC hGuideLine;
+ HIMCC hPrivate;
+ DWORD dwNumMsgBuf;
+ HIMCC hMsgBuf;
+ DWORD fdwInit;
+ DWORD dwReserve[3];
+} INPUTCONTEXT2, *PINPUTCONTEXT2, NEAR *NPINPUTCONTEXT2, FAR *LPINPUTCONTEXT2;
+
+/* Private display data */
+
+typedef struct SDL_VideoData
+{
+ int render;
+
+ DWORD clipboard_count;
+
+ /* Touch input functions */
+ void* userDLL;
+ BOOL (WINAPI *CloseTouchInputHandle)( HTOUCHINPUT );
+ BOOL (WINAPI *GetTouchInputInfo)( HTOUCHINPUT, UINT, PTOUCHINPUT, int );
+ BOOL (WINAPI *RegisterTouchWindow)( HWND, ULONG );
+
+ void* shcoreDLL;
+ HRESULT (WINAPI *GetDpiForMonitor)( HMONITOR hmonitor,
+ MONITOR_DPI_TYPE dpiType,
+ UINT *dpiX,
+ UINT *dpiY );
+
+ SDL_bool ime_com_initialized;
+ struct ITfThreadMgr *ime_threadmgr;
+ SDL_bool ime_initialized;
+ SDL_bool ime_enabled;
+ SDL_bool ime_available;
+ HWND ime_hwnd_main;
+ HWND ime_hwnd_current;
+ HIMC ime_himc;
+
+ WCHAR ime_composition[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
+ WCHAR ime_readingstring[16];
+ int ime_cursor;
+
+ SDL_bool ime_candlist;
+ WCHAR ime_candidates[MAX_CANDLIST][MAX_CANDLENGTH];
+ DWORD ime_candcount;
+ DWORD ime_candref;
+ DWORD ime_candsel;
+ UINT ime_candpgsize;
+ int ime_candlistindexbase;
+ SDL_bool ime_candvertical;
+
+ SDL_bool ime_dirty;
+ SDL_Rect ime_rect;
+ SDL_Rect ime_candlistrect;
+ int ime_winwidth;
+ int ime_winheight;
+
+ HKL ime_hkl;
+ void* ime_himm32;
+ UINT (WINAPI *GetReadingString)(HIMC himc, UINT uReadingBufLen, LPWSTR lpwReadingBuf, PINT pnErrorIndex, BOOL *pfIsVertical, PUINT puMaxReadingLen);
+ BOOL (WINAPI *ShowReadingWindow)(HIMC himc, BOOL bShow);
+ LPINPUTCONTEXT2 (WINAPI *ImmLockIMC)(HIMC himc);
+ BOOL (WINAPI *ImmUnlockIMC)(HIMC himc);
+ LPVOID (WINAPI *ImmLockIMCC)(HIMCC himcc);
+ BOOL (WINAPI *ImmUnlockIMCC)(HIMCC himcc);
+
+ SDL_bool ime_uiless;
+ struct ITfThreadMgrEx *ime_threadmgrex;
+ DWORD ime_uielemsinkcookie;
+ DWORD ime_alpnsinkcookie;
+ DWORD ime_openmodesinkcookie;
+ DWORD ime_convmodesinkcookie;
+ TSFSink *ime_uielemsink;
+ TSFSink *ime_ippasink;
+} SDL_VideoData;
+
+extern SDL_bool g_WindowsEnableMessageLoop;
+extern SDL_bool g_WindowFrameUsableWhileCursorHidden;
+
+typedef struct IDirect3D9 IDirect3D9;
+extern SDL_bool D3D_LoadDLL( void **pD3DDLL, IDirect3D9 **pDirect3D9Interface );
+
+#endif /* SDL_windowsvideo_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.c
new file mode 100644
index 0000000..6bb8f2a
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.c
@@ -0,0 +1,176 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+ * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
+ * SDL_x11vulkan.c.
+ */
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_WINDOWS
+
+#include "SDL_windowsvideo.h"
+#include "SDL_windowswindow.h"
+#include "SDL_assert.h"
+
+#include "SDL_loadso.h"
+#include "SDL_windowsvulkan.h"
+#include "SDL_syswm.h"
+
+int WIN_Vulkan_LoadLibrary(_THIS, const char *path)
+{
+ VkExtensionProperties *extensions = NULL;
+ Uint32 extensionCount = 0;
+ Uint32 i;
+ SDL_bool hasSurfaceExtension = SDL_FALSE;
+ SDL_bool hasWin32SurfaceExtension = SDL_FALSE;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
+ if(_this->vulkan_config.loader_handle)
+ return SDL_SetError("Vulkan already loaded");
+
+ /* Load the Vulkan loader library */
+ if(!path)
+ path = SDL_getenv("SDL_VULKAN_LIBRARY");
+ if(!path)
+ path = "vulkan-1.dll";
+ _this->vulkan_config.loader_handle = SDL_LoadObject(path);
+ if(!_this->vulkan_config.loader_handle)
+ return -1;
+ SDL_strlcpy(_this->vulkan_config.loader_path, path,
+ SDL_arraysize(_this->vulkan_config.loader_path));
+ vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
+ _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
+ if(!vkGetInstanceProcAddr)
+ goto fail;
+ _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
+ _this->vulkan_config.vkEnumerateInstanceExtensionProperties =
+ (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
+ VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
+ if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
+ goto fail;
+ extensions = SDL_Vulkan_CreateInstanceExtensionsList(
+ (PFN_vkEnumerateInstanceExtensionProperties)
+ _this->vulkan_config.vkEnumerateInstanceExtensionProperties,
+ &extensionCount);
+ if(!extensions)
+ goto fail;
+ for(i = 0; i < extensionCount; i++)
+ {
+ if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
+ hasSurfaceExtension = SDL_TRUE;
+ else if(SDL_strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
+ hasWin32SurfaceExtension = SDL_TRUE;
+ }
+ SDL_free(extensions);
+ if(!hasSurfaceExtension)
+ {
+ SDL_SetError("Installed Vulkan doesn't implement the "
+ VK_KHR_SURFACE_EXTENSION_NAME " extension");
+ goto fail;
+ }
+ else if(!hasWin32SurfaceExtension)
+ {
+ SDL_SetError("Installed Vulkan doesn't implement the "
+ VK_KHR_WIN32_SURFACE_EXTENSION_NAME "extension");
+ goto fail;
+ }
+ return 0;
+
+fail:
+ SDL_UnloadObject(_this->vulkan_config.loader_handle);
+ _this->vulkan_config.loader_handle = NULL;
+ return -1;
+}
+
+void WIN_Vulkan_UnloadLibrary(_THIS)
+{
+ if(_this->vulkan_config.loader_handle)
+ {
+ SDL_UnloadObject(_this->vulkan_config.loader_handle);
+ _this->vulkan_config.loader_handle = NULL;
+ }
+}
+
+SDL_bool WIN_Vulkan_GetInstanceExtensions(_THIS,
+ SDL_Window *window,
+ unsigned *count,
+ const char **names)
+{
+ static const char *const extensionsForWin32[] = {
+ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME
+ };
+ if(!_this->vulkan_config.loader_handle)
+ {
+ SDL_SetError("Vulkan is not loaded");
+ return SDL_FALSE;
+ }
+ return SDL_Vulkan_GetInstanceExtensions_Helper(
+ count, names, SDL_arraysize(extensionsForWin32),
+ extensionsForWin32);
+}
+
+SDL_bool WIN_Vulkan_CreateSurface(_THIS,
+ SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR *surface)
+{
+ SDL_WindowData *windowData = (SDL_WindowData *)window->driverdata;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
+ (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
+ PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR =
+ (PFN_vkCreateWin32SurfaceKHR)vkGetInstanceProcAddr(
+ (VkInstance)instance,
+ "vkCreateWin32SurfaceKHR");
+ VkWin32SurfaceCreateInfoKHR createInfo;
+ VkResult result;
+
+ if(!_this->vulkan_config.loader_handle)
+ {
+ SDL_SetError("Vulkan is not loaded");
+ return SDL_FALSE;
+ }
+
+ if(!vkCreateWin32SurfaceKHR)
+ {
+ SDL_SetError(VK_KHR_WIN32_SURFACE_EXTENSION_NAME
+ " extension is not enabled in the Vulkan instance.");
+ return SDL_FALSE;
+ }
+ createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ createInfo.pNext = NULL;
+ createInfo.flags = 0;
+ createInfo.hinstance = windowData->hinstance;
+ createInfo.hwnd = windowData->hwnd;
+ result = vkCreateWin32SurfaceKHR(instance, &createInfo,
+ NULL, surface);
+ if(result != VK_SUCCESS)
+ {
+ SDL_SetError("vkCreateWin32SurfaceKHR failed: %s",
+ SDL_Vulkan_GetResultString(result));
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+}
+
+#endif
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.h
new file mode 100644
index 0000000..0acc0a9
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowsvulkan.h
@@ -0,0 +1,52 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/*
+ * @author Mark Callow, www.edgewise-consulting.com. Based on Jacob Lifshay's
+ * SDL_x11vulkan.h.
+ */
+
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowsvulkan_h_
+#define SDL_windowsvulkan_h_
+
+#include "../SDL_vulkan_internal.h"
+#include "../SDL_sysvideo.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_WINDOWS
+
+int WIN_Vulkan_LoadLibrary(_THIS, const char *path);
+void WIN_Vulkan_UnloadLibrary(_THIS);
+SDL_bool WIN_Vulkan_GetInstanceExtensions(_THIS,
+ SDL_Window *window,
+ unsigned *count,
+ const char **names);
+SDL_bool WIN_Vulkan_CreateSurface(_THIS,
+ SDL_Window *window,
+ VkInstance instance,
+ VkSurfaceKHR *surface);
+
+#endif
+
+#endif /* SDL_windowsvulkan_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.c b/source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.c
new file mode 100644
index 0000000..45463c4
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.c
@@ -0,0 +1,996 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINDOWS
+
+#include "../../core/windows/SDL_windows.h"
+
+#include "SDL_assert.h"
+#include "../SDL_sysvideo.h"
+#include "../SDL_pixels_c.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "../../events/SDL_mouse_c.h"
+
+#include "SDL_windowsvideo.h"
+#include "SDL_windowswindow.h"
+#include "SDL_hints.h"
+
+/* Dropfile support */
+#include <shellapi.h>
+
+/* This is included after SDL_windowsvideo.h, which includes windows.h */
+#include "SDL_syswm.h"
+
+/* Windows CE compatibility */
+#ifndef SWP_NOCOPYBITS
+#define SWP_NOCOPYBITS 0
+#endif
+
+/* Fake window to help with DirectInput events. */
+HWND SDL_HelperWindow = NULL;
+static WCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
+static WCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
+static ATOM SDL_HelperWindowClass = 0;
+
+/* For borderless Windows, still want the following flags:
+ - WS_CAPTION: this seems to enable the Windows minimize animation
+ - WS_SYSMENU: enables system context menu on task bar
+ - WS_MINIMIZEBOX: window will respond to Windows minimize commands sent to all windows, such as windows key + m, shaking title bar, etc.
+ This will also cause the task bar to overlap the window and other windowed behaviors, so only use this for windows that shouldn't appear to be fullscreen
+ */
+
+#define STYLE_BASIC (WS_CLIPSIBLINGS | WS_CLIPCHILDREN)
+#define STYLE_FULLSCREEN (WS_POPUP)
+#define STYLE_BORDERLESS (WS_POPUP)
+#define STYLE_BORDERLESS_WINDOWED (WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
+#define STYLE_NORMAL (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX)
+#define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
+#define STYLE_MASK (STYLE_FULLSCREEN | STYLE_BORDERLESS | STYLE_NORMAL | STYLE_RESIZABLE)
+
+static DWORD
+GetWindowStyle(SDL_Window * window)
+{
+ DWORD style = 0;
+
+ if (window->flags & SDL_WINDOW_FULLSCREEN) {
+ style |= STYLE_FULLSCREEN;
+ } else {
+ if (window->flags & SDL_WINDOW_BORDERLESS) {
+ /* SDL 2.1:
+ This behavior more closely matches other platform where the window is borderless
+ but still interacts with the window manager (e.g. task bar shows above it, it can
+ be resized to fit within usable desktop area, etc.) so this should be the behavior
+ for a future SDL release.
+
+ If you want a borderless window the size of the desktop that looks like a fullscreen
+ window, then you should use the SDL_WINDOW_FULLSCREEN_DESKTOP flag.
+ */
+ if (SDL_GetHintBoolean("SDL_BORDERLESS_WINDOWED_STYLE", SDL_FALSE)) {
+ style |= STYLE_BORDERLESS_WINDOWED;
+ } else {
+ style |= STYLE_BORDERLESS;
+ }
+ } else {
+ style |= STYLE_NORMAL;
+ }
+
+ /* You can have a borderless resizable window */
+ if (window->flags & SDL_WINDOW_RESIZABLE) {
+ style |= STYLE_RESIZABLE;
+ }
+
+ /* Need to set initialize minimize style, or when we call ShowWindow with WS_MINIMIZE it will activate a random window */
+ if (window->flags & SDL_WINDOW_MINIMIZED) {
+ style |= WS_MINIMIZE;
+ }
+ }
+ return style;
+}
+
+static void
+WIN_AdjustWindowRectWithStyle(SDL_Window *window, DWORD style, BOOL menu, int *x, int *y, int *width, int *height, SDL_bool use_current)
+{
+ RECT rect;
+
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = (use_current ? window->w : window->windowed.w);
+ rect.bottom = (use_current ? window->h : window->windowed.h);
+
+ /* borderless windows will have WM_NCCALCSIZE return 0 for the non-client area. When this happens, it looks like windows will send a resize message
+ expanding the window client area to the previous window + chrome size, so shouldn't need to adjust the window size for the set styles.
+ */
+ if (!(window->flags & SDL_WINDOW_BORDERLESS))
+ AdjustWindowRectEx(&rect, style, menu, 0);
+
+ *x = (use_current ? window->x : window->windowed.x) + rect.left;
+ *y = (use_current ? window->y : window->windowed.y) + rect.top;
+ *width = (rect.right - rect.left);
+ *height = (rect.bottom - rect.top);
+}
+
+static void
+WIN_AdjustWindowRect(SDL_Window *window, int *x, int *y, int *width, int *height, SDL_bool use_current)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ DWORD style;
+ BOOL menu;
+
+ style = GetWindowLong(hwnd, GWL_STYLE);
+ menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
+ WIN_AdjustWindowRectWithStyle(window, style, menu, x, y, width, height, use_current);
+}
+
+static void
+WIN_SetWindowPositionInternal(_THIS, SDL_Window * window, UINT flags)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ HWND top;
+ int x, y;
+ int w, h;
+
+ /* Figure out what the window area will be */
+ if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || (window->flags & SDL_WINDOW_ALWAYS_ON_TOP))) {
+ top = HWND_TOPMOST;
+ } else {
+ top = HWND_NOTOPMOST;
+ }
+
+ WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_TRUE);
+
+ data->expected_resize = SDL_TRUE;
+ SetWindowPos(hwnd, top, x, y, w, h, flags);
+ data->expected_resize = SDL_FALSE;
+}
+
+static int
+SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool created)
+{
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ SDL_WindowData *data;
+
+ /* Allocate the window data */
+ data = (SDL_WindowData *) SDL_calloc(1, sizeof(*data));
+ if (!data) {
+ return SDL_OutOfMemory();
+ }
+ data->window = window;
+ data->hwnd = hwnd;
+ data->parent = parent;
+ data->hdc = GetDC(hwnd);
+ data->hinstance = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
+ data->created = created;
+ data->mouse_button_flags = 0;
+ data->videodata = videodata;
+ data->initializing = SDL_TRUE;
+
+ window->driverdata = data;
+
+ /* Associate the data with the window */
+ if (!SetProp(hwnd, TEXT("SDL_WindowData"), data)) {
+ ReleaseDC(hwnd, data->hdc);
+ SDL_free(data);
+ return WIN_SetError("SetProp() failed");
+ }
+
+ /* Set up the window proc function */
+#ifdef GWLP_WNDPROC
+ data->wndproc = (WNDPROC) GetWindowLongPtr(hwnd, GWLP_WNDPROC);
+ if (data->wndproc == WIN_WindowProc) {
+ data->wndproc = NULL;
+ } else {
+ SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) WIN_WindowProc);
+ }
+#else
+ data->wndproc = (WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC);
+ if (data->wndproc == WIN_WindowProc) {
+ data->wndproc = NULL;
+ } else {
+ SetWindowLong(hwnd, GWL_WNDPROC, (LONG_PTR) WIN_WindowProc);
+ }
+#endif
+
+ /* Fill in the SDL window with the window data */
+ {
+ RECT rect;
+ if (GetClientRect(hwnd, &rect)) {
+ int w = rect.right;
+ int h = rect.bottom;
+ if ((window->windowed.w && window->windowed.w != w) || (window->windowed.h && window->windowed.h != h)) {
+ /* We tried to create a window larger than the desktop and Windows didn't allow it. Override! */
+ int x, y;
+ /* Figure out what the window area will be */
+ WIN_AdjustWindowRect(window, &x, &y, &w, &h, SDL_FALSE);
+ SetWindowPos(hwnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOCOPYBITS | SWP_NOZORDER | SWP_NOACTIVATE);
+ } else {
+ window->w = w;
+ window->h = h;
+ }
+ }
+ }
+ {
+ POINT point;
+ point.x = 0;
+ point.y = 0;
+ if (ClientToScreen(hwnd, &point)) {
+ window->x = point.x;
+ window->y = point.y;
+ }
+ }
+ {
+ DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+ if (style & WS_VISIBLE) {
+ window->flags |= SDL_WINDOW_SHOWN;
+ } else {
+ window->flags &= ~SDL_WINDOW_SHOWN;
+ }
+ if (style & WS_POPUP) {
+ window->flags |= SDL_WINDOW_BORDERLESS;
+ } else {
+ window->flags &= ~SDL_WINDOW_BORDERLESS;
+ }
+ if (style & WS_THICKFRAME) {
+ window->flags |= SDL_WINDOW_RESIZABLE;
+ } else {
+ window->flags &= ~SDL_WINDOW_RESIZABLE;
+ }
+#ifdef WS_MAXIMIZE
+ if (style & WS_MAXIMIZE) {
+ window->flags |= SDL_WINDOW_MAXIMIZED;
+ } else
+#endif
+ {
+ window->flags &= ~SDL_WINDOW_MAXIMIZED;
+ }
+#ifdef WS_MINIMIZE
+ if (style & WS_MINIMIZE) {
+ window->flags |= SDL_WINDOW_MINIMIZED;
+ } else
+#endif
+ {
+ window->flags &= ~SDL_WINDOW_MINIMIZED;
+ }
+ }
+ if (GetFocus() == hwnd) {
+ window->flags |= SDL_WINDOW_INPUT_FOCUS;
+ SDL_SetKeyboardFocus(data->window);
+
+ if (window->flags & SDL_WINDOW_INPUT_GRABBED) {
+ RECT rect;
+ GetClientRect(hwnd, &rect);
+ ClientToScreen(hwnd, (LPPOINT) & rect);
+ ClientToScreen(hwnd, (LPPOINT) & rect + 1);
+ ClipCursor(&rect);
+ }
+ }
+
+ /* Enable multi-touch */
+ if (videodata->RegisterTouchWindow) {
+ videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM));
+ }
+
+ data->initializing = SDL_FALSE;
+
+ /* All done! */
+ return 0;
+}
+
+
+
+int
+WIN_CreateWindow(_THIS, SDL_Window * window)
+{
+ HWND hwnd, parent = NULL;
+ DWORD style = STYLE_BASIC;
+ int x, y;
+ int w, h;
+
+ if (window->flags & SDL_WINDOW_SKIP_TASKBAR) {
+ parent = CreateWindow(SDL_Appname, TEXT(""), STYLE_BASIC, 0, 0, 32, 32, NULL, NULL, SDL_Instance, NULL);
+ }
+
+ style |= GetWindowStyle(window);
+
+ /* Figure out what the window area will be */
+ WIN_AdjustWindowRectWithStyle(window, style, FALSE, &x, &y, &w, &h, SDL_FALSE);
+
+ hwnd =
+ CreateWindow(SDL_Appname, TEXT(""), style, x, y, w, h, parent, NULL,
+ SDL_Instance, NULL);
+ if (!hwnd) {
+ return WIN_SetError("Couldn't create window");
+ }
+
+ WIN_PumpEvents(_this);
+
+ if (SetupWindowData(_this, window, hwnd, parent, SDL_TRUE) < 0) {
+ DestroyWindow(hwnd);
+ if (parent) {
+ DestroyWindow(parent);
+ }
+ return -1;
+ }
+
+ /* Inform Windows of the frame change so we can respond to WM_NCCALCSIZE */
+ SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+
+ if (window->flags & SDL_WINDOW_MINIMIZED) {
+ ShowWindow(hwnd, SW_SHOWMINNOACTIVE);
+ }
+
+ if (!(window->flags & SDL_WINDOW_OPENGL)) {
+ return 0;
+ }
+
+ /* The rest of this macro mess is for OpenGL or OpenGL ES windows */
+#if SDL_VIDEO_OPENGL_ES2
+ if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES
+#if SDL_VIDEO_OPENGL_WGL
+ && (!_this->gl_data || WIN_GL_UseEGL(_this))
+#endif /* SDL_VIDEO_OPENGL_WGL */
+ ) {
+#if SDL_VIDEO_OPENGL_EGL
+ if (WIN_GLES_SetupWindow(_this, window) < 0) {
+ WIN_DestroyWindow(_this, window);
+ return -1;
+ }
+ return 0;
+#else
+ return SDL_SetError("Could not create GLES window surface (EGL support not configured)");
+#endif /* SDL_VIDEO_OPENGL_EGL */
+ }
+#endif /* SDL_VIDEO_OPENGL_ES2 */
+
+#if SDL_VIDEO_OPENGL_WGL
+ if (WIN_GL_SetupWindow(_this, window) < 0) {
+ WIN_DestroyWindow(_this, window);
+ return -1;
+ }
+#else
+ return SDL_SetError("Could not create GL window (WGL support not configured)");
+#endif
+
+ return 0;
+}
+
+int
+WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
+{
+ HWND hwnd = (HWND) data;
+ LPTSTR title;
+ int titleLen;
+
+ /* Query the title from the existing window */
+ titleLen = GetWindowTextLength(hwnd);
+ title = SDL_stack_alloc(TCHAR, titleLen + 1);
+ if (title) {
+ titleLen = GetWindowText(hwnd, title, titleLen);
+ } else {
+ titleLen = 0;
+ }
+ if (titleLen > 0) {
+ window->title = WIN_StringToUTF8(title);
+ }
+ if (title) {
+ SDL_stack_free(title);
+ }
+
+ if (SetupWindowData(_this, window, hwnd, GetParent(hwnd), SDL_FALSE) < 0) {
+ return -1;
+ }
+
+#if SDL_VIDEO_OPENGL_WGL
+ {
+ const char *hint = SDL_GetHint(SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT);
+ if (hint) {
+ /* This hint is a pointer (in string form) of the address of
+ the window to share a pixel format with
+ */
+ SDL_Window *otherWindow = NULL;
+ SDL_sscanf(hint, "%p", (void**)&otherWindow);
+
+ /* Do some error checking on the pointer */
+ if (otherWindow != NULL && otherWindow->magic == &_this->window_magic) {
+ /* If the otherWindow has SDL_WINDOW_OPENGL set, set it for the new window as well */
+ if (otherWindow->flags & SDL_WINDOW_OPENGL) {
+ window->flags |= SDL_WINDOW_OPENGL;
+ if (!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) {
+ return -1;
+ }
+ }
+ }
+ }
+ }
+#endif
+ return 0;
+}
+
+void
+WIN_SetWindowTitle(_THIS, SDL_Window * window)
+{
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ LPTSTR title = WIN_UTF8ToString(window->title);
+ SetWindowText(hwnd, title);
+ SDL_free(title);
+}
+
+void
+WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon)
+{
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ HICON hicon = NULL;
+ BYTE *icon_bmp;
+ int icon_len, mask_len, y;
+ SDL_RWops *dst;
+
+ /* Create temporary buffer for ICONIMAGE structure */
+ mask_len = (icon->h * (icon->w + 7)/8);
+ icon_len = 40 + icon->h * icon->w * sizeof(Uint32) + mask_len;
+ icon_bmp = SDL_stack_alloc(BYTE, icon_len);
+ dst = SDL_RWFromMem(icon_bmp, icon_len);
+ if (!dst) {
+ SDL_stack_free(icon_bmp);
+ return;
+ }
+
+ /* Write the BITMAPINFO header */
+ SDL_WriteLE32(dst, 40);
+ SDL_WriteLE32(dst, icon->w);
+ SDL_WriteLE32(dst, icon->h * 2);
+ SDL_WriteLE16(dst, 1);
+ SDL_WriteLE16(dst, 32);
+ SDL_WriteLE32(dst, BI_RGB);
+ SDL_WriteLE32(dst, icon->h * icon->w * sizeof(Uint32));
+ SDL_WriteLE32(dst, 0);
+ SDL_WriteLE32(dst, 0);
+ SDL_WriteLE32(dst, 0);
+ SDL_WriteLE32(dst, 0);
+
+ /* Write the pixels upside down into the bitmap buffer */
+ SDL_assert(icon->format->format == SDL_PIXELFORMAT_ARGB8888);
+ y = icon->h;
+ while (y--) {
+ Uint8 *src = (Uint8 *) icon->pixels + y * icon->pitch;
+ SDL_RWwrite(dst, src, icon->w * sizeof(Uint32), 1);
+ }
+
+ /* Write the mask */
+ SDL_memset(icon_bmp + icon_len - mask_len, 0xFF, mask_len);
+
+ hicon = CreateIconFromResource(icon_bmp, icon_len, TRUE, 0x00030000);
+
+ SDL_RWclose(dst);
+ SDL_stack_free(icon_bmp);
+
+ /* Set the icon for the window */
+ SendMessage(hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);
+
+ /* Set the icon in the task manager (should we do this?) */
+ SendMessage(hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);
+}
+
+void
+WIN_SetWindowPosition(_THIS, SDL_Window * window)
+{
+ WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
+}
+
+void
+WIN_SetWindowSize(_THIS, SDL_Window * window)
+{
+ WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOACTIVATE);
+}
+
+int
+WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
+{
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ RECT rcClient, rcWindow;
+ POINT ptDiff;
+
+ /* rcClient stores the size of the inner window, while rcWindow stores the outer size relative to the top-left
+ * screen position; so the top/left values of rcClient are always {0,0} and bottom/right are {height,width} */
+ GetClientRect(hwnd, &rcClient);
+ GetWindowRect(hwnd, &rcWindow);
+
+ /* convert the top/left values to make them relative to
+ * the window; they will end up being slightly negative */
+ ptDiff.y = rcWindow.top;
+ ptDiff.x = rcWindow.left;
+
+ ScreenToClient(hwnd, &ptDiff);
+
+ rcWindow.top = ptDiff.y;
+ rcWindow.left = ptDiff.x;
+
+ /* convert the bottom/right values to make them relative to the window,
+ * these will be slightly bigger than the inner width/height */
+ ptDiff.y = rcWindow.bottom;
+ ptDiff.x = rcWindow.right;
+
+ ScreenToClient(hwnd, &ptDiff);
+
+ rcWindow.bottom = ptDiff.y;
+ rcWindow.right = ptDiff.x;
+
+ /* Now that both the inner and outer rects use the same coordinate system we can substract them to get the border size.
+ * Keep in mind that the top/left coordinates of rcWindow are negative because the border lies slightly before {0,0},
+ * so switch them around because SDL2 wants them in positive. */
+ *top = rcClient.top - rcWindow.top;
+ *left = rcClient.left - rcWindow.left;
+ *bottom = rcWindow.bottom - rcClient.bottom;
+ *right = rcWindow.right - rcClient.right;
+
+ return 0;
+}
+
+void
+WIN_ShowWindow(_THIS, SDL_Window * window)
+{
+ DWORD style;
+ HWND hwnd;
+ int nCmdShow;
+
+ hwnd = ((SDL_WindowData *)window->driverdata)->hwnd;
+ nCmdShow = SW_SHOW;
+ style = GetWindowLong(hwnd, GWL_EXSTYLE);
+ if (style & WS_EX_NOACTIVATE) {
+ nCmdShow = SW_SHOWNOACTIVATE;
+ }
+ ShowWindow(hwnd, nCmdShow);
+}
+
+void
+WIN_HideWindow(_THIS, SDL_Window * window)
+{
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ ShowWindow(hwnd, SW_HIDE);
+}
+
+void
+WIN_RaiseWindow(_THIS, SDL_Window * window)
+{
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ SetForegroundWindow(hwnd);
+}
+
+void
+WIN_MaximizeWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ data->expected_resize = SDL_TRUE;
+ ShowWindow(hwnd, SW_MAXIMIZE);
+ data->expected_resize = SDL_FALSE;
+}
+
+void
+WIN_MinimizeWindow(_THIS, SDL_Window * window)
+{
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ ShowWindow(hwnd, SW_MINIMIZE);
+}
+
+void
+WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ DWORD style;
+
+ style = GetWindowLong(hwnd, GWL_STYLE);
+ style &= ~STYLE_MASK;
+ style |= GetWindowStyle(window);
+
+ data->in_border_change = SDL_TRUE;
+ SetWindowLong(hwnd, GWL_STYLE, style);
+ WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE);
+ data->in_border_change = SDL_FALSE;
+}
+
+void
+WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ DWORD style;
+
+ style = GetWindowLong(hwnd, GWL_STYLE);
+ style &= ~STYLE_MASK;
+ style |= GetWindowStyle(window);
+
+ SetWindowLong(hwnd, GWL_STYLE, style);
+}
+
+void
+WIN_RestoreWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ data->expected_resize = SDL_TRUE;
+ ShowWindow(hwnd, SW_RESTORE);
+ data->expected_resize = SDL_FALSE;
+}
+
+void
+WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ HWND hwnd = data->hwnd;
+ SDL_Rect bounds;
+ DWORD style;
+ HWND top;
+ int x, y;
+ int w, h;
+
+ if (SDL_ShouldAllowTopmost() && ((window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS)) == (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_INPUT_FOCUS) || window->flags & SDL_WINDOW_ALWAYS_ON_TOP)) {
+ top = HWND_TOPMOST;
+ } else {
+ top = HWND_NOTOPMOST;
+ }
+
+ style = GetWindowLong(hwnd, GWL_STYLE);
+ style &= ~STYLE_MASK;
+ style |= GetWindowStyle(window);
+
+ WIN_GetDisplayBounds(_this, display, &bounds);
+
+ if (fullscreen) {
+ x = bounds.x;
+ y = bounds.y;
+ w = bounds.w;
+ h = bounds.h;
+
+ /* Unset the maximized flag. This fixes
+ https://bugzilla.libsdl.org/show_bug.cgi?id=3215
+ */
+ if (style & WS_MAXIMIZE) {
+ data->windowed_mode_was_maximized = SDL_TRUE;
+ style &= ~WS_MAXIMIZE;
+ }
+ } else {
+ BOOL menu;
+
+ /* Restore window-maximization state, as applicable.
+ Special care is taken to *not* do this if and when we're
+ alt-tab'ing away (to some other window; as indicated by
+ in_window_deactivation), otherwise
+ https://bugzilla.libsdl.org/show_bug.cgi?id=3215 can reproduce!
+ */
+ if (data->windowed_mode_was_maximized && !data->in_window_deactivation) {
+ style |= WS_MAXIMIZE;
+ data->windowed_mode_was_maximized = SDL_FALSE;
+ }
+
+ menu = (style & WS_CHILDWINDOW) ? FALSE : (GetMenu(hwnd) != NULL);
+ WIN_AdjustWindowRectWithStyle(window, style, menu, &x, &y, &w, &h, SDL_FALSE);
+ }
+ SetWindowLong(hwnd, GWL_STYLE, style);
+ data->expected_resize = SDL_TRUE;
+ SetWindowPos(hwnd, top, x, y, w, h, SWP_NOCOPYBITS | SWP_NOACTIVATE);
+ data->expected_resize = SDL_FALSE;
+}
+
+int
+WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp)
+{
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+ HDC hdc;
+ BOOL succeeded = FALSE;
+
+ hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
+ if (hdc) {
+ succeeded = SetDeviceGammaRamp(hdc, (LPVOID)ramp);
+ if (!succeeded) {
+ WIN_SetError("SetDeviceGammaRamp()");
+ }
+ DeleteDC(hdc);
+ }
+ return succeeded ? 0 : -1;
+}
+
+int
+WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp)
+{
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+ HDC hdc;
+ BOOL succeeded = FALSE;
+
+ hdc = CreateDC(data->DeviceName, NULL, NULL, NULL);
+ if (hdc) {
+ succeeded = GetDeviceGammaRamp(hdc, (LPVOID)ramp);
+ if (!succeeded) {
+ WIN_SetError("GetDeviceGammaRamp()");
+ }
+ DeleteDC(hdc);
+ }
+ return succeeded ? 0 : -1;
+}
+
+void
+WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
+{
+ WIN_UpdateClipCursor(window);
+
+ if (window->flags & SDL_WINDOW_FULLSCREEN) {
+ UINT flags = SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE;
+
+ if (!(window->flags & SDL_WINDOW_SHOWN)) {
+ flags |= SWP_NOACTIVATE;
+ }
+ WIN_SetWindowPositionInternal(_this, window, flags);
+ }
+}
+
+void
+WIN_DestroyWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (data) {
+ ReleaseDC(data->hwnd, data->hdc);
+ RemoveProp(data->hwnd, TEXT("SDL_WindowData"));
+ if (data->created) {
+ DestroyWindow(data->hwnd);
+ if (data->parent) {
+ DestroyWindow(data->parent);
+ }
+ } else {
+ /* Restore any original event handler... */
+ if (data->wndproc != NULL) {
+#ifdef GWLP_WNDPROC
+ SetWindowLongPtr(data->hwnd, GWLP_WNDPROC,
+ (LONG_PTR) data->wndproc);
+#else
+ SetWindowLong(data->hwnd, GWL_WNDPROC,
+ (LONG_PTR) data->wndproc);
+#endif
+ }
+ }
+ SDL_free(data);
+ }
+ window->driverdata = NULL;
+}
+
+SDL_bool
+WIN_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
+{
+ const SDL_WindowData *data = (const SDL_WindowData *) window->driverdata;
+ if (info->version.major <= SDL_MAJOR_VERSION) {
+ int versionnum = SDL_VERSIONNUM(info->version.major, info->version.minor, info->version.patch);
+
+ info->subsystem = SDL_SYSWM_WINDOWS;
+ info->info.win.window = data->hwnd;
+
+ if (versionnum >= SDL_VERSIONNUM(2, 0, 4)) {
+ info->info.win.hdc = data->hdc;
+ }
+
+ if (versionnum >= SDL_VERSIONNUM(2, 0, 5)) {
+ info->info.win.hinstance = data->hinstance;
+ }
+
+ return SDL_TRUE;
+ } else {
+ SDL_SetError("Application not compiled with SDL %d.%d",
+ SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
+ return SDL_FALSE;
+ }
+}
+
+
+/*
+ * Creates a HelperWindow used for DirectInput events.
+ */
+int
+SDL_HelperWindowCreate(void)
+{
+ HINSTANCE hInstance = GetModuleHandle(NULL);
+ WNDCLASS wce;
+
+ /* Make sure window isn't created twice. */
+ if (SDL_HelperWindow != NULL) {
+ return 0;
+ }
+
+ /* Create the class. */
+ SDL_zero(wce);
+ wce.lpfnWndProc = DefWindowProc;
+ wce.lpszClassName = (LPCWSTR) SDL_HelperWindowClassName;
+ wce.hInstance = hInstance;
+
+ /* Register the class. */
+ SDL_HelperWindowClass = RegisterClass(&wce);
+ if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) {
+ return WIN_SetError("Unable to create Helper Window Class");
+ }
+
+ /* Create the window. */
+ SDL_HelperWindow = CreateWindowEx(0, SDL_HelperWindowClassName,
+ SDL_HelperWindowName,
+ WS_OVERLAPPED, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, HWND_MESSAGE, NULL,
+ hInstance, NULL);
+ if (SDL_HelperWindow == NULL) {
+ UnregisterClass(SDL_HelperWindowClassName, hInstance);
+ return WIN_SetError("Unable to create Helper Window");
+ }
+
+ return 0;
+}
+
+
+/*
+ * Destroys the HelperWindow previously created with SDL_HelperWindowCreate.
+ */
+void
+SDL_HelperWindowDestroy(void)
+{
+ HINSTANCE hInstance = GetModuleHandle(NULL);
+
+ /* Destroy the window. */
+ if (SDL_HelperWindow != NULL) {
+ if (DestroyWindow(SDL_HelperWindow) == 0) {
+ WIN_SetError("Unable to destroy Helper Window");
+ return;
+ }
+ SDL_HelperWindow = NULL;
+ }
+
+ /* Unregister the class. */
+ if (SDL_HelperWindowClass != 0) {
+ if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) {
+ WIN_SetError("Unable to destroy Helper Window Class");
+ return;
+ }
+ SDL_HelperWindowClass = 0;
+ }
+}
+
+void WIN_OnWindowEnter(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+
+ if (!data || !data->hwnd) {
+ /* The window wasn't fully initialized */
+ return;
+ }
+
+ if (window->flags & SDL_WINDOW_ALWAYS_ON_TOP) {
+ WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+
+#ifdef WM_MOUSELEAVE
+ {
+ TRACKMOUSEEVENT trackMouseEvent;
+
+ trackMouseEvent.cbSize = sizeof(TRACKMOUSEEVENT);
+ trackMouseEvent.dwFlags = TME_LEAVE;
+ trackMouseEvent.hwndTrack = data->hwnd;
+
+ TrackMouseEvent(&trackMouseEvent);
+ }
+#endif /* WM_MOUSELEAVE */
+}
+
+void
+WIN_UpdateClipCursor(SDL_Window *window)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_Mouse *mouse = SDL_GetMouse();
+ RECT rect;
+
+ if (data->in_title_click || data->focus_click_pending) {
+ return;
+ }
+ if (data->skip_update_clipcursor) {
+ data->skip_update_clipcursor = SDL_FALSE;
+ return;
+ }
+
+ if ((mouse->relative_mode || (window->flags & SDL_WINDOW_INPUT_GRABBED)) &&
+ (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
+ if (mouse->relative_mode && !mouse->relative_mode_warp) {
+ LONG cx, cy;
+ GetWindowRect(data->hwnd, &rect);
+
+ cx = (rect.left + rect.right) / 2;
+ cy = (rect.top + rect.bottom) / 2;
+
+ /* Make an absurdly small clip rect */
+ rect.left = cx - 1;
+ rect.right = cx + 1;
+ rect.top = cy - 1;
+ rect.bottom = cy + 1;
+
+ if (ClipCursor(&rect)) {
+ data->cursor_clipped_rect = rect;
+ }
+ } else {
+ if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) {
+ ClientToScreen(data->hwnd, (LPPOINT) & rect);
+ ClientToScreen(data->hwnd, (LPPOINT) & rect + 1);
+ if (ClipCursor(&rect)) {
+ data->cursor_clipped_rect = rect;
+ }
+ }
+ }
+ } else if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) {
+ ClipCursor(NULL);
+ SDL_zero(data->cursor_clipped_rect);
+ }
+}
+
+int
+WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
+{
+ return 0; /* just succeed, the real work is done elsewhere. */
+}
+
+int
+WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ const HWND hwnd = data->hwnd;
+ const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ SDL_assert(style != 0);
+
+ if (opacity == 1.0f) {
+ /* want it fully opaque, just mark it unlayered if necessary. */
+ if (style & WS_EX_LAYERED) {
+ if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
+ return WIN_SetError("SetWindowLong()");
+ }
+ }
+ } else {
+ const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
+ /* want it transparent, mark it layered if necessary. */
+ if ((style & WS_EX_LAYERED) == 0) {
+ if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
+ return WIN_SetError("SetWindowLong()");
+ }
+ }
+
+ if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
+ return WIN_SetError("SetLayeredWindowAttributes()");
+ }
+ }
+
+ return 0;
+}
+
+void
+WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept)
+{
+ const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ DragAcceptFiles(data->hwnd, accept ? TRUE : FALSE);
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINDOWS */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.h b/source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.h
new file mode 100644
index 0000000..b738c34
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/SDL_windowswindow.h
@@ -0,0 +1,87 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifndef SDL_windowswindow_h_
+#define SDL_windowswindow_h_
+
+#if SDL_VIDEO_OPENGL_EGL
+#include "../SDL_egl_c.h"
+#endif
+
+typedef struct
+{
+ SDL_Window *window;
+ HWND hwnd;
+ HWND parent;
+ HDC hdc;
+ HDC mdc;
+ HINSTANCE hinstance;
+ HBITMAP hbm;
+ WNDPROC wndproc;
+ SDL_bool created;
+ WPARAM mouse_button_flags;
+ SDL_bool initializing;
+ SDL_bool expected_resize;
+ SDL_bool in_border_change;
+ SDL_bool in_title_click;
+ Uint8 focus_click_pending;
+ SDL_bool skip_update_clipcursor;
+ SDL_bool windowed_mode_was_maximized;
+ SDL_bool in_window_deactivation;
+ RECT cursor_clipped_rect;
+ struct SDL_VideoData *videodata;
+#if SDL_VIDEO_OPENGL_EGL
+ EGLSurface egl_surface;
+#endif
+} SDL_WindowData;
+
+extern int WIN_CreateWindow(_THIS, SDL_Window * window);
+extern int WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data);
+extern void WIN_SetWindowTitle(_THIS, SDL_Window * window);
+extern void WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
+extern void WIN_SetWindowPosition(_THIS, SDL_Window * window);
+extern void WIN_SetWindowSize(_THIS, SDL_Window * window);
+extern int WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
+extern int WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
+extern void WIN_ShowWindow(_THIS, SDL_Window * window);
+extern void WIN_HideWindow(_THIS, SDL_Window * window);
+extern void WIN_RaiseWindow(_THIS, SDL_Window * window);
+extern void WIN_MaximizeWindow(_THIS, SDL_Window * window);
+extern void WIN_MinimizeWindow(_THIS, SDL_Window * window);
+extern void WIN_RestoreWindow(_THIS, SDL_Window * window);
+extern void WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
+extern void WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
+extern int WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
+extern int WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
+extern void WIN_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
+extern void WIN_DestroyWindow(_THIS, SDL_Window * window);
+extern SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window * window,
+ struct SDL_SysWMinfo *info);
+extern void WIN_OnWindowEnter(_THIS, SDL_Window * window);
+extern void WIN_UpdateClipCursor(SDL_Window *window);
+extern int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
+extern void WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept);
+
+#endif /* SDL_windowswindow_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/source/3rd-party/SDL2/src/video/windows/wmmsg.h b/source/3rd-party/SDL2/src/video/windows/wmmsg.h
new file mode 100644
index 0000000..19c1bf4
--- /dev/null
+++ b/source/3rd-party/SDL2/src/video/windows/wmmsg.h
@@ -0,0 +1,1052 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#define MAX_WMMSG (sizeof(wmtab)/sizeof(wmtab[0]))
+
+char *wmtab[] = {
+ "WM_NULL",
+ "WM_CREATE",
+ "WM_DESTROY",
+ "WM_MOVE",
+ "UNKNOWN (4)",
+ "WM_SIZE",
+ "WM_ACTIVATE",
+ "WM_SETFOCUS",
+ "WM_KILLFOCUS",
+ "UNKNOWN (9)",
+ "WM_ENABLE",
+ "WM_SETREDRAW",
+ "WM_SETTEXT",
+ "WM_GETTEXT",
+ "WM_GETTEXTLENGTH",
+ "WM_PAINT",
+ "WM_CLOSE",
+ "WM_QUERYENDSESSION",
+ "WM_QUIT",
+ "WM_QUERYOPEN",
+ "WM_ERASEBKGND",
+ "WM_SYSCOLORCHANGE",
+ "WM_ENDSESSION",
+ "UNKNOWN (23)",
+ "WM_SHOWWINDOW",
+ "UNKNOWN (25)",
+ "WM_SETTINGCHANGE",
+ "WM_DEVMODECHANGE",
+ "WM_ACTIVATEAPP",
+ "WM_FONTCHANGE",
+ "WM_TIMECHANGE",
+ "WM_CANCELMODE",
+ "WM_SETCURSOR",
+ "WM_MOUSEACTIVATE",
+ "WM_CHILDACTIVATE",
+ "WM_QUEUESYNC",
+ "WM_GETMINMAXINFO",
+ "UNKNOWN (37)",
+ "WM_PAINTICON",
+ "WM_ICONERASEBKGND",
+ "WM_NEXTDLGCTL",
+ "UNKNOWN (41)",
+ "WM_SPOOLERSTATUS",
+ "WM_DRAWITEM",
+ "WM_MEASUREITEM",
+ "WM_DELETEITEM",
+ "WM_VKEYTOITEM",
+ "WM_CHARTOITEM",
+ "WM_SETFONT",
+ "WM_GETFONT",
+ "WM_SETHOTKEY",
+ "WM_GETHOTKEY",
+ "UNKNOWN (52)",
+ "UNKNOWN (53)",
+ "UNKNOWN (54)",
+ "WM_QUERYDRAGICON",
+ "UNKNOWN (56)",
+ "WM_COMPAREITEM",
+ "UNKNOWN (58)",
+ "UNKNOWN (59)",
+ "UNKNOWN (60)",
+ "WM_GETOBJECT",
+ "UNKNOWN (62)",
+ "UNKNOWN (63)",
+ "UNKNOWN (64)",
+ "WM_COMPACTING",
+ "UNKNOWN (66)",
+ "UNKNOWN (67)",
+ "WM_COMMNOTIFY",
+ "UNKNOWN (69)",
+ "WM_WINDOWPOSCHANGING",
+ "WM_WINDOWPOSCHANGED",
+ "WM_POWER",
+ "UNKNOWN (73)",
+ "WM_COPYDATA",
+ "WM_CANCELJOURNAL",
+ "UNKNOWN (76)",
+ "UNKNOWN (77)",
+ "WM_NOTIFY",
+ "UNKNOWN (79)",
+ "WM_INPUTLANGCHANGEREQUEST",
+ "WM_INPUTLANGCHANGE",
+ "WM_TCARD",
+ "WM_HELP",
+ "WM_USERCHANGED",
+ "WM_NOTIFYFORMAT",
+ "UNKNOWN (86)",
+ "UNKNOWN (87)",
+ "UNKNOWN (88)",
+ "UNKNOWN (89)",
+ "UNKNOWN (90)",
+ "UNKNOWN (91)",
+ "UNKNOWN (92)",
+ "UNKNOWN (93)",
+ "UNKNOWN (94)",
+ "UNKNOWN (95)",
+ "UNKNOWN (96)",
+ "UNKNOWN (97)",
+ "UNKNOWN (98)",
+ "UNKNOWN (99)",
+ "UNKNOWN (100)",
+ "UNKNOWN (101)",
+ "UNKNOWN (102)",
+ "UNKNOWN (103)",
+ "UNKNOWN (104)",
+ "UNKNOWN (105)",
+ "UNKNOWN (106)",
+ "UNKNOWN (107)",
+ "UNKNOWN (108)",
+ "UNKNOWN (109)",
+ "UNKNOWN (110)",
+ "UNKNOWN (111)",
+ "UNKNOWN (112)",
+ "UNKNOWN (113)",
+ "UNKNOWN (114)",
+ "UNKNOWN (115)",
+ "UNKNOWN (116)",
+ "UNKNOWN (117)",
+ "UNKNOWN (118)",
+ "UNKNOWN (119)",
+ "UNKNOWN (120)",
+ "UNKNOWN (121)",
+ "UNKNOWN (122)",
+ "WM_CONTEXTMENU",
+ "WM_STYLECHANGING",
+ "WM_STYLECHANGED",
+ "WM_DISPLAYCHANGE",
+ "WM_GETICON",
+ "WM_SETICON",
+ "WM_NCCREATE",
+ "WM_NCDESTROY",
+ "WM_NCCALCSIZE",
+ "WM_NCHITTEST",
+ "WM_NCPAINT",
+ "WM_NCACTIVATE",
+ "WM_GETDLGCODE",
+ "WM_SYNCPAINT",
+ "UNKNOWN (137)",
+ "UNKNOWN (138)",
+ "UNKNOWN (139)",
+ "UNKNOWN (140)",
+ "UNKNOWN (141)",
+ "UNKNOWN (142)",
+ "UNKNOWN (143)",
+ "UNKNOWN (144)",
+ "UNKNOWN (145)",
+ "UNKNOWN (146)",
+ "UNKNOWN (147)",
+ "UNKNOWN (148)",
+ "UNKNOWN (149)",
+ "UNKNOWN (150)",
+ "UNKNOWN (151)",
+ "UNKNOWN (152)",
+ "UNKNOWN (153)",
+ "UNKNOWN (154)",
+ "UNKNOWN (155)",
+ "UNKNOWN (156)",
+ "UNKNOWN (157)",
+ "UNKNOWN (158)",
+ "UNKNOWN (159)",
+ "WM_NCMOUSEMOVE",
+ "WM_NCLBUTTONDOWN",
+ "WM_NCLBUTTONUP",
+ "WM_NCLBUTTONDBLCLK",
+ "WM_NCRBUTTONDOWN",
+ "WM_NCRBUTTONUP",
+ "WM_NCRBUTTONDBLCLK",
+ "WM_NCMBUTTONDOWN",
+ "WM_NCMBUTTONUP",
+ "WM_NCMBUTTONDBLCLK",
+ "UNKNOWN (170)",
+ "WM_NCXBUTTONDOWN",
+ "WM_NCXBUTTONUP",
+ "WM_NCXBUTTONDBLCLK",
+ "WM_NCUAHDRAWCAPTION",
+ "WM_NCUAHDRAWFRAME",
+ "UNKNOWN (176)",
+ "UNKNOWN (177)",
+ "UNKNOWN (178)",
+ "UNKNOWN (179)",
+ "UNKNOWN (180)",
+ "UNKNOWN (181)",
+ "UNKNOWN (182)",
+ "UNKNOWN (183)",
+ "UNKNOWN (184)",
+ "UNKNOWN (185)",
+ "UNKNOWN (186)",
+ "UNKNOWN (187)",
+ "UNKNOWN (188)",
+ "UNKNOWN (189)",
+ "UNKNOWN (190)",
+ "UNKNOWN (191)",
+ "UNKNOWN (192)",
+ "UNKNOWN (193)",
+ "UNKNOWN (194)",
+ "UNKNOWN (195)",
+ "UNKNOWN (196)",
+ "UNKNOWN (197)",
+ "UNKNOWN (198)",
+ "UNKNOWN (199)",
+ "UNKNOWN (200)",
+ "UNKNOWN (201)",
+ "UNKNOWN (202)",
+ "UNKNOWN (203)",
+ "UNKNOWN (204)",
+ "UNKNOWN (205)",
+ "UNKNOWN (206)",
+ "UNKNOWN (207)",
+ "UNKNOWN (208)",
+ "UNKNOWN (209)",
+ "UNKNOWN (210)",
+ "UNKNOWN (211)",
+ "UNKNOWN (212)",
+ "UNKNOWN (213)",
+ "UNKNOWN (214)",
+ "UNKNOWN (215)",
+ "UNKNOWN (216)",
+ "UNKNOWN (217)",
+ "UNKNOWN (218)",
+ "UNKNOWN (219)",
+ "UNKNOWN (220)",
+ "UNKNOWN (221)",
+ "UNKNOWN (222)",
+ "UNKNOWN (223)",
+ "UNKNOWN (224)",
+ "UNKNOWN (225)",
+ "UNKNOWN (226)",
+ "UNKNOWN (227)",
+ "UNKNOWN (228)",
+ "UNKNOWN (229)",
+ "UNKNOWN (230)",
+ "UNKNOWN (231)",
+ "UNKNOWN (232)",
+ "UNKNOWN (233)",
+ "UNKNOWN (234)",
+ "UNKNOWN (235)",
+ "UNKNOWN (236)",
+ "UNKNOWN (237)",
+ "UNKNOWN (238)",
+ "UNKNOWN (239)",
+ "UNKNOWN (240)",
+ "UNKNOWN (241)",
+ "UNKNOWN (242)",
+ "UNKNOWN (243)",
+ "UNKNOWN (244)",
+ "UNKNOWN (245)",
+ "UNKNOWN (246)",
+ "UNKNOWN (247)",
+ "UNKNOWN (248)",
+ "UNKNOWN (249)",
+ "UNKNOWN (250)",
+ "UNKNOWN (251)",
+ "UNKNOWN (252)",
+ "UNKNOWN (253)",
+ "UNKNOWN (254)",
+ "WM_INPUT",
+ "WM_KEYDOWN",
+ "WM_KEYUP",
+ "WM_CHAR",
+ "WM_DEADCHAR",
+ "WM_SYSKEYDOWN",
+ "WM_SYSKEYUP",
+ "WM_SYSCHAR",
+ "WM_SYSDEADCHAR",
+ "WM_KEYLAST",
+ "UNKNOWN (265)",
+ "UNKNOWN (266)",
+ "UNKNOWN (267)",
+ "UNKNOWN (268)",
+ "UNKNOWN (269)",
+ "UNKNOWN (270)",
+ "UNKNOWN (271)",
+ "WM_INITDIALOG",
+ "WM_COMMAND",
+ "WM_SYSCOMMAND",
+ "WM_TIMER",
+ "WM_HSCROLL",
+ "WM_VSCROLL",
+ "WM_INITMENU",
+ "WM_INITMENUPOPUP",
+ "UNKNOWN (280)",
+ "WM_GESTURE",
+ "UNKNOWN (282)",
+ "UNKNOWN (283)",
+ "UNKNOWN (284)",
+ "UNKNOWN (285)",
+ "UNKNOWN (286)",
+ "WM_MENUSELECT",
+ "WM_MENUCHAR",
+ "WM_ENTERIDLE",
+ "WM_MENURBUTTONUP",
+ "WM_MENUDRAG",
+ "WM_MENUGETOBJECT",
+ "WM_UNINITMENUPOPUP",
+ "WM_MENUCOMMAND",
+ "UNKNOWN (295)",
+ "UNKNOWN (296)",
+ "UNKNOWN (297)",
+ "UNKNOWN (298)",
+ "UNKNOWN (299)",
+ "UNKNOWN (300)",
+ "UNKNOWN (301)",
+ "UNKNOWN (302)",
+ "UNKNOWN (303)",
+ "UNKNOWN (304)",
+ "UNKNOWN (305)",
+ "WM_CTLCOLORMSGBOX",
+ "WM_CTLCOLOREDIT",
+ "WM_CTLCOLORLISTBOX",
+ "WM_CTLCOLORBTN",
+ "WM_CTLCOLORDLG",
+ "WM_CTLCOLORSCROLLBAR",
+ "WM_CTLCOLORSTATIC",
+ "UNKNOWN (313)",
+ "UNKNOWN (314)",
+ "UNKNOWN (315)",
+ "UNKNOWN (316)",
+ "UNKNOWN (317)",
+ "UNKNOWN (318)",
+ "UNKNOWN (319)",
+ "UNKNOWN (320)",
+ "UNKNOWN (321)",
+ "UNKNOWN (322)",
+ "UNKNOWN (323)",
+ "UNKNOWN (324)",
+ "UNKNOWN (325)",
+ "UNKNOWN (326)",
+ "UNKNOWN (327)",
+ "UNKNOWN (328)",
+ "UNKNOWN (329)",
+ "UNKNOWN (330)",
+ "UNKNOWN (331)",
+ "UNKNOWN (332)",
+ "UNKNOWN (333)",
+ "UNKNOWN (334)",
+ "UNKNOWN (335)",
+ "UNKNOWN (336)",
+ "UNKNOWN (337)",
+ "UNKNOWN (338)",
+ "UNKNOWN (339)",
+ "UNKNOWN (340)",
+ "UNKNOWN (341)",
+ "UNKNOWN (342)",
+ "UNKNOWN (343)",
+ "UNKNOWN (344)",
+ "UNKNOWN (345)",
+ "UNKNOWN (346)",
+ "UNKNOWN (347)",
+ "UNKNOWN (348)",
+ "UNKNOWN (349)",
+ "UNKNOWN (350)",
+ "UNKNOWN (351)",
+ "UNKNOWN (352)",
+ "UNKNOWN (353)",
+ "UNKNOWN (354)",
+ "UNKNOWN (355)",
+ "UNKNOWN (356)",
+ "UNKNOWN (357)",
+ "UNKNOWN (358)",
+ "UNKNOWN (359)",
+ "UNKNOWN (360)",
+ "UNKNOWN (361)",
+ "UNKNOWN (362)",
+ "UNKNOWN (363)",
+ "UNKNOWN (364)",
+ "UNKNOWN (365)",
+ "UNKNOWN (366)",
+ "UNKNOWN (367)",
+ "UNKNOWN (368)",
+ "UNKNOWN (369)",
+ "UNKNOWN (370)",
+ "UNKNOWN (371)",
+ "UNKNOWN (372)",
+ "UNKNOWN (373)",
+ "UNKNOWN (374)",
+ "UNKNOWN (375)",
+ "UNKNOWN (376)",
+ "UNKNOWN (377)",
+ "UNKNOWN (378)",
+ "UNKNOWN (379)",
+ "UNKNOWN (380)",
+ "UNKNOWN (381)",
+ "UNKNOWN (382)",
+ "UNKNOWN (383)",
+ "UNKNOWN (384)",
+ "UNKNOWN (385)",
+ "UNKNOWN (386)",
+ "UNKNOWN (387)",
+ "UNKNOWN (388)",
+ "UNKNOWN (389)",
+ "UNKNOWN (390)",
+ "UNKNOWN (391)",
+ "UNKNOWN (392)",
+ "UNKNOWN (393)",
+ "UNKNOWN (394)",
+ "UNKNOWN (395)",
+ "UNKNOWN (396)",
+ "UNKNOWN (397)",
+ "UNKNOWN (398)",
+ "UNKNOWN (399)",
+ "UNKNOWN (400)",
+ "UNKNOWN (401)",
+ "UNKNOWN (402)",
+ "UNKNOWN (403)",
+ "UNKNOWN (404)",
+ "UNKNOWN (405)",
+ "UNKNOWN (406)",
+ "UNKNOWN (407)",
+ "UNKNOWN (408)",
+ "UNKNOWN (409)",
+ "UNKNOWN (410)",
+ "UNKNOWN (411)",
+ "UNKNOWN (412)",
+ "UNKNOWN (413)",
+ "UNKNOWN (414)",
+ "UNKNOWN (415)",
+ "UNKNOWN (416)",
+ "UNKNOWN (417)",
+ "UNKNOWN (418)",
+ "UNKNOWN (419)",
+ "UNKNOWN (420)",
+ "UNKNOWN (421)",
+ "UNKNOWN (422)",
+ "UNKNOWN (423)",
+ "UNKNOWN (424)",
+ "UNKNOWN (425)",
+ "UNKNOWN (426)",
+ "UNKNOWN (427)",
+ "UNKNOWN (428)",
+ "UNKNOWN (429)",
+ "UNKNOWN (430)",
+ "UNKNOWN (431)",
+ "UNKNOWN (432)",
+ "UNKNOWN (433)",
+ "UNKNOWN (434)",
+ "UNKNOWN (435)",
+ "UNKNOWN (436)",
+ "UNKNOWN (437)",
+ "UNKNOWN (438)",
+ "UNKNOWN (439)",
+ "UNKNOWN (440)",
+ "UNKNOWN (441)",
+ "UNKNOWN (442)",
+ "UNKNOWN (443)",
+ "UNKNOWN (444)",
+ "UNKNOWN (445)",
+ "UNKNOWN (446)",
+ "UNKNOWN (447)",
+ "UNKNOWN (448)",
+ "UNKNOWN (449)",
+ "UNKNOWN (450)",
+ "UNKNOWN (451)",
+ "UNKNOWN (452)",
+ "UNKNOWN (453)",
+ "UNKNOWN (454)",
+ "UNKNOWN (455)",
+ "UNKNOWN (456)",
+ "UNKNOWN (457)",
+ "UNKNOWN (458)",
+ "UNKNOWN (459)",
+ "UNKNOWN (460)",
+ "UNKNOWN (461)",
+ "UNKNOWN (462)",
+ "UNKNOWN (463)",
+ "UNKNOWN (464)",
+ "UNKNOWN (465)",
+ "UNKNOWN (466)",
+ "UNKNOWN (467)",
+ "UNKNOWN (468)",
+ "UNKNOWN (469)",
+ "UNKNOWN (470)",
+ "UNKNOWN (471)",
+ "UNKNOWN (472)",
+ "UNKNOWN (473)",
+ "UNKNOWN (474)",
+ "UNKNOWN (475)",
+ "UNKNOWN (476)",
+ "UNKNOWN (477)",
+ "UNKNOWN (478)",
+ "UNKNOWN (479)",
+ "UNKNOWN (480)",
+ "UNKNOWN (481)",
+ "UNKNOWN (482)",
+ "UNKNOWN (483)",
+ "UNKNOWN (484)",
+ "UNKNOWN (485)",
+ "UNKNOWN (486)",
+ "UNKNOWN (487)",
+ "UNKNOWN (488)",
+ "UNKNOWN (489)",
+ "UNKNOWN (490)",
+ "UNKNOWN (491)",
+ "UNKNOWN (492)",
+ "UNKNOWN (493)",
+ "UNKNOWN (494)",
+ "UNKNOWN (495)",
+ "UNKNOWN (496)",
+ "UNKNOWN (497)",
+ "UNKNOWN (498)",
+ "UNKNOWN (499)",
+ "UNKNOWN (500)",
+ "UNKNOWN (501)",
+ "UNKNOWN (502)",
+ "UNKNOWN (503)",
+ "UNKNOWN (504)",
+ "UNKNOWN (505)",
+ "UNKNOWN (506)",
+ "UNKNOWN (507)",
+ "UNKNOWN (508)",
+ "UNKNOWN (509)",
+ "UNKNOWN (510)",
+ "UNKNOWN (511)",
+ "WM_MOUSEMOVE",
+ "WM_LBUTTONDOWN",
+ "WM_LBUTTONUP",
+ "WM_LBUTTONDBLCLK",
+ "WM_RBUTTONDOWN",
+ "WM_RBUTTONUP",
+ "WM_RBUTTONDBLCLK",
+ "WM_MBUTTONDOWN",
+ "WM_MBUTTONUP",
+ "WM_MOUSELAST",
+ "WM_MOUSEWHEEL",
+ "WM_XBUTTONDOWN",
+ "WM_XBUTTONUP",
+ "UNKNOWN (525)",
+ "UNKNOWN (526)",
+ "UNKNOWN (527)",
+ "WM_PARENTNOTIFY",
+ "WM_ENTERMENULOOP",
+ "WM_EXITMENULOOP",
+ "WM_NEXTMENU",
+ "WM_SIZING",
+ "WM_CAPTURECHANGED",
+ "WM_MOVING",
+ "UNKNOWN (535)",
+ "WM_POWERBROADCAST",
+ "WM_DEVICECHANGE",
+ "UNKNOWN (538)",
+ "UNKNOWN (539)",
+ "UNKNOWN (540)",
+ "UNKNOWN (541)",
+ "UNKNOWN (542)",
+ "UNKNOWN (543)",
+ "WM_MDICREATE",
+ "WM_MDIDESTROY",
+ "WM_MDIACTIVATE",
+ "WM_MDIRESTORE",
+ "WM_MDINEXT",
+ "WM_MDIMAXIMIZE",
+ "WM_MDITILE",
+ "WM_MDICASCADE",
+ "WM_MDIICONARRANGE",
+ "WM_MDIGETACTIVE",
+ "UNKNOWN (554)",
+ "UNKNOWN (555)",
+ "UNKNOWN (556)",
+ "UNKNOWN (557)",
+ "UNKNOWN (558)",
+ "UNKNOWN (559)",
+ "WM_MDISETMENU",
+ "WM_ENTERSIZEMOVE",
+ "WM_EXITSIZEMOVE",
+ "WM_DROPFILES",
+ "WM_MDIREFRESHMENU",
+ "UNKNOWN (565)",
+ "UNKNOWN (566)",
+ "UNKNOWN (567)",
+ "WM_POINTERDEVICECHANGE",
+ "WM_POINTERDEVICEINRANGE",
+ "WM_POINTERDEVICEOUTOFRANGE",
+ "UNKNOWN (571)",
+ "UNKNOWN (572)",
+ "UNKNOWN (573)",
+ "UNKNOWN (574)",
+ "UNKNOWN (575)",
+ "WM_TOUCH",
+ "WM_NCPOINTERUPDATE",
+ "WM_NCPOINTERDOWN",
+ "WM_NCPOINTERUP",
+ "UNKNOWN (580)",
+ "WM_POINTERUPDATE",
+ "WM_POINTERDOWN",
+ "WM_POINTERUP",
+ "WM_POINTERENTER",
+ "WM_POINTERLEAVE",
+ "WM_POINTERACTIVATE",
+ "WM_POINTERCAPTURECHANGED",
+ "WM_TOUCHHITTESTING",
+ "WM_POINTERWHEEL",
+ "WM_POINTERHWHEEL",
+ "DM_POINTERHITTEST",
+ "UNKNOWN (592)",
+ "UNKNOWN (593)",
+ "UNKNOWN (594)",
+ "UNKNOWN (595)",
+ "UNKNOWN (596)",
+ "UNKNOWN (597)",
+ "UNKNOWN (598)",
+ "UNKNOWN (599)",
+ "UNKNOWN (600)",
+ "UNKNOWN (601)",
+ "UNKNOWN (602)",
+ "UNKNOWN (603)",
+ "UNKNOWN (604)",
+ "UNKNOWN (605)",
+ "UNKNOWN (606)",
+ "UNKNOWN (607)",
+ "UNKNOWN (608)",
+ "UNKNOWN (609)",
+ "UNKNOWN (610)",
+ "UNKNOWN (611)",
+ "UNKNOWN (612)",
+ "UNKNOWN (613)",
+ "UNKNOWN (614)",
+ "UNKNOWN (615)",
+ "UNKNOWN (616)",
+ "UNKNOWN (617)",
+ "UNKNOWN (618)",
+ "UNKNOWN (619)",
+ "UNKNOWN (620)",
+ "UNKNOWN (621)",
+ "UNKNOWN (622)",
+ "UNKNOWN (623)",
+ "UNKNOWN (624)",
+ "UNKNOWN (625)",
+ "UNKNOWN (626)",
+ "UNKNOWN (627)",
+ "UNKNOWN (628)",
+ "UNKNOWN (629)",
+ "UNKNOWN (630)",
+ "UNKNOWN (631)",
+ "UNKNOWN (632)",
+ "UNKNOWN (633)",
+ "UNKNOWN (634)",
+ "UNKNOWN (635)",
+ "UNKNOWN (636)",
+ "UNKNOWN (637)",
+ "UNKNOWN (638)",
+ "UNKNOWN (639)",
+ "UNKNOWN (640)",
+ "WM_IME_SETCONTEXT",
+ "WM_IME_NOTIFY",
+ "WM_IME_CONTROL",
+ "WM_IME_COMPOSITIONFULL",
+ "WM_IME_SELECT",
+ "WM_IME_CHAR",
+ "UNKNOWN (647)",
+ "WM_IME_REQUEST",
+ "UNKNOWN (649)",
+ "UNKNOWN (650)",
+ "UNKNOWN (651)",
+ "UNKNOWN (652)",
+ "UNKNOWN (653)",
+ "UNKNOWN (654)",
+ "UNKNOWN (655)",
+ "WM_IME_KEYDOWN",
+ "WM_IME_KEYUP",
+ "UNKNOWN (658)",
+ "UNKNOWN (659)",
+ "UNKNOWN (660)",
+ "UNKNOWN (661)",
+ "UNKNOWN (662)",
+ "UNKNOWN (663)",
+ "UNKNOWN (664)",
+ "UNKNOWN (665)",
+ "UNKNOWN (666)",
+ "UNKNOWN (667)",
+ "UNKNOWN (668)",
+ "UNKNOWN (669)",
+ "UNKNOWN (670)",
+ "UNKNOWN (671)",
+ "WM_NCMOUSEHOVER",
+ "WM_MOUSEHOVER",
+ "WM_NCMOUSELEAVE",
+ "WM_MOUSELEAVE",
+ "UNKNOWN (676)",
+ "UNKNOWN (677)",
+ "UNKNOWN (678)",
+ "UNKNOWN (679)",
+ "UNKNOWN (680)",
+ "UNKNOWN (681)",
+ "UNKNOWN (682)",
+ "UNKNOWN (683)",
+ "UNKNOWN (684)",
+ "UNKNOWN (685)",
+ "UNKNOWN (686)",
+ "UNKNOWN (687)",
+ "UNKNOWN (688)",
+ "WM_WTSSESSION_CHANGE",
+ "UNKNOWN (690)",
+ "UNKNOWN (691)",
+ "UNKNOWN (692)",
+ "UNKNOWN (693)",
+ "UNKNOWN (694)",
+ "UNKNOWN (695)",
+ "UNKNOWN (696)",
+ "UNKNOWN (697)",
+ "UNKNOWN (698)",
+ "UNKNOWN (699)",
+ "UNKNOWN (700)",
+ "UNKNOWN (701)",
+ "UNKNOWN (702)",
+ "UNKNOWN (703)",
+ "UNKNOWN (704)",
+ "UNKNOWN (705)",
+ "UNKNOWN (706)",
+ "UNKNOWN (707)",
+ "UNKNOWN (708)",
+ "UNKNOWN (709)",
+ "UNKNOWN (710)",
+ "UNKNOWN (711)",
+ "UNKNOWN (712)",
+ "UNKNOWN (713)",
+ "UNKNOWN (714)",
+ "UNKNOWN (715)",
+ "UNKNOWN (716)",
+ "UNKNOWN (717)",
+ "UNKNOWN (718)",
+ "UNKNOWN (719)",
+ "UNKNOWN (720)",
+ "UNKNOWN (721)",
+ "UNKNOWN (722)",
+ "UNKNOWN (723)",
+ "UNKNOWN (724)",
+ "UNKNOWN (725)",
+ "UNKNOWN (726)",
+ "UNKNOWN (727)",
+ "UNKNOWN (728)",
+ "UNKNOWN (729)",
+ "UNKNOWN (730)",
+ "UNKNOWN (731)",
+ "UNKNOWN (732)",
+ "UNKNOWN (733)",
+ "UNKNOWN (734)",
+ "UNKNOWN (735)",
+ "WM_DPICHANGED",
+ "UNKNOWN (737)",
+ "UNKNOWN (738)",
+ "UNKNOWN (739)",
+ "UNKNOWN (740)",
+ "UNKNOWN (741)",
+ "UNKNOWN (742)",
+ "UNKNOWN (743)",
+ "UNKNOWN (744)",
+ "UNKNOWN (745)",
+ "UNKNOWN (746)",
+ "UNKNOWN (747)",
+ "UNKNOWN (748)",
+ "UNKNOWN (749)",
+ "UNKNOWN (750)",
+ "UNKNOWN (751)",
+ "UNKNOWN (752)",
+ "UNKNOWN (753)",
+ "UNKNOWN (754)",
+ "UNKNOWN (755)",
+ "UNKNOWN (756)",
+ "UNKNOWN (757)",
+ "UNKNOWN (758)",
+ "UNKNOWN (759)",
+ "UNKNOWN (760)",
+ "UNKNOWN (761)",
+ "UNKNOWN (762)",
+ "UNKNOWN (763)",
+ "UNKNOWN (764)",
+ "UNKNOWN (765)",
+ "UNKNOWN (766)",
+ "UNKNOWN (767)",
+ "WM_CUT",
+ "WM_COPY",
+ "WM_PASTE",
+ "WM_CLEAR",
+ "WM_UNDO",
+ "WM_RENDERFORMAT",
+ "WM_RENDERALLFORMATS",
+ "WM_DESTROYCLIPBOARD",
+ "WM_DRAWCLIPBOARD",
+ "WM_PAINTCLIPBOARD",
+ "WM_VSCROLLCLIPBOARD",
+ "WM_SIZECLIPBOARD",
+ "WM_ASKCBFORMATNAME",
+ "WM_CHANGECBCHAIN",
+ "WM_HSCROLLCLIPBOARD",
+ "WM_QUERYNEWPALETTE",
+ "WM_PALETTEISCHANGING",
+ "WM_PALETTECHANGED",
+ "WM_HOTKEY",
+ "UNKNOWN (787)",
+ "UNKNOWN (788)",
+ "UNKNOWN (789)",
+ "UNKNOWN (790)",
+ "WM_PRINT",
+ "WM_PRINTCLIENT",
+ "WM_APPCOMMAND",
+ "WM_THEMECHANGED",
+ "UNKNOWN (795)",
+ "UNKNOWN (796)",
+ "WM_CLIPBOARDUPDATE",
+ "WM_DWMCOMPOSITIONCHANGED",
+ "WM_DWMNCRENDERINGCHANGED",
+ "WM_DWMCOLORIZATIONCOLORCHANGED",
+ "WM_DWMWINDOWMAXIMIZEDCHANGE",
+ "UNKNOWN (802)",
+ "WM_DWMSENDICONICTHUMBNAIL",
+ "UNKNOWN (804)",
+ "UNKNOWN (805)",
+ "WM_DWMSENDICONICLIVEPREVIEWBITMAP",
+ "UNKNOWN (807)",
+ "UNKNOWN (808)",
+ "UNKNOWN (809)",
+ "UNKNOWN (810)",
+ "UNKNOWN (811)",
+ "UNKNOWN (812)",
+ "UNKNOWN (813)",
+ "UNKNOWN (814)",
+ "UNKNOWN (815)",
+ "UNKNOWN (816)",
+ "UNKNOWN (817)",
+ "UNKNOWN (818)",
+ "UNKNOWN (819)",
+ "UNKNOWN (820)",
+ "UNKNOWN (821)",
+ "UNKNOWN (822)",
+ "UNKNOWN (823)",
+ "UNKNOWN (824)",
+ "UNKNOWN (825)",
+ "UNKNOWN (826)",
+ "UNKNOWN (827)",
+ "UNKNOWN (828)",
+ "UNKNOWN (829)",
+ "UNKNOWN (830)",
+ "WM_GETTITLEBARINFOEX",
+ "UNKNOWN (832)",
+ "UNKNOWN (833)",
+ "UNKNOWN (834)",
+ "UNKNOWN (835)",
+ "UNKNOWN (836)",
+ "UNKNOWN (837)",
+ "UNKNOWN (838)",
+ "UNKNOWN (839)",
+ "UNKNOWN (840)",
+ "UNKNOWN (841)",
+ "UNKNOWN (842)",
+ "UNKNOWN (843)",
+ "UNKNOWN (844)",
+ "UNKNOWN (845)",
+ "UNKNOWN (846)",
+ "UNKNOWN (847)",
+ "UNKNOWN (848)",
+ "UNKNOWN (849)",
+ "UNKNOWN (850)",
+ "UNKNOWN (851)",
+ "UNKNOWN (852)",
+ "UNKNOWN (853)",
+ "UNKNOWN (854)",
+ "UNKNOWN (855)",
+ "WM_HANDHELDFIRST",
+ "UNKNOWN (857)",
+ "UNKNOWN (858)",
+ "UNKNOWN (859)",
+ "UNKNOWN (860)",
+ "UNKNOWN (861)",
+ "UNKNOWN (862)",
+ "WM_HANDHELDLAST",
+ "WM_AFXFIRST",
+ "UNKNOWN (865)",
+ "UNKNOWN (866)",
+ "UNKNOWN (867)",
+ "UNKNOWN (868)",
+ "UNKNOWN (869)",
+ "UNKNOWN (870)",
+ "UNKNOWN (871)",
+ "UNKNOWN (872)",
+ "UNKNOWN (873)",
+ "UNKNOWN (874)",
+ "UNKNOWN (875)",
+ "UNKNOWN (876)",
+ "UNKNOWN (877)",
+ "UNKNOWN (878)",
+ "UNKNOWN (879)",
+ "UNKNOWN (880)",
+ "UNKNOWN (881)",
+ "UNKNOWN (882)",
+ "UNKNOWN (883)",
+ "UNKNOWN (884)",
+ "UNKNOWN (885)",
+ "UNKNOWN (886)",
+ "UNKNOWN (887)",
+ "UNKNOWN (888)",
+ "UNKNOWN (889)",
+ "UNKNOWN (890)",
+ "UNKNOWN (891)",
+ "UNKNOWN (892)",
+ "UNKNOWN (893)",
+ "UNKNOWN (894)",
+ "WM_AFXLAST",
+ "WM_PENWINFIRST",
+ "UNKNOWN (897)",
+ "UNKNOWN (898)",
+ "UNKNOWN (899)",
+ "UNKNOWN (900)",
+ "UNKNOWN (901)",
+ "UNKNOWN (902)",
+ "UNKNOWN (903)",
+ "UNKNOWN (904)",
+ "UNKNOWN (905)",
+ "UNKNOWN (906)",
+ "UNKNOWN (907)",
+ "UNKNOWN (908)",
+ "UNKNOWN (909)",
+ "UNKNOWN (910)",
+ "WM_PENWINLAST",
+ "UNKNOWN (912)",
+ "UNKNOWN (913)",
+ "UNKNOWN (914)",
+ "UNKNOWN (915)",
+ "UNKNOWN (916)",
+ "UNKNOWN (917)",
+ "UNKNOWN (918)",
+ "UNKNOWN (919)",
+ "UNKNOWN (920)",
+ "UNKNOWN (921)",
+ "UNKNOWN (922)",
+ "UNKNOWN (923)",
+ "UNKNOWN (924)",
+ "UNKNOWN (925)",
+ "UNKNOWN (926)",
+ "UNKNOWN (927)",
+ "UNKNOWN (928)",
+ "UNKNOWN (929)",
+ "UNKNOWN (930)",
+ "UNKNOWN (931)",
+ "UNKNOWN (932)",
+ "UNKNOWN (933)",
+ "UNKNOWN (934)",
+ "UNKNOWN (935)",
+ "UNKNOWN (936)",
+ "UNKNOWN (937)",
+ "UNKNOWN (938)",
+ "UNKNOWN (939)",
+ "UNKNOWN (940)",
+ "UNKNOWN (941)",
+ "UNKNOWN (942)",
+ "UNKNOWN (943)",
+ "UNKNOWN (944)",
+ "UNKNOWN (945)",
+ "UNKNOWN (946)",
+ "UNKNOWN (947)",
+ "UNKNOWN (948)",
+ "UNKNOWN (949)",
+ "UNKNOWN (950)",
+ "UNKNOWN (951)",
+ "UNKNOWN (952)",
+ "UNKNOWN (953)",
+ "UNKNOWN (954)",
+ "UNKNOWN (955)",
+ "UNKNOWN (956)",
+ "UNKNOWN (957)",
+ "UNKNOWN (958)",
+ "UNKNOWN (959)",
+ "UNKNOWN (960)",
+ "UNKNOWN (961)",
+ "UNKNOWN (962)",
+ "UNKNOWN (963)",
+ "UNKNOWN (964)",
+ "UNKNOWN (965)",
+ "UNKNOWN (966)",
+ "UNKNOWN (967)",
+ "UNKNOWN (968)",
+ "UNKNOWN (969)",
+ "UNKNOWN (970)",
+ "UNKNOWN (971)",
+ "UNKNOWN (972)",
+ "UNKNOWN (973)",
+ "UNKNOWN (974)",
+ "UNKNOWN (975)",
+ "UNKNOWN (976)",
+ "UNKNOWN (977)",
+ "UNKNOWN (978)",
+ "UNKNOWN (979)",
+ "UNKNOWN (980)",
+ "UNKNOWN (981)",
+ "UNKNOWN (982)",
+ "UNKNOWN (983)",
+ "UNKNOWN (984)",
+ "UNKNOWN (985)",
+ "UNKNOWN (986)",
+ "UNKNOWN (987)",
+ "UNKNOWN (988)",
+ "UNKNOWN (989)",
+ "UNKNOWN (990)",
+ "UNKNOWN (991)",
+ "UNKNOWN (992)",
+ "UNKNOWN (993)",
+ "UNKNOWN (994)",
+ "UNKNOWN (995)",
+ "UNKNOWN (996)",
+ "UNKNOWN (997)",
+ "UNKNOWN (998)",
+ "UNKNOWN (999)",
+ "UNKNOWN (1000)",
+ "UNKNOWN (1001)",
+ "UNKNOWN (1002)",
+ "UNKNOWN (1003)",
+ "UNKNOWN (1004)",
+ "UNKNOWN (1005)",
+ "UNKNOWN (1006)",
+ "UNKNOWN (1007)",
+ "UNKNOWN (1008)",
+ "UNKNOWN (1009)",
+ "UNKNOWN (1010)",
+ "UNKNOWN (1011)",
+ "UNKNOWN (1012)",
+ "UNKNOWN (1013)",
+ "UNKNOWN (1014)",
+ "UNKNOWN (1015)",
+ "UNKNOWN (1016)",
+ "UNKNOWN (1017)",
+ "UNKNOWN (1018)",
+ "UNKNOWN (1019)",
+ "UNKNOWN (1020)",
+ "UNKNOWN (1021)",
+ "UNKNOWN (1022)",
+ "UNKNOWN (1023)",
+ "WM_USER"
+};
+
+/* vi: set ts=4 sw=4 expandtab: */