PageClientImpl.mm revision 2fc2651226baac27029e38c9d6ef883fa32084db
1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27#import "PageClientImpl.h" 28 29#import "DataReference.h" 30#import "FindIndicator.h" 31#import "NativeWebKeyboardEvent.h" 32#import "WKAPICast.h" 33#import "WKStringCF.h" 34#import "WKViewInternal.h" 35#import "WebContextMenuProxyMac.h" 36#import "WebEditCommandProxy.h" 37#import "WebPopupMenuProxyMac.h" 38#import <WebCore/Cursor.h> 39#import <WebCore/FloatRect.h> 40#import <WebCore/FoundationExtras.h> 41#import <WebCore/GraphicsContext.h> 42#import <WebCore/KeyboardEvent.h> 43#import <wtf/PassOwnPtr.h> 44#import <wtf/text/CString.h> 45#import <wtf/text/WTFString.h> 46 47@interface NSApplication (WebNSApplicationDetails) 48- (NSCursor *)_cursorRectCursor; 49@end 50 51using namespace WebCore; 52 53@interface WebEditCommandObjC : NSObject 54{ 55 RefPtr<WebKit::WebEditCommandProxy> m_command; 56} 57 58- (id)initWithWebEditCommandProxy:(PassRefPtr<WebKit::WebEditCommandProxy>)command; 59- (WebKit::WebEditCommandProxy*)command; 60 61@end 62 63@implementation WebEditCommandObjC 64 65- (id)initWithWebEditCommandProxy:(PassRefPtr<WebKit::WebEditCommandProxy>)command 66{ 67 self = [super init]; 68 if (!self) 69 return nil; 70 71 m_command = command; 72 return self; 73} 74 75- (WebKit::WebEditCommandProxy*)command 76{ 77 return m_command.get(); 78} 79 80@end 81 82@interface WebEditorUndoTargetObjC : NSObject 83 84- (void)undoEditing:(id)sender; 85- (void)redoEditing:(id)sender; 86 87@end 88 89@implementation WebEditorUndoTargetObjC 90 91- (void)undoEditing:(id)sender 92{ 93 ASSERT([sender isKindOfClass:[WebEditCommandObjC class]]); 94 [sender command]->unapply(); 95} 96 97- (void)redoEditing:(id)sender 98{ 99 ASSERT([sender isKindOfClass:[WebEditCommandObjC class]]); 100 [sender command]->reapply(); 101} 102 103@end 104 105namespace WebKit { 106 107NSString* nsStringFromWebCoreString(const String& string) 108{ 109 return string.impl() ? HardAutorelease(WKStringCopyCFString(0, toAPI(string.impl()))) : @""; 110} 111 112PassOwnPtr<PageClientImpl> PageClientImpl::create(WKView* wkView) 113{ 114 return adoptPtr(new PageClientImpl(wkView)); 115} 116 117PageClientImpl::PageClientImpl(WKView* wkView) 118 : m_wkView(wkView) 119 , m_undoTarget(AdoptNS, [[WebEditorUndoTargetObjC alloc] init]) 120{ 121} 122 123PageClientImpl::~PageClientImpl() 124{ 125} 126 127PassOwnPtr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy() 128{ 129 return [m_wkView _createDrawingAreaProxy]; 130} 131 132void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect) 133{ 134 [m_wkView setNeedsDisplayInRect:rect]; 135} 136 137void PageClientImpl::displayView() 138{ 139 [m_wkView displayIfNeeded]; 140} 141 142void PageClientImpl::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset) 143{ 144 NSRect clippedScrollRect = NSIntersectionRect(scrollRect, NSOffsetRect(scrollRect, -scrollOffset.width(), -scrollOffset.height())); 145 146 [m_wkView translateRectsNeedingDisplayInRect:clippedScrollRect by:scrollOffset]; 147 [m_wkView scrollRect:clippedScrollRect by:scrollOffset]; 148} 149 150IntSize PageClientImpl::viewSize() 151{ 152 return IntSize([m_wkView bounds].size); 153} 154 155bool PageClientImpl::isViewWindowActive() 156{ 157 return [[m_wkView window] isKeyWindow]; 158} 159 160bool PageClientImpl::isViewFocused() 161{ 162 return [m_wkView _isFocused]; 163} 164 165bool PageClientImpl::isViewVisible() 166{ 167 if (![m_wkView window]) 168 return false; 169 170 if ([m_wkView isHiddenOrHasHiddenAncestor]) 171 return false; 172 173 return true; 174} 175 176bool PageClientImpl::isViewInWindow() 177{ 178 return [m_wkView window]; 179} 180 181void PageClientImpl::processDidCrash() 182{ 183 [m_wkView _processDidCrash]; 184} 185 186void PageClientImpl::pageClosed() 187{ 188 [m_wkView _pageClosed]; 189} 190 191void PageClientImpl::didRelaunchProcess() 192{ 193 [m_wkView _didRelaunchProcess]; 194} 195 196void PageClientImpl::takeFocus(bool direction) 197{ 198 [m_wkView _takeFocus:direction]; 199} 200 201void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip) 202{ 203 [m_wkView _toolTipChangedFrom:nsStringFromWebCoreString(oldToolTip) to:nsStringFromWebCoreString(newToolTip)]; 204} 205 206void PageClientImpl::setCursor(const WebCore::Cursor& cursor) 207{ 208 if (![NSApp _cursorRectCursor]) 209 [m_wkView _setCursor:cursor.platformCursor()]; 210} 211 212void PageClientImpl::setViewportArguments(const WebCore::ViewportArguments&) 213{ 214 215} 216 217static NSString* nameForEditAction(EditAction editAction) 218{ 219 // FIXME: Use localized strings. 220 // FIXME: Move this to a platform independent location. 221 222 switch (editAction) { 223 case EditActionUnspecified: return nil; 224 case EditActionSetColor: return @"Set Color"; 225 case EditActionSetBackgroundColor: return @"Set Background Color"; 226 case EditActionTurnOffKerning: return @"Turn Off Kerning"; 227 case EditActionTightenKerning: return @"Tighten Kerning"; 228 case EditActionLoosenKerning: return @"Loosen Kerning"; 229 case EditActionUseStandardKerning: return @"Use Standard Kerning"; 230 case EditActionTurnOffLigatures: return @"Turn Off Ligatures"; 231 case EditActionUseStandardLigatures: return @"Use Standard Ligatures"; 232 case EditActionUseAllLigatures: return @"Use All Ligatures"; 233 case EditActionRaiseBaseline: return @"Raise Baseline"; 234 case EditActionLowerBaseline: return @"Lower Baseline"; 235 case EditActionSetTraditionalCharacterShape: return @"Set Traditional Character Shape"; 236 case EditActionSetFont: return @"Set Font"; 237 case EditActionChangeAttributes: return @"Change Attributes"; 238 case EditActionAlignLeft: return @"Align Left"; 239 case EditActionAlignRight: return @"Align Right"; 240 case EditActionCenter: return @"Center"; 241 case EditActionJustify: return @"Justify"; 242 case EditActionSetWritingDirection: return @"Set Writing Direction"; 243 case EditActionSubscript: return @"Subscript"; 244 case EditActionSuperscript: return @"Superscript"; 245 case EditActionUnderline: return @"Underline"; 246 case EditActionOutline: return @"Outline"; 247 case EditActionUnscript: return @"Unscript"; 248 case EditActionDrag: return @"Drag"; 249 case EditActionCut: return @"Cut"; 250 case EditActionPaste: return @"Paste"; 251 case EditActionPasteFont: return @"Paste Font"; 252 case EditActionPasteRuler: return @"Paste Ruler"; 253 case EditActionTyping: return @"Typing"; 254 case EditActionCreateLink: return @"Create Link"; 255 case EditActionUnlink: return @"Unlink"; 256 case EditActionInsertList: return @"Insert List"; 257 case EditActionFormatBlock: return @"Formatting"; 258 case EditActionIndent: return @"Indent"; 259 case EditActionOutdent: return @"Outdent"; 260 } 261 return nil; 262} 263 264void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo) 265{ 266 RefPtr<WebEditCommandProxy> command = prpCommand; 267 268 RetainPtr<WebEditCommandObjC> commandObjC(AdoptNS, [[WebEditCommandObjC alloc] initWithWebEditCommandProxy:command]); 269 NSString *actionName = nameForEditAction(command->editAction()); 270 271 NSUndoManager *undoManager = [m_wkView undoManager]; 272 [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == WebPageProxy::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()]; 273 if (actionName) 274 [undoManager setActionName:actionName]; 275} 276 277void PageClientImpl::clearAllEditCommands() 278{ 279 [[m_wkView undoManager] removeAllActionsWithTarget:m_undoTarget.get()]; 280} 281 282void PageClientImpl::setEditCommandState(const String& commandName, bool isEnabled, int newState) 283{ 284 [m_wkView _setUserInterfaceItemState:nsStringFromWebCoreString(commandName) enabled:isEnabled state:newState]; 285} 286 287void PageClientImpl::interceptKeyEvent(const NativeWebKeyboardEvent& event, Vector<WebCore::KeypressCommand>& commandsList, uint32_t selectionStart, uint32_t selectionEnd, Vector<WebCore::CompositionUnderline>& underlines) 288{ 289 commandsList = [m_wkView _interceptKeyEvent:event.nativeEvent()]; 290 [m_wkView _getTextInputState:selectionStart selectionEnd:selectionEnd underlines:underlines]; 291} 292 293void PageClientImpl::setDragImage(const IntPoint& clientPosition, const IntSize& imageSize, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag) 294{ 295 OwnPtr<GraphicsContext> graphicsContext = dragImage->createGraphicsContext(); 296 RetainPtr<NSImage> dragNSImage(AdoptNS, [[NSImage alloc] initWithCGImage:CGBitmapContextCreateImage(graphicsContext->platformContext()) size:imageSize]); 297 [dragNSImage.get() setFlipped:YES]; 298 [m_wkView _setDragImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag]; 299} 300 301FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect) 302{ 303 return [m_wkView _convertToDeviceSpace:rect]; 304} 305 306FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect) 307{ 308 return [m_wkView _convertToUserSpace:rect]; 309} 310 311void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool wasEventHandled) 312{ 313 NSEvent* nativeEvent = event.nativeEvent(); 314 if ([nativeEvent type] != NSKeyDown) 315 return; 316 if (wasEventHandled) 317 [NSCursor setHiddenUntilMouseMoves:YES]; 318 else { 319 [m_wkView _setEventBeingResent:nativeEvent]; 320 [[NSApplication sharedApplication] sendEvent:nativeEvent]; 321 } 322} 323 324PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page) 325{ 326 return WebPopupMenuProxyMac::create(m_wkView, page); 327} 328 329PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy* page) 330{ 331 return WebContextMenuProxyMac::create(m_wkView, page); 332} 333 334void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator> findIndicator, bool fadeOut) 335{ 336 [m_wkView _setFindIndicator:findIndicator fadeOut:fadeOut]; 337} 338 339void PageClientImpl::accessibilityWebProcessTokenReceived(const CoreIPC::DataReference& data) 340{ 341 NSData* remoteToken = [NSData dataWithBytes:data.data() length:data.size()]; 342 [m_wkView _setAccessibilityWebProcessToken:remoteToken]; 343} 344 345#if USE(ACCELERATED_COMPOSITING) 346void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext) 347{ 348 [m_wkView _enterAcceleratedCompositingMode:layerTreeContext]; 349} 350 351void PageClientImpl::exitAcceleratedCompositingMode() 352{ 353 [m_wkView _exitAcceleratedCompositingMode]; 354} 355 356void PageClientImpl::pageDidEnterAcceleratedCompositing() 357{ 358 [m_wkView _pageDidEnterAcceleratedCompositing]; 359} 360 361void PageClientImpl::pageDidLeaveAcceleratedCompositing() 362{ 363 [m_wkView _pageDidLeaveAcceleratedCompositing]; 364} 365#endif // USE(ACCELERATED_COMPOSITING) 366 367void PageClientImpl::setComplexTextInputEnabled(uint64_t pluginComplexTextInputIdentifier, bool complexTextInputEnabled) 368{ 369 [m_wkView _setComplexTextInputEnabled:complexTextInputEnabled pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier]; 370} 371 372void PageClientImpl::setAutodisplay(bool newState) 373{ 374 if (!newState && [[m_wkView window] isAutodisplay]) 375 [m_wkView displayIfNeeded]; 376 377 [[m_wkView window] setAutodisplay:newState]; 378} 379 380CGContextRef PageClientImpl::containingWindowGraphicsContext() 381{ 382 return static_cast<CGContextRef>([[[m_wkView window] graphicsContext] graphicsPort]); 383} 384 385void PageClientImpl::didChangeScrollbarsForMainFrame() const 386{ 387 [m_wkView _didChangeScrollbarsForMainFrame]; 388} 389 390void PageClientImpl::didCommitLoadForMainFrame(bool useCustomRepresentation) 391{ 392 [m_wkView _setPageHasCustomRepresentation:useCustomRepresentation]; 393} 394 395void PageClientImpl::didFinishLoadingDataForCustomRepresentation(const CoreIPC::DataReference& dataReference) 396{ 397 [m_wkView _didFinishLoadingDataForCustomRepresentation:dataReference]; 398} 399 400double PageClientImpl::customRepresentationZoomFactor() 401{ 402 return [m_wkView _customRepresentationZoomFactor]; 403} 404 405void PageClientImpl::setCustomRepresentationZoomFactor(double zoomFactor) 406{ 407 [m_wkView _setCustomRepresentationZoomFactor:zoomFactor]; 408} 409 410} // namespace WebKit 411