Fix borderless host resize presentation ordering
This commit is contained in:
@@ -527,12 +527,11 @@ void Application::RenderFrame() {
|
||||
return;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
GetClientRect(m_hwnd, &clientRect);
|
||||
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));
|
||||
UINT pixelWidth = 0u;
|
||||
UINT pixelHeight = 0u;
|
||||
if (!ResolveRenderClientPixelSize(pixelWidth, pixelHeight)) {
|
||||
return;
|
||||
}
|
||||
const float width = PixelsToDips(static_cast<float>(pixelWidth));
|
||||
const float height = PixelsToDips(static_cast<float>(pixelHeight));
|
||||
|
||||
@@ -674,6 +673,14 @@ bool Application::IsPointerInsideClientArea() const {
|
||||
}
|
||||
|
||||
LPCWSTR Application::ResolveCurrentCursorResource() const {
|
||||
const Host::BorderlessWindowResizeEdge borderlessResizeEdge =
|
||||
m_hostRuntime.IsBorderlessResizeActive()
|
||||
? m_hostRuntime.GetBorderlessResizeEdge()
|
||||
: m_hostRuntime.GetHoveredBorderlessResizeEdge();
|
||||
if (borderlessResizeEdge != Host::BorderlessWindowResizeEdge::None) {
|
||||
return Host::ResolveBorderlessWindowResizeCursor(borderlessResizeEdge);
|
||||
}
|
||||
|
||||
switch (m_editorWorkspace.GetHostedContentCursorKind()) {
|
||||
case App::ProductProjectPanel::CursorKind::ResizeEW:
|
||||
return IDC_SIZEWE;
|
||||
@@ -707,6 +714,147 @@ bool Application::ApplyCurrentCursor() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
Host::BorderlessWindowResizeEdge Application::HitTestBorderlessWindowResizeEdge(LPARAM lParam) const {
|
||||
if (!IsBorderlessWindowEnabled() || m_hwnd == nullptr || IsZoomed(m_hwnd)) {
|
||||
return Host::BorderlessWindowResizeEdge::None;
|
||||
}
|
||||
|
||||
RECT clientRect = {};
|
||||
if (!GetClientRect(m_hwnd, &clientRect)) {
|
||||
return Host::BorderlessWindowResizeEdge::None;
|
||||
}
|
||||
|
||||
const float clientWidthDips =
|
||||
PixelsToDips(static_cast<float>((std::max)(clientRect.right - clientRect.left, 1L)));
|
||||
const float clientHeightDips =
|
||||
PixelsToDips(static_cast<float>((std::max)(clientRect.bottom - clientRect.top, 1L)));
|
||||
return Host::HitTestBorderlessWindowResizeEdge(
|
||||
::XCEngine::UI::UIRect(0.0f, 0.0f, clientWidthDips, clientHeightDips),
|
||||
ConvertClientPixelsToDips(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
|
||||
}
|
||||
|
||||
bool Application::UpdateBorderlessWindowResizeHover(LPARAM lParam) {
|
||||
const Host::BorderlessWindowResizeEdge hoveredEdge = HitTestBorderlessWindowResizeEdge(lParam);
|
||||
if (m_hostRuntime.GetHoveredBorderlessResizeEdge() == hoveredEdge) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hostRuntime.SetHoveredBorderlessResizeEdge(hoveredEdge);
|
||||
ApplyBorderlessWindowResizeCursorHoverPriority();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::HandleBorderlessWindowResizeButtonDown(LPARAM lParam) {
|
||||
const Host::BorderlessWindowResizeEdge edge = HitTestBorderlessWindowResizeEdge(lParam);
|
||||
if (edge == Host::BorderlessWindowResizeEdge::None || m_hwnd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
POINT screenPoint = {};
|
||||
if (!GetCursorPos(&screenPoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT windowRect = {};
|
||||
if (!GetWindowRect(m_hwnd, &windowRect)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hostRuntime.BeginBorderlessResize(edge, screenPoint, windowRect);
|
||||
SetCapture(m_hwnd);
|
||||
InvalidateHostWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::HandleBorderlessWindowResizeButtonUp() {
|
||||
if (!m_hostRuntime.IsBorderlessResizeActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_hostRuntime.EndBorderlessResize();
|
||||
if (GetCapture() == m_hwnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
InvalidateHostWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::HandleBorderlessWindowResizePointerMove() {
|
||||
if (!m_hostRuntime.IsBorderlessResizeActive() || m_hwnd == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
POINT currentScreenPoint = {};
|
||||
if (!GetCursorPos(¤tScreenPoint)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT targetRect = Host::ComputeBorderlessWindowResizeRect(
|
||||
m_hostRuntime.GetBorderlessResizeInitialWindowRect(),
|
||||
m_hostRuntime.GetBorderlessResizeInitialScreenPoint(),
|
||||
currentScreenPoint,
|
||||
m_hostRuntime.GetBorderlessResizeEdge(),
|
||||
640,
|
||||
360);
|
||||
const int width = targetRect.right - targetRect.left;
|
||||
const int height = targetRect.bottom - targetRect.top;
|
||||
if (width <= 0 || height <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
m_hostRuntime.SetPredictedClientPixelSize(
|
||||
static_cast<UINT>(width),
|
||||
static_cast<UINT>(height));
|
||||
ApplyWindowResize(
|
||||
static_cast<UINT>(width),
|
||||
static_cast<UINT>(height));
|
||||
RenderFrame();
|
||||
|
||||
SetWindowPos(
|
||||
m_hwnd,
|
||||
nullptr,
|
||||
targetRect.left,
|
||||
targetRect.top,
|
||||
width,
|
||||
height,
|
||||
SWP_NOZORDER | SWP_NOACTIVATE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::ClearBorderlessWindowResizeState() {
|
||||
if (m_hostRuntime.IsBorderlessResizeActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_hostRuntime.GetHoveredBorderlessResizeEdge() == Host::BorderlessWindowResizeEdge::None) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_hostRuntime.SetHoveredBorderlessResizeEdge(Host::BorderlessWindowResizeEdge::None);
|
||||
InvalidateHostWindow();
|
||||
}
|
||||
|
||||
void Application::ForceClearBorderlessWindowResizeState() {
|
||||
if (m_hostRuntime.GetHoveredBorderlessResizeEdge() == Host::BorderlessWindowResizeEdge::None &&
|
||||
!m_hostRuntime.IsBorderlessResizeActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_hostRuntime.SetHoveredBorderlessResizeEdge(Host::BorderlessWindowResizeEdge::None);
|
||||
m_hostRuntime.EndBorderlessResize();
|
||||
if (GetCapture() == m_hwnd) {
|
||||
ReleaseCapture();
|
||||
}
|
||||
InvalidateHostWindow();
|
||||
}
|
||||
|
||||
void Application::ApplyBorderlessWindowResizeCursorHoverPriority() {
|
||||
if (m_hostRuntime.GetHoveredBorderlessResizeEdge() != Host::BorderlessWindowResizeEdge::None ||
|
||||
m_hostRuntime.IsBorderlessResizeActive()) {
|
||||
m_borderlessWindowChromeState.hoveredTarget = Host::BorderlessWindowChromeHitTarget::None;
|
||||
}
|
||||
}
|
||||
|
||||
Host::BorderlessWindowChromeLayout Application::ResolveBorderlessWindowChromeLayout(
|
||||
float clientWidthDips) const {
|
||||
const auto& menuBarMetrics = ResolveUIEditorMenuBarMetrics();
|
||||
@@ -748,6 +896,14 @@ Host::BorderlessWindowChromeHitTarget Application::HitTestBorderlessWindowChrome
|
||||
}
|
||||
|
||||
bool Application::UpdateBorderlessWindowChromeHover(LPARAM lParam) {
|
||||
if (m_hostRuntime.GetHoveredBorderlessResizeEdge() != Host::BorderlessWindowResizeEdge::None ||
|
||||
m_hostRuntime.IsBorderlessResizeActive()) {
|
||||
const bool changed =
|
||||
m_borderlessWindowChromeState.hoveredTarget != Host::BorderlessWindowChromeHitTarget::None;
|
||||
m_borderlessWindowChromeState.hoveredTarget = Host::BorderlessWindowChromeHitTarget::None;
|
||||
return changed;
|
||||
}
|
||||
|
||||
const Host::BorderlessWindowChromeHitTarget hitTarget = HitTestBorderlessWindowChrome(lParam);
|
||||
const Host::BorderlessWindowChromeHitTarget buttonTarget =
|
||||
hitTarget == Host::BorderlessWindowChromeHitTarget::MinimizeButton ||
|
||||
@@ -764,6 +920,11 @@ bool Application::UpdateBorderlessWindowChromeHover(LPARAM lParam) {
|
||||
}
|
||||
|
||||
bool Application::HandleBorderlessWindowChromeButtonDown(LPARAM lParam) {
|
||||
if (m_hostRuntime.GetHoveredBorderlessResizeEdge() != Host::BorderlessWindowResizeEdge::None ||
|
||||
m_hostRuntime.IsBorderlessResizeActive()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Host::BorderlessWindowChromeHitTarget hitTarget = HitTestBorderlessWindowChrome(lParam);
|
||||
switch (hitTarget) {
|
||||
case Host::BorderlessWindowChromeHitTarget::MinimizeButton:
|
||||
@@ -929,6 +1090,7 @@ std::string Application::DescribeInputEvents(
|
||||
}
|
||||
|
||||
void Application::OnResize(UINT width, UINT height) {
|
||||
m_hostRuntime.ClearPredictedClientPixelSize();
|
||||
ApplyWindowResize(width, height);
|
||||
}
|
||||
|
||||
@@ -938,6 +1100,7 @@ void Application::OnEnterSizeMove() {
|
||||
|
||||
void Application::OnExitSizeMove() {
|
||||
m_hostRuntime.EndInteractiveResize();
|
||||
m_hostRuntime.ClearPredictedClientPixelSize();
|
||||
UINT width = 0u;
|
||||
UINT height = 0u;
|
||||
if (QueryCurrentClientPixelSize(width, height)) {
|
||||
@@ -989,6 +1152,14 @@ bool Application::QueryCurrentClientPixelSize(UINT& outWidth, UINT& outHeight) c
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::ResolveRenderClientPixelSize(UINT& outWidth, UINT& outHeight) const {
|
||||
if (m_hostRuntime.TryGetPredictedClientPixelSize(outWidth, outHeight)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return QueryCurrentClientPixelSize(outWidth, outHeight);
|
||||
}
|
||||
|
||||
void Application::OnDpiChanged(UINT dpi, const RECT& suggestedRect) {
|
||||
m_hostRuntime.SetWindowDpi(dpi == 0u ? kDefaultDpi : dpi);
|
||||
m_renderer.SetDpiScale(GetDpiScale());
|
||||
@@ -1156,9 +1327,17 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
switch (message) {
|
||||
case WM_MOUSEMOVE:
|
||||
if (application != nullptr) {
|
||||
if (application->HandleBorderlessWindowResizePointerMove()) {
|
||||
return 0;
|
||||
}
|
||||
const bool resizeHoverChanged =
|
||||
application->UpdateBorderlessWindowResizeHover(lParam);
|
||||
if (application->UpdateBorderlessWindowChromeHover(lParam)) {
|
||||
application->InvalidateHostWindow();
|
||||
}
|
||||
if (resizeHoverChanged) {
|
||||
application->InvalidateHostWindow();
|
||||
}
|
||||
if (!application->m_trackingMouseLeave) {
|
||||
TRACKMOUSEEVENT trackMouseEvent = {};
|
||||
trackMouseEvent.cbSize = sizeof(trackMouseEvent);
|
||||
@@ -1168,6 +1347,10 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
application->m_trackingMouseLeave = true;
|
||||
}
|
||||
}
|
||||
if (application->m_hostRuntime.GetHoveredBorderlessResizeEdge() !=
|
||||
Host::BorderlessWindowResizeEdge::None) {
|
||||
return 0;
|
||||
}
|
||||
const Host::BorderlessWindowChromeHitTarget chromeHitTarget =
|
||||
application->HitTestBorderlessWindowChrome(lParam);
|
||||
if (chromeHitTarget == Host::BorderlessWindowChromeHitTarget::MinimizeButton ||
|
||||
@@ -1186,6 +1369,7 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
case WM_MOUSELEAVE:
|
||||
if (application != nullptr) {
|
||||
application->m_trackingMouseLeave = false;
|
||||
application->ClearBorderlessWindowResizeState();
|
||||
application->ClearBorderlessWindowChromeState();
|
||||
application->QueuePointerLeaveEvent();
|
||||
return 0;
|
||||
@@ -1193,6 +1377,9 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
break;
|
||||
case WM_LBUTTONDOWN:
|
||||
if (application != nullptr) {
|
||||
if (application->HandleBorderlessWindowResizeButtonDown(lParam)) {
|
||||
return 0;
|
||||
}
|
||||
if (application->HandleBorderlessWindowChromeButtonDown(lParam)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1207,6 +1394,9 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
break;
|
||||
case WM_LBUTTONUP:
|
||||
if (application != nullptr) {
|
||||
if (application->HandleBorderlessWindowResizeButtonUp()) {
|
||||
return 0;
|
||||
}
|
||||
if (application->HandleBorderlessWindowChromeButtonUp(lParam)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -1249,11 +1439,13 @@ LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT message, WPARAM wParam, LP
|
||||
reinterpret_cast<HWND>(lParam) != hwnd &&
|
||||
application->HasInteractiveCaptureState()) {
|
||||
application->QueueWindowFocusEvent(UIInputEventType::FocusLost);
|
||||
application->ForceClearBorderlessWindowResizeState();
|
||||
application->ClearBorderlessWindowChromeState();
|
||||
return 0;
|
||||
}
|
||||
if (application != nullptr &&
|
||||
reinterpret_cast<HWND>(lParam) != hwnd) {
|
||||
application->ForceClearBorderlessWindowResizeState();
|
||||
application->ClearBorderlessWindowChromeState();
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user