Chromium Code Reviews| Index: Source/core/html/HTMLSelectElement.cpp |
| diff --git a/Source/core/html/HTMLSelectElement.cpp b/Source/core/html/HTMLSelectElement.cpp |
| index b0dc747ff14ab9cee6caa8a9264b2d0c2834ad1f..192e3834fc61a8f6bcbf0c9f497d1fe99ac24e79 100644 |
| --- a/Source/core/html/HTMLSelectElement.cpp |
| +++ b/Source/core/html/HTMLSelectElement.cpp |
| @@ -1114,47 +1114,62 @@ void HTMLSelectElement::resetImpl() |
| setNeedsValidityCheck(); |
| } |
| -#if !OS(WIN) |
| -bool HTMLSelectElement::platformHandleKeydownEvent(KeyboardEvent* event) |
| +void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event) |
| { |
| - if (!RenderTheme::theme().popsMenuByArrowKeys()) |
| - return false; |
| + focus(); |
| + // Calling focus() may cause us to lose our renderer. Return true so |
| + // that our caller doesn't process the event further, but don't set |
| + // the event as handled. |
| + if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) |
| + return; |
| + // Save the selection so it can be compared to the new selection |
| + // when dispatching change events during selectOption, which |
| + // gets called from RenderMenuList::valueChanged, which gets called |
| + // after the user makes a selection from the menu. |
| + saveLastSelection(); |
| + if (RenderMenuList* menuList = toRenderMenuList(renderer())) |
| + menuList->showPopup(); |
| + int index = selectedIndex(); |
| + ASSERT(index >= 0); |
| + ASSERT_WITH_SECURITY_IMPLICATION(index < static_cast<int>(listItems().size())); |
| + setSelectedIndex(index); |
| + event->setDefaultHandled(); |
| + return; |
| +} |
| - if (!isSpatialNavigationEnabled(document().frame())) { |
| - if (event->keyIdentifier() == "Down" || event->keyIdentifier() == "Up") { |
| - focus(); |
| - // Calling focus() may cause us to lose our renderer. Return true so |
| - // that our caller doesn't process the event further, but don't set |
| - // the event as handled. |
| - if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) |
| - return true; |
| +bool HTMLSelectElement::shouldOpenPopupForKeyDownEvent(KeyboardEvent* keyEvent) |
| +{ |
| + const String& keyIdentifier = keyEvent->keyIdentifier(); |
| + RenderTheme& renderTheme = RenderTheme::theme(); |
| - // Save the selection so it can be compared to the new selection |
| - // when dispatching change events during selectOption, which |
| - // gets called from RenderMenuList::valueChanged, which gets called |
| - // after the user makes a selection from the menu. |
| - saveLastSelection(); |
| - if (RenderMenuList* menuList = toRenderMenuList(renderer())) |
| - menuList->showPopup(); |
| - event->setDefaultHandled(); |
| - } |
| - return true; |
| - } |
| + if (isSpatialNavigationEnabled(document().frame())) |
| + return false; |
| - return false; |
| + return ((renderTheme.popsMenuByArrowKeys() && (keyIdentifier == "Down" || keyIdentifier == "Up")) |
| + || (renderTheme.popsMenuByAltDownUpOrF4Key() && (keyIdentifier == "Down" || keyIdentifier == "Up") && (keyEvent->altKey() || keyEvent->altGraphKey())) |
| + || (renderTheme.popsMenuByAltDownUpOrF4Key() && (!keyEvent->altKey() && !keyEvent->ctrlKey() && keyIdentifier == "F4"))); |
| } |
| -#endif |
| -void HTMLSelectElement::menuListDefaultEventHandler(Event* event) |
| +bool HTMLSelectElement::shouldOpenPopupForKeyPressEvent(KeyboardEvent *event) |
| { |
| RenderTheme& renderTheme = RenderTheme::theme(); |
| + int keyCode = event->keyCode(); |
| + |
| + return ((renderTheme.popsMenuBySpaceKey() && event->keyCode() == ' ') |
| + || (renderTheme.popsMenuByReturnKey() && keyCode == '\r')); |
| +} |
| +void HTMLSelectElement::menuListDefaultEventHandler(Event* event) |
| +{ |
| if (event->type() == EventTypeNames::keydown) { |
| if (!renderer() || !event->isKeyboardEvent()) |
| return; |
| - if (platformHandleKeydownEvent(toKeyboardEvent(event))) |
| + KeyboardEvent* keyEvent = toKeyboardEvent(event); |
| + if (shouldOpenPopupForKeyDownEvent(keyEvent)) { |
| + handlePopupOpenKeyboardEvent(event); |
| return; |
| + } |
| // When using spatial navigation, we want to be able to navigate away |
| // from the select element when the user hits any of the arrow keys, |
| @@ -1164,7 +1179,11 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) |
| return; |
| } |
| - const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); |
| + // Early return as for mac below handling keys for key does not hold but for spatial navigation it uses below keys |
|
keishi
2014/07/10 02:24:10
nit: I think this comment is hard to understand. E
|
| + if (RenderTheme::theme().popsMenuByArrowKeys() && !isSpatialNavigationEnabled(document().frame())) |
| + return; |
| + |
| + const String& keyIdentifier = keyEvent->keyIdentifier(); |
| bool handled = true; |
| const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = this->listItems(); |
| int listIndex = optionToListIndex(selectedIndex()); |
| @@ -1191,15 +1210,11 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) |
| event->setDefaultHandled(); |
| } |
| - // Use key press event here since sending simulated mouse events |
| - // on key down blocks the proper sending of the key press event. |
| if (event->type() == EventTypeNames::keypress) { |
| if (!renderer() || !event->isKeyboardEvent()) |
| return; |
| int keyCode = toKeyboardEvent(event)->keyCode(); |
| - bool handled = false; |
| - |
| if (keyCode == ' ' && isSpatialNavigationEnabled(document().frame())) { |
| // Use space to toggle arrow key handling for selection change or spatial navigation. |
| m_activeSelectionState = !m_activeSelectionState; |
| @@ -1207,51 +1222,18 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event) |
| return; |
| } |
| - if (renderTheme.popsMenuBySpaceOrReturn()) { |
| - if (keyCode == ' ' || keyCode == '\r') { |
| - focus(); |
| - |
| - // Calling focus() may remove the renderer or change the |
| - // renderer type. |
| - if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) |
| - return; |
| - |
| - // Save the selection so it can be compared to the new selection |
| - // when dispatching change events during selectOption, which |
| - // gets called from RenderMenuList::valueChanged, which gets called |
| - // after the user makes a selection from the menu. |
| - saveLastSelection(); |
| - if (RenderMenuList* menuList = toRenderMenuList(renderer())) |
| - menuList->showPopup(); |
| - handled = true; |
| - } |
| - } else if (renderTheme.popsMenuByArrowKeys()) { |
| - if (keyCode == ' ') { |
| - focus(); |
| - |
| - // Calling focus() may remove the renderer or change the |
| - // renderer type. |
| - if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl()) |
| - return; |
| - |
| - // Save the selection so it can be compared to the new selection |
| - // when dispatching change events during selectOption, which |
| - // gets called from RenderMenuList::valueChanged, which gets called |
| - // after the user makes a selection from the menu. |
| - saveLastSelection(); |
| - if (RenderMenuList* menuList = toRenderMenuList(renderer())) |
| - menuList->showPopup(); |
| - handled = true; |
| - } else if (keyCode == '\r') { |
| - if (form()) |
| - form()->submitImplicitly(event, false); |
| - dispatchInputAndChangeEventForMenuList(); |
| - handled = true; |
| - } |
| + KeyboardEvent* keyEvent = toKeyboardEvent(event); |
| + if (shouldOpenPopupForKeyPressEvent(keyEvent)) { |
| + handlePopupOpenKeyboardEvent(event); |
| + return; |
| } |
| - if (handled) |
| + if (!RenderTheme::theme().popsMenuByReturnKey() && keyCode == '\r') { |
| + if (form()) |
| + form()->submitImplicitly(event, false); |
| + dispatchInputAndChangeEventForMenuList(); |
| event->setDefaultHandled(); |
| + } |
| } |
| if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && toMouseEvent(event)->button() == LeftButton) { |