refactor(new_editor): continue architecture closeout
This commit is contained in:
@@ -1,9 +1,377 @@
|
||||
#include "WindowMessageDispatcher.h"
|
||||
|
||||
#include "WindowMessageDispatchHandlers.h"
|
||||
#include "Platform/Win32/EditorWindow.h"
|
||||
#include "WindowMessageHost.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace XCEngine::UI::Editor::Host {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr UINT kMessageNcUaDrawCaption = 0x00AEu;
|
||||
constexpr UINT kMessageNcUaDrawFrame = 0x00AFu;
|
||||
|
||||
} // namespace
|
||||
|
||||
struct WindowMessageDispatcher::DispatchContext {
|
||||
HWND hwnd = nullptr;
|
||||
WindowMessageHost& windowHost;
|
||||
App::EditorWindow& window;
|
||||
};
|
||||
|
||||
void WindowMessageDispatcher::RenderAndValidateWindow(const DispatchContext& context) {
|
||||
if (!context.window.IsRenderReady()) {
|
||||
return;
|
||||
}
|
||||
|
||||
App::EditorWindowFrameTransferRequests transferRequests = context.window.RenderFrame(
|
||||
context.windowHost.GetEditorContext(),
|
||||
context.windowHost.IsGlobalTabDragActive());
|
||||
if (transferRequests.HasPendingRequests()) {
|
||||
context.windowHost.HandleWindowFrameTransferRequests(
|
||||
context.window,
|
||||
std::move(transferRequests));
|
||||
}
|
||||
if (context.hwnd != nullptr && IsWindow(context.hwnd)) {
|
||||
ValidateRect(context.hwnd, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowMessageDispatcher::EnsureTrackingMouseLeave(const DispatchContext& context) {
|
||||
if (context.window.IsTrackingMouseLeave()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
TRACKMOUSEEVENT trackMouseEvent = {};
|
||||
trackMouseEvent.cbSize = sizeof(trackMouseEvent);
|
||||
trackMouseEvent.dwFlags = TME_LEAVE;
|
||||
trackMouseEvent.hwndTrack = context.hwnd;
|
||||
if (!TrackMouseEvent(&trackMouseEvent)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
context.window.SetTrackingMouseLeave(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WindowMessageDispatcher::TryHandleChromeHoverConsumption(
|
||||
const DispatchContext& context,
|
||||
LPARAM lParam,
|
||||
LRESULT& outResult) {
|
||||
const bool resizeHoverChanged = context.window.UpdateBorderlessWindowResizeHover(lParam);
|
||||
if (context.window.UpdateBorderlessWindowChromeHover(lParam)) {
|
||||
context.window.InvalidateHostWindow();
|
||||
}
|
||||
if (resizeHoverChanged) {
|
||||
context.window.InvalidateHostWindow();
|
||||
}
|
||||
|
||||
EnsureTrackingMouseLeave(context);
|
||||
if (context.window.HasHoveredBorderlessResizeEdge()) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
const BorderlessWindowChromeHitTarget chromeHitTarget =
|
||||
context.window.HitTestBorderlessWindowChrome(lParam);
|
||||
if (chromeHitTarget == BorderlessWindowChromeHitTarget::MinimizeButton ||
|
||||
chromeHitTarget == BorderlessWindowChromeHitTarget::MaximizeRestoreButton ||
|
||||
chromeHitTarget == BorderlessWindowChromeHitTarget::CloseButton) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool WindowMessageDispatcher::TryDispatchWindowPointerMessage(
|
||||
const DispatchContext& context,
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT& outResult) {
|
||||
switch (message) {
|
||||
case WM_MOUSEMOVE:
|
||||
if (context.windowHost.HandleGlobalTabDragPointerMove(context.hwnd)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (context.window.HandleBorderlessWindowResizePointerMove(
|
||||
context.windowHost.GetEditorContext(),
|
||||
context.windowHost.IsGlobalTabDragActive())) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (context.window.HandleBorderlessWindowChromeDragRestorePointerMove(
|
||||
context.windowHost.GetEditorContext(),
|
||||
context.windowHost.IsGlobalTabDragActive())) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (TryHandleChromeHoverConsumption(context, lParam, outResult)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
context.window.QueuePointerEvent(
|
||||
::XCEngine::UI::UIInputEventType::PointerMove,
|
||||
::XCEngine::UI::UIPointerButton::None,
|
||||
wParam,
|
||||
lParam);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_MOUSELEAVE:
|
||||
context.window.SetTrackingMouseLeave(false);
|
||||
context.window.ClearBorderlessWindowResizeState();
|
||||
context.window.ClearBorderlessWindowChromeDragRestoreState();
|
||||
context.window.ClearBorderlessWindowChromeState();
|
||||
context.window.QueuePointerLeaveEvent();
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_LBUTTONDOWN:
|
||||
if (context.window.HandleBorderlessWindowResizeButtonDown(lParam)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (context.window.HandleBorderlessWindowChromeButtonDown(lParam)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
SetFocus(context.hwnd);
|
||||
context.window.QueuePointerEvent(
|
||||
::XCEngine::UI::UIInputEventType::PointerButtonDown,
|
||||
::XCEngine::UI::UIPointerButton::Left,
|
||||
wParam,
|
||||
lParam);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_LBUTTONUP:
|
||||
if (context.windowHost.HandleGlobalTabDragPointerButtonUp(context.hwnd)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (context.window.HandleBorderlessWindowResizeButtonUp()) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (context.window.HandleBorderlessWindowChromeButtonUp(
|
||||
context.windowHost.GetEditorContext(),
|
||||
context.windowHost.IsGlobalTabDragActive(),
|
||||
lParam)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
context.window.QueuePointerEvent(
|
||||
::XCEngine::UI::UIInputEventType::PointerButtonUp,
|
||||
::XCEngine::UI::UIPointerButton::Left,
|
||||
wParam,
|
||||
lParam);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_LBUTTONDBLCLK:
|
||||
if (context.window.HandleBorderlessWindowChromeDoubleClick(
|
||||
context.windowHost.GetEditorContext(),
|
||||
context.windowHost.IsGlobalTabDragActive(),
|
||||
lParam)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WM_MOUSEWHEEL:
|
||||
context.window.QueuePointerWheelEvent(GET_WHEEL_DELTA_WPARAM(wParam), wParam, lParam);
|
||||
outResult = 0;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowMessageDispatcher::TryDispatchWindowInputMessage(
|
||||
const DispatchContext& context,
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT& outResult) {
|
||||
if (TryDispatchWindowPointerMessage(context, message, wParam, lParam, outResult)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
case WM_SETFOCUS:
|
||||
context.window.SyncInputModifiersFromSystemState();
|
||||
context.window.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusGained);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_KILLFOCUS:
|
||||
context.window.ResetInputModifiers();
|
||||
context.window.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusLost);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_CAPTURECHANGED:
|
||||
if (context.windowHost.OwnsActiveGlobalTabDrag(context.window.GetWindowId()) &&
|
||||
reinterpret_cast<HWND>(lParam) != context.hwnd) {
|
||||
context.windowHost.EndGlobalTabDragSession();
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (reinterpret_cast<HWND>(lParam) != context.hwnd &&
|
||||
context.window.HasInteractiveCaptureState()) {
|
||||
context.window.QueueWindowFocusEvent(::XCEngine::UI::UIInputEventType::FocusLost);
|
||||
context.window.ForceClearBorderlessWindowResizeState();
|
||||
context.window.ClearBorderlessWindowChromeDragRestoreState();
|
||||
context.window.ClearBorderlessWindowChromeState();
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
if (reinterpret_cast<HWND>(lParam) != context.hwnd) {
|
||||
context.window.ForceClearBorderlessWindowResizeState();
|
||||
context.window.ClearBorderlessWindowChromeDragRestoreState();
|
||||
context.window.ClearBorderlessWindowChromeState();
|
||||
}
|
||||
return false;
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
if (wParam == VK_F12) {
|
||||
context.window.RequestManualScreenshot();
|
||||
}
|
||||
context.window.QueueKeyEvent(::XCEngine::UI::UIInputEventType::KeyDown, wParam, lParam);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
context.window.QueueKeyEvent(::XCEngine::UI::UIInputEventType::KeyUp, wParam, lParam);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_CHAR:
|
||||
context.window.QueueCharacterEvent(wParam, lParam);
|
||||
outResult = 0;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowMessageDispatcher::TryDispatchWindowLifecycleMessage(
|
||||
const DispatchContext& context,
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT& outResult) {
|
||||
switch (message) {
|
||||
case WM_DPICHANGED:
|
||||
if (lParam == 0) {
|
||||
return false;
|
||||
}
|
||||
context.window.OnDpiChanged(
|
||||
static_cast<UINT>(LOWORD(wParam)),
|
||||
*reinterpret_cast<const RECT*>(lParam));
|
||||
RenderAndValidateWindow(context);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_ENTERSIZEMOVE:
|
||||
context.window.OnEnterSizeMove();
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_EXITSIZEMOVE:
|
||||
context.window.OnExitSizeMove();
|
||||
RenderAndValidateWindow(context);
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_SIZE:
|
||||
if (wParam != SIZE_MINIMIZED) {
|
||||
context.window.OnResize(
|
||||
static_cast<UINT>(LOWORD(lParam)),
|
||||
static_cast<UINT>(HIWORD(lParam)));
|
||||
RenderAndValidateWindow(context);
|
||||
}
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_PAINT:
|
||||
if (App::EditorWindowFrameTransferRequests transferRequests = context.window.OnPaintMessage(
|
||||
context.windowHost.GetEditorContext(),
|
||||
context.windowHost.IsGlobalTabDragActive());
|
||||
transferRequests.HasPendingRequests()) {
|
||||
context.windowHost.HandleWindowFrameTransferRequests(
|
||||
context.window,
|
||||
std::move(transferRequests));
|
||||
}
|
||||
outResult = 0;
|
||||
return true;
|
||||
case WM_ERASEBKGND:
|
||||
outResult = 1;
|
||||
return true;
|
||||
case WM_DESTROY:
|
||||
if (context.windowHost.OwnsActiveGlobalTabDrag(context.window.GetWindowId())) {
|
||||
context.windowHost.EndGlobalTabDragSession();
|
||||
}
|
||||
context.windowHost.HandleDestroyedWindow(context.hwnd);
|
||||
outResult = 0;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowMessageDispatcher::TryDispatchWindowChromeMessage(
|
||||
const DispatchContext& context,
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT& outResult) {
|
||||
switch (message) {
|
||||
case WM_GETMINMAXINFO:
|
||||
if (context.window.IsBorderlessWindowEnabled() &&
|
||||
context.window.HandleBorderlessWindowGetMinMaxInfo(lParam)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WM_NCCALCSIZE:
|
||||
if (context.window.IsBorderlessWindowEnabled()) {
|
||||
outResult = context.window.HandleBorderlessWindowNcCalcSize(wParam, lParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WM_NCACTIVATE:
|
||||
if (context.window.IsBorderlessWindowEnabled()) {
|
||||
outResult = TRUE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WM_NCHITTEST:
|
||||
if (context.window.IsBorderlessWindowEnabled()) {
|
||||
outResult = HTCLIENT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WM_NCPAINT:
|
||||
case kMessageNcUaDrawCaption:
|
||||
case kMessageNcUaDrawFrame:
|
||||
if (context.window.IsBorderlessWindowEnabled()) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WM_SYSCOMMAND:
|
||||
if (context.window.HandleBorderlessWindowSystemCommand(
|
||||
context.windowHost.GetEditorContext(),
|
||||
context.windowHost.IsGlobalTabDragActive(),
|
||||
wParam)) {
|
||||
outResult = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case WM_SETCURSOR:
|
||||
if (LOWORD(lParam) == HTCLIENT && context.window.ApplyCurrentCursor()) {
|
||||
outResult = TRUE;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowMessageDispatcher::TryDispatch(
|
||||
HWND hwnd,
|
||||
WindowMessageHost& windowHost,
|
||||
@@ -11,8 +379,8 @@ bool WindowMessageDispatcher::TryDispatch(
|
||||
UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
LRESULT& outResult) {
|
||||
const WindowMessageDispatchContext context = {
|
||||
LRESULT& outResult) {
|
||||
const DispatchContext context = {
|
||||
.hwnd = hwnd,
|
||||
.windowHost = windowHost,
|
||||
.window = window,
|
||||
|
||||
Reference in New Issue
Block a user