1 /*
2 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
3 * Copyright (C) 2008 Nuanti Ltd.
4 * Copyright (C) 2008 INdT - Instituto Nokia de Tecnologia
5 * Copyright (C) 2009-2010 ProFUSION embedded systems
6 * Copyright (C) 2009-2010 Samsung Electronics
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include "config.h"
24 #include "EditorClientEfl.h"
25
26 #include "EWebKit.h"
27 #include "EditCommand.h"
28 #include "Editor.h"
29 #include "EventNames.h"
30 #include "FocusController.h"
31 #include "Frame.h"
32 #include "KeyboardEvent.h"
33 #include "NotImplemented.h"
34 #include "Page.h"
35 #include "PlatformKeyboardEvent.h"
36 #include "WindowsKeyboardCodes.h"
37 #include "ewk_private.h"
38
39 using namespace WebCore;
40
41 namespace WebCore {
42
willSetInputMethodState()43 void EditorClientEfl::willSetInputMethodState()
44 {
45 notImplemented();
46 }
47
setInputMethodState(bool active)48 void EditorClientEfl::setInputMethodState(bool active)
49 {
50 ewk_view_input_method_state_set(m_view, active);
51 }
52
shouldDeleteRange(Range *)53 bool EditorClientEfl::shouldDeleteRange(Range*)
54 {
55 notImplemented();
56 return true;
57 }
58
shouldShowDeleteInterface(HTMLElement *)59 bool EditorClientEfl::shouldShowDeleteInterface(HTMLElement*)
60 {
61 return false;
62 }
63
isContinuousSpellCheckingEnabled()64 bool EditorClientEfl::isContinuousSpellCheckingEnabled()
65 {
66 notImplemented();
67 return false;
68 }
69
isGrammarCheckingEnabled()70 bool EditorClientEfl::isGrammarCheckingEnabled()
71 {
72 notImplemented();
73 return false;
74 }
75
spellCheckerDocumentTag()76 int EditorClientEfl::spellCheckerDocumentTag()
77 {
78 notImplemented();
79 return 0;
80 }
81
shouldBeginEditing(Range *)82 bool EditorClientEfl::shouldBeginEditing(Range*)
83 {
84 notImplemented();
85 return true;
86 }
87
shouldEndEditing(Range *)88 bool EditorClientEfl::shouldEndEditing(Range*)
89 {
90 notImplemented();
91 return true;
92 }
93
shouldInsertText(const String &,Range *,EditorInsertAction)94 bool EditorClientEfl::shouldInsertText(const String&, Range*, EditorInsertAction)
95 {
96 notImplemented();
97 return true;
98 }
99
shouldChangeSelectedRange(Range *,Range *,EAffinity,bool)100 bool EditorClientEfl::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool)
101 {
102 notImplemented();
103 return true;
104 }
105
shouldApplyStyle(CSSStyleDeclaration *,Range *)106 bool EditorClientEfl::shouldApplyStyle(CSSStyleDeclaration*, Range*)
107 {
108 notImplemented();
109 return true;
110 }
111
shouldMoveRangeAfterDelete(Range *,Range *)112 bool EditorClientEfl::shouldMoveRangeAfterDelete(Range*, Range*)
113 {
114 notImplemented();
115 return true;
116 }
117
didBeginEditing()118 void EditorClientEfl::didBeginEditing()
119 {
120 notImplemented();
121 }
122
respondToChangedContents()123 void EditorClientEfl::respondToChangedContents()
124 {
125 notImplemented();
126 }
127
respondToChangedSelection()128 void EditorClientEfl::respondToChangedSelection()
129 {
130 notImplemented();
131 }
132
didEndEditing()133 void EditorClientEfl::didEndEditing()
134 {
135 notImplemented();
136 }
137
didWriteSelectionToPasteboard()138 void EditorClientEfl::didWriteSelectionToPasteboard()
139 {
140 notImplemented();
141 }
142
didSetSelectionTypesForPasteboard()143 void EditorClientEfl::didSetSelectionTypesForPasteboard()
144 {
145 notImplemented();
146 }
147
registerCommandForUndo(WTF::PassRefPtr<EditCommand>)148 void EditorClientEfl::registerCommandForUndo(WTF::PassRefPtr<EditCommand>)
149 {
150 notImplemented();
151 }
152
registerCommandForRedo(WTF::PassRefPtr<EditCommand>)153 void EditorClientEfl::registerCommandForRedo(WTF::PassRefPtr<EditCommand>)
154 {
155 notImplemented();
156 }
157
clearUndoRedoOperations()158 void EditorClientEfl::clearUndoRedoOperations()
159 {
160 notImplemented();
161 }
162
canCopyCut(bool defaultValue) const163 bool EditorClientEfl::canCopyCut(bool defaultValue) const
164 {
165 return defaultValue;
166 }
167
canPaste(bool defaultValue) const168 bool EditorClientEfl::canPaste(bool defaultValue) const
169 {
170 return defaultValue;
171 }
172
canUndo() const173 bool EditorClientEfl::canUndo() const
174 {
175 notImplemented();
176 return false;
177 }
178
canRedo() const179 bool EditorClientEfl::canRedo() const
180 {
181 notImplemented();
182 return false;
183 }
184
undo()185 void EditorClientEfl::undo()
186 {
187 notImplemented();
188 }
189
redo()190 void EditorClientEfl::redo()
191 {
192 notImplemented();
193 }
194
shouldInsertNode(Node *,Range *,EditorInsertAction)195 bool EditorClientEfl::shouldInsertNode(Node*, Range*, EditorInsertAction)
196 {
197 notImplemented();
198 return true;
199 }
200
pageDestroyed()201 void EditorClientEfl::pageDestroyed()
202 {
203 delete this;
204 }
205
smartInsertDeleteEnabled()206 bool EditorClientEfl::smartInsertDeleteEnabled()
207 {
208 notImplemented();
209 return false;
210 }
211
isSelectTrailingWhitespaceEnabled()212 bool EditorClientEfl::isSelectTrailingWhitespaceEnabled()
213 {
214 notImplemented();
215 return false;
216 }
217
toggleContinuousSpellChecking()218 void EditorClientEfl::toggleContinuousSpellChecking()
219 {
220 notImplemented();
221 }
222
toggleGrammarChecking()223 void EditorClientEfl::toggleGrammarChecking()
224 {
225 notImplemented();
226 }
227
228 static const unsigned CtrlKey = 1 << 0;
229 static const unsigned AltKey = 1 << 1;
230 static const unsigned ShiftKey = 1 << 2;
231
232 struct KeyDownEntry {
233 unsigned virtualKey;
234 unsigned modifiers;
235 const char* name;
236 };
237
238 struct KeyPressEntry {
239 unsigned charCode;
240 unsigned modifiers;
241 const char* name;
242 };
243
244 static const KeyDownEntry keyDownEntries[] = {
245 { VK_LEFT, 0, "MoveLeft" },
246 { VK_LEFT, ShiftKey, "MoveLeftAndModifySelection" },
247 { VK_LEFT, CtrlKey, "MoveWordLeft" },
248 { VK_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection" },
249 { VK_RIGHT, 0, "MoveRight" },
250 { VK_RIGHT, ShiftKey, "MoveRightAndModifySelection" },
251 { VK_RIGHT, CtrlKey, "MoveWordRight" },
252 { VK_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection" },
253 { VK_UP, 0, "MoveUp" },
254 { VK_UP, ShiftKey, "MoveUpAndModifySelection" },
255 { VK_PRIOR, ShiftKey, "MovePageUpAndModifySelection" },
256 { VK_DOWN, 0, "MoveDown" },
257 { VK_DOWN, ShiftKey, "MoveDownAndModifySelection" },
258 { VK_NEXT, ShiftKey, "MovePageDownAndModifySelection" },
259 { VK_PRIOR, 0, "MovePageUp" },
260 { VK_NEXT, 0, "MovePageDown" },
261 { VK_HOME, 0, "MoveToBeginningOfLine" },
262 { VK_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection" },
263 { VK_HOME, CtrlKey, "MoveToBeginningOfDocument" },
264 { VK_HOME, CtrlKey | ShiftKey, "MoveToBeginningOfDocumentAndModifySelection" },
265
266 { VK_END, 0, "MoveToEndOfLine" },
267 { VK_END, ShiftKey, "MoveToEndOfLineAndModifySelection" },
268 { VK_END, CtrlKey, "MoveToEndOfDocument" },
269 { VK_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection" },
270
271 { VK_BACK, 0, "DeleteBackward" },
272 { VK_BACK, ShiftKey, "DeleteBackward" },
273 { VK_DELETE, 0, "DeleteForward" },
274 { VK_BACK, CtrlKey, "DeleteWordBackward" },
275 { VK_DELETE, CtrlKey, "DeleteWordForward" },
276
277 { 'B', CtrlKey, "ToggleBold" },
278 { 'I', CtrlKey, "ToggleItalic" },
279
280 { VK_ESCAPE, 0, "Cancel" },
281 { VK_OEM_PERIOD, CtrlKey, "Cancel" },
282 { VK_TAB, 0, "InsertTab" },
283 { VK_TAB, ShiftKey, "InsertBacktab" },
284 { VK_RETURN, 0, "InsertNewline" },
285 { VK_RETURN, CtrlKey, "InsertNewline" },
286 { VK_RETURN, AltKey, "InsertNewline" },
287 { VK_RETURN, AltKey | ShiftKey, "InsertNewline" },
288 };
289
290 static const KeyPressEntry keyPressEntries[] = {
291 { '\t', 0, "InsertTab" },
292 { '\t', ShiftKey, "InsertBacktab" },
293 { '\r', 0, "InsertNewline" },
294 { '\r', CtrlKey, "InsertNewline" },
295 { '\r', AltKey, "InsertNewline" },
296 { '\r', AltKey | ShiftKey, "InsertNewline" },
297 };
298
interpretKeyEvent(const KeyboardEvent * event)299 const char* EditorClientEfl::interpretKeyEvent(const KeyboardEvent* event)
300 {
301 ASSERT(event->type() == eventNames().keydownEvent || event->type() == eventNames().keypressEvent);
302
303 static HashMap<int, const char*>* keyDownCommandsMap = 0;
304 static HashMap<int, const char*>* keyPressCommandsMap = 0;
305
306 if (!keyDownCommandsMap) {
307 keyDownCommandsMap = new HashMap<int, const char*>;
308 keyPressCommandsMap = new HashMap<int, const char*>;
309
310 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyDownEntries); ++i)
311 keyDownCommandsMap->set(keyDownEntries[i].modifiers << 16 | keyDownEntries[i].virtualKey, keyDownEntries[i].name);
312
313 for (size_t i = 0; i < WTF_ARRAY_LENGTH(keyPressEntries); ++i)
314 keyPressCommandsMap->set(keyPressEntries[i].modifiers << 16 | keyPressEntries[i].charCode, keyPressEntries[i].name);
315 }
316
317 unsigned modifiers = 0;
318 if (event->shiftKey())
319 modifiers |= ShiftKey;
320 if (event->altKey())
321 modifiers |= AltKey;
322 if (event->ctrlKey())
323 modifiers |= CtrlKey;
324
325 if (event->type() == eventNames().keydownEvent) {
326 int mapKey = modifiers << 16 | event->keyCode();
327 return mapKey ? keyDownCommandsMap->get(mapKey) : 0;
328 }
329
330 int mapKey = modifiers << 16 | event->charCode();
331 return mapKey ? keyPressCommandsMap->get(mapKey) : 0;
332 }
333
handleEditingKeyboardEvent(KeyboardEvent * event)334 bool EditorClientEfl::handleEditingKeyboardEvent(KeyboardEvent* event)
335 {
336 Node* node = event->target()->toNode();
337 ASSERT(node);
338 Frame* frame = node->document()->frame();
339 ASSERT(frame);
340
341 const PlatformKeyboardEvent* keyEvent = event->keyEvent();
342 if (!keyEvent)
343 return false;
344
345 bool caretBrowsing = frame->settings()->caretBrowsingEnabled();
346 if (caretBrowsing) {
347 switch (keyEvent->windowsVirtualKeyCode()) {
348 case VK_LEFT:
349 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
350 DirectionLeft,
351 keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity,
352 true);
353 return true;
354 case VK_RIGHT:
355 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
356 DirectionRight,
357 keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity,
358 true);
359 return true;
360 case VK_UP:
361 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
362 DirectionBackward,
363 keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity,
364 true);
365 return true;
366 case VK_DOWN:
367 frame->selection()->modify(keyEvent->shiftKey() ? SelectionController::AlterationExtend : SelectionController::AlterationMove,
368 DirectionForward,
369 keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity,
370 true);
371 return true;
372 }
373 }
374
375 Editor::Command command = frame->editor()->command(interpretKeyEvent(event));
376
377 if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) {
378 // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated,
379 // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated
380 // (e.g. Tab that inserts a Tab character, or Enter).
381 return !command.isTextInsertion() && command.execute(event);
382 }
383
384 if (command.execute(event))
385 return true;
386
387 // Don't insert null or control characters as they can result in unexpected behaviour
388 if (event->charCode() < ' ')
389 return false;
390
391 // Don't insert anything if a modifier is pressed
392 if (keyEvent->ctrlKey() || keyEvent->altKey())
393 return false;
394
395 return frame->editor()->insertText(event->keyEvent()->text(), event);
396 }
397
handleKeyboardEvent(KeyboardEvent * event)398 void EditorClientEfl::handleKeyboardEvent(KeyboardEvent* event)
399 {
400 if (handleEditingKeyboardEvent(event))
401 event->setDefaultHandled();
402 }
403
handleInputMethodKeydown(KeyboardEvent * event)404 void EditorClientEfl::handleInputMethodKeydown(KeyboardEvent* event)
405 {
406 }
407
EditorClientEfl(Evas_Object * view)408 EditorClientEfl::EditorClientEfl(Evas_Object *view)
409 : m_view(view)
410 {
411 notImplemented();
412 }
413
~EditorClientEfl()414 EditorClientEfl::~EditorClientEfl()
415 {
416 notImplemented();
417 }
418
textFieldDidBeginEditing(Element *)419 void EditorClientEfl::textFieldDidBeginEditing(Element*)
420 {
421 }
422
textFieldDidEndEditing(Element *)423 void EditorClientEfl::textFieldDidEndEditing(Element*)
424 {
425 notImplemented();
426 }
427
textDidChangeInTextField(Element *)428 void EditorClientEfl::textDidChangeInTextField(Element*)
429 {
430 notImplemented();
431 }
432
doTextFieldCommandFromEvent(Element *,KeyboardEvent *)433 bool EditorClientEfl::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
434 {
435 return false;
436 }
437
textWillBeDeletedInTextField(Element *)438 void EditorClientEfl::textWillBeDeletedInTextField(Element*)
439 {
440 notImplemented();
441 }
442
textDidChangeInTextArea(Element *)443 void EditorClientEfl::textDidChangeInTextArea(Element*)
444 {
445 notImplemented();
446 }
447
ignoreWordInSpellDocument(const String &)448 void EditorClientEfl::ignoreWordInSpellDocument(const String&)
449 {
450 notImplemented();
451 }
452
learnWord(const String &)453 void EditorClientEfl::learnWord(const String&)
454 {
455 notImplemented();
456 }
457
checkSpellingOfString(const UChar *,int,int *,int *)458 void EditorClientEfl::checkSpellingOfString(const UChar*, int, int*, int*)
459 {
460 notImplemented();
461 }
462
getAutoCorrectSuggestionForMisspelledWord(const String &)463 String EditorClientEfl::getAutoCorrectSuggestionForMisspelledWord(const String&)
464 {
465 notImplemented();
466 return String();
467 }
468
checkGrammarOfString(const UChar *,int,Vector<GrammarDetail> &,int *,int *)469 void EditorClientEfl::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
470 {
471 notImplemented();
472 }
473
updateSpellingUIWithGrammarString(const String &,const GrammarDetail &)474 void EditorClientEfl::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
475 {
476 notImplemented();
477 }
478
updateSpellingUIWithMisspelledWord(const String &)479 void EditorClientEfl::updateSpellingUIWithMisspelledWord(const String&)
480 {
481 notImplemented();
482 }
483
showSpellingUI(bool)484 void EditorClientEfl::showSpellingUI(bool)
485 {
486 notImplemented();
487 }
488
spellingUIIsShowing()489 bool EditorClientEfl::spellingUIIsShowing()
490 {
491 notImplemented();
492 return false;
493 }
494
getGuessesForWord(const String & word,const String & context,Vector<String> & guesses)495 void EditorClientEfl::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses)
496 {
497 notImplemented();
498 }
499
500 }
501