Merge pull request #118339 from bruvzg/winrt_color
[Windows] Add support for `AdvancedColorInfo` info and change callback.
This commit is contained in:
@@ -8,7 +8,7 @@ from pathlib import Path
|
||||
|
||||
import platform_windows_builders
|
||||
|
||||
from methods import redirect_emitter
|
||||
from methods import get_compiler_version, redirect_emitter
|
||||
|
||||
sources = []
|
||||
|
||||
@@ -92,8 +92,13 @@ if env["winrt"]:
|
||||
env_winrt["CXXFLAGS"].remove("-fno-exceptions")
|
||||
env_winrt.Append(CXXFLAGS=["-fexceptions"])
|
||||
else:
|
||||
cc_version = get_compiler_version(env)
|
||||
cc_version_major = cc_version["major"]
|
||||
if not env["use_llvm"]:
|
||||
env_winrt.Append(CXXFLAGS=["/await"])
|
||||
if cc_version_major >= 18:
|
||||
env_winrt.Append(CXXFLAGS=["/await:strict"]) # /await is deprecated in MSVC 2026+
|
||||
else:
|
||||
env_winrt.Append(CXXFLAGS=["/await"])
|
||||
if "/std:c++17" in env_winrt["CXXFLAGS"]:
|
||||
env_winrt["CXXFLAGS"].remove("/std:c++17")
|
||||
env_winrt.Append(CXXFLAGS=["/std:c++20"])
|
||||
|
||||
@@ -427,6 +427,7 @@ def configure_msvc(env: "SConsEnvironment"):
|
||||
"ntdll",
|
||||
"hid",
|
||||
"mincore",
|
||||
"coremessaging",
|
||||
]
|
||||
|
||||
if env.debug_features:
|
||||
@@ -823,6 +824,7 @@ def configure_mingw(env: "SConsEnvironment"):
|
||||
"ntdll",
|
||||
"hid",
|
||||
"mincore",
|
||||
"coremessaging",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@@ -3407,41 +3407,47 @@ HWND DisplayServerWindows::_find_window_from_process_id(ProcessID p_pid, HWND p_
|
||||
}
|
||||
|
||||
// Get screen HDR capabilities for internal use only.
|
||||
DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(int p_screen, bool p_include_sdr_white_level) const {
|
||||
DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(DisplayServerEnums::WindowID p_window, bool p_include_sdr_white_level) const {
|
||||
ScreenHdrData data;
|
||||
HMONITOR monitor = _get_hmonitor_of_screen(p_screen);
|
||||
if (!monitor) {
|
||||
return data;
|
||||
}
|
||||
const WindowData &wd = windows[p_window];
|
||||
if (WinRTUtils::window_has_display_info(wd.wrt_wd)) {
|
||||
WinRTUtils::window_get_advanced_color_info(wd.wrt_wd, data.hdr_supported, data.min_luminance, data.max_luminance, data.max_average_luminance, data.sdr_white_level);
|
||||
} else {
|
||||
int screen = window_get_current_screen(p_window);
|
||||
HMONITOR monitor = _get_hmonitor_of_screen(screen);
|
||||
if (!monitor) {
|
||||
return data;
|
||||
}
|
||||
|
||||
#ifdef D3D12_ENABLED
|
||||
// A dynamic cast is used here because the rendering context is not an Object and Object:cast is not supported.
|
||||
RenderingContextDriverD3D12 *rendering_context_d3d12 = dynamic_cast<RenderingContextDriverD3D12 *>(rendering_context);
|
||||
if (rendering_context_d3d12) {
|
||||
IDXGIFactory2 *dxgi_factory = rendering_context_d3d12->dxgi_factory_get();
|
||||
// A dynamic cast is used here because the rendering context is not an Object and Object:cast is not supported.
|
||||
RenderingContextDriverD3D12 *rendering_context_d3d12 = dynamic_cast<RenderingContextDriverD3D12 *>(rendering_context);
|
||||
if (rendering_context_d3d12) {
|
||||
IDXGIFactory2 *dxgi_factory = rendering_context_d3d12->dxgi_factory_get();
|
||||
|
||||
DXGI_OUTPUT_DESC1 desc;
|
||||
if (_get_monitor_desc(monitor, dxgi_factory, desc)) {
|
||||
data.hdr_supported = desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
data.min_luminance = desc.MinLuminance;
|
||||
data.max_luminance = desc.MaxLuminance;
|
||||
data.max_average_luminance = desc.MaxFullFrameLuminance;
|
||||
DXGI_OUTPUT_DESC1 desc;
|
||||
if (_get_monitor_desc(monitor, dxgi_factory, desc)) {
|
||||
data.hdr_supported = desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||
data.min_luminance = desc.MinLuminance;
|
||||
data.max_luminance = desc.MaxLuminance;
|
||||
data.max_average_luminance = desc.MaxFullFrameLuminance;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // D3D12_ENABLED
|
||||
|
||||
if (p_include_sdr_white_level) {
|
||||
uint32_t path_count = 0;
|
||||
uint32_t mode_count = 0;
|
||||
if (p_include_sdr_white_level) {
|
||||
uint32_t path_count = 0;
|
||||
uint32_t mode_count = 0;
|
||||
|
||||
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) {
|
||||
LocalVector<DISPLAYCONFIG_PATH_INFO> paths;
|
||||
LocalVector<DISPLAYCONFIG_MODE_INFO> modes;
|
||||
paths.resize(path_count);
|
||||
modes.resize(mode_count);
|
||||
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &path_count, &mode_count) == ERROR_SUCCESS) {
|
||||
LocalVector<DISPLAYCONFIG_PATH_INFO> paths;
|
||||
LocalVector<DISPLAYCONFIG_MODE_INFO> modes;
|
||||
paths.resize(path_count);
|
||||
modes.resize(mode_count);
|
||||
|
||||
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, paths.ptr(), &mode_count, modes.ptr(), nullptr) == ERROR_SUCCESS) {
|
||||
data.sdr_white_level = _get_sdr_white_level_for_hmonitor(monitor, paths);
|
||||
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &path_count, paths.ptr(), &mode_count, modes.ptr(), nullptr) == ERROR_SUCCESS) {
|
||||
data.sdr_white_level = _get_sdr_white_level_for_hmonitor(monitor, paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3449,6 +3455,13 @@ DisplayServerWindows::ScreenHdrData DisplayServerWindows::_get_screen_hdr_data(i
|
||||
return data;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::_winrt_adv_color_info_cb(DisplayServerEnums::WindowID p_id) {
|
||||
WindowData &wd = windows[p_id];
|
||||
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_id, true);
|
||||
_update_hdr_output_for_window(p_id, wd, data);
|
||||
}
|
||||
|
||||
void DisplayServerWindows::_update_hdr_output_for_window(DisplayServerEnums::WindowID p_window, const WindowData &p_window_data, ScreenHdrData p_screen_data) {
|
||||
#ifdef RD_ENABLED
|
||||
if (rendering_context) {
|
||||
@@ -3494,15 +3507,18 @@ void DisplayServerWindows::_update_hdr_output_for_window(DisplayServerEnums::Win
|
||||
#endif // RD_ENABLED
|
||||
}
|
||||
|
||||
void DisplayServerWindows::_update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level) {
|
||||
void DisplayServerWindows::_legacy_update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level) {
|
||||
hdr_output_cache.clear();
|
||||
for (const KeyValue<DisplayServerEnums::WindowID, WindowData> &E : windows) {
|
||||
if (WinRTUtils::window_has_display_info(E.value.wrt_wd)) {
|
||||
continue; // Updated by "_winrt_adv_color_info_cb" callback.
|
||||
}
|
||||
if (E.value.hdr_output_requested) {
|
||||
int screen = window_get_current_screen(E.key);
|
||||
|
||||
ScreenHdrData data;
|
||||
if (!hdr_output_cache.has(screen)) {
|
||||
data = _get_screen_hdr_data(screen, p_include_sdr_white_level);
|
||||
data = _get_screen_hdr_data(E.key, p_include_sdr_white_level);
|
||||
hdr_output_cache.insert(screen, data);
|
||||
} else {
|
||||
data = hdr_output_cache[screen];
|
||||
@@ -4211,7 +4227,7 @@ void DisplayServerWindows::process_events() {
|
||||
// because the only way to adjust this is to leave the Godot Window and adjust the SDR/HDR
|
||||
// Content Brightness Windows display setting. This means the user must return to the Godot
|
||||
// window, which triggers a WM_WINDOWPOSCHANGED event.
|
||||
_update_hdr_output_for_tracked_windows(false);
|
||||
_legacy_update_hdr_output_for_tracked_windows(false);
|
||||
|
||||
LocalVector<List<FileDialogData *>::Element *> to_remove;
|
||||
for (List<FileDialogData *>::Element *E = file_dialogs.front(); E; E = E->next()) {
|
||||
@@ -4737,8 +4753,7 @@ bool DisplayServerWindows::window_is_hdr_output_supported(DisplayServerEnums::Wi
|
||||
#endif
|
||||
|
||||
// The window supports HDR if the screen it is on supports HDR.
|
||||
int screen = window_get_current_screen(p_window);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, false);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, false);
|
||||
return data.hdr_supported;
|
||||
}
|
||||
|
||||
@@ -4752,8 +4767,7 @@ void DisplayServerWindows::window_request_hdr_output(const bool p_enable, Displa
|
||||
WindowData &wd = windows[p_window];
|
||||
wd.hdr_output_requested = p_enable;
|
||||
|
||||
int screen = window_get_current_screen(p_window);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, true);
|
||||
_update_hdr_output_for_window(p_window, wd, data);
|
||||
}
|
||||
|
||||
@@ -4789,8 +4803,7 @@ void DisplayServerWindows::window_set_hdr_output_reference_luminance(const float
|
||||
|
||||
// Negative luminance means auto-adjust
|
||||
if (wd.hdr_output_reference_luminance < 0.0f) {
|
||||
int screen = window_get_current_screen(p_window);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, true);
|
||||
_update_hdr_output_for_window(p_window, wd, data);
|
||||
} else {
|
||||
// Otherwise, apply the requested luminance
|
||||
@@ -4835,8 +4848,7 @@ void DisplayServerWindows::window_set_hdr_output_max_luminance(const float p_max
|
||||
|
||||
// Negative luminance means auto-adjust
|
||||
if (wd.hdr_output_max_luminance < 0.0f) {
|
||||
int screen = window_get_current_screen(p_window);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(screen, true);
|
||||
DisplayServerWindows::ScreenHdrData data = _get_screen_hdr_data(p_window, true);
|
||||
_update_hdr_output_for_window(p_window, wd, data);
|
||||
} else {
|
||||
// Otherwise, apply the requested luminance
|
||||
@@ -6356,7 +6368,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||
|
||||
case WM_DISPLAYCHANGE: {
|
||||
// Update HDR capabilities and reference luminance when display changes.
|
||||
_update_hdr_output_for_tracked_windows(true);
|
||||
_legacy_update_hdr_output_for_tracked_windows(true);
|
||||
} break;
|
||||
|
||||
case WM_WINDOWPOSCHANGED: {
|
||||
@@ -6497,7 +6509,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
||||
// Update HDR capabilities and reference luminance when window moves to different screen.
|
||||
// Also update when Godot has regained focus because the user may have adjusted their SDR white
|
||||
// level while Godot was not in focus.
|
||||
_update_hdr_output_for_tracked_windows(true);
|
||||
_legacy_update_hdr_output_for_tracked_windows(true);
|
||||
|
||||
// Return here to prevent WM_MOVE and WM_SIZE from being sent
|
||||
// See: https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanged#remarks
|
||||
@@ -7036,6 +7048,10 @@ Error DisplayServerWindows::_create_window(DisplayServerEnums::WindowID p_window
|
||||
|
||||
wd.parent_hwnd = p_parent_hwnd;
|
||||
|
||||
if (has_winrt_queue) {
|
||||
wd.wrt_wd = WinRTUtils::create_wd(wd.hWnd, callable_mp(this, &DisplayServerWindows::_winrt_adv_color_info_cb), wd.id);
|
||||
}
|
||||
|
||||
// Detach the input queue from the parent window.
|
||||
// This prevents the embedded window from waiting on the main window's input queue,
|
||||
// causing lags input lags when resizing or moving the main window.
|
||||
@@ -7228,6 +7244,9 @@ void DisplayServerWindows::_destroy_window(DisplayServerEnums::WindowID p_window
|
||||
wd.icon_small = nullptr;
|
||||
}
|
||||
|
||||
if (has_winrt_queue) {
|
||||
WinRTUtils::destroy_wd(wd.wrt_wd);
|
||||
}
|
||||
DestroyWindow(wd.hWnd);
|
||||
windows.erase(p_window_id);
|
||||
}
|
||||
@@ -7565,6 +7584,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Dis
|
||||
}
|
||||
native_menu = memnew(NativeMenuWindows);
|
||||
|
||||
has_winrt_queue = WinRTUtils::create_queue();
|
||||
|
||||
// Enforce default keep screen on value.
|
||||
screen_set_keep_on(GLOBAL_GET("display/window/energy_saving/keep_screen_on"));
|
||||
|
||||
@@ -8238,6 +8259,10 @@ DisplayServerWindows::~DisplayServerWindows() {
|
||||
|
||||
cursors_cache.clear();
|
||||
|
||||
if (has_winrt_queue) {
|
||||
WinRTUtils::destroy_queue();
|
||||
}
|
||||
|
||||
// Destroy all status indicators.
|
||||
for (HashMap<DisplayServerEnums::IndicatorID, IndicatorData>::Iterator E = indicators.begin(); E; ++E) {
|
||||
NOTIFYICONDATAW ndat;
|
||||
|
||||
@@ -184,6 +184,7 @@ typedef struct {
|
||||
class DropTargetWindows;
|
||||
class NativeMenuWindows;
|
||||
class TTS_Windows;
|
||||
class WinRTWindowData;
|
||||
|
||||
#ifndef WDA_EXCLUDEFROMCAPTURE
|
||||
#define WDA_EXCLUDEFROMCAPTURE 0x00000011
|
||||
@@ -282,9 +283,13 @@ class DisplayServerWindows : public DisplayServer {
|
||||
NativeMenuWindows *native_menu = nullptr;
|
||||
ITaskbarList3 *taskbar = nullptr;
|
||||
|
||||
bool has_winrt_queue = false;
|
||||
void _winrt_adv_color_info_cb(DisplayServerEnums::WindowID p_id);
|
||||
|
||||
struct WindowData {
|
||||
HWND hWnd;
|
||||
DisplayServerEnums::WindowID id;
|
||||
WinRTWindowData *wrt_wd = nullptr;
|
||||
|
||||
Vector<Vector2> mpath;
|
||||
DisplayServerEnums::ProgressState progress_state = DisplayServerEnums::PROGRESS_STATE_NOPROGRESS;
|
||||
@@ -556,9 +561,9 @@ class DisplayServerWindows : public DisplayServer {
|
||||
};
|
||||
AHashMap<int, ScreenHdrData> hdr_output_cache;
|
||||
|
||||
ScreenHdrData _get_screen_hdr_data(int p_screen, bool p_include_sdr_white_level) const;
|
||||
ScreenHdrData _get_screen_hdr_data(DisplayServerEnums::WindowID p_window, bool p_include_sdr_white_level) const;
|
||||
void _update_hdr_output_for_window(DisplayServerEnums::WindowID p_window, const WindowData &p_window_data, ScreenHdrData p_screen_data);
|
||||
void _update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level);
|
||||
void _legacy_update_hdr_output_for_tracked_windows(bool p_include_sdr_white_level);
|
||||
|
||||
public:
|
||||
LRESULT WndProcFileDialog(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
@@ -42,16 +42,99 @@ GODOT_GCC_WARNING_IGNORE("-Wstrict-aliasing")
|
||||
GODOT_CLANG_WARNING_PUSH
|
||||
GODOT_CLANG_WARNING_IGNORE("-Wnon-virtual-dtor")
|
||||
|
||||
#include <inspectable.h>
|
||||
#include <winrt/Windows.Foundation.Metadata.h>
|
||||
#include <winrt/Windows.Graphics.Display.h>
|
||||
#include <winrt/Windows.System.h>
|
||||
#include <winrt/Windows.UI.Input.h>
|
||||
#include <winrt/Windows.UI.ViewManagement.Core.h>
|
||||
|
||||
enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE {
|
||||
DQTAT_COM_NONE = 0,
|
||||
DQTAT_COM_ASTA = 1,
|
||||
DQTAT_COM_STA = 2
|
||||
};
|
||||
|
||||
enum DISPATCHERQUEUE_THREAD_TYPE {
|
||||
DQTYPE_THREAD_DEDICATED = 1,
|
||||
DQTYPE_THREAD_CURRENT = 2,
|
||||
};
|
||||
|
||||
struct DispatcherQueueOptions {
|
||||
DWORD dwSize;
|
||||
DISPATCHERQUEUE_THREAD_TYPE threadType;
|
||||
DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
|
||||
};
|
||||
|
||||
extern "C" HRESULT __declspec(dllexport) WINAPI CreateDispatcherQueueController(DispatcherQueueOptions options, void *dispatcherQueueController);
|
||||
|
||||
#ifndef E_BOUNDS
|
||||
#define E_BOUNDS _HRESULT_TYPEDEF_(0x8000000B)
|
||||
#endif // E_BOUNDS
|
||||
|
||||
#if defined __MINGW32__ || defined __MINGW64__
|
||||
|
||||
#ifndef __IDisplayInformationStaticsInterop_INTERFACE_DEFINED__
|
||||
#define __IDisplayInformationStaticsInterop_INTERFACE_DEFINED__
|
||||
|
||||
// clang-format off
|
||||
MIDL_INTERFACE("7449121c-382b-4705-8da7-a795ba482013")
|
||||
IDisplayInformationStaticsInterop : public IInspectable {
|
||||
public:
|
||||
virtual HRESULT STDMETHODCALLTYPE GetForWindow(
|
||||
HWND window,
|
||||
REFIID riid,
|
||||
void **displayInfo) = 0;
|
||||
|
||||
virtual HRESULT STDMETHODCALLTYPE GetForMonitor(
|
||||
HMONITOR monitor,
|
||||
REFIID riid,
|
||||
void **displayInfo) = 0;
|
||||
};
|
||||
// clang-format on
|
||||
#ifdef __CRT_UUID_DECL
|
||||
__CRT_UUID_DECL(IDisplayInformationStaticsInterop, 0x7449121c, 0x382b, 0x4705, 0x8d, 0xa7, 0xa7, 0x95, 0xba, 0x48, 0x20, 0x13)
|
||||
#endif // __CRT_UUID_DECL
|
||||
|
||||
#endif // __IDisplayInformationStaticsInterop_INTERFACE_DEFINED__
|
||||
|
||||
#else // defined __MINGW32__ || defined __MINGW64__
|
||||
|
||||
#include <windows.graphics.display.interop.h>
|
||||
|
||||
#endif // defined __MINGW32__ || defined __MINGW64__
|
||||
|
||||
GODOT_GCC_WARNING_POP
|
||||
GODOT_CLANG_WARNING_POP
|
||||
|
||||
using namespace winrt::Windows::Graphics::Display;
|
||||
using namespace winrt::Windows::System;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Metadata;
|
||||
using namespace winrt::Windows::UI::ViewManagement::Core;
|
||||
|
||||
DispatcherQueueController controller{ nullptr };
|
||||
|
||||
class WinRTWindowData {
|
||||
friend class WinRTUtils;
|
||||
|
||||
int64_t id = 0;
|
||||
bool has_disp_info = false;
|
||||
DisplayInformation disp_info{ nullptr };
|
||||
Callable cb;
|
||||
winrt::event_token token{};
|
||||
};
|
||||
|
||||
bool WinRTUtils::create_queue() {
|
||||
DispatcherQueueOptions options{ sizeof(options), DQTYPE_THREAD_CURRENT, DQTAT_COM_NONE };
|
||||
HRESULT res = CreateDispatcherQueueController(options, winrt::put_abi(controller));
|
||||
return SUCCEEDED(res);
|
||||
}
|
||||
|
||||
void WinRTUtils::destroy_queue() {
|
||||
controller.ShutdownQueueAsync();
|
||||
}
|
||||
|
||||
bool WinRTUtils::try_show_onecore_emoji_picker() {
|
||||
if (ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 7)) { // Windows 10, 1809+
|
||||
return CoreInputView::GetForCurrentView().TryShow(CoreInputViewKind::Emoji);
|
||||
@@ -59,10 +142,84 @@ bool WinRTUtils::try_show_onecore_emoji_picker() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WinRTUtils::window_has_display_info(const WinRTWindowData *p_data) {
|
||||
if (p_data) {
|
||||
return p_data->has_disp_info;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void WinRTUtils::window_get_advanced_color_info(const WinRTWindowData *p_data, bool &r_hdr_supported, float &r_min_luminance, float &r_max_luminance, float &r_max_average_luminance, float &r_sdr_white_level) {
|
||||
if (p_data && p_data->has_disp_info) {
|
||||
Dictionary info;
|
||||
|
||||
AdvancedColorInfo adv_info = p_data->disp_info.GetAdvancedColorInfo();
|
||||
|
||||
r_hdr_supported = (adv_info.CurrentAdvancedColorKind() == AdvancedColorKind::HighDynamicRange);
|
||||
r_min_luminance = adv_info.MinLuminanceInNits();
|
||||
r_max_luminance = adv_info.MaxLuminanceInNits();
|
||||
r_max_average_luminance = adv_info.MaxAverageFullFrameLuminanceInNits();
|
||||
r_sdr_white_level = adv_info.SdrWhiteLevelInNits();
|
||||
}
|
||||
}
|
||||
|
||||
WinRTWindowData *WinRTUtils::create_wd(HWND p_window, const Callable &p_color_cb, int64_t p_window_id) {
|
||||
WinRTWindowData *wd = memnew(WinRTWindowData);
|
||||
|
||||
wd->id = p_window_id;
|
||||
wd->cb = p_color_cb;
|
||||
if (ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 6)) {
|
||||
try {
|
||||
HRESULT res = winrt::get_activation_factory<DisplayInformation, IDisplayInformationStaticsInterop>()->GetForWindow(p_window, winrt::guid_of<DisplayInformation>(), winrt::put_abi(wd->disp_info));
|
||||
if (res == S_OK && wd->disp_info) {
|
||||
wd->has_disp_info = true;
|
||||
wd->token = wd->disp_info.AdvancedColorInfoChanged([wd](const DisplayInformation &p_sender, auto &&) {
|
||||
wd->cb.call_deferred(wd->id);
|
||||
});
|
||||
}
|
||||
} catch (...) {
|
||||
memdelete(wd);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return wd;
|
||||
}
|
||||
|
||||
void WinRTUtils::destroy_wd(WinRTWindowData *p_data) {
|
||||
if (p_data) {
|
||||
if (p_data->token) {
|
||||
p_data->disp_info.AdvancedColorInfoChanged(p_data->token);
|
||||
}
|
||||
p_data->disp_info = nullptr;
|
||||
|
||||
memdelete(p_data);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool WinRTUtils::try_show_onecore_emoji_picker() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WinRTUtils::create_queue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void WinRTUtils::destroy_queue() {}
|
||||
|
||||
bool WinRTUtils::window_has_display_info(const WinRTWindowData *p_data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void WinRTUtils::window_get_advanced_color_info(const WinRTWindowData *p_data, bool &r_hdr_supported, float &r_min_luminance, float &r_max_luminance, float &r_max_average_luminance, float &r_sdr_white_level) {}
|
||||
|
||||
WinRTWindowData *WinRTUtils::create_wd(HWND p_window, const Callable &p_color_cb, int64_t p_window_id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void WinRTUtils::destroy_wd(WinRTWindowData *p_data) {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -30,7 +30,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/typedefs.h"
|
||||
#include "core/variant/callable.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
class WinRTWindowData;
|
||||
|
||||
class WinRTUtils {
|
||||
public:
|
||||
static bool try_show_onecore_emoji_picker();
|
||||
|
||||
static bool create_queue();
|
||||
static void destroy_queue();
|
||||
|
||||
static WinRTWindowData *create_wd(HWND p_window, const Callable &p_color_cb, int64_t p_window_id);
|
||||
static bool window_has_display_info(const WinRTWindowData *p_data);
|
||||
static void window_get_advanced_color_info(const WinRTWindowData *p_data, bool &r_hdr_supported, float &r_min_luminance, float &r_max_luminance, float &r_max_average_luminance, float &r_sdr_white_level);
|
||||
static void destroy_wd(WinRTWindowData *p_data);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user