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