• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2007, The Android Open Source Project
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  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * 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 THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #define LOG_TAG "WebCore"
27 
28 #include "config.h"
29 #include "Editor.h"
30 #include "EditorClientAndroid.h"
31 #include "Event.h"
32 #include "EventNames.h"
33 #include "FocusController.h"
34 #include "Frame.h"
35 #include "HTMLNames.h"
36 #include "KeyboardEvent.h"
37 #include "NotImplemented.h"
38 #include "PlatformKeyboardEvent.h"
39 #include "PlatformString.h"
40 #include "WebViewCore.h"
41 #include "WindowsKeyboardCodes.h"
42 
43 using namespace WebCore::HTMLNames;
44 
45 namespace android {
46 
pageDestroyed()47 void EditorClientAndroid::pageDestroyed() {
48     delete this;
49 }
50 
shouldDeleteRange(Range *)51 bool EditorClientAndroid::shouldDeleteRange(Range*) { return true; }
shouldShowDeleteInterface(HTMLElement *)52 bool EditorClientAndroid::shouldShowDeleteInterface(HTMLElement*) { notImplemented(); return false; }
smartInsertDeleteEnabled()53 bool EditorClientAndroid::smartInsertDeleteEnabled() { notImplemented(); return false; }
isSelectTrailingWhitespaceEnabled()54 bool EditorClientAndroid::isSelectTrailingWhitespaceEnabled(){ notImplemented(); return false; }
isContinuousSpellCheckingEnabled()55 bool EditorClientAndroid::isContinuousSpellCheckingEnabled() { notImplemented(); return false; }
toggleContinuousSpellChecking()56 void EditorClientAndroid::toggleContinuousSpellChecking() { notImplemented(); }
isGrammarCheckingEnabled()57 bool EditorClientAndroid::isGrammarCheckingEnabled() { notImplemented(); return false; }
toggleGrammarChecking()58 void EditorClientAndroid::toggleGrammarChecking() { notImplemented(); }
spellCheckerDocumentTag()59 int EditorClientAndroid::spellCheckerDocumentTag() { notImplemented(); return -1; }
60 
isEditable()61 bool EditorClientAndroid::isEditable() { /* notImplemented(); */ return false; }
62 
63 // Following Qt's implementation. For shouldBeginEditing and shouldEndEditing.
64 // Returning true for these fixes issue http://b/issue?id=735185
shouldBeginEditing(Range *)65 bool EditorClientAndroid::shouldBeginEditing(Range*)
66 {
67     return true;
68 }
69 
shouldEndEditing(Range *)70 bool EditorClientAndroid::shouldEndEditing(Range*)
71 {
72     return true;
73 }
74 
shouldInsertNode(Node *,Range *,EditorInsertAction)75 bool EditorClientAndroid::shouldInsertNode(Node*, Range*, EditorInsertAction) { notImplemented(); return true; }
shouldInsertText(const String &,Range *,EditorInsertAction)76 bool EditorClientAndroid::shouldInsertText(const String&, Range*, EditorInsertAction) { return true; }
shouldApplyStyle(CSSStyleDeclaration *,Range *)77 bool EditorClientAndroid::shouldApplyStyle(CSSStyleDeclaration*, Range*) { notImplemented(); return true; }
78 
didBeginEditing()79 void EditorClientAndroid::didBeginEditing() { notImplemented(); }
80 
81 // This function is called so that the platform can handle changes to content. It is called
82 // after the contents have been edited or unedited (ie undo)
respondToChangedContents()83 void EditorClientAndroid::respondToChangedContents() { notImplemented(); }
84 
didEndEditing()85 void EditorClientAndroid::didEndEditing() { notImplemented(); }
didWriteSelectionToPasteboard()86 void EditorClientAndroid::didWriteSelectionToPasteboard() { notImplemented(); }
didSetSelectionTypesForPasteboard()87 void EditorClientAndroid::didSetSelectionTypesForPasteboard() { notImplemented(); }
88 
89 // Copied from the Window's port of WebKit.
90 static const unsigned AltKey = 1 << 0;
91 static const unsigned ShiftKey = 1 << 1;
92 
93 struct KeyDownEntry {
94     unsigned virtualKey;
95     unsigned modifiers;
96     const char* name;
97 };
98 
99 struct KeyPressEntry {
100     unsigned charCode;
101     unsigned modifiers;
102     const char* name;
103 };
104 
105 static const KeyDownEntry keyDownEntries[] = {
106     { VK_LEFT,   0,                  "MoveLeft"                                    },
107     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
108     { VK_LEFT,   AltKey,             "MoveWordLeft"                                },
109     { VK_LEFT,   AltKey | ShiftKey,  "MoveWordLeftAndModifySelection"              },
110     { VK_RIGHT,  0,                  "MoveRight"                                   },
111     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
112     { VK_RIGHT,  AltKey,             "MoveWordRight"                               },
113     { VK_RIGHT,  AltKey | ShiftKey,  "MoveWordRightAndModifySelection"             },
114     { VK_UP,     0,                  "MoveUp"                                      },
115     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
116     { VK_DOWN,   0,                  "MoveDown"                                    },
117     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
118 
119     { VK_BACK,   0,                  "BackwardDelete"                              },
120     { VK_BACK,   ShiftKey,           "ForwardDelete"                               },
121     { VK_BACK,   AltKey,             "DeleteWordBackward"                          },
122     { VK_BACK,   AltKey | ShiftKey,  "DeleteWordForward"                           },
123 
124     { VK_ESCAPE, 0,                  "Cancel"                                      },
125     { VK_TAB,    0,                  "InsertTab"                                   },
126     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
127     { VK_RETURN, 0,                  "InsertNewline"                               },
128     { VK_RETURN, AltKey,             "InsertNewline"                               },
129     { VK_RETURN, AltKey | ShiftKey,  "InsertNewline"                               }
130 };
131 
132 static const KeyPressEntry keyPressEntries[] = {
133     { '\t', 0,                  "InsertTab"     },
134     { '\t', ShiftKey,           "InsertBackTab" },
135     { '\r', 0,                  "InsertNewline" },
136     { '\r', AltKey,             "InsertNewline" },
137     { '\r', AltKey | ShiftKey,  "InsertNewline" }
138 };
139 
interpretKeyEvent(const KeyboardEvent * evt)140 static const char* interpretKeyEvent(const KeyboardEvent* evt)
141 {
142     const PlatformKeyboardEvent* keyEvent = evt->keyEvent();
143 
144     static HashMap<int, const char*>* keyDownCommandsMap = 0;
145     static HashMap<int, const char*>* keyPressCommandsMap = 0;
146 
147     if (!keyDownCommandsMap) {
148         keyDownCommandsMap = new HashMap<int, const char*>;
149         keyPressCommandsMap = new HashMap<int, const char*>;
150 
151         for (unsigned i = 0; i < sizeof(keyDownEntries)/sizeof(KeyDownEntry); i++)
152             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
153 
154         for (unsigned i = 0; i < sizeof(keyPressEntries)/sizeof(KeyPressEntry); i++)
155             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
156     }
157 
158     unsigned modifiers = 0;
159     if (keyEvent->shiftKey())
160         modifiers |= ShiftKey;
161     if (keyEvent->altKey())
162         modifiers |= AltKey;
163 
164     if (evt->type() == eventNames().keydownEvent) {
165         int mapKey = modifiers << 16 | evt->keyCode();
166         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
167     }
168 
169     int mapKey = modifiers << 16 | evt->charCode();
170     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
171 }
172 
handleKeyboardEvent(KeyboardEvent * event)173 void EditorClientAndroid::handleKeyboardEvent(KeyboardEvent* event) {
174     ASSERT(m_page);
175     Frame* frame = m_page->focusController()->focusedOrMainFrame();
176     if (!frame)
177         return;
178 
179     const PlatformKeyboardEvent* keyEvent = event->keyEvent();
180     // TODO: If the event is not coming from Android Java, e.g. from JavaScript,
181     // PlatformKeyboardEvent is null. We should support this later.
182     if (!keyEvent)
183         return;
184 
185     Editor::Command command = frame->editor()->command(interpretKeyEvent(event));
186     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
187         if (!command.isTextInsertion() && command.execute(event)) {
188             // This function mimics the Windows version.  However, calling event->setDefaultHandled()
189             // prevents the javascript key events for the delete key from happening.
190             // Update: Safari doesn't send delete key events to javascript so
191             // we will mimic that behavior.
192             event->setDefaultHandled();
193         }
194         return;
195     }
196 
197     if (command.execute(event)) {
198         event->setDefaultHandled();
199         return;
200     }
201 
202     // Don't insert null or control characters as they can result in unexpected behaviour
203     if (event->charCode() < ' ')
204         return;
205 
206     if (frame->editor()->insertText(keyEvent->text(), event))
207         event->setDefaultHandled();
208 }
209 
210 ////////////////////////////////////////////////////////////////////////////////////////////////
211 // we just don't support Undo/Redo at the moment
212 
registerCommandForUndo(PassRefPtr<EditCommand>)213 void EditorClientAndroid::registerCommandForUndo(PassRefPtr<EditCommand>) {}
registerCommandForRedo(PassRefPtr<EditCommand>)214 void EditorClientAndroid::registerCommandForRedo(PassRefPtr<EditCommand>) {}
clearUndoRedoOperations()215 void EditorClientAndroid::clearUndoRedoOperations() {}
canUndo() const216 bool EditorClientAndroid::canUndo() const { return false; }
canRedo() const217 bool EditorClientAndroid::canRedo() const { return false; }
undo()218 void EditorClientAndroid::undo() {}
redo()219 void EditorClientAndroid::redo() {}
canCopyCut(bool defaultValue) const220 bool EditorClientAndroid::canCopyCut(bool defaultValue) const { return defaultValue; }
canPaste(bool defaultValue) const221 bool EditorClientAndroid::canPaste(bool defaultValue) const { return defaultValue; }
222 
223 // functions new to Jun-07 tip of tree merge:
showSpellingUI(bool)224 void EditorClientAndroid::showSpellingUI(bool) {}
getGuessesForWord(String const &,const String &,WTF::Vector<String> &)225 void EditorClientAndroid::getGuessesForWord(String const&, const String&, WTF::Vector<String>&) {}
spellingUIIsShowing()226 bool EditorClientAndroid::spellingUIIsShowing() { return false; }
checkGrammarOfString(unsigned short const *,int,WTF::Vector<GrammarDetail> &,int *,int *)227 void EditorClientAndroid::checkGrammarOfString(unsigned short const*, int, WTF::Vector<GrammarDetail>&, int*, int*) {}
checkSpellingOfString(unsigned short const *,int,int *,int *)228 void EditorClientAndroid::checkSpellingOfString(unsigned short const*, int, int*, int*) {}
getAutoCorrectSuggestionForMisspelledWord(const String &)229 String EditorClientAndroid::getAutoCorrectSuggestionForMisspelledWord(const String&) { return String(); }
textFieldDidEndEditing(Element *)230 void EditorClientAndroid::textFieldDidEndEditing(Element*) {}
textDidChangeInTextArea(Element * element)231 void EditorClientAndroid::textDidChangeInTextArea(Element* element)
232 {
233     Frame* frame = m_page->focusController()->focusedOrMainFrame();
234     if (!frame || !frame->view())
235         return;
236     WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view());
237     webViewCore->updateTextSizeAndScroll(element);
238 }
textDidChangeInTextField(Element * element)239 void EditorClientAndroid::textDidChangeInTextField(Element* element)
240 {
241     Frame* frame = m_page->focusController()->focusedOrMainFrame();
242     if (!frame || !frame->view())
243         return;
244     WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view());
245     webViewCore->updateTextSizeAndScroll(element);
246 }
textFieldDidBeginEditing(Element *)247 void EditorClientAndroid::textFieldDidBeginEditing(Element*) {}
ignoreWordInSpellDocument(String const &)248 void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {}
249 
250 // We need to pass the selection up to the WebTextView
respondToChangedSelection()251 void EditorClientAndroid::respondToChangedSelection() {
252     if (m_uiGeneratedSelectionChange)
253         return;
254     Frame* frame = m_page->focusController()->focusedOrMainFrame();
255     if (!frame || !frame->view())
256         return;
257     WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view());
258     webViewCore->updateTextSelection();
259 }
260 
shouldChangeSelectedRange(Range *,Range *,EAffinity,bool)261 bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity,
262         bool) {
263     return m_shouldChangeSelectedRange;
264 }
265 
doTextFieldCommandFromEvent(Element *,KeyboardEvent *)266 bool EditorClientAndroid::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; }
textWillBeDeletedInTextField(Element *)267 void EditorClientAndroid::textWillBeDeletedInTextField(Element*) {}
updateSpellingUIWithGrammarString(String const &,GrammarDetail const &)268 void EditorClientAndroid::updateSpellingUIWithGrammarString(String const&, GrammarDetail const&) {}
updateSpellingUIWithMisspelledWord(String const &)269 void EditorClientAndroid::updateSpellingUIWithMisspelledWord(String const&) {}
learnWord(String const &)270 void EditorClientAndroid::learnWord(String const&) {}
271 
272 // functions new to the Nov-16-08 tip of tree merge:
shouldMoveRangeAfterDelete(Range *,Range *)273 bool EditorClientAndroid::shouldMoveRangeAfterDelete(Range*, Range*) { return true; }
setInputMethodState(bool)274 void EditorClientAndroid::setInputMethodState(bool) {}
275 
276 // functions new to Feb-19 tip of tree merge:
handleInputMethodKeydown(KeyboardEvent *)277 void EditorClientAndroid::handleInputMethodKeydown(KeyboardEvent*) {}
278 
willSetInputMethodState()279 void EditorClientAndroid::willSetInputMethodState()
280 {
281     notImplemented();
282 }
283 
requestCheckingOfString(SpellChecker *,int,TextCheckingTypeMask,const String &)284 void EditorClientAndroid::requestCheckingOfString(SpellChecker*, int, TextCheckingTypeMask, const String&) {}
285 
286 #if ENABLE(WEB_AUTOFILL)
getAutofill()287 WebAutofill* EditorClientAndroid::getAutofill()
288 {
289     if (!m_autoFill)
290         m_autoFill.set(new WebAutofill());
291 
292     return m_autoFill.get();
293 }
294 #endif
295 
296 }
297