1/*
2 * Copyright (C) 2010-2017 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#include "config.h"
27#include "WebEditorClient.h"
28
29#include "EditorState.h"
30#include "SharedBufferDataReference.h"
31#include "UndoOrRedo.h"
32#include "WKBundlePageEditorClient.h"
33#include "WebCoreArgumentCoders.h"
34#include "WebFrame.h"
35#include "WebPage.h"
36#include "WebPageProxy.h"
37#include "WebPageProxyMessages.h"
38#include "WebProcess.h"
39#include "WebUndoStep.h"
40#include <WebCore/ArchiveResource.h>
41#include <WebCore/DOMPasteAccess.h>
42#include <WebCore/DocumentFragment.h>
43#include <WebCore/FocusController.h>
44#include <WebCore/Frame.h>
45#include <WebCore/FrameLoader.h>
46#include <WebCore/FrameView.h>
47#include <WebCore/HTMLInputElement.h>
48#include <WebCore/HTMLNames.h>
49#include <WebCore/HTMLTextAreaElement.h>
50#include <WebCore/KeyboardEvent.h>
51#include <WebCore/NotImplemented.h>
52#include <WebCore/Page.h>
53#include <WebCore/SerializedAttachmentData.h>
54#include <WebCore/SpellChecker.h>
55#include <WebCore/StyleProperties.h>
56#include <WebCore/TextIterator.h>
57#include <WebCore/UndoStep.h>
58#include <WebCore/UserTypingGestureIndicator.h>
59#include <WebCore/VisibleUnits.h>
60#include <wtf/NeverDestroyed.h>
61#include <wtf/text/StringView.h>
62
63#if PLATFORM(GTK)
64#include <WebCore/PlatformDisplay.h>
65#endif
66
67namespace WebKit {
68using namespace WebCore;
69using namespace HTMLNames;
70
71static uint64_t generateTextCheckingRequestID()
72{
73 static uint64_t uniqueTextCheckingRequestID = 1;
74 return uniqueTextCheckingRequestID++;
75}
76
77bool WebEditorClient::shouldDeleteRange(Range* range)
78{
79 bool result = m_page->injectedBundleEditorClient().shouldDeleteRange(*m_page, range);
80 notImplemented();
81 return result;
82}
83
84bool WebEditorClient::smartInsertDeleteEnabled()
85{
86 return m_page->isSmartInsertDeleteEnabled();
87}
88
89bool WebEditorClient::isSelectTrailingWhitespaceEnabled() const
90{
91 return m_page->isSelectTrailingWhitespaceEnabled();
92}
93
94bool WebEditorClient::isContinuousSpellCheckingEnabled()
95{
96 return WebProcess::singleton().textCheckerState().isContinuousSpellCheckingEnabled;
97}
98
99void WebEditorClient::toggleContinuousSpellChecking()
100{
101 notImplemented();
102}
103
104bool WebEditorClient::isGrammarCheckingEnabled()
105{
106 return WebProcess::singleton().textCheckerState().isGrammarCheckingEnabled;
107}
108
109void WebEditorClient::toggleGrammarChecking()
110{
111 notImplemented();
112}
113
114int WebEditorClient::spellCheckerDocumentTag()
115{
116 notImplemented();
117 return false;
118}
119
120bool WebEditorClient::shouldBeginEditing(Range* range)
121{
122 bool result = m_page->injectedBundleEditorClient().shouldBeginEditing(*m_page, range);
123 notImplemented();
124 return result;
125}
126
127bool WebEditorClient::shouldEndEditing(Range* range)
128{
129 bool result = m_page->injectedBundleEditorClient().shouldEndEditing(*m_page, range);
130 notImplemented();
131 return result;
132}
133
134bool WebEditorClient::shouldInsertNode(Node* node, Range* rangeToReplace, EditorInsertAction action)
135{
136 bool result = m_page->injectedBundleEditorClient().shouldInsertNode(*m_page, node, rangeToReplace, action);
137 notImplemented();
138 return result;
139}
140
141bool WebEditorClient::shouldInsertText(const String& text, Range* rangeToReplace, EditorInsertAction action)
142{
143 bool result = m_page->injectedBundleEditorClient().shouldInsertText(*m_page, text.impl(), rangeToReplace, action);
144 notImplemented();
145 return result;
146}
147
148bool WebEditorClient::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting)
149{
150 bool result = m_page->injectedBundleEditorClient().shouldChangeSelectedRange(*m_page, fromRange, toRange, affinity, stillSelecting);
151 notImplemented();
152 return result;
153}
154
155bool WebEditorClient::shouldApplyStyle(StyleProperties* style, Range* range)
156{
157 Ref<MutableStyleProperties> mutableStyle(style->isMutable() ? Ref<MutableStyleProperties>(static_cast<MutableStyleProperties&>(*style)) : style->mutableCopy());
158 bool result = m_page->injectedBundleEditorClient().shouldApplyStyle(*m_page, &mutableStyle->ensureCSSStyleDeclaration(), range);
159 notImplemented();
160 return result;
161}
162
163#if ENABLE(ATTACHMENT_ELEMENT)
164
165void WebEditorClient::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& preferredFileName, Ref<SharedBuffer>&& data)
166{
167 m_page->send(Messages::WebPageProxy::RegisterAttachmentIdentifierFromData(identifier, contentType, preferredFileName, { data }));
168}
169
170void WebEditorClient::registerAttachments(Vector<WebCore::SerializedAttachmentData>&& data)
171{
172 m_page->send(Messages::WebPageProxy::registerAttachmentsFromSerializedData(WTFMove(data)));
173}
174
175void WebEditorClient::registerAttachmentIdentifier(const String& identifier, const String& contentType, const String& filePath)
176{
177 m_page->send(Messages::WebPageProxy::RegisterAttachmentIdentifierFromFilePath(identifier, contentType, filePath));
178}
179
180void WebEditorClient::registerAttachmentIdentifier(const String& identifier)
181{
182 m_page->send(Messages::WebPageProxy::RegisterAttachmentIdentifier(identifier));
183}
184
185void WebEditorClient::cloneAttachmentData(const String& fromIdentifier, const String& toIdentifier)
186{
187 m_page->send(Messages::WebPageProxy::CloneAttachmentData(fromIdentifier, toIdentifier));
188}
189
190void WebEditorClient::didInsertAttachmentWithIdentifier(const String& identifier, const String& source, bool hasEnclosingImage)
191{
192 m_page->send(Messages::WebPageProxy::DidInsertAttachmentWithIdentifier(identifier, source, hasEnclosingImage));
193}
194
195void WebEditorClient::didRemoveAttachmentWithIdentifier(const String& identifier)
196{
197 m_page->send(Messages::WebPageProxy::DidRemoveAttachmentWithIdentifier(identifier));
198}
199
200Vector<SerializedAttachmentData> WebEditorClient::serializedAttachmentDataForIdentifiers(const Vector<String>& identifiers)
201{
202 Vector<WebCore::SerializedAttachmentData> serializedData;
203 m_page->sendSync(Messages::WebPageProxy::SerializedAttachmentDataForIdentifiers(identifiers), Messages::WebPageProxy::SerializedAttachmentDataForIdentifiers::Reply(serializedData));
204 return serializedData;
205}
206
207#endif
208
209void WebEditorClient::didApplyStyle()
210{
211 m_page->didApplyStyle();
212}
213
214bool WebEditorClient::shouldMoveRangeAfterDelete(Range*, Range*)
215{
216 notImplemented();
217 return true;
218}
219
220void WebEditorClient::didBeginEditing()
221{
222 // FIXME: What good is a notification name, if it's always the same?
223 static NeverDestroyed<String> WebViewDidBeginEditingNotification(MAKE_STATIC_STRING_IMPL("WebViewDidBeginEditingNotification"));
224 m_page->injectedBundleEditorClient().didBeginEditing(*m_page, WebViewDidBeginEditingNotification.get().impl());
225 notImplemented();
226}
227
228void WebEditorClient::respondToChangedContents()
229{
230 static NeverDestroyed<String> WebViewDidChangeNotification(MAKE_STATIC_STRING_IMPL("WebViewDidChangeNotification"));
231 m_page->injectedBundleEditorClient().didChange(*m_page, WebViewDidChangeNotification.get().impl());
232 m_page->didChangeContents();
233}
234
235void WebEditorClient::respondToChangedSelection(Frame* frame)
236{
237 static NeverDestroyed<String> WebViewDidChangeSelectionNotification(MAKE_STATIC_STRING_IMPL("WebViewDidChangeSelectionNotification"));
238 m_page->injectedBundleEditorClient().didChangeSelection(*m_page, WebViewDidChangeSelectionNotification.get().impl());
239 if (!frame)
240 return;
241
242 m_page->didChangeSelection();
243
244#if PLATFORM(GTK)
245 updateGlobalSelection(frame);
246#endif
247}
248
249void WebEditorClient::didEndUserTriggeredSelectionChanges()
250{
251 m_page->didEndUserTriggeredSelectionChanges();
252}
253
254void WebEditorClient::updateEditorStateAfterLayoutIfEditabilityChanged()
255{
256 m_page->updateEditorStateAfterLayoutIfEditabilityChanged();
257}
258
259void WebEditorClient::didUpdateComposition()
260{
261 m_page->didUpdateComposition();
262}
263
264void WebEditorClient::discardedComposition(Frame*)
265{
266 m_page->discardedComposition();
267}
268
269void WebEditorClient::canceledComposition()
270{
271 m_page->canceledComposition();
272}
273
274void WebEditorClient::didEndEditing()
275{
276 static NeverDestroyed<String> WebViewDidEndEditingNotification(MAKE_STATIC_STRING_IMPL("WebViewDidEndEditingNotification"));
277 m_page->injectedBundleEditorClient().didEndEditing(*m_page, WebViewDidEndEditingNotification.get().impl());
278 notImplemented();
279}
280
281void WebEditorClient::didWriteSelectionToPasteboard()
282{
283 m_page->injectedBundleEditorClient().didWriteToPasteboard(*m_page);
284}
285
286void WebEditorClient::willWriteSelectionToPasteboard(Range* range)
287{
288 m_page->injectedBundleEditorClient().willWriteToPasteboard(*m_page, range);
289}
290
291void WebEditorClient::getClientPasteboardDataForRange(Range* range, Vector<String>& pasteboardTypes, Vector<RefPtr<SharedBuffer>>& pasteboardData)
292{
293 m_page->injectedBundleEditorClient().getPasteboardDataForRange(*m_page, range, pasteboardTypes, pasteboardData);
294}
295
296bool WebEditorClient::performTwoStepDrop(DocumentFragment& fragment, Range& destination, bool isMove)
297{
298 return m_page->injectedBundleEditorClient().performTwoStepDrop(*m_page, fragment, destination, isMove);
299}
300
301void WebEditorClient::registerUndoStep(UndoStep& step)
302{
303 // FIXME: Add assertion that the command being reapplied is the same command that is
304 // being passed to us.
305 if (m_page->isInRedo())
306 return;
307
308 auto webStep = WebUndoStep::create(step);
309 auto stepID = webStep->stepID();
310
311 m_page->addWebUndoStep(stepID, WTFMove(webStep));
312 m_page->send(Messages::WebPageProxy::RegisterEditCommandForUndo(stepID, step.label()), IPC::SendOption::DispatchMessageEvenWhenWaitingForSyncReply);
313}
314
315void WebEditorClient::registerRedoStep(UndoStep&)
316{
317}
318
319void WebEditorClient::clearUndoRedoOperations()
320{
321 m_page->send(Messages::WebPageProxy::ClearAllEditCommands());
322}
323
324bool WebEditorClient::canCopyCut(Frame*, bool defaultValue) const
325{
326 return defaultValue;
327}
328
329bool WebEditorClient::canPaste(Frame*, bool defaultValue) const
330{
331 return defaultValue;
332}
333
334bool WebEditorClient::canUndo() const
335{
336 bool result = false;
337 m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(UndoOrRedo::Undo), Messages::WebPageProxy::CanUndoRedo::Reply(result));
338 return result;
339}
340
341bool WebEditorClient::canRedo() const
342{
343 bool result = false;
344 m_page->sendSync(Messages::WebPageProxy::CanUndoRedo(UndoOrRedo::Redo), Messages::WebPageProxy::CanUndoRedo::Reply(result));
345 return result;
346}
347
348void WebEditorClient::undo()
349{
350 m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(UndoOrRedo::Undo), Messages::WebPageProxy::ExecuteUndoRedo::Reply());
351}
352
353void WebEditorClient::redo()
354{
355 m_page->sendSync(Messages::WebPageProxy::ExecuteUndoRedo(UndoOrRedo::Redo), Messages::WebPageProxy::ExecuteUndoRedo::Reply());
356}
357
358WebCore::DOMPasteAccessResponse WebEditorClient::requestDOMPasteAccess(const String& originIdentifier)
359{
360 return m_page->requestDOMPasteAccess(originIdentifier);
361}
362
363#if PLATFORM(WIN)
364void WebEditorClient::handleKeyboardEvent(KeyboardEvent& event)
365{
366 if (m_page->handleEditingKeyboardEvent(event))
367 event.setDefaultHandled();
368}
369
370void WebEditorClient::handleInputMethodKeydown(KeyboardEvent&)
371{
372 notImplemented();
373}
374#endif // PLATFORM(WIN)
375
376void WebEditorClient::textFieldDidBeginEditing(Element* element)
377{
378 if (!is<HTMLInputElement>(*element))
379 return;
380
381 WebFrame* webFrame = WebFrame::fromCoreFrame(*element->document().frame());
382 ASSERT(webFrame);
383
384 m_page->injectedBundleFormClient().textFieldDidBeginEditing(m_page, downcast<HTMLInputElement>(element), webFrame);
385}
386
387void WebEditorClient::textFieldDidEndEditing(Element* element)
388{
389 if (!is<HTMLInputElement>(*element))
390 return;
391
392 WebFrame* webFrame = WebFrame::fromCoreFrame(*element->document().frame());
393 ASSERT(webFrame);
394
395 m_page->injectedBundleFormClient().textFieldDidEndEditing(m_page, downcast<HTMLInputElement>(element), webFrame);
396}
397
398void WebEditorClient::textDidChangeInTextField(Element* element)
399{
400 if (!is<HTMLInputElement>(*element))
401 return;
402
403 bool initiatedByUserTyping = UserTypingGestureIndicator::processingUserTypingGesture() && UserTypingGestureIndicator::focusedElementAtGestureStart() == element;
404
405 WebFrame* webFrame = WebFrame::fromCoreFrame(*element->document().frame());
406 ASSERT(webFrame);
407
408 m_page->injectedBundleFormClient().textDidChangeInTextField(m_page, downcast<HTMLInputElement>(element), webFrame, initiatedByUserTyping);
409}
410
411void WebEditorClient::textDidChangeInTextArea(Element* element)
412{
413 if (!is<HTMLTextAreaElement>(*element))
414 return;
415
416 WebFrame* webFrame = WebFrame::fromCoreFrame(*element->document().frame());
417 ASSERT(webFrame);
418
419 m_page->injectedBundleFormClient().textDidChangeInTextArea(m_page, downcast<HTMLTextAreaElement>(element), webFrame);
420}
421
422#if !PLATFORM(IOS_FAMILY)
423void WebEditorClient::overflowScrollPositionChanged()
424{
425 notImplemented();
426}
427#endif
428
429static bool getActionTypeForKeyEvent(KeyboardEvent* event, WKInputFieldActionType& type)
430{
431 String key = event->keyIdentifier();
432 if (key == "Up")
433 type = WKInputFieldActionTypeMoveUp;
434 else if (key == "Down")
435 type = WKInputFieldActionTypeMoveDown;
436 else if (key == "U+001B")
437 type = WKInputFieldActionTypeCancel;
438 else if (key == "U+0009") {
439 if (event->shiftKey())
440 type = WKInputFieldActionTypeInsertBacktab;
441 else
442 type = WKInputFieldActionTypeInsertTab;
443 } else if (key == "Enter")
444 type = WKInputFieldActionTypeInsertNewline;
445 else
446 return false;
447
448 return true;
449}
450
451static API::InjectedBundle::FormClient::InputFieldAction toInputFieldAction(WKInputFieldActionType action)
452{
453 switch (action) {
454 case WKInputFieldActionTypeMoveUp:
455 return API::InjectedBundle::FormClient::InputFieldAction::MoveUp;
456 case WKInputFieldActionTypeMoveDown:
457 return API::InjectedBundle::FormClient::InputFieldAction::MoveDown;
458 case WKInputFieldActionTypeCancel:
459 return API::InjectedBundle::FormClient::InputFieldAction::Cancel;
460 case WKInputFieldActionTypeInsertTab:
461 return API::InjectedBundle::FormClient::InputFieldAction::InsertTab;
462 case WKInputFieldActionTypeInsertNewline:
463 return API::InjectedBundle::FormClient::InputFieldAction::InsertNewline;
464 case WKInputFieldActionTypeInsertDelete:
465 return API::InjectedBundle::FormClient::InputFieldAction::InsertDelete;
466 case WKInputFieldActionTypeInsertBacktab:
467 return API::InjectedBundle::FormClient::InputFieldAction::InsertBacktab;
468 }
469
470 ASSERT_NOT_REACHED();
471 return API::InjectedBundle::FormClient::InputFieldAction::Cancel;
472}
473
474bool WebEditorClient::doTextFieldCommandFromEvent(Element* element, KeyboardEvent* event)
475{
476 if (!is<HTMLInputElement>(*element))
477 return false;
478
479 WKInputFieldActionType actionType = static_cast<WKInputFieldActionType>(0);
480 if (!getActionTypeForKeyEvent(event, actionType))
481 return false;
482
483 WebFrame* webFrame = WebFrame::fromCoreFrame(*element->document().frame());
484 ASSERT(webFrame);
485
486 return m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, downcast<HTMLInputElement>(element), toInputFieldAction(actionType), webFrame);
487}
488
489void WebEditorClient::textWillBeDeletedInTextField(Element* element)
490{
491 if (!is<HTMLInputElement>(*element))
492 return;
493
494 WebFrame* webFrame = WebFrame::fromCoreFrame(*element->document().frame());
495 ASSERT(webFrame);
496
497 m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, downcast<HTMLInputElement>(element), toInputFieldAction(WKInputFieldActionTypeInsertDelete), webFrame);
498}
499
500bool WebEditorClient::shouldEraseMarkersAfterChangeSelection(WebCore::TextCheckingType type) const
501{
502 // This prevents erasing spelling markers on OS X Lion or later to match AppKit on these Mac OS X versions.
503#if PLATFORM(COCOA)
504 return type != TextCheckingType::Spelling;
505#else
506 UNUSED_PARAM(type);
507 return true;
508#endif
509}
510
511void WebEditorClient::ignoreWordInSpellDocument(const String& word)
512{
513 m_page->send(Messages::WebPageProxy::IgnoreWord(word));
514}
515
516void WebEditorClient::learnWord(const String& word)
517{
518 m_page->send(Messages::WebPageProxy::LearnWord(word));
519}
520
521void WebEditorClient::checkSpellingOfString(StringView text, int* misspellingLocation, int* misspellingLength)
522{
523 int32_t resultLocation = -1;
524 int32_t resultLength = 0;
525 m_page->sendSync(Messages::WebPageProxy::CheckSpellingOfString(text.toStringWithoutCopying()),
526 Messages::WebPageProxy::CheckSpellingOfString::Reply(resultLocation, resultLength));
527 *misspellingLocation = resultLocation;
528 *misspellingLength = resultLength;
529}
530
531String WebEditorClient::getAutoCorrectSuggestionForMisspelledWord(const String&)
532{
533 notImplemented();
534 return String();
535}
536
537void WebEditorClient::checkGrammarOfString(StringView text, Vector<WebCore::GrammarDetail>& grammarDetails, int* badGrammarLocation, int* badGrammarLength)
538{
539 int32_t resultLocation = -1;
540 int32_t resultLength = 0;
541 m_page->sendSync(Messages::WebPageProxy::CheckGrammarOfString(text.toStringWithoutCopying()),
542 Messages::WebPageProxy::CheckGrammarOfString::Reply(grammarDetails, resultLocation, resultLength));
543 *badGrammarLocation = resultLocation;
544 *badGrammarLength = resultLength;
545}
546
547static int32_t insertionPointFromCurrentSelection(const VisibleSelection& currentSelection)
548{
549 VisiblePosition selectionStart = currentSelection.visibleStart();
550 VisiblePosition paragraphStart = startOfParagraph(selectionStart);
551 return TextIterator::rangeLength(makeRange(paragraphStart, selectionStart).get());
552}
553
554#if USE(UNIFIED_TEXT_CHECKING)
555Vector<TextCheckingResult> WebEditorClient::checkTextOfParagraph(StringView stringView, OptionSet<WebCore::TextCheckingType> checkingTypes, const VisibleSelection& currentSelection)
556{
557 Vector<TextCheckingResult> results;
558 m_page->sendSync(Messages::WebPageProxy::CheckTextOfParagraph(stringView.toStringWithoutCopying(), checkingTypes, insertionPointFromCurrentSelection(currentSelection)), Messages::WebPageProxy::CheckTextOfParagraph::Reply(results));
559 return results;
560}
561#endif
562
563void WebEditorClient::updateSpellingUIWithGrammarString(const String& badGrammarPhrase, const GrammarDetail& grammarDetail)
564{
565 m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithGrammarString(badGrammarPhrase, grammarDetail));
566}
567
568void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
569{
570 m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithMisspelledWord(misspelledWord));
571}
572
573void WebEditorClient::showSpellingUI(bool)
574{
575 notImplemented();
576}
577
578bool WebEditorClient::spellingUIIsShowing()
579{
580 bool isShowing = false;
581 m_page->sendSync(Messages::WebPageProxy::SpellingUIIsShowing(), Messages::WebPageProxy::SpellingUIIsShowing::Reply(isShowing));
582 return isShowing;
583}
584
585void WebEditorClient::getGuessesForWord(const String& word, const String& context, const VisibleSelection& currentSelection, Vector<String>& guesses)
586{
587 m_page->sendSync(Messages::WebPageProxy::GetGuessesForWord(word, context, insertionPointFromCurrentSelection(currentSelection)), Messages::WebPageProxy::GetGuessesForWord::Reply(guesses));
588}
589
590void WebEditorClient::requestCheckingOfString(TextCheckingRequest& request, const WebCore::VisibleSelection& currentSelection)
591{
592 uint64_t requestID = generateTextCheckingRequestID();
593 m_page->addTextCheckingRequest(requestID, request);
594
595 m_page->send(Messages::WebPageProxy::RequestCheckingOfString(requestID, request.data(), insertionPointFromCurrentSelection(currentSelection)));
596}
597
598void WebEditorClient::willSetInputMethodState()
599{
600}
601
602void WebEditorClient::setInputMethodState(bool enabled)
603{
604#if PLATFORM(GTK)
605 m_page->setInputMethodState(enabled);
606#else
607 notImplemented();
608 UNUSED_PARAM(enabled);
609#endif
610}
611
612bool WebEditorClient::supportsGlobalSelection()
613{
614#if PLATFORM(GTK)
615#if PLATFORM(X11)
616 if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11)
617 return true;
618#endif
619#if PLATFORM(WAYLAND)
620 if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
621 return true;
622#endif
623#endif
624 return false;
625}
626
627} // namespace WebKit
628