Changeset 290743 in webkit


Ignore:
Timestamp:
Mar 2, 2022 11:39:49 AM (5 months ago)
Author:
Chris Dumez
Message:

Mousemove events double-firing in Safari
https://bugs.webkit.org/show_bug.cgi?id=237342
<rdar://88025610>

Reviewed by Wenson Hsieh.

Source/WebKit:

When we constructed a WebViewImpl, we would add a mouse tracking area to the view,
so that mouseMoved/mouseEntered/mouseExited would get called and we would be able
to forward these mouse events to the WebContent process. However, when the view
becomes first responder, an implicit mouse tracking area also gets added. As a
result, we would get duplicate calls to mouseMoved/mouseEntered/mouseExited.

We consulted with the AppKit team and their recommendation was to use a different
owner object for our mouse tracking area and have that object forward the
mouseMoved/mouseEntered/mouseExited calls to our WebViewImpl. In doing so, we
can stop forwarding mouseMoved/mouseEntered/mouseExited calls from WKWebView &
WKView, which are NOT for our mouse tracking area.

No new tests, I tried but wasn't able to write an API test for this.
I had trouble making the test window key so that the view would receive
the (duplicate) mousemove events. I validated via logging that we are no longer
getting duplicate mousemove events. I also checked on
https://www.vsynctester.com/testing/mouse.html that the output now looks correct.

  • UIProcess/API/Cocoa/WKViewPrivate.h:
  • UIProcess/API/Cocoa/WKWebViewPrivate.h:
  • UIProcess/API/mac/WKView.mm:

(-[WKView _simulateMouseMove:]):
(-[WKView mouseMoved:]): Deleted.
(-[WKView mouseEntered:]): Deleted.
(-[WKView mouseExited:]): Deleted.

  • UIProcess/API/mac/WKWebViewMac.mm:

(-[WKWebView _simulateMouseMove:]):
(-[WKWebView mouseMoved:]): Deleted.
(-[WKWebView mouseEntered:]): Deleted.
(-[WKWebView mouseExited:]): Deleted.

  • UIProcess/Cocoa/WebViewImpl.h:
  • UIProcess/Cocoa/WebViewImpl.mm:

(-[WKMouseTrackingObserver initWithViewImpl:]):
(-[WKMouseTrackingObserver mouseMoved:]):
(-[WKMouseTrackingObserver mouseEntered:]):
(-[WKMouseTrackingObserver mouseExited:]):
(WebKit::WebViewImpl::WebViewImpl):
(WebKit::WebViewImpl::updatePrimaryTrackingAreaOptions):
(WebKit::WebViewImpl::setPrimaryTrackingArea): Deleted.

  • UIProcess/mac/PageClientImplMac.mm:

(WebKit::PageClientImpl::recommendedScrollbarStyleDidChange):

Tools:

Call [WKWebView _simulateMouseMove:] SPI instead of calling [WKWebView mouseMoved:]
since the latter calls are now being ignored.

  • TestWebKitAPI/cocoa/TestWKWebView.mm:

(-[TestWKWebView mouseMoveToPoint:withFlags:]):

  • TestWebKitAPI/mac/PlatformWebViewMac.mm:

(TestWebKitAPI::PlatformWebView::simulateMouseMove):

  • WebKitTestRunner/mac/EventSenderProxy.mm:

(WTR::EventSenderProxy::mouseMoveTo):

