Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: Source/core/html/HTMLSelectElement.cpp

Issue 368023003: Popup open and hide using Alt+KeyDown (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: "Build fix" Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/html/HTMLSelectElement.h ('k') | Source/core/html/HTMLSelectElementWin.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
4 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 1999 Antti Koivisto (koivisto@kde.org)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
8 * Copyright (C) 2010 Google Inc. All rights reserved. 8 * Copyright (C) 2010 Google Inc. All rights reserved.
9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/)
10 * 10 *
(...skipping 1096 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 } 1107 }
1108 1108
1109 if (!selectedOption && firstOption && !m_multiple && m_size <= 1) 1109 if (!selectedOption && firstOption && !m_multiple && m_size <= 1)
1110 firstOption->setSelectedState(true); 1110 firstOption->setSelectedState(true);
1111 1111
1112 setOptionsChangedOnRenderer(); 1112 setOptionsChangedOnRenderer();
1113 setNeedsStyleRecalc(SubtreeStyleChange); 1113 setNeedsStyleRecalc(SubtreeStyleChange);
1114 setNeedsValidityCheck(); 1114 setNeedsValidityCheck();
1115 } 1115 }
1116 1116
1117 #if !OS(WIN) 1117 void HTMLSelectElement::handlePopupOpenKeyboardEvent(Event* event)
1118 bool HTMLSelectElement::platformHandleKeydownEvent(KeyboardEvent* event)
1119 { 1118 {
1120 if (!RenderTheme::theme().popsMenuByArrowKeys()) 1119 focus();
1120 // Calling focus() may cause us to lose our renderer. Return true so
1121 // that our caller doesn't process the event further, but don't set
1122 // the event as handled.
1123 if (!renderer() || !renderer()->isMenuList() || isDisabledFormControl())
1124 return;
1125 // Save the selection so it can be compared to the new selection
1126 // when dispatching change events during selectOption, which
1127 // gets called from RenderMenuList::valueChanged, which gets called
1128 // after the user makes a selection from the menu.
1129 saveLastSelection();
1130 if (RenderMenuList* menuList = toRenderMenuList(renderer()))
1131 menuList->showPopup();
1132 int index = selectedIndex();
1133 ASSERT(index >= 0);
1134 ASSERT_WITH_SECURITY_IMPLICATION(index < static_cast<int>(listItems().size() ));
1135 setSelectedIndex(index);
1136 event->setDefaultHandled();
1137 return;
1138 }
1139
1140 bool HTMLSelectElement::shouldOpenPopupForKeyDownEvent(KeyboardEvent* keyEvent)
1141 {
1142 const String& keyIdentifier = keyEvent->keyIdentifier();
1143 RenderTheme& renderTheme = RenderTheme::theme();
1144
1145 if (isSpatialNavigationEnabled(document().frame()))
1121 return false; 1146 return false;
1122 1147
1123 if (!isSpatialNavigationEnabled(document().frame())) { 1148 return ((renderTheme.popsMenuByArrowKeys() && (keyIdentifier == "Down" || k eyIdentifier == "Up"))
1124 if (event->keyIdentifier() == "Down" || event->keyIdentifier() == "Up") { 1149 || (renderTheme.popsMenuByAltDownUpOrF4Key() && (keyIdentifier == "Down" || keyIdentifier == "Up") && (keyEvent->altKey() || keyEvent->altGraphKey()))
1125 focus(); 1150 || (renderTheme.popsMenuByAltDownUpOrF4Key() && (!keyEvent->altKey() && !keyEvent->ctrlKey() && keyIdentifier == "F4")));
1126 // Calling focus() may cause us to lose our renderer. Return true so 1151 }
1127 // that our caller doesn't process the event further, but don't set
1128 // the event as handled.
1129 if (!renderer() || !renderer()->isMenuList() || isDisabledFormContro l())
1130 return true;
1131 1152
1132 // Save the selection so it can be compared to the new selection 1153 bool HTMLSelectElement::shouldOpenPopupForKeyPressEvent(KeyboardEvent *event)
1133 // when dispatching change events during selectOption, which 1154 {
1134 // gets called from RenderMenuList::valueChanged, which gets called 1155 RenderTheme& renderTheme = RenderTheme::theme();
1135 // after the user makes a selection from the menu. 1156 int keyCode = event->keyCode();
1136 saveLastSelection();
1137 if (RenderMenuList* menuList = toRenderMenuList(renderer()))
1138 menuList->showPopup();
1139 event->setDefaultHandled();
1140 }
1141 return true;
1142 }
1143 1157
1144 return false; 1158 return ((renderTheme.popsMenuBySpaceKey() && event->keyCode() == ' ')
1159 || (renderTheme.popsMenuByReturnKey() && keyCode == '\r'));
1145 } 1160 }
1146 #endif
1147 1161
1148 void HTMLSelectElement::menuListDefaultEventHandler(Event* event) 1162 void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
1149 { 1163 {
1150 RenderTheme& renderTheme = RenderTheme::theme();
1151
1152 if (event->type() == EventTypeNames::keydown) { 1164 if (event->type() == EventTypeNames::keydown) {
1153 if (!renderer() || !event->isKeyboardEvent()) 1165 if (!renderer() || !event->isKeyboardEvent())
1154 return; 1166 return;
1155 1167
1156 if (platformHandleKeydownEvent(toKeyboardEvent(event))) 1168 KeyboardEvent* keyEvent = toKeyboardEvent(event);
1169 if (shouldOpenPopupForKeyDownEvent(keyEvent)) {
1170 handlePopupOpenKeyboardEvent(event);
1157 return; 1171 return;
1172 }
1158 1173
1159 // When using spatial navigation, we want to be able to navigate away 1174 // When using spatial navigation, we want to be able to navigate away
1160 // from the select element when the user hits any of the arrow keys, 1175 // from the select element when the user hits any of the arrow keys,
1161 // instead of changing the selection. 1176 // instead of changing the selection.
1162 if (isSpatialNavigationEnabled(document().frame())) { 1177 if (isSpatialNavigationEnabled(document().frame())) {
1163 if (!m_activeSelectionState) 1178 if (!m_activeSelectionState)
1164 return; 1179 return;
1165 } 1180 }
1166 1181
1167 const String& keyIdentifier = toKeyboardEvent(event)->keyIdentifier(); 1182 // The key handling below shouldn't be used for non spatial navigation m ode Mac
1183 if (RenderTheme::theme().popsMenuByArrowKeys() && !isSpatialNavigationEn abled(document().frame()))
1184 return;
1185
1186 const String& keyIdentifier = keyEvent->keyIdentifier();
1168 bool handled = true; 1187 bool handled = true;
1169 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = th is->listItems(); 1188 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems = th is->listItems();
1170 int listIndex = optionToListIndex(selectedIndex()); 1189 int listIndex = optionToListIndex(selectedIndex());
1171 1190
1172 if (keyIdentifier == "Down" || keyIdentifier == "Right") 1191 if (keyIdentifier == "Down" || keyIdentifier == "Right")
1173 listIndex = nextValidIndex(listIndex, SkipForwards, 1); 1192 listIndex = nextValidIndex(listIndex, SkipForwards, 1);
1174 else if (keyIdentifier == "Up" || keyIdentifier == "Left") 1193 else if (keyIdentifier == "Up" || keyIdentifier == "Left")
1175 listIndex = nextValidIndex(listIndex, SkipBackwards, 1); 1194 listIndex = nextValidIndex(listIndex, SkipBackwards, 1);
1176 else if (keyIdentifier == "PageDown") 1195 else if (keyIdentifier == "PageDown")
1177 listIndex = nextValidIndex(listIndex, SkipForwards, 3); 1196 listIndex = nextValidIndex(listIndex, SkipForwards, 3);
1178 else if (keyIdentifier == "PageUp") 1197 else if (keyIdentifier == "PageUp")
1179 listIndex = nextValidIndex(listIndex, SkipBackwards, 3); 1198 listIndex = nextValidIndex(listIndex, SkipBackwards, 3);
1180 else if (keyIdentifier == "Home") 1199 else if (keyIdentifier == "Home")
1181 listIndex = nextValidIndex(-1, SkipForwards, 1); 1200 listIndex = nextValidIndex(-1, SkipForwards, 1);
1182 else if (keyIdentifier == "End") 1201 else if (keyIdentifier == "End")
1183 listIndex = nextValidIndex(listItems.size(), SkipBackwards, 1); 1202 listIndex = nextValidIndex(listItems.size(), SkipBackwards, 1);
1184 else 1203 else
1185 handled = false; 1204 handled = false;
1186 1205
1187 if (handled && static_cast<size_t>(listIndex) < listItems.size()) 1206 if (handled && static_cast<size_t>(listIndex) < listItems.size())
1188 selectOption(listToOptionIndex(listIndex), DeselectOtherOptions | Di spatchInputAndChangeEvent | UserDriven); 1207 selectOption(listToOptionIndex(listIndex), DeselectOtherOptions | Di spatchInputAndChangeEvent | UserDriven);
1189 1208
1190 if (handled) 1209 if (handled)
1191 event->setDefaultHandled(); 1210 event->setDefaultHandled();
1192 } 1211 }
1193 1212
1194 // Use key press event here since sending simulated mouse events
1195 // on key down blocks the proper sending of the key press event.
1196 if (event->type() == EventTypeNames::keypress) { 1213 if (event->type() == EventTypeNames::keypress) {
1197 if (!renderer() || !event->isKeyboardEvent()) 1214 if (!renderer() || !event->isKeyboardEvent())
1198 return; 1215 return;
1199 1216
1200 int keyCode = toKeyboardEvent(event)->keyCode(); 1217 int keyCode = toKeyboardEvent(event)->keyCode();
1201 bool handled = false;
1202
1203 if (keyCode == ' ' && isSpatialNavigationEnabled(document().frame())) { 1218 if (keyCode == ' ' && isSpatialNavigationEnabled(document().frame())) {
1204 // Use space to toggle arrow key handling for selection change or sp atial navigation. 1219 // Use space to toggle arrow key handling for selection change or sp atial navigation.
1205 m_activeSelectionState = !m_activeSelectionState; 1220 m_activeSelectionState = !m_activeSelectionState;
1206 event->setDefaultHandled(); 1221 event->setDefaultHandled();
1207 return; 1222 return;
1208 } 1223 }
1209 1224
1210 if (renderTheme.popsMenuBySpaceOrReturn()) { 1225 KeyboardEvent* keyEvent = toKeyboardEvent(event);
1211 if (keyCode == ' ' || keyCode == '\r') { 1226 if (shouldOpenPopupForKeyPressEvent(keyEvent)) {
1212 focus(); 1227 handlePopupOpenKeyboardEvent(event);
1213 1228 return;
1214 // Calling focus() may remove the renderer or change the
1215 // renderer type.
1216 if (!renderer() || !renderer()->isMenuList() || isDisabledFormCo ntrol())
1217 return;
1218
1219 // Save the selection so it can be compared to the new selection
1220 // when dispatching change events during selectOption, which
1221 // gets called from RenderMenuList::valueChanged, which gets cal led
1222 // after the user makes a selection from the menu.
1223 saveLastSelection();
1224 if (RenderMenuList* menuList = toRenderMenuList(renderer()))
1225 menuList->showPopup();
1226 handled = true;
1227 }
1228 } else if (renderTheme.popsMenuByArrowKeys()) {
1229 if (keyCode == ' ') {
1230 focus();
1231
1232 // Calling focus() may remove the renderer or change the
1233 // renderer type.
1234 if (!renderer() || !renderer()->isMenuList() || isDisabledFormCo ntrol())
1235 return;
1236
1237 // Save the selection so it can be compared to the new selection
1238 // when dispatching change events during selectOption, which
1239 // gets called from RenderMenuList::valueChanged, which gets cal led
1240 // after the user makes a selection from the menu.
1241 saveLastSelection();
1242 if (RenderMenuList* menuList = toRenderMenuList(renderer()))
1243 menuList->showPopup();
1244 handled = true;
1245 } else if (keyCode == '\r') {
1246 if (form())
1247 form()->submitImplicitly(event, false);
1248 dispatchInputAndChangeEventForMenuList();
1249 handled = true;
1250 }
1251 } 1229 }
1252 1230
1253 if (handled) 1231 if (!RenderTheme::theme().popsMenuByReturnKey() && keyCode == '\r') {
1232 if (form())
1233 form()->submitImplicitly(event, false);
1234 dispatchInputAndChangeEventForMenuList();
1254 event->setDefaultHandled(); 1235 event->setDefaultHandled();
1236 }
1255 } 1237 }
1256 1238
1257 if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && t oMouseEvent(event)->button() == LeftButton) { 1239 if (event->type() == EventTypeNames::mousedown && event->isMouseEvent() && t oMouseEvent(event)->button() == LeftButton) {
1258 focus(); 1240 focus();
1259 if (renderer() && renderer()->isMenuList() && !isDisabledFormControl()) { 1241 if (renderer() && renderer()->isMenuList() && !isDisabledFormControl()) {
1260 if (RenderMenuList* menuList = toRenderMenuList(renderer())) { 1242 if (RenderMenuList* menuList = toRenderMenuList(renderer())) {
1261 if (menuList->popupIsVisible()) 1243 if (menuList->popupIsVisible())
1262 menuList->hidePopup(); 1244 menuList->hidePopup();
1263 else { 1245 else {
1264 // Save the selection so it can be compared to the new 1246 // Save the selection so it can be compared to the new
(...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after
1658 1640
1659 void HTMLSelectElement::trace(Visitor* visitor) 1641 void HTMLSelectElement::trace(Visitor* visitor)
1660 { 1642 {
1661 #if ENABLE(OILPAN) 1643 #if ENABLE(OILPAN)
1662 visitor->trace(m_listItems); 1644 visitor->trace(m_listItems);
1663 #endif 1645 #endif
1664 HTMLFormControlElementWithState::trace(visitor); 1646 HTMLFormControlElementWithState::trace(visitor);
1665 } 1647 }
1666 1648
1667 } // namespace 1649 } // namespace
OLDNEW
« no previous file with comments | « Source/core/html/HTMLSelectElement.h ('k') | Source/core/html/HTMLSelectElementWin.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698