static inline KeyboardEvent::KeyLocationCode keyLocationCode(const PlatformKeyboardEvent& key) { if (key.isKeypad()) return KeyboardEvent::DOM_KEY_LOCATION_NUMPAD; if (key.modifiers() & PlatformEvent::IsLeft) return KeyboardEvent::DOM_KEY_LOCATION_LEFT; if (key.modifiers() & PlatformEvent::IsRight) return KeyboardEvent::DOM_KEY_LOCATION_RIGHT; return KeyboardEvent::DOM_KEY_LOCATION_STANDARD; }
KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, AbstractView* view) : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()), true, true, view, 0, key.modifiers(), InputDeviceCapabilities::doesntFireTouchEventsSourceCapabilities()) , m_keyEvent(adoptPtr(new PlatformKeyboardEvent(key))) , m_keyIdentifier(key.keyIdentifier()) , m_code(key.code()) , m_key(key.key()) , m_location(keyLocationCode(key)) { setPlatformTimeStamp(key.timestamp()); initLocationModifiers(m_location); }
// FIXME: This needs to be unified with the keyPress method on FrameMac bool FrameWin::keyPress(const PlatformKeyboardEvent& keyEvent) { bool result; // Check for cases where we are too early for events -- possible unmatched key up // from pressing return in the location bar. Document *doc = document(); if (!doc) return false; Node *node = doc->focusNode(); if (!node) { if (doc->isHTMLDocument()) node = doc->body(); else node = doc->documentElement(); if (!node) return false; } if (!keyEvent.isKeyUp()) prepareForUserAction(); result = !EventTargetNodeCast(node)->dispatchKeyEvent(keyEvent); // FIXME: FrameMac has a keyDown/keyPress hack here which we are not copying. return result; }
static bool isCharacterTypeEvent(const PlatformKeyboardEvent& event) { // Check whether the event is a character-typed event or not. // We use RawKeyDown/Char/KeyUp event scheme on all platforms, // so PlatformKeyboardEvent::Char (not RawKeyDown) type event // is considered as character type event. return event.type() == PlatformEvent::Char; }
static inline KeyboardEvent::KeyLocationCode keyLocationCode(const PlatformKeyboardEvent& key) { if (key.isKeypad()) return KeyboardEvent::DOM_KEY_LOCATION_NUMPAD; switch (key.windowsVirtualKeyCode()) { case VK_LCONTROL: case VK_LSHIFT: case VK_LMENU: case VK_LWIN: return KeyboardEvent::DOM_KEY_LOCATION_LEFT; case VK_RCONTROL: case VK_RSHIFT: case VK_RMENU: case VK_RWIN: return KeyboardEvent::DOM_KEY_LOCATION_RIGHT; default: return KeyboardEvent::DOM_KEY_LOCATION_STANDARD; } }
static void handleKeyPress(Frame& frame, KeyboardEvent& event, const PlatformKeyboardEvent& platformEvent) { String commandName = interpretKeyEvent(event); if (!commandName.isEmpty()) { frame.editor().command(commandName).execute(); event.setDefaultHandled(); return; } // Don't insert null or control characters as they can result in unexpected behaviour if (event.charCode() < ' ') return; // Don't insert anything if a modifier is pressed and it has not been handled yet if (platformEvent.ctrlKey() || platformEvent.altKey()) return; if (frame.editor().insertText(platformEvent.text(), &event)) event.setDefaultHandled(); }
KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, AbstractView* view) : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()), true, true, view, 0, key.ctrlKey(), key.altKey(), key.shiftKey(), key.metaKey(), InputDevice::doesntFireTouchEventsInputDevice()) , m_keyEvent(adoptPtr(new PlatformKeyboardEvent(key))) , m_keyIdentifier(key.keyIdentifier()) , m_code(key.code()) , m_key(key.key()) , m_location(keyLocationCode(key)) , m_isAutoRepeat(key.isAutoRepeat()) , m_bbIsNumLock(key.bbIsNumLock()) { setUICreateTime(key.timestamp()); }
KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, AbstractView* view) : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()), true, true, view, 0, key.ctrlKey(), key.altKey(), key.shiftKey(), key.metaKey()) , m_keyEvent(adoptPtr(new PlatformKeyboardEvent(key))) , m_keyIdentifier(key.keyIdentifier()) , m_keyLocation(key.isKeypad() ? DOM_KEY_LOCATION_NUMPAD : DOM_KEY_LOCATION_STANDARD) // FIXME: differentiate right/left, too , m_altGraphKey(false) { }
// From HTMLSelectElement.cpp, with modifications void PopupListBox::typeAheadFind(const PlatformKeyboardEvent& event) { TimeStamp now = static_cast<TimeStamp>(currentTime() * 1000.0f); TimeStamp delta = now - m_lastCharTime; // Reset the time when user types in a character. The time gap between // last character and the current character is used to indicate whether // user typed in a string or just a character as the search prefix. m_lastCharTime = now; UChar c = event.windowsVirtualKeyCode(); String prefix; int searchStartOffset = 1; if (delta > typeAheadTimeoutMs) { m_typedString = prefix = String(&c, 1); m_repeatingChar = c; } else { m_typedString.append(c); if (c == m_repeatingChar) { // The user is likely trying to cycle through all the items starting // with this character, so just search on the character. prefix = String(&c, 1); } else { m_repeatingChar = 0; prefix = m_typedString; searchStartOffset = 0; } } // Compute a case-folded copy of the prefix string before beginning the // search for a matching element. This code uses foldCase to work around the // fact that String::startWith does not fold non-ASCII characters. This code // can be changed to use startWith once that is fixed. String prefixWithCaseFolded(prefix.foldCase()); int itemCount = numItems(); int index = (max(0, m_selectedIndex) + searchStartOffset) % itemCount; for (int i = 0; i < itemCount; i++, index = (index + 1) % itemCount) { if (!isSelectableItem(index)) continue; if (stripLeadingWhiteSpace(m_items[index]->label).foldCase().startsWith(prefixWithCaseFolded)) { selectIndex(index); return; } } }
KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, AbstractView* view) : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()), true, true, view, 0, key.ctrlKey(), key.altKey(), key.shiftKey(), key.metaKey()) , m_keyEvent(adoptPtr(new PlatformKeyboardEvent(key))) , m_keyIdentifier(key.keyIdentifier()) , m_location(keyLocationCode(key)) , m_altGraphKey(false) , m_isAutoRepeat(key.isAutoRepeat()) { ScriptWrappable::init(this); }
KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, AbstractView* view) : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()), true, true, key.timestamp(), view, 0, key.ctrlKey(), key.altKey(), key.shiftKey(), key.metaKey()) , m_keyEvent(std::make_unique<PlatformKeyboardEvent>(key)) , m_keyIdentifier(key.keyIdentifier()) , m_location(keyLocationCode(key)) , m_altGraphKey(false) #if PLATFORM(COCOA) #if USE(APPKIT) , m_handledByInputMethod(key.handledByInputMethod()) , m_keypressCommands(key.commands()) #else , m_handledByInputMethod(false) #endif #endif { }
KeyboardEvent::KeyboardEvent(const PlatformKeyboardEvent& key, DOMWindow* view) : UIEventWithKeyState(eventTypeForKeyboardEventType(key.type()) , true, true, key.timestamp(), view, 0, key.ctrlKey(), key.altKey(), key.shiftKey() , key.metaKey(), false, key.modifiers().contains(PlatformEvent::Modifier::CapsLockKey)) , m_keyEvent(std::make_unique<PlatformKeyboardEvent>(key)) #if ENABLE(KEYBOARD_KEY_ATTRIBUTE) , m_key(key.key()) #endif #if ENABLE(KEYBOARD_CODE_ATTRIBUTE) , m_code(key.code()) #endif , m_keyIdentifier(key.keyIdentifier()) , m_location(keyLocationCode(key)) , m_repeat(key.isAutoRepeat()) , m_isComposing(view && view->frame() && view->frame()->editor().hasComposition()) #if PLATFORM(COCOA) #if USE(APPKIT) , m_handledByInputMethod(key.handledByInputMethod()) , m_keypressCommands(key.commands()) #else , m_handledByInputMethod(false) #endif #endif { }
bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event) { if (event.type() == PlatformEvent::KeyUp) return true; if (!numItems() && event.windowsVirtualKeyCode() != VKEY_ESCAPE) return true; switch (event.windowsVirtualKeyCode()) { case VKEY_ESCAPE: abandon(); // may delete this return true; case VKEY_RETURN: if (m_selectedIndex == -1) { hidePopup(); // Don't eat the enter if nothing is selected. return false; } acceptIndex(m_selectedIndex); // may delete this return true; case VKEY_UP: case VKEY_DOWN: // We have to forward only shift + up combination to focused node when // autofill popup. Because all characters from the cursor to the start // of the text area should selected when you press shift + up arrow. // shift + down should be the similar way to shift + up. if (event.modifiers() && m_popupClient->menuStyle().menuType() == PopupMenuStyle::AutofillPopup) m_focusedElement->dispatchKeyEvent(event); else if (event.windowsVirtualKeyCode() == VKEY_UP) selectPreviousRow(); else selectNextRow(); break; case VKEY_PRIOR: adjustSelectedIndex(-m_visibleRows); break; case VKEY_NEXT: adjustSelectedIndex(m_visibleRows); break; case VKEY_HOME: adjustSelectedIndex(-m_selectedIndex); break; case VKEY_END: adjustSelectedIndex(m_items.size()); break; default: if (!event.ctrlKey() && !event.altKey() && !event.metaKey() && isPrintableChar(event.windowsVirtualKeyCode()) && isCharacterTypeEvent(event)) typeAheadFind(event); break; } if (m_originalIndex != m_selectedIndex) { // Keyboard events should update the selection immediately (but we don't // want to fire the onchange event until the popup is closed, to match // IE). We change the original index so we revert to that when the // popup is closed. if (m_settings.acceptOnAbandon) m_acceptedIndexOnAbandon = m_selectedIndex; setOriginalIndex(m_selectedIndex); if (m_settings.setTextOnIndexChange) m_popupClient->setTextFromItem(m_selectedIndex); } if (event.windowsVirtualKeyCode() == VKEY_TAB) { // TAB is a special case as it should select the current item if any and // advance focus. if (m_selectedIndex >= 0) { acceptIndex(m_selectedIndex); // May delete us. // Return false so the TAB key event is propagated to the page. return false; } // Call abandon() so we honor m_acceptedIndexOnAbandon if set. abandon(); // Return false so the TAB key event is propagated to the page. return false; } return true; }