summaryrefslogtreecommitdiffstats
path: root/WebCore/dom/SelectElement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/dom/SelectElement.cpp')
-rw-r--r--WebCore/dom/SelectElement.cpp31
1 files changed, 29 insertions, 2 deletions
diff --git a/WebCore/dom/SelectElement.cpp b/WebCore/dom/SelectElement.cpp
index bcab08c..57fb277 100644
--- a/WebCore/dom/SelectElement.cpp
+++ b/WebCore/dom/SelectElement.cpp
@@ -41,6 +41,7 @@
#include "Page.h"
#include "RenderListBox.h"
#include "RenderMenuList.h"
+#include "Settings.h"
#include <wtf/Assertions.h>
#if ENABLE(WML)
@@ -151,7 +152,7 @@ void SelectElement::setActiveSelectionEndIndex(SelectElementData& data, int inde
void SelectElement::updateListBoxSelection(SelectElementData& data, Element* element, bool deselectOtherOptions)
{
ASSERT(element->renderer() && (element->renderer()->isListBox() || data.multiple()));
- ASSERT(data.activeSelectionAnchorIndex() >= 0);
+ ASSERT(!data.listItems(element).size() || data.activeSelectionAnchorIndex() >= 0);
unsigned start = min(data.activeSelectionAnchorIndex(), data.activeSelectionEndIndex());
unsigned end = max(data.activeSelectionAnchorIndex(), data.activeSelectionEndIndex());
@@ -546,6 +547,10 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element
#if ARROW_KEYS_POP_MENU
if (keyIdentifier == "Down" || keyIdentifier == "Up") {
element->focus();
+
+ if (!element->renderer()) // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event.
+ return;
+
// Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
// which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
saveLastSelection(data, element);
@@ -554,6 +559,13 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element
handled = true;
}
#else
+ // 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, instead of changing the selection.
+ if (Frame* frame = element->document()->frame()) {
+ if (frame->settings() && frame->settings()->isSpatialNavigationEnabled())
+ return;
+ }
+
UNUSED_PARAM(htmlForm);
const Vector<Element*>& listItems = data.listItems(element);
@@ -597,6 +609,10 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element
#if SPACE_OR_RETURN_POP_MENU
if (keyCode == ' ' || keyCode == '\r') {
element->focus();
+
+ if (!element->renderer()) // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event.
+ return;
+
// Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
// which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
saveLastSelection(data, element);
@@ -607,6 +623,10 @@ void SelectElement::menuListDefaultEventHandler(SelectElementData& data, Element
#elif ARROW_KEYS_POP_MENU
if (keyCode == ' ') {
element->focus();
+
+ if (!element->renderer()) // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event.
+ return;
+
// Save the selection so it can be compared to the new selection when dispatching change events during setSelectedIndex,
// which gets called from RenderMenuList::valueChanged, which gets called after the user makes a selection from the menu.
saveLastSelection(data, element);
@@ -702,6 +722,9 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element*
if (event->type() == eventNames().mousedownEvent && event->isMouseEvent() && static_cast<MouseEvent*>(event)->button() == LeftButton) {
element->focus();
+ if (!element->renderer()) // Calling focus() may cause us to lose our renderer, in which case do not want to handle the event.
+ return;
+
// Convert to coords relative to the list box if needed.
MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
IntPoint localOffset = roundedIntPoint(element->renderer()->absoluteToLocal(mouseEvent->absoluteLocation(), false, true));
@@ -744,7 +767,7 @@ void SelectElement::listBoxDefaultEventHandler(SelectElementData& data, Element*
// Save the selection so it can be compared to the new selection when dispatching change events immediately after making the new selection.
saveLastSelection(data, element);
- ASSERT_UNUSED(listItems, endIndex >= 0 && (unsigned) endIndex < listItems.size());
+ ASSERT_UNUSED(listItems, !listItems.size() || (endIndex >= 0 && (unsigned) endIndex < listItems.size()));
setActiveSelectionEndIndex(data, endIndex);
// If the anchor is unitialized, or if we're going to deselect all other options, then set the anchor index equal to the end index.
@@ -945,6 +968,10 @@ SelectElementData::SelectElementData()
{
}
+SelectElementData::~SelectElementData()
+{
+}
+
void SelectElementData::checkListItems(const Element* element) const
{
#if !ASSERT_DISABLED