diff options
Diffstat (limited to 'Source/3rdParty/SDL2/src/video/windows')
9 files changed, 720 insertions, 85 deletions
diff --git a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsevents.c b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsevents.c index a5fd006..e961cf5 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsevents.c +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsevents.c @@ -228,9 +228,7 @@ WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePress /* Ignore the button click for activation */ if (!bwParamMousePressed) { data->focus_click_pending &= ~SDL_BUTTON(button); - if (!data->focus_click_pending) { - WIN_UpdateClipCursor(data->window); - } + WIN_UpdateClipCursor(data->window); } if (WIN_ShouldIgnoreFocusClick()) { return; @@ -416,11 +414,23 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } 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) { @@ -460,6 +470,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 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) { @@ -467,7 +479,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) WIN_ResetDeadKeys(); } - ClipCursor(NULL); + 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; } @@ -648,7 +663,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; case WM_UNICHAR: - if ( wParam == UNICODE_NOCHAR ) { + if (wParam == UNICODE_NOCHAR) { returnCode = 1; break; } @@ -656,8 +671,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_CHAR: { char text[5]; - if ( WIN_ConvertUTF32toUTF8( (UINT32)wParam, text ) ) { - SDL_SendKeyboardText( text ); + if (WIN_ConvertUTF32toUTF8((UINT32)wParam, text)) { + SDL_SendKeyboardText(text); } } returnCode = 0; @@ -1022,6 +1037,20 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM 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; @@ -1067,6 +1096,9 @@ WIN_PumpEvents(_THIS) 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) @@ -1094,9 +1126,9 @@ IsWin10FCUorNewer(void) 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) ) + if ((info.dwMajorVersion == 10 && info.dwMinorVersion == 0 && info.dwBuildNumber >= 16299) || + (info.dwMajorVersion == 10 && info.dwMinorVersion > 0) || + (info.dwMajorVersion > 10)) { return SDL_TRUE; } diff --git a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmessagebox.c b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmessagebox.c index 924b412..9ddb9e2 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmessagebox.c +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmessagebox.c @@ -22,16 +22,52 @@ #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) @@ -70,15 +106,79 @@ typedef struct 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 */ - EndDialog(hDlg, LOWORD(wParam)); + 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: @@ -89,15 +189,30 @@ static INT_PTR MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPA 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) { - size = space; - } else { - while ((dialog->used + space) > size) { - size *= 2; + /* 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) { @@ -175,7 +290,7 @@ static void Vec2ToDLU(short *x, short *y) } -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) +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; @@ -205,32 +320,54 @@ static SDL_bool AddDialogControl(WIN_DialogData *dialog, WORD type, DWORD style, if (!AddDialogData(dialog, &type, sizeof(type))) { return SDL_FALSE; } - if (!AddDialogString(dialog, caption)) { - 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 AddDialogStatic(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text) +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; - return AddDialogControl(dialog, 0x0082, style, 0, x, y, w, h, -1, 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; + DWORD style = WS_VISIBLE | WS_CHILD | WS_TABSTOP; if (isDefault) { style |= BS_DEFPUSHBUTTON; } else { style |= BS_PUSHBUTTON; } - return AddDialogControl(dialog, 0x0080, style, 0, x, y, w, h, id, text); + /* 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) @@ -341,17 +478,87 @@ static WIN_DialogData *CreateDialogData(int w, int h, const char *caption) return dialog; } -int -WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +/* 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; + 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; @@ -359,7 +566,25 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) 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 * @@ -393,7 +618,7 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) * 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. */ - HDC FontDC = CreateCompatibleDC(0); + FontDC = CreateCompatibleDC(0); { /* Create a duplicate of the font used in system message boxes. */ @@ -428,11 +653,13 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) /* Measure the *pixel* size of the string. */ wmessage = WIN_UTF8ToString(messageboxdata->message); SDL_zero(TextSize); - DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT); + DrawText(FontDC, wmessage, -1, &TextSize, DT_CALCRECT | DT_LEFT | DT_NOPREFIX | DT_EDITCONTROL); - /* Add some padding for hangs, etc. */ - TextSize.right += 2; - TextSize.bottom += 2; + /* 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); @@ -444,10 +671,22 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) 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; @@ -456,7 +695,12 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) return -1; } - if (!AddDialogStatic(dialog, TextMargin, TextMargin, TextSize.right - TextSize.left, TextSize.bottom - TextSize.top, messageboxdata->message)) { + 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; } @@ -465,19 +709,25 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) x = Size.cx - (ButtonWidth + ButtonMargin) * messageboxdata->numbuttons; y = Size.cy - ButtonHeight - ButtonMargin; for (i = messageboxdata->numbuttons - 1; i >= 0; --i) { - SDL_bool isDefault; + SDL_bool isdefault = SDL_FALSE; + const char *buttontext; if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) { - isDefault = SDL_TRUE; - } else { - isDefault = SDL_FALSE; + defbuttoncount++; + if (defbuttoncount == 1) { + isdefault = SDL_TRUE; + } } - if (!AddDialogButton(dialog, x, y, ButtonWidth, ButtonHeight, buttons[i].text, buttons[i].buttonid, isDefault)) { + + buttontext = EscapeAmpersands(&escape, &escapesize, 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. */ @@ -485,10 +735,169 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) ParentWindow = ((SDL_WindowData*)messageboxdata->window->driverdata)->hwnd; } - *buttonid = (int)DialogBoxIndirect(NULL, (DLGTEMPLATE*)dialog->lpDialog, ParentWindow, (DLGPROC)MessageBoxDialogProc); + 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 0; + 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(&escape, &escapesize, 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 */ diff --git a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmouse.c b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmouse.c index 1ddeae2..eff3160 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmouse.c +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsmouse.c @@ -304,8 +304,6 @@ WIN_InitMouse(_THIS) mouse->GetGlobalMouseState = WIN_GetGlobalMouseState; SDL_SetDefaultCursor(WIN_CreateDefaultCursor()); - - SDL_SetDoubleClickTime(GetDoubleClickTime()); } void diff --git a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsopengl.h b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsopengl.h index 75b4898..8704411 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsopengl.h +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsopengl.h @@ -33,31 +33,31 @@ struct SDL_GLDriverData 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; + /* 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); + 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); }; diff --git a/Source/3rdParty/SDL2/src/video/windows/SDL_windowstaskdialog.h b/Source/3rdParty/SDL2/src/video/windows/SDL_windowstaskdialog.h new file mode 100644 index 0000000..a2a9e8a --- /dev/null +++ b/Source/3rdParty/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/3rdParty/SDL2/src/video/windows/SDL_windowsvideo.c b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsvideo.c index 8d45b72..358ab23 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsvideo.c +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsvideo.c @@ -63,6 +63,15 @@ UpdateWindowFrameUsableWhileCursorHidden(void *userdata, const char *name, const } } +static void WIN_SuspendScreenSaver(_THIS) +{ + if (_this->suspend_screensaver) { + SetThreadExecutionState(ES_CONTINUOUS | ES_DISPLAY_REQUIRED); + } else { + SetThreadExecutionState(ES_CONTINUOUS); + } +} + /* Windows driver bootstrap functions */ @@ -136,6 +145,7 @@ WIN_CreateDevice(int devindex) device->GetDisplayModes = WIN_GetDisplayModes; device->SetDisplayMode = WIN_SetDisplayMode; device->PumpEvents = WIN_PumpEvents; + device->SuspendScreenSaver = WIN_SuspendScreenSaver; device->CreateSDLWindow = WIN_CreateWindow; device->CreateSDLWindowFrom = WIN_CreateWindowFrom; @@ -164,6 +174,7 @@ WIN_CreateDevice(int devindex) 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; diff --git a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsvulkan.c b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsvulkan.c index c4b34f0..6bb8f2a 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowsvulkan.c +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowsvulkan.c @@ -40,7 +40,7 @@ int WIN_Vulkan_LoadLibrary(_THIS, const char *path) { VkExtensionProperties *extensions = NULL; Uint32 extensionCount = 0; - Uint32 i; + Uint32 i; SDL_bool hasSurfaceExtension = SDL_FALSE; SDL_bool hasWin32SurfaceExtension = SDL_FALSE; PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL; diff --git a/Source/3rdParty/SDL2/src/video/windows/SDL_windowswindow.c b/Source/3rdParty/SDL2/src/video/windows/SDL_windowswindow.c index b082443..45463c4 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowswindow.c +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowswindow.c @@ -97,6 +97,11 @@ GetWindowStyle(SDL_Window * 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; } @@ -215,8 +220,6 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre 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; - int w, h; - /* 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); @@ -287,9 +290,6 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre videodata->RegisterTouchWindow(hwnd, (TWF_FINETOUCH|TWF_WANTPALM)); } - /* Enable dropping files */ - DragAcceptFiles(hwnd, TRUE); - data->initializing = SDL_FALSE; /* All done! */ @@ -335,6 +335,10 @@ WIN_CreateWindow(_THIS, SDL_Window * window) /* 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; } @@ -407,13 +411,11 @@ WIN_CreateWindowFrom(_THIS, SDL_Window * window, const void *data) SDL_sscanf(hint, "%p", (void**)&otherWindow); /* Do some error checking on the pointer */ - if (otherWindow != NULL && otherWindow->magic == &_this->window_magic) - { + 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) - { + if (otherWindow->flags & SDL_WINDOW_OPENGL) { window->flags |= SDL_WINDOW_OPENGL; - if(!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) { + if (!WIN_GL_SetPixelFormatFrom(_this, otherWindow, window)) { return -1; } } @@ -546,8 +548,17 @@ WIN_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *b void WIN_ShowWindow(_THIS, SDL_Window * window) { - HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; - ShowWindow(hwnd, SW_SHOW); + 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 @@ -891,8 +902,13 @@ WIN_UpdateClipCursor(SDL_Window *window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; SDL_Mouse *mouse = SDL_GetMouse(); + RECT rect; - if (data->focus_click_pending) { + if (data->in_title_click || data->focus_click_pending) { + return; + } + if (data->skip_update_clipcursor) { + data->skip_update_clipcursor = SDL_FALSE; return; } @@ -900,7 +916,6 @@ WIN_UpdateClipCursor(SDL_Window *window) (window->flags & SDL_WINDOW_INPUT_FOCUS)) { if (mouse->relative_mode && !mouse->relative_mode_warp) { LONG cx, cy; - RECT rect; GetWindowRect(data->hwnd, &rect); cx = (rect.left + rect.right) / 2; @@ -912,17 +927,21 @@ WIN_UpdateClipCursor(SDL_Window *window) rect.top = cy - 1; rect.bottom = cy + 1; - ClipCursor(&rect); + if (ClipCursor(&rect)) { + data->cursor_clipped_rect = rect; + } } else { - RECT rect; if (GetClientRect(data->hwnd, &rect) && !IsRectEmpty(&rect)) { ClientToScreen(data->hwnd, (LPPOINT) & rect); ClientToScreen(data->hwnd, (LPPOINT) & rect + 1); - ClipCursor(&rect); + if (ClipCursor(&rect)) { + data->cursor_clipped_rect = rect; + } } } - } else { + } else if (GetClipCursor(&rect) && SDL_memcmp(&rect, &data->cursor_clipped_rect, sizeof(rect)) == 0) { ClipCursor(NULL); + SDL_zero(data->cursor_clipped_rect); } } @@ -965,6 +984,13 @@ WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity) 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/3rdParty/SDL2/src/video/windows/SDL_windowswindow.h b/Source/3rdParty/SDL2/src/video/windows/SDL_windowswindow.h index 0325abb..b738c34 100644 --- a/Source/3rdParty/SDL2/src/video/windows/SDL_windowswindow.h +++ b/Source/3rdParty/SDL2/src/video/windows/SDL_windowswindow.h @@ -44,8 +44,10 @@ typedef struct 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; @@ -78,6 +80,7 @@ extern SDL_bool WIN_GetWindowWMInfo(_THIS, SDL_Window * window, 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_ */ |