bool WebPage::handleEditingKeyboardEvent(KeyboardEvent* evt) { Node* node = evt->target()->toNode(); ASSERT(node); Frame* frame = node->document()->frame(); ASSERT(frame); const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); if (!keyEvent) return false; Editor::Command command = frame->editor()->command(interpretKeyEvent(evt)); if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) { // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated, // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated // (e.g. Tab that inserts a Tab character, or Enter). return !command.isTextInsertion() && command.execute(evt); } if (command.execute(evt)) return true; // Don't insert null or control characters as they can result in unexpected behaviour if (evt->charCode() < ' ') return false; return frame->editor()->insertText(evt->keyEvent()->text(), evt); }
bool EditorClient::executePendingEditorCommands(Frame* frame, bool allowTextInsertion) { Vector<Editor::Command> commands; for (size_t i = 0; i < m_pendingEditorCommands.size(); i++) { Editor::Command command = frame->editor()->command(m_pendingEditorCommands.at(i).utf8().data()); if (command.isTextInsertion() && !allowTextInsertion) return false; commands.append(command); } bool success = true; for (size_t i = 0; i < commands.size(); i++) { if (!commands.at(i).execute()) { success = false; break; } } m_pendingEditorCommands.clear(); // If we successfully completed all editor commands, then // this signals a canceling of the composition. if (success) clearPendingComposition(); return success; }
bool EditorClientWx::handleEditingKeyboardEvent(KeyboardEvent* event) { Node* node = event->target()->toNode(); ASSERT(node); Frame* frame = node->document()->frame(); ASSERT(frame); const PlatformKeyboardEvent* keyEvent = event->keyEvent(); //NB: this is what windows does, but they also have a keypress event for Alt+Enter which clearly won't get hit with this if (!keyEvent || keyEvent->altKey()) // do not treat this as text input if Alt is down return false; Editor::Command command = frame->editor()->command(interpretKeyEvent(event)); if (keyEvent->type() == PlatformEvent::RawKeyDown) { // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated, // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or if not to let a CHAR event be generated // (e.g. Tab that inserts a Tab character, or Enter). return !command.isTextInsertion() && command.execute(event); } if (command.execute(event)) return true; // Don't insert null or control characters as they can result in unexpected behaviour if (event->charCode() < ' ') return false; return frame->editor()->insertText(event->keyEvent()->text(), event); }
static void handleKeyDown(Frame& frame, KeyboardEvent& event, const PlatformKeyboardEvent&) { String commandName = interpretKeyEvent(event); if (commandName.isEmpty()) return; // We shouldn't insert text through the editor. Let WebCore decide // how to handle that (say, Tab, which could also be used to // change focus). Editor::Command command = frame.editor().command(commandName); if (command.isTextInsertion()) return; command.execute(); event.setDefaultHandled(); }
bool WebEditorClient::executePendingEditorCommands(Frame* frame, Vector<WTF::String> pendingEditorCommands, bool allowTextInsertion) { Vector<Editor::Command> commands; for (size_t i = 0; i < pendingEditorCommands.size(); i++) { Editor::Command command = frame->editor()->command(pendingEditorCommands.at(i).utf8().data()); if (command.isTextInsertion() && !allowTextInsertion) return false; commands.append(command); } for (size_t i = 0; i < commands.size(); i++) { if (!commands.at(i).execute()) return false; } return true; }
bool WebEditorClient::executePendingEditorCommands(Frame* frame, const Vector<WTF::String>& pendingEditorCommands, bool allowTextInsertion) { Vector<Editor::Command> commands; for (auto& commandString : pendingEditorCommands) { Editor::Command command = frame->editor().command(commandString.utf8().data()); if (command.isTextInsertion() && !allowTextInsertion) return false; commands.append(WTF::move(command)); } for (auto& command : commands) { if (!command.execute()) return false; } return true; }
bool EditorClient::executePendingEditorCommands(Frame* frame, bool allowTextInsertion) { Vector<Editor::Command> commands; for (size_t i = 0; i < m_pendingEditorCommands.size(); i++) { Editor::Command command = frame->editor().command(m_pendingEditorCommands.at(i).utf8().data()); if (command.isTextInsertion() && !allowTextInsertion) return false; commands.append(command); } bool success = true; for (size_t i = 0; i < commands.size(); i++) { if (!commands.at(i).execute()) { success = false; break; } } m_pendingEditorCommands.clear(); return success; }
void EditorClientAndroid::handleKeyboardEvent(KeyboardEvent* event) { ASSERT(m_page); Frame* frame = m_page->focusController()->focusedOrMainFrame(); if (!frame) return; const PlatformKeyboardEvent* keyEvent = event->keyEvent(); // TODO: If the event is not coming from Android Java, e.g. from JavaScript, // PlatformKeyboardEvent is null. We should support this later. if (!keyEvent) return; Editor::Command command = frame->editor()->command(interpretKeyEvent(event)); if (keyEvent->type() == PlatformKeyboardEvent::RawKeyDown) { if (!command.isTextInsertion() && command.execute(event)) { // This function mimics the Windows version. However, calling event->setDefaultHandled() // prevents the javascript key events for the delete key from happening. // Update: Safari doesn't send delete key events to javascript so // we will mimic that behavior. event->setDefaultHandled(); } return; } if (command.execute(event)) { event->setDefaultHandled(); return; } // Don't insert null or control characters as they can result in unexpected behaviour if (event->charCode() < ' ') return; if (frame->editor()->insertText(keyEvent->text(), event)) event->setDefaultHandled(); }
bool EditorClientWinCE::handleEditingKeyboardEvent(KeyboardEvent* event) { Node* node = event->target()->toNode(); ASSERT(node); Frame* frame = node->document()->frame(); ASSERT(frame); const PlatformKeyboardEvent* keyEvent = event->keyEvent(); if (!keyEvent) return false; bool caretBrowsing = frame->settings()->caretBrowsingEnabled(); if (caretBrowsing) { switch (keyEvent->windowsVirtualKeyCode()) { case VK_LEFT: frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove, DirectionLeft, keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity, UserTriggered); return true; case VK_RIGHT: frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove, DirectionRight, keyEvent->ctrlKey() ? WordGranularity : CharacterGranularity, UserTriggered); return true; case VK_UP: frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove, DirectionBackward, keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity, UserTriggered); return true; case VK_DOWN: frame->selection()->modify(keyEvent->shiftKey() ? FrameSelection::AlterationExtend : FrameSelection::AlterationMove, DirectionForward, keyEvent->ctrlKey() ? ParagraphGranularity : LineGranularity, UserTriggered); return true; } } Editor::Command command = frame->editor()->command(interpretKeyEvent(event)); if (keyEvent->type() == PlatformEvent::RawKeyDown) { // WebKit doesn't have enough information about mode to decide how commands that just insert text if executed via Editor should be treated, // so we leave it upon WebCore to either handle them immediately (e.g. Tab that changes focus) or let a keypress event be generated // (e.g. Tab that inserts a Tab character, or Enter). return !command.isTextInsertion() && command.execute(event); } if (command.execute(event)) return true; // Don't insert null or control characters as they can result in unexpected behaviour if (event->charCode() < ' ') return false; // Don't insert anything if a modifier is pressed if (keyEvent->ctrlKey() || keyEvent->altKey()) return false; return frame->editor()->insertText(event->keyEvent()->text(), event); }
void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const { if (item.type() == SeparatorType) return; Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame(); if (!frame) return; bool shouldEnable = true; bool shouldCheck = false; switch (item.action()) { case ContextMenuItemTagCheckSpelling: shouldEnable = frame->editor()->canEdit(); break; case ContextMenuItemTagDefaultDirection: shouldCheck = false; shouldEnable = false; break; case ContextMenuItemTagLeftToRight: case ContextMenuItemTagRightToLeft: { ExceptionCode ec = 0; RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl"; style->setProperty(CSSPropertyDirection, direction, false, ec); shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; shouldEnable = true; break; } case ContextMenuItemTagTextDirectionDefault: { Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural"); shouldCheck = command.state() == TrueTriState; shouldEnable = command.isEnabled(); break; } case ContextMenuItemTagTextDirectionLeftToRight: { Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight"); shouldCheck = command.state() == TrueTriState; shouldEnable = command.isEnabled(); break; } case ContextMenuItemTagTextDirectionRightToLeft: { Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft"); shouldCheck = command.state() == TrueTriState; shouldEnable = command.isEnabled(); break; } case ContextMenuItemTagCopy: shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy(); break; case ContextMenuItemTagCut: shouldEnable = frame->editor()->canDHTMLCut() || frame->editor()->canCut(); break; case ContextMenuItemTagIgnoreSpelling: case ContextMenuItemTagLearnSpelling: shouldEnable = frame->selection()->isRange(); break; case ContextMenuItemTagPaste: shouldEnable = frame->editor()->canDHTMLPaste() || frame->editor()->canPaste(); break; #if PLATFORM(GTK) case ContextMenuItemTagDelete: shouldEnable = frame->editor()->canDelete(); break; case ContextMenuItemTagSelectAll: case ContextMenuItemTagInputMethods: case ContextMenuItemTagUnicode: shouldEnable = true; break; #endif case ContextMenuItemTagUnderline: { ExceptionCode ec = 0; RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); style->setProperty(CSSPropertyWebkitTextDecorationsInEffect, "underline", false, ec); shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; shouldEnable = frame->editor()->canEditRichly(); break; } case ContextMenuItemTagLookUpInDictionary: shouldEnable = frame->selection()->isRange(); break; case ContextMenuItemTagCheckGrammarWithSpelling: #ifndef BUILDING_ON_TIGER if (frame->editor()->isGrammarCheckingEnabled()) shouldCheck = true; shouldEnable = true; #endif break; case ContextMenuItemTagItalic: { ExceptionCode ec = 0; RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); style->setProperty(CSSPropertyFontStyle, "italic", false, ec); shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; shouldEnable = frame->editor()->canEditRichly(); break; } case ContextMenuItemTagBold: { ExceptionCode ec = 0; RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration(); style->setProperty(CSSPropertyFontWeight, "bold", false, ec); shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState; shouldEnable = frame->editor()->canEditRichly(); break; } case ContextMenuItemTagOutline: shouldEnable = false; break; case ContextMenuItemTagShowSpellingPanel: #ifndef BUILDING_ON_TIGER if (frame->editor()->spellingPanelIsShowing()) item.setTitle(contextMenuItemTagShowSpellingPanel(false)); else item.setTitle(contextMenuItemTagShowSpellingPanel(true)); #endif shouldEnable = frame->editor()->canEdit(); break; case ContextMenuItemTagNoGuessesFound: shouldEnable = false; break; case ContextMenuItemTagCheckSpellingWhileTyping: shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled(); break; #if PLATFORM(GTK) case ContextMenuItemTagGoBack: shouldEnable = frame->loader()->canGoBackOrForward(-1); break; case ContextMenuItemTagGoForward: shouldEnable = frame->loader()->canGoBackOrForward(1); break; case ContextMenuItemTagStop: shouldEnable = frame->loader()->documentLoader()->isLoadingInAPISense(); break; case ContextMenuItemTagReload: shouldEnable = !frame->loader()->documentLoader()->isLoadingInAPISense(); break; case ContextMenuItemTagFontMenu: shouldEnable = frame->editor()->canEditRichly(); break; #else case ContextMenuItemTagGoBack: case ContextMenuItemTagGoForward: case ContextMenuItemTagStop: case ContextMenuItemTagReload: case ContextMenuItemTagFontMenu: #endif case ContextMenuItemTagNoAction: case ContextMenuItemTagOpenLinkInNewWindow: case ContextMenuItemTagDownloadLinkToDisk: case ContextMenuItemTagCopyLinkToClipboard: case ContextMenuItemTagOpenImageInNewWindow: case ContextMenuItemTagDownloadImageToDisk: case ContextMenuItemTagCopyImageToClipboard: case ContextMenuItemTagOpenFrameInNewWindow: case ContextMenuItemTagSpellingGuess: case ContextMenuItemTagOther: case ContextMenuItemTagSearchInSpotlight: case ContextMenuItemTagSearchWeb: case ContextMenuItemTagOpenWithDefaultApplication: case ContextMenuItemPDFActualSize: case ContextMenuItemPDFZoomIn: case ContextMenuItemPDFZoomOut: case ContextMenuItemPDFAutoSize: case ContextMenuItemPDFSinglePage: case ContextMenuItemPDFFacingPages: case ContextMenuItemPDFContinuous: case ContextMenuItemPDFNextPage: case ContextMenuItemPDFPreviousPage: case ContextMenuItemTagOpenLink: case ContextMenuItemTagIgnoreGrammar: case ContextMenuItemTagSpellingMenu: case ContextMenuItemTagShowFonts: case ContextMenuItemTagStyles: case ContextMenuItemTagShowColors: case ContextMenuItemTagSpeechMenu: case ContextMenuItemTagStartSpeaking: case ContextMenuItemTagStopSpeaking: case ContextMenuItemTagWritingDirectionMenu: case ContextMenuItemTagTextDirectionMenu: case ContextMenuItemTagPDFSinglePageScrolling: case ContextMenuItemTagPDFFacingPagesScrolling: case ContextMenuItemTagInspectElement: case ContextMenuItemBaseApplicationTag: break; } item.setChecked(shouldCheck); item.setEnabled(shouldEnable); }
bool EditorClientImpl::handleEditingKeyboardEvent(KeyboardEvent* evt) { const PlatformKeyboardEvent* keyEvent = evt->keyEvent(); // do not treat this as text input if it's a system key event if (!keyEvent || keyEvent->isSystemKey()) return false; Frame* frame = evt->target()->toNode()->document()->frame(); if (!frame) return false; String commandName = interpretKeyEvent(evt); Editor::Command command = frame->editor()->command(commandName); if (keyEvent->type() == PlatformEvent::RawKeyDown) { // WebKit doesn't have enough information about mode to decide how // commands that just insert text if executed via Editor should be treated, // so we leave it upon WebCore to either handle them immediately // (e.g. Tab that changes focus) or let a keypress event be generated // (e.g. Tab that inserts a Tab character, or Enter). if (command.isTextInsertion() || commandName.isEmpty()) return false; if (command.execute(evt)) { if (m_webView->client()) m_webView->client()->didExecuteCommand(WebString(commandName)); return true; } return false; } if (command.execute(evt)) { if (m_webView->client()) m_webView->client()->didExecuteCommand(WebString(commandName)); return true; } // Here we need to filter key events. // On Gtk/Linux, it emits key events with ASCII text and ctrl on for ctrl-<x>. // In Webkit, EditorClient::handleKeyboardEvent in // WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp drop such events. // On Mac, it emits key events with ASCII text and meta on for Command-<x>. // These key events should not emit text insert event. // Alt key would be used to insert alternative character, so we should let // through. Also note that Ctrl-Alt combination equals to AltGr key which is // also used to insert alternative character. // http://code.google.com/p/chromium/issues/detail?id=10846 // Windows sets both alt and meta are on when "Alt" key pressed. // http://code.google.com/p/chromium/issues/detail?id=2215 // Also, we should not rely on an assumption that keyboards don't // send ASCII characters when pressing a control key on Windows, // which may be configured to do it so by user. // See also http://en.wikipedia.org/wiki/Keyboard_Layout // FIXME(ukai): investigate more detail for various keyboard layout. if (evt->keyEvent()->text().length() == 1) { UChar ch = evt->keyEvent()->text()[0U]; // Don't insert null or control characters as they can result in // unexpected behaviour if (ch < ' ') return false; #if !OS(WINDOWS) // Don't insert ASCII character if ctrl w/o alt or meta is on. // On Mac, we should ignore events when meta is on (Command-<x>). if (ch < 0x80) { if (evt->keyEvent()->ctrlKey() && !evt->keyEvent()->altKey()) return false; #if OS(DARWIN) if (evt->keyEvent()->metaKey()) return false; #endif } #endif } if (!frame->editor()->canEdit()) return false; return frame->editor()->insertText(evt->keyEvent()->text(), evt); }