Files
XCEngine/new_editor/app/Platform/Win32/EditorWindowInput.cpp

239 lines
7.1 KiB
C++

#include "Platform/Win32/EditorWindow.h"
#include "Platform/Win32/EditorWindowChromeController.h"
#include "Platform/Win32/EditorWindowInputController.h"
#include "Platform/Win32/EditorWindowInternalState.h"
#include "Platform/Win32/EditorWindowRuntimeController.h"
#include <XCEngine/UI/Types.h>
#include <XCEditor/Shell/UIEditorShellCapturePolicy.h>
#include <windowsx.h>
namespace XCEngine::UI::Editor::App {
using ::XCEngine::UI::UIInputEvent;
using ::XCEngine::UI::UIInputEventType;
using ::XCEngine::UI::UIPointerButton;
namespace {
bool IsScreenPointOverWindow(HWND hwnd, const POINT& screenPoint) {
if (hwnd == nullptr || !IsWindow(hwnd)) {
return false;
}
const HWND hitWindow = WindowFromPoint(screenPoint);
if (hitWindow == nullptr || GetAncestor(hitWindow, GA_ROOT) != hwnd) {
return false;
}
RECT windowRect = {};
if (!GetWindowRect(hwnd, &windowRect)) {
return false;
}
return screenPoint.x >= windowRect.left && screenPoint.x < windowRect.right &&
screenPoint.y >= windowRect.top && screenPoint.y < windowRect.bottom;
}
} // namespace
bool EditorWindow::ApplyCurrentCursor() const {
if (!HasInteractiveCaptureState() && !IsPointerInsideClientArea()) {
return false;
}
const HCURSOR cursor = LoadCursorW(nullptr, ResolveCurrentCursorResource());
if (cursor == nullptr) {
return false;
}
SetCursor(cursor);
return true;
}
bool EditorWindow::HasInteractiveCaptureState() const {
return m_runtime->GetShellRuntime().HasInteractiveCapture() ||
m_chromeController->IsBorderlessWindowDragRestoreArmed() ||
m_chromeController->IsBorderlessResizeActive() ||
m_inputController->HasPointerCaptureOwner();
}
EditorWindowPointerCaptureOwner EditorWindow::GetPointerCaptureOwner() const {
return m_inputController->GetPointerCaptureOwner();
}
bool EditorWindow::OwnsPointerCapture(EditorWindowPointerCaptureOwner owner) const {
return m_inputController->OwnsPointerCapture(owner);
}
void EditorWindow::AcquirePointerCapture(EditorWindowPointerCaptureOwner owner) {
m_inputController->AcquirePointerCapture(m_state->window.hwnd, owner);
}
void EditorWindow::ReleasePointerCapture(EditorWindowPointerCaptureOwner owner) {
m_inputController->ReleasePointerCapture(m_state->window.hwnd, owner);
}
void EditorWindow::ForceReleasePointerCapture() {
m_inputController->ForceReleasePointerCapture(m_state->window.hwnd);
}
void EditorWindow::ClearPointerCaptureOwner() {
m_inputController->ClearPointerCaptureOwner();
}
void EditorWindow::TryStartImmediateShellPointerCapture(LPARAM lParam) {
if (m_state->window.hwnd == nullptr ||
!IsWindow(m_state->window.hwnd) ||
GetCapture() == m_state->window.hwnd) {
return;
}
const ::XCEngine::UI::UIPoint clientPoint = ConvertClientPixelsToDips(
GET_X_LPARAM(lParam),
GET_Y_LPARAM(lParam));
if (!ShouldStartImmediateUIEditorShellPointerCapture(
m_runtime->GetShellFrame(),
clientPoint)) {
return;
}
AcquirePointerCapture(EditorWindowPointerCaptureOwner::Shell);
}
void EditorWindow::QueuePointerEvent(
UIInputEventType type,
UIPointerButton button,
WPARAM wParam,
LPARAM lParam) {
UIInputEvent event = {};
m_inputController->QueuePointerEvent(
type,
button,
ConvertClientPixelsToDips(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)),
wParam);
}
void EditorWindow::QueueSyntheticPointerStateSyncEvent(
const ::XCEngine::UI::UIInputModifiers& modifiers) {
if (m_state->window.hwnd == nullptr || !IsWindow(m_state->window.hwnd)) {
return;
}
POINT screenPoint = {};
if (!GetCursorPos(&screenPoint)) {
return;
}
if (!ScreenToClient(m_state->window.hwnd, &screenPoint)) {
return;
}
m_inputController->QueueSyntheticPointerStateSyncEvent(
ConvertClientPixelsToDips(screenPoint.x, screenPoint.y),
modifiers);
}
void EditorWindow::QueuePointerLeaveEvent() {
::XCEngine::UI::UIPoint position = {};
if (m_state->window.hwnd != nullptr) {
POINT clientPoint = {};
GetCursorPos(&clientPoint);
ScreenToClient(m_state->window.hwnd, &clientPoint);
position = ConvertClientPixelsToDips(clientPoint.x, clientPoint.y);
}
m_inputController->QueuePointerLeaveEvent(position);
}
void EditorWindow::QueuePointerWheelEvent(short wheelDelta, WPARAM wParam, LPARAM lParam) {
if (m_state->window.hwnd == nullptr) {
return;
}
POINT screenPoint = {
GET_X_LPARAM(lParam),
GET_Y_LPARAM(lParam)
};
ScreenToClient(m_state->window.hwnd, &screenPoint);
m_inputController->QueuePointerWheelEvent(
ConvertClientPixelsToDips(screenPoint.x, screenPoint.y),
wheelDelta,
wParam);
}
void EditorWindow::QueueKeyEvent(UIInputEventType type, WPARAM wParam, LPARAM lParam) {
m_inputController->QueueKeyEvent(type, wParam, lParam);
}
void EditorWindow::QueueCharacterEvent(WPARAM wParam, LPARAM) {
m_inputController->QueueCharacterEvent(wParam);
}
void EditorWindow::QueueWindowFocusEvent(UIInputEventType type) {
m_inputController->QueueWindowFocusEvent(type);
}
void EditorWindow::SyncInputModifiersFromSystemState() {
m_inputController->SyncInputModifiersFromSystemState();
}
void EditorWindow::ResetInputModifiers() {
m_inputController->ResetInputModifiers();
}
void EditorWindow::RequestManualScreenshot() {
m_runtime->RequestManualScreenshot("manual_f12");
}
bool EditorWindow::IsPointerInsideClientArea() const {
if (m_state->window.hwnd == nullptr || !IsWindow(m_state->window.hwnd)) {
return false;
}
POINT screenPoint = {};
if (!GetCursorPos(&screenPoint)) {
return false;
}
if (!IsScreenPointOverWindow(m_state->window.hwnd, screenPoint)) {
return false;
}
const LPARAM pointParam = MAKELPARAM(
static_cast<SHORT>(screenPoint.x),
static_cast<SHORT>(screenPoint.y));
return SendMessageW(m_state->window.hwnd, WM_NCHITTEST, 0, pointParam) == HTCLIENT;
}
LPCWSTR EditorWindow::ResolveCurrentCursorResource() const {
const Host::BorderlessWindowResizeEdge borderlessResizeEdge =
m_chromeController->IsBorderlessResizeActive()
? m_chromeController->GetBorderlessResizeEdge()
: m_chromeController->GetHoveredBorderlessResizeEdge();
if (borderlessResizeEdge != Host::BorderlessWindowResizeEdge::None) {
return Host::ResolveBorderlessWindowResizeCursor(borderlessResizeEdge);
}
switch (m_runtime->GetShellRuntime().GetHostedContentCursorKind()) {
case ProjectPanel::CursorKind::ResizeEW:
return IDC_SIZEWE;
case ProjectPanel::CursorKind::Arrow:
default:
break;
}
switch (m_runtime->GetShellRuntime().GetDockCursorKind()) {
case Widgets::UIEditorDockHostCursorKind::ResizeEW:
return IDC_SIZEWE;
case Widgets::UIEditorDockHostCursorKind::ResizeNS:
return IDC_SIZENS;
case Widgets::UIEditorDockHostCursorKind::Arrow:
default:
return IDC_ARROW;
}
}
} // namespace XCEngine::UI::Editor::App