diff options
author | Steve Block <steveblock@google.com> | 2011-05-18 13:36:51 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-24 15:38:28 +0100 |
commit | 2fc2651226baac27029e38c9d6ef883fa32084db (patch) | |
tree | e396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebKit2/UIProcess/API/mac | |
parent | b3725cedeb43722b3b175aaeff70552e562d2c94 (diff) | |
download | external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2 |
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebKit2/UIProcess/API/mac')
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.mm | 7 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/PDFViewController.mm | 1 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/PageClientImpl.h | 11 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm | 50 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKPrintingView.h | 61 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm | 585 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm | 5 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKView.h | 3 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKView.mm | 693 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKViewInternal.h | 9 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h | 36 |
11 files changed, 1168 insertions, 293 deletions
diff --git a/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.mm b/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.mm index 5b93a9e..e622c9d 100644 --- a/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.mm +++ b/Source/WebKit2/UIProcess/API/mac/FindIndicatorWindow.mm @@ -23,10 +23,11 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include "FindIndicatorWindow.h" +#import "config.h" +#import "FindIndicatorWindow.h" -#include "FindIndicator.h" -#include <WebCore/GraphicsContext.h> +#import "FindIndicator.h" +#import <WebCore/GraphicsContext.h> static const double bounceAnimationDuration = 0.12; static const double timeBeforeFadeStarts = bounceAnimationDuration + 0.2; diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm index a92c2d4..6ab425d 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm @@ -23,6 +23,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#import "config.h" #import "PDFViewController.h" #import "DataReference.h" diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h index 625b8f6..b557c1a 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h @@ -60,6 +60,7 @@ private: virtual bool isViewInWindow(); virtual void processDidCrash(); + virtual void pageClosed(); virtual void didRelaunchProcess(); virtual void takeFocus(bool direction); virtual void toolTipChanged(const String& oldToolTip, const String& newToolTip); @@ -75,23 +76,29 @@ private: virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&); virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&); - virtual void didNotHandleKeyEvent(const NativeWebKeyboardEvent&); + virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&, bool wasEventHandled); virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*); virtual PassRefPtr<WebContextMenuProxy> createContextMenuProxy(WebPageProxy*); void setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut); + virtual void enterAcceleratedCompositingMode(const LayerTreeContext&); + virtual void exitAcceleratedCompositingMode(); + #if USE(ACCELERATED_COMPOSITING) virtual void pageDidEnterAcceleratedCompositing(); virtual void pageDidLeaveAcceleratedCompositing(); #endif - virtual void accessibilityChildTokenReceived(const CoreIPC::DataReference&); + virtual void accessibilityWebProcessTokenReceived(const CoreIPC::DataReference&); virtual void setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled); + virtual void setAutodisplay(bool); virtual CGContextRef containingWindowGraphicsContext(); + virtual void didChangeScrollbarsForMainFrame() const; + virtual void didCommitLoadForMainFrame(bool useCustomRepresentation); virtual void didFinishLoadingDataForCustomRepresentation(const CoreIPC::DataReference&); diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm index 60be5bc..fd70a67 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm @@ -23,11 +23,12 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#import "NativeWebKeyboardEvent.h" +#import "config.h" #import "PageClientImpl.h" #import "DataReference.h" #import "FindIndicator.h" +#import "NativeWebKeyboardEvent.h" #import "WKAPICast.h" #import "WKStringCF.h" #import "WKViewInternal.h" @@ -43,6 +44,10 @@ #import <wtf/text/CString.h> #import <wtf/text/WTFString.h> +@interface NSApplication (WebNSApplicationDetails) +- (NSCursor *)_cursorRectCursor; +@end + using namespace WebCore; @interface WebEditCommandObjC : NSObject @@ -177,6 +182,11 @@ void PageClientImpl::processDidCrash() { [m_wkView _processDidCrash]; } + +void PageClientImpl::pageClosed() +{ + [m_wkView _pageClosed]; +} void PageClientImpl::didRelaunchProcess() { @@ -195,7 +205,8 @@ void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newT void PageClientImpl::setCursor(const WebCore::Cursor& cursor) { - [m_wkView _setCursor:cursor.platformCursor()]; + if (![NSApp _cursorRectCursor]) + [m_wkView _setCursor:cursor.platformCursor()]; } void PageClientImpl::setViewportArguments(const WebCore::ViewportArguments&) @@ -297,10 +308,14 @@ FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect) return [m_wkView _convertToUserSpace:rect]; } -void PageClientImpl::didNotHandleKeyEvent(const NativeWebKeyboardEvent& event) +void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool wasEventHandled) { NSEvent* nativeEvent = event.nativeEvent(); - if ([nativeEvent type] == NSKeyDown) { + if ([nativeEvent type] != NSKeyDown) + return; + if (wasEventHandled) + [NSCursor setHiddenUntilMouseMoves:YES]; + else { [m_wkView _setEventBeingResent:nativeEvent]; [[NSApplication sharedApplication] sendEvent:nativeEvent]; } @@ -321,13 +336,23 @@ void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, b [m_wkView _setFindIndicator:findIndicator fadeOut:fadeOut]; } -void PageClientImpl::accessibilityChildTokenReceived(const CoreIPC::DataReference& data) +void PageClientImpl::accessibilityWebProcessTokenReceived(const CoreIPC::DataReference& data) { NSData* remoteToken = [NSData dataWithBytes:data.data() length:data.size()]; - [m_wkView _setAccessibilityChildToken:remoteToken]; + [m_wkView _setAccessibilityWebProcessToken:remoteToken]; } #if USE(ACCELERATED_COMPOSITING) +void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext) +{ + [m_wkView _enterAcceleratedCompositingMode:layerTreeContext]; +} + +void PageClientImpl::exitAcceleratedCompositingMode() +{ + [m_wkView _exitAcceleratedCompositingMode]; +} + void PageClientImpl::pageDidEnterAcceleratedCompositing() { [m_wkView _pageDidEnterAcceleratedCompositing]; @@ -344,11 +369,24 @@ void PageClientImpl::setComplexTextInputEnabled(uint64_t pluginComplexTextInputI [m_wkView _setComplexTextInputEnabled:complexTextInputEnabled pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier]; } +void PageClientImpl::setAutodisplay(bool newState) +{ + if (!newState && [[m_wkView window] isAutodisplay]) + [m_wkView displayIfNeeded]; + + [[m_wkView window] setAutodisplay:newState]; +} + CGContextRef PageClientImpl::containingWindowGraphicsContext() { return static_cast<CGContextRef>([[[m_wkView window] graphicsContext] graphicsPort]); } +void PageClientImpl::didChangeScrollbarsForMainFrame() const +{ + [m_wkView _didChangeScrollbarsForMainFrame]; +} + void PageClientImpl::didCommitLoadForMainFrame(bool useCustomRepresentation) { [m_wkView _setPageHasCustomRepresentation:useCustomRepresentation]; diff --git a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h new file mode 100644 index 0000000..3f7a692 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import <WebCore/IntRectHash.h> +#import <wtf/RetainPtr.h> + +@class WKPrintingViewData; + +namespace WebKit { + class WebFrameProxy; +} + +@interface WKPrintingView : NSView { +@public + NSPrintOperation *_printOperation; // WKPrintingView is owned by the operation. + + RefPtr<WebKit::WebFrameProxy> _webFrame; + Vector<WebCore::IntRect> _printingPageRects; + double _totalScaleFactorForPrinting; + HashMap<WebCore::IntRect, Vector<uint8_t> > _pagePreviews; + + Vector<uint8_t> _printedPagesData; + RetainPtr<CGPDFDocumentRef> _printedPagesPDFDocument; + + uint64_t _expectedComputedPagesCallback; + HashMap<uint64_t, WebCore::IntRect> _expectedPreviewCallbacks; + uint64_t _latestExpectedPreviewCallback; + uint64_t _expectedPrintCallback; + + BOOL _isPrintingFromSecondaryThread; + Mutex _printingCallbackMutex; + ThreadCondition _printingCallbackCondition; + + NSTimer *_autodisplayResumeTimer; +} + +- (id)initWithFrameProxy:(WebKit::WebFrameProxy*)frame; + +@end diff --git a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm new file mode 100644 index 0000000..28ba153 --- /dev/null +++ b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "config.h" +#import "WKPrintingView.h" + +#import "Logging.h" +#import "PrintInfo.h" +#import "WebData.h" +#import "WebPageProxy.h" + +using namespace WebKit; +using namespace WebCore; + +NSString * const WebKitOriginalTopPrintingMarginKey = @"WebKitOriginalTopMargin"; +NSString * const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMargin"; + +NSString * const NSPrintInfoDidChangeNotification = @"NSPrintInfoDidChange"; + +static BOOL isForcingPreviewUpdate; + +@implementation WKPrintingView + +- (id)initWithFrameProxy:(WebFrameProxy*)frame +{ + self = [super init]; // No frame rect to pass to NSView. + if (!self) + return nil; + + _webFrame = frame; + + return self; +} + +- (BOOL)isFlipped +{ + 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]; + 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. + double originalTopMargin; + double originalBottomMargin; + NSNumber *originalTopMarginNumber = [infoDictionary objectForKey:WebKitOriginalTopPrintingMarginKey]; + if (!originalTopMarginNumber) { + ASSERT(![infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey]); + originalTopMargin = [info topMargin]; + originalBottomMargin = [info bottomMargin]; + [infoDictionary setObject:[NSNumber numberWithDouble:originalTopMargin] forKey:WebKitOriginalTopPrintingMarginKey]; + [infoDictionary setObject:[NSNumber numberWithDouble:originalBottomMargin] forKey:WebKitOriginalBottomPrintingMarginKey]; + } else { + ASSERT([originalTopMarginNumber isKindOfClass:[NSNumber class]]); + ASSERT([[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] isKindOfClass:[NSNumber class]]); + originalTopMargin = [originalTopMarginNumber doubleValue]; + originalBottomMargin = [[infoDictionary objectForKey:WebKitOriginalBottomPrintingMarginKey] doubleValue]; + } + + CGFloat scale = [info scalingFactor]; + [info setTopMargin:originalTopMargin + _webFrame->page()->headerHeight(_webFrame.get()) * scale]; + [info setBottomMargin:originalBottomMargin + _webFrame->page()->footerHeight(_webFrame.get()) * scale]; +} + +- (BOOL)_isPrintingPreview +{ + // <rdar://problem/8901041> Please add an API returning whether the current print operation is for preview. + // Assuming that if NSPrintOperation is allowed to spawn a thread for printing, it will. Print preview doesn't spawn a thread. + return !_isPrintingFromSecondaryThread; +} + +- (void)_updatePreview +{ + // <rdar://problem/8900923> Please add an API to force print preview update. + ASSERT(!isForcingPreviewUpdate); + isForcingPreviewUpdate = YES; + [[NSNotificationCenter defaultCenter] postNotificationName:NSPrintInfoDidChangeNotification object:nil]; + isForcingPreviewUpdate = NO; +} + +- (BOOL)_hasPageRects +{ + // WebCore always prints at least one page. + return !_printingPageRects.isEmpty(); +} + +- (NSUInteger)_firstPrintedPageNumber +{ + // Need to directly access the dictionary because -[NSPrintOperation pageRange] verifies pagination, potentially causing recursion. + return [[[[_printOperation printInfo] dictionary] objectForKey:NSPrintFirstPage] unsignedIntegerValue]; +} + +- (NSUInteger)_lastPrintedPageNumber +{ + ASSERT([self _hasPageRects]); + + // Need to directly access the dictionary because -[NSPrintOperation pageRange] verifies pagination, potentially causing recursion. + NSUInteger firstPage = [[[[_printOperation printInfo] dictionary] objectForKey:NSPrintFirstPage] unsignedIntegerValue]; + NSUInteger lastPage = [[[[_printOperation printInfo] dictionary] objectForKey:NSPrintLastPage] unsignedIntegerValue]; + if (lastPage - firstPage >= _printingPageRects.size()) + return _printingPageRects.size(); + return lastPage; +} + +- (uint64_t)_expectedPreviewCallbackForRect:(const IntRect&)rect +{ + for (HashMap<uint64_t, WebCore::IntRect>::iterator iter = _expectedPreviewCallbacks.begin(); iter != _expectedPreviewCallbacks.end(); ++iter) { + if (iter->second == rect) + return iter->first; + } + return 0; +} + +struct IPCCallbackContext { + RetainPtr<WKPrintingView> view; + uint64_t callbackID; +}; + +static void pageDidDrawToPDF(WKDataRef dataRef, WKErrorRef, void* untypedContext) +{ + ASSERT(isMainThread()); + + OwnPtr<IPCCallbackContext> context = adoptPtr(static_cast<IPCCallbackContext*>(untypedContext)); + WKPrintingView *view = context->view.get(); + WebData* data = toImpl(dataRef); + + if (context->callbackID == view->_expectedPrintCallback) { + ASSERT(![view _isPrintingPreview]); + ASSERT(view->_printedPagesData.isEmpty()); + ASSERT(!view->_printedPagesPDFDocument); + if (data) + view->_printedPagesData.append(data->bytes(), data->size()); + view->_expectedPrintCallback = 0; + view->_printingCallbackCondition.signal(); + } else { + // If the user has already changed print setup, then this response is obsolete. And this callback is not in response to the latest request, + // then the user has already moved to another page - we'll cache the response, but won't draw it. + HashMap<uint64_t, WebCore::IntRect>::iterator iter = view->_expectedPreviewCallbacks.find(context->callbackID); + if (iter != view->_expectedPreviewCallbacks.end()) { + ASSERT([view _isPrintingPreview]); + + if (data) { + pair<HashMap<WebCore::IntRect, Vector<uint8_t> >::iterator, bool> entry = view->_pagePreviews.add(iter->second, Vector<uint8_t>()); + entry.first->second.append(data->bytes(), data->size()); + } + bool receivedResponseToLatestRequest = view->_latestExpectedPreviewCallback == context->callbackID; + view->_latestExpectedPreviewCallback = 0; + view->_expectedPreviewCallbacks.remove(context->callbackID); + if (receivedResponseToLatestRequest) + [view _updatePreview]; + } + } +} + +- (void)_preparePDFDataForPrintingOnSecondaryThread +{ + ASSERT(isMainThread()); + + if (!_webFrame->page()) { + _printingCallbackCondition.signal(); + return; + } + + MutexLocker lock(_printingCallbackMutex); + + ASSERT([self _hasPageRects]); + ASSERT(_printedPagesData.isEmpty()); + ASSERT(!_printedPagesPDFDocument); + ASSERT(!_expectedPrintCallback); + + NSUInteger firstPage = [self _firstPrintedPageNumber]; + NSUInteger lastPage = [self _lastPrintedPageNumber]; + + ASSERT(firstPage > 0); + ASSERT(firstPage <= lastPage); + LOG(View, "WKPrintingView requesting PDF data for pages %u...%u", firstPage, lastPage); + + // Return to printing mode if we're already back to screen (e.g. due to window resizing). + _webFrame->page()->beginPrinting(_webFrame.get(), PrintInfo([_printOperation printInfo])); + + IPCCallbackContext* context = new IPCCallbackContext; + RefPtr<DataCallback> callback = DataCallback::create(context, pageDidDrawToPDF); + _expectedPrintCallback = callback->callbackID(); + + context->view = self; + context->callbackID = callback->callbackID(); + + _webFrame->page()->drawPagesToPDF(_webFrame.get(), firstPage - 1, lastPage - firstPage + 1, callback.get()); +} + +static void pageDidComputePageRects(const Vector<WebCore::IntRect>& pageRects, double totalScaleFactorForPrinting, WKErrorRef, void* untypedContext) +{ + ASSERT(isMainThread()); + + OwnPtr<IPCCallbackContext> context = adoptPtr(static_cast<IPCCallbackContext*>(untypedContext)); + WKPrintingView *view = context->view.get(); + + // If the user has already changed print setup, then this response is obsolete. + if (context->callbackID == view->_expectedComputedPagesCallback) { + ASSERT(isMainThread()); + ASSERT(view->_expectedPreviewCallbacks.isEmpty()); + ASSERT(!view->_latestExpectedPreviewCallback); + ASSERT(!view->_expectedPrintCallback); + ASSERT(view->_pagePreviews.isEmpty()); + view->_expectedComputedPagesCallback = 0; + + view->_printingPageRects = pageRects; + view->_totalScaleFactorForPrinting = totalScaleFactorForPrinting; + + const IntRect& lastPrintingPageRect = view->_printingPageRects[view->_printingPageRects.size() - 1]; + NSRect newFrameSize = NSMakeRect(0, 0, + ceil(lastPrintingPageRect.maxX() * view->_totalScaleFactorForPrinting), + ceil(lastPrintingPageRect.maxY() * view->_totalScaleFactorForPrinting)); + LOG(View, "WKPrintingView setting frame size to x:%g y:%g width:%g height:%g", newFrameSize.origin.x, newFrameSize.origin.y, newFrameSize.size.width, newFrameSize.size.height); + [view setFrame:newFrameSize]; + + if ([view _isPrintingPreview]) { + // Show page count, and ask for an actual image to replace placeholder. + [view _updatePreview]; + } else { + // When printing, request everything we'll need beforehand. + [view _preparePDFDataForPrintingOnSecondaryThread]; + } + } +} + +- (BOOL)_askPageToComputePageRects +{ + ASSERT(isMainThread()); + + if (!_webFrame->page()) + return NO; + + ASSERT(!_expectedComputedPagesCallback); + + IPCCallbackContext* context = new IPCCallbackContext; + RefPtr<ComputedPagesCallback> callback = ComputedPagesCallback::create(context, pageDidComputePageRects); + _expectedComputedPagesCallback = callback->callbackID(); + context->view = self; + context->callbackID = _expectedComputedPagesCallback; + + _webFrame->page()->computePagesForPrinting(_webFrame.get(), PrintInfo([_printOperation printInfo]), callback.release()); + return YES; +} + +static void prepareDataForPrintingOnSecondaryThread(void* untypedContext) +{ + ASSERT(isMainThread()); + + WKPrintingView *view = static_cast<WKPrintingView *>(untypedContext); + MutexLocker lock(view->_printingCallbackMutex); + + // We may have received page rects while a message to call this function traveled from secondary thread to main one. + if ([view _hasPageRects]) { + [view _preparePDFDataForPrintingOnSecondaryThread]; + return; + } + + // A request for pages has already been made, just wait for it to finish. + if (view->_expectedComputedPagesCallback) + return; + + [view _askPageToComputePageRects]; +} + +- (BOOL)knowsPageRange:(NSRangePointer)range +{ + LOG(View, "-[WKPrintingView %p knowsPageRange:], %s, %s", self, [self _hasPageRects] ? "print data is available" : "print data is not available yet", isMainThread() ? "on main thread" : "on secondary thread"); + ASSERT(_printOperation == [NSPrintOperation currentOperation]); + + // Assuming that once we switch to printing from a secondary thread, we don't go back. + ASSERT(!_isPrintingFromSecondaryThread || !isMainThread()); + if (!isMainThread()) + _isPrintingFromSecondaryThread = YES; + + [self _suspendAutodisplay]; + + [self _adjustPrintingMarginsForHeaderAndFooter]; + + if ([self _hasPageRects]) + *range = NSMakeRange(1, _printingPageRects.size()); + else if (!isMainThread()) { + ASSERT(![self _isPrintingPreview]); + MutexLocker lock(_printingCallbackMutex); + callOnMainThread(prepareDataForPrintingOnSecondaryThread, self); + _printingCallbackCondition.wait(_printingCallbackMutex); + *range = NSMakeRange(1, _printingPageRects.size()); + } else { + ASSERT([self _isPrintingPreview]); + + // If a request for pages hasn't already been made, make it now. + if (!_expectedComputedPagesCallback) + [self _askPageToComputePageRects]; + + *range = NSMakeRange(1, NSIntegerMax); + } + return YES; +} + +- (unsigned)_pageForRect:(NSRect)rect +{ + // Assuming that rect exactly matches one of the pages. + for (size_t i = 0; i < _printingPageRects.size(); ++i) { + IntRect currentRect(_printingPageRects[i]); + currentRect.scale(_totalScaleFactorForPrinting); + if (rect.origin.y == currentRect.y() && rect.origin.x == currentRect.x()) + return i + 1; + } + ASSERT_NOT_REACHED(); + return 0; // Invalid page number. +} + +- (void)_drawPDFDocument:(CGPDFDocumentRef)pdfDocument page:(unsigned)page atPoint:(NSPoint)point +{ + if (!pdfDocument) { + LOG_ERROR("Couldn't create a PDF document with data passed for preview"); + return; + } + + CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument, page); + if (!pdfPage) { + LOG_ERROR("Preview data doesn't have page %d", page); + return; + } + + NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; + CGContextRef context = static_cast<CGContextRef>([nsGraphicsContext graphicsPort]); + + CGContextSaveGState(context); + CGContextTranslateCTM(context, point.x, point.y); + CGContextScaleCTM(context, _totalScaleFactorForPrinting, -_totalScaleFactorForPrinting); + CGContextTranslateCTM(context, 0, -CGPDFPageGetBoxRect(pdfPage, kCGPDFMediaBox).size.height); + CGContextDrawPDFPage(context, pdfPage); + CGContextRestoreGState(context); +} + +- (void)_drawPreview:(NSRect)nsRect +{ + ASSERT(isMainThread()); + + IntRect rect(nsRect); + rect.scale(1 / _totalScaleFactorForPrinting); + HashMap<WebCore::IntRect, Vector<uint8_t> >::iterator pagePreviewIterator = _pagePreviews.find(rect); + if (pagePreviewIterator == _pagePreviews.end()) { + // It's too early to ask for page preview if we don't even know page size and scale. + if ([self _hasPageRects]) { + if (uint64_t existingCallback = [self _expectedPreviewCallbackForRect:rect]) { + // We've already asked for a preview of this page, and are waiting for response. + // There is no need to ask again. + _latestExpectedPreviewCallback = existingCallback; + } else { + // Preview isn't available yet, request it asynchronously. + if (!_webFrame->page()) + return; + + // Return to printing mode if we're already back to screen (e.g. due to window resizing). + _webFrame->page()->beginPrinting(_webFrame.get(), PrintInfo([_printOperation printInfo])); + + IPCCallbackContext* context = new IPCCallbackContext; + RefPtr<DataCallback> callback = DataCallback::create(context, pageDidDrawToPDF); + _latestExpectedPreviewCallback = callback->callbackID(); + _expectedPreviewCallbacks.add(_latestExpectedPreviewCallback, rect); + + context->view = self; + context->callbackID = callback->callbackID(); + + _webFrame->page()->drawRectToPDF(_webFrame.get(), rect, callback.get()); + return; + } + } + + // FIXME: Draw a placeholder + return; + } + + const Vector<uint8_t>& pdfData = pagePreviewIterator->second; + RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, pdfData.data(), pdfData.size(), 0)); + RetainPtr<CGPDFDocumentRef> pdfDocument(AdoptCF, CGPDFDocumentCreateWithProvider(pdfDataProvider.get())); + + [self _drawPDFDocument:pdfDocument.get() page:1 atPoint:NSMakePoint(nsRect.origin.x, nsRect.origin.y)]; +} + +- (void)drawRect:(NSRect)nsRect +{ + LOG(View, "WKPrintingView %p printing rect x:%g, y:%g, width:%g, height:%g%s", self, nsRect.origin.x, nsRect.origin.y, nsRect.size.width, nsRect.size.height, [self _isPrintingPreview] ? " for preview" : ""); + + ASSERT(_printOperation == [NSPrintOperation currentOperation]); + + if (!_webFrame->page()) + return; + + if ([self _isPrintingPreview]) { + [self _drawPreview:nsRect]; + return; + } + + ASSERT(!isMainThread()); + ASSERT(!_printedPagesData.isEmpty()); // Prepared by knowsPageRange: + + if (!_printedPagesPDFDocument) { + RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, _printedPagesData.data(), _printedPagesData.size(), 0)); + _printedPagesPDFDocument.adoptCF(CGPDFDocumentCreateWithProvider(pdfDataProvider.get())); + } + + unsigned printedPageNumber = [self _pageForRect:nsRect] - [self _firstPrintedPageNumber] + 1; + [self _drawPDFDocument:_printedPagesPDFDocument.get() page:printedPageNumber atPoint:NSMakePoint(nsRect.origin.x, nsRect.origin.y)]; +} + +- (void)_drawPageBorderWithSizeOnMainThread:(NSSize)borderSize +{ + ASSERT(isMainThread()); + + // When printing from a secondary thread, the main thread doesn't have graphics context and printing operation set up. + NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; + [NSGraphicsContext setCurrentContext:[_printOperation context]]; + + ASSERT(![NSPrintOperation currentOperation]); + [NSPrintOperation setCurrentOperation:_printOperation]; + + [self drawPageBorderWithSize:borderSize]; + + [NSPrintOperation setCurrentOperation:nil]; + [NSGraphicsContext setCurrentContext:currentContext]; +} + +- (void)drawPageBorderWithSize:(NSSize)borderSize +{ + ASSERT(NSEqualSizes(borderSize, [[_printOperation printInfo] paperSize])); + ASSERT(_printOperation == [NSPrintOperation currentOperation]); + + if (!isMainThread()) { + // Don't call the client from a secondary thread. + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[WKPrintingView instanceMethodSignatureForSelector:@selector(_drawPageBorderWithSizeOnMainThread:)]]; + [invocation setSelector:@selector(_drawPageBorderWithSizeOnMainThread:)]; + [invocation setArgument:&borderSize atIndex:2]; + [invocation performSelectorOnMainThread:@selector(invokeWithTarget:) withObject:self waitUntilDone:YES]; + return; + } + + if (!_webFrame->page()) + return; + + // 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). + NSPrintInfo *printInfo = [_printOperation printInfo]; + CGFloat scale = [printInfo scalingFactor]; + NSSize paperSize = [printInfo paperSize]; + CGFloat headerFooterLeft = [printInfo leftMargin] / scale; + CGFloat headerFooterWidth = (paperSize.width - ([printInfo leftMargin] + [printInfo rightMargin])) / scale; + NSRect footerRect = NSMakeRect(headerFooterLeft, [printInfo bottomMargin] / scale - _webFrame->page()->footerHeight(_webFrame.get()), headerFooterWidth, _webFrame->page()->footerHeight(_webFrame.get())); + NSRect headerRect = NSMakeRect(headerFooterLeft, (paperSize.height - [printInfo topMargin]) / scale, headerFooterWidth, _webFrame->page()->headerHeight(_webFrame.get())); + + NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; + [currentContext saveGraphicsState]; + NSRectClip(headerRect); + _webFrame->page()->drawHeader(_webFrame.get(), headerRect); + [currentContext restoreGraphicsState]; + + [currentContext saveGraphicsState]; + NSRectClip(footerRect); + _webFrame->page()->drawFooter(_webFrame.get(), footerRect); + [currentContext restoreGraphicsState]; +} + +- (NSRect)rectForPage:(NSInteger)page +{ + ASSERT(_printOperation == [NSPrintOperation currentOperation]); + if (![self _hasPageRects]) { + LOG(View, "-[WKPrintingView %p rectForPage:%d] - data is not yet available", self, (int)page); + // We must be still calculating the page range. + ASSERT(_expectedComputedPagesCallback); + return NSMakeRect(0, 0, 1, 1); + } + + IntRect rect = _printingPageRects[page - 1]; + rect.scale(_totalScaleFactorForPrinting); + LOG(View, "-[WKPrintingView %p rectForPage:%d] -> x %d, y %d, width %d, height %d", self, (int)page, rect.x(), rect.y(), rect.width(), rect.height()); + return rect; +} + +// Temporary workaround for <rdar://problem/8944535>. Force correct printout positioning. +- (NSPoint)locationOfPrintRect:(NSRect)aRect +{ + ASSERT(_printOperation == [NSPrintOperation currentOperation]); + return NSMakePoint([[_printOperation printInfo] leftMargin], [[_printOperation printInfo] bottomMargin]); +} + +- (void)beginDocument +{ + ASSERT(_printOperation == [NSPrintOperation currentOperation]); + + // Forcing preview update gets us here, but page setup hasn't actually changed. + if (isForcingPreviewUpdate) + return; + + LOG(View, "-[WKPrintingView %p beginDocument]", self); + + [super beginDocument]; + + [self _suspendAutodisplay]; +} + +- (void)endDocument +{ + ASSERT(_printOperation == [NSPrintOperation currentOperation]); + + // Forcing preview update gets us here, but page setup hasn't actually changed. + if (isForcingPreviewUpdate) + return; + + LOG(View, "-[WKPrintingView %p endDocument] - clearing cached data", self); + + // Both existing data and pending responses are now obsolete. + _printingPageRects.clear(); + _totalScaleFactorForPrinting = 1; + _pagePreviews.clear(); + _printedPagesData.clear(); + _printedPagesPDFDocument = nullptr; + _expectedComputedPagesCallback = 0; + _expectedPreviewCallbacks.clear(); + _latestExpectedPreviewCallback = 0; + _expectedPrintCallback = 0; + + [self _delayedResumeAutodisplay]; + + [super endDocument]; +} +@end diff --git a/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm b/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm index b7dae31..3b69a1d 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKTextInputWindowController.mm @@ -23,9 +23,10 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#include "WKTextInputWindowController.h" +#import "config.h" +#import "WKTextInputWindowController.h" -#include <WebKitSystemInterface.h> +#import <WebKitSystemInterface.h> @interface WKTextInputPanel : NSPanel { NSTextView *_inputTextView; diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.h b/Source/WebKit2/UIProcess/API/mac/WKView.h index 618bbc4..8c1826c 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.h +++ b/Source/WebKit2/UIProcess/API/mac/WKView.h @@ -31,6 +31,7 @@ WK_EXPORT @interface WKView : NSView <NSTextInput> { WKViewData *_data; + unsigned _frameSizeUpdatesDisabledCount; } - (id)initWithFrame:(NSRect)frame contextRef:(WKContextRef)contextRef; @@ -39,6 +40,8 @@ WK_EXPORT - (NSPrintOperation *)printOperationWithPrintInfo:(NSPrintInfo *)printInfo forFrame:(WKFrameRef)frameRef; - (BOOL)canChangeFrameLayout:(WKFrameRef)frameRef; +- (void)setFrame:(NSRect)rect andScrollBy:(NSSize)offset; + @property(readonly) WKPageRef pageRef; @property BOOL drawsBackground; diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index 400239d..da29e04 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -23,6 +23,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#import "config.h" #import "WKView.h" #import "ChunkedUpdateDrawingAreaProxy.h" @@ -31,19 +32,22 @@ #import "FindIndicator.h" #import "FindIndicatorWindow.h" #import "LayerBackedDrawingAreaProxy.h" +#import "LayerTreeContext.h" #import "Logging.h" #import "NativeWebKeyboardEvent.h" #import "PDFViewController.h" #import "PageClientImpl.h" #import "PasteboardTypes.h" -#import "PrintInfo.h" #import "Region.h" #import "RunLoop.h" #import "TextChecker.h" #import "TextCheckerState.h" #import "WKAPICast.h" +#import "WKPrintingView.h" #import "WKStringCF.h" #import "WKTextInputWindowController.h" +#import "WKViewInternal.h" +#import "WKViewPrivate.h" #import "WebContext.h" #import "WebEventFactory.h" #import "WebPage.h" @@ -71,12 +75,9 @@ - (void)speakString:(NSString *)string; @end -@interface NSView (Details) -- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView; -@end - @interface NSWindow (Details) - (NSRect)_growBoxRect; +- (void)_setShowOpaqueGrowBoxForOwner:(id)owner; - (BOOL)_updateGrowBoxForWindowFrameChange; @end @@ -97,9 +98,6 @@ typedef HashMap<String, ValidationVector> ValidationMap; } -NSString* const WebKitOriginalTopPrintingMarginKey = @"WebKitOriginalTopMargin"; -NSString* const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMargin"; - @interface WKViewData : NSObject { @public OwnPtr<PageClientImpl> _pageClient; @@ -110,8 +108,11 @@ NSString* const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMa id _trackingRectOwner; void* _trackingRectUserData; + RetainPtr<NSView> _layerHostingView; + + // FIXME: Remove _oldLayerHostingView. #if USE(ACCELERATED_COMPOSITING) - NSView *_layerHostingView; + NSView *_oldLayerHostingView; #endif RetainPtr<id> _remoteAccessibilityChild; @@ -128,6 +129,8 @@ NSString* const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMa NSEvent *_keyDownEventBeingResent; Vector<KeypressCommand> _commandsList; + NSSize _resizeScrollOffset; + // The identifier of the plug-in we want to send complex text input to, or 0 if there is none. uint64_t _pluginComplexTextInputIdentifier; @@ -135,50 +138,21 @@ NSString* const WebKitOriginalBottomPrintingMarginKey = @"WebKitOriginalBottomMa unsigned _selectionStart; unsigned _selectionEnd; - Vector<IntRect> _printingPageRects; - double _totalScaleFactorForPrinting; - bool _inBecomeFirstResponder; bool _inResignFirstResponder; NSEvent *_mouseDownEvent; BOOL _ignoringMouseDraggedEvents; BOOL _dragHasStarted; -} -@end -@implementation WKViewData -@end - -@interface WebFrameWrapper : NSObject { -@public - RefPtr<WebFrameProxy> _frame; +#if ENABLE(GESTURE_EVENTS) + id _endGestureMonitor; +#endif } - -- (id)initWithFrameProxy:(WebFrameProxy*)frame; -- (WebFrameProxy*)webFrame; @end -@implementation WebFrameWrapper - -- (id)initWithFrameProxy:(WebFrameProxy*)frame -{ - self = [super init]; - if (!self) - return nil; - - _frame = frame; - return self; -} - -- (WebFrameProxy*)webFrame -{ - return _frame.get(); -} - +@implementation WKViewData @end -NSString * const PrintedFrameKey = @"WebKitPrintedFrameKey"; - @interface NSObject (NSTextInputContextDetails) - (BOOL)wantsToHandleMouseEvents; - (BOOL)handleMouseEvent:(NSEvent *)event; @@ -186,11 +160,10 @@ NSString * const PrintedFrameKey = @"WebKitPrintedFrameKey"; @implementation WKView +// FIXME: Remove this once we no longer want to be able to go back to the old drawing area. static bool useNewDrawingArea() { - static bool useNewDrawingArea = getenv("USE_NEW_DRAWING_AREA"); - - return useNewDrawingArea; + return true; } - (id)initWithFrame:(NSRect)frame @@ -211,6 +184,24 @@ static bool useNewDrawingArea() [types release]; } +- (void)_updateRemoteAccessibilityRegistration:(BOOL)registerProcess +{ +#if !defined(BUILDING_ON_SNOW_LEOPARD) + // When the tree is connected/disconnected, the remote accessibility registration + // needs to be updated with the pid of the remote process. If the process is going + // away, that information is not present in WebProcess + pid_t pid = 0; + if (registerProcess && _data->_page->process()) + pid = _data->_page->process()->processIdentifier(); + else if (!registerProcess) { + pid = WKAXRemoteProcessIdentifier(_data->_remoteAccessibilityChild.get()); + _data->_remoteAccessibilityChild = nil; + } + if (pid) + WKAXRegisterRemoteProcess(registerProcess, pid); +#endif +} + - (id)initWithFrame:(NSRect)frame contextRef:(WKContextRef)contextRef pageGroupRef:(WKPageGroupRef)pageGroupRef { self = [super initWithFrame:frame]; @@ -239,12 +230,6 @@ static bool useNewDrawingArea() WebContext::statistics().wkViewCount++; -#if !defined(BUILDING_ON_SNOW_LEOPARD) - NSData *remoteToken = (NSData *)WKAXRemoteTokenForElement(self); - CoreIPC::DataReference dataToken = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>([remoteToken bytes]), [remoteToken length]); - _data->_page->sendAccessibilityPresenterToken(dataToken); -#endif - return self; } @@ -312,19 +297,35 @@ static bool useNewDrawingArea() return YES; } +- (void)viewWillStartLiveResize +{ + _data->_page->viewWillStartLiveResize(); +} + +- (void)viewDidEndLiveResize +{ + _data->_page->viewWillEndLiveResize(); +} + - (BOOL)isFlipped { return YES; } +- (void)setFrame:(NSRect)rect andScrollBy:(NSSize)offset +{ + ASSERT(NSEqualSizes(_data->_resizeScrollOffset, NSZeroSize)); + + _data->_resizeScrollOffset = offset; + [self setFrame:rect]; +} + - (void)setFrameSize:(NSSize)size { [super setFrameSize:size]; - - if (!_data->_page->drawingArea()) - return; - _data->_page->drawingArea()->setSize(IntSize(size)); + if (![self frameSizeUpdatesDisabled]) + [self _setDrawingAreaSize:size]; } - (void)_updateWindowAndViewFrames @@ -366,6 +367,8 @@ static const SelectorNameMap* createSelectorExceptionMap() map->add(@selector(pageDownAndModifySelection:), "MovePageDownAndModifySelection"); map->add(@selector(pageUp:), "MovePageUp"); map->add(@selector(pageUpAndModifySelection:), "MovePageUpAndModifySelection"); + map->add(@selector(scrollPageDown:), "ScrollPageForward"); + map->add(@selector(scrollPageUp:), "ScrollPageBackward"); return map; } @@ -392,16 +395,143 @@ static String commandNameForSelector(SEL selector) #define WEBCORE_COMMAND(command) - (void)command:(id)sender { _data->_page->executeEditCommand(commandNameForSelector(_cmd)); } +WEBCORE_COMMAND(alignCenter) +WEBCORE_COMMAND(alignJustified) +WEBCORE_COMMAND(alignLeft) +WEBCORE_COMMAND(alignRight) WEBCORE_COMMAND(copy) WEBCORE_COMMAND(cut) -WEBCORE_COMMAND(paste) WEBCORE_COMMAND(delete) +WEBCORE_COMMAND(deleteBackward) +WEBCORE_COMMAND(deleteBackwardByDecomposingPreviousCharacter) +WEBCORE_COMMAND(deleteForward) +WEBCORE_COMMAND(deleteToBeginningOfLine) +WEBCORE_COMMAND(deleteToBeginningOfParagraph) +WEBCORE_COMMAND(deleteToEndOfLine) +WEBCORE_COMMAND(deleteToEndOfParagraph) +WEBCORE_COMMAND(deleteToMark) +WEBCORE_COMMAND(deleteWordBackward) +WEBCORE_COMMAND(deleteWordForward) +WEBCORE_COMMAND(ignoreSpelling) +WEBCORE_COMMAND(indent) +WEBCORE_COMMAND(insertBacktab) +WEBCORE_COMMAND(insertLineBreak) +WEBCORE_COMMAND(insertNewline) +WEBCORE_COMMAND(insertNewlineIgnoringFieldEditor) +WEBCORE_COMMAND(insertParagraphSeparator) +WEBCORE_COMMAND(insertTab) +WEBCORE_COMMAND(insertTabIgnoringFieldEditor) +WEBCORE_COMMAND(makeTextWritingDirectionLeftToRight) +WEBCORE_COMMAND(makeTextWritingDirectionNatural) +WEBCORE_COMMAND(makeTextWritingDirectionRightToLeft) +WEBCORE_COMMAND(moveBackward) +WEBCORE_COMMAND(moveBackwardAndModifySelection) +WEBCORE_COMMAND(moveDown) +WEBCORE_COMMAND(moveDownAndModifySelection) +WEBCORE_COMMAND(moveForward) +WEBCORE_COMMAND(moveForwardAndModifySelection) +WEBCORE_COMMAND(moveLeft) +WEBCORE_COMMAND(moveLeftAndModifySelection) +WEBCORE_COMMAND(moveParagraphBackwardAndModifySelection) +WEBCORE_COMMAND(moveParagraphForwardAndModifySelection) +WEBCORE_COMMAND(moveRight) +WEBCORE_COMMAND(moveRightAndModifySelection) +WEBCORE_COMMAND(moveToBeginningOfDocument) +WEBCORE_COMMAND(moveToBeginningOfDocumentAndModifySelection) +WEBCORE_COMMAND(moveToBeginningOfLine) +WEBCORE_COMMAND(moveToBeginningOfLineAndModifySelection) +WEBCORE_COMMAND(moveToBeginningOfParagraph) +WEBCORE_COMMAND(moveToBeginningOfParagraphAndModifySelection) +WEBCORE_COMMAND(moveToBeginningOfSentence) +WEBCORE_COMMAND(moveToBeginningOfSentenceAndModifySelection) +WEBCORE_COMMAND(moveToEndOfDocument) +WEBCORE_COMMAND(moveToEndOfDocumentAndModifySelection) +WEBCORE_COMMAND(moveToEndOfLine) +WEBCORE_COMMAND(moveToEndOfLineAndModifySelection) +WEBCORE_COMMAND(moveToEndOfParagraph) +WEBCORE_COMMAND(moveToEndOfParagraphAndModifySelection) +WEBCORE_COMMAND(moveToEndOfSentence) +WEBCORE_COMMAND(moveToEndOfSentenceAndModifySelection) +WEBCORE_COMMAND(moveToLeftEndOfLine) +WEBCORE_COMMAND(moveToLeftEndOfLineAndModifySelection) +WEBCORE_COMMAND(moveToRightEndOfLine) +WEBCORE_COMMAND(moveToRightEndOfLineAndModifySelection) +WEBCORE_COMMAND(moveUp) +WEBCORE_COMMAND(moveUpAndModifySelection) +WEBCORE_COMMAND(moveWordBackward) +WEBCORE_COMMAND(moveWordBackwardAndModifySelection) +WEBCORE_COMMAND(moveWordForward) +WEBCORE_COMMAND(moveWordForwardAndModifySelection) +WEBCORE_COMMAND(moveWordLeft) +WEBCORE_COMMAND(moveWordLeftAndModifySelection) +WEBCORE_COMMAND(moveWordRight) +WEBCORE_COMMAND(moveWordRightAndModifySelection) +WEBCORE_COMMAND(outdent) +WEBCORE_COMMAND(pageDown) +WEBCORE_COMMAND(pageDownAndModifySelection) +WEBCORE_COMMAND(pageUp) +WEBCORE_COMMAND(pageUpAndModifySelection) +WEBCORE_COMMAND(paste) WEBCORE_COMMAND(pasteAsPlainText) +WEBCORE_COMMAND(scrollPageDown) +WEBCORE_COMMAND(scrollPageUp) +WEBCORE_COMMAND(scrollToBeginningOfDocument) +WEBCORE_COMMAND(scrollToEndOfDocument) WEBCORE_COMMAND(selectAll) +WEBCORE_COMMAND(selectLine) +WEBCORE_COMMAND(selectParagraph) +WEBCORE_COMMAND(selectSentence) +WEBCORE_COMMAND(selectToMark) +WEBCORE_COMMAND(selectWord) +WEBCORE_COMMAND(setMark) +WEBCORE_COMMAND(subscript) +WEBCORE_COMMAND(superscript) +WEBCORE_COMMAND(swapWithMark) WEBCORE_COMMAND(takeFindStringFromSelection) +WEBCORE_COMMAND(transpose) +WEBCORE_COMMAND(underline) +WEBCORE_COMMAND(unscript) +WEBCORE_COMMAND(yank) +WEBCORE_COMMAND(yankAndSelect) #undef WEBCORE_COMMAND +/* + +When possible, editing-related methods should be implemented in WebCore with the +EditorCommand mechanism and invoked via WEBCORE_COMMAND, rather than implementing +individual methods here with Mac-specific code. + +Editing-related methods still unimplemented that are implemented in WebKit1: + +- (void)capitalizeWord:(id)sender; +- (void)centerSelectionInVisibleArea:(id)sender; +- (void)changeFont:(id)sender; +- (void)complete:(id)sender; +- (void)copyFont:(id)sender; +- (void)lowercaseWord:(id)sender; +- (void)makeBaseWritingDirectionLeftToRight:(id)sender; +- (void)makeBaseWritingDirectionNatural:(id)sender; +- (void)makeBaseWritingDirectionRightToLeft:(id)sender; +- (void)pasteFont:(id)sender; +- (void)scrollLineDown:(id)sender; +- (void)scrollLineUp:(id)sender; +- (void)showGuessPanel:(id)sender; +- (void)uppercaseWord:(id)sender; + +Some other editing-related methods still unimplemented: + +- (void)changeCaseOfLetter:(id)sender; +- (void)copyRuler:(id)sender; +- (void)insertContainerBreak:(id)sender; +- (void)insertDoubleQuoteIgnoringSubstitution:(id)sender; +- (void)insertSingleQuoteIgnoringSubstitution:(id)sender; +- (void)pasteRuler:(id)sender; +- (void)toggleRuler:(id)sender; +- (void)transposeWords:(id)sender; + +*/ + // Menu items validation static NSMenuItem *menuItem(id <NSValidatedUserInterfaceItem> item) @@ -791,6 +921,41 @@ EVENT_HANDLER(scrollWheel, Wheel) [self _mouseHandler:event]; } +#if ENABLE(GESTURE_EVENTS) + +static const short kIOHIDEventTypeScroll = 6; + +- (void)shortCircuitedEndGestureWithEvent:(NSEvent *)event +{ + if ([event subtype] != kIOHIDEventTypeScroll) + return; + + WebGestureEvent webEvent = WebEventFactory::createWebGestureEvent(event, self); + _data->_page->handleGestureEvent(webEvent); + + if (_data->_endGestureMonitor) { + [NSEvent removeMonitor:_data->_endGestureMonitor]; + _data->_endGestureMonitor = nil; + } +} + +- (void)beginGestureWithEvent:(NSEvent *)event +{ + if ([event subtype] != kIOHIDEventTypeScroll) + return; + + WebGestureEvent webEvent = WebEventFactory::createWebGestureEvent(event, self); + _data->_page->handleGestureEvent(webEvent); + + if (!_data->_endGestureMonitor) { + _data->_endGestureMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskEndGesture handler:^(NSEvent *blockEvent) { + [self shortCircuitedEndGestureWithEvent:blockEvent]; + return blockEvent; + }]; + } +} +#endif + - (void)doCommandBySelector:(SEL)selector { if (selector != @selector(noop:)) @@ -830,6 +995,9 @@ EVENT_HANDLER(scrollWheel, Wheel) - (BOOL)_handleStyleKeyEquivalent:(NSEvent *)event { + if (!_data->_page->selectionState().isContentEditable) + return NO; + if (([event modifierFlags] & NSDeviceIndependentModifierFlagsMask) != NSCommandKeyMask) return NO; @@ -875,27 +1043,6 @@ EVENT_HANDLER(scrollWheel, Wheel) return [self _handleStyleKeyEquivalent:event] || [super performKeyEquivalent:event]; } -- (void)_setEventBeingResent:(NSEvent *)event -{ - _data->_keyDownEventBeingResent = [event retain]; -} - -- (Vector<KeypressCommand>&)_interceptKeyEvent:(NSEvent *)theEvent -{ - _data->_commandsList.clear(); - // interpretKeyEvents will trigger one or more calls to doCommandBySelector or setText - // that will populate the commandsList vector. - [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; - return _data->_commandsList; -} - -- (void)_getTextInputState:(unsigned)start selectionEnd:(unsigned)end underlines:(Vector<WebCore::CompositionUnderline>&)lines -{ - start = _data->_selectionStart; - end = _data->_selectionEnd; - lines = _data->_underlines; -} - - (void)keyUp:(NSEvent *)theEvent { _data->_page->handleKeyboardEvent(NativeWebKeyboardEvent(theEvent, self)); @@ -1165,15 +1312,22 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde { // Temporarily enable the resize indicator to make a the _ownsWindowGrowBox calculation work. BOOL wasShowingIndicator = [[self window] showsResizeIndicator]; - [[self window] setShowsResizeIndicator:YES]; + if (!wasShowingIndicator) + [[self window] setShowsResizeIndicator:YES]; BOOL ownsGrowBox = [self _ownsWindowGrowBox]; _data->_page->setWindowResizerSize(ownsGrowBox ? enclosingIntRect([[self window] _growBoxRect]).size() : IntSize()); - + + if (ownsGrowBox) + [[self window] _setShowOpaqueGrowBoxForOwner:(_data->_page->hasHorizontalScrollbar() || _data->_page->hasVerticalScrollbar() ? self : nil)]; + else + [[self window] _setShowOpaqueGrowBoxForOwner:nil]; + // Once WebCore can draw the window resizer, this should read: // if (wasShowingIndicator) // [[self window] setShowsResizeIndicator:!ownsGrowBox]; - [[self window] setShowsResizeIndicator:wasShowingIndicator]; + if (!wasShowingIndicator) + [[self window] setShowsResizeIndicator:NO]; return ownsGrowBox; } @@ -1228,11 +1382,27 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde _data->_page->viewStateDidChange(WebPageProxy::ViewIsVisible | WebPageProxy::ViewIsInWindow); [self _updateWindowVisibility]; [self _updateWindowAndViewFrames]; + + // Initialize remote accessibility when the window connection has been established. +#if !defined(BUILDING_ON_SNOW_LEOPARD) + NSData *remoteElementToken = WKAXRemoteTokenForElement(self); + NSData *remoteWindowToken = WKAXRemoteTokenForElement([self window]); + CoreIPC::DataReference elementToken = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>([remoteElementToken bytes]), [remoteElementToken length]); + CoreIPC::DataReference windowToken = CoreIPC::DataReference(reinterpret_cast<const uint8_t*>([remoteWindowToken bytes]), [remoteWindowToken length]); + _data->_page->registerUIProcessAccessibilityTokens(elementToken, windowToken); +#endif + } else { _data->_page->viewStateDidChange(WebPageProxy::ViewIsVisible); _data->_page->viewStateDidChange(WebPageProxy::ViewWindowIsActive | WebPageProxy::ViewIsInWindow); - } +#if ENABLE(GESTURE_EVENTS) + if (_data->_endGestureMonitor) { + [NSEvent removeMonitor:_data->_endGestureMonitor]; + _data->_endGestureMonitor = nil; + } +#endif + } } - (void)_windowDidBecomeKey:(NSNotification *)notification @@ -1264,13 +1434,34 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde [self _updateWindowAndViewFrames]; } +static void drawPageBackground(CGContextRef context, WebPageProxy* page, const IntRect& rect) +{ + if (!page->drawsBackground()) + return; + + CGContextSaveGState(context); + CGContextSetBlendMode(context, kCGBlendModeCopy); + + CGColorRef backgroundColor; + if (page->drawsTransparentBackground()) + backgroundColor = CGColorGetConstantColor(kCGColorClear); + else + backgroundColor = CGColorGetConstantColor(kCGColorWhite); + + CGContextSetFillColorWithColor(context, backgroundColor); + CGContextFillRect(context, rect); + + CGContextRestoreGState(context); +} + - (void)drawRect:(NSRect)rect { LOG(View, "drawRect: x:%g, y:%g, width:%g, height:%g", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); + _data->_page->endPrinting(); if (useNewDrawingArea()) { - if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(_data->_page->drawingArea())) { - CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]); + CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]); + if (DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(_data->_page->drawingArea())) { const NSRect *rectsBeingDrawn; NSInteger numRectsBeingDrawn; [self getRectsBeingDrawn:&rectsBeingDrawn count:&numRectsBeingDrawn]; @@ -1278,11 +1469,13 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde Region unpaintedRegion; IntRect rect = enclosingIntRect(rectsBeingDrawn[i]); drawingArea->paint(context, rect, unpaintedRegion); + + Vector<IntRect> unpaintedRects = unpaintedRegion.rects(); + for (size_t i = 0; i < unpaintedRects.size(); ++i) + drawPageBackground(context, _data->_page.get(), unpaintedRects[i]); } - } else if (_data->_page->drawsBackground()) { - [_data->_page->drawsTransparentBackground() ? [NSColor clearColor] : [NSColor whiteColor] set]; - NSRectFill(rect); - } + } else + drawPageBackground(context, _data->_page.get(), enclosingIntRect(rect)); _data->_page->didDraw(); return; @@ -1313,14 +1506,6 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde _data->_page->viewStateDidChange(WebPageProxy::ViewIsVisible); } -- (void)_setAccessibilityChildToken:(NSData *)data -{ -#if !defined(BUILDING_ON_SNOW_LEOPARD) - _data->_remoteAccessibilityChild = WKAXRemoteElementForToken((CFDataRef)data); - WKAXInitializeRemoteElementWithWindow(_data->_remoteAccessibilityChild.get(), [self window]); -#endif -} - - (BOOL)accessibilityIsIgnored { return NO; @@ -1353,9 +1538,12 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde - (NSView *)hitTest:(NSPoint)point { NSView *hitView = [super hitTest:point]; -#if USE(ACCELERATED_COMPOSITING) if (hitView && _data && hitView == _data->_layerHostingView) hitView = self; + +#if USE(ACCELERATED_COMPOSITING) + if (hitView && _data && hitView == _data->_oldLayerHostingView) + hitView = self; #endif return hitView; } @@ -1365,190 +1553,30 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde return (NSInteger)self; } -static void setFrameBeingPrinted(NSPrintOperation *printOperation, WebFrameProxy* frame) -{ - RetainPtr<WebFrameWrapper> frameWrapper(AdoptNS, [[WebFrameWrapper alloc] initWithFrameProxy:frame]); - [[[printOperation printInfo] dictionary] setObject:frameWrapper.get() forKey:PrintedFrameKey]; -} - -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 +- (BOOL)canChangeFrameLayout:(WKFrameRef)frameRef { - 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]; + // PDF documents are already paginated, so we can't change them to add headers and footers. + return !toImpl(frameRef)->isMainFrame() || !_data->_pdfViewController; } - (NSPrintOperation *)printOperationWithPrintInfo:(NSPrintInfo *)printInfo forFrame:(WKFrameRef)frameRef { LOG(View, "Creating an NSPrintOperation for frame '%s'", toImpl(frameRef)->url().utf8().data()); - NSPrintOperation *printOperation; // Only the top frame can currently contain a PDF view. if (_data->_pdfViewController) { - ASSERT(toImpl(frameRef)->isMainFrame()); - printOperation = _data->_pdfViewController->makePrintOperation(printInfo); - } else - printOperation = [NSPrintOperation printOperationWithView:self printInfo:printInfo]; - - setFrameBeingPrinted(printOperation, toImpl(frameRef)); - return printOperation; -} - -- (BOOL)canChangeFrameLayout:(WKFrameRef)frameRef -{ - // PDF documents are already paginated, so we can't change them to add headers and footers. - return !toImpl(frameRef)->isMainFrame() || !_data->_pdfViewController; -} - -// Return the number of pages available for printing -- (BOOL)knowsPageRange:(NSRangePointer)range -{ - LOG(View, "knowsPageRange:"); - WebFrameProxy* frame = frameBeingPrinted(); - ASSERT(frame); - - 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()); - return YES; -} - -// Take over printing. AppKit applies incorrect clipping, and doesn't print pages beyond the first one. -- (void)_recursiveDisplayRectIfNeededIgnoringOpacity:(NSRect)rect isVisibleRect:(BOOL)isVisibleRect rectIsVisibleRectForView:(NSView *)visibleView topView:(BOOL)topView -{ - // FIXME: This check isn't right for some non-printing cases, such as capturing into a buffer using cacheDisplayInRect:toBitmapImageRep:. - if ([NSGraphicsContext currentContextDrawingToScreen]) { - _data->_page->endPrinting(); - [super _recursiveDisplayRectIfNeededIgnoringOpacity:rect isVisibleRect:isVisibleRect rectIsVisibleRectForView:visibleView topView:topView]; - return; - } - - LOG(View, "Printing rect x:%g, y:%g, width:%g, height:%g", rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); - - ASSERT(self == visibleView); - ASSERT(frameBeingPrinted()); - - WebFrameProxy* frame = frameBeingPrinted(); - ASSERT(frame); - - _data->_page->beginPrinting(frame, PrintInfo([[NSPrintOperation currentOperation] printInfo])); - - // FIXME: This is optimized for print preview. Get the whole document at once when actually printing. - Vector<uint8_t> pdfData; - _data->_page->drawRectToPDF(frame, IntRect(rect), pdfData); - - RetainPtr<CGDataProviderRef> pdfDataProvider(AdoptCF, CGDataProviderCreateWithData(0, pdfData.data(), pdfData.size(), 0)); - RetainPtr<CGPDFDocumentRef> pdfDocument(AdoptCF, CGPDFDocumentCreateWithProvider(pdfDataProvider.get())); - if (!pdfDocument) { - LOG_ERROR("Couldn't create a PDF document with data passed for printing"); - return; - } - - CGPDFPageRef pdfPage = CGPDFDocumentGetPage(pdfDocument.get(), 1); - if (!pdfPage) { - LOG_ERROR("Printing data doesn't have page 1"); - return; + if (!toImpl(frameRef)->isMainFrame()) + return 0; + return _data->_pdfViewController->makePrintOperation(printInfo); + } else { + RetainPtr<WKPrintingView> printingView(AdoptNS, [[WKPrintingView alloc] initWithFrameProxy:toImpl(frameRef)]); + // NSPrintOperation takes ownership of the view. + NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:printingView.get()]; + [printOperation setCanSpawnSeparateThread:YES]; + printingView->_printOperation = printOperation; + return printOperation; } - - NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; - CGContextRef context = static_cast<CGContextRef>([nsGraphicsContext graphicsPort]); - - CGContextSaveGState(context); - // Flip the destination. - CGContextScaleCTM(context, 1, -1); - CGContextTranslateCTM(context, 0, -rect.size.height); - CGContextDrawPDFPage(context, pdfPage); - 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. -- (CGFloat)_provideTotalScaleFactorForPrintOperation:(NSPrintOperation *)printOperation -{ - return _data->_totalScaleFactorForPrinting; -} - -// Return the drawing rectangle for a particular page number -- (NSRect)rectForPage:(NSInteger)page -{ - WebFrameProxy* frame = frameBeingPrinted(); - ASSERT(frame); - - if (frame->isMainFrame() && _data->_pdfViewController) - return [super rectForPage:page]; - - LOG(View, "rectForPage:%d -> x %d, y %d, width %d, height %d\n", (int)page, _data->_printingPageRects[page - 1].x(), _data->_printingPageRects[page - 1].y(), _data->_printingPageRects[page - 1].width(), _data->_printingPageRects[page - 1].height()); - return _data->_printingPageRects[page - 1]; } @end @@ -1575,6 +1603,12 @@ static float currentPrintOperationScale() - (void)_processDidCrash { [self setNeedsDisplay:YES]; + [self _updateRemoteAccessibilityRegistration:NO]; +} + +- (void)_pageClosed +{ + [self _updateRemoteAccessibilityRegistration:NO]; } - (void)_didRelaunchProcess @@ -1610,6 +1644,27 @@ static float currentPrintOperationScale() } } +- (void)_setEventBeingResent:(NSEvent *)event +{ + _data->_keyDownEventBeingResent = [event retain]; +} + +- (Vector<KeypressCommand>&)_interceptKeyEvent:(NSEvent *)theEvent +{ + _data->_commandsList.clear(); + // interpretKeyEvents will trigger one or more calls to doCommandBySelector or setText + // that will populate the commandsList vector. + [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + return _data->_commandsList; +} + +- (void)_getTextInputState:(unsigned)start selectionEnd:(unsigned)end underlines:(Vector<WebCore::CompositionUnderline>&)lines +{ + start = _data->_selectionStart; + end = _data->_selectionEnd; + lines = _data->_underlines; +} + - (NSRect)_convertToDeviceSpace:(NSRect)rect { return toDeviceSpace(rect, [self window]); @@ -1750,7 +1805,7 @@ static float currentPrintOperationScale() #if USE(ACCELERATED_COMPOSITING) - (void)_startAcceleratedCompositing:(CALayer *)rootLayer { - if (!_data->_layerHostingView) { + if (!_data->_oldLayerHostingView) { NSView *hostingView = [[NSView alloc] initWithFrame:[self bounds]]; #if !defined(BUILDING_ON_LEOPARD) [hostingView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; @@ -1758,7 +1813,7 @@ static float currentPrintOperationScale() [self addSubview:hostingView]; [hostingView release]; - _data->_layerHostingView = hostingView; + _data->_oldLayerHostingView = hostingView; } // Make a container layer, which will get sized/positioned by AppKit and CA. @@ -1792,8 +1847,8 @@ static float currentPrintOperationScale() [viewLayer setTransform:CATransform3DMakeScale(scaleFactor, scaleFactor, 1)]; #endif - [_data->_layerHostingView setLayer:viewLayer]; - [_data->_layerHostingView setWantsLayer:YES]; + [_data->_oldLayerHostingView setLayer:viewLayer]; + [_data->_oldLayerHostingView setWantsLayer:YES]; // Parent our root layer in the container layer [viewLayer addSublayer:rootLayer]; @@ -1801,11 +1856,11 @@ static float currentPrintOperationScale() - (void)_stopAcceleratedCompositing { - if (_data->_layerHostingView) { - [_data->_layerHostingView setLayer:nil]; - [_data->_layerHostingView setWantsLayer:NO]; - [_data->_layerHostingView removeFromSuperview]; - _data->_layerHostingView = nil; + if (_data->_oldLayerHostingView) { + [_data->_oldLayerHostingView setLayer:nil]; + [_data->_oldLayerHostingView setWantsLayer:NO]; + [_data->_oldLayerHostingView removeFromSuperview]; + _data->_oldLayerHostingView = nil; } } @@ -1830,12 +1885,46 @@ static float currentPrintOperationScale() } } - newDrawingArea->setSize(IntSize([self frame].size)); + newDrawingArea->setSize(IntSize([self frame].size), IntSize()); _data->_page->drawingArea()->detachCompositingContext(); _data->_page->setDrawingArea(newDrawingArea.release()); } +- (void)_enterAcceleratedCompositingMode:(const LayerTreeContext&)layerTreeContext +{ + ASSERT(!_data->_layerHostingView); + ASSERT(!layerTreeContext.isEmpty()); + + // Create an NSView that will host our layer tree. + _data->_layerHostingView.adoptNS([[NSView alloc] initWithFrame:[self bounds]]); + [_data->_layerHostingView.get() setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; + [self addSubview:_data->_layerHostingView.get()]; + + // Create a root layer that will back the NSView. + RetainPtr<CALayer> rootLayer(AdoptNS, [[CALayer alloc] init]); +#ifndef NDEBUG + [rootLayer.get() setName:@"Hosting root layer"]; +#endif + + CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID); + [rootLayer.get() addSublayer:renderLayer]; + + [_data->_layerHostingView.get() setLayer:rootLayer.get()]; + [_data->_layerHostingView.get() setWantsLayer:YES]; +} + +- (void)_exitAcceleratedCompositingMode +{ + ASSERT(_data->_layerHostingView); + + [_data->_layerHostingView.get() setLayer:nil]; + [_data->_layerHostingView.get() setWantsLayer:NO]; + [_data->_layerHostingView.get() removeFromSuperview]; + + _data->_layerHostingView = nullptr; +} + - (void)_pageDidEnterAcceleratedCompositing { [self _switchToDrawingAreaTypeIfNecessary:DrawingAreaInfo::LayerBacked]; @@ -1848,6 +1937,14 @@ static float currentPrintOperationScale() } #endif // USE(ACCELERATED_COMPOSITING) +- (void)_setAccessibilityWebProcessToken:(NSData *)data +{ +#if !defined(BUILDING_ON_SNOW_LEOPARD) + _data->_remoteAccessibilityChild = WKAXRemoteElementForToken(data); + [self _updateRemoteAccessibilityRegistration:YES]; +#endif +} + - (void)_setComplexTextInputEnabled:(BOOL)complexTextInputEnabled pluginComplexTextInputIdentifier:(uint64_t)pluginComplexTextInputIdentifier { BOOL inputSourceChanged = _data->_pluginComplexTextInputIdentifier; @@ -1922,4 +2019,42 @@ static float currentPrintOperationScale() _data->_dragHasStarted = NO; } +- (void)_setDrawingAreaSize:(NSSize)size +{ + if (!_data->_page->drawingArea()) + return; + + _data->_page->drawingArea()->setSize(IntSize(size), IntSize(_data->_resizeScrollOffset)); + _data->_resizeScrollOffset = NSZeroSize; +} + +- (void)_didChangeScrollbarsForMainFrame +{ + [self _updateGrowBoxForWindowFrameChange]; +} + +@end + +@implementation WKView (Private) + +- (void)disableFrameSizeUpdates +{ + _frameSizeUpdatesDisabledCount++; +} + +- (void)enableFrameSizeUpdates +{ + if (!_frameSizeUpdatesDisabledCount) + return; + + if (!(--_frameSizeUpdatesDisabledCount)) + [self _setDrawingAreaSize:[self frame].size]; +} + +- (BOOL)frameSizeUpdatesDisabled +{ + return _frameSizeUpdatesDisabledCount > 0; +} + @end + diff --git a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h index cba241d..9e77e30 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h +++ b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h @@ -36,6 +36,7 @@ namespace WebKit { - (PassOwnPtr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy; - (BOOL)_isFocused; - (void)_processDidCrash; +- (void)_pageClosed; - (void)_didRelaunchProcess; - (void)_takeFocus:(BOOL)direction; - (void)_toolTipChangedFrom:(NSString *)oldToolTip to:(NSString *)newToolTip; @@ -48,6 +49,9 @@ namespace WebKit { - (NSRect)_convertToUserSpace:(NSRect)rect; - (void)_setFindIndicator:(PassRefPtr<WebKit::FindIndicator>)findIndicator fadeOut:(BOOL)fadeOut; +- (void)_enterAcceleratedCompositingMode:(const WebKit::LayerTreeContext&)layerTreeContext; +- (void)_exitAcceleratedCompositingMode; + #if USE(ACCELERATED_COMPOSITING) - (void)_startAcceleratedCompositing:(CALayer *)rootLayer; - (void)_stopAcceleratedCompositing; @@ -55,7 +59,7 @@ namespace WebKit { - (void)_pageDidLeaveAcceleratedCompositing; #endif -- (void)_setAccessibilityChildToken:(NSData *)data; +- (void)_setAccessibilityWebProcessToken:(NSData *)data; - (void)_setComplexTextInputEnabled:(BOOL)complexTextInputEnabled pluginComplexTextInputIdentifier:(uint64_t)pluginComplexTextInputIdentifier; - (void)_setPageHasCustomRepresentation:(BOOL)pageHasCustomRepresentation; @@ -64,4 +68,7 @@ namespace WebKit { - (void)_setCustomRepresentationZoomFactor:(double)zoomFactor; - (void)_setDragImage:(NSImage *)image at:(NSPoint)clientPoint linkDrag:(BOOL)linkDrag; +- (void)_setDrawingAreaSize:(NSSize)size; + +- (void)_didChangeScrollbarsForMainFrame; @end diff --git a/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h b/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h new file mode 100644 index 0000000..5d6125e --- /dev/null +++ b/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2011 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +@interface WKView (Private) + +// Stops updating the size of the page as the WKView frame size updates. +// This should always be followed by enableFrameSizeUpdates. Calls can be nested. +- (void)disableFrameSizeUpdates; +// Immediately updates the size of the page to match WKView's frame size +// and allows subsequent updates as the frame size is set. Calls can be nested. +- (void)enableFrameSizeUpdates; +- (BOOL)frameSizeUpdatesDisabled; + +@end |