Changeset 265091 in webkit


Ignore:
Timestamp:
Jul 30, 2020 11:25:47 AM (4 years ago)
Author:
timothy_horton@apple.com
Message:

Web content gets stuck in an inactive state (no cursor updates or text insertion caret) when activating a tab with a thumbnail visible
https://bugs.webkit.org/show_bug.cgi?id=214962
<rdar://problem/65670984>

Reviewed by Wenson Hsieh.

Source/WebCore:

New API test: WebKit.WKThumbnailViewResetsViewStateWhenUnparented

  • testing/Internals.cpp:

(WebCore::Internals::isPageActive const):

  • testing/Internals.h:
  • testing/Internals.idl:

Add a "view window is active" getter.

Source/WebKit:

  • UIProcess/Cocoa/WebViewImpl.mm:

(WebKit::WebViewImpl::setThumbnailView):
When WKThumbnailView is unparented, invalidate all activity state bits.
We do this because many of the functions that compute activity state bits
use the WKThumbnailView's window while it is parented. When it is unparented,
and we switch back to using the WKWebView's window, we mustn't get stuck
with activity state bits from WKThumbnailView's window.

This was particularly problematic in the case of the WKThumbnailViews
used for tab hover previews, because that window is not key, so we'd get
stuck with the inactive-window state, resulting in a lack of cursor updates,
a hidden text caret, the wrong selection color, etc.

  • UIProcess/mac/PageClientImplMac.mm:

(WebKit::PageClientImpl::isViewWindowActive):
While writing the API test for this, I noticed that isViewWindowActive
returns YES if there is no key window AND WKWebView is unparented
([NSApp keyWindow] == activeWindow() == nil).
This seems completely insane (how can the window be active if it doesn't
exist?), and breaks the test, so ensure that we only say YES if we actually
have a window.

Tools:

  • TestWebKitAPI/Tests/WebKit/WKThumbnailView.mm:

(TestWebKitAPI::TEST):
Add a test ensuring that we go back to the active-window state after
unparenting a WKThumbnailView that was installed in an inactive window.

(-[WKThumbnailViewDelegate webView:didFinishNavigation:]): Deleted.

  • TestWebKitAPI/mac/OffscreenWindow.h:
  • TestWebKitAPI/mac/OffscreenWindow.mm:

