Update SDL3 from 3.2.4 to 3.2.20
This commit is contained in:
@@ -33,15 +33,12 @@
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
||||
#include "SDL_windowsvideo.h"
|
||||
#include "SDL_windowskeyboard.h"
|
||||
#include "SDL_windowswindow.h"
|
||||
|
||||
// Dropfile support
|
||||
#include <shellapi.h>
|
||||
|
||||
// DWM setting support
|
||||
typedef HRESULT (WINAPI *DwmSetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
|
||||
typedef HRESULT (WINAPI *DwmGetWindowAttribute_t)(HWND hwnd, DWORD dwAttribute, PVOID pvAttribute, DWORD cbAttribute);
|
||||
|
||||
// Dark mode support
|
||||
typedef enum {
|
||||
UXTHEME_APPMODE_DEFAULT,
|
||||
@@ -80,46 +77,6 @@ typedef UxthemePreferredAppMode (WINAPI *SetPreferredAppMode_t)(UxthemePreferred
|
||||
typedef BOOL (WINAPI *SetWindowCompositionAttribute_t)(HWND, const WINDOWCOMPOSITIONATTRIBDATA *);
|
||||
typedef void (NTAPI *RtlGetVersion_t)(NT_OSVERSIONINFOW *);
|
||||
|
||||
// Corner rounding support (Win 11+)
|
||||
#ifndef DWMWA_WINDOW_CORNER_PREFERENCE
|
||||
#define DWMWA_WINDOW_CORNER_PREFERENCE 33
|
||||
#endif
|
||||
typedef enum {
|
||||
DWMWCP_DEFAULT = 0,
|
||||
DWMWCP_DONOTROUND = 1,
|
||||
DWMWCP_ROUND = 2,
|
||||
DWMWCP_ROUNDSMALL = 3
|
||||
} DWM_WINDOW_CORNER_PREFERENCE;
|
||||
|
||||
// Border Color support (Win 11+)
|
||||
#ifndef DWMWA_BORDER_COLOR
|
||||
#define DWMWA_BORDER_COLOR 34
|
||||
#endif
|
||||
|
||||
#ifndef DWMWA_COLOR_DEFAULT
|
||||
#define DWMWA_COLOR_DEFAULT 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
#ifndef DWMWA_COLOR_NONE
|
||||
#define DWMWA_COLOR_NONE 0xFFFFFFFE
|
||||
#endif
|
||||
|
||||
// Transparent window support
|
||||
#ifndef DWM_BB_ENABLE
|
||||
#define DWM_BB_ENABLE 0x00000001
|
||||
#endif
|
||||
#ifndef DWM_BB_BLURREGION
|
||||
#define DWM_BB_BLURREGION 0x00000002
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
DWORD flags;
|
||||
BOOL enable;
|
||||
HRGN blur_region;
|
||||
BOOL transition_on_maxed;
|
||||
} DWM_BLURBEHIND;
|
||||
typedef HRESULT(WINAPI *DwmEnableBlurBehindWindow_t)(HWND hwnd, const DWM_BLURBEHIND *pBlurBehind);
|
||||
|
||||
// Windows CE compatibility
|
||||
#ifndef SWP_NOCOPYBITS
|
||||
#define SWP_NOCOPYBITS 0
|
||||
@@ -135,12 +92,6 @@ typedef HRESULT(WINAPI *DwmEnableBlurBehindWindow_t)(HWND hwnd, const DWM_BLURBE
|
||||
|
||||
// #define HIGHDPI_DEBUG
|
||||
|
||||
// Fake window to help with DirectInput events.
|
||||
HWND SDL_HelperWindow = NULL;
|
||||
static const TCHAR *SDL_HelperWindowClassName = TEXT("SDLHelperWindowInputCatcher");
|
||||
static const TCHAR *SDL_HelperWindowName = TEXT("SDLHelperWindowInputMsgWindow");
|
||||
static ATOM SDL_HelperWindowClass = 0;
|
||||
|
||||
/* For borderless Windows, still want the following flag:
|
||||
- WS_MINIMIZEBOX: window will respond to Windows minimize commands sent to all windows, such as windows key + m, shaking title bar, etc.
|
||||
Additionally, non-fullscreen windows can add:
|
||||
@@ -392,6 +343,10 @@ bool WIN_SetWindowPositionInternal(SDL_Window *window, UINT flags, SDL_WindowRec
|
||||
|
||||
// Update any child windows
|
||||
for (child_window = window->first_child; child_window; child_window = child_window->next_sibling) {
|
||||
if (!child_window->internal) {
|
||||
// This child window is not yet fully initialized.
|
||||
continue;
|
||||
}
|
||||
if (!WIN_SetWindowPositionInternal(child_window, flags, SDL_WINDOWRECT_CURRENT)) {
|
||||
result = false;
|
||||
}
|
||||
@@ -447,7 +402,6 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
|
||||
data->videodata = videodata;
|
||||
data->initializing = true;
|
||||
data->last_displayID = window->last_displayID;
|
||||
data->dwma_border_color = DWMWA_COLOR_DEFAULT;
|
||||
data->hint_erase_background_mode = GetEraseBackgroundModeHint();
|
||||
|
||||
|
||||
@@ -535,7 +489,7 @@ static bool SetupWindowData(SDL_VideoDevice *_this, SDL_Window *window, HWND hwn
|
||||
}
|
||||
if (!(window->flags & SDL_WINDOW_MINIMIZED)) {
|
||||
RECT rect;
|
||||
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
|
||||
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
|
||||
int w = rect.right;
|
||||
int h = rect.bottom;
|
||||
|
||||
@@ -679,7 +633,7 @@ static void CleanupWindowData(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
|
||||
static void WIN_ConstrainPopup(SDL_Window *window, bool output_to_pending)
|
||||
{
|
||||
// Clamp popup windows to the output borders
|
||||
// Possibly clamp popup windows to the output borders
|
||||
if (SDL_WINDOW_IS_POPUP(window)) {
|
||||
SDL_Window *w;
|
||||
SDL_DisplayID displayID;
|
||||
@@ -690,28 +644,30 @@ static void WIN_ConstrainPopup(SDL_Window *window, bool output_to_pending)
|
||||
const int height = window->last_size_pending ? window->pending.h : window->floating.h;
|
||||
int offset_x = 0, offset_y = 0;
|
||||
|
||||
// Calculate the total offset from the parents
|
||||
for (w = window->parent; SDL_WINDOW_IS_POPUP(w); w = w->parent) {
|
||||
if (window->constrain_popup) {
|
||||
// Calculate the total offset from the parents
|
||||
for (w = window->parent; SDL_WINDOW_IS_POPUP(w); w = w->parent) {
|
||||
offset_x += w->x;
|
||||
offset_y += w->y;
|
||||
}
|
||||
|
||||
offset_x += w->x;
|
||||
offset_y += w->y;
|
||||
}
|
||||
abs_x += offset_x;
|
||||
abs_y += offset_y;
|
||||
|
||||
offset_x += w->x;
|
||||
offset_y += w->y;
|
||||
abs_x += offset_x;
|
||||
abs_y += offset_y;
|
||||
|
||||
// Constrain the popup window to the display of the toplevel parent
|
||||
displayID = SDL_GetDisplayForWindow(w);
|
||||
SDL_GetDisplayBounds(displayID, &rect);
|
||||
if (abs_x + width > rect.x + rect.w) {
|
||||
abs_x -= (abs_x + width) - (rect.x + rect.w);
|
||||
// Constrain the popup window to the display of the toplevel parent
|
||||
displayID = SDL_GetDisplayForWindow(w);
|
||||
SDL_GetDisplayBounds(displayID, &rect);
|
||||
if (abs_x + width > rect.x + rect.w) {
|
||||
abs_x -= (abs_x + width) - (rect.x + rect.w);
|
||||
}
|
||||
if (abs_y + height > rect.y + rect.h) {
|
||||
abs_y -= (abs_y + height) - (rect.y + rect.h);
|
||||
}
|
||||
abs_x = SDL_max(abs_x, rect.x);
|
||||
abs_y = SDL_max(abs_y, rect.y);
|
||||
}
|
||||
if (abs_y + height > rect.y + rect.h) {
|
||||
abs_y -= (abs_y + height) - (rect.y + rect.h);
|
||||
}
|
||||
abs_x = SDL_max(abs_x, rect.x);
|
||||
abs_y = SDL_max(abs_y, rect.y);
|
||||
|
||||
if (output_to_pending) {
|
||||
window->pending.x = abs_x - offset_x;
|
||||
@@ -736,7 +692,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window, bool set_active_focus)
|
||||
toplevel = toplevel->parent;
|
||||
}
|
||||
|
||||
toplevel->internal->keyboard_focus = window;
|
||||
toplevel->keyboard_focus = window;
|
||||
|
||||
if (set_active_focus && !window->is_hiding && !window->is_destroying) {
|
||||
SDL_SetKeyboardFocus(window);
|
||||
@@ -745,6 +701,7 @@ static void WIN_SetKeyboardFocus(SDL_Window *window, bool set_active_focus)
|
||||
|
||||
bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_PropertiesID create_props)
|
||||
{
|
||||
SDL_VideoData *videodata = _this->internal;
|
||||
HWND hwnd = (HWND)SDL_GetPointerProperty(create_props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, SDL_GetPointerProperty(create_props, "sdl2-compat.external_window", NULL));
|
||||
HWND parent = NULL;
|
||||
if (hwnd) {
|
||||
@@ -790,6 +747,9 @@ bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ensure that the IME isn't active on the new window until explicitly requested.
|
||||
WIN_StopTextInput(_this, 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_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE);
|
||||
|
||||
@@ -806,24 +766,19 @@ bool WIN_CreateWindow(SDL_VideoDevice *_this, SDL_Window *window, SDL_Properties
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
// FIXME: does not work on all hardware configurations with different renders (i.e. hybrid GPUs)
|
||||
if (window->flags & SDL_WINDOW_TRANSPARENT) {
|
||||
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
|
||||
if (handle) {
|
||||
DwmEnableBlurBehindWindow_t DwmEnableBlurBehindWindowFunc = (DwmEnableBlurBehindWindow_t)SDL_LoadFunction(handle, "DwmEnableBlurBehindWindow");
|
||||
if (DwmEnableBlurBehindWindowFunc) {
|
||||
/* The region indicates which part of the window will be blurred and rest will be transparent. This
|
||||
is because the alpha value of the window will be used for non-blurred areas
|
||||
We can use (-1, -1, 0, 0) boundary to make sure no pixels are being blurred
|
||||
*/
|
||||
HRGN rgn = CreateRectRgn(-1, -1, 0, 0);
|
||||
DWM_BLURBEHIND bb;
|
||||
bb.flags = (DWM_BB_ENABLE | DWM_BB_BLURREGION);
|
||||
bb.enable = TRUE;
|
||||
bb.blur_region = rgn;
|
||||
bb.transition_on_maxed = FALSE;
|
||||
DwmEnableBlurBehindWindowFunc(hwnd, &bb);
|
||||
DeleteObject(rgn);
|
||||
}
|
||||
SDL_UnloadObject(handle);
|
||||
if (videodata->DwmEnableBlurBehindWindow) {
|
||||
/* The region indicates which part of the window will be blurred and rest will be transparent. This
|
||||
is because the alpha value of the window will be used for non-blurred areas
|
||||
We can use (-1, -1, 0, 0) boundary to make sure no pixels are being blurred
|
||||
*/
|
||||
HRGN rgn = CreateRectRgn(-1, -1, 0, 0);
|
||||
DWM_BLURBEHIND bb;
|
||||
bb.flags = (DWM_BB_ENABLE | DWM_BB_BLURREGION);
|
||||
bb.enable = TRUE;
|
||||
bb.blur_region = rgn;
|
||||
bb.transition_on_maxed = FALSE;
|
||||
videodata->DwmEnableBlurBehindWindow(hwnd, &bb);
|
||||
DeleteObject(rgn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1062,7 +1017,7 @@ void WIN_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *
|
||||
HWND hwnd = data->hwnd;
|
||||
RECT rect;
|
||||
|
||||
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
|
||||
if (GetClientRect(hwnd, &rect) && WIN_WindowRectValid(&rect)) {
|
||||
*w = rect.right;
|
||||
*h = rect.bottom;
|
||||
} else if (window->last_pixel_w && window->last_pixel_h) {
|
||||
@@ -1077,8 +1032,9 @@ void WIN_GetWindowSizeInPixels(SDL_VideoDevice *_this, SDL_Window *window, int *
|
||||
|
||||
void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->internal;
|
||||
HWND hwnd = data->hwnd;
|
||||
DWORD style;
|
||||
HWND hwnd;
|
||||
|
||||
bool bActivate = SDL_GetHintBoolean(SDL_HINT_WINDOW_ACTIVATE_WHEN_SHOWN, true);
|
||||
|
||||
@@ -1087,20 +1043,33 @@ void WIN_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
WIN_SetWindowPosition(_this, window);
|
||||
}
|
||||
|
||||
hwnd = window->internal->hwnd;
|
||||
// If the window isn't borderless and will be fullscreen, use the borderless style to hide the initial borders.
|
||||
if (window->pending_flags & SDL_WINDOW_FULLSCREEN) {
|
||||
if (!(window->flags & SDL_WINDOW_BORDERLESS)) {
|
||||
window->flags |= SDL_WINDOW_BORDERLESS;
|
||||
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||
style &= ~STYLE_MASK;
|
||||
style |= GetWindowStyle(window);
|
||||
SetWindowLong(hwnd, GWL_STYLE, style);
|
||||
window->flags &= ~SDL_WINDOW_BORDERLESS;
|
||||
}
|
||||
}
|
||||
style = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
if (style & WS_EX_NOACTIVATE) {
|
||||
bActivate = false;
|
||||
}
|
||||
|
||||
data->showing_window = true;
|
||||
if (bActivate) {
|
||||
ShowWindow(hwnd, SW_SHOW);
|
||||
} else {
|
||||
// Use SetWindowPos instead of ShowWindow to avoid activating the parent window if this is a child window
|
||||
SetWindowPos(hwnd, NULL, 0, 0, 0, 0, window->internal->copybits_flag | SWP_SHOWWINDOW | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
|
||||
}
|
||||
data->showing_window = false;
|
||||
|
||||
if (window->flags & SDL_WINDOW_POPUP_MENU && bActivate) {
|
||||
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE) && bActivate) {
|
||||
WIN_SetKeyboardFocus(window, true);
|
||||
}
|
||||
if (window->flags & SDL_WINDOW_MODAL) {
|
||||
WIN_SetWindowModal(_this, window, true);
|
||||
@@ -1117,21 +1086,10 @@ void WIN_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
|
||||
// Transfer keyboard focus back to the parent
|
||||
if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||
SDL_Window *new_focus = window->parent;
|
||||
bool set_focus = window == SDL_GetKeyboardFocus();
|
||||
|
||||
// Find the highest level window, up to the toplevel parent, that isn't being hidden or destroyed.
|
||||
while (SDL_WINDOW_IS_POPUP(new_focus) && (new_focus->is_hiding || new_focus->is_destroying)) {
|
||||
new_focus = new_focus->parent;
|
||||
|
||||
// If some window in the chain currently had keyboard focus, set it to the new lowest-level window.
|
||||
if (!set_focus) {
|
||||
set_focus = new_focus == SDL_GetKeyboardFocus();
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer keyboard focus back to the parent from a grabbing popup.
|
||||
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
|
||||
SDL_Window *new_focus;
|
||||
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
|
||||
WIN_SetKeyboardFocus(new_focus, set_focus);
|
||||
}
|
||||
}
|
||||
@@ -1169,7 +1127,7 @@ void WIN_RaiseWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
}
|
||||
if (bActivate) {
|
||||
SetForegroundWindow(hwnd);
|
||||
if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||
if ((window->flags & SDL_WINDOW_POPUP_MENU) && !(window->flags & SDL_WINDOW_NOT_FOCUSABLE)) {
|
||||
WIN_SetKeyboardFocus(window, window->parent == SDL_GetKeyboardFocus());
|
||||
}
|
||||
} else {
|
||||
@@ -1256,51 +1214,35 @@ void WIN_RestoreWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->internal;
|
||||
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
|
||||
HWND hwnd = data->hwnd;
|
||||
data->expected_resize = true;
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
data->expected_resize = false;
|
||||
if (!data->showing_window || window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) {
|
||||
HWND hwnd = data->hwnd;
|
||||
data->expected_resize = true;
|
||||
ShowWindow(hwnd, SW_RESTORE);
|
||||
data->expected_resize = false;
|
||||
}
|
||||
} else {
|
||||
data->windowed_mode_was_maximized = false;
|
||||
}
|
||||
}
|
||||
|
||||
static DWM_WINDOW_CORNER_PREFERENCE WIN_UpdateCornerRoundingForHWND(HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
|
||||
static void WIN_UpdateCornerRoundingForHWND(SDL_VideoDevice *_this, HWND hwnd, DWM_WINDOW_CORNER_PREFERENCE cornerPref)
|
||||
{
|
||||
DWM_WINDOW_CORNER_PREFERENCE oldPref = DWMWCP_DEFAULT;
|
||||
|
||||
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
|
||||
if (handle) {
|
||||
DwmGetWindowAttribute_t DwmGetWindowAttributeFunc = (DwmGetWindowAttribute_t)SDL_LoadFunction(handle, "DwmGetWindowAttribute");
|
||||
DwmSetWindowAttribute_t DwmSetWindowAttributeFunc = (DwmSetWindowAttribute_t)SDL_LoadFunction(handle, "DwmSetWindowAttribute");
|
||||
if (DwmGetWindowAttributeFunc && DwmSetWindowAttributeFunc) {
|
||||
DwmGetWindowAttributeFunc(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &oldPref, sizeof(oldPref));
|
||||
DwmSetWindowAttributeFunc(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
|
||||
}
|
||||
|
||||
SDL_UnloadObject(handle);
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
SDL_VideoData *videodata = _this->internal;
|
||||
if (videodata->DwmSetWindowAttribute) {
|
||||
videodata->DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, &cornerPref, sizeof(cornerPref));
|
||||
}
|
||||
|
||||
return oldPref;
|
||||
#endif
|
||||
}
|
||||
|
||||
static COLORREF WIN_UpdateBorderColorForHWND(HWND hwnd, COLORREF colorRef)
|
||||
static void WIN_UpdateBorderColorForHWND(SDL_VideoDevice *_this, HWND hwnd, COLORREF colorRef)
|
||||
{
|
||||
COLORREF oldPref = DWMWA_COLOR_DEFAULT;
|
||||
|
||||
SDL_SharedObject *handle = SDL_LoadObject("dwmapi.dll");
|
||||
if (handle) {
|
||||
DwmGetWindowAttribute_t DwmGetWindowAttributeFunc = (DwmGetWindowAttribute_t)SDL_LoadFunction(handle, "DwmGetWindowAttribute");
|
||||
DwmSetWindowAttribute_t DwmSetWindowAttributeFunc = (DwmSetWindowAttribute_t)SDL_LoadFunction(handle, "DwmSetWindowAttribute");
|
||||
if (DwmGetWindowAttributeFunc && DwmSetWindowAttributeFunc) {
|
||||
DwmGetWindowAttributeFunc(hwnd, DWMWA_BORDER_COLOR, &oldPref, sizeof(oldPref));
|
||||
DwmSetWindowAttributeFunc(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
|
||||
}
|
||||
|
||||
SDL_UnloadObject(handle);
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
SDL_VideoData *videodata = _this->internal;
|
||||
if (videodata->DwmSetWindowAttribute) {
|
||||
videodata->DwmSetWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &colorRef, sizeof(colorRef));
|
||||
}
|
||||
|
||||
return oldPref;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1311,7 +1253,7 @@ SDL_FullscreenResult WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
SDL_DisplayData *displaydata = display->internal;
|
||||
SDL_WindowData *data = window->internal;
|
||||
HWND hwnd = data->hwnd;
|
||||
HWND hwnd = data ? data->hwnd : NULL;
|
||||
MONITORINFO minfo;
|
||||
DWORD style, styleEx;
|
||||
HWND top;
|
||||
@@ -1366,13 +1308,13 @@ SDL_FullscreenResult WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window
|
||||
}
|
||||
|
||||
// Disable corner rounding & border color (Windows 11+) so the window fills the full screen
|
||||
data->windowed_mode_corner_rounding = WIN_UpdateCornerRoundingForHWND(hwnd, DWMWCP_DONOTROUND);
|
||||
data->dwma_border_color = WIN_UpdateBorderColorForHWND(hwnd, DWMWA_COLOR_NONE);
|
||||
WIN_UpdateCornerRoundingForHWND(_this, hwnd, DWMWCP_DONOTROUND);
|
||||
WIN_UpdateBorderColorForHWND(_this, hwnd, DWMWA_COLOR_NONE);
|
||||
} else {
|
||||
BOOL menu;
|
||||
|
||||
WIN_UpdateCornerRoundingForHWND(hwnd, (DWM_WINDOW_CORNER_PREFERENCE)data->windowed_mode_corner_rounding);
|
||||
WIN_UpdateBorderColorForHWND(hwnd, data->dwma_border_color);
|
||||
WIN_UpdateCornerRoundingForHWND(_this, hwnd, DWMWCP_DEFAULT);
|
||||
WIN_UpdateBorderColorForHWND(_this, hwnd, DWMWA_COLOR_DEFAULT);
|
||||
|
||||
/* Restore window-maximization state, as applicable.
|
||||
Special care is taken to *not* do this if and when we're
|
||||
@@ -1391,6 +1333,35 @@ SDL_FullscreenResult WIN_SetWindowFullscreen(SDL_VideoDevice *_this, SDL_Window
|
||||
&w, &h,
|
||||
SDL_WINDOWRECT_FLOATING);
|
||||
data->windowed_mode_was_maximized = false;
|
||||
|
||||
/* A window may have been maximized by dragging it to the top of another display, in which case the floating
|
||||
* position may be out-of-date. If the window is being restored to maximized, and the maximized and floating
|
||||
* position are on different displays, try to center the window on the maximized display for restoration, which
|
||||
* mimics native Windows behavior.
|
||||
*/
|
||||
if (enterMaximized) {
|
||||
const SDL_Point windowed_point = { window->windowed.x, window->windowed.y };
|
||||
const SDL_Point floating_point = { window->floating.x, window->floating.y };
|
||||
const SDL_DisplayID floating_display = SDL_GetDisplayForPoint(&floating_point);
|
||||
const SDL_DisplayID windowed_display = SDL_GetDisplayForPoint(&windowed_point);
|
||||
|
||||
if (floating_display != windowed_display) {
|
||||
SDL_Rect bounds;
|
||||
|
||||
SDL_zero(bounds);
|
||||
SDL_GetDisplayUsableBounds(windowed_display, &bounds);
|
||||
if (w < bounds.w) {
|
||||
x = bounds.x + (bounds.w - w) / 2;
|
||||
} else {
|
||||
x = bounds.x;
|
||||
}
|
||||
if (h < bounds.h) {
|
||||
y = bounds.y + (bounds.h - h) / 2;
|
||||
} else {
|
||||
y = bounds.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Always reset the window to the base floating size before possibly re-applying the maximized state,
|
||||
@@ -1533,72 +1504,6 @@ void WIN_DestroyWindow(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
CleanupWindowData(_this, window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a HelperWindow used for DirectInput.
|
||||
*/
|
||||
bool SDL_HelperWindowCreate(void)
|
||||
{
|
||||
HINSTANCE hInstance = GetModuleHandle(NULL);
|
||||
WNDCLASS wce;
|
||||
|
||||
// Make sure window isn't created twice.
|
||||
if (SDL_HelperWindow != NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create the class.
|
||||
SDL_zero(wce);
|
||||
wce.lpfnWndProc = DefWindowProc;
|
||||
wce.lpszClassName = 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) {
|
||||
UnregisterClass(SDL_HelperWindowClassName, hInstance);
|
||||
return WIN_SetError("Unable to create Helper Window");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
void WIN_OnWindowEnter(SDL_VideoDevice *_this, SDL_Window *window)
|
||||
{
|
||||
@@ -1633,7 +1538,7 @@ void WIN_UnclipCursorForWindow(SDL_Window *window) {
|
||||
void WIN_UpdateClipCursor(SDL_Window *window)
|
||||
{
|
||||
SDL_WindowData *data = window->internal;
|
||||
if (data->in_title_click || data->focus_click_pending || data->skip_update_clipcursor) {
|
||||
if (data->in_title_click || data->focus_click_pending || data->postpone_clipcursor) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2272,24 +2177,40 @@ void WIN_ShowWindowSystemMenu(SDL_Window *window, int x, int y)
|
||||
|
||||
bool WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool focusable)
|
||||
{
|
||||
SDL_WindowData *data = window->internal;
|
||||
HWND hwnd = data->hwnd;
|
||||
const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
if (!SDL_WINDOW_IS_POPUP(window)) {
|
||||
SDL_WindowData *data = window->internal;
|
||||
HWND hwnd = data->hwnd;
|
||||
const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
|
||||
|
||||
SDL_assert(style != 0);
|
||||
SDL_assert(style != 0);
|
||||
|
||||
if (focusable) {
|
||||
if (style & WS_EX_NOACTIVATE) {
|
||||
if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_NOACTIVATE) == 0) {
|
||||
return WIN_SetError("SetWindowLong()");
|
||||
if (focusable) {
|
||||
if (style & WS_EX_NOACTIVATE) {
|
||||
if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_NOACTIVATE) == 0) {
|
||||
return WIN_SetError("SetWindowLong()");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(style & WS_EX_NOACTIVATE)) {
|
||||
if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_NOACTIVATE) == 0) {
|
||||
return WIN_SetError("SetWindowLong()");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!(style & WS_EX_NOACTIVATE)) {
|
||||
if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_NOACTIVATE) == 0) {
|
||||
return WIN_SetError("SetWindowLong()");
|
||||
} else if (window->flags & SDL_WINDOW_POPUP_MENU) {
|
||||
if (!(window->flags & SDL_WINDOW_HIDDEN)) {
|
||||
if (!focusable && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
|
||||
SDL_Window *new_focus;
|
||||
const bool set_focus = SDL_ShouldRelinquishPopupFocus(window, &new_focus);
|
||||
WIN_SetKeyboardFocus(new_focus, set_focus);
|
||||
} else if (focusable) {
|
||||
if (SDL_ShouldFocusPopup(window)) {
|
||||
WIN_SetKeyboardFocus(window, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2299,38 +2220,38 @@ bool WIN_SetWindowFocusable(SDL_VideoDevice *_this, SDL_Window *window, bool foc
|
||||
void WIN_UpdateDarkModeForHWND(HWND hwnd)
|
||||
{
|
||||
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)
|
||||
SDL_SharedObject *ntdll = SDL_LoadObject("ntdll.dll");
|
||||
HMODULE ntdll = LoadLibrary(TEXT("ntdll.dll"));
|
||||
if (!ntdll) {
|
||||
return;
|
||||
}
|
||||
// There is no function to get Windows build number, so let's get it here via RtlGetVersion
|
||||
RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)SDL_LoadFunction(ntdll, "RtlGetVersion");
|
||||
RtlGetVersion_t RtlGetVersionFunc = (RtlGetVersion_t)GetProcAddress(ntdll, "RtlGetVersion");
|
||||
NT_OSVERSIONINFOW os_info;
|
||||
os_info.dwOSVersionInfoSize = sizeof(NT_OSVERSIONINFOW);
|
||||
os_info.dwBuildNumber = 0;
|
||||
if (RtlGetVersionFunc) {
|
||||
RtlGetVersionFunc(&os_info);
|
||||
}
|
||||
SDL_UnloadObject(ntdll);
|
||||
FreeLibrary(ntdll);
|
||||
os_info.dwBuildNumber &= ~0xF0000000;
|
||||
if (os_info.dwBuildNumber < 17763) {
|
||||
// Too old to support dark mode
|
||||
return;
|
||||
}
|
||||
SDL_SharedObject *uxtheme = SDL_LoadObject("uxtheme.dll");
|
||||
HMODULE uxtheme = LoadLibrary(TEXT("uxtheme.dll"));
|
||||
if (!uxtheme) {
|
||||
return;
|
||||
}
|
||||
RefreshImmersiveColorPolicyState_t RefreshImmersiveColorPolicyStateFunc = (RefreshImmersiveColorPolicyState_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(104));
|
||||
ShouldAppsUseDarkMode_t ShouldAppsUseDarkModeFunc = (ShouldAppsUseDarkMode_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(132));
|
||||
AllowDarkModeForWindow_t AllowDarkModeForWindowFunc = (AllowDarkModeForWindow_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(133));
|
||||
RefreshImmersiveColorPolicyState_t RefreshImmersiveColorPolicyStateFunc = (RefreshImmersiveColorPolicyState_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(104));
|
||||
ShouldAppsUseDarkMode_t ShouldAppsUseDarkModeFunc = (ShouldAppsUseDarkMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(132));
|
||||
AllowDarkModeForWindow_t AllowDarkModeForWindowFunc = (AllowDarkModeForWindow_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(133));
|
||||
if (os_info.dwBuildNumber < 18362) {
|
||||
AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(135));
|
||||
AllowDarkModeForApp_t AllowDarkModeForAppFunc = (AllowDarkModeForApp_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135));
|
||||
if (AllowDarkModeForAppFunc) {
|
||||
AllowDarkModeForAppFunc(true);
|
||||
}
|
||||
} else {
|
||||
SetPreferredAppMode_t SetPreferredAppModeFunc = (SetPreferredAppMode_t)SDL_LoadFunction(uxtheme, MAKEINTRESOURCEA(135));
|
||||
SetPreferredAppMode_t SetPreferredAppModeFunc = (SetPreferredAppMode_t)GetProcAddress(uxtheme, MAKEINTRESOURCEA(135));
|
||||
if (SetPreferredAppModeFunc) {
|
||||
SetPreferredAppModeFunc(UXTHEME_APPMODE_ALLOW_DARK);
|
||||
}
|
||||
@@ -2348,7 +2269,7 @@ void WIN_UpdateDarkModeForHWND(HWND hwnd)
|
||||
} else {
|
||||
value = (SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK) ? TRUE : FALSE;
|
||||
}
|
||||
SDL_UnloadObject(uxtheme);
|
||||
FreeLibrary(uxtheme);
|
||||
if (os_info.dwBuildNumber < 18362) {
|
||||
SetProp(hwnd, TEXT("UseImmersiveDarkModeColors"), SDL_reinterpret_cast(HANDLE, SDL_static_cast(INT_PTR, value)));
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user