Reviewed by Darin Adler.
authorap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 5 Feb 2011 00:28:05 +0000 (00:28 +0000)
committerap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 5 Feb 2011 00:28:05 +0000 (00:28 +0000)
        https://bugs.webkit.org/show_bug.cgi?id=53823
        Print layout sometimes seen on screen

        <rdar://problem/8948742> REGRESSION (WebKit2) - When I print a page, I visually see it re-layout
        <rdar://problem/8899389> REGRESSION(WebKit2): Wrong content can appear when print dialog is up

        * UIProcess/API/mac/PageClientImpl.mm: (WebKit::PageClientImpl::setAutodisplay): Removed a
        branch that didn't do anything useful.

        * UIProcess/API/mac/WKPrintingView.h:
        * UIProcess/API/mac/WKPrintingView.mm:
        (-[WKPrintingView _suspendAutodisplay]):
        (-[WKPrintingView _delayedResumeAutodisplayTimerFired]):
        (-[WKPrintingView _delayedResumeAutodisplay]):
        (-[WKPrintingView knowsPageRange:]):
        (-[WKPrintingView beginDocument]):
        (-[WKPrintingView endDocument]):
        When page setup changes, or when going from print preview to actual printing, AppKit calls
        -endDocument just to begin it again. Delay resuming autodisplay until the next run loop
        iteration.

        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
        (WebKit::WebChromeClient::invalidateContentsAndWindow):
        (WebKit::WebChromeClient::invalidateContentsForSlowScroll):
        Tightened it up from other side - we should never send pixels to UI process while in
        printing mode. This is not 100% reliable, because relayout doesn't happen immediately,
        and we can still have print layout in screen mode - but it helps.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@77701 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm
Source/WebKit2/UIProcess/API/mac/WKPrintingView.h
Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp

index 6b6b5af2fd3d67693f1d746a034a6a0e381b24d9..e2f679a96cb271f5b8bc653897faeeec6af60ca0 100644 (file)
@@ -1,3 +1,35 @@
+2011-02-04  Alexey Proskuryakov  <ap@apple.com>
+
+        Reviewed by Darin Adler.
+
+        https://bugs.webkit.org/show_bug.cgi?id=53823
+        Print layout sometimes seen on screen
+
+        <rdar://problem/8948742> REGRESSION (WebKit2) - When I print a page, I visually see it re-layout
+        <rdar://problem/8899389> REGRESSION(WebKit2): Wrong content can appear when print dialog is up
+
+        * UIProcess/API/mac/PageClientImpl.mm: (WebKit::PageClientImpl::setAutodisplay): Removed a
+        branch that didn't do anything useful.
+
+        * UIProcess/API/mac/WKPrintingView.h:
+        * UIProcess/API/mac/WKPrintingView.mm:
+        (-[WKPrintingView _suspendAutodisplay]):
+        (-[WKPrintingView _delayedResumeAutodisplayTimerFired]):
+        (-[WKPrintingView _delayedResumeAutodisplay]):
+        (-[WKPrintingView knowsPageRange:]):
+        (-[WKPrintingView beginDocument]):
+        (-[WKPrintingView endDocument]):
+        When page setup changes, or when going from print preview to actual printing, AppKit calls
+        -endDocument just to begin it again. Delay resuming autodisplay until the next run loop
+        iteration.
+
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::invalidateContentsAndWindow):
+        (WebKit::WebChromeClient::invalidateContentsForSlowScroll):
+        Tightened it up from other side - we should never send pixels to UI process while in
+        printing mode. This is not 100% reliable, because relayout doesn't happen immediately,
+        and we can still have print layout in screen mode - but it helps.
+
 2011-02-04  Sam Weinig  <sam@webkit.org>
 
         Reviewed by Mark Rowe.
index f2046d04e84ded284df19ed538fb424ed282730d..96f609a20c1e51d5b5161540f00652af9d1972ca 100644 (file)
@@ -373,8 +373,6 @@ void PageClientImpl::setAutodisplay(bool newState)
 {
     if (!newState && [[m_wkView window] isAutodisplay])
         [m_wkView displayIfNeeded];
-    else
-        [m_wkView setNeedsDisplay:NO];
     
     [[m_wkView window] setAutodisplay:newState];
 }
