updates to improve cursor lock behavior

Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
hultonha
2021-10-15 15:19:38 +01:00
parent 1d6542c274
commit 3d4c060fb5
6 changed files with 52 additions and 37 deletions
@@ -244,6 +244,16 @@ namespace AzToolsFramework
const auto eventType = event->type();
if (eventType == QEvent::Type::MouseMove)
{
const auto* mouseEvent = static_cast<const QMouseEvent*>(event);
if (m_overrideCursor && !m_sourceWidget->geometry().contains(mouseEvent->pos()))
{
qApp->restoreOverrideCursor();
m_overrideCursor = false;
}
}
// Only accept mouse & key release events that originate from an object that is not our target widget,
// as we don't want to erroneously intercept user input meant for another component.
if (object != m_sourceWidget && eventType != QEvent::Type::KeyRelease && eventType != QEvent::Type::MouseButtonRelease)
@@ -256,27 +266,14 @@ namespace AzToolsFramework
// If our focus changes, go ahead and reset all input devices.
HandleFocusChange(event);
if (eventType == QEvent::FocusOut)
{
if (m_capturingCursor)
{
qApp->restoreOverrideCursor();
}
}
// If we focus in on the source widget and the mouse is contained in its
// bounds, refresh the cached cursor position to ensure it is up to date (this
// ensures cursor positions are refreshed correctly with context menu focus changes)
if (eventType == QEvent::FocusIn)
{
const auto globalCursorPosition = QCursor::pos();
if (m_sourceWidget->geometry().contains(globalCursorPosition))
if (m_sourceWidget->geometry().contains(m_sourceWidget->mapFromGlobal(globalCursorPosition)))
{
if (m_capturingCursor)
{
qApp->setOverrideCursor(Qt::ForbiddenCursor);
}
HandleMouseMoveEvent(globalCursorPosition);
}
}
@@ -466,16 +463,26 @@ namespace AzToolsFramework
}
}
void QtEventToAzInputMapper::PushCursor(/*enum*/)
static Qt::CursorShape QtCursorFromAzCursor(const ViewportInteraction::CursorStyleOverride cursorStyleOverride)
{
if (!m_overrideCursor)
switch (cursorStyleOverride)
{
qApp->setOverrideCursor(Qt::ForbiddenCursor);
m_overrideCursor = true;
case ViewportInteraction::CursorStyleOverride::Forbidden:
return Qt::ForbiddenCursor;
default:
return Qt::ArrowCursor;
}
}
void QtEventToAzInputMapper::PopCursor()
void QtEventToAzInputMapper::SetOverrideCursor(ViewportInteraction::CursorStyleOverride cursorStyleOverride)
{
ClearOverrideCursor();
qApp->setOverrideCursor(QtCursorFromAzCursor(cursorStyleOverride));
m_overrideCursor = true;
}
void QtEventToAzInputMapper::ClearOverrideCursor()
{
if (m_overrideCursor)
{
@@ -15,10 +15,11 @@
#include <AzFramework/Input/Channels/InputChannelDeltaWithSharedPosition2D.h>
#include <AzFramework/Input/Channels/InputChannelDigitalWithSharedModifierKeyStates.h>
#include <AzFramework/Input/Channels/InputChannelDigitalWithSharedPosition2D.h>
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
#include <AzFramework/Input/Devices/Mouse/InputDeviceMouse.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <QEvent>
#include <QObject>
#include <QPoint>
@@ -55,8 +56,8 @@ namespace AzToolsFramework
//! like a dolly or rotation, where mouse movement is important but cursor location is not.
void SetCursorCaptureEnabled(bool enabled);
void PushCursor(/*enum*/);
void PopCursor();
void SetOverrideCursor(ViewportInteraction::CursorStyleOverride cursorStyleOverride);
void ClearOverrideCursor();
// QObject overrides...
bool eventFilter(QObject* object, QEvent* event) override;
@@ -167,8 +168,8 @@ namespace AzToolsFramework
bool m_enabled = true;
// Flags whether or not the cursor is being constrained to the source widget (for invisible mouse movement).
bool m_capturingCursor = false;
//
bool m_overrideCursor = true;
// Flags whether the cursor has been overridden.
bool m_overrideCursor = false;
// Our viewport-specific AZ devices. We control their internal input channel states.
AZStd::unique_ptr<EditorQtMouseDevice> m_mouseDevice;
@@ -300,6 +300,12 @@ namespace AzToolsFramework
using EditorViewportInputTimeNowRequestBus = AZ::EBus<EditorViewportInputTimeNowRequests>;
//! The style of cursor override.
enum class CursorStyleOverride
{
Forbidden
};
//! Viewport requests for managing the viewport cursor state.
class ViewportMouseCursorRequests
{
@@ -310,10 +316,10 @@ namespace AzToolsFramework
virtual void EndCursorCapture() = 0;
//! Is the mouse over the viewport.
virtual bool IsMouseOver() const = 0;
//!
virtual void PushOverrideCursor(/*enum*/) {} // make virtual
//!
virtual void PopOverrideCursor() {} // make virtual
//! Set the cursor style override.
virtual void SetOverrideCursor(CursorStyleOverride cursorStyleOverride) = 0;
//! Clear the current cursor style override.
virtual void ClearOverrideCursor() = 0;
protected:
~ViewportMouseCursorRequests() = default;
@@ -187,16 +187,17 @@ namespace AzToolsFramework
}
// Verify if the entity Id corresponds to an entity that is focused; if not, halt selection.
if (!IsSelectableAccordingToFocusMode(entityIdUnderCursor))
if (entityIdUnderCursor.IsValid() && !IsSelectableAccordingToFocusMode(entityIdUnderCursor))
{
ViewportInteraction::ViewportMouseCursorRequestBus::Event(
viewportId, &ViewportInteraction::ViewportMouseCursorRequestBus::Events::PushOverrideCursor);
viewportId, &ViewportInteraction::ViewportMouseCursorRequestBus::Events::SetOverrideCursor,
ViewportInteraction::CursorStyleOverride::Forbidden);
return AZ::EntityId();
}
ViewportInteraction::ViewportMouseCursorRequestBus::Event(
viewportId, &ViewportInteraction::ViewportMouseCursorRequestBus::Events::PopOverrideCursor);
viewportId, &ViewportInteraction::ViewportMouseCursorRequestBus::Events::ClearOverrideCursor);
// Container Entity support - if the entity that is being selected is part of a closed container,
// change the selection to the container instead.
@@ -102,8 +102,8 @@ namespace AtomToolsFramework
void BeginCursorCapture() override;
void EndCursorCapture() override;
bool IsMouseOver() const override;
void PushOverrideCursor(/*enum*/) override;
void PopOverrideCursor() override;
void SetOverrideCursor(AzToolsFramework::ViewportInteraction::CursorStyleOverride cursorStyleOverride) override;
void ClearOverrideCursor() override;
// AzFramework::WindowRequestBus::Handler overrides ...
void SetWindowTitle(const AZStd::string& title) override;
@@ -367,14 +367,14 @@ namespace AtomToolsFramework
m_inputChannelMapper->SetCursorCaptureEnabled(false);
}
void RenderViewportWidget::PushOverrideCursor(/*enum*/)
void RenderViewportWidget::SetOverrideCursor(AzToolsFramework::ViewportInteraction::CursorStyleOverride cursorStyleOverride)
{
m_inputChannelMapper->PushCursor();
m_inputChannelMapper->SetOverrideCursor(cursorStyleOverride);
}
void RenderViewportWidget::PopOverrideCursor()
void RenderViewportWidget::ClearOverrideCursor()
{
m_inputChannelMapper->PopCursor();
m_inputChannelMapper->ClearOverrideCursor();
}
void RenderViewportWidget::SetWindowTitle(const AZStd::string& title)