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 * Copyright (C) 2010 Patrick Gansterer <paroga@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 34using namespace WebCore; 35 36namespace WebKit { 37 38EditorClientWinCE::EditorClientWinCE(WebView* webView) 39 : m_webView(webView) 40{ 41} 42 43EditorClientWinCE::~EditorClientWinCE() 44{ 45} 46 47void EditorClientWinCE::setInputMethodState(bool active) 48{ 49 notImplemented(); 50} 51 52bool EditorClientWinCE::shouldDeleteRange(Range*) 53{ 54 notImplemented(); 55 return true; 56} 57 58bool EditorClientWinCE::shouldShowDeleteInterface(HTMLElement*) 59{ 60 return false; 61} 62 63bool EditorClientWinCE::isContinuousSpellCheckingEnabled() 64{ 65 notImplemented(); 66 return false; 67} 68 69bool EditorClientWinCE::isGrammarCheckingEnabled() 70{ 71 notImplemented(); 72 return false; 73} 74 75int EditorClientWinCE::spellCheckerDocumentTag() 76{ 77 notImplemented(); 78 return 0; 79} 80 81bool EditorClientWinCE::shouldBeginEditing(WebCore::Range*) 82{ 83 notImplemented(); 84 return true; 85} 86 87bool EditorClientWinCE::shouldEndEditing(WebCore::Range*) 88{ 89 notImplemented(); 90 return true; 91} 92 93bool EditorClientWinCE::shouldInsertText(const String&, Range*, EditorInsertAction) 94{ 95 notImplemented(); 96 return true; 97} 98 99bool EditorClientWinCE::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool) 100{ 101 notImplemented(); 102 return true; 103} 104 105bool EditorClientWinCE::shouldApplyStyle(WebCore::CSSStyleDeclaration*, WebCore::Range*) 106{ 107 notImplemented(); 108 return true; 109} 110 111bool EditorClientWinCE::shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*) 112{ 113 notImplemented(); 114 return true; 115} 116 117void EditorClientWinCE::didBeginEditing() 118{ 119 notImplemented(); 120} 121 122void EditorClientWinCE::respondToChangedContents() 123{ 124 notImplemented(); 125} 126 127void EditorClientWinCE::respondToChangedSelection() 128{ 129 notImplemented(); 130} 131 132void EditorClientWinCE::didEndEditing() 133{ 134 notImplemented(); 135} 136 137void EditorClientWinCE::didWriteSelectionToPasteboard() 138{ 139 notImplemented(); 140} 141 142void EditorClientWinCE::didSetSelectionTypesForPasteboard() 143{ 144 notImplemented(); 145} 146 147void EditorClientWinCE::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand> command) 148{ 149 notImplemented(); 150} 151 152void EditorClientWinCE::registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand> command) 153{ 154 notImplemented(); 155} 156 157void EditorClientWinCE::clearUndoRedoOperations() 158{ 159 notImplemented(); 160} 161 162bool EditorClientWinCE::canCopyCut(bool defaultValue) const 163{ 164 return defaultValue; 165} 166 167bool EditorClientWinCE::canPaste(bool defaultValue) const 168{ 169 return defaultValue; 170} 171 172bool EditorClientWinCE::canUndo() const 173{ 174 notImplemented(); 175 return false; 176} 177 178bool EditorClientWinCE::canRedo() const 179{ 180 notImplemented(); 181 return false; 182} 183 184void EditorClientWinCE::undo() 185{ 186 notImplemented(); 187} 188 189void EditorClientWinCE::redo() 190{ 191 notImplemented(); 192} 193 194bool EditorClientWinCE::shouldInsertNode(Node*, Range*, EditorInsertAction) 195{ 196 notImplemented(); 197 return true; 198} 199 200void EditorClientWinCE::pageDestroyed() 201{ 202 delete this; 203} 204 205bool EditorClientWinCE::smartInsertDeleteEnabled() 206{ 207 notImplemented(); 208 return false; 209} 210 211bool EditorClientWinCE::isSelectTrailingWhitespaceEnabled() 212{ 213 notImplemented(); 214 return false; 215} 216 217void EditorClientWinCE::toggleContinuousSpellChecking() 218{ 219 notImplemented(); 220} 221 222void EditorClientWinCE::toggleGrammarChecking() 223{ 224 notImplemented(); 225} 226 227static const unsigned CtrlKey = 1 << 0; 228static const unsigned AltKey = 1 << 1; 229static const unsigned ShiftKey = 1 << 2; 230 231struct KeyDownEntry { 232 unsigned virtualKey; 233 unsigned modifiers; 234 const char* name; 235}; 236 237struct KeyPressEntry { 238 unsigned charCode; 239 unsigned modifiers; 240 const char* name; 241}; 242 243static 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 300static 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 309const 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 344bool 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 408void EditorClientWinCE::handleKeyboardEvent(KeyboardEvent* event) 409{ 410 if (handleEditingKeyboardEvent(event)) 411 event->setDefaultHandled(); 412} 413 414void EditorClientWinCE::handleInputMethodKeydown(KeyboardEvent* event) 415{ 416 notImplemented(); 417} 418 419void EditorClientWinCE::textFieldDidBeginEditing(Element*) 420{ 421} 422 423void EditorClientWinCE::textFieldDidEndEditing(Element*) 424{ 425} 426 427void EditorClientWinCE::textDidChangeInTextField(Element*) 428{ 429} 430 431bool EditorClientWinCE::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) 432{ 433 return false; 434} 435 436void EditorClientWinCE::textWillBeDeletedInTextField(Element*) 437{ 438 notImplemented(); 439} 440 441void EditorClientWinCE::textDidChangeInTextArea(Element*) 442{ 443 notImplemented(); 444} 445 446void EditorClientWinCE::ignoreWordInSpellDocument(const String& text) 447{ 448 notImplemented(); 449} 450 451void EditorClientWinCE::learnWord(const String& text) 452{ 453 notImplemented(); 454} 455 456void EditorClientWinCE::checkSpellingOfString(const UChar* text, int length, int* misspellingLocation, int* misspellingLength) 457{ 458 notImplemented(); 459} 460 461String 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 468void EditorClientWinCE::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*) 469{ 470 notImplemented(); 471} 472 473void EditorClientWinCE::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&) 474{ 475 notImplemented(); 476} 477 478void EditorClientWinCE::updateSpellingUIWithMisspelledWord(const String&) 479{ 480 notImplemented(); 481} 482 483void EditorClientWinCE::showSpellingUI(bool) 484{ 485 notImplemented(); 486} 487 488bool EditorClientWinCE::spellingUIIsShowing() 489{ 490 notImplemented(); 491 return false; 492} 493 494void EditorClientWinCE::getGuessesForWord(const String& word, const String& context, WTF::Vector<String>& guesses) 495{ 496 notImplemented(); 497} 498 499void EditorClientWinCE::willSetInputMethodState() 500{ 501 notImplemented(); 502} 503 504} // namespace WebKit 505