(-[OffscreenWindow initWithSize:]):
(-[OffscreenWindow initWithSize:isKeyWindow:]):
(-[OffscreenWindow isKeyWindow]):

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r265088 r265091  
     12020-07-30  Tim Horton  <timothy_horton@apple.com>
     2
     3        Web content gets stuck in an inactive state (no cursor updates or text insertion caret) when activating a tab with a thumbnail visible
     4        https://bugs.webkit.org/show_bug.cgi?id=214962
     5        <rdar://problem/65670984>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        New API test: WebKit.WKThumbnailViewResetsViewStateWhenUnparented
     10
     11        * testing/Internals.cpp:
     12        (WebCore::Internals::isPageActive const):
     13        * testing/Internals.h:
     14        * testing/Internals.idl:
     15        Add a "view window is active" getter.
     16
    1172020-07-30  Antoine Quint  <graouts@webkit.org>
    218
  • trunk/Source/WebCore/testing/Internals.cpp

    r264975 r265091  
    51725172}
    51735173
     5174bool Internals::isPageActive() const
     5175{
     5176    auto* document = contextDocument();
     5177    if (!document || !document->page())
     5178        return false;
     5179    auto& page = *document->page();
     5180    return page.activityState().contains(ActivityState::WindowIsActive);
     5181}
     5182
    51745183#if ENABLE(WEB_RTC)
    51755184void Internals::setH264HardwareEncoderAllowed(bool allowed)
  • trunk/Source/WebCore/testing/Internals.h

    r264975 r265091  
    773773    void setPageVisibility(bool isVisible);
    774774    void setPageIsFocusedAndActive(bool);
    775 
     775    bool isPageActive() const;
    776776
    777777#if ENABLE(WEB_RTC)
  • trunk/Source/WebCore/testing/Internals.idl

    r264975 r265091  
    797797    void setPageVisibility(boolean isVisible);
    798798    void setPageIsFocusedAndActive(boolean isFocused);
     799    boolean isPageActive();
    799800
    800801    [Conditional=WEB_RTC] void setH264HardwareEncoderAllowed(boolean allowed);
  • trunk/Source/WebKit/ChangeLog

    r265089 r265091  
     12020-07-30  Tim Horton  <timothy_horton@apple.com>
     2
     3        Web content gets stuck in an inactive state (no cursor updates or text insertion caret) when activating a tab with a thumbnail visible
     4        https://bugs.webkit.org/show_bug.cgi?id=214962
     5        <rdar://problem/65670984>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        * UIProcess/Cocoa/WebViewImpl.mm:
     10        (WebKit::WebViewImpl::setThumbnailView):
     11        When WKThumbnailView is unparented, invalidate all activity state bits.
     12        We do this because many of the functions that compute activity state bits
     13        use the WKThumbnailView's window while it is parented. When it is unparented,
     14        and we switch back to using the WKWebView's window, we mustn't get stuck
     15        with activity state bits from WKThumbnailView's window.
     16
     17        This was particularly problematic in the case of the WKThumbnailViews
     18        used for tab hover previews, because that window is not key, so we'd get
     19        stuck with the inactive-window state, resulting in a lack of cursor updates,
     20        a hidden text caret, the wrong selection color, etc.
     21
     22        * UIProcess/mac/PageClientImplMac.mm:
     23        (WebKit::PageClientImpl::isViewWindowActive):
     24        While writing the API test for this, I noticed that isViewWindowActive
     25        returns YES if there is no key window AND WKWebView is unparented
     26        ([NSApp keyWindow] == activeWindow() == nil).
     27        This seems completely insane (how can the window be active if it doesn't
     28        exist?), and breaks the test, so ensure that we only say YES if we actually
     29        have a window.
     30
    1312020-07-30  Peng Liu  <peng.liu6@apple.com>
    232
  • trunk/Source/WebKit/UIProcess/Cocoa/WebViewImpl.mm

    r264585 r265091  
    38553855    if (thumbnailView)
    38563856        updateThumbnailViewLayer();
    3857     else
     3857    else {
    38583858        setAcceleratedCompositingRootLayer(m_rootLayer.get());
     3859        m_page->activityStateDidChange(WebCore::ActivityState::allFlags());
     3860    }
    38593861}
    38603862
  • trunk/Source/WebKit/UIProcess/mac/PageClientImplMac.mm

    r263825 r265091  
    161161    ASSERT(hasProcessPrivilege(ProcessPrivilege::CanCommunicateWithWindowServer));
    162162    NSWindow *activeViewWindow = activeWindow();
    163     return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
     163    return activeViewWindow.isKeyWindow || (activeViewWindow && [NSApp keyWindow] == activeViewWindow);
    164164}
    165165
  • trunk/Tools/ChangeLog

    r265082 r265091  
     12020-07-30  Tim Horton  <timothy_horton@apple.com>
     2
     3        Web content gets stuck in an inactive state (no cursor updates or text insertion caret) when activating a tab with a thumbnail visible
     4        https://bugs.webkit.org/show_bug.cgi?id=214962
     5        <rdar://problem/65670984>
     6
     7        Reviewed by Wenson Hsieh.
     8
     9        * TestWebKitAPI/Tests/WebKit/WKThumbnailView.mm:
     10        (TestWebKitAPI::TEST):
     11        Add a test ensuring that we go back to the active-window state after
     12        unparenting a WKThumbnailView that was installed in an inactive window.
     13
     14        (-[WKThumbnailViewDelegate webView:didFinishNavigation:]): Deleted.
     15        * TestWebKitAPI/mac/OffscreenWindow.h:
     16        * TestWebKitAPI/mac/OffscreenWindow.mm:
     17        (-[OffscreenWindow initWithSize:]):
     18        (-[OffscreenWindow initWithSize:isKeyWindow:]):
     19        (-[OffscreenWindow isKeyWindow]):
     20
    1212020-07-30  Jonathan Bedard  <jbedard@apple.com>
    222
  • trunk/Tools/TestWebKitAPI/Tests/WebKit/WKThumbnailView.mm

    r260366 r265091  
    2929
    3030#import "JavaScriptTest.h"
     31#import "OffscreenWindow.h"
    3132#import "PlatformUtilities.h"
    3233#import "PlatformWebView.h"
    3334#import "TestWKWebView.h"
     35#import "WKWebViewConfigurationExtras.h"
    3436#import <WebKit/WKViewPrivate.h>
    3537#import <WebKit/_WKThumbnailView.h>
     
    5860
    5961    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    60 }
    61 
    62 @end
    63 
    64 
    65 @interface WKThumbnailViewDelegate : NSObject <WKNavigationDelegate>
    66 @end
    67 
    68 @implementation WKThumbnailViewDelegate
    69 
    70 - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
    71 {
    72     didFinishLoad = true;
    7362}
    7463
     
    200189    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
    201190    WKPageSetCustomBackingScaleFactor([webView _pageForTesting], 1);
    202     auto delegate = adoptNS([[WKThumbnailViewDelegate alloc] init]);
    203     [webView setNavigationDelegate:delegate.get()];
    204     [webView  loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"lots-of-text" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
    205     Util::run(&didFinishLoad);
     191    [webView synchronouslyLoadTestPageNamed:@"lots-of-text"];
    206192
    207193    RetainPtr<_WKThumbnailView> thumbnailView = adoptNS([[_WKThumbnailView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) fromWKWebView:webView.get()]);
     
    242228    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600)]);
    243229    WKPageSetCustomBackingScaleFactor([webView _pageForTesting], 1);
    244     auto delegate = adoptNS([[WKThumbnailViewDelegate alloc] init]);
    245     [webView setNavigationDelegate:delegate.get()];
    246     [webView  loadRequest:[NSURLRequest requestWithURL:[[NSBundle mainBundle] URLForResource:@"lots-of-text" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"]]];
    247     Util::run(&didFinishLoad);
     230    [webView synchronouslyLoadTestPageNamed:@"lots-of-text"];
    248231
    249232    auto thumbnailView = adoptNS([[_WKThumbnailView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) fromWKWebView:webView.get()]);
     
    286269}
    287270
     271TEST(WebKit, WKThumbnailViewResetsViewStateWhenUnparented)
     272{
     273    WKWebViewConfiguration *configuration = [WKWebViewConfiguration _test_configurationWithTestPlugInClassName:@"WebProcessPlugInWithInternals" configureJSCForTesting:YES];
     274    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration]);
     275    [webView removeFromSuperview];
     276    [webView synchronouslyLoadTestPageNamed:@"lots-of-text"];
     277
     278    auto thumbnailView = adoptNS([[_WKThumbnailView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) fromWKWebView:webView.get()]);
     279
     280    auto observer = adoptNS([[SnapshotSizeObserver alloc] init]);
     281
     282    [thumbnailView addObserver:observer.get() forKeyPath:@"snapshotSize" options:NSKeyValueObservingOptionNew context:snapshotSizeChangeKVOContext];
     283
     284    RetainPtr<NSWindow> otherWindow = adoptNS([[OffscreenWindow alloc] initWithSize:CGSizeMake(100, 100) isKeyWindow:NO]);
     285    [[otherWindow contentView] addSubview:thumbnailView.get()];
     286    [otherWindow orderFront:nil];
     287    [[webView hostWindow] makeKeyAndOrderFront:nil];
     288    Util::run(&didTakeSnapshot);
     289    didTakeSnapshot = false;
     290    EXPECT_FALSE([thumbnailView layer].contents == nil);
     291    [webView waitForNextPresentationUpdate];
     292    EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"window.internals.isPageActive()"] boolValue]);
     293
     294    [webView addToTestWindow];
     295    [webView waitForNextPresentationUpdate];
     296    EXPECT_FALSE([[webView objectByEvaluatingJavaScript:@"window.internals.isPageActive()"] boolValue]);
     297
     298    [thumbnailView removeFromSuperview];
     299    [webView waitForNextPresentationUpdate];
     300    EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"window.internals.isPageActive()"] boolValue]);
     301
     302    [thumbnailView removeObserver:observer.get() forKeyPath:@"snapshotSize" context:snapshotSizeChangeKVOContext];
     303}
     304
     305
    288306} // namespace TestWebKitAPI
    289307
    290 #endif
     308#endif // PLATFORM(MAC)
  • trunk/Tools/TestWebKitAPI/mac/OffscreenWindow.h

    r260366 r265091  
    3535
    3636- (instancetype)initWithSize:(CGSize)size;
     37- (instancetype)initWithSize:(CGSize)size isKeyWindow:(BOOL)isKeyWindow;
    3738
    3839@end
  • trunk/Tools/TestWebKitAPI/mac/OffscreenWindow.mm

    r240010 r265091  
    2727#import "OffscreenWindow.h"
    2828
    29 @implementation OffscreenWindow
     29@implementation OffscreenWindow {
     30    BOOL _isKeyWindow;
     31}
    3032
    3133- (instancetype)initWithSize:(CGSize)size
    3234{
     35    return [self initWithSize:size isKeyWindow:YES];
     36}
     37
     38- (instancetype)initWithSize:(CGSize)size isKeyWindow:(BOOL)isKeyWindow
     39{
     40    _isKeyWindow = isKeyWindow;
     41
    3342    NSRect rect = NSMakeRect(0, 0, size.width, size.height);
    3443    NSRect windowRect = NSOffsetRect(rect, -10000, [(NSScreen *)[[NSScreen screens] objectAtIndex:0] frame].size.height - rect.size.height + 10000);
     
    4756- (BOOL)isKeyWindow
    4857{
    49     return YES;
     58    return _isKeyWindow;
    5059}
    5160
Note: See TracChangeset for help on using the changeset viewer.