⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 284654 in webkit


Ignore:
Timestamp:
Oct 21, 2021, 4:58:35 PM (5 years ago)
Author:
Simon Fraser
Message:

Content offset in this codepen when switching tabs
https://bugs.webkit.org/show_bug.cgi?id=231989

Reviewed by Tim Horton.

Source/WebCore:

There were two problems that occurred with async-scrollable iframes when their associated
WKWebView was removed and re-added to the view hierarchy (e.g. when switching tabs).
These resulted in misplaced position:fixed content, and the first user scroll in the
iframe causing the scroll position to jump back to the top.

The positon:fixed issue was caused by an ordering problem in
ScrollingTreeFrameScrollingNode::commitStateBeforeChildren() which resulted in the layout
viewport being computed incorrectly; we called updateViewportForCurrentScrollPosition()
before setting the min and max scroll position, so we'd always clamp the layout viewport to
a location of 0,0.

The second scroll position reset issue was caused by the ScrollingTreeScrollingNode's
m_currentScrollPosition reverting to a stale after re-attaching the iframe's scrolling
subtree. ScrollingTreeScrollingNode::commitStateBeforeChildren() has code to set
m_currentScrollPosition from the state tree node's scroll position on first commit;
the issue was that ScrollingStateScrollingNode's scrollPosition() was not updated on every
scroll, only when something triggered a scrolling tree commit.

Fix by silently updating ScrollingStateScrollingNode's scrollPosition() when we get
notifications back from the scrolling thread that a scroll happened.

Both fixes are tested by the ScrollingCoordinatorTests.ScrollingTreeAfterDetachReattach API test.

  • page/scrolling/AsyncScrollingCoordinator.cpp:

(WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):

  • page/scrolling/ScrollingStateScrollingNode.cpp:

(WebCore::ScrollingStateScrollingNode::syncScrollPosition):
(WebCore::ScrollingStateScrollingNode::hasScrollPositionRequest const):

  • page/scrolling/ScrollingStateScrollingNode.h:
  • page/scrolling/ScrollingStateTree.cpp:

(WebCore::ScrollingStateTree::insertNode):

  • page/scrolling/ScrollingTreeFrameScrollingNode.cpp:

(WebCore::ScrollingTreeFrameScrollingNode::commitStateBeforeChildren): We need to check
state.hasScrollPositionRequest(), otherwise the "cancel animated scroll request" that comes
out of Page::stopKeyboardScrollAnimation() prevents scroll position restoration.

  • page/scrolling/ScrollingTreeScrollingNode.cpp:

(WebCore::ScrollingTreeScrollingNode::commitStateBeforeChildren):
(WebCore::ScrollingTreeScrollingNode::dumpProperties const):

  • page/scrolling/mac/ScrollingCoordinatorMac.mm:

(WebCore::ScrollingCoordinatorMac::commitTreeStateIfNeeded):

Tools:

API test that scrolls an iframe via wheel events, then detached and re-attaches the view.

The two wheel scrolls are necessary to exercise the "stale ScrollingStateScrollingNode
scroll position" issue.

The scrolling tree dumps validate the layout viewport part of the fix.

Also correct some functions where the sense of 'isWaitingForJavaScript' was flipped.

  • TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
  • TestWebKitAPI/Tests/mac/ScrollingCoordinatorTests.mm: Added.

(TestWebKitAPI::synthesizeWheelEvents):
(TestWebKitAPI::waitForScrollEventAndReturnScrollY):
(TestWebKitAPI::scrollingTreeElidingLastCommittedScrollPosition):
(TestWebKitAPI::TEST):

  • TestWebKitAPI/cocoa/TestWKWebView.mm:

(-[WKWebView objectByEvaluatingJavaScript:]):
(-[WKWebView objectByEvaluatingJavaScriptWithUserGesture:]):
(-[WKWebView objectByCallingAsyncFunction:withArguments:error:]):

LayoutTests:

New baselines.

  • tiled-drawing/scrolling/clamp-out-of-bounds-scrolls-expected.txt:
  • tiled-drawing/scrolling/scrolling-tree-after-scroll-expected.txt:
