| /* |
| * 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 |
| * 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 "PageClientImpl.h" |
| |
| #import "DataReference.h" |
| #import "DictionaryPopupInfo.h" |
| #import "FindIndicator.h" |
| #import "NativeWebKeyboardEvent.h" |
| #import "WKAPICast.h" |
| #import "WKStringCF.h" |
| #import "WKViewInternal.h" |
| #import "WebContextMenuProxyMac.h" |
| #import "WebEditCommandProxy.h" |
| #import "WebPopupMenuProxyMac.h" |
| #import <WebCore/Cursor.h> |
| #import <WebCore/FloatRect.h> |
| #import <WebCore/FoundationExtras.h> |
| #import <WebCore/GraphicsContext.h> |
| #import <WebCore/KeyboardEvent.h> |
| #import <WebCore/NotImplemented.h> |
| #import <wtf/PassOwnPtr.h> |
| #import <wtf/text/CString.h> |
| #import <wtf/text/WTFString.h> |
| #import <WebKitSystemInterface.h> |
| |
| @interface NSApplication (WebNSApplicationDetails) |
| - (NSCursor *)_cursorRectCursor; |
| @end |
| |
| using namespace WebCore; |
| using namespace WebKit; |
| |
| @interface WKEditCommandObjC : NSObject |
| { |
| RefPtr<WebEditCommandProxy> m_command; |
| } |
| - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command; |
| - (WebEditCommandProxy*)command; |
| @end |
| |
| @interface WKEditorUndoTargetObjC : NSObject |
| - (void)undoEditing:(id)sender; |
| - (void)redoEditing:(id)sender; |
| @end |
| |
| @implementation WKEditCommandObjC |
| |
| - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command |
| { |
| self = [super init]; |
| if (!self) |
| return nil; |
| |
| m_command = command; |
| return self; |
| } |
| |
| - (WebEditCommandProxy*)command |
| { |
| return m_command.get(); |
| } |
| |
| @end |
| |
| @implementation WKEditorUndoTargetObjC |
| |
| - (void)undoEditing:(id)sender |
| { |
| ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]); |
| [sender command]->unapply(); |
| } |
| |
| - (void)redoEditing:(id)sender |
| { |
| ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]); |
| [sender command]->reapply(); |
| } |
| |
| @end |
| |
| namespace WebKit { |
| |
| NSString* nsStringFromWebCoreString(const String& string) |
| { |
| return string.impl() ? HardAutorelease(WKStringCopyCFString(0, toAPI(string.impl()))) : @""; |
| } |
| |
| PassOwnPtr<PageClientImpl> PageClientImpl::create(WKView* wkView) |
| { |
| return adoptPtr(new PageClientImpl(wkView)); |
| } |
| |
| PageClientImpl::PageClientImpl(WKView* wkView) |
| : m_wkView(wkView) |
| , m_undoTarget(AdoptNS, [[WKEditorUndoTargetObjC alloc] init]) |
| { |
| } |
| |
| PageClientImpl::~PageClientImpl() |
| { |
| } |
| |
| PassOwnPtr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy() |
| { |
| return [m_wkView _createDrawingAreaProxy]; |
| } |
| |
| void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect) |
| { |
| [m_wkView setNeedsDisplayInRect:rect]; |
| } |
| |
| void PageClientImpl::displayView() |
| { |
| [m_wkView displayIfNeeded]; |
| } |
| |
| void PageClientImpl::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset) |
| { |
| NSRect clippedScrollRect = NSIntersectionRect(scrollRect, NSOffsetRect(scrollRect, -scrollOffset.width(), -scrollOffset.height())); |
| |
| [m_wkView translateRectsNeedingDisplayInRect:clippedScrollRect by:scrollOffset]; |
| [m_wkView scrollRect:clippedScrollRect by:scrollOffset]; |
| } |
| |
| IntSize PageClientImpl::viewSize() |
| { |
| return IntSize([m_wkView bounds].size); |
| } |
| |
| bool PageClientImpl::isViewWindowActive() |
| { |
| return [[m_wkView window] isKeyWindow] || [NSApp keyWindow] == [m_wkView window]; |
| } |
| |
| bool PageClientImpl::isViewFocused() |
| { |
| return [m_wkView _isFocused]; |
| } |
| |
| bool PageClientImpl::isViewVisible() |
| { |
| if (![m_wkView window]) |
| return false; |
| |
| if (![[m_wkView window] isVisible]) |
| return false; |
| |
| if ([m_wkView isHiddenOrHasHiddenAncestor]) |
| return false; |
| |
| return true; |
| } |
| |
| bool PageClientImpl::isViewInWindow() |
| { |
| return [m_wkView window]; |
| } |
| |
| void PageClientImpl::processDidCrash() |
| { |
| [m_wkView _processDidCrash]; |
| } |
| |
| void PageClientImpl::pageClosed() |
| { |
| [m_wkView _pageClosed]; |
| } |
| |
| void PageClientImpl::didRelaunchProcess() |
| { |
| [m_wkView _didRelaunchProcess]; |
| } |
| |
| void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip) |
| { |
| [m_wkView _toolTipChangedFrom:nsStringFromWebCoreString(oldToolTip) to:nsStringFromWebCoreString(newToolTip)]; |
| } |
| |
| void PageClientImpl::setCursor(const WebCore::Cursor& cursor) |
| { |
| if (![NSApp _cursorRectCursor]) |
| [m_wkView _setCursor:cursor.platformCursor()]; |
| } |
| |
| void PageClientImpl::setViewportArguments(const WebCore::ViewportArguments&) |
| { |
| } |
| |
| void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo) |
| { |
| RefPtr<WebEditCommandProxy> command = prpCommand; |
| |
| RetainPtr<WKEditCommandObjC> commandObjC(AdoptNS, [[WKEditCommandObjC alloc] initWithWebEditCommandProxy:command]); |
| String actionName = WebEditCommandProxy::nameForEditAction(command->editAction()); |
| |
| NSUndoManager *undoManager = [m_wkView undoManager]; |
| [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == WebPageProxy::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()]; |
| if (!actionName.isEmpty()) |
| [undoManager setActionName:(NSString *)actionName]; |
| } |
| |
| void PageClientImpl::clearAllEditCommands() |
| { |
| [[m_wkView undoManager] removeAllActionsWithTarget:m_undoTarget.get()]; |
| } |
| |
| bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo) |
| { |
| return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] canUndo] : [[m_wkView undoManager] canRedo]; |
| } |
| |
| void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo) |
| { |
| return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] undo] : [[m_wkView undoManager] redo]; |
| } |
| |
| bool PageClientImpl::interpretKeyEvent(const NativeWebKeyboardEvent& event, Vector<WebCore::KeypressCommand>& commands) |
| { |
| return [m_wkView _interpretKeyEvent:event.nativeEvent() savingCommandsTo:commands]; |
| } |
| |
| void PageClientImpl::setDragImage(const IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag) |
| { |
| 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]; |
| } |
| |
| void PageClientImpl::updateSecureInputState() |
| { |
| [m_wkView _updateSecureInputState]; |
| } |
| |
| FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect) |
| { |
| return [m_wkView _convertToDeviceSpace:rect]; |
| } |
| |
| 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) |
| { |
| NSEvent* nativeEvent = event.nativeEvent(); |
| if ([nativeEvent type] != NSKeyDown) |
| return; |
| if (wasEventHandled) |
| [NSCursor setHiddenUntilMouseMoves:YES]; |
| else |
| [m_wkView _resendKeyDownEvent:nativeEvent]; |
| } |
| |
| PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page) |
| { |
| return WebPopupMenuProxyMac::create(m_wkView, page); |
| } |
| |
| PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy* page) |
| { |
| return WebContextMenuProxyMac::create(m_wkView, page); |
| } |
| |
| void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, bool fadeOut) |
| { |
| [m_wkView _setFindIndicator:findIndicator fadeOut:fadeOut]; |
| } |
| |
| void PageClientImpl::accessibilityWebProcessTokenReceived(const CoreIPC::DataReference& data) |
| { |
| NSData* remoteToken = [NSData dataWithBytes:data.data() length:data.size()]; |
| [m_wkView _setAccessibilityWebProcessToken:remoteToken]; |
| } |
| |
| #if USE(ACCELERATED_COMPOSITING) |
| void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext) |
| { |
| [m_wkView _enterAcceleratedCompositingMode:layerTreeContext]; |
| } |
| |
| void PageClientImpl::exitAcceleratedCompositingMode() |
| { |
| [m_wkView _exitAcceleratedCompositingMode]; |
| } |
| #endif // USE(ACCELERATED_COMPOSITING) |
| |
| void PageClientImpl::setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled) |
| { |
| [m_wkView _setComplexTextInputEnabled:complexTextInputEnabled pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier]; |
| } |
| |
| CGContextRef PageClientImpl::containingWindowGraphicsContext() |
| { |
| NSWindow *window = [m_wkView window]; |
| |
| // Don't try to get the graphics context if the NSWindow doesn't have a window device. |
| if ([window windowNumber] <= 0) |
| return 0; |
| |
| return static_cast<CGContextRef>([[window graphicsContext] graphicsPort]); |
| } |
| |
| void PageClientImpl::didChangeScrollbarsForMainFrame() const |
| { |
| [m_wkView _didChangeScrollbarsForMainFrame]; |
| } |
| |
| void PageClientImpl::didCommitLoadForMainFrame(bool useCustomRepresentation) |
| { |
| [m_wkView _setPageHasCustomRepresentation:useCustomRepresentation]; |
| } |
| |
| void PageClientImpl::didFinishLoadingDataForCustomRepresentation(const String& suggestedFilename, const CoreIPC::DataReference& dataReference) |
| { |
| [m_wkView _didFinishLoadingDataForCustomRepresentationWithSuggestedFilename:suggestedFilename dataReference:dataReference]; |
| } |
| |
| double PageClientImpl::customRepresentationZoomFactor() |
| { |
| return [m_wkView _customRepresentationZoomFactor]; |
| } |
| |
| void PageClientImpl::setCustomRepresentationZoomFactor(double zoomFactor) |
| { |
| [m_wkView _setCustomRepresentationZoomFactor:zoomFactor]; |
| } |
| |
| void PageClientImpl::findStringInCustomRepresentation(const String& string, FindOptions options, unsigned maxMatchCount) |
| { |
| [m_wkView _findStringInCustomRepresentation:string withFindOptions:options maxMatchCount:maxMatchCount]; |
| } |
| |
| void PageClientImpl::countStringMatchesInCustomRepresentation(const String& string, FindOptions options, unsigned maxMatchCount) |
| { |
| [m_wkView _countStringMatchesInCustomRepresentation:string withFindOptions:options maxMatchCount:maxMatchCount]; |
| } |
| |
| void PageClientImpl::flashBackingStoreUpdates(const Vector<IntRect>&) |
| { |
| notImplemented(); |
| } |
| |
| void PageClientImpl::didPerformDictionaryLookup(const String& text, double scaleFactor, const DictionaryPopupInfo& dictionaryPopupInfo) |
| { |
| NSFontDescriptor *fontDescriptor = [NSFontDescriptor fontDescriptorWithFontAttributes:(NSDictionary *)dictionaryPopupInfo.fontInfo.fontAttributeDictionary.get()]; |
| NSFont *font = [NSFont fontWithDescriptor:fontDescriptor size:((scaleFactor != 1) ? [fontDescriptor pointSize] * scaleFactor : 0)]; |
| |
| RetainPtr<NSMutableAttributedString> attributedString(AdoptNS, [[NSMutableAttributedString alloc] initWithString:nsStringFromWebCoreString(text)]); |
| [attributedString.get() addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, [attributedString.get() length])]; |
| |
| 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::dismissDictionaryLookupPanel() |
| { |
| #if !defined(BUILDING_ON_SNOW_LEOPARD) |
| WKHideWordDefinitionWindow(); |
| #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 |
| } |
| |
| bool PageClientImpl::executeSavedCommandBySelector(const String& selectorString) |
| { |
| return [m_wkView _executeSavedCommandBySelector:NSSelectorFromString(selectorString)]; |
| } |
| |
| } // namespace WebKit |