Reviewed by Darin Adler.
authorap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Jan 2011 22:45:56 +0000 (22:45 +0000)
committerap@apple.com <ap@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Jan 2011 22:45:56 +0000 (22:45 +0000)
        https://bugs.webkit.org/show_bug.cgi?id=52739
        Make it possible for a WebKit2 client to print headers and footers

        * UIProcess/API/C/WKPage.h:
        * UIProcess/WebPageProxy.cpp:
        (WebKit::WebPageProxy::headerHeight):
        (WebKit::WebPageProxy::footerHeight):
        (WebKit::WebPageProxy::drawHeader):
        (WebKit::WebPageProxy::drawFooter):
        * UIProcess/WebPageProxy.h:
        * UIProcess/WebUIClient.cpp:
        (WebKit::WebUIClient::headerHeight):
        (WebKit::WebUIClient::footerHeight):
        (WebKit::WebUIClient::drawHeader):
        (WebKit::WebUIClient::drawFooter):
        * UIProcess/WebUIClient.h:
        Pass UIClient calls through.

        * UIProcess/API/mac/WKView.mm:
        (currentPrintOperationScale): A helper to extract scale factor from the current NSPrintOperation.
        (-[WKView _adjustPrintingMarginsForHeaderAndFooter]): Copied from WebKit1. Change current
        print info to account for header and footer height as provided by the client.
        (-[WKView knowsPageRange:]): Call -[self _adjustPrintingMarginsForHeaderAndFooter].
        (-[WKView drawPageBorderWithSize:]): When AppKit asks to print page border, call the client
        to do that. Code adapted form WebKit1.

        * UIProcess/API/qt/qwkpage:
        (QWKPage::QWKPage): Added zeroes for new WKPageUIClient members to avoid breaking the build.

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/API/C/WKPage.h
Source/WebKit2/UIProcess/API/mac/WKView.mm
Source/WebKit2/UIProcess/API/qt/qwkpage.cpp
Source/WebKit2/UIProcess/WebPageProxy.cpp
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebUIClient.cpp
Source/WebKit2/UIProcess/WebUIClient.h
Tools/ChangeLog
Tools/MiniBrowser/mac/BrowserWindowController.m
Tools/WebKitTestRunner/TestController.cpp

index f267db1..b5684d7 100644 (file)
@@ -1,3 +1,36 @@
+2011-01-19  Alexey Proskuryakov  <ap@apple.com>
+
+        Reviewed by Darin Adler.
+
+        https://bugs.webkit.org/show_bug.cgi?id=52739
+        Make it possible for a WebKit2 client to print headers and footers
+
+        * UIProcess/API/C/WKPage.h:
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::headerHeight):
+        (WebKit::WebPageProxy::footerHeight):
+        (WebKit::WebPageProxy::drawHeader):
+        (WebKit::WebPageProxy::drawFooter):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebUIClient.cpp:
+        (WebKit::WebUIClient::headerHeight):
+        (WebKit::WebUIClient::footerHeight):
+        (WebKit::WebUIClient::drawHeader):
+        (WebKit::WebUIClient::drawFooter):
+        * UIProcess/WebUIClient.h:
+        Pass UIClient calls through.
+
+        * UIProcess/API/mac/WKView.mm:
+        (currentPrintOperationScale): A helper to extract scale factor from the current NSPrintOperation.
+        (-[WKView _adjustPrintingMarginsForHeaderAndFooter]): Copied from WebKit1. Change current
+        print info to account for header and footer height as provided by the client.
+        (-[WKView knowsPageRange:]): Call -[self _adjustPrintingMarginsForHeaderAndFooter].
+        (-[WKView drawPageBorderWithSize:]): When AppKit asks to print page border, call the client
+        to do that. Code adapted form WebKit1.
+
+        * UIProcess/API/qt/qwkpage:
+        (QWKPage::QWKPage): Added zeroes for new WKPageUIClient members to avoid breaking the build.
+
 2011-01-19  Jessie Berlin  <jberlin@apple.com>
 
         Reviewed by Darin Adler.
index 615eecc..6a007e7 100644 (file)
@@ -177,6 +177,10 @@ typedef void (*WKPageDidScrollCallback)(WKPageRef page, const void *clientInfo);
 typedef unsigned long long (*WKPageExceededDatabaseQuotaCallback)(WKPageRef page, WKFrameRef frame, WKSecurityOriginRef origin, WKStringRef databaseName, WKStringRef displayName, unsigned long long currentQuota, unsigned long long currentUsage, unsigned long long expectedUsage, const void *clientInfo);
 typedef void (*WKPageRunOpenPanelCallback)(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void *clientInfo);
 typedef void (*WKPageDecidePolicyForGeolocationPermissionRequestCallback)(WKPageRef page, WKFrameRef frame, WKSecurityOriginRef origin, WKGeolocationPermissionRequestRef permissionRequest, const void* clientInfo);
