diff options
Diffstat (limited to 'platform/windows')
-rw-r--r-- | platform/windows/detect.py | 24 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 104 | ||||
-rw-r--r-- | platform/windows/display_server_windows.h | 25 | ||||
-rw-r--r-- | platform/windows/export/export.cpp | 2 | ||||
-rw-r--r-- | platform/windows/gl_manager_windows.cpp | 7 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 49 | ||||
-rw-r--r-- | platform/windows/os_windows.h | 3 |
7 files changed, 166 insertions, 48 deletions
diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 5607eab342..e6e1874fc0 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -191,7 +191,6 @@ def get_opts(): ), BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", False), BoolVariable("use_llvm", "Use the LLVM compiler", False), - BoolVariable("use_thinlto", "Use ThinLTO", False), BoolVariable("use_static_cpp", "Link MinGW/MSVC C++ runtime libraries statically", True), BoolVariable("use_asan", "Use address sanitizer (ASAN)", False), ] @@ -449,7 +448,10 @@ def configure_msvc(env, vcvars_msvc_config): ## LTO - if env["use_lto"]: + if env["lto"] != "none": + if env["lto"] == "thin": + print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") + sys.exit(255) env.AppendUnique(CCFLAGS=["/GL"]) env.AppendUnique(ARFLAGS=["/LTCG"]) if env["progress"]: @@ -562,17 +564,19 @@ def configure_mingw(env): if try_cmd("gcc-ranlib --version", env["mingw_prefix"], env["arch"]): env["RANLIB"] = mingw_bin_prefix + "gcc-ranlib" - if env["use_lto"]: - if not env["use_llvm"] and env.GetOption("num_jobs") > 1: + if env["lto"] != "none": + if env["lto"] == "thin": + if not env["use_llvm"]: + print("ThinLTO is only compatible with LLVM, use `use_llvm=yes` or `lto=full`.") + sys.exit(255) + env.Append(CCFLAGS=["-flto=thin"]) + env.Append(LINKFLAGS=["-flto=thin"]) + elif not env["use_llvm"] and env.GetOption("num_jobs") > 1: env.Append(CCFLAGS=["-flto"]) env.Append(LINKFLAGS=["-flto=" + str(env.GetOption("num_jobs"))]) else: - if env["use_thinlto"]: - env.Append(CCFLAGS=["-flto=thin"]) - env.Append(LINKFLAGS=["-flto=thin"]) - else: - env.Append(CCFLAGS=["-flto"]) - env.Append(LINKFLAGS=["-flto"]) + env.Append(CCFLAGS=["-flto"]) + env.Append(LINKFLAGS=["-flto"]) env.Append(LINKFLAGS=["-Wl,--stack," + str(STACK_SIZE)]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index fd6b5486a8..237215c198 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -37,6 +37,11 @@ #include "scene/resources/texture.h" #include <avrt.h> +#include <dwmapi.h> + +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif #if defined(GLES3_ENABLED) #include "drivers/gles3/rasterizer_gles3.h" @@ -1307,7 +1312,28 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W _update_window_style(p_window); } break; case WINDOW_FLAG_TRANSPARENT: { - // FIXME: Implement. + if (p_enabled) { + //enable per-pixel alpha + + DWM_BLURBEHIND bb = { 0 }; + HRGN hRgn = CreateRectRgn(0, 0, -1, -1); + bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; + bb.hRgnBlur = hRgn; + bb.fEnable = TRUE; + DwmEnableBlurBehindWindow(wd.hWnd, &bb); + + wd.layered_window = true; + } else { + //disable per-pixel alpha + wd.layered_window = false; + + DWM_BLURBEHIND bb = { 0 }; + HRGN hRgn = CreateRectRgn(0, 0, -1, -1); + bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; + bb.hRgnBlur = hRgn; + bb.fEnable = FALSE; + DwmEnableBlurBehindWindow(wd.hWnd, &bb); + } } break; case WINDOW_FLAG_NO_FOCUS: { wd.no_focus = p_enabled; @@ -1339,7 +1365,7 @@ bool DisplayServerWindows::window_get_flag(WindowFlags p_flag, WindowID p_window return wd.always_on_top; } break; case WINDOW_FLAG_TRANSPARENT: { - // FIXME: Implement. + return wd.layered_window; } break; case WINDOW_FLAG_NO_FOCUS: { return wd.no_focus; @@ -2347,6 +2373,20 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA case WM_PAINT: { Main::force_redraw(); } break; + case WM_SETTINGCHANGE: { + if (lParam && CompareStringOrdinal(reinterpret_cast<LPCWCH>(lParam), -1, L"ImmersiveColorSet", -1, true) == CSTR_EQUAL) { + if (is_dark_mode_supported() && dark_title_available) { + BOOL value = is_dark_mode(); + ::DwmSetWindowAttribute(windows[window_id].hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value)); + } + } + } break; + case WM_THEMECHANGED: { + if (is_dark_mode_supported() && dark_title_available) { + BOOL value = is_dark_mode(); + ::DwmSetWindowAttribute(windows[window_id].hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value)); + } + } break; case WM_SYSCOMMAND: // Intercept system commands. { switch (wParam) // Check system calls. @@ -3457,6 +3497,11 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, wd.pre_fs_valid = true; } + if (is_dark_mode_supported() && dark_title_available) { + BOOL value = is_dark_mode(); + ::DwmSetWindowAttribute(wd.hWnd, DWMWA_USE_IMMERSIVE_DARK_MODE, &value, sizeof(value)); + } + #ifdef VULKAN_ENABLED if (context_vulkan) { if (context_vulkan->window_create(id, p_vsync_mode, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) { @@ -3543,6 +3588,15 @@ WTInfoPtr DisplayServerWindows::wintab_WTInfo = nullptr; WTPacketPtr DisplayServerWindows::wintab_WTPacket = nullptr; WTEnablePtr DisplayServerWindows::wintab_WTEnable = nullptr; +// UXTheme API. +bool DisplayServerWindows::dark_title_available = false; +bool DisplayServerWindows::ux_theme_available = false; +IsDarkModeAllowedForAppPtr DisplayServerWindows::IsDarkModeAllowedForApp = nullptr; +ShouldAppsUseDarkModePtr DisplayServerWindows::ShouldAppsUseDarkMode = nullptr; +GetImmersiveColorFromColorSetExPtr DisplayServerWindows::GetImmersiveColorFromColorSetEx = nullptr; +GetImmersiveColorTypeFromNamePtr DisplayServerWindows::GetImmersiveColorTypeFromName = nullptr; +GetImmersiveUserColorSetPreferencePtr DisplayServerWindows::GetImmersiveUserColorSetPreference = nullptr; + // Windows Ink API. bool DisplayServerWindows::winink_available = false; GetPointerTypePtr DisplayServerWindows::win8p_GetPointerType = nullptr; @@ -3554,6 +3608,23 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS { SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2 } SHC_PROCESS_DPI_AWARENESS; +bool DisplayServerWindows::is_dark_mode_supported() const { + return ux_theme_available && IsDarkModeAllowedForApp(); +} + +bool DisplayServerWindows::is_dark_mode() const { + return ux_theme_available && ShouldAppsUseDarkMode(); +} + +Color DisplayServerWindows::get_accent_color() const { + if (!ux_theme_available) { + return Color(0, 0, 0, 0); + } + + int argb = GetImmersiveColorFromColorSetEx((UINT)GetImmersiveUserColorSetPreference(false, false), GetImmersiveColorTypeFromName(L"ImmersiveSystemAccent"), false, 0); + return Color((argb & 0xFF) / 255.f, ((argb & 0xFF00) >> 8) / 255.f, ((argb & 0xFF0000) >> 16) / 255.f, ((argb & 0xFF000000) >> 24) / 255.f); +} + int DisplayServerWindows::tablet_get_driver_count() const { return tablet_drivers.size(); } @@ -3611,6 +3682,35 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win // Enforce default keep screen on value. screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on")); + // Load Windows version info. + OSVERSIONINFOW os_ver; + ZeroMemory(&os_ver, sizeof(OSVERSIONINFOW)); + os_ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + + HMODULE nt_lib = LoadLibraryW(L"ntdll.dll"); + if (nt_lib) { + RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(nt_lib, "RtlGetVersion"); + if (RtlGetVersion) { + RtlGetVersion(&os_ver); + } + FreeLibrary(nt_lib); + } + + // Load UXTheme. + HMODULE ux_theme_lib = LoadLibraryW(L"uxtheme.dll"); + if (ux_theme_lib) { + IsDarkModeAllowedForApp = (IsDarkModeAllowedForAppPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(136)); + ShouldAppsUseDarkMode = (ShouldAppsUseDarkModePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(132)); + GetImmersiveColorFromColorSetEx = (GetImmersiveColorFromColorSetExPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(95)); + GetImmersiveColorTypeFromName = (GetImmersiveColorTypeFromNamePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(96)); + GetImmersiveUserColorSetPreference = (GetImmersiveUserColorSetPreferencePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(98)); + + ux_theme_available = IsDarkModeAllowedForApp && ShouldAppsUseDarkMode && GetImmersiveColorFromColorSetEx && GetImmersiveColorTypeFromName && GetImmersiveUserColorSetPreference; + if (os_ver.dwBuildNumber >= 22000) { + dark_title_available = true; + } + } + // Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink. HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll"); if (wintab_lib) { diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index c4e5b20f45..fd64a02020 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -152,6 +152,13 @@ typedef UINT(WINAPI *WTInfoPtr)(UINT p_category, UINT p_index, LPVOID p_output); typedef BOOL(WINAPI *WTPacketPtr)(HANDLE p_ctx, UINT p_param, LPVOID p_packets); typedef BOOL(WINAPI *WTEnablePtr)(HANDLE p_ctx, BOOL p_enable); +typedef bool(WINAPI *IsDarkModeAllowedForAppPtr)(); +typedef bool(WINAPI *ShouldAppsUseDarkModePtr)(); +typedef DWORD(WINAPI *GetImmersiveColorFromColorSetExPtr)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode); +typedef int(WINAPI *GetImmersiveColorTypeFromNamePtr)(const WCHAR *name); +typedef int(WINAPI *GetImmersiveUserColorSetPreferencePtr)(bool bForceCheckRegistry, bool bSkipCheckOnFail); +typedef HRESULT(WINAPI *RtlGetVersionPtr)(OSVERSIONINFOW *lpVersionInformation); + // Windows Ink API #ifndef POINTER_STRUCTURES @@ -278,6 +285,15 @@ class DisplayServerWindows : public DisplayServer { _THREAD_SAFE_CLASS_ + // UXTheme API + static bool dark_title_available; + static bool ux_theme_available; + static IsDarkModeAllowedForAppPtr IsDarkModeAllowedForApp; + static ShouldAppsUseDarkModePtr ShouldAppsUseDarkMode; + static GetImmersiveColorFromColorSetExPtr GetImmersiveColorFromColorSetEx; + static GetImmersiveColorTypeFromNamePtr GetImmersiveColorTypeFromName; + static GetImmersiveUserColorSetPreferencePtr GetImmersiveUserColorSetPreference; + // WinTab API static bool wintab_available; static WTOpenPtr wintab_WTOpen; @@ -336,7 +352,6 @@ class DisplayServerWindows : public DisplayServer { struct WindowData { HWND hWnd; - //layered window Vector<Vector2> mpath; @@ -376,10 +391,6 @@ class DisplayServerWindows : public DisplayServer { Vector2 last_tilt; bool last_pen_inverted = false; - HBITMAP hBitmap; //DIB section for layered window - uint8_t *dib_data = nullptr; - Size2 dib_size; - HDC hDC_dib; Size2 min_size; Size2 max_size; int width = 0, height = 0; @@ -483,6 +494,10 @@ public: virtual void tts_resume() override; virtual void tts_stop() override; + virtual bool is_dark_mode_supported() const override; + virtual bool is_dark_mode() const override; + virtual Color get_accent_color() const override; + virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index 20320470b8..8f91756c02 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -34,6 +34,7 @@ #include "export_plugin.h" void register_windows_exporter() { +#ifndef ANDROID_ENABLED EDITOR_DEF("export/windows/rcedit", ""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe")); #ifdef WINDOWS_ENABLED @@ -46,6 +47,7 @@ void register_windows_exporter() { EDITOR_DEF("export/windows/wine", ""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/wine", PROPERTY_HINT_GLOBAL_FILE)); #endif +#endif Ref<EditorExportPlatformWindows> platform; platform.instantiate(); diff --git a/platform/windows/gl_manager_windows.cpp b/platform/windows/gl_manager_windows.cpp index d509ff8c51..7689751f1b 100644 --- a/platform/windows/gl_manager_windows.cpp +++ b/platform/windows/gl_manager_windows.cpp @@ -289,12 +289,7 @@ void GLManager_Windows::make_current() { } void GLManager_Windows::swap_buffers() { - // on other platforms, OpenGL swaps buffers for all windows (on all displays, really?) - // Windows swaps buffers on a per-window basis - // REVISIT: this could be structurally bad, should we have "dirty" flags then? - for (KeyValue<DisplayServer::WindowID, GLWindow> &entry : _windows) { - SwapBuffers(entry.value.hDC); - } + SwapBuffers(_current_window->hDC); } Error GLManager_Windows::initialize() { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 403d53ae53..2c268ff3d5 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -290,7 +290,7 @@ String OS_Windows::get_name() const { return "Windows"; } -OS::Date OS_Windows::get_date(bool p_utc) const { +OS::DateTime OS_Windows::get_datetime(bool p_utc) const { SYSTEMTIME systemtime; if (p_utc) { GetSystemTime(&systemtime); @@ -305,28 +305,16 @@ OS::Date OS_Windows::get_date(bool p_utc) const { daylight = true; } - Date date; - date.day = systemtime.wDay; - date.month = Month(systemtime.wMonth); - date.weekday = Weekday(systemtime.wDayOfWeek); - date.year = systemtime.wYear; - date.dst = daylight; - return date; -} - -OS::Time OS_Windows::get_time(bool p_utc) const { - SYSTEMTIME systemtime; - if (p_utc) { - GetSystemTime(&systemtime); - } else { - GetLocalTime(&systemtime); - } - - Time time; - time.hour = systemtime.wHour; - time.minute = systemtime.wMinute; - time.second = systemtime.wSecond; - return time; + DateTime dt; + dt.year = systemtime.wYear; + dt.month = Month(systemtime.wMonth); + dt.day = systemtime.wDay; + dt.weekday = Weekday(systemtime.wDayOfWeek); + dt.hour = systemtime.wHour; + dt.minute = systemtime.wMinute; + dt.second = systemtime.wSecond; + dt.dst = daylight; + return dt; } OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { @@ -1146,6 +1134,21 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { DisplayServerWindows::register_windows_driver(); + // Enable ANSI escape code support on Windows 10 v1607 (Anniversary Update) and later. + // This lets the engine and projects use ANSI escape codes to color text just like on macOS and Linux. + // + // NOTE: The engine does not use ANSI escape codes to color error/warning messages; it uses Windows API calls instead. + // Therefore, error/warning messages are still colored on Windows versions older than 10. + HANDLE stdoutHandle; + stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE); + DWORD outMode = 0; + outMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; + + if (!SetConsoleMode(stdoutHandle, outMode)) { + // Windows 8.1 or below, or Windows 10 prior to Anniversary Update. + print_verbose("Can't set the ENABLE_VIRTUAL_TERMINAL_PROCESSING Windows console mode. `print_rich()` will not work as expected."); + } + Vector<Logger *> loggers; loggers.push_back(memnew(WindowsTerminalLogger)); _set_logger(memnew(CompositeLogger(loggers))); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 3e054c068c..53451b780e 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -146,8 +146,7 @@ public: virtual void initialize_joypads() override {} - virtual Date get_date(bool p_utc) const override; - virtual Time get_time(bool p_utc) const override; + virtual DateTime get_datetime(bool p_utc) const override; virtual TimeZoneInfo get_time_zone_info() const override; virtual double get_unix_time() const override; |