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