+typedef float (*WKPageHeaderHeight)(WKPageRef page, WKFrameRef frame, const void* clientInfo);
+typedef float (*WKPageFooterHeight)(WKPageRef page, WKFrameRef frame, const void* clientInfo);
+typedef void (*WKPageDrawHeader)(WKPageRef page, WKFrameRef frame, WKRect rect, const void* clientInfo);
+typedef void (*WKPageDrawFooter)(WKPageRef page, WKFrameRef frame, WKRect rect, const void* clientInfo);
 
 struct WKPageUIClient {
     int                                                                 version;
@@ -207,6 +211,10 @@ struct WKPageUIClient {
     WKPageExceededDatabaseQuotaCallback                                 exceededDatabaseQuota;
     WKPageRunOpenPanelCallback                                          runOpenPanel;
     WKPageDecidePolicyForGeolocationPermissionRequestCallback           decidePolicyForGeolocationPermissionRequest;
+    WKPageHeaderHeight                                                  headerHeight;
+    WKPageFooterHeight                                                  footerHeight;
+    WKPageDrawHeader                                                    drawHeader;
+    WKPageDrawFooter                                                    drawFooter;
 };
 typedef struct WKPageUIClient WKPageUIClient;
 
index a781d64..d634909 100644 (file)
@@ -95,6 +95,9 @@ typedef HashMap<String, ValidationVector> ValidationMap;
 
 }
 
+NSString* const WebKitOriginalTopPrintingMarginKey = @"WebKitOriginalTopMargin";
+NSString* const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMargin";
+
 @interface WKViewData : NSObject {
 @public
     OwnPtr<PageClientImpl> _pageClient;
@@ -1339,6 +1342,44 @@ static WebFrameProxy* frameBeingPrinted()
     return [[[[[NSPrintOperation currentOperation] printInfo] dictionary] objectForKey:PrintedFrameKey] webFrame];
 }
 
+static float currentPrintOperationScale()
+{
+    ASSERT([NSPrintOperation currentOperation]);
+    ASSERT([[[[NSPrintOperation currentOperation] printInfo] dictionary] objectForKey:NSPrintScalingFactor]);
+    return [[[[[NSPrintOperation currentOperation] printInfo] dictionary] objectForKey:NSPrintScalingFactor] floatValue];
+}
+
+- (void)_adjustPrintingMarginsForHeaderAndFooter
+{
+    NSPrintOperation *printOperation = [NSPrintOperation currentOperation];
+    NSPrintInfo *info = [printOperation printInfo];
+    NSMutableDictionary *infoDictionary = [info dictionary];
+
+    // We need to modify the top and bottom margins in the NSPrintInfo to account for the space needed by the
+    // header and footer. Because this method can be called more than once on the same NSPrintInfo (see 5038087),
+    // we stash away the unmodified top and bottom margins the first time this method is called, and we read from
+    // those stashed-away values on subsequent calls.
+    float originalTopMargin;
+    float originalBottomMargin;
+    NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey];
+    if (!originalTopMarginNumber) {
+        ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]);
+        originalTopMargin = [info topMargin];
+        originalBottomMargin = [info bottomMargin];
+        [infoDictionary setObject:[NSNumber numberWithFloat:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey];
+        [infoDictionary setObject:[NSNumber numberWithFloat:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey];
+    } else {
+        ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]);
+        ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]);
+        originalTopMargin = [originalTopMarginNumber floatValue];
+        originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] floatValue];
+    }
+    
+    float scale = currentPrintOperationScale();
+    [info setTopMargin:originalTopMargin + _data->_page->headerHeight(frameBeingPrinted()) * scale];
+    [info setBottomMargin:originalBottomMargin + _data->_page->footerHeight(frameBeingPrinted()) * scale];
+}
+
 - (NSPrintOperation *)printOperationWithPrintInfo:(NSPrintInfo *)printInfo forFrame:(WKFrameRef)frameRef
 {
     LOG(View, "Creating an NSPrintOperation for frame '%s'", toImpl(frameRef)->url().utf8().data());
@@ -1371,6 +1412,8 @@ static WebFrameProxy* frameBeingPrinted()
     if (frame->isMainFrame() && _data->_pdfViewController)
         return [super knowsPageRange:range];
 
+    [self _adjustPrintingMarginsForHeaderAndFooter];
+
     _data->_page->computePagesForPrinting(frame, PrintInfo([[NSPrintOperation currentOperation] printInfo]), _data->_printingPageRects, _data->_totalScaleFactorForPrinting);
 
     *range = NSMakeRange(1, _data->_printingPageRects.size());
@@ -1425,6 +1468,34 @@ static WebFrameProxy* frameBeingPrinted()
     CGContextRestoreGState(context);
 }
 
