Home | History | Annotate | Download | only in WebKitSupport
      1 /*
      2  * Copyright (C) 2007 Kevin Ollivier <kevino (at) theolliviers.com>
      3  *
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     16  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     19  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     22  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     23  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 #include "config.h"
     28 #include "EditorClientWx.h"
     29 
     30 #include "EditCommand.h"
     31 #include "Editor.h"
     32 #include "FocusController.h"
     33 #include "Frame.h"
     34 #include "FrameView.h"
     35 #include "HostWindow.h"
     36 #include "KeyboardEvent.h"
     37 #include "NotImplemented.h"
     38 #include "Page.h"
     39 #include "PlatformKeyboardEvent.h"
     40 #include "PlatformString.h"
     41 #include "SelectionController.h"
     42 #include "WebFrame.h"
     43 #include "WebFramePrivate.h"
     44 #include "WebView.h"
     45 #include "WebViewPrivate.h"
     46 #include "WindowsKeyboardCodes.h"
     47 
     48 #include <stdio.h>
     49 
     50 namespace WebCore {
     51 
     52 static const unsigned CtrlKey = 1 << 0;
     53 static const unsigned AltKey = 1 << 1;
     54 static const unsigned ShiftKey = 1 << 2;
     55 
     56 struct KeyDownEntry {
     57     unsigned virtualKey;
     58     unsigned modifiers;
     59     const char* name;
     60 };
     61 
     62 struct KeyPressEntry {
     63     unsigned charCode;
     64     unsigned modifiers;
     65     const char* name;
     66 };
     67 
     68 static const KeyDownEntry keyDownEntries[] = {
     69     { VK_LEFT,   0,                  "MoveLeft"                                    },
     70     { VK_LEFT,   ShiftKey,           "MoveLeftAndModifySelection"                  },
     71     { VK_LEFT,   CtrlKey,            "MoveWordLeft"                                },
     72     { VK_LEFT,   CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"              },
     73     { VK_RIGHT,  0,                  "MoveRight"                                   },
     74     { VK_RIGHT,  ShiftKey,           "MoveRightAndModifySelection"                 },
     75     { VK_RIGHT,  CtrlKey,            "MoveWordRight"                               },
     76     { VK_RIGHT,  CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"             },
     77     { VK_UP,     0,                  "MoveUp"                                      },
     78     { VK_UP,     ShiftKey,           "MoveUpAndModifySelection"                    },
     79     { VK_PRIOR,  ShiftKey,           "MovePageUpAndModifySelection"                },
     80     { VK_DOWN,   0,                  "MoveDown"                                    },
     81     { VK_DOWN,   ShiftKey,           "MoveDownAndModifySelection"                  },
     82     { VK_NEXT,   ShiftKey,           "MovePageDownAndModifySelection"              },
     83     { VK_PRIOR,  0,                  "MovePageUp"                                  },
     84     { VK_NEXT,   0,                  "MovePageDown"                                },
     85     { VK_HOME,   0,                  "MoveToBeginningOfLine"                       },
     86     { VK_HOME,   ShiftKey,           "MoveToBeginningOfLineAndModifySelection"     },
     87     { VK_HOME,   CtrlKey,            "MoveToBeginningOfDocument"                   },
     88     { VK_HOME,   CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
     89 
     90     { VK_END,    0,                  "MoveToEndOfLine"                             },
     91     { VK_END,    ShiftKey,           "MoveToEndOfLineAndModifySelection"           },
     92     { VK_END,    CtrlKey,            "MoveToEndOfDocument"                         },
     93     { VK_END,    CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"       },
     94 
     95     { VK_BACK,   0,                  "DeleteBackward"                              },
     96     { VK_BACK,   ShiftKey,           "DeleteBackward"                              },
     97     { VK_DELETE, 0,                  "DeleteForward"                               },
     98     { VK_BACK,   CtrlKey,            "DeleteWordBackward"                          },
     99     { VK_DELETE, CtrlKey,            "DeleteWordForward"                           },
    100 
    101     { 'B',       CtrlKey,            "ToggleBold"                                  },
    102     { 'I',       CtrlKey,            "ToggleItalic"                                },
    103 
    104     { VK_ESCAPE, 0,                  "Cancel"                                      },
    105     //FIXME: this'll never happen. We can trash it or make it a normal period
    106     { VK_OEM_PERIOD, CtrlKey,        "Cancel"                                      },
    107     { VK_TAB,    0,                  "InsertTab"                                   },
    108     { VK_TAB,    ShiftKey,           "InsertBacktab"                               },
    109     { VK_RETURN, 0,                  "InsertNewline"                               },
    110     { VK_RETURN, CtrlKey,            "InsertNewline"                               },
    111     { VK_RETURN, AltKey,             "InsertNewline"                               },
    112     { VK_RETURN, ShiftKey,           "InsertLineBreak"                               },
    113     { 'A',       CtrlKey,            "SelectAll"                                   },
    114     { 'Z',       CtrlKey,            "Undo"                                        },
    115     { 'Z',       CtrlKey | ShiftKey, "Redo"                                        },
    116 };
    117 
    118 static const KeyPressEntry keyPressEntries[] = {
    119     { '\t',   0,                  "InsertTab"                                   },
    120     { '\t',   ShiftKey,           "InsertBacktab"                               },
    121     { '\r',   0,                  "InsertNewline"                               },
    122     { '\r',   CtrlKey,            "InsertNewline"                               },
    123     { '\r',   AltKey,             "InsertNewline"                               },
    124     { '\r',   AltKey | ShiftKey,  "InsertNewline"                               },
    125 };
    126 
    127 EditorClientWx::~EditorClientWx()
    128 {
    129     m_page = NULL;
    130 }
    131 
    132 void EditorClientWx::setPage(Page* page)
    133 {
    134     m_page = page;
    135 }
    136 
    137 void EditorClientWx::pageDestroyed()
    138 {
    139     delete this;
    140 }
    141 
    142 bool EditorClientWx::shouldDeleteRange(Range*)
    143 {
    144     notImplemented();
    145     return true;
    146 }
    147 
    148 bool EditorClientWx::shouldShowDeleteInterface(HTMLElement*)
    149 {
    150     notImplemented();
    151     return false;
    152 }
    153 
    154 bool EditorClientWx::smartInsertDeleteEnabled()
    155 {
    156     notImplemented();
    157     return false;
    158 }
    159 
    160 bool EditorClientWx::isSelectTrailingWhitespaceEnabled()
    161 {
    162     notImplemented();
    163     return false;
    164 }
    165 
    166 bool EditorClientWx::isContinuousSpellCheckingEnabled()
    167 {
    168     notImplemented();
    169     return false;
    170 }
    171 
    172 void EditorClientWx::toggleContinuousSpellChecking()
    173 {
    174     notImplemented();
    175 }
    176 
    177 bool EditorClientWx::isGrammarCheckingEnabled()
    178 {
    179     notImplemented();
    180     return false;
    181 }
    182 
    183 void EditorClientWx::toggleGrammarChecking()
    184 {
    185     notImplemented();
    186 }
    187 
    188 int EditorClientWx::spellCheckerDocumentTag()
    189 {
    190     notImplemented();
    191     return 0;
    192 }
    193 
    194 bool EditorClientWx::selectWordBeforeMenuEvent()
    195 {
    196     notImplemented();
    197     return false;
    198 }
    199 
    200 bool EditorClientWx::shouldBeginEditing(Range*)
    201 {
    202     notImplemented();
    203     return true;
    204 }
    205 
    206 bool EditorClientWx::shouldEndEditing(Range*)
    207 {
    208     notImplemented();
    209     return true;
    210 }
    211 
    212 bool EditorClientWx::shouldInsertNode(Node*, Range*,
    213                                        EditorInsertAction)
    214 {
    215     notImplemented();
    216     return true;
    217 }
    218 
    219 bool EditorClientWx::shouldInsertText(const String&, Range*,
    220                                        EditorInsertAction)
    221 {
    222     notImplemented();
    223     return true;
    224 }
    225 
    226 bool EditorClientWx::shouldApplyStyle(CSSStyleDeclaration*,
    227                                        Range*)
    228 {
    229     notImplemented();
    230     return true;
    231 }
    232 
    233 bool EditorClientWx::shouldMoveRangeAfterDelete(Range*, Range*)
    234 {
    235     notImplemented();
    236     return true;
    237 }
    238 
    239 bool EditorClientWx::shouldChangeSelectedRange(Range* fromRange, Range* toRange,
    240                                 EAffinity, bool stillSelecting)
    241 {
    242     notImplemented();
    243     return true;
    244 }
    245 
    246 void EditorClientWx::didBeginEditing()
    247 {
    248     notImplemented();
    249 }
    250 
    251 void EditorClientWx::respondToChangedContents()
    252 {
    253     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    254 
    255     if (frame) {
    256         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    257         if (webKitWin) {
    258             wxWebViewContentsChangedEvent wkEvent(webKitWin);
    259             webKitWin->GetEventHandler()->ProcessEvent(wkEvent);
    260         }
    261     }
    262 }
    263 
    264 void EditorClientWx::didEndEditing()
    265 {
    266     notImplemented();
    267 }
    268 
    269 void EditorClientWx::didWriteSelectionToPasteboard()
    270 {
    271     notImplemented();
    272 }
    273 
    274 void EditorClientWx::didSetSelectionTypesForPasteboard()
    275 {
    276     notImplemented();
    277 }
    278 
    279 void EditorClientWx::registerCommandForUndo(PassRefPtr<EditCommand> command)
    280 {
    281     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    282 
    283     if (frame) {
    284         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    285         if (webKitWin) {
    286             webKitWin->m_impl->undoStack.append(EditCommandWx(command));
    287         }
    288     }
    289 }
    290 
    291 void EditorClientWx::registerCommandForRedo(PassRefPtr<EditCommand> command)
    292 {
    293     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    294 
    295     if (frame) {
    296         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    297         if (webKitWin) {
    298             webKitWin->m_impl->redoStack.insert(0, EditCommandWx(command));
    299         }
    300     }
    301 }
    302 
    303 void EditorClientWx::clearUndoRedoOperations()
    304 {
    305     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    306 
    307     if (frame) {
    308         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    309         if (webKitWin) {
    310             webKitWin->m_impl->redoStack.clear();
    311             webKitWin->m_impl->undoStack.clear();
    312         }
    313     }
    314 }
    315 
    316 bool EditorClientWx::canCopyCut(bool defaultValue) const
    317 {
    318     return defaultValue;
    319 }
    320 
    321 bool EditorClientWx::canPaste(bool defaultValue) const
    322 {
    323     return defaultValue;
    324 }
    325 
    326 bool EditorClientWx::canUndo() const
    327 {
    328     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    329 
    330     if (frame) {
    331         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    332         if (webKitWin) {
    333             return webKitWin->m_impl->undoStack.size() != 0;
    334         }
    335     }
    336     return false;
    337 }
    338 
    339 bool EditorClientWx::canRedo() const
    340 {
    341     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    342 
    343     if (frame) {
    344         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    345         if (webKitWin && webKitWin) {
    346             return webKitWin->m_impl->redoStack.size() != 0;
    347         }
    348     }
    349     return false;
    350 }
    351 
    352 void EditorClientWx::undo()
    353 {
    354     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    355 
    356     if (frame) {
    357         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    358         if (webKitWin) {
    359             webKitWin->m_impl->undoStack.last().editCommand()->unapply();
    360             webKitWin->m_impl->undoStack.removeLast();
    361         }
    362     }
    363 }
    364 
    365 void EditorClientWx::redo()
    366 {
    367     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    368 
    369     if (frame) {
    370         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    371         if (webKitWin) {
    372             webKitWin->m_impl->redoStack.last().editCommand()->reapply();
    373             webKitWin->m_impl->redoStack.removeLast();
    374         }
    375     }
    376 }
    377 
    378 bool EditorClientWx::handleEditingKeyboardEvent(KeyboardEvent* event)
    379 {
    380     Node* node = event->target()->toNode();
    381     ASSERT(node);
    382     Frame* frame = node->document()->frame();
    383     ASSERT(frame);
    384 
    385     const PlatformKeyboardEvent* keyEvent = event->keyEvent();
    386 
    387     //NB: this is what windows does, but they also have a keypress event for Alt+Enter which clearly won't get hit with this
    388     if (!keyEvent || keyEvent->altKey())  // do not treat this as text input if Alt is down
    389         return false;
    390 
    391     Editor::Command command = frame->editor()->command(interpretKeyEvent(event));
    392 
    393     if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
    394         // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
    395         // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or if not to let a CHAR event be generated
    396         // (e.g. Tab that inserts a Tab character, or Enter).
    397         return !command.isTextInsertion() && command.execute(event);
    398     }
    399 
    400      if (command.execute(event))
    401         return true;
    402 
    403     // Don't insert null or control characters as they can result in unexpected behaviour
    404     if (event->charCode() < ' ')
    405         return false;
    406 
    407     return frame->editor()->insertText(event->keyEvent()->text(), event);
    408 }
    409 
    410 const char* EditorClientWx::interpretKeyEvent(const KeyboardEvent* evt)
    411 {
    412     ASSERT(evt->keyEvent()->type() == PlatformKeyboardEvent::RawKeyDown || evt->keyEvent()->type() == PlatformKeyboardEvent::Char);
    413 
    414     static HashMap<int, const char*>* keyDownCommandsMap = 0;
    415     static HashMap<int, const char*>* keyPressCommandsMap = 0;
    416 
    417     if (!keyDownCommandsMap) {
    418         keyDownCommandsMap = new HashMap<int, const char*>;
    419         keyPressCommandsMap = new HashMap<int, const char*>;
    420 
    421         for (unsigned i = 0; i < WXSIZEOF(keyDownEntries); i++)
    422             keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
    423 
    424         for (unsigned i = 0; i < WXSIZEOF(keyPressEntries); i++)
    425             keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
    426     }
    427 
    428     unsigned modifiers = 0;
    429     if (evt->shiftKey())
    430         modifiers |= ShiftKey;
    431     if (evt->altKey())
    432         modifiers |= AltKey;
    433     if (evt->ctrlKey())
    434         modifiers |= CtrlKey;
    435 
    436     if (evt->keyEvent()->type() == PlatformKeyboardEvent::RawKeyDown) {
    437         int mapKey = modifiers << 16 | evt->keyCode();
    438         return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
    439     }
    440 
    441     int mapKey = modifiers << 16 | evt->charCode();
    442     return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
    443 }
    444 
    445 
    446 void EditorClientWx::handleInputMethodKeydown(KeyboardEvent* event)
    447 {
    448 // NOTE: we don't currently need to handle this. When key events occur,
    449 // both this method and handleKeyboardEvent get a chance at handling them.
    450 // We might use this method later on for IME-specific handling.
    451 }
    452 
    453 void EditorClientWx::handleKeyboardEvent(KeyboardEvent* event)
    454 {
    455     if (handleEditingKeyboardEvent(event))
    456         event->setDefaultHandled();
    457 }
    458 
    459 void EditorClientWx::textFieldDidBeginEditing(Element*)
    460 {
    461     notImplemented();
    462 }
    463 
    464 void EditorClientWx::textFieldDidEndEditing(Element*)
    465 {
    466     notImplemented();
    467 }
    468 
    469 void EditorClientWx::textDidChangeInTextField(Element*)
    470 {
    471     notImplemented();
    472 }
    473 
    474 bool EditorClientWx::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
    475 {
    476     notImplemented();
    477     return false;
    478 }
    479 
    480 void EditorClientWx::textWillBeDeletedInTextField(Element*)
    481 {
    482     notImplemented();
    483 }
    484 
    485 void EditorClientWx::textDidChangeInTextArea(Element*)
    486 {
    487     notImplemented();
    488 }
    489 
    490 void EditorClientWx::respondToChangedSelection()
    491 {
    492     Frame* frame = m_page->focusController()->focusedOrMainFrame();
    493     if (frame) {
    494         wxWebView* webKitWin = dynamic_cast<wxWebView*>(frame->view()->hostWindow()->platformPageClient());
    495         if (webKitWin) {
    496             wxWebViewSelectionChangedEvent wkEvent(webKitWin);
    497             webKitWin->GetEventHandler()->ProcessEvent(wkEvent);
    498         }
    499     }
    500 }
    501 
    502 void EditorClientWx::ignoreWordInSpellDocument(const String&)
    503 {
    504     notImplemented();
    505 }
    506 
    507 void EditorClientWx::learnWord(const String&)
    508 {
    509     notImplemented();
    510 }
    511 
    512 void EditorClientWx::checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength)
    513 {
    514     notImplemented();
    515 }
    516 
    517 void EditorClientWx::checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength)
    518 {
    519     notImplemented();
    520 }
    521 
    522 void EditorClientWx::updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail)
    523 {
    524     notImplemented();
    525 }
    526 
    527 void EditorClientWx::updateSpellingUIWithMisspelledWord(const String&)
    528 {
    529     notImplemented();
    530 }
    531 
    532 void EditorClientWx::showSpellingUI(bool show)
    533 {
    534     notImplemented();
    535 }
    536 
    537 bool EditorClientWx::spellingUIIsShowing()
    538 {
    539     notImplemented();
    540     return false;
    541 }
    542 
    543 void EditorClientWx::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
    544 {
    545     notImplemented();
    546 }
    547 
    548 String EditorClientWx::getAutoCorrectSuggestionForMisspelledWord(const WTF::String&)
    549 {
    550     notImplemented();
    551     return String();
    552 }
    553 
    554 void EditorClientWx::willSetInputMethodState()
    555 {
    556     notImplemented();
    557 }
    558 
    559 void EditorClientWx::setInputMethodState(bool enabled)
    560 {
    561     notImplemented();
    562 }
    563 
    564 }
    565