1 /* 2 * Copyright (C) 2007 Alp Toker <alp (at) 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 43 void EditorClientEfl::willSetInputMethodState() 44 { 45 notImplemented(); 46 } 47 48 void EditorClientEfl::setInputMethodState(bool active) 49 { 50 ewk_view_input_method_state_set(m_view, active); 51 } 52 53 bool EditorClientEfl::shouldDeleteRange(Range*) 54 { 55 notImplemented(); 56 return true; 57 } 58 59 bool EditorClientEfl::shouldShowDeleteInterface(HTMLElement*) 60 { 61 return false; 62 } 63 64 bool EditorClientEfl::isContinuousSpellCheckingEnabled() 65 { 66 notImplemented(); 67 return false; 68 } 69 70 bool EditorClientEfl::isGrammarCheckingEnabled() 71 { 72 notImplemented(); 73 return false; 74 } 75 76 int EditorClientEfl::spellCheckerDocumentTag() 77 { 78 notImplemented(); 79 return 0; 80 } 81 82 bool EditorClientEfl::shouldBeginEditing(Range*) 83 { 84 notImplemented(); 85 return true; 86 } 87 88 bool EditorClientEfl::shouldEndEditing(Range*) 89 { 90 notImplemented(); 91 return true; 92 } 93 94 bool EditorClientEfl::shouldInsertText(const String&, Range*, EditorInsertAction) 95 { 96 notImplemented(); 97 return true; 98 } 99 100 bool EditorClientEfl::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool) 101 { 102 notImplemented(); 103 return true; 104 } 105 106 bool EditorClientEfl::shouldApplyStyle(CSSStyleDeclaration*, Range*) 107 { 108 notImplemented(); 109 return true; 110 } 111 112 bool EditorClientEfl::shouldMoveRangeAfterDelete(Range*, Range*) 113 { 114 notImplemented(); 115 return true; 116 } 117 118 void EditorClientEfl::didBeginEditing() 119 { 120 notImplemented(); 121 } 122 123 void EditorClientEfl::respondToChangedContents() 124 { 125 notImplemented(); 126 } 127 128 void EditorClientEfl::respondToChangedSelection() 129 { 130 notImplemented(); 131 } 132 133 void EditorClientEfl::didEndEditing() 134 { 135 notImplemented(); 136 } 137 138 void EditorClientEfl::didWriteSelectionToPasteboard() 139 { 140 notImplemented(); 141 } 142 143 void EditorClientEfl::didSetSelectionTypesForPasteboard() 144 { 145 notImplemented(); 146 } 147 148 void EditorClientEfl::registerCommandForUndo(WTF::PassRefPtr<EditCommand>) 149 { 150 notImplemented(); 151 } 152 153 void EditorClientEfl::registerCommandForRedo(WTF::PassRefPtr<EditCommand>) 154 { 155 notImplemented(); 156 } 157 158 void EditorClientEfl::clearUndoRedoOperations() 159 { 160 notImplemented(); 161 } 162 163 bool EditorClientEfl::canCopyCut(bool defaultValue) const 164 { 165 return defaultValue; 166 } 167 168 bool EditorClientEfl::canPaste(bool defaultValue) const 169 { 170 return defaultValue; 171 } 172 173 bool EditorClientEfl::canUndo() const 174 { 175 notImplemented(); 176 return false; 177 } 178 179 bool EditorClientEfl::canRedo() const 180 { 181 notImplemented(); 182 return false; 183 } 184 185 void EditorClientEfl::undo() 186 { 187 notImplemented(); 188 } 189 190 void EditorClientEfl::redo() 191 { 192 notImplemented(); 193 } 194 195 bool EditorClientEfl::shouldInsertNode(Node*, Range*, EditorInsertAction) 196 { 197 notImplemented(); 198 return true; 199 } 200 201 void EditorClientEfl::pageDestroyed() 202 { 203 delete this; 204 } 205 206 bool EditorClientEfl::smartInsertDeleteEnabled() 207 { 208 notImplemented(); 209 return false; 210 } 211 212 bool EditorClientEfl::isSelectTrailingWhitespaceEnabled() 213 { 214 notImplemented(); 215 return false; 216 } 217 218 void EditorClientEfl::toggleContinuousSpellChecking() 219 { 220 notImplemented(); 221 } 222 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 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 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 398 void EditorClientEfl::handleKeyboardEvent(KeyboardEvent* event) 399 { 400 if (handleEditingKeyboardEvent(event)) 401 event->setDefaultHandled(); 402 } 403 404 void EditorClientEfl::handleInputMethodKeydown(KeyboardEvent* event) 405 { 406 } 407 408 EditorClientEfl::EditorClientEfl(Evas_Object *view) 409 : m_view(view) 410 { 411 notImplemented(); 412 } 413 414 EditorClientEfl::~EditorClientEfl() 415 { 416 notImplemented(); 417 } 418 419 void EditorClientEfl::textFieldDidBeginEditing(Element*) 420 { 421 } 422 423 void EditorClientEfl::textFieldDidEndEditing(Element*) 424 { 425 notImplemented(); 426 } 427 428 void EditorClientEfl::textDidChangeInTextField(Element*) 429 { 430 notImplemented(); 431 } 432 433 bool EditorClientEfl::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) 434 { 435 return false; 436 } 437 438 void EditorClientEfl::textWillBeDeletedInTextField(Element*) 439 { 440 notImplemented(); 441 } 442 443 void EditorClientEfl::textDidChangeInTextArea(Element*) 444 { 445 notImplemented(); 446 } 447 448 void EditorClientEfl::ignoreWordInSpellDocument(const String&) 449 { 450 notImplemented(); 451 } 452 453 void EditorClientEfl::learnWord(const String&) 454 { 455 notImplemented(); 456 } 457 458 void EditorClientEfl::checkSpellingOfString(const UChar*, int, int*, int*) 459 { 460 notImplemented(); 461 } 462 463 String EditorClientEfl::getAutoCorrectSuggestionForMisspelledWord(const String&) 464 { 465 notImplemented(); 466 return String(); 467 } 468 469 void EditorClientEfl::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*) 470 { 471 notImplemented(); 472 } 473 474 void EditorClientEfl::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) 475 { 476 notImplemented(); 477 } 478 479 void EditorClientEfl::updateSpellingUIWithMisspelledWord(const String&) 480 { 481 notImplemented(); 482 } 483 484 void EditorClientEfl::showSpellingUI(bool) 485 { 486 notImplemented(); 487 } 488 489 bool EditorClientEfl::spellingUIIsShowing() 490 { 491 notImplemented(); 492 return false; 493 } 494 495 void EditorClientEfl::getGuessesForWord(const String& word, const String& context, Vector<String>& guesses) 496 { 497 notImplemented(); 498 } 499 500 } 501