+- (void)drawPageBorderWithSize:(NSSize)borderSize
+{
+    ASSERT(NSEqualSizes(borderSize, [[[NSPrintOperation currentOperation] printInfo] paperSize]));    
+
+    // The header and footer rect height scales with the page, but the width is always
+    // all the way across the printed page (inset by printing margins).
+    NSPrintOperation *printOperation = [NSPrintOperation currentOperation];
+    NSPrintInfo *printInfo = [printOperation printInfo];
+    float scale = currentPrintOperationScale();
+    NSSize paperSize = [printInfo paperSize];
+    float headerFooterLeft = [printInfo leftMargin] / scale;
+    float headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin])) / scale;
+    WebFrameProxy* frame = frameBeingPrinted();
+    NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin] / scale - _data->_page->footerHeight(frame), headerFooterWidth, _data->_page->footerHeight(frame));
+    NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin]) / scale, headerFooterWidth, _data->_page->headerHeight(frame));
+
+    NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
+    [currentContext saveGraphicsState];
+    NSRectClip(headerRect);
+    _data->_page->drawHeader(frame, headerRect);
+    [currentContext restoreGraphicsState];
+
+    [currentContext saveGraphicsState];
+    NSRectClip(footerRect);
+    _data->_page->drawFooter(frame, footerRect);
+    [currentContext restoreGraphicsState];
+}
+
 // FIXME 3491344: This is an AppKit-internal method that we need to override in order
 // to get our shrink-to-fit to work with a custom pagination scheme. We can do this better
 // if AppKit makes it SPI/API.
index 08d7852..f645db8 100644 (file)
@@ -445,7 +445,11 @@ QWKPage::QWKPage(QWKContext* context)
         0,  /* pageDidScroll */
         0,  /* exceededDatabaseQuota */
         0,  /* runOpenPanel */
-        0   /* decidePolicyForGeolocationPermissionRequest */
+        0,  /* decidePolicyForGeolocationPermissionRequest */
+        0,  /* headerHeight */
+        0,  /* footerHeight */
+        0,  /* drawHeader */
+        0   /* drawFooter */
     };
     WKPageSetPageUIClient(pageRef(), &uiClient);
 }
index b51581a..f76972d 100644 (file)
@@ -2336,6 +2336,26 @@ void WebPageProxy::requestGeolocationPermissionForFrame(uint64_t geolocationID,
         request->deny();
 }
 
+float WebPageProxy::headerHeight(WebFrameProxy* frame)
+{
+    return m_uiClient.headerHeight(this, frame);
+}
+
+float WebPageProxy::footerHeight(WebFrameProxy* frame)
+{
+    return m_uiClient.footerHeight(this, frame);
+}
+
+void WebPageProxy::drawHeader(WebFrameProxy* frame, const WebCore::FloatRect& rect)
+{
+    m_uiClient.drawHeader(this, frame, rect);
+}
+
+void WebPageProxy::drawFooter(WebFrameProxy* frame, const WebCore::FloatRect& rect)
+{
+    m_uiClient.drawFooter(this, frame, rect);
+}
+
 void WebPageProxy::didFinishLoadingDataForCustomRepresentation(const CoreIPC::DataReference& dataReference)
 {
     m_pageClient->didFinishLoadingDataForCustomRepresentation(dataReference);
index 374c9f6..8456c9c 100644 (file)
@@ -274,6 +274,11 @@ public:
     void getWebArchiveOfFrame(WebFrameProxy*, PassRefPtr<DataCallback>);
     void runJavaScriptInMainFrame(const String&, PassRefPtr<StringCallback>);
 
+    float headerHeight(WebFrameProxy*);
+    float footerHeight(WebFrameProxy*);
+    void drawHeader(WebFrameProxy*, const WebCore::FloatRect&);
+    void drawFooter(WebFrameProxy*, const WebCore::FloatRect&);
+
     void receivedPolicyDecision(WebCore::PolicyAction, WebFrameProxy*, uint64_t listenerID);
 
     void backForwardRemovedItem(uint64_t itemID);
index e95af34..90c7e56 100644 (file)
@@ -273,4 +273,36 @@ bool WebUIClient::decidePolicyForGeolocationPermissionRequest(WebPageProxy* page
     return true;
 }
 
+float WebUIClient::headerHeight(WebPageProxy* page, WebFrameProxy* frame)
+{
+    if (!m_client.headerHeight)
+        return 0;
+
+    return m_client.headerHeight(toAPI(page), toAPI(frame), m_client.clientInfo);
+}
+
+float WebUIClient::footerHeight(WebPageProxy* page, WebFrameProxy* frame)
+{
+    if (!m_client.footerHeight)
+        return 0;
+
+    return m_client.footerHeight(toAPI(page), toAPI(frame), m_client.clientInfo);
+}
+
+void WebUIClient::drawHeader(WebPageProxy* page, WebFrameProxy* frame, const WebCore::FloatRect& rect)
+{
+    if (!m_client.drawHeader)
+        return;
+
+    m_client.drawHeader(toAPI(page), toAPI(frame), toAPI(rect), m_client.clientInfo);
+}
+
+void WebUIClient::drawFooter(WebPageProxy* page, WebFrameProxy* frame, const WebCore::FloatRect& rect)
+{
+    if (!m_client.drawFooter)
+        return;
+
+    m_client.drawFooter(toAPI(page), toAPI(frame), toAPI(rect), m_client.clientInfo);
+}
+
 } // namespace WebKit
