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 "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* 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 }
    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 }
    247 void EditorClientAndroid::textFieldDidBeginEditing(Element*) {}
    248 void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {}
    249 
    250 // We need to pass the selection up to the WebTextView
    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 
    261 bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity,
    262         bool) {
    263     return m_shouldChangeSelectedRange;
    264 }
    265 
    266 bool EditorClientAndroid::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; }
    267 void EditorClientAndroid::textWillBeDeletedInTextField(Element*) {}
    268 void EditorClientAndroid::updateSpellingUIWithGrammarString(String const&, GrammarDetail const&) {}
    269 void EditorClientAndroid::updateSpellingUIWithMisspelledWord(String const&) {}
    270 void EditorClientAndroid::learnWord(String const&) {}
    271 
    272 // functions new to the Nov-16-08 tip of tree merge:
    273 bool EditorClientAndroid::shouldMoveRangeAfterDelete(Range*, Range*) { return true; }
    274 void EditorClientAndroid::setInputMethodState(bool) {}
    275 
    276 // functions new to Feb-19 tip of tree merge:
    277 void EditorClientAndroid::handleInputMethodKeydown(KeyboardEvent*) {}
    278 
    279 void EditorClientAndroid::willSetInputMethodState()
    280 {
    281     notImplemented();
    282 }
    283 
    284 void EditorClientAndroid::requestCheckingOfString(SpellChecker*, int, TextCheckingTypeMask, const String&) {}
    285 
    286 #if ENABLE(WEB_AUTOFILL)
    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