Cursor doesn't change back to pointer when leaving Mail
[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 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
74 #include <WebCore/MediaPlaybackTargetPickerMac.h>
75 #endif
76
77 @interface NSApplication (WebNSApplicationDetails)
78 - (NSCursor *)_cursorRectCursor;
79 @end
80
81 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
82 @interface NSWindow (WebNSWindowDetails)
83 - (BOOL)_hostsLayersInWindowServer;
84 @end
85 #endif
86
87 SOFT_LINK_CONSTANT_MAY_FAIL(Lookup, LUTermOptionDisableSearchTermIndicator, NSString *)
88
89 using namespace WebCore;
90 using namespace WebKit;
91
92 @interface WKEditCommandObjC : NSObject
93 {
94     RefPtr<WebEditCommandProxy> m_command;
95 }
96 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command;
97 - (WebEditCommandProxy*)command;
98 @end
99
100 @interface WKEditorUndoTargetObjC : NSObject
101 - (void)undoEditing:(id)sender;
102 - (void)redoEditing:(id)sender;
103 @end
104
105 @implementation WKEditCommandObjC
106
107 - (id)initWithWebEditCommandProxy:(PassRefPtr<WebEditCommandProxy>)command
108 {
109     self = [super init];
110     if (!self)
111         return nil;
112
113     m_command = command;
114     return self;
115 }
116
117 - (WebEditCommandProxy*)command
118 {
119     return m_command.get();
120 }
121
122 @end
123
124 @implementation WKEditorUndoTargetObjC
125
126 - (void)undoEditing:(id)sender
127 {
128     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
129     [sender command]->unapply();
130 }
131
132 - (void)redoEditing:(id)sender
133 {
134     ASSERT([sender isKindOfClass:[WKEditCommandObjC class]]);
135     [sender command]->reapply();
136 }
137
138 @end
139
140 namespace WebKit {
141
142 PageClientImpl::PageClientImpl(WKView* wkView, WKWebView *webView)
143     : m_wkView(wkView)
144     , m_webView(webView)
145     , m_undoTarget(adoptNS([[WKEditorUndoTargetObjC alloc] init]))
146 #if USE(DICTATION_ALTERNATIVES)
147     , m_alternativeTextUIController(std::make_unique<AlternativeTextUIController>())
148 #endif
149 {
150 #if !WK_API_ENABLED
151     ASSERT_UNUSED(m_webView, !m_webView);
152 #endif
153 }
154
155 PageClientImpl::~PageClientImpl()
156 {
157 }
158
159 std::unique_ptr<DrawingAreaProxy> PageClientImpl::createDrawingAreaProxy()
160 {
161     return [m_wkView _createDrawingAreaProxy];
162 }
163
164 void PageClientImpl::setViewNeedsDisplay(const WebCore::IntRect& rect)
165 {
166     ASSERT_NOT_REACHED();
167 }
168
169 void PageClientImpl::displayView()
170 {
171     ASSERT_NOT_REACHED();
172 }
173
174 bool PageClientImpl::canScrollView()
175 {
176     return false;
177 }
178
179 void PageClientImpl::scrollView(const IntRect& scrollRect, const IntSize& scrollOffset)
180 {
181     ASSERT_NOT_REACHED();
182 }
183
184 void PageClientImpl::requestScroll(const FloatPoint& scrollPosition, bool isProgrammaticScroll)
185 {
186     ASSERT_NOT_REACHED();
187 }
188
189 IntSize PageClientImpl::viewSize()
190 {
191     return IntSize([m_wkView bounds].size);
192 }
193
194 NSView *PageClientImpl::activeView() const
195 {
196 #if WK_API_ENABLED
197     return m_wkView._thumbnailView ? (NSView *)m_wkView._thumbnailView : (NSView *)m_wkView;
198 #else
199     return m_wkView;
200 #endif
201 }
202
203 NSWindow *PageClientImpl::activeWindow() const
204 {
205 #if WK_API_ENABLED
206     if (m_wkView._thumbnailView)
207         return m_wkView._thumbnailView.window;
208 #endif
209     if (m_wkView._targetWindowForMovePreparation)
210         return m_wkView._targetWindowForMovePreparation;
211     return m_wkView.window;
212 }
213
214 bool PageClientImpl::isViewWindowActive()
215 {
216     NSWindow *activeViewWindow = activeWindow();
217     return activeViewWindow.isKeyWindow || [NSApp keyWindow] == activeViewWindow;
218 }
219
220 bool PageClientImpl::isViewFocused()
221 {
222     return [m_wkView _isFocused];
223 }
224
225 void PageClientImpl::makeFirstResponder()
226 {
227      [[m_wkView window] makeFirstResponder:m_wkView];
228 }
229     
230 bool PageClientImpl::isViewVisible()
231 {
232     NSView *activeView = this->activeView();
233     NSWindow *activeViewWindow = activeWindow();
234
235     if (!activeViewWindow)
236         return false;
237
238     if (!activeViewWindow.isVisible)
239         return false;
240
241     if (activeView.isHiddenOrHasHiddenAncestor)
242         return false;
243
244     if ([m_wkView windowOcclusionDetectionEnabled] && (activeViewWindow.occlusionState & NSWindowOcclusionStateVisible) != NSWindowOcclusionStateVisible)
245         return false;
246
247     return true;
248 }
249
250 bool PageClientImpl::isViewVisibleOrOccluded()
251 {
252     return activeWindow().isVisible;
253 }
254
255 bool PageClientImpl::isViewInWindow()
256 {
257     return activeWindow();
258 }
259
260 bool PageClientImpl::isVisuallyIdle()
261 {
262     return WindowServerConnection::singleton().applicationWindowModificationsHaveStopped() || !isViewVisible();
263 }
264
265 LayerHostingMode PageClientImpl::viewLayerHostingMode()
266 {
267 #if HAVE(OUT_OF_PROCESS_LAYER_HOSTING)
268     if ([activeWindow() _hostsLayersInWindowServer])
269         return LayerHostingMode::OutOfProcess;
270 #endif
271     return LayerHostingMode::InProcess;
272 }
273
274 void PageClientImpl::viewWillMoveToAnotherWindow()
275 {
276     clearAllEditCommands();
277 }
278
279 ColorSpaceData PageClientImpl::colorSpace()
280 {
281     return [m_wkView _colorSpace];
282 }
283
284 void PageClientImpl::processDidExit()
285 {
286     [m_wkView _processDidExit];
287 }
288
289 void PageClientImpl::pageClosed()
290 {
291     [m_wkView _pageClosed];
292 #if USE(DICTATION_ALTERNATIVES)
293     m_alternativeTextUIController->clear();
294 #endif
295 }
296
297 void PageClientImpl::didRelaunchProcess()
298 {
299     [m_wkView _didRelaunchProcess];
300 }
301
302 void PageClientImpl::preferencesDidChange()
303 {
304     [m_wkView _preferencesDidChange];
305 }
306
307 void PageClientImpl::toolTipChanged(const String& oldToolTip, const String& newToolTip)
308 {
309     [m_wkView _toolTipChangedFrom:nsStringFromWebCoreString(oldToolTip) to:nsStringFromWebCoreString(newToolTip)];
310 }
311
312 void PageClientImpl::didCommitLoadForMainFrame(const String& mimeType, bool useCustomContentProvider)
313 {
314 }
315
316 void PageClientImpl::didFinishLoadingDataForCustomContentProvider(const String& suggestedFilename, const IPC::DataReference& dataReference)
317 {
318 }
319
320 void PageClientImpl::handleDownloadRequest(DownloadProxy* download)
321 {
322     ASSERT_ARG(download, download);
323 #if WK_API_ENABLED
324     ASSERT([download->wrapper() isKindOfClass:[_WKDownload class]]);
325     [static_cast<_WKDownload *>(download->wrapper()) setOriginatingWebView:m_webView];
326 #endif
327 }
328
329 void PageClientImpl::didChangeContentSize(const WebCore::IntSize& newSize)
330 {
331     [m_wkView _didChangeContentSize:newSize];
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::setPromisedDataForImage(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 _setPromisedDataForImage:image.get() withFileName:filename withExtension:extension withTitle:title withURL:url withVisibleURL:visibleUrl withArchive:archiveBuffer.get() forPasteboard:pasteboardName];
415 }
416
417 #if ENABLE(ATTACHMENT_ELEMENT)
418 void PageClientImpl::setPromisedDataForAttachment(const String& pasteboardName, const String& filename, const String& extension, const String& title, const String& url, const String& visibleUrl)
419 {
420     [m_wkView _setPromisedDataForAttachment:filename withExtension:extension withTitle:title withURL:url withVisibleURL:visibleUrl forPasteboard:pasteboardName];
421 }
422 #endif
423
424 void PageClientImpl::updateSecureInputState()
425 {
426     [m_wkView _updateSecureInputState];
427 }
428
429 void PageClientImpl::resetSecureInputState()
430 {
431     [m_wkView _resetSecureInputState];
432 }
433
434 void PageClientImpl::notifyInputContextAboutDiscardedComposition()
435 {
436     [m_wkView _notifyInputContextAboutDiscardedComposition];
437 }
438
439 #if PLATFORM(MAC) && !USE(ASYNC_NSTEXTINPUTCLIENT)
440 void PageClientImpl::notifyApplicationAboutInputContextChange()
441 {
442     [NSApp updateWindows];
443 }
444 #endif
445
446 FloatRect PageClientImpl::convertToDeviceSpace(const FloatRect& rect)
447 {
448     return [m_wkView _convertToDeviceSpace:rect];
449 }
450
451 FloatRect PageClientImpl::convertToUserSpace(const FloatRect& rect)
452 {
453     return [m_wkView _convertToUserSpace:rect];
454 }
455    
456 IntPoint PageClientImpl::screenToRootView(const IntPoint& point)
457 {
458 #pragma clang diagnostic push
459 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
460     NSPoint windowCoord = [[m_wkView window] convertScreenToBase:point];
461 #pragma clang diagnostic pop
462     return IntPoint([m_wkView convertPoint:windowCoord fromView:nil]);
463 }
464     
465 IntRect PageClientImpl::rootViewToScreen(const IntRect& rect)
466 {
467     NSRect tempRect = rect;
468     tempRect = [m_wkView convertRect:tempRect toView:nil];
469 #pragma clang diagnostic push
470 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
471     tempRect.origin = [[m_wkView window] convertBaseToScreen:tempRect.origin];
472 #pragma clang diagnostic pop
473     return enclosingIntRect(tempRect);
474 }
475
476 void PageClientImpl::doneWithKeyEvent(const NativeWebKeyboardEvent& event, bool eventWasHandled)
477 {
478     [m_wkView _doneWithKeyEvent:event.nativeEvent() eventWasHandled:eventWasHandled];
479 }
480
481 PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy* page)
482 {
483     return WebPopupMenuProxyMac::create(m_wkView, page);
484 }
485
486 PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy* page)
487 {
488     return WebContextMenuProxyMac::create(m_wkView, page);
489 }
490
491 #if ENABLE(INPUT_TYPE_COLOR)
492 PassRefPtr<WebColorPicker> PageClientImpl::createColorPicker(WebPageProxy* page, const WebCore::Color& initialColor,  const WebCore::IntRect& rect)
493 {
494     return WebColorPickerMac::create(page, initialColor, rect, wkView());
495 }
496 #endif
497
498 void PageClientImpl::setTextIndicator(PassRefPtr<TextIndicator> textIndicator, bool fadeOut)
499 {
500     [m_wkView _setTextIndicator:textIndicator fadeOut:fadeOut];
501 }
502
503 void PageClientImpl::setTextIndicatorAnimationProgress(float progress)
504 {
505     [m_wkView _setTextIndicatorAnimationProgress:progress];
506 }
507
508 void PageClientImpl::accessibilityWebProcessTokenReceived(const IPC::DataReference& data)
509 {
510     NSData* remoteToken = [NSData dataWithBytes:data.data() length:data.size()];
511     [m_wkView _setAccessibilityWebProcessToken:remoteToken];
512 }
513     
514 void PageClientImpl::enterAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
515 {
516     ASSERT(!layerTreeContext.isEmpty());
517
518     CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID);
519     [m_wkView _setAcceleratedCompositingModeRootLayer:renderLayer];
520 }
521
522 void PageClientImpl::exitAcceleratedCompositingMode()
523 {
524     [m_wkView _setAcceleratedCompositingModeRootLayer:nil];
525 }
526
527 void PageClientImpl::updateAcceleratedCompositingMode(const LayerTreeContext& layerTreeContext)
528 {
529     ASSERT(!layerTreeContext.isEmpty());
530
531     CALayer *renderLayer = WKMakeRenderLayer(layerTreeContext.contextID);
532     [m_wkView _setAcceleratedCompositingModeRootLayer:renderLayer];
533 }
534
535 void PageClientImpl::setAcceleratedCompositingRootLayer(CALayer *rootLayer)
536 {
537     [m_wkView _setAcceleratedCompositingModeRootLayer:rootLayer];
538 }
539
540 CALayer *PageClientImpl::acceleratedCompositingRootLayer() const
541 {
542     return m_wkView._acceleratedCompositingModeRootLayer;
543 }
544
545 PassRefPtr<ViewSnapshot> PageClientImpl::takeViewSnapshot()
546 {
547     return [m_wkView _takeViewSnapshot];
548 }
549
550 void PageClientImpl::selectionDidChange()
551 {
552     [m_wkView _selectionChanged];
553 }
554
555 void PageClientImpl::wheelEventWasNotHandledByWebCore(const NativeWebWheelEvent& event)
556 {
557     [m_wkView _wheelEventWasNotHandledByWebCore:event.nativeEvent()];
558 }
559
560 void PageClientImpl::pluginFocusOrWindowFocusChanged(uint64_t pluginComplexTextInputIdentifier, bool pluginHasFocusAndWindowHasFocus)
561 {
562     [m_wkView _pluginFocusOrWindowFocusChanged:pluginHasFocusAndWindowHasFocus pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier];
563 }
564
565 void PageClientImpl::setPluginComplexTextInputState(uint64_t pluginComplexTextInputIdentifier, PluginComplexTextInputState pluginComplexTextInputState)
566 {
567     [m_wkView _setPluginComplexTextInputState:pluginComplexTextInputState pluginComplexTextInputIdentifier:pluginComplexTextInputIdentifier];
568 }
569
570 void PageClientImpl::didPerformDictionaryLookup(const DictionaryPopupInfo& dictionaryPopupInfo)
571 {
572     if (!getLULookupDefinitionModuleClass())
573         return;
574
575     NSPoint textBaselineOrigin = dictionaryPopupInfo.origin;
576
577     // Convert to screen coordinates.
578     textBaselineOrigin = [m_wkView convertPoint:textBaselineOrigin toView:nil];
579     textBaselineOrigin = [m_wkView.window convertRectToScreen:NSMakeRect(textBaselineOrigin.x, textBaselineOrigin.y, 0, 0)].origin;
580
581     RetainPtr<NSMutableDictionary> mutableOptions = adoptNS([(NSDictionary *)dictionaryPopupInfo.options.get() mutableCopy]);
582
583     if (canLoadLUTermOptionDisableSearchTermIndicator() && dictionaryPopupInfo.textIndicator.contentImage) {
584         [m_wkView _setTextIndicator:TextIndicator::create(dictionaryPopupInfo.textIndicator) fadeOut:NO];
585         [mutableOptions setObject:@YES forKey:getLUTermOptionDisableSearchTermIndicator()];
586         [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.string.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
587     } else
588         [getLULookupDefinitionModuleClass() showDefinitionForTerm:dictionaryPopupInfo.attributedString.string.get() atLocation:textBaselineOrigin options:mutableOptions.get()];
589 }
590
591 void PageClientImpl::dismissContentRelativeChildWindows()
592 {
593     [m_wkView _dismissContentRelativeChildWindows];
594 }
595
596 void PageClientImpl::showCorrectionPanel(AlternativeTextType type, const FloatRect& boundingBoxOfReplacedString, const String& replacedString, const String& replacementString, const Vector<String>& alternativeReplacementStrings)
597 {
598 #if USE(AUTOCORRECTION_PANEL)
599     if (!isViewVisible() || !isViewInWindow())
600         return;
601     m_correctionPanel.show(m_wkView, type, boundingBoxOfReplacedString, replacedString, replacementString, alternativeReplacementStrings);
602 #endif
603 }
604
605 void PageClientImpl::dismissCorrectionPanel(ReasonForDismissingAlternativeText reason)
606 {
607 #if USE(AUTOCORRECTION_PANEL)
608     m_correctionPanel.dismiss(reason);
609 #endif
610 }
611
612 String PageClientImpl::dismissCorrectionPanelSoon(WebCore::ReasonForDismissingAlternativeText reason)
613 {
614 #if USE(AUTOCORRECTION_PANEL)
615     return m_correctionPanel.dismiss(reason);
616 #else
617     return String();
618 #endif
619 }
620
621 void PageClientImpl::recordAutocorrectionResponse(AutocorrectionResponseType responseType, const String& replacedString, const String& replacementString)
622 {
623     NSCorrectionResponse response = responseType == AutocorrectionReverted ? NSCorrectionResponseReverted : NSCorrectionResponseEdited;
624     CorrectionPanel::recordAutocorrectionResponse(m_wkView, response, replacedString, replacementString);
625 }
626
627 void PageClientImpl::recommendedScrollbarStyleDidChange(ScrollbarStyle newStyle)
628 {
629     // Now re-create a tracking area with the appropriate options given the new scrollbar style
630     NSTrackingAreaOptions options = NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingInVisibleRect | NSTrackingCursorUpdate;
631     if (newStyle == ScrollbarStyle::AlwaysVisible)
632         options |= NSTrackingActiveAlways;
633     else
634         options |= NSTrackingActiveInKeyWindow;
635
636     RetainPtr<NSTrackingArea> trackingArea = adoptNS([[NSTrackingArea alloc] initWithRect:[m_wkView frame] options:options owner:m_wkView userInfo:nil]);
637     [m_wkView _setPrimaryTrackingArea:trackingArea.get()];
638 }
639
640 void PageClientImpl::intrinsicContentSizeDidChange(const IntSize& intrinsicContentSize)
641 {
642     [m_wkView _setIntrinsicContentSize:intrinsicContentSize];
643 }
644
645 bool PageClientImpl::executeSavedCommandBySelector(const String& selectorString)
646 {
647     return [m_wkView _executeSavedCommandBySelector:NSSelectorFromString(selectorString)];
648 }
649
650 #if USE(DICTATION_ALTERNATIVES)
651 uint64_t PageClientImpl::addDictationAlternatives(const RetainPtr<NSTextAlternatives>& alternatives)
652 {
653     return m_alternativeTextUIController->addAlternatives(alternatives);
654 }
655
656 void PageClientImpl::removeDictationAlternatives(uint64_t dictationContext)
657 {
658     m_alternativeTextUIController->removeAlternatives(dictationContext);
659 }
660
661 void PageClientImpl::showDictationAlternativeUI(const WebCore::FloatRect& boundingBoxOfDictatedText, uint64_t dictationContext)
662 {
663     if (!isViewVisible() || !isViewInWindow())
664         return;
665     m_alternativeTextUIController->showAlternatives(m_wkView, boundingBoxOfDictatedText, dictationContext, ^(NSString* acceptedAlternative){
666         [m_wkView handleAcceptedAlternativeText:acceptedAlternative];
667     });
668 }
669
670 Vector<String> PageClientImpl::dictationAlternatives(uint64_t dictationContext)
671 {
672     return m_alternativeTextUIController->alternativesForContext(dictationContext);
673 }
674 #endif
675
676 #if ENABLE(FULLSCREEN_API)
677
678 WebFullScreenManagerProxyClient& PageClientImpl::fullScreenManagerProxyClient()
679 {
680     return *this;
681 }
682
683 // WebFullScreenManagerProxyClient
684
685 void PageClientImpl::closeFullScreenManager()
686 {
687     [m_wkView _closeFullScreenWindowController];
688 }
689
690 bool PageClientImpl::isFullScreen()
691 {
692     if (!m_wkView._hasFullScreenWindowController)
693         return false;
694
695     return m_wkView._fullScreenWindowController.isFullScreen;
696 }
697
698 void PageClientImpl::enterFullScreen()
699 {
700     [m_wkView._fullScreenWindowController enterFullScreen:nil];
701 }
702
703 void PageClientImpl::exitFullScreen()
704 {
705     [m_wkView._fullScreenWindowController exitFullScreen];
706 }
707
708 void PageClientImpl::beganEnterFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
709 {
710     [m_wkView._fullScreenWindowController beganEnterFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
711 }
712
713 void PageClientImpl::beganExitFullScreen(const IntRect& initialFrame, const IntRect& finalFrame)
714 {
715     [m_wkView._fullScreenWindowController beganExitFullScreenWithInitialFrame:initialFrame finalFrame:finalFrame];
716 }
717
718 #endif // ENABLE(FULLSCREEN_API)
719
720 void PageClientImpl::navigationGestureDidBegin()
721 {
722     dismissContentRelativeChildWindows();
723
724 #if WK_API_ENABLED
725     if (m_webView)
726         NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidBegin();
727 #endif
728 }
729
730 void PageClientImpl::navigationGestureWillEnd(bool willNavigate, WebBackForwardListItem& item)
731 {
732 #if WK_API_ENABLED
733     if (m_webView)
734         NavigationState::fromWebPage(*m_webView->_page).navigationGestureWillEnd(willNavigate, item);
735 #else
736     UNUSED_PARAM(willNavigate);
737     UNUSED_PARAM(item);
738 #endif
739 }
740
741 void PageClientImpl::navigationGestureDidEnd(bool willNavigate, WebBackForwardListItem& item)
742 {
743 #if WK_API_ENABLED
744     if (m_webView)
745         NavigationState::fromWebPage(*m_webView->_page).navigationGestureDidEnd(willNavigate, item);
746 #else
747     UNUSED_PARAM(willNavigate);
748     UNUSED_PARAM(item);
749 #endif
750 }
751
752 void PageClientImpl::willRecordNavigationSnapshot(WebBackForwardListItem& item)
753 {
754 #if WK_API_ENABLED
755     if (m_webView)
756         NavigationState::fromWebPage(*m_webView->_page).willRecordNavigationSnapshot(item);
757 #else
758     UNUSED_PARAM(item);
759 #endif
760 }
761
762 void PageClientImpl::didFirstVisuallyNonEmptyLayoutForMainFrame()
763 {
764     [m_wkView _didFirstVisuallyNonEmptyLayoutForMainFrame];
765 }
766
767 void PageClientImpl::didFinishLoadForMainFrame()
768 {
769     [m_wkView _didFinishLoadForMainFrame];
770 }
771
772 void PageClientImpl::didSameDocumentNavigationForMainFrame(SameDocumentNavigationType type)
773 {
774     [m_wkView _didSameDocumentNavigationForMainFrame:type];
775 }
776
777 void PageClientImpl::removeNavigationGestureSnapshot()
778 {
779     [m_wkView _removeNavigationGestureSnapshot];
780 }
781
782 CGRect PageClientImpl::boundsOfLayerInLayerBackedWindowCoordinates(CALayer *layer) const
783 {
784     CALayer *windowContentLayer = static_cast<NSView *>(m_wkView.window.contentView).layer;
785     ASSERT(windowContentLayer);
786
787     return [windowContentLayer convertRect:layer.bounds fromLayer:layer];
788 }
789
790 void PageClientImpl::didPerformActionMenuHitTest(const ActionMenuHitTestResult& result, bool forImmediateAction, API::Object* userData)
791 {
792 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
793     [m_wkView _didPerformActionMenuHitTest:result forImmediateAction:forImmediateAction userData:userData];
794 #endif
795 }
796
797 void PageClientImpl::showPlatformContextMenu(NSMenu *menu, IntPoint location)
798 {
799     [menu popUpMenuPositioningItem:nil atLocation:location inView:m_wkView];
800 }
801
802 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
803 std::unique_ptr<WebCore::MediaPlaybackTargetPicker> PageClientImpl::createPlaybackTargetPicker(WebPageProxy* page)
804 {
805     return MediaPlaybackTargetPickerMac::create(*page);
806 }
807 #endif
808
809 } // namespace WebKit
810
811 #endif // PLATFORM(MAC)