2 * Copyright (C) 2010 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "WebEditorClient.h"
29 #define DISABLE_NOT_IMPLEMENTED_WARNINGS 1
30 #include "NotImplemented.h"
32 #include "SelectionState.h"
33 #include "WebFrameLoaderClient.h"
35 #include "WebPageProxyMessages.h"
36 #include "WebProcess.h"
37 #include <WebCore/ArchiveResource.h>
38 #include <WebCore/DocumentFragment.h>
39 #include <WebCore/EditCommand.h>
40 #include <WebCore/FocusController.h>
41 #include <WebCore/Frame.h>
42 #include <WebCore/HTMLInputElement.h>
43 #include <WebCore/HTMLNames.h>
44 #include <WebCore/HTMLTextAreaElement.h>
45 #include <WebCore/KeyboardEvent.h>
46 #include <WebCore/Page.h>
47 #include <WebCore/UserTypingGestureIndicator.h>
49 using namespace WebCore;
50 using namespace HTMLNames;
54 void WebEditorClient::pageDestroyed()
59 bool WebEditorClient::shouldDeleteRange(Range* range)
61 bool result = m_page->injectedBundleEditorClient().shouldDeleteRange(m_page, range);
66 bool WebEditorClient::shouldShowDeleteInterface(HTMLElement*)
72 bool WebEditorClient::smartInsertDeleteEnabled()
74 // FIXME: Why isn't this Mac specific like toggleSmartInsertDeleteEnabled?
76 return m_page->isSmartInsertDeleteEnabled();
82 bool WebEditorClient::isSelectTrailingWhitespaceEnabled()
88 bool WebEditorClient::isContinuousSpellCheckingEnabled()
90 return WebProcess::shared().textCheckerState().isContinuousSpellCheckingEnabled;
93 void WebEditorClient::toggleContinuousSpellChecking()
98 bool WebEditorClient::isGrammarCheckingEnabled()
100 return WebProcess::shared().textCheckerState().isGrammarCheckingEnabled;
103 void WebEditorClient::toggleGrammarChecking()
108 int WebEditorClient::spellCheckerDocumentTag()
115 bool WebEditorClient::isEditable()
122 bool WebEditorClient::shouldBeginEditing(Range* range)
124 bool result = m_page->injectedBundleEditorClient().shouldBeginEditing(m_page, range);
129 bool WebEditorClient::shouldEndEditing(Range* range)
131 bool result = m_page->injectedBundleEditorClient().shouldEndEditing(m_page, range);
136 bool WebEditorClient::shouldInsertNode(Node* node, Range* rangeToReplace, EditorInsertAction action)
138 bool result = m_page->injectedBundleEditorClient().shouldInsertNode(m_page, node, rangeToReplace, action);
143 bool WebEditorClient::shouldInsertText(const String& text, Range* rangeToReplace, EditorInsertAction action)
145 bool result = m_page->injectedBundleEditorClient().shouldInsertText(m_page, text.impl(), rangeToReplace, action);
150 bool WebEditorClient::shouldChangeSelectedRange(Range* fromRange, Range* toRange, EAffinity affinity, bool stillSelecting)
152 bool result = m_page->injectedBundleEditorClient().shouldChangeSelectedRange(m_page, fromRange, toRange, affinity, stillSelecting);
157 bool WebEditorClient::shouldApplyStyle(CSSStyleDeclaration* style, Range* range)
159 bool result = m_page->injectedBundleEditorClient().shouldApplyStyle(m_page, style, range);
164 bool WebEditorClient::shouldMoveRangeAfterDelete(Range*, Range*)
170 void WebEditorClient::didBeginEditing()
172 // FIXME: What good is a notification name, if it's always the same?
173 static const String WebViewDidBeginEditingNotification = "WebViewDidBeginEditingNotification";
174 m_page->injectedBundleEditorClient().didBeginEditing(m_page, WebViewDidBeginEditingNotification.impl());
178 void WebEditorClient::respondToChangedContents()
180 static const String WebViewDidChangeNotification = "WebViewDidChangeNotification";
181 m_page->injectedBundleEditorClient().didChange(m_page, WebViewDidChangeNotification.impl());
185 void WebEditorClient::respondToChangedSelection()
187 static const String WebViewDidChangeSelectionNotification = "WebViewDidChangeSelectionNotification";
188 m_page->injectedBundleEditorClient().didChangeSelection(m_page, WebViewDidChangeSelectionNotification.impl());
189 Frame* frame = m_page->corePage()->focusController()->focusedFrame();
193 SelectionState selectionState;
194 selectionState.isNone = frame->selection()->isNone();
195 selectionState.isContentEditable = frame->selection()->isContentEditable();
196 selectionState.isInPasswordField = frame->selection()->isInPasswordField();
197 selectionState.hasComposition = frame->editor()->hasComposition();
199 WebPage::getLocationAndLengthFromRange(frame->selection()->toNormalizedRange().get(), selectionState.selectedRangeStart, selectionState.selectedRangeLength);
201 m_page->send(Messages::WebPageProxy::SelectionStateChanged(selectionState));
204 // FIXME: This should also go into the selection state.
205 if (!frame->editor()->hasComposition() || frame->editor()->ignoreCompositionSelectionChange())
210 m_page->send(Messages::WebPageProxy::DidChangeCompositionSelection(frame->editor()->getCompositionSelection(start, end)));
214 void WebEditorClient::didEndEditing()
216 static const String WebViewDidEndEditingNotification = "WebViewDidEndEditingNotification";
217 m_page->injectedBundleEditorClient().didEndEditing(m_page, WebViewDidEndEditingNotification.impl());
221 void WebEditorClient::didWriteSelectionToPasteboard()
226 void WebEditorClient::didSetSelectionTypesForPasteboard()
231 void WebEditorClient::registerCommandForUndo(PassRefPtr<EditCommand> command)
233 // FIXME: Add assertion that the command being reapplied is the same command that is
234 // being passed to us.
235 if (m_page->isInRedo())
238 RefPtr<WebEditCommand> webCommand = WebEditCommand::create(command);
239 m_page->addWebEditCommand(webCommand->commandID(), webCommand.get());
240 uint32_t editAction = static_cast<uint32_t>(webCommand->command()->editingAction());
242 m_page->send(Messages::WebPageProxy::RegisterEditCommandForUndo(webCommand->commandID(), editAction));
245 void WebEditorClient::registerCommandForRedo(PassRefPtr<EditCommand>)
249 void WebEditorClient::clearUndoRedoOperations()
251 m_page->send(Messages::WebPageProxy::ClearAllEditCommands());
254 bool WebEditorClient::canUndo() const
260 bool WebEditorClient::canRedo() const
266 void WebEditorClient::undo()
271 void WebEditorClient::redo()
277 void WebEditorClient::handleKeyboardEvent(KeyboardEvent* event)
279 if (m_page->handleEditingKeyboardEvent(event))
280 event->setDefaultHandled();
283 void WebEditorClient::handleInputMethodKeydown(KeyboardEvent*)
289 void WebEditorClient::textFieldDidBeginEditing(Element* element)
291 if (!element->hasTagName(inputTag))
294 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
295 m_page->injectedBundleFormClient().textFieldDidBeginEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
298 void WebEditorClient::textFieldDidEndEditing(Element* element)
300 if (!element->hasTagName(inputTag))
303 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
304 m_page->injectedBundleFormClient().textFieldDidEndEditing(m_page, static_cast<HTMLInputElement*>(element), webFrame);
307 void WebEditorClient::textDidChangeInTextField(Element* element)
309 if (!element->hasTagName(inputTag))
312 if (!UserTypingGestureIndicator::processingUserTypingGesture() || UserTypingGestureIndicator::focusedElementAtGestureStart() != element)
315 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
316 m_page->injectedBundleFormClient().textDidChangeInTextField(m_page, static_cast<HTMLInputElement*>(element), webFrame);
319 void WebEditorClient::textDidChangeInTextArea(Element* element)
321 if (!element->hasTagName(textareaTag))
324 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
325 m_page->injectedBundleFormClient().textDidChangeInTextArea(m_page, static_cast<HTMLTextAreaElement*>(element), webFrame);
328 static bool getActionTypeForKeyEvent(KeyboardEvent* event, WKInputFieldActionType& type)
330 String key = event->keyIdentifier();
332 type = WKInputFieldActionTypeMoveUp;
333 else if (key == "Down")
334 type = WKInputFieldActionTypeMoveDown;
335 else if (key == "U+001B")
336 type = WKInputFieldActionTypeCancel;
337 else if (key == "U+0009") {
338 if (event->shiftKey())
339 type = WKInputFieldActionTypeInsertBacktab;
341 type = WKInputFieldActionTypeInsertTab;
342 } else if (key == "Enter")
343 type = WKInputFieldActionTypeInsertNewline;
350 bool WebEditorClient::doTextFieldCommandFromEvent(Element* element, KeyboardEvent* event)
352 if (!element->hasTagName(inputTag))
355 WKInputFieldActionType actionType = static_cast<WKInputFieldActionType>(0);
356 if (!getActionTypeForKeyEvent(event, actionType))
359 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
360 return m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), actionType, webFrame);
363 void WebEditorClient::textWillBeDeletedInTextField(Element* element)
365 if (!element->hasTagName(inputTag))
368 WebFrame* webFrame = static_cast<WebFrameLoaderClient*>(element->document()->frame()->loader()->client())->webFrame();
369 m_page->injectedBundleFormClient().shouldPerformActionInTextField(m_page, static_cast<HTMLInputElement*>(element), WKInputFieldActionTypeInsertDelete, webFrame);
372 void WebEditorClient::ignoreWordInSpellDocument(const String& word)
374 m_page->send(Messages::WebPageProxy::IgnoreWord(word));
377 void WebEditorClient::learnWord(const String& word)
379 m_page->send(Messages::WebPageProxy::LearnWord(word));
382 void WebEditorClient::checkSpellingOfString(const UChar*, int, int*, int*)
387 String WebEditorClient::getAutoCorrectSuggestionForMisspelledWord(const String&)
393 void WebEditorClient::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
398 void WebEditorClient::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
403 void WebEditorClient::updateSpellingUIWithMisspelledWord(const String& misspelledWord)
405 m_page->send(Messages::WebPageProxy::UpdateSpellingUIWithMisspelledWord(misspelledWord));
408 void WebEditorClient::showSpellingUI(bool)
413 bool WebEditorClient::spellingUIIsShowing()
419 void WebEditorClient::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
421 m_page->sendSync(Messages::WebPageProxy::GetGuessesForWord(word, context), Messages::WebPageProxy::GetGuessesForWord::Reply(guesses));
424 void WebEditorClient::willSetInputMethodState()
429 void WebEditorClient::setInputMethodState(bool)
434 void WebEditorClient::requestCheckingOfString(WebCore::SpellChecker*, int, const WTF::String&)
439 } // namespace WebKit