Location:
trunk
Files:
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r290739 r290743  
     12022-03-02  Chris Dumez  <cdumez@apple.com>
     2
     3        Mousemove events double-firing in Safari
     4        https://bugs.webkit.org/show_bug.cgi?id=237342
     5        <rdar://88025610>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        When we constructed a WebViewImpl, we would add a mouse tracking area to the view,
     10        so that mouseMoved/mouseEntered/mouseExited would get called and we would be able
     11        to forward these mouse events to the WebContent process. However, when the view
     12        becomes first responder, an implicit mouse tracking area also gets added. As a
     13        result, we would get duplicate calls to mouseMoved/mouseEntered/mouseExited.
     14
     15        We consulted with the AppKit team and their recommendation was to use a different
     16        owner object for our mouse tracking area and have that object forward the
     17        mouseMoved/mouseEntered/mouseExited calls to our WebViewImpl. In doing so, we
     18        can stop forwarding mouseMoved/mouseEntered/mouseExited calls from WKWebView &
     19        WKView, which are NOT for our mouse tracking area.
     20
     21        No new tests, I tried but wasn't able to write an API test for this.
     22        I had trouble making the test window key so that the view would receive
     23        the (duplicate) mousemove events. I validated via logging that we are no longer
     24        getting duplicate mousemove events. I also checked on
     25        https://www.vsynctester.com/testing/mouse.html that the output now looks correct.
     26
     27        * UIProcess/API/Cocoa/WKViewPrivate.h:
     28        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
     29        * UIProcess/API/mac/WKView.mm:
     30        (-[WKView _simulateMouseMove:]):
     31        (-[WKView mouseMoved:]): Deleted.
     32        (-[WKView mouseEntered:]): Deleted.
     33        (-[WKView mouseExited:]): Deleted.
     34        * UIProcess/API/mac/WKWebViewMac.mm:
     35        (-[WKWebView _simulateMouseMove:]):
     36        (-[WKWebView mouseMoved:]): Deleted.
     37        (-[WKWebView mouseEntered:]): Deleted.
     38        (-[WKWebView mouseExited:]): Deleted.
     39        * UIProcess/Cocoa/WebViewImpl.h:
     40        * UIProcess/Cocoa/WebViewImpl.mm:
     41        (-[WKMouseTrackingObserver initWithViewImpl:]):
     42        (-[WKMouseTrackingObserver mouseMoved:]):
     43        (-[WKMouseTrackingObserver mouseEntered:]):
     44        (-[WKMouseTrackingObserver mouseExited:]):
     45        (WebKit::WebViewImpl::WebViewImpl):
     46        (WebKit::WebViewImpl::updatePrimaryTrackingAreaOptions):
     47        (WebKit::WebViewImpl::setPrimaryTrackingArea): Deleted.
     48        * UIProcess/mac/PageClientImplMac.mm:
     49        (WebKit::PageClientImpl::recommendedScrollbarStyleDidChange):
     50
    1512022-03-02  Sihui Liu  <sihui_liu@apple.com>
    252
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKViewPrivate.h

    r282375 r290743  
    132132
    133133- (void)_gestureEventWasNotHandledByWebCore:(NSEvent *)event;
     134- (void)_simulateMouseMove:(NSEvent *)event;
    134135
    135136- (void)_setShouldSuppressFirstResponderChanges:(BOOL)shouldSuppress WK_API_AVAILABLE(macos(10.13.4));
  • trunk/Source/WebKit/UIProcess/API/mac/WKView.mm

    r286894 r290743  
    517517}
    518518
    519 - (void)mouseMoved:(NSEvent *)event
    520 {
    521     _data->_impl->mouseMoved(event);
    522 }
    523 
    524519- (void)mouseDown:(NSEvent *)event
    525520{
     
    535530{
    536531    _data->_impl->mouseDragged(event);
    537 }
    538 
    539 - (void)mouseEntered:(NSEvent *)event
    540 {
    541     _data->_impl->mouseEntered(event);
    542 }
    543 
    544 - (void)mouseExited:(NSEvent *)event
    545 {
    546     _data->_impl->mouseExited(event);
    547532}
    548533
     
    15471532}
    15481533
     1534- (void)_simulateMouseMove:(NSEvent *)event
     1535{
     1536    _data->_impl->mouseMoved(event);
     1537}
     1538
    15491539- (void)smartMagnifyWithEvent:(NSEvent *)event
    15501540{
  • trunk/Source/WebKit/UIProcess/API/mac/WKWebViewMac.mm

    r287737 r290743  
    475475}
    476476
    477 - (void)mouseMoved:(NSEvent *)event
    478 {
    479     _impl->mouseMoved(event);
    480 }
    481 
    482477- (void)mouseDown:(NSEvent *)event
    483478{
     
    493488{
    494489    _impl->mouseDragged(event);
    495 }
    496 
    497 - (void)mouseEntered:(NSEvent *)event
    498 {
    499     _impl->mouseEntered(event);
    500 }
    501 
    502 - (void)mouseExited:(NSEvent *)event
    503 {
    504     _impl->mouseExited(event);
    505490}
    506491
  • trunk/Source/WebKit/UIProcess/API/mac/WKWebViewPrivateForTestingMac.h

    r266654 r290743  
    5353- (NSSet<NSView *> *)_pdfHUDs;
    5454
     55- (void)_simulateMouseMove:(NSEvent *)event;
     56
    5557@end
    5658
  • trunk/Source/WebKit/UIProcess/API/mac/WKWebViewTestingMac.mm

    r290712 r290743  
    122122}
    123123
     124- (void)_simulateMouseMove:(NSEvent *)event
     125{
     126    return _impl->mouseMoved(event);
     127}
     128
    124129@end
    125130
  • trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.h

    r288961 r290743  
    6363OBJC_CLASS WKFullScreenWindowController;
    6464OBJC_CLASS WKImmediateActionController;
     65OBJC_CLASS WKMouseTrackingObserver;
    6566OBJC_CLASS WKRevealItemPresenter;
    6667OBJC_CLASS WKSafeBrowsingWarning;
     
    447448
    448449    NSTrackingArea *primaryTrackingArea() const { return m_primaryTrackingArea.get(); }
    449     void setPrimaryTrackingArea(NSTrackingArea *);
     450    void updatePrimaryTrackingAreaOptions(NSTrackingAreaOptions);
    450451
    451452    NSTrackingRectTag addTrackingRect(CGRect, id owner, void* userData, bool assumeInside);
     
    816817    bool m_allowsLinkPreview { true };
    817818
     819    RetainPtr<WKMouseTrackingObserver> m_mouseTrackingObserver;
    818820    RetainPtr<NSTrackingArea> m_primaryTrackingArea;
    819821
  • trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm

    r290712 r290743  
    182182#endif
    183183
     184// We use a WKMouseTrackingObserver as tracking area owner instead of the WKWebView. This is because WKWebView
     185// gets an implicit tracking area when it is first responder and we only want to process mouse events from our
     186// tracking area. Otherwise, it would lead to duplicate mouse events (rdar://88025610).
     187@interface WKMouseTrackingObserver : NSObject
     188@end
     189
     190@implementation WKMouseTrackingObserver {
     191    WeakPtr<WebKit::WebViewImpl> _impl;
     192}
     193
     194- (instancetype)initWithViewImpl:(WebKit::WebViewImpl&)impl
     195{
     196    if ((self = [super init]))
     197        _impl = impl;
     198    return self;
     199}
     200
     201- (void)mouseMoved:(NSEvent *)event
     202{
     203    if (_impl)
     204        _impl->mouseMoved(event);
     205}
     206
     207- (void)mouseEntered:(NSEvent *)event
     208{
     209    if (_impl)
     210        _impl->mouseEntered(event);
     211}
     212
     213- (void)mouseExited:(NSEvent *)event
     214{
     215    if (_impl)
     216        _impl->mouseExited(event);
     217}
     218
     219@end
     220
    184221#if ENABLE(IMAGE_ANALYSIS)
    185222
     
    14881525    , m_windowVisibilityObserver(adoptNS([[WKWindowVisibilityObserver alloc] initWithView:view impl:*this]))
    14891526    , m_accessibilitySettingsObserver(adoptNS([[WKAccessibilitySettingsObserver alloc] initWithImpl:*this]))
    1490     , m_primaryTrackingArea(adoptNS([[NSTrackingArea alloc] initWithRect:view.frame options:trackingAreaOptions() owner:view userInfo:nil]))
     1527    , m_mouseTrackingObserver(adoptNS([[WKMouseTrackingObserver alloc] initWithViewImpl:*this]))
     1528    , m_primaryTrackingArea(adoptNS([[NSTrackingArea alloc] initWithRect:view.frame options:trackingAreaOptions() owner:m_mouseTrackingObserver.get() userInfo:nil]))
    14911529{
    14921530    static_cast<PageClientImpl&>(*m_pageClient).setImpl(*this);
     
    38323870}
    38333871
    3834 void WebViewImpl::setPrimaryTrackingArea(NSTrackingArea *trackingArea)
    3835 {
     3872void WebViewImpl::updatePrimaryTrackingAreaOptions(NSTrackingAreaOptions options)
     3873{
     3874    auto trackingArea = adoptNS([[NSTrackingArea alloc] initWithRect:[m_view frame] options:options owner:m_mouseTrackingObserver.get() userInfo:nil]);
    38363875    [m_view removeTrackingArea:m_primaryTrackingArea.get()];
    38373876    m_primaryTrackingArea = trackingArea;
    3838     [m_view addTrackingArea:trackingArea];
     3877    [m_view addTrackingArea:trackingArea.get()];
     3878
    38393879}
    38403880
  • trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm

    r287163 r290743  
    720720        options |= NSTrackingActiveInKeyWindow;
    721721
    722     RetainPtr<NSTrackingArea> trackingArea = adoptNS([[NSTrackingArea alloc] initWithRect:[m_view frame] options:options owner:m_view userInfo:nil]);
    723     m_impl->setPrimaryTrackingArea(trackingArea.get());
     722    m_impl->updatePrimaryTrackingAreaOptions(options);
    724723}
    725724
  • trunk/Tools/ChangeLog

    r290739 r290743  
     12022-03-02  Chris Dumez  <cdumez@apple.com>
     2
     3        Mousemove events double-firing in Safari
     4        https://bugs.webkit.org/show_bug.cgi?id=237342
     5        <rdar://88025610>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        Call [WKWebView _simulateMouseMove:] SPI instead of calling [WKWebView mouseMoved:]
     10        since the latter calls are now being ignored.
     11
     12        * TestWebKitAPI/cocoa/TestWKWebView.mm:
     13        (-[TestWKWebView mouseMoveToPoint:withFlags:]):
     14        * TestWebKitAPI/mac/PlatformWebViewMac.mm:
     15        (TestWebKitAPI::PlatformWebView::simulateMouseMove):
     16        * WebKitTestRunner/mac/EventSenderProxy.mm:
     17        (WTR::EventSenderProxy::mouseMoveTo):
     18
    1192022-03-02  Sihui Liu  <sihui_liu@apple.com>
    220
  • trunk/Tools/TestWebKitAPI/cocoa/TestWKWebView.mm

    r290620 r290743  
    838838- (void)mouseMoveToPoint:(NSPoint)pointInWindow withFlags:(NSEventModifierFlags)flags
    839839{
    840     [self mouseMoved:[self _mouseEventWithType:NSEventTypeMouseMoved atLocation:pointInWindow flags:flags timestamp:self.eventTimestamp clickCount:0]];
     840    [self _simulateMouseMove:[self _mouseEventWithType:NSEventTypeMouseMoved atLocation:pointInWindow flags:flags timestamp:self.eventTimestamp clickCount:0]];
    841841}
    842842
  • trunk/Tools/TestWebKitAPI/mac/PlatformWebViewMac.mm

    r249327 r290743  
    196196{
    197197    NSEvent *event = [NSEvent mouseEventWithType:NSEventTypeMouseMoved location:NSMakePoint(x, y) modifierFlags:modifierFlagsForWKModifiers(modifiers) timestamp:GetCurrentEventTime() windowNumber:[m_window windowNumber] context:[NSGraphicsContext currentContext] eventNumber:0 clickCount:0 pressure:0];
    198     [m_view mouseMoved:event];
     198    [m_view _simulateMouseMove:event];
    199199}
    200200
  • trunk/Tools/WebKitTestRunner/mac/EventSenderProxy.mm

    r285409 r290743  
    3939#import <WebKit/WKPagePrivate.h>
    4040#import <WebKit/WKWebView.h>
     41#import <WebKit/WKWebViewPrivateForTestingMac.h>
    4142#import <pal/spi/cocoa/IOKitSPI.h>
    4243#import <wtf/RetainPtr.h>
     
    614615            [targetView mouseDragged:event];
    615616        else
    616             [targetView mouseMoved:event];
     617            [static_cast<WKWebView*>(targetView) _simulateMouseMove:event];
    617618        [NSApp _setCurrentEvent:nil];
    618619    } else
Note: See TracChangeset for help on using the changeset viewer.