summaryrefslogtreecommitdiff
path: root/Source/WebCore/html/HTMLSelectElement.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
commitcd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch)
tree8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/WebCore/html/HTMLSelectElement.cpp
parentd11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff)
downloadqtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/WebCore/html/HTMLSelectElement.cpp')
-rw-r--r--Source/WebCore/html/HTMLSelectElement.cpp132
1 files changed, 68 insertions, 64 deletions
diff --git a/Source/WebCore/html/HTMLSelectElement.cpp b/Source/WebCore/html/HTMLSelectElement.cpp
index bfebf8e64..4bd10b800 100644
--- a/Source/WebCore/html/HTMLSelectElement.cpp
+++ b/Source/WebCore/html/HTMLSelectElement.cpp
@@ -61,19 +61,6 @@ using namespace HTMLNames;
// Upper limit agreed upon with representatives of Opera and Mozilla.
static const unsigned maxSelectItems = 10000;
-// Configure platform-specific behavior when focused pop-up receives arrow/space/return keystroke.
-// (PLATFORM(MAC) and PLATFORM(GTK) are always false in Chromium, hence the extra tests.)
-#if PLATFORM(MAC) || (PLATFORM(CHROMIUM) && OS(DARWIN))
-#define ARROW_KEYS_POP_MENU 1
-#define SPACE_OR_RETURN_POP_MENU 0
-#elif PLATFORM(GTK) || (PLATFORM(CHROMIUM) && OS(UNIX))
-#define ARROW_KEYS_POP_MENU 0
-#define SPACE_OR_RETURN_POP_MENU 1
-#else
-#define ARROW_KEYS_POP_MENU 0
-#define SPACE_OR_RETURN_POP_MENU 0
-#endif
-
static const DOMTimeStamp typeAheadTimeout = 1000;
HTMLSelectElement::HTMLSelectElement(const QualifiedName& tagName, Document* document, HTMLFormElement* form)
@@ -247,10 +234,13 @@ String HTMLSelectElement::value() const
void HTMLSelectElement::setValue(const String &value)
{
- if (value.isNull())
+ // We clear the previously selected option(s) when needed, to guarantee calling setSelectedIndex() only once.
+ if (value.isNull()) {
+ setSelectedIndex(-1);
return;
- // find the option with value() matching the given parameter
- // and make it the current selection.
+ }
+
+ // Find the option with value() matching the given parameter and make it the current selection.
const Vector<HTMLElement*>& items = listItems();
unsigned optionIndex = 0;
for (unsigned i = 0; i < items.size(); i++) {
@@ -262,6 +252,8 @@ void HTMLSelectElement::setValue(const String &value)
optionIndex++;
}
}
+
+ setSelectedIndex(-1);
}
void HTMLSelectElement::parseMappedAttribute(Attribute* attr)
@@ -775,8 +767,10 @@ void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b
ASSERT(option->ownerSelectElement() == this);
if (optionIsSelected)
selectOption(option->index());
+ else if (!usesMenuList())
+ selectOption(-1);
else
- selectOption(m_multiple ? -1 : nextSelectableListIndex(-1));
+ selectOption(nextSelectableListIndex(-1));
}
void HTMLSelectElement::selectOption(int optionIndex, SelectOptionFlags flags)
@@ -986,7 +980,12 @@ void HTMLSelectElement::reset()
#if !PLATFORM(WIN) || OS(WINCE)
bool HTMLSelectElement::platformHandleKeydownEvent(KeyboardEvent* event)
{
-#if ARROW_KEYS_POP_MENU
+ const Page* page = document()->page();
+ RefPtr<RenderTheme> renderTheme = page ? page->theme() : RenderTheme::defaultTheme();
+
+ if (!renderTheme->popsMenuByArrowKeys())
+ return false;
+
if (!isSpatialNavigationEnabled(document()->frame())) {
if (event->keyIdentifier() == "Down" || event->keyIdentifier() == "Up") {
focus();
@@ -1007,15 +1006,16 @@ bool HTMLSelectElement::platformHandleKeydownEvent(KeyboardEvent* event)
}
return true;
}
-#else
- UNUSED_PARAM(event);
-#endif
+
return false;
}
#endif
void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
{
+ const Page* page = document()->page();
+ RefPtr<RenderTheme> renderTheme = page ? page->theme() : RenderTheme::defaultTheme();
+
if (event->type() == eventNames().keydownEvent) {
if (!renderer() || !event->isKeyboardEvent())
return;
@@ -1074,48 +1074,49 @@ void HTMLSelectElement::menuListDefaultEventHandler(Event* event)
return;
}
-#if SPACE_OR_RETURN_POP_MENU
- if (keyCode == ' ' || keyCode == '\r') {
- focus();
-
- // Calling focus() may cause us to lose our renderer, in which case
- // do not want to handle the event.
- if (!renderer())
- 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;
+ if (renderTheme->popsMenuBySpaceOrReturn()) {
+ if (keyCode == ' ' || keyCode == '\r') {
+ focus();
+
+ // Calling focus() may cause us to lose our renderer, in which case
+ // do not want to handle the event.
+ if (!renderer())
+ 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 cause us to lose our renderer, in which case
+ // do not want to handle the event.
+ if (!renderer())
+ 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);
+ dispatchChangeEventForMenuList();
+ handled = true;
+ }
}
-#elif ARROW_KEYS_POP_MENU
- if (keyCode == ' ') {
- focus();
-
- // Calling focus() may cause us to lose our renderer, in which case
- // do not want to handle the event.
- if (!renderer())
- 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);
- dispatchChangeEventForMenuList();
- handled = true;
- }
-#endif
if (handled)
event->setDefaultHandled();
}
@@ -1158,7 +1159,7 @@ void HTMLSelectElement::updateSelectedState(int listIndex, bool multi, bool shif
if (clickedElement->hasTagName(optionTag)) {
// Keep track of whether an active selection (like during drag
// selection), should select or deselect.
- if (toHTMLOptionElement(clickedElement)->selected() && multi)
+ if (toHTMLOptionElement(clickedElement)->selected() && multiSelect)
m_activeSelectionState = false;
if (!m_activeSelectionState)
toHTMLOptionElement(clickedElement)->setSelectedState(false);
@@ -1226,8 +1227,11 @@ void HTMLSelectElement::listBoxDefaultEventHandler(Event* event)
if (m_multiple) {
setActiveSelectionEndIndex(listIndex);
updateListBoxSelection(false);
- } else
- updateSelectedState(listIndex, false, false);
+ } else {
+ setActiveSelectionAnchorIndex(listIndex);
+ setActiveSelectionEndIndex(listIndex);
+ updateListBoxSelection(true);
+ }
event->setDefaultHandled();
}
} else if (event->type() == eventNames().mouseupEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton && document()->frame()->eventHandler()->autoscrollRenderer() != renderer()) {