| OLD | NEW |
| (Empty) | |
| 1 Foo.cpp |
| 2 /* |
| 3 * Copyright (C) 2006, 2007 Apple, Inc. All rights reserved. |
| 4 * Copyright (C) 2012 Google, Inc. All rights reserved. |
| 5 * |
| 6 * Redistribution and use in source and binary forms, with or without |
| 7 * modification, are permitted provided that the following conditions |
| 8 * are met: |
| 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. |
| 11 * 2. Redistributions in binary form must reproduce the above copyright |
| 12 * notice, this list of conditions and the following disclaimer in the |
| 13 * documentation and/or other materials provided with the distribution. |
| 14 * |
| 15 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| 16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| 19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| 23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 26 */ |
| 27 |
| 28 #include "core/editing/EditingBehavior.h" |
| 29 |
| 30 #include "core/events/KeyboardEvent.h" |
| 31 #include "platform/KeyboardCodes.h" |
| 32 #include "public/platform/WebInputEvent.h" |
| 33 |
| 34 namespace blink { |
| 35 |
| 36 namespace { |
| 37 |
| 38 // |
| 39 // The below code was adapted from the WebKit file webview.cpp |
| 40 // |
| 41 |
| 42 const unsigned CtrlKey = WebInputEvent::ControlKey; |
| 43 const unsigned AltKey = WebInputEvent::AltKey; |
| 44 const unsigned ShiftKey = WebInputEvent::ShiftKey; |
| 45 const unsigned MetaKey = WebInputEvent::MetaKey; |
| 46 #if OS(MACOSX) |
| 47 // Aliases for the generic key defintions to make kbd shortcuts definitions |
| 48 // more |
| 49 // readable on OS X. |
| 50 const unsigned OptionKey = AltKey; |
| 51 |
| 52 // Do not use this constant for anything but cursor movement commands. Keys |
| 53 // with cmd set have their |isSystemKey| bit set, so chances are the shortcut |
| 54 // will not be executed. Another, less important, reason is that shortcuts |
| 55 // defined in the layoutObject do not blink the menu item that they triggered. |
| 56 // See http://crbug.com/25856 and the bugs linked from there for details. |
| 57 const unsigned CommandKey = MetaKey; |
| 58 #endif |
| 59 |
| 60 // Keys with special meaning. These will be delegated to the editor using |
| 61 // the execCommand() method |
| 62 struct KeyboardCodeKeyDownEntry { |
| 63 unsigned virtualKey; |
| 64 unsigned modifiers; |
| 65 const char* name; |
| 66 }; |
| 67 |
| 68 struct KeyboardCodeKeyPressEntry { |
| 69 unsigned charCode; |
| 70 unsigned modifiers; |
| 71 const char* name; |
| 72 }; |
| 73 |
| 74 // DomKey has a broader range than KeyboardCode, we need DomKey to handle some |
| 75 // special keys. |
| 76 // Note: We cannot use DomKey for printable keys since it may vary based on |
| 77 // locale. |
| 78 struct DomKeyKeyDownEntry { |
| 79 const char* key; |
| 80 unsigned modifiers; |
| 81 const char* name; |
| 82 }; |
| 83 |
| 84 // Key bindings with command key on Mac and alt key on other platforms are |
| 85 // marked as system key events and will be ignored (with the exception |
| 86 // of Command-B and Command-I) so they shouldn't be added here. |
| 87 const KeyboardCodeKeyDownEntry kKeyboardCodeKeyDownEntries[] = { |
| 88 {VKEY_LEFT, 0, "MoveLeft"}, |
| 89 {VKEY_LEFT, ShiftKey, "MoveLeftAndModifySelection"}, |
| 90 #if OS(MACOSX) |
| 91 {VKEY_LEFT, OptionKey, "MoveWordLeft"}, |
| 92 {VKEY_LEFT, OptionKey | ShiftKey, "MoveWordLeftAndModifySelection"}, |
| 93 #else |
| 94 {VKEY_LEFT, CtrlKey, "MoveWordLeft"}, |
| 95 {VKEY_LEFT, CtrlKey | ShiftKey, "MoveWordLeftAndModifySelection"}, |
| 96 #endif |
| 97 {VKEY_RIGHT, 0, "MoveRight"}, |
| 98 {VKEY_RIGHT, ShiftKey, "MoveRightAndModifySelection"}, |
| 99 #if OS(MACOSX) |
| 100 {VKEY_RIGHT, OptionKey, "MoveWordRight"}, |
| 101 {VKEY_RIGHT, OptionKey | ShiftKey, "MoveWordRightAndModifySelection"}, |
| 102 #else |
| 103 {VKEY_RIGHT, CtrlKey, "MoveWordRight"}, |
| 104 {VKEY_RIGHT, CtrlKey | ShiftKey, "MoveWordRightAndModifySelection"}, |
| 105 #endif |
| 106 {VKEY_UP, 0, "MoveUp"}, |
| 107 {VKEY_UP, ShiftKey, "MoveUpAndModifySelection"}, |
| 108 {VKEY_PRIOR, ShiftKey, "MovePageUpAndModifySelection"}, |
| 109 {VKEY_DOWN, 0, "MoveDown"}, |
| 110 {VKEY_DOWN, ShiftKey, "MoveDownAndModifySelection"}, |
| 111 {VKEY_NEXT, ShiftKey, "MovePageDownAndModifySelection"}, |
| 112 #if !OS(MACOSX) |
| 113 {VKEY_UP, CtrlKey, "MoveParagraphBackward"}, |
| 114 {VKEY_UP, CtrlKey | ShiftKey, "MoveParagraphBackwardAndModifySelection"}, |
| 115 {VKEY_DOWN, CtrlKey, "MoveParagraphForward"}, |
| 116 {VKEY_DOWN, CtrlKey | ShiftKey, "MoveParagraphForwardAndModifySelection"}, |
| 117 {VKEY_PRIOR, 0, "MovePageUp"}, |
| 118 {VKEY_NEXT, 0, "MovePageDown"}, |
| 119 #endif |
| 120 {VKEY_HOME, 0, "MoveToBeginningOfLine"}, |
| 121 {VKEY_HOME, ShiftKey, "MoveToBeginningOfLineAndModifySelection"}, |
| 122 #if OS(MACOSX) |
| 123 {VKEY_PRIOR, OptionKey, "MovePageUp"}, |
| 124 {VKEY_NEXT, OptionKey, "MovePageDown"}, |
| 125 #endif |
| 126 #if !OS(MACOSX) |
| 127 {VKEY_HOME, CtrlKey, "MoveToBeginningOfDocument"}, |
| 128 {VKEY_HOME, CtrlKey | ShiftKey, |
| 129 "MoveToBeginningOfDocumentAndModifySelection"}, |
| 130 #endif |
| 131 {VKEY_END, 0, "MoveToEndOfLine"}, |
| 132 {VKEY_END, ShiftKey, "MoveToEndOfLineAndModifySelection"}, |
| 133 #if !OS(MACOSX) |
| 134 {VKEY_END, CtrlKey, "MoveToEndOfDocument"}, |
| 135 {VKEY_END, CtrlKey | ShiftKey, "MoveToEndOfDocumentAndModifySelection"}, |
| 136 #endif |
| 137 {VKEY_BACK, 0, "DeleteBackward"}, |
| 138 {VKEY_BACK, ShiftKey, "DeleteBackward"}, |
| 139 {VKEY_DELETE, 0, "DeleteForward"}, |
| 140 #if OS(MACOSX) |
| 141 {VKEY_BACK, OptionKey, "DeleteWordBackward"}, |
| 142 {VKEY_DELETE, OptionKey, "DeleteWordForward"}, |
| 143 #else |
| 144 {VKEY_BACK, CtrlKey, "DeleteWordBackward"}, |
| 145 {VKEY_DELETE, CtrlKey, "DeleteWordForward"}, |
| 146 #endif |
| 147 #if OS(MACOSX) |
| 148 {'B', CommandKey, "ToggleBold"}, |
| 149 {'I', CommandKey, "ToggleItalic"}, |
| 150 #else |
| 151 {'B', CtrlKey, "ToggleBold"}, |
| 152 {'I', CtrlKey, "ToggleItalic"}, |
| 153 #endif |
| 154 {'U', CtrlKey, "ToggleUnderline"}, |
| 155 {VKEY_ESCAPE, 0, "Cancel"}, |
| 156 {VKEY_OEM_PERIOD, CtrlKey, "Cancel"}, |
| 157 {VKEY_TAB, 0, "InsertTab"}, |
| 158 {VKEY_TAB, ShiftKey, "InsertBacktab"}, |
| 159 {VKEY_RETURN, 0, "InsertNewline"}, |
| 160 {VKEY_RETURN, CtrlKey, "InsertNewline"}, |
| 161 {VKEY_RETURN, AltKey, "InsertNewline"}, |
| 162 {VKEY_RETURN, AltKey | ShiftKey, "InsertNewline"}, |
| 163 {VKEY_RETURN, ShiftKey, "InsertLineBreak"}, |
| 164 {VKEY_INSERT, CtrlKey, "Copy"}, |
| 165 {VKEY_INSERT, ShiftKey, "Paste"}, |
| 166 {VKEY_DELETE, ShiftKey, "Cut"}, |
| 167 #if !OS(MACOSX) |
| 168 // On OS X, we pipe these back to the browser, so that it can do menu item |
| 169 // blinking. |
| 170 {'C', CtrlKey, "Copy"}, |
| 171 {'V', CtrlKey, "Paste"}, |
| 172 {'V', CtrlKey | ShiftKey, "PasteAndMatchStyle"}, |
| 173 {'X', CtrlKey, "Cut"}, |
| 174 {'A', CtrlKey, "SelectAll"}, |
| 175 {'Z', CtrlKey, "Undo"}, |
| 176 {'Z', CtrlKey | ShiftKey, "Redo"}, |
| 177 {'Y', CtrlKey, "Redo"}, |
| 178 #endif |
| 179 {VKEY_INSERT, 0, "OverWrite"}, |
| 180 }; |
| 181 |
| 182 const KeyboardCodeKeyPressEntry kKeyboardCodeKeyPressEntries[] = { |
| 183 {'\t', 0, "InsertTab"}, |
| 184 {'\t', ShiftKey, "InsertBacktab"}, |
| 185 {'\r', 0, "InsertNewline"}, |
| 186 {'\r', ShiftKey, "InsertLineBreak"}, |
| 187 }; |
| 188 |
| 189 const DomKeyKeyDownEntry kDomKeyKeyDownEntries[] = { |
| 190 {"Copy", 0, "Copy"}, |
| 191 {"Cut", 0, "Cut"}, |
| 192 {"Paste", 0, "Paste"}, |
| 193 }; |
| 194 |
| 195 const char* lookupCommandNameFromDomKeyKeyDown(const String& key, |
| 196 unsigned modifiers) { |
| 197 // This table is not likely to grow, so sequential search is fine here. |
| 198 for (const auto& entry : kDomKeyKeyDownEntries) { |
| 199 if (key == entry.key && modifiers == entry.modifiers) |
| 200 return entry.name; |
| 201 } |
| 202 return nullptr; |
| 203 } |
| 204 |
| 205 } // anonymous namespace |
| 206 |
| 207 const char* EditingBehavior::interpretKeyEvent(const KeyboardEvent& event) |
| 208 const { |
| 209 const WebKeyboardEvent* keyEvent = event.keyEvent(); |
| 210 if (!keyEvent) |
| 211 return ""; |
| 212 |
| 213 static HashMap<int, const char*>* keyDownCommandsMap = nullptr; |
| 214 static HashMap<int, const char*>* keyPressCommandsMap = nullptr; |
| 215 |
| 216 if (!keyDownCommandsMap) { |
| 217 keyDownCommandsMap = new HashMap<int, const char*>; |
| 218 keyPressCommandsMap = new HashMap<int, const char*>; |
| 219 |
| 220 for (const auto& entry : kKeyboardCodeKeyDownEntries) { |
| 221 keyDownCommandsMap->set(entry.modifiers << 16 | entry.virtualKey, |
| 222 entry.name); |
| 223 } |
| 224 |
| 225 for (const auto& entry : kKeyboardCodeKeyPressEntries) { |
| 226 keyPressCommandsMap->set(entry.modifiers << 16 | entry.charCode, |
| 227 entry.name); |
| 228 } |
| 229 } |
| 230 |
| 231 unsigned modifiers = |
| 232 keyEvent->modifiers() & (ShiftKey | AltKey | CtrlKey | MetaKey); |
| 233 |
| 234 if (keyEvent->type() == WebInputEvent::RawKeyDown) { |
| 235 int mapKey = modifiers << 16 | event.keyCode(); |
| 236 const char* name = mapKey ? keyDownCommandsMap->get(mapKey) : nullptr; |
| 237 if (!name) |
| 238 name = lookupCommandNameFromDomKeyKeyDown(event.key(), modifiers); |
| 239 return name; |
| 240 } |
| 241 |
| 242 int mapKey = modifiers << 16 | event.charCode(); |
| 243 return mapKey ? keyPressCommandsMap->get(mapKey) : 0; |
| 244 } |
| 245 |
| 246 bool EditingBehavior::shouldInsertCharacter(const KeyboardEvent& event) |
| 247 const { |
| 248 if (event.keyEvent()->text[1] != 0) |
| 249 return true; |
| 250 |
| 251 // On Gtk/Linux, it emits key events with ASCII text and ctrl on for |
| 252 // ctrl-<x>. |
| 253 // In Webkit, EditorClient::handleKeyboardEvent in |
| 254 // WebKit/gtk/WebCoreSupport/EditorClientGtk.cpp drop such events. |
| 255 // On Mac, it emits key events with ASCII text and meta on for Command-<x>. |
| 256 // These key events should not emit text insert event. |
| 257 // Alt key would be used to insert alternative character, so we should let |
| 258 // through. Also note that Ctrl-Alt combination equals to AltGr key which is |
| 259 // also used to insert alternative character. |
| 260 // http://code.google.com/p/chromium/issues/detail?id=10846 |
| 261 // Windows sets both alt and meta are on when "Alt" key pressed. |
| 262 // http://code.google.com/p/chromium/issues/detail?id=2215 |
| 263 // Also, we should not rely on an assumption that keyboards don't |
| 264 // send ASCII characters when pressing a control key on Windows, |
| 265 // which may be configured to do it so by user. |
| 266 // See also http://en.wikipedia.org/wiki/Keyboard_Layout |
| 267 // FIXME(ukai): investigate more detail for various keyboard layout. |
| 268 UChar ch = event.keyEvent()->text[0U]; |
| 269 |
| 270 // Don't insert null or control characters as they can result in |
| 271 // unexpected behaviour |
| 272 if (ch < ' ') |
| 273 return false; |
| 274 #if OS(LINUX) |
| 275 // According to XKB map no keyboard combinations with ctrl key are mapped to |
| 276 // printable characters, however we need the filter as the DomKey/text could |
| 277 // contain printable characters. |
| 278 if (event.ctrlKey()) |
| 279 return false; |
| 280 #elif !OS(WIN) |
| 281 // Don't insert ASCII character if ctrl w/o alt or meta is on. |
| 282 // On Mac, we should ignore events when meta is on (Command-<x>). |
| 283 if (ch < 0x80) { |
| 284 if (event.ctrlKey() && !event.altKey()) |
| 285 return false; |
| 286 #if OS(MACOSX) |
| 287 if (event.metaKey()) |
| 288 return false; |
| 289 #endif |
| 290 } |
| 291 #endif |
| 292 |
| 293 return true; |
| 294 } |
| 295 } // namespace blink |
| OLD | NEW |