diff options
Diffstat (limited to 'platform/windows')
-rw-r--r-- | platform/windows/detect.py | 24 | ||||
-rw-r--r-- | platform/windows/display_server_windows.cpp | 86 | ||||
-rw-r--r-- | platform/windows/display_server_windows.h | 23 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 15 |
4 files changed, 131 insertions, 17 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 7eb61b3038..b4949de3f7 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; @@ -2391,6 +2417,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()) { + 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()) { + 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. @@ -3501,6 +3541,11 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, wd.pre_fs_valid = true; } + if (is_dark_mode_supported()) { + 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) { @@ -3587,6 +3632,14 @@ WTInfoPtr DisplayServerWindows::wintab_WTInfo = nullptr; WTPacketPtr DisplayServerWindows::wintab_WTPacket = nullptr; WTEnablePtr DisplayServerWindows::wintab_WTEnable = nullptr; +// UXTheme API. +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; @@ -3598,6 +3651,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(); } @@ -3655,6 +3725,18 @@ 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 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; + } + // 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 556ce9ff5d..dbc9821970 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -152,6 +152,12 @@ 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); + // Windows Ink API #ifndef POINTER_STRUCTURES @@ -278,6 +284,14 @@ class DisplayServerWindows : public DisplayServer { _THREAD_SAFE_CLASS_ + // UXTheme API + 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; @@ -338,7 +352,6 @@ class DisplayServerWindows : public DisplayServer { struct WindowData { HWND hWnd; - //layered window Vector<Vector2> mpath; @@ -378,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; @@ -485,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/os_windows.cpp b/platform/windows/os_windows.cpp index 403d53ae53..b7794bbbf8 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1146,6 +1146,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))); |