@@ -1460,33 +1460,132 @@ public IEnumerator UI_CanDriveUIFromMultiplePointers(UIPointerBehavior pointerBe
1460
1460
scene . leftChildReceiver . events . Clear ( ) ;
1461
1461
scene . rightChildReceiver . events . Clear ( ) ;
1462
1462
1463
- // Test if creating Pointer events from different devices at the same time results in only one event
1464
- BeginTouch ( 0 , firstPosition , screen : touch1 , queueEventOnly : true ) ;
1463
+ // End previous touches that started so that we can do a cleanup from the last test.
1464
+ EndTouch ( 1 , secondPosition , screen : touch1 ) ;
1465
+ yield return null ;
1466
+ EndTouch ( 1 , firstPosition , screen : touch2 ) ;
1467
+ yield return null ;
1468
+ // Set a mouse position without any clicks to "emulate" a real movement before a button press.
1469
+ Set ( mouse1 . position , secondPosition + new Vector2 ( - 10 , 0 ) ) ;
1470
+ yield return null ;
1471
+
1472
+ scene . leftChildReceiver . events . Clear ( ) ;
1473
+ scene . rightChildReceiver . events . Clear ( ) ;
1474
+
1475
+ // Test a press and release from both a Mouse and Touchscreen at the same time
1476
+ // This is to simulate some platforms that always send Mouse/Pen and Touches (e.g. Android).
1477
+ // Also, this mostly assets the expected behavior for the options SingleMouseOrPenButMultiTouchAndTrack.
1478
+ var touchId = 2 ;
1479
+ BeginTouch ( touchId , secondPosition , screen : touch1 , queueEventOnly : true ) ;
1480
+ Set ( mouse1 . position , secondPosition , queueEventOnly : true ) ;
1465
1481
Press ( mouse1 . leftButton ) ;
1482
+
1466
1483
yield return null ;
1467
- EndTouch ( 0 , firstPosition , screen : touch1 , queueEventOnly : true ) ;
1484
+
1485
+ EndTouch ( touchId , secondPosition , screen : touch1 , queueEventOnly : true ) ;
1468
1486
Release ( mouse1 . leftButton ) ;
1469
1487
yield return null ;
1470
1488
1489
+ Func < UICallbackReceiver . Event , bool > eventDeviceCondition = null ;
1490
+ var expectedCount = 0 ;
1471
1491
switch ( pointerBehavior )
1472
1492
{
1493
+ case UIPointerBehavior . SingleMouseOrPenButMultiTouchAndTrack :
1494
+ // Expects only mouse events for PointerClick, PointerDown, and PointerUp
1495
+ eventDeviceCondition = ( e ) => e . pointerData . device == mouse1 ;
1496
+ expectedCount = 1 ;
1497
+ // Make sure that the touch does not generate a UI events.
1498
+ Assert . That ( scene . rightChildReceiver . events , Has . None . Matches ( ( UICallbackReceiver . Event e ) =>
1499
+ e . pointerData != null && e . pointerData . device == touch1 ) ) ;
1500
+ break ;
1501
+
1473
1502
case UIPointerBehavior . SingleUnifiedPointer :
1474
- //// Getting "Drop" event even if using only one type of input device for Press/Release.
1475
- //// E.g. the following test would also produce only a Drop event:
1476
- //// Press(mouse1.leftButton);
1477
- //// yield return null;
1478
- //// Release(mouse1.leftButton);
1479
- //// yield return null;
1503
+ // Expects only single UI events with touch source since they are the first events in the queue
1504
+ eventDeviceCondition = ( e ) => e . pointerData . device == touch1 ;
1505
+ expectedCount = 1 ;
1480
1506
break ;
1481
- case UIPointerBehavior . SingleMouseOrPenButMultiTouchAndTrack :
1507
+
1482
1508
case UIPointerBehavior . AllPointersAsIs :
1483
- // Single pointer click on the left object
1484
- Assert . That ( scene . leftChildReceiver . events ,
1485
- Has . Exactly ( 1 ) . With . Property ( "type" ) . EqualTo ( EventType . PointerClick ) . And
1486
- . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . device == mouse1 ) . And
1487
- . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == firstPosition ) ) ;
1509
+ // Expects both pointer devices to generate PointerClick, PointerDown, and PointerUp events
1510
+ eventDeviceCondition = ( e ) => e . pointerData . device == mouse1 || e . pointerData . device == touch1 ;
1511
+ expectedCount = 2 ;
1488
1512
break ;
1513
+
1514
+ default :
1515
+ throw new ArgumentOutOfRangeException ( nameof ( pointerBehavior ) , pointerBehavior , null ) ;
1489
1516
}
1517
+
1518
+ Assert . That ( scene . rightChildReceiver . events ,
1519
+ Has . Exactly ( expectedCount ) . With . Property ( "type" ) . EqualTo ( EventType . PointerClick ) . And
1520
+ . Matches ( ( UICallbackReceiver . Event e ) => eventDeviceCondition ( e ) ) . And
1521
+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == secondPosition ) ) ;
1522
+ Assert . That ( scene . rightChildReceiver . events ,
1523
+ Has . Exactly ( expectedCount ) . With . Property ( "type" ) . EqualTo ( EventType . PointerDown ) . And
1524
+ . Matches ( ( UICallbackReceiver . Event e ) => eventDeviceCondition ( e ) ) . And
1525
+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == secondPosition ) ) ;
1526
+ Assert . That ( scene . rightChildReceiver . events ,
1527
+ Has . Exactly ( expectedCount ) . With . Property ( "type" ) . EqualTo ( EventType . PointerUp ) . And
1528
+ . Matches ( ( UICallbackReceiver . Event e ) => eventDeviceCondition ( e ) ) . And
1529
+ . Matches ( ( UICallbackReceiver . Event e ) => e . pointerData . position == secondPosition ) ) ;
1530
+ }
1531
+
1532
+ [ UnityTest ]
1533
+ [ Category ( "UI" ) ]
1534
+ [ Description ( "Tests that disabling the UI module during a Button click event works correctly with touch pointers." +
1535
+ "ISXB-687" ) ]
1536
+ public IEnumerator UI_DisablingEventSystemOnClickEventWorksWithTouchPointers ( )
1537
+ {
1538
+ var touch = InputSystem . AddDevice < Touchscreen > ( ) ;
1539
+ var scene = CreateTestUI ( ) ;
1540
+
1541
+ var actions = ScriptableObject . CreateInstance < InputActionAsset > ( ) ;
1542
+ var uiActions = actions . AddActionMap ( "UI" ) ;
1543
+ var pointAction = uiActions . AddAction ( "point" , type : InputActionType . PassThrough ) ;
1544
+ var clickAction = uiActions . AddAction ( "click" , type : InputActionType . PassThrough ) ;
1545
+
1546
+ pointAction . AddBinding ( "<Touchscreen>/touch*/position" ) ;
1547
+ clickAction . AddBinding ( "<Touchscreen>/touch*/press" ) ;
1548
+
1549
+ pointAction . Enable ( ) ;
1550
+ clickAction . Enable ( ) ;
1551
+
1552
+ scene . uiModule . point = InputActionReference . Create ( pointAction ) ;
1553
+ scene . uiModule . pointerBehavior = UIPointerBehavior . SingleMouseOrPenButMultiTouchAndTrack ;
1554
+ scene . uiModule . leftClick = InputActionReference . Create ( clickAction ) ;
1555
+
1556
+ // Turn left object into a button.
1557
+ var button = scene . leftGameObject . AddComponent < MyButton > ( ) ;
1558
+ var clicked = false ;
1559
+
1560
+ // Add a listener to the button to disable the UI module when clicked.
1561
+ // This calls InputSystemUIInputModule.OnDisable() which will reset the pointer data during
1562
+ // InputSystemUIInputModule.Process() and ProcessPointer(). It will allow us to test that removing
1563
+ // a pointer once the UI module is disabled (all pointers are removed) works correctly.
1564
+ button . onClick . AddListener ( ( ) =>
1565
+ {
1566
+ clicked = true ;
1567
+ scene . uiModule . enabled = false ; // Disable the UI module to test pointer reset.
1568
+ } ) ;
1569
+
1570
+ yield return null ;
1571
+
1572
+ var firstPosition = scene . From640x480ToScreen ( 100 , 100 ) ;
1573
+
1574
+ // This will allocate a pointer for the touch and set the first touch position and press
1575
+ BeginTouch ( 1 , firstPosition , screen : touch ) ;
1576
+ yield return null ;
1577
+
1578
+ Assert . That ( clicked , Is . False , "Button was clicked when it should not have been yet." ) ;
1579
+ Assert . That ( scene . uiModule . m_PointerStates . length , Is . EqualTo ( 1 ) ,
1580
+ "A pointer states was not allocated for the touch pointer." ) ;
1581
+
1582
+ // Release the touch to make sure we have a Click event that calls the button listener.
1583
+ EndTouch ( 1 , firstPosition , screen : touch ) ;
1584
+ yield return null ;
1585
+
1586
+ Assert . That ( clicked , Is . True , "Button was not clicked when it should have been." ) ;
1587
+ Assert . That ( scene . uiModule . m_PointerStates . length , Is . EqualTo ( 0 ) ,
1588
+ "Pointer states were not cleared when the UI module was disabled after a click event." ) ;
1490
1589
}
1491
1590
1492
1591
[ UnityTest ]
0 commit comments