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