Home | History | Annotate | Download | only in WebCoreSupport
      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