Skip to content

Commit cd1c631

Browse files
FIX: MouseDownEvent is triggered when changing from Scene view to Game view (ISXB-1671) (#2234)
1 parent 2608cd9 commit cd1c631

File tree

6 files changed

+290
-67
lines changed

6 files changed

+290
-67
lines changed

.github/pull_request_template.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ _Please describe the testing already done by you and what testing you request/re
1111

1212
_Please rate the potential complexity and halo effect from low to high for the reviewers. Note down potential risks to specific Editor branches if any._
1313

14-
- Complexity:
15-
- Halo Effect:
14+
- Complexity:
15+
- Halo Effect:
1616

1717
### Comments to reviewers
1818

@@ -45,7 +45,3 @@ During merge:
4545
- `DOCS: ___`.
4646
- `CHANGE: ___`.
4747
- `RELEASE: 1.1.0-preview.3`.
48-
49-
After merge:
50-
51-
- [ ] Create forward/backward port if needed. If you are blocked from creating a forward port now please add a task to ISX-1444.

Assets/Tests/InputSystem/CoreTests_Actions.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,60 @@ public void Actions_DoNotGetTriggeredByEditorUpdates()
641641
}
642642
}
643643

644+
[Test]
645+
[Category("Actions")]
646+
[Description("Tests that that only the latest event after focus is regained is able to trigger the action." +
647+
"Depends on background behavior. (ISXB-1671)")]
648+
[TestCase(InputSettings.BackgroundBehavior.IgnoreFocus)]
649+
[TestCase(InputSettings.BackgroundBehavior.ResetAndDisableNonBackgroundDevices)]
650+
[TestCase(InputSettings.BackgroundBehavior.ResetAndDisableAllDevices)]
651+
public void Actions_DoNotGetTriggeredByOutOfFocusEventInEditor(InputSettings.BackgroundBehavior backgroundBehavior)
652+
{
653+
InputSystem.settings.backgroundBehavior = backgroundBehavior;
654+
655+
var mouse = InputSystem.AddDevice<Mouse>();
656+
var mousePointAction = new InputAction(binding: "<Mouse>/position", type: InputActionType.PassThrough);
657+
mousePointAction.Enable();
658+
659+
using (var trace = new InputActionTrace(mousePointAction))
660+
{
661+
// Note: We currently test against timestamps otherwise the test fails. But, ideally, we wouldn't need to.
662+
// If we ever reach a point of having all relevant input events in the queue (including focus events) we
663+
// could just rely on order of event. Which means this test work for a fixed timestamp and it should
664+
// changed accordingly.
665+
currentTime += 1.0f;
666+
runtime.PlayerFocusLost();
667+
currentTime += 1.0f;
668+
// Queuing an event like it would be in the editor when the GameView is out of focus.
669+
Set(mouse.position, new Vector2(0.234f, 0.345f) , queueEventOnly: true);
670+
currentTime += 1.0f;
671+
// Gaining focus like it would happen in the editor when the GameView regains focus.
672+
runtime.PlayerFocusGained();
673+
currentTime += 1.0f;
674+
// This emulates a device sync that happens when the player regains focus through an IOCTL command.
675+
// That's why it also has it's time incremented.
676+
Set(mouse.position, new Vector2(1.0f, 2.0f), queueEventOnly: true);
677+
currentTime += 1.0f;
678+
// This update should not trigger any ction as it's an editor update.
679+
InputSystem.Update(InputUpdateType.Editor);
680+
currentTime += 1.0f;
681+
682+
var actions = trace.ToArray();
683+
Assert.That(actions, Has.Length.EqualTo(0));
684+
// This update should trigger an action with regards to the event queued after focus was regained.
685+
// The one queued while out of focus should have been ignored and we should expect only one action triggered.
686+
// Unless background behavior is set to IgnoreFocus in which case both events should trigger the action.
687+
InputSystem.Update(InputUpdateType.Dynamic);
688+
689+
actions = trace.ToArray();
690+
Assert.That(actions, Has.Length.EqualTo(backgroundBehavior == InputSettings.BackgroundBehavior.IgnoreFocus ? 2 : 1));
691+
Assert.That(actions[0].phase, Is.EqualTo(InputActionPhase.Performed));
692+
Vector2Control control = (Vector2Control)actions[0].control;
693+
// Make sure the value is from the event after focus was regained.
694+
Assert.That(control.value, Is.EqualTo(new Vector2(1.0f, 2.0f)).Using(Vector2EqualityComparer.Instance));
695+
}
696+
}
697+
644698
[Test]
645699
[Category("Actions")]
646700
public void Actions_TimeoutsDoNotGetTriggeredInEditorUpdates()

Assets/Tests/InputSystem/Plugins/InputForUITests.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,72 @@ public void ActionWithDifferentExpectedControlType_ShouldGenerateWarning(string
691691
LogAssert.NoUnexpectedReceived();
692692
}
693693