index 10c59c40484673d870cbe433b6f33f20d72e218d..1be94de97bcdfe8eb9a317d7faab53bbbefa8205 100644 (file)
@@ -53,6 +53,8 @@ namespace WebKit {
     BOOL _isPrintingFromSecondaryThread;
     Mutex _printingCallbackMutex;
     ThreadCondition _printingCallbackCondition;
+
+    NSTimer *_autodisplayResumeTimer;
 }
 
 - (id)initWithFrameProxy:(WebKit::WebFrameProxy*)frame;
index 4386dec5b89bdaa7585fb08432f17609c5fbcdfe..0645069ea4099c286731b73c7f5ffb4a1020f2ca 100644 (file)
@@ -57,6 +57,36 @@ NSString * const NSPrintInfoDidChangeNotification = @"NSPrintInfoDidChange";
     return YES;
 }
 
+- (void)_suspendAutodisplay
+{
+    // A drawRect: call on WKView causes a switch to screen mode, which is slow due to relayout, and we want to avoid that.
+    // Disabling autodisplay will prevent random updates from causing this, but resizing the window will still work.
+    if (_autodisplayResumeTimer) {
+        [_autodisplayResumeTimer invalidate];
+        _autodisplayResumeTimer = nil;
+    } else
+        _webFrame->page()->setAutodisplay(false);
+}
+
+- (void)_delayedResumeAutodisplayTimerFired
+{
+    ASSERT(isMainThread());
+    
+    _autodisplayResumeTimer = nil;
+    _webFrame->page()->setAutodisplay(true);
+}
+
+- (void)_delayedResumeAutodisplay
+{
+    // AppKit calls endDocument/beginDocument when print option change. We don't want to switch between print and screen mode just for that,
+    // and enabling autodisplay may result in switching into screen mode. So, autodisplay is only resumed on next run loop iteration.
+    if (!_autodisplayResumeTimer) {
+        _autodisplayResumeTimer = [NSTimer timerWithTimeInterval:0 target:self selector:@selector(_delayedResumeAutodisplayTimerFired) userInfo:nil repeats:NO];
+        // The timer must be scheduled on main thread, because printing thread may finish before it fires.
+        [[NSRunLoop mainRunLoop] addTimer:_autodisplayResumeTimer forMode:NSDefaultRunLoopMode];
+    }
+}
+
 - (void)_adjustPrintingMarginsForHeaderAndFooter
 {
     NSPrintInfo *info = [_printOperation printInfo];
@@ -297,6 +327,8 @@ static void prepareDataForPrintingOnSecondaryThread(void* untypedContext)
     if (!isMainThread())
         _isPrintingFromSecondaryThread = YES;
 
+    [self _suspendAutodisplay];
+    
     [self _adjustPrintingMarginsForHeaderAndFooter];
 
     if ([self _hasPageRects])
@@ -513,9 +545,11 @@ static void prepareDataForPrintingOnSecondaryThread(void* untypedContext)
     if (_isForcingPreviewUpdate)
         return;
 
+    LOG(View, "-[WKPrintingView beginDocument]");
+
     [super beginDocument];
 
-    _webFrame->page()->setAutodisplay(false);
+    [self _suspendAutodisplay];
 }
 
 - (void)endDocument
@@ -539,8 +573,8 @@ static void prepareDataForPrintingOnSecondaryThread(void* untypedContext)
     _latestExpectedPreviewCallback = 0;
     _expectedPrintCallback = 0;
 
-    _webFrame->page()->setAutodisplay(true);
-
+    [self _delayedResumeAutodisplay];
+    
     [super endDocument];
 }
 @end
index 75d493cab2bedde2d75f4b31ae1b04e790f83772..e5830222c7c972b1b057305ad823a809568b3940 100644 (file)
@@ -355,11 +355,15 @@ void WebChromeClient::invalidateWindow(const IntRect&, bool)
 
 void WebChromeClient::invalidateContentsAndWindow(const IntRect& rect, bool)
 {
+    if (m_page->corePage()->mainFrame()->document()->printing())
+        return;
     m_page->drawingArea()->setNeedsDisplay(rect);
 }
 
 void WebChromeClient::invalidateContentsForSlowScroll(const IntRect& rect, bool)
 {
+    if (m_page->corePage()->mainFrame()->document()->printing())
+        return;
     m_page->pageDidScroll();
     m_page->drawingArea()->setNeedsDisplay(rect);
 }