index a25b37f..802848c 100644 (file)
@@ -86,6 +86,12 @@ public:
 
     bool runOpenPanel(WebPageProxy*, WebFrameProxy*, const WebOpenPanelParameters::Data&, WebOpenPanelResultListenerProxy*);
     bool decidePolicyForGeolocationPermissionRequest(WebPageProxy*, WebFrameProxy*, WebSecurityOrigin*, GeolocationPermissionRequestProxy*);
+
+    // Printing.
+    float headerHeight(WebPageProxy*, WebFrameProxy*);
+    float footerHeight(WebPageProxy*, WebFrameProxy*);
+    void drawHeader(WebPageProxy*, WebFrameProxy*, const WebCore::FloatRect&);
+    void drawFooter(WebPageProxy*, WebFrameProxy*, const WebCore::FloatRect&);
 };
 
 } // namespace WebKit
index 18c33cf..d5a0e76 100644 (file)
@@ -1,3 +1,18 @@
+2011-01-19  Alexey Proskuryakov  <ap@apple.com>
+
+        Reviewed by Darin Adler.
+
+        https://bugs.webkit.org/show_bug.cgi?id=52739
+        Make it possible for a WebKit2 client to print headers and footers
+
+        Added dummy implementations for new printing UIClient calls.
+
+        * MiniBrowser/mac/BrowserWindowController.m:
+        (-[BrowserWindowController awakeFromNib]):
+        * WebKitTestRunner/TestController.cpp:
+        (WTR::createOtherPage):
+        (WTR::TestController::initialize):
+
 2011-01-19  Dirk Pranke  <dpranke@chromium.org>
 
         Reviewed by Ojan Vafai.
index e761624..7331957 100644 (file)
@@ -639,6 +639,10 @@ static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParameters
         0,          /* exceededDatabaseQuota */
         runOpenPanel,
         0,          /* decidePolicyForGeolocationPermissionRequest */
+        0, // headerHeight
+        0, // footerHeight
+        0, // drawHeader
+        0, // drawFooter
     };
     WKPageSetPageUIClient(_webView.pageRef, &uiClient);
 }
index 2557424..05eda8e 100644 (file)
@@ -146,6 +146,10 @@ static WKPageRef createOtherPage(WKPageRef oldPage, WKDictionaryRef, WKEventModi
         0, // exceededDatabaseQuota
         0, // runOpenPanel
         0, // decidePolicyForGeolocationPermissionRequest
+        0, // headerHeight
+        0, // footerHeight
+        0, // drawHeader
+        0, // drawFooter
     };
     WKPageSetPageUIClient(newPage, &otherPageUIClient);
 
@@ -251,6 +255,10 @@ void TestController::initialize(int argc, const char* argv[])
         0, // exceededDatabaseQuota
         0, // runOpenPanel
         0, // decidePolicyForGeolocationPermissionRequest
+        0, // headerHeight
+        0, // footerHeight
+        0, // drawHeader
+        0, // drawFooter
     };
     WKPageSetPageUIClient(m_mainWebView->page(), &pageUIClient);