694+
[Test]
695+
[Category("Actions")]
696+
[Description("Tests that that only the latest event after focus is regained is able to trigger the action." +
697+
"Depends on background behavior. " +
698+
"Similar to CoreTests_Actions.Actions_DoNotGetTriggeredByOutOfFocusEventInEditor but with InputForUI nuances.")]
699+
[TestCase(InputSettings.BackgroundBehavior.IgnoreFocus)]
700+
[TestCase(InputSettings.BackgroundBehavior.ResetAndDisableNonBackgroundDevices)]
701+
[TestCase(InputSettings.BackgroundBehavior.ResetAndDisableAllDevices)]
702+
public void UIActions_DoNotGetTriggeredByOutOfFocusEventInEditor(InputSettings.BackgroundBehavior backgroundBehavior)
703+
{
704+
InputSystem.settings.backgroundBehavior = backgroundBehavior;
705+
var mouse = InputSystem.AddDevice<Mouse>();
706+
707+
Vector2 focusPosition = new Vector2(800f, 600f);
708+
Vector2 outOfFocusPosition = new Vector2(100f, 500f);
709+
710+
// Simulate moving the mouse, losing focus, moving out of focus, regaining focus, and moving again to emulate
711+
// a device sync that happens when regaining focus in play mode.
712+
Update();
713+
currentTime += 1.0f;
714+
Set(mouse.position, new Vector2(1.0f, 1.0f), queueEventOnly: true);
715+
currentTime += 1.0f;
716+
Update();
717+
currentTime += 1.0f;
718+
runtime.PlayerFocusLost();
719+
currentTime += 1.0f;
720+
Set(mouse.position, outOfFocusPosition , queueEventOnly: true);
721+
currentTime += 1.0f;
722+
runtime.PlayerFocusGained();
723+
currentTime += 1.0f;
724+
Set(mouse.position, focusPosition, queueEventOnly: true);
725+
currentTime += 1.0f;
726+
727+
// We call specific updates to simulate editor behavior when regaining focus.
728+
InputSystem.Update(InputUpdateType.Editor);
729+
Assert.AreEqual(0, m_InputForUIEvents.Count);
730+
InputSystem.Update();
731+
// Calling the event provider update after we call InputSystem updates so that we trigger InputForUI events
732+
EventProvider.NotifyUpdate();
733+
734+
// Convert the input coordinates to UI panel space. We only assume 1 display for the tests.
735+
var focusPositionInUI = InputSystemProvider.ScreenBottomLeftToPanelPosition(focusPosition, 0);
736+
var outOfFocusPositionInUI = InputSystemProvider.ScreenBottomLeftToPanelPosition(outOfFocusPosition, 0);
737+
738+
739+
// If we don't ignore focus, we only expect one event (the last one after focus is regained).
740+
Assert.AreEqual(backgroundBehavior != InputSettings.BackgroundBehavior.IgnoreFocus ? 1 : 2, m_InputForUIEvents.Count);
741+
742+
// There will be an out of focus event only if we are ignoring focus. Validate its position.
743+
if (backgroundBehavior == InputSettings.BackgroundBehavior.IgnoreFocus)
744+
{
745+
Assert.That(GetNextRecordedUIEvent() is
746+
{
747+
type: Event.Type.PointerEvent,
748+
asPointerEvent: { type: PointerEvent.Type.PointerMoved, eventSource: EventSource.Mouse, position: var outOfFocusVector2 },
749+
} && Mathf.Approximately(outOfFocusVector2.y, outOfFocusPositionInUI.y) && Mathf.Approximately(outOfFocusVector2.x, outOfFocusPositionInUI.x));
750+
}
751+
752+
// Validate that we only we get the event for the position after focus is regained. Make sure its position is correct.
753+
Assert.That(GetNextRecordedUIEvent() is
754+
{
755+
type: Event.Type.PointerEvent,
756+
asPointerEvent: { type: PointerEvent.Type.PointerMoved, eventSource: EventSource.Mouse, position: var focusPositionVector2 },
757+
} && Mathf.Approximately(focusPositionVector2.y, focusPositionInUI.y) && Mathf.Approximately(focusPositionVector2.x, focusPositionInUI.x));
758+
}
759+
694760
#endif // UNITY_EDITOR
695761

696762
[Test]

Packages/com.unity.inputsystem/CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ however, it has to be formatted properly to pass verification tests.
1010

1111
## [Unreleased] - yyyy-mm-dd
1212

13-
14-
13+
### Fixed
14+
- An issue where a UITK MouseEvent was triggered when changing from Scene View to Game View in the Editor has been fixed. [ISXB-1671](https://issuetracker.unity3d.com/product/unity/issues/guid/ISXB-1671)
1515

1616
## [1.16.0] - 2025-11-10
1717

0 commit comments

Comments
 (0)