| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |