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 "KeyboardCodes.h" 36 #include "KeyboardEvent.h" 37 #include "NotImplemented.h" 38 #include "PlatformKeyboardEvent.h" 39 #include "PlatformString.h" 40 #include "WebViewCore.h" 41 42 namespace android { 43 44 void EditorClientAndroid::pageDestroyed() { 45 delete this; 46 } 47 48 bool EditorClientAndroid::shouldDeleteRange(Range*) { return true; } 49 bool EditorClientAndroid::shouldShowDeleteInterface(HTMLElement*) { notImplemented(); return false; } 50 bool EditorClientAndroid::smartInsertDeleteEnabled() { notImplemented(); return false; } 51 bool EditorClientAndroid::isSelectTrailingWhitespaceEnabled(){ notImplemented(); return false; } 52 bool EditorClientAndroid::isContinuousSpellCheckingEnabled() { notImplemented(); return false; } 53 void EditorClientAndroid::toggleContinuousSpellChecking() { notImplemented(); } 54 bool EditorClientAndroid::isGrammarCheckingEnabled() { notImplemented(); return false; } 55 void EditorClientAndroid::toggleGrammarChecking() { notImplemented(); } 56 int EditorClientAndroid::spellCheckerDocumentTag() { notImplemented(); return -1; } 57 58 bool EditorClientAndroid::isEditable() { /* notImplemented(); */ return false; } 59 60 // Following Qt's implementation. For shouldBeginEditing and shouldEndEditing. 61 // Returning true for these fixes issue http://b/issue?id=735185 62 bool EditorClientAndroid::shouldBeginEditing(Range*) 63 { 64 return true; 65 } 66 67 bool EditorClientAndroid::shouldEndEditing(Range*) 68 { 69 return true; 70 } 71 72 bool EditorClientAndroid::shouldInsertNode(Node*, Range*, EditorInsertAction) { notImplemented(); return true; } 73 bool EditorClientAndroid::shouldInsertText(const String&, Range*, EditorInsertAction) { return true; } 74 bool EditorClientAndroid::shouldApplyStyle(CSSStyleDeclaration*, Range*) { notImplemented(); return true; } 75 76 void EditorClientAndroid::didBeginEditing() { notImplemented(); } 77 78 // This function is called so that the platform can handle changes to content. It is called 79 // after the contents have been edited or unedited (ie undo) 80 void EditorClientAndroid::respondToChangedContents() { notImplemented(); } 81 82 void EditorClientAndroid::didEndEditing() { notImplemented(); } 83 void EditorClientAndroid::didWriteSelectionToPasteboard() { notImplemented(); } 84 void EditorClientAndroid::didSetSelectionTypesForPasteboard() { notImplemented(); } 85 86 // Copied from the Window's port of WebKit. 87 static const unsigned AltKey = 1 << 0; 88 static const unsigned ShiftKey = 1 << 1; 89 90 struct KeyDownEntry { 91 unsigned virtualKey; 92 unsigned modifiers; 93 const char* name; 94 }; 95 96 struct KeyPressEntry { 97 unsigned charCode; 98 unsigned modifiers; 99 const char* name; 100 }; 101 102 static const KeyDownEntry keyDownEntries[] = { 103 { VK_LEFT, 0, "MoveLeft" }, 104 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" }, 105 { VK_LEFT, AltKey, "MoveWordLeft" }, 106 { VK_LEFT, AltKey | ShiftKey, "MoveWordLeftAndModifySelection" }, 107 { VK_RIGHT, 0, "MoveRight" }, 108 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" }, 109 { VK_RIGHT, AltKey, "MoveWordRight" }, 110 { VK_RIGHT, AltKey | ShiftKey, "MoveWordRightAndModifySelection" }, 111 { VK_UP, 0, "MoveUp" }, 112 { VK_UP, ShiftKey, "MoveUpAndModifySelection" }, 113 { VK_DOWN, 0, "MoveDown" }, 114 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" }, 115 116 { VK_BACK, 0, "BackwardDelete" }, 117 { VK_BACK, ShiftKey, "ForwardDelete" }, 118 { VK_BACK, AltKey, "DeleteWordBackward" }, 119 { VK_BACK, AltKey | ShiftKey, "DeleteWordForward" }, 120 121 { VK_ESCAPE, 0, "Cancel" }, 122 { VK_TAB, 0, "InsertTab" }, 123 { VK_TAB, ShiftKey, "InsertBacktab" }, 124 { VK_RETURN, 0, "InsertNewline" }, 125 { VK_RETURN, AltKey, "InsertNewline" }, 126 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" } 127 }; 128 129 static const KeyPressEntry keyPressEntries[] = { 130 { '\t', 0, "InsertTab" }, 131 { '\t', ShiftKey, "InsertBackTab" }, 132 { '\r', 0, "InsertNewline" }, 133 { '\r', AltKey, "InsertNewline" }, 134 { '\r', AltKey | ShiftKey, "InsertNewline" } 135 }; 136 137 static const char* interpretKeyEvent(const KeyboardEvent* evt) 138 { 139 const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); 140 141 static HashMap<int, const char*>* keyDownCommandsMap = 0; 142 static HashMap<int, const char*>* keyPressCommandsMap = 0; 143 144 if (!keyDownCommandsMap) { 145 keyDownCommandsMap = new HashMap<int, const char*>; 146 keyPressCommandsMap = new HashMap<int, const char*>; 147 148 for (unsigned i = 0; i < sizeof(keyDownEntries)/sizeof(KeyDownEntry); i++) 149 keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name); 150 151 for (unsigned i = 0; i < sizeof(keyPressEntries)/sizeof(KeyPressEntry); i++) 152 keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name); 153 } 154 155 unsigned modifiers = 0; 156 if (keyEvent->shiftKey()) 157 modifiers |= ShiftKey; 158 if (keyEvent->altKey()) 159 modifiers |= AltKey; 160 161 if (evt->type() == eventNames().keydownEvent) { 162 int mapKey = modifiers << 16 | evt->keyCode(); 163 return mapKey ? keyDownCommandsMap->get(mapKey) : 0; 164 } 165 166 int mapKey = modifiers << 16 | evt->charCode(); 167 return mapKey ? keyPressCommandsMap->get(mapKey) : 0; 168 } 169 170 void EditorClientAndroid::handleKeyboardEvent(KeyboardEvent* event) { 171 ASSERT(m_page); 172 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 173 if (!frame) 174 return; 175 176 const PlatformKeyboardEvent* keyEvent = event->keyEvent(); 177 // TODO: If the event is not coming from Android Java, e.g. from JavaScript, 178 // PlatformKeyboardEvent is null. We should support this later. 179 if (!keyEvent) 180 return; 181 182 Editor::Command command = frame->editor()->command(interpretKeyEvent(event)); 183 if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) { 184 if (!command.isTextInsertion() && command.execute(event)) { 185 // This function mimics the Windows version. However, calling event->setDefaultHandled() 186 // prevents the javascript key events for the delete key from happening. 187 // Update: Safari doesn't send delete key events to javascript so 188 // we will mimic that behavior. 189 event->setDefaultHandled(); 190 } 191 return; 192 } 193 194 if (command.execute(event)) { 195 event->setDefaultHandled(); 196 return; 197 } 198 199 // Don't insert null or control characters as they can result in unexpected behaviour 200 if (event->charCode() < ' ') 201 return; 202 203 if (frame->editor()->insertText(keyEvent->text(), event)) 204 event->setDefaultHandled(); 205 } 206 207 //////////////////////////////////////////////////////////////////////////////////////////////// 208 // we just don't support Undo/Redo at the moment 209 210 void EditorClientAndroid::registerCommandForUndo(PassRefPtr<EditCommand>) {} 211 void EditorClientAndroid::registerCommandForRedo(PassRefPtr<EditCommand>) {} 212 void EditorClientAndroid::clearUndoRedoOperations() {} 213 bool EditorClientAndroid::canUndo() const { return false; } 214 bool EditorClientAndroid::canRedo() const { return false; } 215 void EditorClientAndroid::undo() {} 216 void EditorClientAndroid::redo() {} 217 218 // functions new to Jun-07 tip of tree merge: 219 void EditorClientAndroid::showSpellingUI(bool) {} 220 void EditorClientAndroid::getGuessesForWord(String const&, WTF::Vector<String>&) {} 221 bool EditorClientAndroid::spellingUIIsShowing() { return false; } 222 void EditorClientAndroid::checkGrammarOfString(unsigned short const*, int, WTF::Vector<GrammarDetail>&, int*, int*) {} 223 void EditorClientAndroid::checkSpellingOfString(unsigned short const*, int, int*, int*) {} 224 String EditorClientAndroid::getAutoCorrectSuggestionForMisspelledWord(const String&) { return String(); } 225 void EditorClientAndroid::textFieldDidEndEditing(Element*) {} 226 void EditorClientAndroid::textDidChangeInTextArea(Element*) {} 227 void EditorClientAndroid::textDidChangeInTextField(Element*) {} 228 void EditorClientAndroid::textFieldDidBeginEditing(Element*) {} 229 void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {} 230 231 // We need to pass the selection up to the WebTextView 232 void EditorClientAndroid::respondToChangedSelection() { 233 if (m_uiGeneratedSelectionChange) 234 return; 235 Frame* frame = m_page->focusController()->focusedOrMainFrame(); 236 if (!frame || !frame->view()) 237 return; 238 WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view()); 239 webViewCore->updateTextSelection(); 240 } 241 242 bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity, 243 bool) { 244 return m_shouldChangeSelectedRange; 245 } 246 247 bool EditorClientAndroid::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; } 248 void EditorClientAndroid::textWillBeDeletedInTextField(Element*) {} 249 void EditorClientAndroid::updateSpellingUIWithGrammarString(String const&, GrammarDetail const&) {} 250 void EditorClientAndroid::updateSpellingUIWithMisspelledWord(String const&) {} 251 void EditorClientAndroid::learnWord(String const&) {} 252 253 // functions new to the Nov-16-08 tip of tree merge: 254 bool EditorClientAndroid::shouldMoveRangeAfterDelete(Range*, Range*) { return true; } 255 void EditorClientAndroid::setInputMethodState(bool) {} 256 257 // functions new to Feb-19 tip of tree merge: 258 void EditorClientAndroid::handleInputMethodKeydown(KeyboardEvent*) {} 259 260 } 261