Merge commit 'de6af361ab15a9fc504518368e5a8fca2db5a065' into mbalfour/gitflow_211102_o3de
This commit is contained in:
@@ -85,6 +85,7 @@ namespace UnitTest
|
||||
|
||||
m_rootWidget = AZStd::make_unique<QWidget>();
|
||||
m_rootWidget->setFixedSize(QSize(100, 100));
|
||||
QApplication::setActiveWindow(m_rootWidget.get());
|
||||
|
||||
m_controllerList = AZStd::make_shared<AzFramework::ViewportControllerList>();
|
||||
m_controllerList->RegisterViewportContext(TestViewportId);
|
||||
@@ -100,6 +101,8 @@ namespace UnitTest
|
||||
m_controllerList.reset();
|
||||
m_rootWidget.reset();
|
||||
|
||||
QApplication::setActiveWindow(nullptr);
|
||||
|
||||
AllocatorsTestFixture::TearDown();
|
||||
}
|
||||
|
||||
@@ -110,7 +113,7 @@ namespace UnitTest
|
||||
|
||||
const AzFramework::ViewportId ViewportManipulatorControllerFixture::TestViewportId = AzFramework::ViewportId(0);
|
||||
|
||||
TEST_F(ViewportManipulatorControllerFixture, An_event_is_not_propagated_to_the_viewport_when_a_manipulator_handles_it_first)
|
||||
TEST_F(ViewportManipulatorControllerFixture, AnEventIsNotPropagatedToTheViewportWhenAManipulatorHandlesItFirst)
|
||||
{
|
||||
// forward input events to our controller list
|
||||
QObject::connect(
|
||||
@@ -151,4 +154,77 @@ namespace UnitTest
|
||||
|
||||
editorInteractionViewportFake.Disconnect();
|
||||
}
|
||||
|
||||
TEST_F(ViewportManipulatorControllerFixture, ChangingFocusDoesNotClearInput)
|
||||
{
|
||||
bool endedEvent = false;
|
||||
// detect input events and ensure that the Alt key press does not end before the end of the test
|
||||
QObject::connect(
|
||||
m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(),
|
||||
[&endedEvent](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event)
|
||||
{
|
||||
if (inputChannel->GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::ModifierAltL &&
|
||||
inputChannel->IsStateEnded())
|
||||
{
|
||||
endedEvent = true;
|
||||
}
|
||||
});
|
||||
|
||||
// given
|
||||
auto* secondaryWidget = new QWidget(m_rootWidget.get());
|
||||
|
||||
m_rootWidget->show();
|
||||
secondaryWidget->show();
|
||||
|
||||
m_rootWidget->setFocus();
|
||||
|
||||
// simulate a key press when root widget has focus
|
||||
QTest::keyPress(m_rootWidget.get(), Qt::Key_Alt, Qt::KeyboardModifier::AltModifier);
|
||||
|
||||
// when
|
||||
// change focus to secondary widget
|
||||
secondaryWidget->setFocus();
|
||||
|
||||
// then
|
||||
// the alt key was not released (cleared)
|
||||
EXPECT_FALSE(endedEvent);
|
||||
}
|
||||
|
||||
// note: Application State Change includes events such as switching to another application or minimizing
|
||||
// the current application
|
||||
TEST_F(ViewportManipulatorControllerFixture, ApplicationStateChangeDoesClearInput)
|
||||
{
|
||||
bool endedEvent = false;
|
||||
// detect input events and ensure that the Alt key press does not end before the end of the test
|
||||
QObject::connect(
|
||||
m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(),
|
||||
[&endedEvent](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event)
|
||||
{
|
||||
if (inputChannel->GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::AlphanumericW &&
|
||||
inputChannel->IsStateEnded())
|
||||
{
|
||||
endedEvent = true;
|
||||
}
|
||||
});
|
||||
|
||||
// given
|
||||
auto* secondaryWidget = new QWidget(m_rootWidget.get());
|
||||
|
||||
m_rootWidget->show();
|
||||
secondaryWidget->show();
|
||||
|
||||
m_rootWidget->setFocus();
|
||||
|
||||
// simulate a key press when root widget has focus
|
||||
QTest::keyPress(m_rootWidget.get(), Qt::Key_W);
|
||||
|
||||
// when
|
||||
// simulate changing the window state
|
||||
QApplicationStateChangeEvent applicationStateChangeEvent(Qt::ApplicationState::ApplicationInactive);
|
||||
QCoreApplication::sendEvent(m_rootWidget.get(), &applicationStateChangeEvent);
|
||||
|
||||
// then
|
||||
// the key was released (cleared)
|
||||
EXPECT_TRUE(endedEvent);
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -210,8 +210,8 @@ namespace AzToolsFramework
|
||||
m_enabled = enabled;
|
||||
if (!enabled)
|
||||
{
|
||||
// Send an internal focus change event to reset our input state to fresh if we're disabled.
|
||||
HandleFocusChange(nullptr);
|
||||
// Clear input channels to reset our input state if we're disabled.
|
||||
ClearInputChannels(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (eventType == QEvent::Type::MouseMove)
|
||||
{
|
||||
// clear override cursor when moving outside of the viewport
|
||||
// Clear override cursor when moving outside of the viewport
|
||||
const auto* mouseEvent = static_cast<const QMouseEvent*>(event);
|
||||
if (m_overrideCursor && !m_sourceWidget->geometry().contains(m_sourceWidget->mapFromGlobal(mouseEvent->globalPos())))
|
||||
{
|
||||
@@ -255,6 +255,13 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
// If the application state changes (e.g. we have alt-tabbed or minimized the
|
||||
// main editor window) then ensure all input channels are cleared
|
||||
if (eventType == QEvent::ApplicationStateChange)
|
||||
{
|
||||
ClearInputChannels(event);
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -264,9 +271,6 @@ namespace AzToolsFramework
|
||||
|
||||
if (eventType == QEvent::FocusIn || eventType == QEvent::FocusOut)
|
||||
{
|
||||
// If our focus changes, go ahead and reset all input devices.
|
||||
HandleFocusChange(event);
|
||||
|
||||
// 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)
|
||||
@@ -451,7 +455,7 @@ namespace AzToolsFramework
|
||||
NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent);
|
||||
}
|
||||
|
||||
void QtEventToAzInputMapper::HandleFocusChange(QEvent* event)
|
||||
void QtEventToAzInputMapper::ClearInputChannels(QEvent* event)
|
||||
{
|
||||
for (auto& channelData : m_channels)
|
||||
{
|
||||
|
||||
@@ -138,8 +138,9 @@ namespace AzToolsFramework
|
||||
void HandleKeyEvent(QKeyEvent* keyEvent);
|
||||
// Handles mouse wheel events.
|
||||
void HandleWheelEvent(QWheelEvent* wheelEvent);
|
||||
// Handles focus change events.
|
||||
void HandleFocusChange(QEvent* event);
|
||||
|
||||
// Clear all input channels (set all channel states to 'ended').
|
||||
void ClearInputChannels(QEvent* event);
|
||||
|
||||
// Populates m_keyMappings.
|
||||
void InitializeKeyMappings();
|
||||
|
||||
Reference in New Issue
Block a user