diff options
Diffstat (limited to 'Source/WebKit2/UIProcess/API/mac')
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/PDFViewController.h | 6 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/PDFViewController.mm | 46 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/PageClientImpl.h | 18 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm | 98 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKPrintingView.h | 3 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm | 49 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKView.mm | 248 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKViewInternal.h | 15 | ||||
-rw-r--r-- | Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h | 2 |
9 files changed, 362 insertions, 123 deletions
diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.h b/Source/WebKit2/UIProcess/API/mac/PDFViewController.h index d22d8b5..dc30f56 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.h +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.h @@ -41,6 +41,8 @@ namespace CoreIPC { namespace WebKit { +class WebPageProxy; + class PDFViewController { WTF_MAKE_NONCOPYABLE(PDFViewController); @@ -49,6 +51,9 @@ public: ~PDFViewController(); WKView* wkView() const { return m_wkView; } + WebPageProxy* page() const; + NSView* pdfView() const; + void setPDFDocumentData(const String& mimeType, const String& suggestedFilename, const CoreIPC::DataReference&); double zoomFactor() const; @@ -58,6 +63,7 @@ public: NSPrintOperation *makePrintOperation(NSPrintInfo *); void openPDFInFinder(); + void savePDFToDownloadsFolder(); private: explicit PDFViewController(WKView *wkView); diff --git a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm index 5d9b860..5c64000 100644 --- a/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm +++ b/Source/WebKit2/UIProcess/API/mac/PDFViewController.mm @@ -29,6 +29,7 @@ #import "DataReference.h" #import "WKAPICast.h" #import "WKView.h" +#import "WebData.h" #import "WebPageGroup.h" #import "WebPageProxy.h" #import "WebPreferences.h" @@ -116,7 +117,7 @@ extern "C" NSString *_NSPathForSystemFramework(NSString *framework); if (!_pdfViewController) return; - WebPreferences *preferences = toImpl([_pdfViewController->wkView() pageRef])->pageGroup()->preferences(); + WebPreferences *preferences = _pdfViewController->page()->pageGroup()->preferences(); CGFloat scaleFactor = preferences->pdfScaleFactor(); if (!scaleFactor) @@ -135,7 +136,7 @@ extern "C" NSString *_NSPathForSystemFramework(NSString *framework); if (!_pdfViewController) return; - WebPreferences* preferences = toImpl([_pdfViewController->wkView() pageRef])->pageGroup()->preferences(); + WebPreferences* preferences = _pdfViewController->page()->pageGroup()->preferences(); CGFloat scaleFactor = [_pdfView autoScales] ? 0 : [_pdfView scaleFactor]; preferences->setPDFScaleFactor(scaleFactor); @@ -187,6 +188,11 @@ extern "C" NSString *_NSPathForSystemFramework(NSString *framework); _pdfViewController->openPDFInFinder(); } +- (void)PDFViewSavePDFToDownloadFolder:(PDFView *)sender +{ + _pdfViewController->savePDFToDownloadsFolder(); +} + @end namespace WebKit { @@ -212,6 +218,16 @@ PDFViewController::~PDFViewController() m_wkPDFView = nullptr; } +WebPageProxy* PDFViewController::page() const +{ + return toImpl([m_wkView pageRef]); +} + +NSView* PDFViewController::pdfView() const +{ + return m_wkPDFView.get(); +} + static RetainPtr<CFDataRef> convertPostScriptDataSourceToPDF(const CoreIPC::DataReference& dataReference) { // Convert PostScript to PDF using Quartz 2D API @@ -330,6 +346,32 @@ void PDFViewController::openPDFInFinder() [[NSWorkspace sharedWorkspace] openFile:path]; } +static void releaseCFData(unsigned char*, const void* data) +{ + ASSERT(CFGetTypeID(data) == CFDataGetTypeID()); + + // Balanced by CFRetain in savePDFToDownloadsFolder. + CFRelease(data); +} + +void PDFViewController::savePDFToDownloadsFolder() +{ + // We don't want to write the file until we have a document to write. (see 5267607). + if (![m_pdfView document]) { + NSBeep(); + return; + } + + ASSERT(m_pdfData); + + // Balanced by CFRelease in releaseCFData. + CFRetain(m_pdfData.get()); + + RefPtr<WebData> data = WebData::createWithoutCopying(CFDataGetBytePtr(m_pdfData.get()), CFDataGetLength(m_pdfData.get()), releaseCFData, m_pdfData.get()); + + page()->saveDataToFileInDownloadsFolder(m_suggestedFilename.get(), page()->mainFrame()->mimeType(), page()->mainFrame()->url(), data.get()); +} + static NSString *temporaryPDFDirectoryPath() { static NSString *temporaryPDFDirectoryPath; diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h index e01cf66..e217fc5 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.h @@ -26,6 +26,7 @@ #ifndef PageClientImpl_h #define PageClientImpl_h +#include "CorrectionPanel.h" #include "PageClient.h" #include <wtf/RetainPtr.h> @@ -62,6 +63,7 @@ private: virtual void processDidCrash(); virtual void pageClosed(); virtual void didRelaunchProcess(); + virtual void setFocus(bool focused); virtual void takeFocus(bool direction); virtual void toolTipChanged(const String& oldToolTip, const String& newToolTip); virtual void setCursor(const WebCore::Cursor&); @@ -70,11 +72,12 @@ private: virtual void registerEditCommand(PassRefPtr<WebEditCommandProxy>, WebPageProxy::UndoOrRedo); virtual void clearAllEditCommands(); virtual void interceptKeyEvent(const NativeWebKeyboardEvent& event, Vector<WebCore::KeypressCommand>& commandName, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines); - virtual void setDragImage(const WebCore::IntPoint& clientPosition, const WebCore::IntSize& imageSize, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag); + virtual void setDragImage(const WebCore::IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag); virtual WebCore::FloatRect convertToDeviceSpace(const WebCore::FloatRect&); virtual WebCore::FloatRect convertToUserSpace(const WebCore::FloatRect&); - + virtual WebCore::IntRect windowToScreen(const WebCore::IntRect&); + virtual void doneWithKeyEvent(const NativeWebKeyboardEvent&, bool wasEventHandled); virtual PassRefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy*); @@ -87,7 +90,6 @@ private: virtual void accessibilityWebProcessTokenReceived(const CoreIPC::DataReference&); virtual void setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled); - virtual void setAutodisplay(bool); virtual CGContextRef containingWindowGraphicsContext(); @@ -103,8 +105,18 @@ private: virtual void didPerformDictionaryLookup(const String&, double scaleFactor, const DictionaryPopupInfo&); + virtual void showCorrectionPanel(WebCore::CorrectionPanelInfo::PanelType, const WebCore::FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings); + virtual void dismissCorrectionPanel(WebCore::ReasonForDismissingCorrectionPanel); + virtual String dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel); + virtual void recordAutocorrectionResponse(WebCore::EditorClient::AutocorrectionResponseType, const String& replacedString, const String& replacementString); + + virtual float userSpaceScaleFactor() const; + WKView* m_wkView; RetainPtr<WebEditorUndoTargetObjC> m_undoTarget; +#if !defined(BUILDING_ON_SNOW_LEOPARD) + CorrectionPanel m_correctionPanel; +#endif }; } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm index 88bb9a4..7a0d62d 100644 --- a/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm +++ b/Source/WebKit2/UIProcess/API/mac/PageClientImpl.mm @@ -45,6 +45,7 @@ #import <wtf/PassOwnPtr.h> #import <wtf/text/CString.h> #import <wtf/text/WTFString.h> +#import <WebKitSystemInterface.h> @interface NSApplication (WebNSApplicationDetails) - (NSCursor *)_cursorRectCursor; @@ -195,6 +196,15 @@ void PageClientImpl::didRelaunchProcess() [m_wkView _didRelaunchProcess]; } +void PageClientImpl::setFocus(bool focused) +{ + if (focused) + [[m_wkView window] makeFirstResponder:m_wkView]; + else + // takeFocus in this context means take focus away from the WKView. + takeFocus(true); +} + void PageClientImpl::takeFocus(bool direction) { [m_wkView _takeFocus:direction]; @@ -287,10 +297,11 @@ void PageClientImpl::interceptKeyEvent(const NativeWebKeyboardEvent& event, Vect [m_wkView _getTextInputState:selectionStart selectionEnd:selectionEnd underlines:underlines]; } -void PageClientImpl::setDragImage(const IntPoint& clientPosition, const IntSize& imageSize, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag) +void PageClientImpl::setDragImage(const IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag) { - OwnPtr<GraphicsContext> graphicsContext = dragImage->createGraphicsContext(); - RetainPtr<NSImage> dragNSImage(AdoptNS, [[NSImage alloc] initWithCGImage:CGBitmapContextCreateImage(graphicsContext->platformContext()) size:imageSize]); + RetainPtr<CGImageRef> dragCGImage = dragImage->makeCGImage(); + RetainPtr<NSImage> dragNSImage(AdoptNS, [[NSImage alloc] initWithCGImage:dragCGImage.get() size:dragImage->size()]); + [m_wkView _setDragImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag]; } @@ -303,6 +314,14 @@ FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect) { return [m_wkView _convertToUserSpace:rect]; } + +IntRect PageClientImpl::windowToScreen(const IntRect& rect) +{ + NSRect tempRect = rect; + tempRect = [m_wkView convertRect:tempRect toView:nil]; + tempRect.origin = [[m_wkView window] convertBaseToScreen:tempRect.origin]; + return enclosingIntRect(tempRect); +} void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool wasEventHandled) { @@ -311,10 +330,8 @@ void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool return; if (wasEventHandled) [NSCursor setHiddenUntilMouseMoves:YES]; - else { - [m_wkView _setEventBeingResent:nativeEvent]; - [[NSApplication sharedApplication] sendEvent:nativeEvent]; - } + else + [m_wkView _resendKeyDownEvent:nativeEvent]; } PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page) @@ -355,18 +372,6 @@ 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]; - - // For some reason, painting doesn't happen for a long time without this call, <rdar://problem/8975229>. - if (newState) - [m_wkView displayIfNeeded]; -} - CGContextRef PageClientImpl::containingWindowGraphicsContext() { NSWindow *window = [m_wkView window]; @@ -419,9 +424,64 @@ void PageClientImpl::didPerformDictionaryLookup(const String& text, double scale NSPoint textBaselineOrigin = dictionaryPopupInfo.origin; textBaselineOrigin.y += [font ascender]; +#if !defined(BUILDING_ON_SNOW_LEOPARD) + // Convert to screen coordinates. + textBaselineOrigin = [m_wkView convertPoint:textBaselineOrigin toView:nil]; + textBaselineOrigin = [m_wkView.window convertRectToScreen:NSMakeRect(textBaselineOrigin.x, textBaselineOrigin.y, 0, 0)].origin; + + WKShowWordDefinitionWindow(attributedString.get(), textBaselineOrigin, (NSDictionary *)dictionaryPopupInfo.options.get()); +#else // If the dictionary lookup is being triggered by a hot key, force the overlay style. NSDictionary *options = (dictionaryPopupInfo.type == DictionaryPopupInfo::HotKey) ? [NSDictionary dictionaryWithObject:NSDefinitionPresentationTypeOverlay forKey:NSDefinitionPresentationTypeKey] : 0; [m_wkView showDefinitionForAttributedString:attributedString.get() range:NSMakeRange(0, [attributedString.get() length]) options:options baselineOriginProvider:^(NSRange adjustedRange) { return (NSPoint)textBaselineOrigin; }]; +#endif +} + +void PageClientImpl::showCorrectionPanel(CorrectionPanelInfo::PanelType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings) +{ +#if !defined(BUILDING_ON_SNOW_LEOPARD) + if (!isViewVisible() || !isViewInWindow()) + return; + m_correctionPanel.show(m_wkView, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings); +#endif +} + +void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingCorrectionPanel reason) +{ +#if !defined(BUILDING_ON_SNOW_LEOPARD) + m_correctionPanel.dismiss(reason); +#endif +} + +String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingCorrectionPanel reason) +{ +#if !defined(BUILDING_ON_SNOW_LEOPARD) + return m_correctionPanel.dismissSoon(reason); +#else + return String(); +#endif +} + +void PageClientImpl::recordAutocorrectionResponse(EditorClient::AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString) +{ +#if !defined(BUILDING_ON_SNOW_LEOPARD) + NSCorrectionResponse response = responseType == EditorClient::AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited; + CorrectionPanel::recordAutocorrectionResponse(m_wkView, response, replacedString, replacementString); +#endif +} + +float PageClientImpl::userSpaceScaleFactor() const +{ + NSWindow *window = [m_wkView window]; +#if !defined(BUILDING_ON_SNOW_LEOPARD) + if (window) + return [window backingScaleFactor]; + return [[NSScreen mainScreen] backingScaleFactor]; +#else + if (window) + return [window userSpaceScaleFactor]; + return [[NSScreen mainScreen] userSpaceScaleFactor]; +#endif } } // namespace WebKit diff --git a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h index 3f7a692..87d81f4 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h +++ b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.h @@ -35,6 +35,7 @@ namespace WebKit { @interface WKPrintingView : NSView { @public NSPrintOperation *_printOperation; // WKPrintingView is owned by the operation. + RetainPtr<NSView> _wkView; RefPtr<WebKit::WebFrameProxy> _webFrame; Vector<WebCore::IntRect> _printingPageRects; @@ -56,6 +57,6 @@ namespace WebKit { NSTimer *_autodisplayResumeTimer; } -- (id)initWithFrameProxy:(WebKit::WebFrameProxy*)frame; +- (id)initWithFrameProxy:(WebKit::WebFrameProxy*)frame view:(NSView *)wkView; @end diff --git a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm index 28ba153..d5d9de7 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKPrintingView.mm @@ -43,13 +43,14 @@ static BOOL isForcingPreviewUpdate; @implementation WKPrintingView -- (id)initWithFrameProxy:(WebFrameProxy*)frame +- (id)initWithFrameProxy:(WebKit::WebFrameProxy*)frame view:(NSView *)wkView { self = [super init]; // No frame rect to pass to NSView. if (!self) return nil; _webFrame = frame; + _wkView = wkView; return self; } @@ -59,6 +60,19 @@ static BOOL isForcingPreviewUpdate; return YES; } +- (void)_setAutodisplay:(BOOL)newState +{ + if (!newState && [[_wkView.get() window] isAutodisplay]) + [_wkView.get() displayIfNeeded]; + + [[_wkView.get() window] setAutodisplay:newState]; + + // For some reason, painting doesn't happen for a long time without this call, <rdar://problem/8975229>. + if (newState) + [_wkView.get() displayIfNeeded]; +} + + - (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. @@ -67,7 +81,7 @@ static BOOL isForcingPreviewUpdate; [_autodisplayResumeTimer invalidate]; _autodisplayResumeTimer = nil; } else - _webFrame->page()->setAutodisplay(false); + [self _setAutodisplay:NO]; } - (void)_delayedResumeAutodisplayTimerFired @@ -75,7 +89,7 @@ static BOOL isForcingPreviewUpdate; ASSERT(isMainThread()); _autodisplayResumeTimer = nil; - _webFrame->page()->setAutodisplay(true); + [self _setAutodisplay:YES]; } - (void)_delayedResumeAutodisplay @@ -200,11 +214,12 @@ static void pageDidDrawToPDF(WKDataRef dataRef, WKErrorRef, void* untypedContext 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) + bool receivedResponseToLatestRequest = view->_latestExpectedPreviewCallback == context->callbackID; + if (receivedResponseToLatestRequest) { + view->_latestExpectedPreviewCallback = 0; [view _updatePreview]; + } } } } @@ -264,6 +279,12 @@ static void pageDidComputePageRects(const Vector<WebCore::IntRect>& pageRects, d view->_printingPageRects = pageRects; view->_totalScaleFactorForPrinting = totalScaleFactorForPrinting; + // Sanitize a response coming from the Web process. + if (view->_printingPageRects.isEmpty()) + view->_printingPageRects.append(IntRect(0, 0, 1, 1)); + if (view->_totalScaleFactorForPrinting <= 0) + view->_totalScaleFactorForPrinting = 1; + const IntRect& lastPrintingPageRect = view->_printingPageRects[view->_printingPageRects.size() - 1]; NSRect newFrameSize = NSMakeRect(0, 0, ceil(lastPrintingPageRect.maxX() * view->_totalScaleFactorForPrinting), @@ -330,6 +351,11 @@ static void prepareDataForPrintingOnSecondaryThread(void* untypedContext) if (!isMainThread()) _isPrintingFromSecondaryThread = YES; + if (!_webFrame->page()) { + *range = NSMakeRange(1, NSIntegerMax); + return YES; + } + [self _suspendAutodisplay]; [self _adjustPrintingMarginsForHeaderAndFooter]; @@ -524,11 +550,22 @@ static void prepareDataForPrintingOnSecondaryThread(void* untypedContext) ASSERT(_printOperation == [NSPrintOperation currentOperation]); if (![self _hasPageRects]) { LOG(View, "-[WKPrintingView %p rectForPage:%d] - data is not yet available", self, (int)page); + if (!_webFrame->page()) { + // We may have not told AppKit how many pages there are, so it will try to print until a null rect is returned. + return NSMakeRect(0, 0, 0, 0); + } // We must be still calculating the page range. ASSERT(_expectedComputedPagesCallback); return NSMakeRect(0, 0, 1, 1); } + // If Web process crashes while computing page rects, we never tell AppKit how many pages there are. + // Returning a null rect prevents selecting non-existent pages in preview dialog. + if (static_cast<unsigned>(page) > _printingPageRects.size()) { + ASSERT(!_webFrame->page()); + return NSMakeRect(0, 0, 0, 0); + } + 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()); diff --git a/Source/WebKit2/UIProcess/API/mac/WKView.mm b/Source/WebKit2/UIProcess/API/mac/WKView.mm index e432549..05693ef 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKView.mm +++ b/Source/WebKit2/UIProcess/API/mac/WKView.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2010, 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 @@ -42,6 +42,7 @@ #import "TextChecker.h" #import "TextCheckerState.h" #import "WKAPICast.h" +#import "WKFullScreenWindowController.h" #import "WKPrintingView.h" #import "WKStringCF.h" #import "WKTextInputWindowController.h" @@ -49,6 +50,7 @@ #import "WKViewPrivate.h" #import "WebContext.h" #import "WebEventFactory.h" +#import "WebFullScreenManagerProxy.h" #import "WebPage.h" #import "WebPageProxy.h" #import "WebProcessProxy.h" @@ -57,6 +59,7 @@ #import <WebCore/ColorMac.h> #import <WebCore/DragController.h> #import <WebCore/DragData.h> +#import <WebCore/LocalizedStrings.h> #import <WebCore/FloatRect.h> #import <WebCore/IntRect.h> #import <WebCore/KeyboardEvent.h> @@ -66,15 +69,14 @@ #import <wtf/RefPtr.h> #import <wtf/RetainPtr.h> -// FIXME (WebKit2) <rdar://problem/8728860> WebKit2 needs to be localized -#define UI_STRING(__str, __desc) [NSString stringWithUTF8String:__str] - -@interface NSApplication (Details) +@interface NSApplication (WebNSApplicationDetails) - (void)speakString:(NSString *)string; +- (void)_setCurrentEvent:(NSEvent *)event; @end -@interface NSWindow (Details) +@interface NSWindow (WebNSWindowDetails) - (NSRect)_growBoxRect; +- (id)_growBoxOwner; - (void)_setShowOpaqueGrowBoxForOwner:(id)owner; - (BOOL)_updateGrowBoxForWindowFrameChange; @end @@ -108,11 +110,6 @@ typedef HashMap<String, ValidationVector> ValidationMap; RetainPtr<NSView> _layerHostingView; - // FIXME: Remove _oldLayerHostingView. -#if USE(ACCELERATED_COMPOSITING) - NSView *_oldLayerHostingView; -#endif - RetainPtr<id> _remoteAccessibilityChild; // For asynchronous validation. @@ -124,7 +121,8 @@ typedef HashMap<String, ValidationVector> ValidationMap; // We keep here the event when resending it to // the application to distinguish the case of a new event from one // that has been already sent to WebCore. - NSEvent *_keyDownEventBeingResent; + RetainPtr<NSEvent> _keyDownEventBeingResent; + bool _isInInterpretKeyEvents; Vector<KeypressCommand> _commandsList; NSSize _resizeScrollOffset; @@ -145,6 +143,13 @@ typedef HashMap<String, ValidationVector> ValidationMap; #if ENABLE(GESTURE_EVENTS) id _endGestureMonitor; #endif + +#if ENABLE(FULLSCREEN_API) + RetainPtr<WKFullScreenWindowController> _fullScreenWindowController; +#endif + + BOOL _hasSpellCheckerDocumentTag; + NSInteger _spellCheckerDocumentTag; } @end @@ -158,12 +163,6 @@ typedef HashMap<String, ValidationVector> ValidationMap; @implementation WKView -// FIXME: Remove this once we no longer want to be able to go back to the old drawing area. -static bool useNewDrawingArea() -{ - return true; -} - - (id)initWithFrame:(NSRect)frame { return [self initWithFrame:frame contextRef:toAPI(WebContext::sharedProcessContext())]; @@ -223,6 +222,9 @@ static bool useNewDrawingArea() _data->_pageClient = PageClientImpl::create(self); _data->_page = toImpl(contextRef)->createWebPage(_data->_pageClient.get(), toImpl(pageGroupRef)); _data->_page->initializeWebPage(); +#if ENABLE(FULLSCREEN_API) + _data->_page->fullScreenManager()->setWebView(self); +#endif _data->_mouseDownEvent = nil; _data->_ignoringMouseDraggedEvents = NO; @@ -238,6 +240,7 @@ static bool useNewDrawingArea() _data->_page->close(); [_data release]; + _data = nil; WebContext::statistics().wkViewCount--; @@ -496,6 +499,8 @@ WEBCORE_COMMAND(yankAndSelect) #undef WEBCORE_COMMAND +// This method is needed to support Mac OS X services. + - (BOOL)writeSelectionToPasteboard:(NSPasteboard *)pasteboard types:(NSArray *)types { Vector<String> pasteboardTypes; @@ -505,6 +510,8 @@ WEBCORE_COMMAND(yankAndSelect) return _data->_page->writeSelectionToPasteboard([pasteboard name], pasteboardTypes); } +// This method is needed to support Mac OS X services. + - (id)validRequestorForSendType:(NSString *)sendType returnType:(NSString *)returnType { BOOL isValidSendType = !sendType || ([PasteboardTypes::forSelection() containsObject:sendType] && !_data->_page->selectionState().isNone); @@ -520,6 +527,13 @@ WEBCORE_COMMAND(yankAndSelect) return [[self nextResponder] validRequestorForSendType:sendType returnType:returnType]; } +// This method is needed to support Mac OS X services. + +- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pasteboard +{ + return _data->_page->readSelectionFromPasteboard([pasteboard name]); +} + /* When possible, editing-related methods should be implemented in WebCore with the @@ -589,12 +603,8 @@ static void validateCommandCallback(WKStringRef commandName, bool isEnabled, int SEL action = [item action]; if (action == @selector(showGuessPanel:)) { - if (NSMenuItem *menuItem = ::menuItem(item)) { - BOOL panelShowing = [[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible]; - [menuItem setTitle:panelShowing - ? UI_STRING("Hide Spelling and Grammar", "menu item title") - : UI_STRING("Show Spelling and Grammar", "menu item title")]; - } + if (NSMenuItem *menuItem = ::menuItem(item)) + [menuItem setTitle:contextMenuItemTagShowSpellingPanel([[[NSSpellChecker sharedSpellChecker] spellingPanel] isVisible])]; return _data->_page->selectionState().isContentEditable; } @@ -621,12 +631,8 @@ static void validateCommandCallback(WKStringRef commandName, bool isEnabled, int } if (action == @selector(orderFrontSubstitutionsPanel:)) { - if (NSMenuItem *menuItem = ::menuItem(item)) { - BOOL panelShowing = [[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible]; - [menuItem setTitle:panelShowing - ? UI_STRING("Hide Substitutions", "menu item title") - : UI_STRING("Show Substitutions", "menu item title")]; - } + if (NSMenuItem *menuItem = ::menuItem(item)) + [menuItem setTitle:contextMenuItemTagShowSubstitutions([[[NSSpellChecker sharedSpellChecker] substitutionsPanel] isVisible])]; return _data->_page->selectionState().isContentEditable; } @@ -1010,6 +1016,12 @@ static const short kIOHIDEventTypeScroll = 6; - (void)doCommandBySelector:(SEL)selector { + LOG(TextInput, "doCommandBySelector:\"%s\"", sel_getName(selector)); + + if (!_data->_isInInterpretKeyEvents) { + [super doCommandBySelector:selector]; + return; + } if (selector != @selector(noop:)) _data->_commandsList.append(KeypressCommand(commandNameForSelector(selector))); } @@ -1034,9 +1046,13 @@ static const short kIOHIDEventTypeScroll = 6; isFromInputMethod = YES; } else text = string; - + String eventText = text; + // We'd need a different code path here if we wanted to be able to handle this + // outside of interpretKeyEvents. + ASSERT(_data->_isInInterpretKeyEvents); + if (!isFromInputMethod) _data->_commandsList.append(KeypressCommand("insertText", text)); else { @@ -1085,9 +1101,6 @@ static const short kIOHIDEventTypeScroll = 6; // But don't do it if we have already handled the event. // Pressing Esc results in a fake event being sent - don't pass it to WebCore. if (!eventWasSentToWebCore && event == [NSApp currentEvent] && self == [[self window] firstResponder]) { - [_data->_keyDownEventBeingResent release]; - _data->_keyDownEventBeingResent = nil; - _data->_page->handleKeyboardEvent(NativeWebKeyboardEvent(event, self)); return YES; } @@ -1102,6 +1115,11 @@ static const short kIOHIDEventTypeScroll = 6; - (void)keyDown:(NSEvent *)theEvent { + // There's a chance that responding to this event will run a nested event loop, and + // fetching a new event might release the old one. Retaining and then autoreleasing + // the current event prevents that from causing a problem inside WebKit or AppKit code. + [[theEvent retain] autorelease]; + if (_data->_pluginComplexTextInputIdentifier) { // Try feeding the keyboard event directly to the plug-in. NSString *string = nil; @@ -1120,8 +1138,6 @@ static const short kIOHIDEventTypeScroll = 6; // there is no range selection). // If this is the case we should ignore the key down. if (_data->_keyDownEventBeingResent == theEvent) { - [_data->_keyDownEventBeingResent release]; - _data->_keyDownEventBeingResent = nil; [super keyDown:theEvent]; return; } @@ -1129,7 +1145,7 @@ static const short kIOHIDEventTypeScroll = 6; } - (NSTextInputContext *)inputContext { - if (_data->_pluginComplexTextInputIdentifier) + if (_data->_pluginComplexTextInputIdentifier && !_data->_isInInterpretKeyEvents) return [[WKTextInputWindowController sharedTextInputWindowController] inputContext]; return [super inputContext]; @@ -1153,7 +1169,11 @@ static const short kIOHIDEventTypeScroll = 6; - (void)unmarkText { LOG(TextInput, "unmarkText"); - + + // We'd need a different code path here if we wanted to be able to handle this + // outside of interpretKeyEvents. + ASSERT(_data->_isInInterpretKeyEvents); + _data->_commandsList.append(KeypressCommand("unmarkText")); } @@ -1208,6 +1228,10 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde extractUnderlines(string, _data->_underlines); } + // We'd need a different code path here if we wanted to be able to handle this + // outside of interpretKeyEvents. + ASSERT(_data->_isInInterpretKeyEvents); + _data->_commandsList.append(KeypressCommand("setMarkedText", text)); _data->_selectionStart = newSelRange.location; _data->_selectionEnd = NSMaxRange(newSelRange); @@ -1418,10 +1442,15 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde - (void)viewWillMoveToWindow:(NSWindow *)window { - if (window != [self window]) { - [self removeWindowObservers]; - [self addWindowObserversForWindow:window]; - } + NSWindow *currentWindow = [self window]; + if (window == currentWindow) + return; + + [self removeWindowObservers]; + [self addWindowObserversForWindow:window]; + + if ([currentWindow _growBoxOwner] == self) + [currentWindow _setShowOpaqueGrowBoxForOwner:nil]; } - (void)viewDidMoveToWindow @@ -1438,7 +1467,7 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde // 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]); + NSData *remoteWindowToken = WKAXRemoteTokenForElement([self accessibilityAttributeValue:NSAccessibilityWindowAttribute]); 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); @@ -1454,6 +1483,9 @@ static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnde _data->_endGestureMonitor = nil; } #endif +#if !defined(BUILDING_ON_SNOW_LEOPARD) + WKHideWordDefinitionWindow(); +#endif } } @@ -1510,37 +1542,25 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I { 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()) { - 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]; - for (NSInteger i = 0; i < numRectsBeingDrawn; ++i) { - 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 - drawPageBackground(context, _data->_page.get(), enclosingIntRect(rect)); - - _data->_page->didDraw(); - return; - } + 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]; + for (NSInteger i = 0; i < numRectsBeingDrawn; ++i) { + 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 + drawPageBackground(context, _data->_page.get(), enclosingIntRect(rect)); - if (_data->_page->isValid() && _data->_page->drawingArea()) { - CGContextRef context = static_cast<CGContextRef>([[NSGraphicsContext currentContext] graphicsPort]); - _data->_page->drawingArea()->paint(IntRect(rect), context); - _data->_page->didDraw(); - } else if (_data->_page->drawsBackground()) { - [_data->_page->drawsTransparentBackground() ? [NSColor clearColor] : [NSColor whiteColor] set]; - NSRectFill(rect); - } + _data->_page->didDraw(); } - (BOOL)isOpaque @@ -1567,6 +1587,9 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (id)accessibilityFocusedUIElement { + if (_data->_pdfViewController) + return NSAccessibilityUnignoredDescendant(_data->_pdfViewController->pdfView()); + return _data->_remoteAccessibilityChild.get(); } @@ -1577,15 +1600,25 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (id)accessibilityHitTest:(NSPoint)point { + if (_data->_pdfViewController) + return [_data->_pdfViewController->pdfView() accessibilityHitTest:point]; + return _data->_remoteAccessibilityChild.get(); } - (id)accessibilityAttributeValue:(NSString*)attribute { if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) { - if (!_data->_remoteAccessibilityChild) + + id child = nil; + if (_data->_pdfViewController) + child = NSAccessibilityUnignoredDescendant(_data->_pdfViewController->pdfView()); + else if (_data->_remoteAccessibilityChild) + child = _data->_remoteAccessibilityChild.get(); + + if (!child) return nil; - return [NSArray arrayWithObject:_data->_remoteAccessibilityChild.get()]; + return [NSArray arrayWithObject:child]; } if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) return NSAccessibilityGroupRole; @@ -1605,10 +1638,6 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I if (hitView && _data && hitView == _data->_layerHostingView) hitView = self; -#if USE(ACCELERATED_COMPOSITING) - if (hitView && _data && hitView == _data->_oldLayerHostingView) - hitView = self; -#endif return hitView; } @@ -1634,7 +1663,7 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I return 0; return _data->_pdfViewController->makePrintOperation(printInfo); } else { - RetainPtr<WKPrintingView> printingView(AdoptNS, [[WKPrintingView alloc] initWithFrameProxy:toImpl(frameRef)]); + RetainPtr<WKPrintingView> printingView(AdoptNS, [[WKPrintingView alloc] initWithFrameProxy:toImpl(frameRef) view:self]); // NSPrintOperation takes ownership of the view. NSPrintOperation *printOperation = [NSPrintOperation printOperationWithView:printingView.get()]; [printOperation setCanSpawnSeparateThread:YES]; @@ -1649,10 +1678,7 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (PassOwnPtr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy { - if (useNewDrawingArea()) - return DrawingAreaProxyImpl::create(_data->_page.get()); - - return ChunkedUpdateDrawingAreaProxy::create(self, _data->_page.get()); + return DrawingAreaProxyImpl::create(_data->_page.get()); } - (BOOL)_isFocused @@ -1708,21 +1734,33 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I } } -- (void)_setEventBeingResent:(NSEvent *)event +- (void)_resendKeyDownEvent:(NSEvent *)event { - _data->_keyDownEventBeingResent = [event retain]; + ASSERT(!_data->_keyDownEventBeingResent); + _data->_keyDownEventBeingResent = event; + [NSApp _setCurrentEvent:event]; + [NSApp sendEvent:event]; + + _data->_keyDownEventBeingResent = nullptr; } - (Vector<KeypressCommand>&)_interceptKeyEvent:(NSEvent *)theEvent { + ASSERT(!_data->_isInInterpretKeyEvents); + + _data->_isInInterpretKeyEvents = true; _data->_commandsList.clear(); - // interpretKeyEvents will trigger one or more calls to doCommandBySelector or setText + + // Calling interpretKeyEvents will trigger one or more calls to doCommandBySelector and insertText // that will populate the commandsList vector. [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]]; + + _data->_isInInterpretKeyEvents = false; + return _data->_commandsList; } -- (void)_getTextInputState:(unsigned)start selectionEnd:(unsigned)end underlines:(Vector<WebCore::CompositionUnderline>&)lines +- (void)_getTextInputState:(unsigned)start selectionEnd:(unsigned)end underlines:(Vector<CompositionUnderline>&)lines { start = _data->_selectionStart; end = _data->_selectionEnd; @@ -1771,20 +1809,23 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I - (void)removeTrackingRect:(NSTrackingRectTag)tag { + if (!_data) + return; + if (tag == 0) return; - if (_data && (tag == TRACKING_RECT_TAG)) { + if (tag == TRACKING_RECT_TAG) { _data->_trackingRectOwner = nil; return; } - if (_data && (tag == _data->_lastToolTipTag)) { + if (tag == _data->_lastToolTipTag) { [super removeTrackingRect:tag]; _data->_lastToolTipTag = 0; return; } - + // If any other tracking rect is being removed, we don't know how it was created // and it's possible there's a leak involved (see 3500217) ASSERT_NOT_REACHED(); @@ -2001,6 +2042,17 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I [self _updateGrowBoxForWindowFrameChange]; } +#if ENABLE(FULLSCREEN_API) +- (WKFullScreenWindowController*)fullScreenWindowController +{ + if (!_data->_fullScreenWindowController) { + _data->_fullScreenWindowController.adoptNS([[WKFullScreenWindowController alloc] init]); + [_data->_fullScreenWindowController.get() setWebView:self]; + } + return _data->_fullScreenWindowController.get(); +} +#endif + @end @implementation WKView (Private) @@ -2033,5 +2085,19 @@ static void drawPageBackground(CGContextRef context, WebPageProxy* page, const I _data->_page->performDictionaryLookupAtLocation(FloatPoint(thePoint.x, thePoint.y)); } +- (NSInteger)spellCheckerDocumentTag +{ + if (!_data->_hasSpellCheckerDocumentTag) { + _data->_spellCheckerDocumentTag = [NSSpellChecker uniqueSpellDocumentTag]; + _data->_hasSpellCheckerDocumentTag = YES; + } + return _data->_spellCheckerDocumentTag; +} + +- (void)handleCorrectionPanelResult:(NSString*)result +{ + _data->_page->handleCorrectionPanelResult(result); +} + @end diff --git a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h index 4147658..e4a40f7 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h +++ b/Source/WebKit2/UIProcess/API/mac/WKViewInternal.h @@ -27,11 +27,20 @@ #import <WebCore/Editor.h> #import <WebCore/KeyboardEvent.h> +namespace CoreIPC { + class DataReference; +} + namespace WebKit { class DrawingAreaProxy; class FindIndicator; + class LayerTreeContext; } +#if ENABLE(FULLSCREEN_API) +@class WKFullScreenWindowController; +#endif + @interface WKView (Internal) - (PassOwnPtr<WebKit::DrawingAreaProxy>)_createDrawingAreaProxy; - (BOOL)_isFocused; @@ -44,7 +53,7 @@ namespace WebKit { - (void)_setUserInterfaceItemState:(NSString *)commandName enabled:(BOOL)isEnabled state:(int)newState; - (Vector<WebCore::KeypressCommand>&)_interceptKeyEvent:(NSEvent *)theEvent; - (void)_getTextInputState:(unsigned)start selectionEnd:(unsigned)end underlines:(Vector<WebCore::CompositionUnderline>&)lines; -- (void)_setEventBeingResent:(NSEvent *)event; +- (void)_resendKeyDownEvent:(NSEvent *)event; - (NSRect)_convertToDeviceSpace:(NSRect)rect; - (NSRect)_convertToUserSpace:(NSRect)rect; - (void)_setFindIndicator:(PassRefPtr<WebKit::FindIndicator>)findIndicator fadeOut:(BOOL)fadeOut; @@ -64,4 +73,8 @@ namespace WebKit { - (void)_setDrawingAreaSize:(NSSize)size; - (void)_didChangeScrollbarsForMainFrame; + +#if ENABLE(FULLSCREEN_API) +- (WKFullScreenWindowController*)fullScreenWindowController; +#endif @end diff --git a/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h b/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h index cece1c7..37c2d8d 100644 --- a/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h +++ b/Source/WebKit2/UIProcess/API/mac/WKViewPrivate.h @@ -35,4 +35,6 @@ - (void)performDictionaryLookupAtCurrentMouseLocation; +- (NSInteger)spellCheckerDocumentTag; +- (void)handleCorrectionPanelResult:(NSString*)result; @end |