Location:
trunk
Files:
1 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r284653 r284654  
     12021-10-21  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Content offset in this codepen when switching tabs
     4        https://bugs.webkit.org/show_bug.cgi?id=231989
     5
     6        Reviewed by Tim Horton.
     7
     8        New baselines.
     9
     10        * tiled-drawing/scrolling/clamp-out-of-bounds-scrolls-expected.txt:
     11        * tiled-drawing/scrolling/scrolling-tree-after-scroll-expected.txt:
     12
    1132021-10-21  John Wilander  <wilander@apple.com>
    214
  • trunk/LayoutTests/tiled-drawing/scrolling/clamp-out-of-bounds-scrolls-expected.txt

    r271070 r284654  
    5656
    5757(Frame scrolling node
     58  (scroll position 4223 0)
    5859  (scrollable area size 785 585)
    5960  (contents size 5008 5021)
     
    7677
    7778(Frame scrolling node
    78   (scroll position 4223 0)
     79  (scroll position 0 4436)
    7980  (scrollable area size 785 585)
    8081  (contents size 5008 5021)
     
    9798
    9899(Frame scrolling node
    99   (scroll position 0 4436)
     100  (scroll position 4223 4436)
    100101  (scrollable area size 785 585)
    101102  (contents size 5008 5021)
  • trunk/LayoutTests/tiled-drawing/scrolling/scrolling-tree-after-scroll-expected.txt

    r271070 r284654  
    11
    22(Frame scrolling node
     3  (scroll position 0 3000)
    34  (scrollable area size 785 600)
    45  (contents size 785 5021)
  • trunk/Source/WebCore/ChangeLog

    r284652 r284654  
     12021-10-21  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Content offset in this codepen when switching tabs
     4        https://bugs.webkit.org/show_bug.cgi?id=231989
     5
     6        Reviewed by Tim Horton.
     7
     8        There were two problems that occurred with async-scrollable iframes when their associated
     9        WKWebView was removed and re-added to the view hierarchy (e.g. when switching tabs).
     10        These resulted in misplaced position:fixed content, and the first user scroll in the
     11        iframe causing the scroll position to jump back to the top.
     12
     13        The positon:fixed issue was caused by an ordering problem in
     14        ScrollingTreeFrameScrollingNode::commitStateBeforeChildren() which resulted in the layout
     15        viewport being computed incorrectly; we called updateViewportForCurrentScrollPosition()
     16        before setting the min and max scroll position, so we'd always clamp the layout viewport to
     17        a location of 0,0.
     18
     19        The second scroll position reset issue was caused by the ScrollingTreeScrollingNode's
     20        m_currentScrollPosition reverting to a stale after re-attaching the iframe's scrolling
     21        subtree. ScrollingTreeScrollingNode::commitStateBeforeChildren() has code to set
     22        m_currentScrollPosition from the state tree node's scroll position on first commit;
     23        the issue was that ScrollingStateScrollingNode's scrollPosition() was not updated on every
     24        scroll, only when something triggered a scrolling tree commit.
     25
     26        Fix by silently updating ScrollingStateScrollingNode's scrollPosition() when we get
     27        notifications back from the scrolling thread that a scroll happened.
     28
     29        Both fixes are tested by the ScrollingCoordinatorTests.ScrollingTreeAfterDetachReattach API test.
     30
     31        * page/scrolling/AsyncScrollingCoordinator.cpp:
     32        (WebCore::AsyncScrollingCoordinator::updateScrollPositionAfterAsyncScroll):
     33        * page/scrolling/ScrollingStateScrollingNode.cpp:
     34        (WebCore::ScrollingStateScrollingNode::syncScrollPosition):
     35        (WebCore::ScrollingStateScrollingNode::hasScrollPositionRequest const):
     36        * page/scrolling/ScrollingStateScrollingNode.h:
     37        * page/scrolling/ScrollingStateTree.cpp:
     38        (WebCore::ScrollingStateTree::insertNode):
     39        * page/scrolling/ScrollingTreeFrameScrollingNode.cpp:
     40        (WebCore::ScrollingTreeFrameScrollingNode::commitStateBeforeChildren): We need to check
     41        state.hasScrollPositionRequest(), otherwise the "cancel animated scroll request" that comes
     42        out of Page::stopKeyboardScrollAnimation() prevents scroll position restoration.
     43        * page/scrolling/ScrollingTreeScrollingNode.cpp:
     44        (WebCore::ScrollingTreeScrollingNode::commitStateBeforeChildren):
     45        (WebCore::ScrollingTreeScrollingNode::dumpProperties const):
     46        * page/scrolling/mac/ScrollingCoordinatorMac.mm:
     47        (WebCore::ScrollingCoordinatorMac::commitTreeStateIfNeeded):
     48
    1492021-10-21  Sihui Liu  <sihui_liu@apple.com>
    250
  • trunk/Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp

    r284534 r284654  
    452452    }
    453453
     454    auto* node = m_scrollingStateTree->stateNodeForID(scrollingNodeID);
     455    if (is<ScrollingStateScrollingNode>(node)) {
     456        auto& scrollingNode = downcast<ScrollingStateScrollingNode>(*node);
     457        scrollingNode.syncScrollPosition(scrollPosition);
     458    }
     459
    454460    if (scrollingNodeID == frameView.scrollingNodeID()) {
    455461        reconcileScrollingState(frameView, scrollPosition, layoutViewportOrigin, scrollType, ViewportRectStability::Stable, scrollingLayerPositionAction);
  • trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp

    r284534 r284654  
    144144}
    145145
     146void ScrollingStateScrollingNode::syncScrollPosition(const FloatPoint& scrollPosition)
     147{
     148    m_scrollPosition = scrollPosition;
     149}
     150
    146151void ScrollingStateScrollingNode::setScrollOrigin(const IntPoint& scrollOrigin)
    147152{
     
    205210    m_requestedScrollData = scrollData;
    206211    setPropertyChanged(Property::RequestedScrollPosition);
     212}
     213
     214bool ScrollingStateScrollingNode::hasScrollPositionRequest() const
     215{
     216    return hasChangedProperty(Property::RequestedScrollPosition) && m_requestedScrollData.requestType == ScrollRequestType::PositionUpdate;
    207217}
    208218
  • trunk/Source/WebCore/page/scrolling/ScrollingStateScrollingNode.h

    r284534 r284654  
    5555    WEBCORE_EXPORT void setScrollPosition(const FloatPoint&);
    5656
     57    // Does not trigger a scrolling tree commit.
     58    WEBCORE_EXPORT void syncScrollPosition(const FloatPoint&);
     59
    5760    const IntPoint& scrollOrigin() const { return m_scrollOrigin; }
    5861    WEBCORE_EXPORT void setScrollOrigin(const IntPoint&);
     
    7881    const RequestedScrollData& requestedScrollData() const { return m_requestedScrollData; }
    7982    WEBCORE_EXPORT void setRequestedScrollData(const RequestedScrollData&);
     83
     84    WEBCORE_EXPORT bool hasScrollPositionRequest() const;
    8085
    8186    bool isMonitoringWheelEvents() const { return m_isMonitoringWheelEvents; }
  • trunk/Source/WebCore/page/scrolling/ScrollingStateTree.cpp

    r284534 r284654  
    177177        if (parentID) {
    178178            if (auto unparentedNode = m_unparentedNodes.take(newNodeID)) {
    179                 LOG_WITH_STREAM(ScrollingTree, stream << "ScrollingStateTree " << this << " insertNode " << newNodeID << " getting node from unparented nodes");
     179                LOG_WITH_STREAM(ScrollingTree, stream << "ScrollingStateTree " << this << " insertNode reattaching node " << newNodeID);
    180180                newNode = unparentedNode.get();
    181181                nodeWasReattachedRecursive(*unparentedNode);
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeFrameScrollingNode.cpp

    r284534 r284654  
    7373        m_fixedElementsLayoutRelativeToFrame = state.fixedElementsLayoutRelativeToFrame();
    7474
    75     if (state.hasChangedProperty(ScrollingStateNode::Property::LayoutViewport)) {
     75    if (state.hasChangedProperty(ScrollingStateNode::Property::LayoutViewport))
    7676        m_layoutViewport = state.layoutViewport();
    77         updateViewportForCurrentScrollPosition({ });
    78     }
    7977
    8078    if (state.hasChangedProperty(ScrollingStateNode::Property::MinLayoutViewportOrigin))
     
    8684    if (state.hasChangedProperty(ScrollingStateNode::Property::OverrideVisualViewportSize))
    8785        m_overrideVisualViewportSize = state.overrideVisualViewportSize();
     86
     87    if (state.hasChangedProperty(ScrollingStateNode::Property::LayoutViewport)) {
     88        // This requires that minLayoutViewportOrigin and maxLayoutViewportOrigin have been updated.
     89        updateViewportForCurrentScrollPosition({ });
     90    }
    8891}
    8992
  • trunk/Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp

    r284534 r284654  
    6868    if (state.hasChangedProperty(ScrollingStateNode::Property::ScrollPosition)) {
    6969        m_lastCommittedScrollPosition = state.scrollPosition();
    70         if (m_isFirstCommit && !state.hasChangedProperty(ScrollingStateNode::Property::RequestedScrollPosition))
     70        if (m_isFirstCommit && !state.hasScrollPositionRequest())
    7171            m_currentScrollPosition = m_lastCommittedScrollPosition;
    7272    }
     
    337337    ts.dumpProperty("last committed scroll position", m_lastCommittedScrollPosition);
    338338
    339     if (m_scrollOrigin != IntPoint())
     339    if (!m_currentScrollPosition.isZero())
     340        ts.dumpProperty("scroll position", m_currentScrollPosition);
     341
     342    if (!m_scrollOrigin.isZero())
    340343        ts.dumpProperty("scroll origin", m_scrollOrigin);
    341344
  • trunk/Source/WebCore/page/scrolling/mac/ScrollingCoordinatorMac.mm

    r284534 r284654  
    115115        return;
    116116
    117     LOG_WITH_STREAM(ScrollingTree, stream << scrollingStateTreeAsText(debugScrollingStateTreeAsTextBehaviors));
     117    LOG_WITH_STREAM(ScrollingTree, stream << "ScrollingCoordinatorMac::commitTreeState: state tree " << scrollingStateTreeAsText(debugScrollingStateTreeAsTextBehaviors));
    118118
    119119    auto stateTree = scrollingStateTree()->commit(LayerRepresentation::PlatformLayerRepresentation);
  • trunk/Tools/ChangeLog

    r284638 r284654  
     12021-10-21  Simon Fraser  <simon.fraser@apple.com>
     2
     3        Content offset in this codepen when switching tabs
     4        https://bugs.webkit.org/show_bug.cgi?id=231989
     5
     6        Reviewed by Tim Horton.
     7
     8        API test that scrolls an iframe via wheel events, then detached and re-attaches the view.
     9
     10        The two wheel scrolls are necessary to exercise the "stale ScrollingStateScrollingNode
     11        scroll position" issue.
     12
     13        The scrolling tree dumps validate the layout viewport part of the fix.
     14
     15        Also correct some functions where the sense of 'isWaitingForJavaScript' was flipped.
     16
     17        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
     18        * TestWebKitAPI/Tests/mac/ScrollingCoordinatorTests.mm: Added.
     19        (TestWebKitAPI::synthesizeWheelEvents):
     20        (TestWebKitAPI::waitForScrollEventAndReturnScrollY):
     21        (TestWebKitAPI::scrollingTreeElidingLastCommittedScrollPosition):
     22        (TestWebKitAPI::TEST):
     23        * TestWebKitAPI/cocoa/TestWKWebView.mm:
     24        (-[WKWebView objectByEvaluatingJavaScript:]):
     25        (-[WKWebView objectByEvaluatingJavaScriptWithUserGesture:]):
     26        (-[WKWebView objectByCallingAsyncFunction:withArguments:error:]):
     27
    1282021-10-21  Fujii Hironori  <Hironori.Fujii@sony.com>
    229
  • trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj

    r284628 r284654  
    8787                0F5651F71FCE4DDC00310FBC /* NoHistoryItemScrollToFragment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F5651F61FCE4DDB00310FBC /* NoHistoryItemScrollToFragment.mm */; };
    8888                0F5651F91FCE513500310FBC /* scroll-to-anchor.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 0F5651F81FCE50E800310FBC /* scroll-to-anchor.html */; };
     89                0FEFAF64271FC2CD005704D7 /* ScrollingCoordinatorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FEFAF63271FC2CD005704D7 /* ScrollingCoordinatorTests.mm */; };
    8990                0FF1134E22D68679009A81DA /* ScrollViewScrollabilityTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0FF1134D22D68679009A81DA /* ScrollViewScrollabilityTests.mm */; };
    9091                115EB3431EE0BA03003C2C0A /* ViewportSizeForViewportUnits.mm in Sources */ = {isa = PBXBuildFile; fileRef = 115EB3421EE0B720003C2C0A /* ViewportSizeForViewportUnits.mm */; };
     
    18611862                0FE447971B76F1E3009498EB /* ParkingLot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParkingLot.cpp; sourceTree = "<group>"; };
    18621863                0FEAE3671B7D19CB00CE17F2 /* Condition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Condition.cpp; sourceTree = "<group>"; };
     1864                0FEFAF63271FC2CD005704D7 /* ScrollingCoordinatorTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollingCoordinatorTests.mm; sourceTree = "<group>"; };
    18631865                0FF1134D22D68679009A81DA /* ScrollViewScrollabilityTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ScrollViewScrollabilityTests.mm; sourceTree = "<group>"; };
    18641866                0FFC45A41B73EBE20085BD62 /* Lock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Lock.cpp; sourceTree = "<group>"; };
     
    30933095                F44A531021B8976900DBB99C /* InstanceMethodSwizzler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = InstanceMethodSwizzler.mm; path = ../TestRunnerShared/cocoa/InstanceMethodSwizzler.mm; sourceTree = "<group>"; };
    30943096                F44A7D1F268D5C6900B49BB8 /* ImageAnalysisTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ImageAnalysisTests.mm; sourceTree = "<group>"; };
    3095                 F44A9AF52649BBDD00E7CB16 /* ImmediateActionTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImmediateActionTests.h; sourceTree = "<group>"; };
    30963097                F44A9AF62649BBDD00E7CB16 /* ImmediateActionTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ImmediateActionTests.mm; sourceTree = "<group>"; };
    30973098                F44C79FB20F9E50C0014478C /* ParserYieldTokenPlugIn.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ParserYieldTokenPlugIn.mm; sourceTree = "<group>"; };
     
    48294830                                9B4F8FA3159D52B1002D9F94 /* HTMLCollectionNamedItem.mm */,
    48304831                                9B26FC6B159D061000CC3765 /* HTMLFormCollectionNamedItem.mm */,
    4831                                 F44A9AF52649BBDD00E7CB16 /* ImmediateActionTests.h */,
    48324832                                F44A9AF62649BBDD00E7CB16 /* ImmediateActionTests.mm */,
    48334833                                C507E8A614C6545B005D6B3B /* InspectorBar.mm */,
     
    48494849                                37C784DE197C8F2E0010A496 /* RenderedImageFromDOMNode.mm */,
    48504850                                3722C8681461E03E00C45D00 /* RenderedImageFromDOMRange.mm */,
     4851                                0FEFAF63271FC2CD005704D7 /* ScrollingCoordinatorTests.mm */,
    48514852                                261516D515B0E60500A2C201 /* SetAndUpdateCacheModel.mm */,
    48524853                                52B8CF9515868CF000281053 /* SetDocumentURI.mm */,
     
    58465847                                CDCFA7AA1E45183200C2433D /* SampleMap.cpp in Sources */,
    58475848                                CE0947372063223B003C9BA0 /* SchemeRegistry.mm in Sources */,
     5849                                0FEFAF64271FC2CD005704D7 /* ScrollingCoordinatorTests.mm in Sources */,
    58485850                                CDC0932B21C872C10030C4B0 /* ScrollingDoesNotPauseMedia.mm in Sources */,
    58495851                                7CCE7F121A411AE600447C4C /* ScrollPinningBehaviors.cpp in Sources */,
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.h

    r281468 r284654  
    140140- (void)sendClicksAtPoint:(NSPoint)pointInWindow numberOfClicks:(NSUInteger)numberOfClicks;
    141141- (void)sendClickAtPoint:(NSPoint)pointInWindow;
     142- (void)wheelEventAtPoint:(CGPoint)pointInWindow wheelDelta:(CGSize)delta;
    142143- (NSWindow *)hostWindow;
    143144- (void)typeCharacter:(char)character modifiers:(NSEventModifierFlags)modifiers;
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm

    r283276 r284654  
    205205- (id)objectByEvaluatingJavaScript:(NSString *)script
    206206{
    207     bool isWaitingForJavaScript = false;
     207    bool callbackComplete = false;
    208208    RetainPtr<id> evalResult;
    209209    [self _evaluateJavaScriptWithoutUserGesture:script completionHandler:[&] (id result, NSError *error) {
    210210        evalResult = result;
    211         isWaitingForJavaScript = true;
     211        callbackComplete = true;
    212212        EXPECT_TRUE(!error);
    213213        if (error)
    214214            NSLog(@"Encountered error: %@ while evaluating script: %@", error, script);
    215215    }];
    216     TestWebKitAPI::Util::run(&isWaitingForJavaScript);
     216    TestWebKitAPI::Util::run(&callbackComplete);
    217217    return evalResult.autorelease();
    218218}
     
    220220- (id)objectByEvaluatingJavaScriptWithUserGesture:(NSString *)script
    221221{
    222     bool isWaitingForJavaScript = false;
     222    bool callbackComplete = false;
    223223    RetainPtr<id> evalResult;
    224224    [self evaluateJavaScript:script completionHandler:[&] (id result, NSError *error) {
    225225        evalResult = result;
    226         isWaitingForJavaScript = true;
     226        callbackComplete = true;
    227227        EXPECT_TRUE(!error);
    228228        if (error)
    229229            NSLog(@"Encountered error: %@ while evaluating script: %@", error, script);
    230230    }];
    231     TestWebKitAPI::Util::run(&isWaitingForJavaScript);
     231    TestWebKitAPI::Util::run(&callbackComplete);
    232232    return evalResult.autorelease();
    233233}
     
    235235- (id)objectByCallingAsyncFunction:(NSString *)script withArguments:(NSDictionary *)arguments error:(NSError **)errorOut
    236236{
    237     bool isWaitingForJavaScript = false;
     237    bool callbackComplete = false;
    238238    if (errorOut)
    239239        *errorOut = nil;
     
    244244        evalResult = result;
    245245        strongError = error;
    246         isWaitingForJavaScript = true;
    247     }];
    248     TestWebKitAPI::Util::run(&isWaitingForJavaScript);
     246        callbackComplete = true;
     247    }];
     248    TestWebKitAPI::Util::run(&callbackComplete);
    249249
    250250    if (errorOut)
     
    863863}
    864864
     865- (void)wheelEventAtPoint:(CGPoint)pointInWindow wheelDelta:(CGSize)delta
     866{
     867    RetainPtr<CGEventRef> cgScrollEvent = adoptCF(CGEventCreateScrollWheelEvent(nullptr, kCGScrollEventUnitPixel, 2, delta.height, delta.width, 0));
     868
     869    CGPoint locationInGlobalScreenCoordinates = [[self window] convertPointToScreen:pointInWindow];
     870    locationInGlobalScreenCoordinates.y = [[[NSScreen screens] objectAtIndex:0] frame].size.height - locationInGlobalScreenCoordinates.y;
     871    CGEventSetLocation(cgScrollEvent.get(), locationInGlobalScreenCoordinates);
     872   
     873    NSEvent* event = [NSEvent eventWithCGEvent:cgScrollEvent.get()];
     874    [self scrollWheel:event];
     875}
     876
    865877- (NSWindow *)hostWindow
    866878{
Note: See TracChangeset for help on using the changeset viewer.