Refine XCEditor docking and DPI rendering
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Shell/ProductShellAsset.h"
|
||||
|
||||
#include <XCEditor/Foundation/UIEditorRuntimeTrace.h>
|
||||
#include <XCEditor/Foundation/UIEditorTheme.h>
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
@@ -10,8 +11,11 @@
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#ifndef XCUIEDITOR_REPO_ROOT
|
||||
#define XCUIEDITOR_REPO_ROOT "."
|
||||
#endif
|
||||
@@ -34,11 +38,112 @@ using App::BuildProductShellInteractionDefinition;
|
||||
|
||||
constexpr const wchar_t* kWindowClassName = L"XCEditorShellHost";
|
||||
constexpr const wchar_t* kWindowTitle = L"Main Scene * - Main.xx - XCEngine Editor";
|
||||
constexpr UINT kDefaultDpi = 96u;
|
||||
constexpr float kBaseDpiScale = 96.0f;
|
||||
|
||||
Application* GetApplicationFromWindow(HWND hwnd) {
|
||||
return reinterpret_cast<Application*>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
|
||||
}
|
||||
|
||||
UINT QuerySystemDpi() {
|
||||
HDC screenDc = GetDC(nullptr);
|
||||
if (screenDc == nullptr) {
|
||||
return kDefaultDpi;
|
||||
}
|
||||
|
||||
const int dpiX = GetDeviceCaps(screenDc, LOGPIXELSX);
|
||||
ReleaseDC(nullptr, screenDc);
|
||||
return dpiX > 0 ? static_cast<UINT>(dpiX) : kDefaultDpi;
|
||||
}
|
||||
|
||||
UINT QueryWindowDpi(HWND hwnd) {
|
||||
if (hwnd != nullptr) {
|
||||
const HMODULE user32 = GetModuleHandleW(L"user32.dll");
|
||||
if (user32 != nullptr) {
|
||||
using GetDpiForWindowFn = UINT(WINAPI*)(HWND);
|
||||
const auto getDpiForWindow =
|
||||
reinterpret_cast<GetDpiForWindowFn>(GetProcAddress(user32, "GetDpiForWindow"));
|
||||
if (getDpiForWindow != nullptr) {
|
||||
const UINT dpi = getDpiForWindow(hwnd);
|
||||
if (dpi != 0u) {
|
||||
return dpi;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QuerySystemDpi();
|
||||
}
|
||||
|
||||
void EnableDpiAwareness() {
|
||||
const HMODULE user32 = GetModuleHandleW(L"user32.dll");
|
||||
if (user32 != nullptr) {
|
||||
using SetProcessDpiAwarenessContextFn = BOOL(WINAPI*)(DPI_AWARENESS_CONTEXT);
|
||||
const auto setProcessDpiAwarenessContext =
|
||||
reinterpret_cast<SetProcessDpiAwarenessContextFn>(
|
||||
GetProcAddress(user32, "SetProcessDpiAwarenessContext"));
|
||||
if (setProcessDpiAwarenessContext != nullptr) {
|
||||
if (setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) {
|
||||
return;
|
||||
}
|
||||
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
||||
return;
|
||||
}
|
||||
if (setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) {
|
||||
return;
|
||||
}
|
||||
if (GetLastError() == ERROR_ACCESS_DENIED) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const HMODULE shcore = LoadLibraryW(L"shcore.dll");
|
||||
if (shcore != nullptr) {
|
||||
using SetProcessDpiAwarenessFn = HRESULT(WINAPI*)(PROCESS_DPI_AWARENESS);
|
||||
const auto setProcessDpiAwareness =
|
||||
reinterpret_cast<SetProcessDpiAwarenessFn>(
|
||||
GetProcAddress(shcore, "SetProcessDpiAwareness"));
|
||||
if (setProcessDpiAwareness != nullptr) {
|
||||
const HRESULT hr = setProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
|
||||
FreeLibrary(shcore);
|
||||
if (SUCCEEDED(hr) || hr == E_ACCESSDENIED) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
FreeLibrary(shcore);
|
||||
}
|
||||
}
|
||||
|
||||
if (user32 != nullptr) {
|
||||
using SetProcessDPIAwareFn = BOOL(WINAPI*)();
|
||||
const auto setProcessDPIAware =
|
||||
reinterpret_cast<SetProcessDPIAwareFn>(GetProcAddress(user32, "SetProcessDPIAware"));
|
||||
if (setProcessDPIAware != nullptr) {
|
||||
setProcessDPIAware();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TryEnableNonClientDpiScaling(HWND hwnd) {
|
||||
if (hwnd == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const HMODULE user32 = GetModuleHandleW(L"user32.dll");
|
||||
if (user32 == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
using EnableNonClientDpiScalingFn = BOOL(WINAPI*)(HWND);
|
||||
const auto enableNonClientDpiScaling =
|
||||
reinterpret_cast<EnableNonClientDpiScalingFn>(
|
||||
GetProcAddress(user32, "EnableNonClientDpiScaling"));
|
||||
if (enableNonClientDpiScaling != nullptr) {
|
||||
enableNonClientDpiScaling(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
std::string TruncateText(const std::string& text, std::size_t maxLength) {
|
||||
if (text.size() <= maxLength) {
|
||||
return text;
|
||||
@@ -146,6 +251,44 @@ bool IsRepeatKeyMessage(LPARAM lParam) {
|
||||
return (static_cast<unsigned long>(lParam) & (1ul << 30)) != 0ul;
|
||||
}
|
||||
|
||||
std::filesystem::path GetExecutableDirectory() {
|
||||
std::vector<wchar_t> buffer(MAX_PATH);
|
||||
while (true) {
|
||||
const DWORD copied = ::GetModuleFileNameW(
|
||||
nullptr,
|
||||
buffer.data(),
|
||||
static_cast<DWORD>(buffer.size()));
|
||||
if (copied == 0u) {
|
||||
return std::filesystem::current_path().lexically_normal();
|
||||
}
|
||||
|
||||
if (copied < buffer.size() - 1u) {
|
||||
return std::filesystem::path(std::wstring(buffer.data(), copied))
|
||||
.parent_path()
|
||||
.lexically_normal();
|
||||
}
|
||||
|
||||
buffer.resize(buffer.size() * 2u);
|
||||
}
|
||||
}
|
||||
|
||||
std::string DescribeInputEventType(const UIInputEvent& event) {
|
||||
switch (event.type) {
|
||||
case UIInputEventType::PointerMove: return "PointerMove";
|
||||
case UIInputEventType::PointerEnter: return "PointerEnter";
|
||||
case UIInputEventType::PointerLeave: return "PointerLeave";
|
||||
case UIInputEventType::PointerButtonDown: return "PointerDown";
|
||||
case UIInputEventType::PointerButtonUp: return "PointerUp";
|
||||
case UIInputEventType::PointerWheel: return "PointerWheel";
|
||||
case UIInputEventType::KeyDown: return "KeyDown";
|
||||
case UIInputEventType::KeyUp: return "KeyUp";
|
||||
case UIInputEventType::Character: return "Character";
|
||||
case UIInputEventType::FocusGained: return "FocusGained";
|
||||
case UIInputEventType::FocusLost: return "FocusLost";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int Application::Run(HINSTANCE hInstance, int nCmdShow) {
|
||||
@@ -172,10 +315,17 @@ int Application::Run(HINSTANCE hInstance, int nCmdShow) {
|
||||
|
||||
bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
|
||||
m_hInstance = hInstance;
|
||||
EnableDpiAwareness();
|
||||
const std::filesystem::path logRoot =
|
||||
GetExecutableDirectory() / "logs";
|
||||
InitializeUIEditorRuntimeTrace(logRoot);
|
||||
SetUnhandledExceptionFilter(&Application::HandleUnhandledException);
|
||||
LogRuntimeTrace("app", "initialize begin");
|
||||
m_shellAsset = BuildProductShellAsset(ResolveRepoRootPath());
|
||||
m_shellValidation = ValidateEditorShellAsset(m_shellAsset);
|
||||
m_validationMessage = m_shellValidation.message;
|
||||
if (!m_shellValidation.IsValid()) {
|
||||
LogRuntimeTrace("app", "shell asset validation failed: " + m_validationMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -188,8 +338,10 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
|
||||
m_shellServices = {};
|
||||
m_shellServices.commandDispatcher = &m_shortcutManager.GetCommandDispatcher();
|
||||
m_shellServices.shortcutManager = &m_shortcutManager;
|
||||
m_shellServices.textMeasurer = &m_renderer;
|
||||
m_lastStatus = "Ready";
|
||||
m_lastMessage = "Old editor shell baseline loaded.";
|
||||
LogRuntimeTrace("app", "workspace initialized: " + DescribeWorkspaceState());
|
||||
|
||||
WNDCLASSEXW windowClass = {};
|
||||
windowClass.cbSize = sizeof(windowClass);
|
||||
@@ -200,6 +352,7 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
|
||||
windowClass.lpszClassName = kWindowClassName;
|
||||
m_windowClassAtom = RegisterClassExW(&windowClass);
|
||||
if (m_windowClassAtom == 0) {
|
||||
LogRuntimeTrace("app", "window class registration failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -207,7 +360,7 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
|
||||
0,
|
||||
kWindowClassName,
|
||||
kWindowTitle,
|
||||
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
1540,
|
||||
@@ -217,26 +370,37 @@ bool Application::Initialize(HINSTANCE hInstance, int nCmdShow) {
|
||||
hInstance,
|
||||
this);
|
||||
if (m_hwnd == nullptr) {
|
||||
LogRuntimeTrace("app", "window creation failed");
|
||||
return false;
|
||||
}
|
||||
m_windowDpi = QueryWindowDpi(m_hwnd);
|
||||
m_dpiScale = GetDpiScale();
|
||||
m_renderer.SetDpiScale(m_dpiScale);
|
||||
|
||||
std::ostringstream dpiTrace = {};
|
||||
dpiTrace << "initial dpi=" << m_windowDpi << " scale=" << m_dpiScale;
|
||||
LogRuntimeTrace("window", dpiTrace.str());
|
||||
|
||||
if (!m_renderer.Initialize(m_hwnd)) {
|
||||
LogRuntimeTrace("app", "renderer initialization failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
ShowWindow(m_hwnd, nCmdShow);
|
||||
UpdateWindow(m_hwnd);
|
||||
|
||||
if (!m_renderer.Initialize(m_hwnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_autoScreenshot.Initialize(m_shellAsset.captureRootPath);
|
||||
if (IsAutoCaptureOnStartupEnabled()) {
|
||||
m_autoScreenshot.RequestCapture("startup");
|
||||
m_lastStatus = "Capture";
|
||||
m_lastMessage = "Startup capture requested.";
|
||||
}
|
||||
LogRuntimeTrace("app", "initialize completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::Shutdown() {
|
||||
LogRuntimeTrace("app", "shutdown begin");
|
||||
if (GetCapture() == m_hwnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
@@ -253,6 +417,9 @@ void Application::Shutdown() {
|
||||
UnregisterClassW(kWindowClassName, m_hInstance);
|
||||
m_windowClassAtom = 0;
|
||||
}
|
||||
|
||||
LogRuntimeTrace("app", "shutdown end");
|
||||
ShutdownUIEditorRuntimeTrace();
|
||||
}
|
||||
|
||||
void Application::RenderFrame() {
|
||||
@@ -262,8 +429,12 @@ void Application::RenderFrame() {
|
||||
|
||||
RECT clientRect = {};
|
||||
GetClientRect(m_hwnd, &clientRect);
|
||||
const float width = static_cast<float>((std::max)(clientRect.right - clientRect.left, 1L));
|
||||
const float height = static_cast<float>((std::max)(clientRect.bottom - clientRect.top, 1L));
|
||||
const unsigned int pixelWidth =
|
||||
static_cast<unsigned int>((std::max)(clientRect.right - clientRect.left, 1L));
|
||||
const unsigned int pixelHeight =
|
||||
static_cast<unsigned int>((std::max)(clientRect.bottom - clientRect.top, 1L));
|
||||
const float width = PixelsToDips(static_cast<float>(pixelWidth));
|
||||
const float height = PixelsToDips(static_cast<float>(pixelHeight));
|
||||
|
||||
UIDrawData drawData = {};
|
||||
UIDrawList& drawList = drawData.EmplaceDrawList("XCEditorShell");
|
||||
@@ -277,6 +448,11 @@ void Application::RenderFrame() {
|
||||
const UIEditorShellInteractionDefinition definition = BuildShellDefinition();
|
||||
std::vector<UIInputEvent> frameEvents = std::move(m_pendingInputEvents);
|
||||
m_pendingInputEvents.clear();
|
||||
if (!frameEvents.empty()) {
|
||||
LogRuntimeTrace(
|
||||
"input",
|
||||
DescribeInputEvents(frameEvents) + " | " + DescribeWorkspaceState());
|
||||
}
|
||||
|
||||
m_shellFrame = UpdateUIEditorShellInteraction(
|
||||
m_shellInteractionState,
|
||||
@@ -286,6 +462,24 @@ void Application::RenderFrame() {
|
||||
frameEvents,
|
||||
m_shellServices,
|
||||
metrics);
|
||||
if (!frameEvents.empty() ||
|
||||
m_shellFrame.result.workspaceResult.dockHostResult.layoutChanged ||
|
||||
m_shellFrame.result.workspaceResult.dockHostResult.commandExecuted) {
|
||||
std::ostringstream frameTrace = {};
|
||||
frameTrace << "result consumed="
|
||||
<< (m_shellFrame.result.consumed ? "true" : "false")
|
||||
<< " layoutChanged="
|
||||
<< (m_shellFrame.result.workspaceResult.dockHostResult.layoutChanged ? "true" : "false")
|
||||
<< " commandExecuted="
|
||||
<< (m_shellFrame.result.workspaceResult.dockHostResult.commandExecuted ? "true" : "false")
|
||||
<< " active="
|
||||
<< m_workspaceController.GetWorkspace().activePanelId
|
||||
<< " message="
|
||||
<< m_shellFrame.result.workspaceResult.dockHostResult.layoutResult.message;
|
||||
LogRuntimeTrace(
|
||||
"frame",
|
||||
frameTrace.str());
|
||||
}
|
||||
ApplyHostCaptureRequests(m_shellFrame.result);
|
||||
UpdateLastStatus(m_shellFrame.result);
|
||||
AppendUIEditorShellInteraction(
|
||||
@@ -311,11 +505,78 @@ void Application::RenderFrame() {
|
||||
m_autoScreenshot.CaptureIfRequested(
|
||||
m_renderer,
|
||||
drawData,
|
||||
static_cast<unsigned int>(width),
|
||||
static_cast<unsigned int>(height),
|
||||
pixelWidth,
|
||||
pixelHeight,
|
||||
framePresented);
|
||||
}
|
||||
|
||||
float Application::GetDpiScale() const {
|
||||
const UINT dpi = m_windowDpi == 0u ? kDefaultDpi : m_windowDpi;
|
||||
return static_cast<float>(dpi) / kBaseDpiScale;
|
||||
}
|
||||
|
||||
float Application::PixelsToDips(float pixels) const {
|
||||
const float dpiScale = GetDpiScale();
|
||||
return dpiScale > 0.0f ? pixels / dpiScale : pixels;
|
||||
}
|
||||
|
||||
UIPoint Application::ConvertClientPixelsToDips(LONG x, LONG y) const {
|
||||
return UIPoint(
|
||||
PixelsToDips(static_cast<float>(x)),
|
||||
PixelsToDips(static_cast<float>(y)));
|
||||
}
|
||||
|
||||
void Application::LogRuntimeTrace(
|
||||
std::string_view channel,
|
||||
std::string_view message) const {
|
||||
AppendUIEditorRuntimeTrace(channel, message);
|
||||
}
|
||||
|
||||
std::string Application::DescribeWorkspaceState() const {
|
||||
std::ostringstream stream = {};
|
||||
stream << "active=" << m_workspaceController.GetWorkspace().activePanelId;
|
||||
const auto visiblePanels =
|
||||
CollectUIEditorWorkspaceVisiblePanels(
|
||||
m_workspaceController.GetWorkspace(),
|
||||
m_workspaceController.GetSession());
|
||||
stream << " visible=[";
|
||||
for (std::size_t index = 0; index < visiblePanels.size(); ++index) {
|
||||
if (index > 0u) {
|
||||
stream << ',';
|
||||
}
|
||||
stream << visiblePanels[index].panelId;
|
||||
}
|
||||
stream << ']';
|
||||
|
||||
const auto& dockState =
|
||||
m_shellInteractionState.workspaceInteractionState.dockHostInteractionState;
|
||||
stream << " dragNode=" << dockState.activeTabDragNodeId;
|
||||
stream << " dragPanel=" << dockState.activeTabDragPanelId;
|
||||
if (dockState.dockHostState.dropPreview.visible) {
|
||||
stream << " dropTarget=" << dockState.dockHostState.dropPreview.targetNodeId;
|
||||
}
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::string Application::DescribeInputEvents(
|
||||
const std::vector<UIInputEvent>& events) const {
|
||||
std::ostringstream stream = {};
|
||||
stream << "events=[";
|
||||
for (std::size_t index = 0; index < events.size(); ++index) {
|
||||
if (index > 0u) {
|
||||
stream << " | ";
|
||||
}
|
||||
const UIInputEvent& event = events[index];
|
||||
stream << DescribeInputEventType(event)
|
||||
<< '@'
|
||||
<< static_cast<int>(event.position.x)
|
||||
<< ','
|
||||
<< static_cast<int>(event.position.y);
|
||||
}
|
||||
stream << ']';
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
void Application::OnResize(UINT width, UINT height) {
|
||||
if (width == 0 || height == 0) {
|
||||
return;
|
||||
@@ -324,6 +585,27 @@ void Application::OnResize(UINT width, UINT height) {
|
||||
m_renderer.Resize(width, height);
|
||||
}
|
||||
|
||||
void Application::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
|
||||
m_windowDpi = dpi == 0u ? kDefaultDpi : dpi;
|
||||
m_dpiScale = GetDpiScale();
|
||||
m_renderer.SetDpiScale(m_dpiScale);
|
||||
if (m_hwnd != nullptr) {
|
||||
SetWindowPos(
|
||||
m_hwnd,
|
||||
nullptr,
|
||||
suggestedRect.left,
|
||||
suggestedRect.top,
|
||||
suggestedRect.right - suggestedRect.left,
|
||||
suggestedRect.bottom - suggestedRect.top,
|
||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
InvalidateRect(m_hwnd, nullptr, FALSE);
|
||||
}
|
||||
|
||||
std::ostringstream trace = {};
|
||||
trace << "dpi changed to " << m_windowDpi << " scale=" << m_dpiScale;
|
||||
LogRuntimeTrace("window", trace.str());
|
||||
}
|
||||
|
||||
void Application::ApplyHostCaptureRequests(const UIEditorShellInteractionResult& result) {
|
||||
if (result.requestPointerCapture && GetCapture() != m_hwnd) {
|
||||
SetCapture(m_hwnd);
|
||||
@@ -338,6 +620,10 @@ bool Application::HasInteractiveCaptureState() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!m_shellInteractionState.workspaceInteractionState.dockHostInteractionState.activeTabDragNodeId.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const auto& panelState : m_shellInteractionState.workspaceInteractionState.composeState.panelStates) {
|
||||
if (panelState.viewportShellState.inputBridgeState.captured) {
|
||||
return true;
|
||||
@@ -434,9 +720,9 @@ void Application::QueuePointerEvent(
|
||||
UIInputEvent event = {};
|
||||
event.type = type;
|
||||
event.pointerButton = button;
|
||||
event.position = UIPoint(
|
||||
static_cast<float>(GET_X_LPARAM(lParam)),
|
||||
static_cast<float>(GET_Y_LPARAM(lParam)));
|
||||
event.position = ConvertClientPixelsToDips(
|
||||
GET_X_LPARAM(lParam),
|
||||
GET_Y_LPARAM(lParam));
|
||||
event.modifiers = m_inputModifierTracker.BuildPointerModifiers(static_cast<std::size_t>(wParam));
|
||||
m_pendingInputEvents.push_back(event);
|
||||
}
|
||||
@@ -448,9 +734,7 @@ void Application::QueuePointerLeaveEvent() {
|
||||
POINT clientPoint = {};
|
||||
GetCursorPos(&clientPoint);
|
||||
ScreenToClient(m_hwnd, &clientPoint);
|
||||
event.position = UIPoint(
|
||||
static_cast<float>(clientPoint.x),
|
||||
static_cast<float>(clientPoint.y));
|
||||
event.position = ConvertClientPixelsToDips(clientPoint.x, clientPoint.y);
|
||||
}
|
||||
m_pendingInputEvents.push_back(event);
|
||||
}
|
||||
@@ -468,9 +752,7 @@ void Application::QueuePointerWheelEvent(short wheelDelta, WPARAM wParam, LPARAM
|
||||
|
||||
UIInputEvent event = {};
|
||||
event.type = UIInputEventType::PointerWheel;
|
||||
event.position = UIPoint(
|
||||
static_cast<float>(screenPoint.x),
|
||||
static_cast<float>(screenPoint.y));
|
||||
event.position = ConvertClientPixelsToDips(screenPoint.x, screenPoint.y);
|
||||
event.wheelDelta = static_cast<float>(wheelDelta);
|
||||
event.modifiers = m_inputModifierTracker.BuildPointerModifiers(static_cast<std::size_t>(wParam));
|
||||
m_pendingInputEvents.push_back(event);
|
||||
@@ -507,6 +789,19 @@ std::filesystem::path Application::ResolveRepoRootPath() {
|
||||
return std::filesystem::path(root).lexically_normal();
|
||||
}
|
||||
|
||||
LONG WINAPI Application::HandleUnhandledException(EXCEPTION_POINTERS* exceptionInfo) {
|
||||
if (exceptionInfo != nullptr &&
|
||||
exceptionInfo->ExceptionRecord != nullptr) {
|
||||
AppendUIEditorCrashTrace(
|
||||
exceptionInfo->ExceptionRecord->ExceptionCode,
|
||||
exceptionInfo->ExceptionRecord->ExceptionAddress);
|
||||
} else {
|
||||
AppendUIEditorCrashTrace(0u, nullptr);
|
||||
}
|
||||
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
UIEditorHostCommandEvaluationResult Application::EvaluateHostCommand(
|
||||
std::string_view commandId) const {
|
||||
UIEditorHostCommandEvaluationResult result = {};
|
||||
@@ -573,6 +868,7 @@ UIEditorHostCommandDispatchResult Application::DispatchHostCommand(
|
||||
|
||||
LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
if (message == WM_NCCREATE) {
|
||||
TryEnableNonClientDpiScaling(hwnd);
|
||||
const auto* createStruct = reinterpret_cast<CREATESTRUCTW*>(lParam);
|
||||
auto* application = reinterpret_cast<Application*>(createStruct->lpCreateParams);
|
||||
SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(application));
|
||||
@@ -581,6 +877,14 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
|
||||
Application* application = GetApplicationFromWindow(hwnd);
|
||||
switch (message) {
|
||||
case WM_DPICHANGED:
|
||||
if (application != nullptr && lParam != 0) {
|
||||
application->OnDpiChanged(
|
||||
static_cast<UINT>(LOWORD(wParam)),
|
||||
*reinterpret_cast<RECT*>(lParam));
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
if (application != nullptr && wParam != SIZE_MINIMIZED) {
|
||||
application->OnResize(static_cast<UINT>(LOWORD(lParam)), static_cast<UINT>(HIWORD(lParam)));
|
||||
|
||||
Reference in New Issue
Block a user