TextIndicator (and other view-relative subwindows) is not dismissed on zoom gesture
[WebKit-https.git] / Source / WebKit2 / UIProcess / mac / PageClientImpl.mm
1 /*
2  * Copyright (C) 2010, 2011 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 #if PLATFORM(MAC)
30
31 #import "AttributedString.h"
32 #import "ColorSpaceData.h"
33 #import "DataReference.h"
34 #import "DictionaryPopupInfo.h"
35 #import "DownloadProxy.h"
36 #import "NativeWebKeyboardEvent.h"
37 #import "NativeWebWheelEvent.h"
38 #import "NavigationState.h"
39 #import "StringUtilities.h"
40 #import "ViewSnapshotStore.h"
41 #import "WKAPICast.h"
42 #import "WKFullScreenWindowController.h"
43 #import "WKStringCF.h"
44 #import "WKViewInternal.h"
45 #import "WKWebViewInternal.h"
46 #import "WebColorPickerMac.h"
47 #import "WebContextMenuProxyMac.h"
48 #import "WebEditCommandProxy.h"
49 #import "WebPopupMenuProxyMac.h"
50 #import "WindowServerConnection.h"
51 #import "_WKDownloadInternal.h"
52 #import "_WKThumbnailView.h"
53 #import <WebCore/AlternativeTextUIController.h>
54 #import <WebCore/BitmapImage.h>
55 #import <WebCore/Cursor.h>
56 #import <WebCore/FloatRect.h>
57 #import <WebCore/GraphicsContext.h>
58 #import <WebCore/Image.h>
59 #import <WebCore/KeyboardEvent.h>
60 #import <WebCore/LookupSPI.h>
61 #import <WebCore/NotImplemented.h>
62 #import <WebCore/SharedBuffer.h>
63 #import <WebCore/TextIndicator.h>
64 #import <WebCore/TextUndoInsertionMarkupMac.h>
65 #import <WebKitSystemInterface.h>
66 #import <wtf/text/CString.h>
67 #import <wtf/text/WTFString.h>
68
69 #if USE(DICTATION_ALTERNATIVES)
70 #import <AppKit/NSTextAlternatives.h>
71 #endif
72
73 @interface NSApplication (WebNSApplicationDetails)
74 - (NSCursor *)_cursorRectCursor;
75 @end
76
77 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
78 @interface NSWindow (WebNSWindowDetails)
79 - (BOOL)_hostsLayersInWindowServer;
80 @end
81 #endif
82
83 SOFT_LINK_CONSTANT_MAY_FAIL(Lookup, LUTermOptionDisableSearchTermIndicator, NSString *)
84
85 using namespace WebCore;
86 using namespace WebKit;
87
88 @interface WKEditCommandObjC : NSObject
89 {
90     RefPtr<WebEditCommandProxy> m_command;
91 }
92 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command;
93 - (WebEditCommandProxy*)command;
94 @end
95
96 @interface WKEditorUndoTargetObjC : NSObject
97 - (void)undoEditing:(id)sender;
98 - (void)redoEditing:(id)sender;
99 @end
100
101 @implementation WKEditCommandObjC
102
103 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command
104 {
105     self = [super init];
106     if (!self)
107         return nil;
108
109     m_command = command;
110     return self;
111 }
112
113 - (WebEditCommandProxy*)command
114 {
115     return m_command.get();
116 }
117
118 @end
119
120 @implementation WKEditorUndoTargetObjC
121
122 - (void)undoEditing:(id)sender
123 {
124     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
125     [sender command]->unapply();
126 }
127
128 - (void)redoEditing:(id)sender
129 {
130     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
131     [sender command]->reapply();
132 }
133
134 @end
135
136 namespace WebKit {
137
138 PageClientImpl::PageClientImpl(WKView* wkView, WKWebView *webView)
139     : m_wkView(wkView)
140     , m_webView(webView)
141     , m_undoTarget(adoptNS([[WKEditorUndoTargetObjC alloc] init]))
142 #if USE(DICTATION_ALTERNATIVES)
143     , m_alternativeTextUIController(adoptPtr(new AlternativeTextUIController))
144 #endif
145 {
146 #if !WK_API_ENABLED
147     ASSERT_UNUSED(m_webView, !m_webView);
148 #endif
149 }
150
151 PageClientImpl::~PageClientImpl()
152 {
153 }
154
155 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
156 {
157     return [m_wkView _createDrawingAreaProxy];
158 }
159
160 void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect)
161 {
162     ASSERT_NOT_REACHED();
163 }
164
165 void PageClientImpl::displayView()
166 {
167     ASSERT_NOT_REACHED();
168 }
169
170 bool PageClientImpl::canScrollView()
171 {
172     return false;
173 }
174
175 void PageClientImpl::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
176 {
177     ASSERT_NOT_REACHED();
178 }
179
180 void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
181 {
182     ASSERT_NOT_REACHED();
183 }
184
185 IntSize PageClientImpl::viewSize()
186 {
187     return IntSize([m_wkView bounds].size);
188 }
189
190 NSView *PageClientImpl::activeView() const
191 {
192 #if WK_API_ENABLED
193     return m_wkView._thumbnailView ? (NSView *)m_wkView._thumbnailView : (NSView *)m_wkView;
194 #else
195     return m_wkView;
196 #endif
197 }
198
199 NSWindow *PageClientImpl::activeWindow() const
200 {
201 #if WK_API_ENABLED
202     if (m_wkView._thumbnailView)
203         return m_wkView._thumbnailView.window;
204 #endif
205     if (m_wkView._targetWindowForMovePreparation)
206         return m_wkView._targetWindowForMovePreparation;
207     return m_wkView.window;
208 }
209
210 bool PageClientImpl::isViewWindowActive()
211 {
212     NSWindow *activeViewWindow = activeWindow();
213     return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
214 }
215
216 bool PageClientImpl::isViewFocused()
217 {
218     return [m_wkView _isFocused];
219 }
220
221 void PageClientImpl::makeFirstResponder()
222 {
223      [[m_wkView window] makeFirstResponder:m_wkView];
224 }
225     
226 bool PageClientImpl::isViewVisible()
227 {
228     NSView *activeView = this->activeView();
229     NSWindow *activeViewWindow = activeWindow();
230
231     if (!activeViewWindow)
232         return false;
233
234     if (!activeViewWindow.isVisible)
235         return false;
236
237 #if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
238     // Mountain Lion and previous do not support occlusion notifications, and as such will
239     // continue to report as "visible" when not on the active space.
240     if (!activeViewWindow.isOnActiveSpace)
241         return false;
242 #endif
243
244     if (activeView.isHiddenOrHasHiddenAncestor)
245         return false;
246
247 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090
248     if ([m_wkView windowOcclusionDetectionEnabled] && (activeViewWindow.occlusionState & NSWindowOcclusionStateVisible) != NSWindowOcclusionStateVisible)
249         return false;
250 #endif
251
252     return true;
253 }
254
255 bool PageClientImpl::isViewVisibleOrOccluded()
256 {
257     return activeWindow().isVisible;
258 }
259
260 bool PageClientImpl::isViewInWindow()
261 {
262     return activeWindow();
263 }
264
265 bool PageClientImpl::isVisuallyIdle()
266 {
267     return WindowServerConnection::shared().applicationWindowModificationsHaveStopped() || !isViewVisible();
268 }
269
270 LayerHostingMode PageClientImpl::viewLayerHostingMode()
271 {
272 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
273     if ([activeWindow() _hostsLayersInWindowServer])
274         return LayerHostingMode::OutOfProcess;
275 #endif
276     return LayerHostingMode::InProcess;
277 }
278
279 void PageClientImpl::viewWillMoveToAnotherWindow()
280 {
281     clearAllEditCommands();
282 }
283
284 ColorSpaceData PageClientImpl::colorSpace()
285 {
286     return [m_wkView _colorSpace];
287 }
288
289 void PageClientImpl::processDidExit()
290 {
291     [m_wkView _processDidExit];
292 }
293
294 void PageClientImpl::pageClosed()
295 {
296     [m_wkView _pageClosed];
297 #if USE(DICTATION_ALTERNATIVES)
298     m_alternativeTextUIController->clear();
299 #endif
300 }
301
302 void PageClientImpl::didRelaunchProcess()
303 {
304     [m_wkView _didRelaunchProcess];
305 }
306
307 void PageClientImpl::preferencesDidChange()
308 {
309     [m_wkView _preferencesDidChange];
310 }
311
312 void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip)
313 {
314     [m_wkView _toolTipChangedFrom:nsStringFromWebCoreString(oldToolTip) to:nsStringFromWebCoreString(newToolTip)];
315 }
316
317 void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
318 {
319 }
320
321 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
322 {
323 }
324
325 void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
326 {
327     ASSERT_ARG(download, download);
328 #if WK_API_ENABLED
329     ASSERT([download->wrapper() isKindOfClass:[_WKDownload class]]);
330     [static_cast<_WKDownload *>(download->wrapper()) setOriginatingWebView:m_webView];
331 #endif
332 }
333
334 void PageClientImpl::setCursor(const WebCore::Cursor& cursor)
335 {
336     // FIXME: Would be nice to share this code with WebKit1's WebChromeClient.
337
338     if ([NSApp _cursorRectCursor])
339         return;
340
341     if (!m_wkView)
342         return;
343
344     NSWindow *window = [m_wkView window];
345     if (!window)
346         return;
347
348     if ([window windowNumber] != [NSWindow windowNumberAtPoint:[NSEvent mouseLocation] belowWindowWithWindowNumber:0])
349         return;
350
351     NSCursor *platformCursor = cursor.platformCursor();
352     if ([NSCursor currentCursor] == platformCursor)
353         return;
354
355     [platformCursor set];
356 }
357
358 void PageClientImpl::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
359 {
360     [NSCursor setHiddenUntilMouseMoves:hiddenUntilMouseMoves];
361 }
362
363 void PageClientImpl::didChangeViewportProperties(const WebCore::ViewportAttributes&)
364 {
365 }
366
367 void PageClientImpl::registerEditCommand(PassRefPtr<WebEditCommandProxy> prpCommand, WebPageProxy::UndoOrRedo undoOrRedo)
368 {
369     RefPtr<WebEditCommandProxy> command = prpCommand;
370
371     RetainPtr<WKEditCommandObjC> commandObjC = adoptNS([[WKEditCommandObjC alloc] initWithWebEditCommandProxy:command]);
372     String actionName = WebEditCommandProxy::nameForEditAction(command->editAction());
373
374     NSUndoManager *undoManager = [m_wkView undoManager];
375     [undoManager registerUndoWithTarget:m_undoTarget.get() selector:((undoOrRedo == WebPageProxy::Undo) ? @selector(undoEditing:) : @selector(redoEditing:)) object:commandObjC.get()];
376     if (!actionName.isEmpty())
377         [undoManager setActionName:(NSString *)actionName];
378 }
379
380 #if USE(INSERTION_UNDO_GROUPING)
381 void PageClientImpl::registerInsertionUndoGrouping()
382 {
383     registerInsertionUndoGroupingWithUndoManager([m_wkView undoManager]);
384 }
385 #endif
386
387 void PageClientImpl::clearAllEditCommands()
388 {
389     [[m_wkView undoManager] removeAllActionsWithTarget:m_undoTarget.get()];
390 }
391
392 bool PageClientImpl::canUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
393 {
394     return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] canUndo] : [[m_wkView undoManager] canRedo];
395 }
396
397 void PageClientImpl::executeUndoRedo(WebPageProxy::UndoOrRedo undoOrRedo)
398 {
399     return (undoOrRedo == WebPageProxy::Undo) ? [[m_wkView undoManager] undo] : [[m_wkView undoManager] redo];
400 }
401
402 void PageClientImpl::setDragImage(const IntPoint& clientPosition, PassRefPtr<ShareableBitmap> dragImage, bool isLinkDrag)
403 {
404     RetainPtr<CGImageRef> dragCGImage = dragImage->makeCGImage();
405     RetainPtr<NSImage> dragNSImage = adoptNS([[NSImage alloc] initWithCGImage:dragCGImage.get() size:dragImage->size()]);
406
407     [m_wkView _setDragImage:dragNSImage.get() at:clientPosition linkDrag:isLinkDrag];
408 }
409
410 void PageClientImpl::setPromisedData(const String& pasteboardName, PassRefPtr<SharedBuffer> imageBuffer, const String& filename, const String& extension, const String& title, const String& url, const String& visibleUrl, PassRefPtr<SharedBuffer> archiveBuffer)
411 {
412     RefPtr<Image> image = BitmapImage::create();
413     image->setData(imageBuffer.get(), true);
414     [m_wkView _setPromisedData:image.get() withFileName:filename withExtension:extension withTitle:title withURL:url withVisibleURL:visibleUrl withArchive:archiveBuffer.get() forPasteboard:pasteboardName];
415 }
416
417 void PageClientImpl::updateSecureInputState()
418 {
419     [m_wkView _updateSecureInputState];
420 }
421
422 void PageClientImpl::resetSecureInputState()
423 {
424     [m_wkView _resetSecureInputState];
425 }
426
427 void PageClientImpl::notifyInputContextAboutDiscardedComposition()
428 {
429     [m_wkView _notifyInputContextAboutDiscardedComposition];
430 }
431
432 #if PLATFORM(MAC) && !USE(ASYNC_NSTEXTINPUTCLIENT)
433 void PageClientImpl::notifyApplicationAboutInputContextChange()
434 {
435     [NSApp updateWindows];
436 }
437 #endif
438
439 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
440 {
441     return [m_wkView _convertToDeviceSpace:rect];
442 }
443
444 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
445 {
446     return [m_wkView _convertToUserSpace:rect];
447 }
448    
449 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
450 {
451 #pragma clang diagnostic push
452 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
453     NSPoint windowCoord = [[m_wkView window] convertScreenToBase:point];
454 #pragma clang diagnostic pop
455     return IntPoint([m_wkView convertPoint:windowCoord fromView:nil]);
456 }
457     
458 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
459 {
460     NSRect tempRect = rect;
461     tempRect = [m_wkView convertRect:tempRect toView:nil];
462 #pragma clang diagnostic push
463 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
464     tempRect.origin = [[m_wkView window] convertBaseToScreen:tempRect.origin];
465 #pragma clang diagnostic pop
466     return enclosingIntRect(tempRect);
467 }
468
469 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
470 {
471     [m_wkView _doneWithKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
472 }
473
474 PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page)
475 {
476     return WebPopupMenuProxyMac::create(m_wkView, page);
477 }
478
479 PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy* page)
480 {
481     return WebContextMenuProxyMac::create(m_wkView, page);
482 }
483
484 #if ENABLE(INPUT_TYPE_COLOR)
485 PassRefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& initialColor,  const WebCore::IntRect& rect)
486 {
487     return WebColorPickerMac::create(page, initialColor, rect, wkView());
488 }
489 #endif
490
491 void PageClientImpl::setTextIndicator(PassRefPtr<TextIndicator> textIndicator, bool fadeOut)
492 {
493     [m_wkView _setTextIndicator:textIndicator fadeOut:fadeOut];
494 }
495
496 void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
497 {
498     NSData* remoteToken = [NSData dataWithBytes:data.data() length:data.size()];
499     [m_wkView _setAccessibilityWebProcessToken:remoteToken];
500 }
501     
502 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
503 {
504     ASSERT(!layerTreeContext.isEmpty());
505
506     CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID);
507     [m_wkView _setAcceleratedCompositingModeRootLayer:renderLayer];
508 }
509
510 void PageClientImpl::exitAcceleratedCompositingMode()
511 {
512     [m_wkView _setAcceleratedCompositingModeRootLayer:nil];
513 }
514
515 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
516 {
517     ASSERT(!layerTreeContext.isEmpty());
518
519     CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID);
520     [m_wkView _setAcceleratedCompositingModeRootLayer:renderLayer];
521 }
522
523 void PageClientImpl::setAcceleratedCompositingRootLayer(CALayer *rootLayer)
524 {
525     [m_wkView _setAcceleratedCompositingModeRootLayer:rootLayer];
526 }
527
528 CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
529 {
530     return m_wkView._acceleratedCompositingModeRootLayer;
531 }
532
533 PassRefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
534 {
535     return [m_wkView _takeViewSnapshot];
536 }
537
538 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
539 {
540     [m_wkView _wheelEventWasNotHandledByWebCore:event.nativeEvent()];
541 }
542
543 void PageClientImpl::pluginFocusOrWindowFocusChanged(uint64_t pluginComplexTextInputIdentifier, bool pluginHasFocusAndWindowHasFocus)
544 {
545     [m_wkView _pluginFocusOrWindowFocusChanged:pluginHasFocusAndWindowHasFocus pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier];
546 }
547
548 void PageClientImpl::setPluginComplexTextInputState(uint64_t pluginComplexTextInputIdentifier, PluginComplexTextInputState pluginComplexTextInputState)
549 {
550     [m_wkView _setPluginComplexTextInputState:pluginComplexTextInputState pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier];
551 }
552
553 void PageClientImpl::didPerformDictionaryLookup(const DictionaryPopupInfo& dictionaryPopupInfo)
554 {
555     if (!getLULookupDefinitionModuleClass())
556         return;
557
558     NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
559
560     // Convert to screen coordinates.
561     textBaselineOrigin = [m_wkView convertPoint:textBaselineOrigin toView:nil];
562     textBaselineOrigin = [m_wkView.window convertRectToScreen:NSMakeRect(textBaselineOrigin.x, textBaselineOrigin.y, 0, 0)].origin;
563
564     RetainPtr<NSMutableDictionary> mutableOptions = adoptNS([(NSDictionary *)dictionaryPopupInfo.options.get() mutableCopy]);
565
566     if (canLoadLUTermOptionDisableSearchTermIndicator() && dictionaryPopupInfo.textIndicator.contentImage) {
567         // Run the animations serially because attaching another subwindow breaks the bounce animation.
568         // We could consider making the bounce NSAnimationNonblockingThreaded instead, which seems
569         // to work, but need to consider all of the implications.
570         [m_wkView _setTextIndicator:TextIndicator::create(dictionaryPopupInfo.textIndicator) fadeOut:NO animationCompletionHandler:[dictionaryPopupInfo, textBaselineOrigin, mutableOptions] {
571             [mutableOptions setObject:@YES forKey:getLUTermOptionDisableSearchTermIndicator()];
572             [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.string.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
573         }];
574     } else
575         [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.string.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
576 }
577
578 void PageClientImpl::dismissContentRelativeChildWindows()
579 {
580     [m_wkView _dismissContentRelativeChildWindows];
581 }
582
583 void PageClientImpl::showCorrectionPanel(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
584 {
585 #if USE(AUTOCORRECTION_PANEL)
586     if (!isViewVisible() || !isViewInWindow())
587         return;
588     m_correctionPanel.show(m_wkView, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
589 #endif
590 }
591
592 void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingAlternativeText reason)
593 {
594 #if USE(AUTOCORRECTION_PANEL)
595     m_correctionPanel.dismiss(reason);
596 #endif
597 }
598
599 String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText reason)
600 {
601 #if USE(AUTOCORRECTION_PANEL)
602     return m_correctionPanel.dismiss(reason);
603 #else
604     return String();
605 #endif
606 }
607
608 void PageClientImpl::recordAutocorrectionResponse(AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
609 {
610     NSCorrectionResponse response = responseType == AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited;
611     CorrectionPanel::recordAutocorrectionResponse(m_wkView, response, replacedString, replacementString);
612 }
613
614 void PageClientImpl::recommendedScrollbarStyleDidChange(int32_t newStyle)
615 {
616     // Now re-create a tracking area with the appropriate options given the new scrollbar style
617     NSTrackingAreaOptions options = NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect;
618     if (newStyle == NSScrollerStyleLegacy)
619         options |= NSTrackingActiveAlways;
620     else
621         options |= NSTrackingActiveInKeyWindow;
622
623     RetainPtr<NSTrackingArea> trackingArea = adoptNS([[NSTrackingArea alloc] initWithRect:[m_wkView frame] options:options owner:m_wkView userInfo:nil]);
624     [m_wkView _setPrimaryTrackingArea:trackingArea.get()];
625 }
626
627 void PageClientImpl::intrinsicContentSizeDidChange(const IntSize& intrinsicContentSize)
628 {
629     [m_wkView _setIntrinsicContentSize:intrinsicContentSize];
630 }
631
632 bool PageClientImpl::executeSavedCommandBySelector(const String& selectorString)
633 {
634     return [m_wkView _executeSavedCommandBySelector:NSSelectorFromString(selectorString)];
635 }
636
637 #if USE(DICTATION_ALTERNATIVES)
638 uint64_t PageClientImpl::addDictationAlternatives(const RetainPtr<NSTextAlternatives>& alternatives)
639 {
640     return m_alternativeTextUIController->addAlternatives(alternatives);
641 }
642
643 void PageClientImpl::removeDictationAlternatives(uint64_t dictationContext)
644 {
645     m_alternativeTextUIController->removeAlternatives(dictationContext);
646 }
647
648 void PageClientImpl::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
649 {
650     if (!isViewVisible() || !isViewInWindow())
651         return;
652     m_alternativeTextUIController->showAlternatives(m_wkView, boundingBoxOfDictatedText, dictationContext, ^(NSString* acceptedAlternative){
653         [m_wkView handleAcceptedAlternativeText:acceptedAlternative];
654     });
655 }
656
657 Vector<String> PageClientImpl::dictationAlternatives(uint64_t dictationContext)
658 {
659     return m_alternativeTextUIController->alternativesForContext(dictationContext);
660 }
661 #endif
662
663 #if ENABLE(FULLSCREEN_API)
664
665 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
666 {
667     return *this;
668 }
669
670 // WebFullScreenManagerProxyClient
671
672 void PageClientImpl::closeFullScreenManager()
673 {
674     [m_wkView _closeFullScreenWindowController];
675 }
676
677 bool PageClientImpl::isFullScreen()
678 {
679     if (!m_wkView._hasFullScreenWindowController)
680         return false;
681
682     return m_wkView._fullScreenWindowController.isFullScreen;
683 }
684
685 void PageClientImpl::enterFullScreen()
686 {
687     [m_wkView._fullScreenWindowController enterFullScreen:nil];
688 }
689
690 void PageClientImpl::exitFullScreen()
691 {
692     [m_wkView._fullScreenWindowController exitFullScreen];
693 }
694
695 void PageClientImpl::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
696 {
697     [m_wkView._fullScreenWindowController beganEnterFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
698 }
699
700 void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
701 {
702     [m_wkView._fullScreenWindowController beganExitFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
703 }
704
705 #endif // ENABLE(FULLSCREEN_API)
706
707 void PageClientImpl::navigationGestureDidBegin()
708 {
709     dismissContentRelativeChildWindows();
710
711 #if WK_API_ENABLED
712     if (m_webView)
713         NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidBegin();
714 #endif
715 }
716
717 void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
718 {
719 #if WK_API_ENABLED
720     if (m_webView)
721         NavigationState::fromWebPage(*m_webView->_page).navigationGestureWillEnd(willNavigate, item);
722 #else
723     UNUSED_PARAM(willNavigate);
724     UNUSED_PARAM(item);
725 #endif
726 }
727
728 void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
729 {
730 #if WK_API_ENABLED
731     if (m_webView)
732         NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidEnd(willNavigate, item);
733 #else
734     UNUSED_PARAM(willNavigate);
735     UNUSED_PARAM(item);
736 #endif
737 }
738
739 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
740 {
741 #if WK_API_ENABLED
742     if (m_webView)
743         NavigationState::fromWebPage(*m_webView->_page).willRecordNavigationSnapshot(item);
744 #else
745     UNUSED_PARAM(item);
746 #endif
747 }
748
749 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
750 {
751     [m_wkView _didFirstVisuallyNonEmptyLayoutForMainFrame];
752 }
753
754 void PageClientImpl::didFinishLoadForMainFrame()
755 {
756     [m_wkView _didFinishLoadForMainFrame];
757 }
758
759 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type)
760 {
761     [m_wkView _didSameDocumentNavigationForMainFrame:type];
762 }
763
764 void PageClientImpl::removeNavigationGestureSnapshot()
765 {
766     [m_wkView _removeNavigationGestureSnapshot];
767 }
768
769 CGRect PageClientImpl::boundsOfLayerInLayerBackedWindowCoordinates(CALayer *layer) const
770 {
771     CALayer *windowContentLayer = static_cast<NSView *>(m_wkView.window.contentView).layer;
772     ASSERT(windowContentLayer);
773
774     return [windowContentLayer convertRect:layer.bounds fromLayer:layer];
775 }
776
777 void PageClientImpl::didPerformActionMenuHitTest(const ActionMenuHitTestResult& result, API::Object* userData)
778 {
779 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
780     [m_wkView _didPerformActionMenuHitTest:result userData:userData];
781 #endif
782 }
783
784 void PageClientImpl::showPlatformContextMenu(NSMenu *menu, IntPoint location)
785 {
786     [menu popUpMenuPositioningItem:nil atLocation:location inView:m_wkView];
787 }
788
789
790 } // namespace WebKit
791
792 #endif // PLATFORM(MAC)