• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 Kevin Ollivier <kevino@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 
~EditorClientWx()127 EditorClientWx::~EditorClientWx()
128 {
129     m_page = NULL;
130 }
131 
setPage(Page * page)132 void EditorClientWx::setPage(Page* page)
133 {
134     m_page = page;
135 }
136 
pageDestroyed()137 void EditorClientWx::pageDestroyed()
138 {
139     delete this;
140 }
141 
shouldDeleteRange(Range *)142 bool EditorClientWx::shouldDeleteRange(Range*)
143 {
144     notImplemented();
145     return true;
146 }
147 
shouldShowDeleteInterface(HTMLElement *)148 bool EditorClientWx::shouldShowDeleteInterface(HTMLElement*)
149 {
150     notImplemented();
151     return false;
152 }
153 
smartInsertDeleteEnabled()154 bool EditorClientWx::smartInsertDeleteEnabled()
155 {
156     notImplemented();
157     return false;
158 }
159 
isSelectTrailingWhitespaceEnabled()160 bool EditorClientWx::isSelectTrailingWhitespaceEnabled()
161 {
162     notImplemented();
163     return false;
164 }
165 
isContinuousSpellCheckingEnabled()166 bool EditorClientWx::isContinuousSpellCheckingEnabled()
167 {
168     notImplemented();
169     return false;
170 }
171 
toggleContinuousSpellChecking()172 void EditorClientWx::toggleContinuousSpellChecking()
173 {
174     notImplemented();
175 }
176 
isGrammarCheckingEnabled()177 bool EditorClientWx::isGrammarCheckingEnabled()
178 {
179     notImplemented();
180     return false;
181 }
182 
toggleGrammarChecking()183 void EditorClientWx::toggleGrammarChecking()
184 {
185     notImplemented();
186 }
187 
spellCheckerDocumentTag()188 int EditorClientWx::spellCheckerDocumentTag()
189 {
190     notImplemented();
191     return 0;
192 }
193 
selectWordBeforeMenuEvent()194 bool EditorClientWx::selectWordBeforeMenuEvent()
195 {
196     notImplemented();
197     return false;
198 }
199 
shouldBeginEditing(Range *)200 bool EditorClientWx::shouldBeginEditing(Range*)
201 {
202     notImplemented();
203     return true;
204 }
205 
shouldEndEditing(Range *)206 bool EditorClientWx::shouldEndEditing(Range*)
207 {
208     notImplemented();
209     return true;
210 }
211 
shouldInsertNode(Node *,Range *,EditorInsertAction)212 bool EditorClientWx::shouldInsertNode(Node*, Range*,
213                                        EditorInsertAction)
214 {
215     notImplemented();
216     return true;
217 }
218 
shouldInsertText(const String &,Range *,EditorInsertAction)219 bool EditorClientWx::shouldInsertText(const String&, Range*,
220                                        EditorInsertAction)
221 {
222     notImplemented();
223     return true;
224 }
225 
shouldApplyStyle(CSSStyleDeclaration *,Range *)226 bool EditorClientWx::shouldApplyStyle(CSSStyleDeclaration*,
227                                        Range*)
228 {
229     notImplemented();
230     return true;
231 }
232 
shouldMoveRangeAfterDelete(Range *,Range *)233 bool EditorClientWx::shouldMoveRangeAfterDelete(Range*, Range*)
234 {
235     notImplemented();
236     return true;
237 }
238 
shouldChangeSelectedRange(Range * fromRange,Range * toRange,EAffinity,bool stillSelecting)239 bool EditorClientWx::shouldChangeSelectedRange(Range* fromRange, Range* toRange,
240                                 EAffinity, bool stillSelecting)
241 {
242     notImplemented();
243     return true;
244 }
245 
didBeginEditing()246 void EditorClientWx::didBeginEditing()
247 {
248     notImplemented();
249 }
250 
respondToChangedContents()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 
didEndEditing()264 void EditorClientWx::didEndEditing()
265 {
266     notImplemented();
267 }
268 
didWriteSelectionToPasteboard()269 void EditorClientWx::didWriteSelectionToPasteboard()
270 {
271     notImplemented();
272 }
273 
didSetSelectionTypesForPasteboard()274 void EditorClientWx::didSetSelectionTypesForPasteboard()
275 {
276     notImplemented();
277 }
278 
registerCommandForUndo(PassRefPtr<EditCommand> command)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 
registerCommandForRedo(PassRefPtr<EditCommand> command)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 
clearUndoRedoOperations()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 
canCopyCut(bool defaultValue) const316 bool EditorClientWx::canCopyCut(bool defaultValue) const
317 {
318     return defaultValue;
319 }
320 
canPaste(bool defaultValue) const321 bool EditorClientWx::canPaste(bool defaultValue) const
322 {
323     return defaultValue;
324 }
325 
canUndo() const326 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 
canRedo() const339 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 
undo()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 
redo()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 
handleEditingKeyboardEvent(KeyboardEvent * event)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 
interpretKeyEvent(const KeyboardEvent * evt)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 
handleInputMethodKeydown(KeyboardEvent * event)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 
handleKeyboardEvent(KeyboardEvent * event)453 void EditorClientWx::handleKeyboardEvent(KeyboardEvent* event)
454 {
455     if (handleEditingKeyboardEvent(event))
456         event->setDefaultHandled();
457 }
458 
textFieldDidBeginEditing(Element *)459 void EditorClientWx::textFieldDidBeginEditing(Element*)
460 {
461     notImplemented();
462 }
463 
textFieldDidEndEditing(Element *)464 void EditorClientWx::textFieldDidEndEditing(Element*)
465 {
466     notImplemented();
467 }
468 
textDidChangeInTextField(Element *)469 void EditorClientWx::textDidChangeInTextField(Element*)
470 {
471     notImplemented();
472 }
473 
doTextFieldCommandFromEvent(Element *,KeyboardEvent *)474 bool EditorClientWx::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
475 {
476     notImplemented();
477     return false;
478 }
479 
textWillBeDeletedInTextField(Element *)480 void EditorClientWx::textWillBeDeletedInTextField(Element*)
481 {
482     notImplemented();
483 }
484 
textDidChangeInTextArea(Element *)485 void EditorClientWx::textDidChangeInTextArea(Element*)
486 {
487     notImplemented();
488 }
489 
respondToChangedSelection()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 
ignoreWordInSpellDocument(const String &)502 void EditorClientWx::ignoreWordInSpellDocument(const String&)
503 {
504     notImplemented();
505 }
506 
learnWord(const String &)507 void EditorClientWx::learnWord(const String&)
508 {
509     notImplemented();
510 }
511 
checkSpellingOfString(const UChar *,int length,int * misspellingLocation,int * misspellingLength)512 void EditorClientWx::checkSpellingOfString(const UChar*, int length, int* misspellingLocation, int* misspellingLength)
513 {
514     notImplemented();
515 }
516 
checkGrammarOfString(const UChar *,int length,Vector<GrammarDetail> &,int * badGrammarLocation,int * badGrammarLength)517 void EditorClientWx::checkGrammarOfString(const UChar*, int length, Vector<GrammarDetail>&, int* badGrammarLocation, int* badGrammarLength)
518 {
519     notImplemented();
520 }
521 
updateSpellingUIWithGrammarString(const String &,const GrammarDetail & detail)522 void EditorClientWx::updateSpellingUIWithGrammarString(const String&, const GrammarDetail& detail)
523 {
524     notImplemented();
525 }
526 
updateSpellingUIWithMisspelledWord(const String &)527 void EditorClientWx::updateSpellingUIWithMisspelledWord(const String&)
528 {
529     notImplemented();
530 }
531 
showSpellingUI(bool show)532 void EditorClientWx::showSpellingUI(bool show)
533 {
534     notImplemented();
535 }
536 
spellingUIIsShowing()537 bool EditorClientWx::spellingUIIsShowing()
538 {
539     notImplemented();
540     return false;
541 }
542 
getGuessesForWord(const String & word,const String & context,Vector<String> & guesses)543 void EditorClientWx::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
544 {
545     notImplemented();
546 }
547 
getAutoCorrectSuggestionForMisspelledWord(const WTF::String &)548 String EditorClientWx::getAutoCorrectSuggestionForMisspelledWord(const WTF::String&)
549 {
550     notImplemented();
551     return String();
552 }
553 
willSetInputMethodState()554 void EditorClientWx::willSetInputMethodState()
555 {
556     notImplemented();
557 }
558 
setInputMethodState(bool enabled)559 void EditorClientWx::setInputMethodState(bool enabled)
560 {
561     notImplemented();
562 }
563 
564 }
565