TestTreeManager.cpp (22053B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "APZCTreeManagerTester.h" 8 #include "APZTestCommon.h" 9 #include "InputUtils.h" 10 #include "Units.h" 11 #include "mozilla/BasicEvents.h" 12 #include "mozilla/StaticPrefs_apz.h" 13 14 class APZCTreeManagerGenericTester : public APZCTreeManagerTester { 15 protected: 16 void CreateSimpleScrollingLayer() { 17 const char* treeShape = "x"; 18 LayerIntRect layerVisibleRect[] = { 19 LayerIntRect(0, 0, 200, 200), 20 }; 21 CreateScrollData(treeShape, layerVisibleRect); 22 SetScrollableFrameMetrics(layers[0], ScrollableLayerGuid::START_SCROLL_ID, 23 CSSRect(0, 0, 500, 500)); 24 } 25 26 void CreateSimpleMultiLayerTree() { 27 const char* treeShape = "x(xx)"; 28 // LayerID 0 12 29 LayerIntRect layerVisibleRect[] = { 30 LayerIntRect(0, 0, 100, 100), 31 LayerIntRect(0, 0, 100, 50), 32 LayerIntRect(0, 50, 100, 50), 33 }; 34 CreateScrollData(treeShape, layerVisibleRect); 35 } 36 37 void CreatePotentiallyLeakingTree() { 38 const char* treeShape = "x(x(x(x))x(x(x)))"; 39 // LayerID 0 1 2 3 4 5 6 40 CreateScrollData(treeShape); 41 SetScrollableFrameMetrics(layers[0], ScrollableLayerGuid::START_SCROLL_ID); 42 SetScrollableFrameMetrics(layers[2], 43 ScrollableLayerGuid::START_SCROLL_ID + 1); 44 SetScrollableFrameMetrics(layers[5], 45 ScrollableLayerGuid::START_SCROLL_ID + 1); 46 SetScrollableFrameMetrics(layers[3], 47 ScrollableLayerGuid::START_SCROLL_ID + 2); 48 SetScrollableFrameMetrics(layers[6], 49 ScrollableLayerGuid::START_SCROLL_ID + 3); 50 } 51 52 void CreateTwoLayerTree(int32_t aRootContentLayerIndex) { 53 const char* treeShape = "x(x)"; 54 // LayerID 0 1 55 LayerIntRect layerVisibleRect[] = { 56 LayerIntRect(0, 0, 100, 100), 57 LayerIntRect(0, 0, 100, 100), 58 }; 59 CreateScrollData(treeShape, layerVisibleRect); 60 SetScrollableFrameMetrics(layers[0], ScrollableLayerGuid::START_SCROLL_ID); 61 SetScrollableFrameMetrics(layers[1], 62 ScrollableLayerGuid::START_SCROLL_ID + 1); 63 SetScrollHandoff(layers[1], layers[0]); 64 65 // Make layers[aRootContentLayerIndex] the root content 66 ModifyFrameMetrics(layers[aRootContentLayerIndex], 67 [](ScrollMetadata& sm, FrameMetrics& fm) { 68 fm.SetIsRootContent(true); 69 }); 70 } 71 }; 72 73 TEST_F(APZCTreeManagerGenericTester, ScrollablePaintedLayers) { 74 CreateSimpleMultiLayerTree(); 75 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 76 77 // both layers have the same scrollId 78 SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID); 79 SetScrollableFrameMetrics(layers[2], ScrollableLayerGuid::START_SCROLL_ID); 80 UpdateHitTestingTree(); 81 82 TestAsyncPanZoomController* nullAPZC = nullptr; 83 // so they should have the same APZC 84 EXPECT_FALSE(HasScrollableFrameMetrics(layers[0])); 85 EXPECT_NE(nullAPZC, ApzcOf(layers[1])); 86 EXPECT_NE(nullAPZC, ApzcOf(layers[2])); 87 EXPECT_EQ(ApzcOf(layers[1]), ApzcOf(layers[2])); 88 } 89 90 TEST_F(APZCTreeManagerGenericTester, Bug1068268) { 91 CreatePotentiallyLeakingTree(); 92 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 93 94 UpdateHitTestingTree(); 95 RefPtr<HitTestingTreeNode> root = manager->GetRootNode(); 96 RefPtr<HitTestingTreeNode> node2 = root->GetFirstChild()->GetFirstChild(); 97 RefPtr<HitTestingTreeNode> node5 = root->GetLastChild()->GetLastChild(); 98 99 EXPECT_EQ(ApzcOf(layers[2]), node5->GetApzc()); 100 EXPECT_EQ(ApzcOf(layers[2]), node2->GetApzc()); 101 EXPECT_EQ(ApzcOf(layers[0]), ApzcOf(layers[2])->GetParent()); 102 EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[5])); 103 104 EXPECT_EQ(node2->GetFirstChild(), node2->GetLastChild()); 105 EXPECT_EQ(ApzcOf(layers[3]), node2->GetLastChild()->GetApzc()); 106 EXPECT_EQ(node5->GetFirstChild(), node5->GetLastChild()); 107 EXPECT_EQ(ApzcOf(layers[6]), node5->GetLastChild()->GetApzc()); 108 EXPECT_EQ(ApzcOf(layers[2]), ApzcOf(layers[3])->GetParent()); 109 EXPECT_EQ(ApzcOf(layers[5]), ApzcOf(layers[6])->GetParent()); 110 } 111 112 class APZCTreeManagerGenericTesterMock : public APZCTreeManagerGenericTester { 113 public: 114 APZCTreeManagerGenericTesterMock() { CreateMockHitTester(); } 115 }; 116 117 TEST_F(APZCTreeManagerGenericTesterMock, Bug1194876) { 118 // Create a layer tree with parent and child scrollable layers, with the 119 // child being the root content. 120 CreateTwoLayerTree(1); 121 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 122 UpdateHitTestingTree(); 123 124 uint64_t blockId; 125 nsTArray<ScrollableLayerGuid> targets; 126 127 // First touch goes down, APZCTM will hit layers[1] because it is on top of 128 // layers[0], but we tell it the real target APZC is layers[0]. 129 MultiTouchInput mti; 130 mti = CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time()); 131 mti.mTouches.AppendElement( 132 SingleTouchData(0, ScreenIntPoint(25, 50), ScreenSize(0, 0), 0, 0)); 133 QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1, 134 {CompositorHitTestFlags::eVisibleToHitTest, 135 CompositorHitTestFlags::eIrregularArea}); 136 blockId = manager->ReceiveInputEvent(mti).mInputBlockId; 137 manager->ContentReceivedInputBlock(blockId, false); 138 targets.AppendElement(ApzcOf(layers[0])->GetGuid()); 139 manager->SetTargetAPZC(blockId, targets); 140 141 // Around here, the above touch will get processed by ApzcOf(layers[0]) 142 143 // Second touch goes down (first touch remains down), APZCTM will again hit 144 // layers[1]. Again we tell it both touches landed on layers[0], but because 145 // layers[1] is the RCD layer, it will end up being the multitouch target. 146 mti.mTouches.AppendElement( 147 SingleTouchData(1, ScreenIntPoint(75, 50), ScreenSize(0, 0), 0, 0)); 148 // Each touch will get hit-tested, so queue two hit-test results. 149 QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1, 150 {CompositorHitTestFlags::eVisibleToHitTest, 151 CompositorHitTestFlags::eIrregularArea}); 152 QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1, 153 {CompositorHitTestFlags::eVisibleToHitTest, 154 CompositorHitTestFlags::eIrregularArea}); 155 blockId = manager->ReceiveInputEvent(mti).mInputBlockId; 156 manager->ContentReceivedInputBlock(blockId, false); 157 targets.AppendElement(ApzcOf(layers[0])->GetGuid()); 158 manager->SetTargetAPZC(blockId, targets); 159 160 // Around here, the above multi-touch will get processed by ApzcOf(layers[1]). 161 // We want to ensure that ApzcOf(layers[0]) has had its state cleared, because 162 // otherwise it will do things like dispatch spurious long-tap events. 163 164 EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _, _)).Times(0); 165 } 166 167 TEST_F(APZCTreeManagerGenericTesterMock, TargetChangesMidGesture_Bug1570559) { 168 // Create a layer tree with parent and child scrollable layers, with the 169 // parent being the root content. 170 CreateTwoLayerTree(0); 171 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 172 UpdateHitTestingTree(); 173 174 uint64_t blockId; 175 nsTArray<ScrollableLayerGuid> targets; 176 177 // First touch goes down. APZCTM hits the child layer because it is on top 178 // (and we confirm this target), but do not prevent-default the event, causing 179 // the child APZC's gesture detector to start a long-tap timeout task. 180 MultiTouchInput mti = 181 CreateMultiTouchInput(MultiTouchInput::MULTITOUCH_START, mcc->Time()); 182 mti.mTouches.AppendElement( 183 SingleTouchData(0, ScreenIntPoint(25, 50), ScreenSize(0, 0), 0, 0)); 184 QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1, 185 {CompositorHitTestFlags::eVisibleToHitTest, 186 CompositorHitTestFlags::eIrregularArea}); 187 blockId = manager->ReceiveInputEvent(mti).mInputBlockId; 188 manager->ContentReceivedInputBlock(blockId, /* default prevented = */ false); 189 targets.AppendElement(ApzcOf(layers[1])->GetGuid()); 190 manager->SetTargetAPZC(blockId, targets); 191 192 // Second touch goes down (first touch remains down). APZCTM again hits the 193 // child and we confirm this, but multi-touch events are routed to the root 194 // content APZC which is the parent. This event is prevent-defaulted, so we 195 // clear the parent's gesture state. The bug is that we fail to clear the 196 // child's gesture state. 197 mti.mTouches.AppendElement( 198 SingleTouchData(1, ScreenIntPoint(75, 50), ScreenSize(0, 0), 0, 0)); 199 // Each touch will get hit-tested, so queue two hit-test results. 200 QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1, 201 {CompositorHitTestFlags::eVisibleToHitTest, 202 CompositorHitTestFlags::eIrregularArea}); 203 QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID + 1, 204 {CompositorHitTestFlags::eVisibleToHitTest, 205 CompositorHitTestFlags::eIrregularArea}); 206 blockId = manager->ReceiveInputEvent(mti).mInputBlockId; 207 manager->ContentReceivedInputBlock(blockId, /* default prevented = */ true); 208 targets.AppendElement(ApzcOf(layers[1])->GetGuid()); 209 manager->SetTargetAPZC(blockId, targets); 210 211 // If we've failed to clear the child's gesture state, then the long tap 212 // timeout task will fire in TearDown() and a long-tap will be dispatched. 213 EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, _, _, _, _, _)).Times(0); 214 } 215 216 TEST_F(APZCTreeManagerGenericTesterMock, Bug1198900) { 217 // This is just a test that cancels a wheel event to make sure it doesn't 218 // crash. 219 CreateSimpleScrollingLayer(); 220 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 221 UpdateHitTestingTree(); 222 223 ScreenPoint origin(100, 50); 224 ScrollWheelInput swi(mcc->Time(), 0, ScrollWheelInput::SCROLLMODE_INSTANT, 225 ScrollWheelInput::SCROLLDELTA_PIXEL, origin, 0, 10, 226 false, WheelDeltaAdjustmentStrategy::eNone); 227 uint64_t blockId; 228 QueueMockHitResult(ScrollableLayerGuid::START_SCROLL_ID, 229 {CompositorHitTestFlags::eVisibleToHitTest, 230 CompositorHitTestFlags::eIrregularArea}); 231 blockId = manager->ReceiveInputEvent(swi).mInputBlockId; 232 manager->ContentReceivedInputBlock(blockId, /* preventDefault= */ true); 233 } 234 235 // The next two tests check that APZ clamps the scroll offset it composites even 236 // if the main thread fails to do so. (The main thread will always clamp its 237 // scroll offset internally, but it may not send APZ the clamped version for 238 // scroll offset synchronization reasons.) 239 TEST_F(APZCTreeManagerTester, Bug1551582) { 240 // The simple layer tree has a scrollable rect of 500x500 and a composition 241 // bounds of 200x200, leading to a scroll range of (0,0,300,300). 242 CreateSimpleScrollingLayer(); 243 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 244 UpdateHitTestingTree(); 245 246 // Simulate the main thread scrolling to the end of the scroll range. 247 ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) { 248 aMetrics.SetLayoutScrollOffset(CSSPoint(300, 300)); 249 nsTArray<ScrollPositionUpdate> scrollUpdates; 250 scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll( 251 ScrollOrigin::Other, CSSPoint::ToAppUnits(CSSPoint(300, 300)))); 252 aSm.SetScrollUpdates(scrollUpdates); 253 aMetrics.SetScrollGeneration(scrollUpdates.LastElement().GetGeneration()); 254 }); 255 UpdateHitTestingTree(); 256 257 // Sanity check. 258 RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root); 259 CSSPoint compositedScrollOffset = apzc->GetCompositedScrollOffset(); 260 EXPECT_EQ(CSSPoint(300, 300), compositedScrollOffset); 261 262 // Simulate the main thread shrinking the scrollable rect to 400x400 (and 263 // thereby the scroll range to (0,0,200,200) without sending a new scroll 264 // offset update for the clamped scroll position (200,200). 265 ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) { 266 aMetrics.SetScrollableRect(CSSRect(0, 0, 400, 400)); 267 }); 268 UpdateHitTestingTree(); 269 270 // Check that APZ has clamped the scroll offset to (200,200) for us. 271 compositedScrollOffset = apzc->GetCompositedScrollOffset(); 272 EXPECT_EQ(CSSPoint(200, 200), compositedScrollOffset); 273 } 274 TEST_F(APZCTreeManagerTester, Bug1557424) { 275 // The simple layer tree has a scrollable rect of 500x500 and a composition 276 // bounds of 200x200, leading to a scroll range of (0,0,300,300). 277 CreateSimpleScrollingLayer(); 278 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 279 UpdateHitTestingTree(); 280 281 // Simulate the main thread scrolling to the end of the scroll range. 282 ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) { 283 aMetrics.SetLayoutScrollOffset(CSSPoint(300, 300)); 284 nsTArray<ScrollPositionUpdate> scrollUpdates; 285 scrollUpdates.AppendElement(ScrollPositionUpdate::NewScroll( 286 ScrollOrigin::Other, CSSPoint::ToAppUnits(CSSPoint(300, 300)))); 287 aSm.SetScrollUpdates(scrollUpdates); 288 aMetrics.SetScrollGeneration(scrollUpdates.LastElement().GetGeneration()); 289 }); 290 UpdateHitTestingTree(); 291 292 // Sanity check. 293 RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root); 294 CSSPoint compositedScrollOffset = apzc->GetCompositedScrollOffset(); 295 EXPECT_EQ(CSSPoint(300, 300), compositedScrollOffset); 296 297 // Simulate the main thread expanding the composition bounds to 300x300 (and 298 // thereby shrinking the scroll range to (0,0,200,200) without sending a new 299 // scroll offset update for the clamped scroll position (200,200). 300 ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) { 301 aMetrics.SetCompositionBounds(ParentLayerRect(0, 0, 300, 300)); 302 }); 303 UpdateHitTestingTree(); 304 305 // Check that APZ has clamped the scroll offset to (200,200) for us. 306 compositedScrollOffset = apzc->GetCompositedScrollOffset(); 307 EXPECT_EQ(CSSPoint(200, 200), compositedScrollOffset); 308 } 309 310 TEST_F(APZCTreeManagerTester, Bug1805601) { 311 // The simple layer tree has a scrollable rect of 500x500 and a composition 312 // bounds of 200x200, leading to a scroll range of (0,0,300,300) at unit zoom. 313 CreateSimpleScrollingLayer(); 314 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 315 UpdateHitTestingTree(); 316 RefPtr<TestAsyncPanZoomController> apzc = ApzcOf(root); 317 FrameMetrics& compositorMetrics = apzc->GetFrameMetrics(); 318 EXPECT_EQ(CSSRect(0, 0, 300, 300), compositorMetrics.CalculateScrollRange()); 319 320 // Zoom the page in by 2x. This needs to be reflected in each of the pres 321 // shell resolution, cumulative resolution, and zoom. This makes the scroll 322 // range (0,0,400,400). 323 compositorMetrics.SetZoom(CSSToParentLayerScale(2.0)); 324 EXPECT_EQ(CSSRect(0, 0, 400, 400), compositorMetrics.CalculateScrollRange()); 325 326 // Scroll to an area inside the 2x scroll range but outside the original one. 327 compositorMetrics.ClampAndSetVisualScrollOffset(CSSPoint(350, 350)); 328 EXPECT_EQ(CSSPoint(350, 350), compositorMetrics.GetVisualScrollOffset()); 329 330 // Simulate a main-thread update where the zoom is reset to 1x but the visual 331 // scroll offset is unmodified. 332 ModifyFrameMetrics(root, [](ScrollMetadata& aSm, FrameMetrics& aMetrics) { 333 // Changes to |compositorMetrics| are not reflected in |aMetrics|, which 334 // is the "layer tree" copy, so we don't need to explicitly set the zoom to 335 // 1.0 (it still has that as the initial value), but we do need to set 336 // the visual scroll offset to the same value the APZ copy has. 337 aMetrics.SetVisualScrollOffset(CSSPoint(350, 350)); 338 339 // Needed to get APZ to accept the 1.0 zoom in |aMetrics|, otherwise 340 // it will act as though its zoom is newer (e.g. an async zoom that hasn't 341 // been repainted yet) and ignore ours. 342 aSm.SetResolutionUpdated(true); 343 }); 344 UpdateHitTestingTree(); 345 346 // Check that APZ clamped the scroll offset. 347 EXPECT_EQ(CSSRect(0, 0, 300, 300), compositorMetrics.CalculateScrollRange()); 348 EXPECT_EQ(CSSPoint(300, 300), compositorMetrics.GetVisualScrollOffset()); 349 } 350 351 TEST_F(APZCTreeManagerTester, 352 InstantKeyScrollBetweenTwoSamplingsWithSameTimeStamp) { 353 if (!StaticPrefs::apz_keyboard_enabled_AtStartup()) { 354 // On Android apz.keyboard.enabled is false by default and it's can't be 355 // changed here since it's `mirror: once`, so we just skip this test. 356 return; 357 } 358 359 // For instant scrolling, i.e. no async animation should not be involved. 360 SCOPED_GFX_PREF_BOOL("general.smoothScroll", false); 361 362 // Set up a keyboard shortcuts map to scroll page down. 363 AutoTArray<KeyboardShortcut, 1> shortcuts{KeyboardShortcut( 364 KeyboardInput::KEY_DOWN, 0, 0, 0, 0, 365 KeyboardScrollAction( 366 KeyboardScrollAction::KeyboardScrollActionType::eScrollPage, true))}; 367 KeyboardMap keyboardMap(std::move(shortcuts)); 368 manager->SetKeyboardMap(keyboardMap); 369 370 // Set up a scrollable layer. 371 CreateSimpleScrollingLayer(); 372 ScopedLayerTreeRegistration registration(LayersId{0}, mcc); 373 UpdateHitTestingTree(); 374 375 // Setup the scrollable layer is scrollable by key events. 376 FocusTarget focusTarget; 377 focusTarget.mSequenceNumber = 1; 378 focusTarget.mData = AsVariant<FocusTarget::ScrollTargets>( 379 {ScrollableLayerGuid::START_SCROLL_ID, 380 ScrollableLayerGuid::START_SCROLL_ID}); 381 manager->UpdateFocusState(LayersId{0}, LayersId{0}, focusTarget); 382 383 // A vsync tick happens. 384 mcc->AdvanceByMillis(16); 385 386 // The first sampling happens, there's no change have happened, thus no need 387 // to composite. 388 EXPECT_FALSE(manager->AdvanceAnimations(mcc->GetSampleTime())); 389 390 // A key event causing scroll page down happens. 391 WidgetKeyboardEvent widgetEvent(true, eKeyDown, nullptr); 392 KeyboardInput input(widgetEvent); 393 (void)manager->ReceiveInputEvent(input); 394 395 // Simulate WebRender compositing frames until APZ tells it the scroll offset 396 // has stopped changing. 397 // Important to trigger the bug: the first composite has the same time stamp 398 // as the earlier one above. 399 ParentLayerPoint compositedScrollOffset; 400 while (true) { 401 bool needMoreFrames = manager->AdvanceAnimations(mcc->GetSampleTime()); 402 compositedScrollOffset = ApzcOf(root)->GetCurrentAsyncScrollOffset( 403 AsyncPanZoomController::eForCompositing); 404 if (!needMoreFrames) { 405 break; 406 } 407 mcc->AdvanceBy(TimeDuration::FromMilliseconds(16)); 408 } 409 410 // Check that the effect of the keyboard scroll has been composited. 411 EXPECT_GT(compositedScrollOffset.y, 0); 412 } 413 414 TEST_F(APZCTreeManagerGenericTesterMock, 415 PanGestureWithCtrlModifier_Bug1917488) { 416 // The outer layer represents the browser chrome, and has layers id 0. 417 // The inner layer represents web content, and will initally get layers id 1. 418 const char* treeShape = "x(x)"; 419 LayerIntRect layerVisibleRect[] = { 420 LayerIntRect(0, 0, 100, 100), 421 LayerIntRect(0, 0, 100, 100), 422 }; 423 CreateScrollData(treeShape, layerVisibleRect); 424 425 // We need one of these for every LayersId the test will use! 426 ScopedLayerTreeRegistration registration0(LayersId{0}, mcc); 427 ScopedLayerTreeRegistration registration1(LayersId{1}, mcc); 428 ScopedLayerTreeRegistration registration2(LayersId{2}, mcc); 429 430 // In this test, we only bother to give the inner layer an APZC. 431 ScrollableLayerGuid::ViewID scrollId = ScrollableLayerGuid::START_SCROLL_ID; 432 SetScrollableFrameMetrics(layers[1], scrollId, CSSRect(0, 0, 100, 100)); 433 434 // Set the referent id of the root layer to 1. 435 // Note that this causes the *descendants* of the root layer 436 // to get a layers id of 1 during the hit-testing tree update. 437 LayersId tab1LayersId{1}; 438 ScrollableLayerGuid tab1Guid(tab1LayersId, 0, scrollId); 439 root->SetReferentId(tab1LayersId); 440 UpdateHitTestingTree(); 441 442 // Perform a pan gesture on the content layer. 443 // For the START event, do not use the PanGesture() helper, because we want to 444 // check the mLayersId that APZ sets on the input event object. This 445 // determines what content process the event will gets dispatched to. 446 ScreenIntPoint panPoint(50, 50); 447 QueueMockHitResult(tab1Guid); 448 PanGestureInput panStart(PanGestureInput::PANGESTURE_START, mcc->Time(), 449 panPoint, ScreenPoint(0, 10), MODIFIER_NONE); 450 manager->ReceiveInputEvent(panStart); 451 mcc->AdvanceByMillis(5); 452 QueueMockHitResult(tab1Guid); 453 PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint, 454 ScreenPoint(0, 10), mcc->Time()); 455 mcc->AdvanceByMillis(5); 456 QueueMockHitResult(tab1Guid); 457 PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint, 458 ScreenPoint(0, 0), mcc->Time()); 459 460 // The layers id assigned to the events of this gesture should be 1. 461 EXPECT_EQ(panStart.mLayersId, tab1LayersId); 462 463 // Simulate a tab switch by updating the referent id of the root layer 464 // to a new layers id, 2. 465 LayersId tab2LayersId{2}; 466 ScrollableLayerGuid tab2Guid(tab2LayersId, 0, scrollId); 467 root->SetReferentId(tab2LayersId); 468 UpdateHitTestingTree(); 469 470 // Perform another pan gesture on the content layer, but this time with 471 // the Control modifier held down. 472 QueueMockHitResult(tab2Guid); 473 PanGestureInput zoomStart(PanGestureInput::PANGESTURE_START, mcc->Time(), 474 panPoint, ScreenPoint(0, 10), MODIFIER_CONTROL); 475 manager->ReceiveInputEvent(zoomStart); 476 mcc->AdvanceByMillis(5); 477 QueueMockHitResult(tab2Guid); 478 PanGesture(PanGestureInput::PANGESTURE_PAN, manager, panPoint, 479 ScreenPoint(0, 10), mcc->Time(), MODIFIER_CONTROL); 480 mcc->AdvanceByMillis(5); 481 QueueMockHitResult(tab2Guid); 482 PanGesture(PanGestureInput::PANGESTURE_END, manager, panPoint, 483 ScreenPoint(0, 0), mcc->Time(), MODIFIER_CONTROL); 484 485 // The layers id assigned to the events in the zoom gesture should be 2. 486 // (In the buggy scenario, it's 1, meaning the events get incorrectly 487 // sent to the previous tab's content process.) 488 EXPECT_EQ(zoomStart.mLayersId, tab2LayersId); 489 }