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 47 void EditorClientAndroid::pageDestroyed() { 48 delete this; 49 } 50 51 bool EditorClientAndroid::shouldDeleteRange(Range*) { return true; } 52 bool EditorClientAndroid::shouldShowDeleteInterface(HTMLElement*) { notImplemented(); return false; } 53 bool EditorClientAndroid::smartInsertDeleteEnabled() { notImplemented(); return false; } 54 bool EditorClientAndroid::isSelectTrailingWhitespaceEnabled(){ notImplemented(); return false; } 55 bool EditorClientAndroid::isContinuousSpellCheckingEnabled() { notImplemented(); return false; } 56 void EditorClientAndroid::toggleContinuousSpellChecking() { notImplemented(); } 57 bool EditorClientAndroid::isGrammarCheckingEnabled() { notImplemented(); return false; } 58 void EditorClientAndroid::toggleGrammarChecking() { notImplemented(); } 59 int EditorClientAndroid::spellCheckerDocumentTag() { notImplemented(); return -1; } 60 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 65 bool EditorClientAndroid::shouldBeginEditing(Range*) 66 { 67 return true; 68 } 69 70 bool EditorClientAndroid::shouldEndEditing(Range*) 71 { 72 return true; 73 } 74 75 bool EditorClientAndroid::shouldInsertNode(Node*, Range*, EditorInsertAction) { notImplemented(); return true; } 76 bool EditorClientAndroid::shouldInsertText(const String&, Range*, EditorInsertAction) { return true; } 77 bool EditorClientAndroid::shouldApplyStyle(CSSStyleDeclaration*, Range*) { notImplemented(); return true; } 78 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) 83 void EditorClientAndroid::respondToChangedContents() { notImplemented(); } 84 85 void EditorClientAndroid::didEndEditing() { notImplemented(); } 86 void EditorClientAndroid::didWriteSelectionToPasteboard() { notImplemented(); } 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 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 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 213 void EditorClientAndroid::registerCommandForUndo(PassRefPtr<EditCommand>) {} 214 void EditorClientAndroid::registerCommandForRedo(PassRefPtr<EditCommand>) {} 215 void EditorClientAndroid::clearUndoRedoOperations() {} 216 bool EditorClientAndroid::canUndo() const { return false; } 217 bool EditorClientAndroid::canRedo() const { return false; } 218 void EditorClientAndroid::undo() {} 219 void EditorClientAndroid::redo() {} 220 bool EditorClientAndroid::canCopyCut(bool defaultValue) const { return defaultValue; } 221 bool EditorClientAndroid::canPaste(bool defaultValue) const { return defaultValue; } 222 223 // functions new to Jun-07 tip of tree merge: 224 void EditorClientAndroid::showSpellingUI(bool) {} 225 void EditorClientAndroid::getGuessesForWord(String const&, const String&, WTF::Vector<String>&) {} 226 bool EditorClientAndroid::spellingUIIsShowing() { return false; } 227 void EditorClientAndroid::checkGrammarOfString(unsigned short const*, int, WTF::Vector<GrammarDetail>&, int*, int*) {} 228 void EditorClientAndroid::checkSpellingOfString(unsigned short const*, int, int*, int*) {} 229 String EditorClientAndroid::getAutoCorrectSuggestionForMisspelledWord(const String&) { return String(); } 230 void EditorClientAndroid::textFieldDidEndEditing(Element*) {} 231 void EditorClientAndroid::textDidChangeInTextArea(Element*) {} 232 void EditorClientAndroid::textDidChangeInTextField(Element*) {} 233 void EditorClientAndroid::textFieldDidBeginEditing(Element*) {} 234 void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {} 235 236 // We need to pass the selection up to the WebTextView 237 void EditorClientAndroid::respondToChangedSelection() { 238 if (m_uiGeneratedSelectionChange) 239 return; 240 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 241 if (!frame || !frame->view()) 242 return; 243 WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view()); 244 webViewCore->updateTextSelection(); 245 } 246 247 bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity, 248 bool) { 249 return m_shouldChangeSelectedRange; 250 } 251 252 bool EditorClientAndroid::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; } 253 void EditorClientAndroid::textWillBeDeletedInTextField(Element*) {} 254 void EditorClientAndroid::updateSpellingUIWithGrammarString(String const&, GrammarDetail const&) {} 255 void EditorClientAndroid::updateSpellingUIWithMisspelledWord(String const&) {} 256 void EditorClientAndroid::learnWord(String const&) {} 257 258 // functions new to the Nov-16-08 tip of tree merge: 259 bool EditorClientAndroid::shouldMoveRangeAfterDelete(Range*, Range*) { return true; } 260 void EditorClientAndroid::setInputMethodState(bool) {} 261 262 // functions new to Feb-19 tip of tree merge: 263 void EditorClientAndroid::handleInputMethodKeydown(KeyboardEvent*) {} 264 265 void EditorClientAndroid::willSetInputMethodState() 266 { 267 notImplemented(); 268 } 269 270 void EditorClientAndroid::requestCheckingOfString(SpellChecker*, int, TextCheckingTypeMask, const String&) {} 271 272 #if ENABLE(WEB_AUTOFILL) 273 WebAutofill* EditorClientAndroid::getAutofill() 274 { 275 if (!m_autoFill) 276 m_autoFill.set(new WebAutofill()); 277 278 return m_autoFill.get(); 279 } 280 #endif 281 282 } 283