summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/chromium/PopupMenuChromium.cpp
diff options
context:
space:
mode:
authorFeng Qian <>2009-04-10 18:11:29 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-04-10 18:11:29 -0700
commit8f72e70a9fd78eec56623b3a62e68f16b7b27e28 (patch)
tree181bf9a400c30a1bf34ea6d72560e8d00111d549 /WebCore/platform/chromium/PopupMenuChromium.cpp
parent7ed56f225e0ade046e1c2178977f72b2d896f196 (diff)
downloadexternal_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.zip
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.gz
external_webkit-8f72e70a9fd78eec56623b3a62e68f16b7b27e28.tar.bz2
AI 145796: Land the WebKit merge @r42026.
Automated import of CL 145796
Diffstat (limited to 'WebCore/platform/chromium/PopupMenuChromium.cpp')
-rw-r--r--WebCore/platform/chromium/PopupMenuChromium.cpp156
1 files changed, 58 insertions, 98 deletions
diff --git a/WebCore/platform/chromium/PopupMenuChromium.cpp b/WebCore/platform/chromium/PopupMenuChromium.cpp
index fad0a6b..53f565a 100644
--- a/WebCore/platform/chromium/PopupMenuChromium.cpp
+++ b/WebCore/platform/chromium/PopupMenuChromium.cpp
@@ -69,10 +69,24 @@ static const int kMaxHeight = 500;
static const int kBorderSize = 1;
static const TimeStamp kTypeAheadTimeoutMs = 1000;
+// The settings used for the drop down menu.
+// This is the delegate used if none is provided.
+static const PopupContainerSettings dropDownSettings = {
+ true, // focusOnShow
+ true, // setTextOnIndexChange
+ true, // acceptOnAbandon
+ false // loopSelectionNavigation
+};
+
// This class uses WebCore code to paint and handle events for a drop-down list
// box ("combobox" on Windows).
class PopupListBox : public FramelessScrollView, public RefCounted<PopupListBox> {
public:
+ static PassRefPtr<PopupListBox> create(PopupMenuClient* client, const PopupContainerSettings& settings)
+ {
+ return adoptRef(new PopupListBox(client, settings));
+ }
+
// FramelessScrollView
virtual void paint(GraphicsContext*, const IntRect&);
virtual bool handleMouseDownEvent(const PlatformMouseEvent&);
@@ -84,9 +98,6 @@ public:
// ScrollView
virtual HostWindow* hostWindow() const;
- // Widget
- virtual void invalidateRect(const IntRect&);
-
// PopupListBox methods
// Shows the popup
@@ -125,20 +136,6 @@ public:
// Returns whether the popup wants to process events for the passed key.
bool isInterestedInEventForKey(int keyCode);
- // Sets whether the PopupMenuClient should be told to change its text when a
- // new item is selected (by using the arrow keys). Default is true.
- void setTextOnIndexChange(bool value) { m_setTextOnIndexChange = value; }
-
- // Sets whether we should accept the selected index when the popup is
- // abandonned.
- void setAcceptOnAbandon(bool value) { m_shouldAcceptOnAbandon = value; }
-
- // Sets whether pressing the down/up arrow when the last/first row is
- // selected clears the selection on the first key press and then selects the
- // first/last row on the next key press. If false, the selected row stays
- // the last/first row.
- void setLoopSelectionNavigation(bool value) { m_loopSelectionNavigation = value; }
-
private:
friend class PopupContainer;
friend class RefCounted<PopupListBox>;
@@ -159,17 +156,15 @@ private:
int y; // y offset of this item, relative to the top of the popup.
};
- PopupListBox(PopupMenuClient* client)
- : m_originalIndex(0)
+ PopupListBox(PopupMenuClient* client, const PopupContainerSettings& settings)
+ : m_settings(settings)
+ , m_originalIndex(0)
, m_selectedIndex(0)
- , m_shouldAcceptOnAbandon(true)
, m_willAcceptOnAbandon(false)
, m_visibleRows(0)
, m_popupClient(client)
, m_repeatingChar(0)
, m_lastCharTime(0)
- , m_setTextOnIndexChange(true)
- , m_loopSelectionNavigation(false)
{
setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
}
@@ -228,6 +223,9 @@ private:
void selectPreviousRow();
void selectNextRow();
+ // The settings that specify the behavior for this Popup window.
+ PopupContainerSettings m_settings;
+
// This is the index of the item marked as "selected" - i.e. displayed in the widget on the
// page.
int m_originalIndex;
@@ -237,15 +235,10 @@ private:
// enter yet however.
int m_selectedIndex;
- // Whether we should accept the selectedIndex as chosen when the popup is
- // "abandoned". This value is set through its setter and is useful as
- // select popup menu and form autofill popup menu have different behaviors.
- bool m_shouldAcceptOnAbandon;
-
// True if we should accept the selectedIndex as chosen, even if the popup
// is "abandoned". This is used for keyboard navigation, where we want the
- // selection to change immediately, and is only used if
- // m_shouldAcceptOnAbandon is true.
+ // selection to change immediately, and is only used if the settings
+ // acceptOnAbandon field is true.
bool m_willAcceptOnAbandon;
// This is the number of rows visible in the popup. The maximum number visible at a time is
@@ -277,10 +270,6 @@ private:
// The last time the user hit a key. Used for typeAheadFind.
TimeStamp m_lastCharTime;
-
- bool m_setTextOnIndexChange;
-
- bool m_loopSelectionNavigation;
};
static PlatformMouseEvent constructRelativeMouseEvent(const PlatformMouseEvent& e,
@@ -316,19 +305,15 @@ static PlatformWheelEvent constructRelativeWheelEvent(const PlatformWheelEvent&
// static
PassRefPtr<PopupContainer> PopupContainer::create(PopupMenuClient* client,
- bool focusOnShow)
+ const PopupContainerSettings& settings)
{
- return adoptRef(new PopupContainer(client, focusOnShow));
+ return adoptRef(new PopupContainer(client, settings));
}
-PopupContainer::PopupContainer(PopupMenuClient* client, bool focusOnShow)
- : m_listBox(new PopupListBox(client)),
- m_focusOnShow(focusOnShow)
+PopupContainer::PopupContainer(PopupMenuClient* client, const PopupContainerSettings& settings)
+ : m_listBox(PopupListBox::create(client, settings))
+ , m_settings(settings)
{
- // FrameViews are created with a refcount of 1 so it needs releasing after we
- // assign it to a RefPtr.
- m_listBox->deref();
-
setScrollbarModes(ScrollbarAlwaysOff, ScrollbarAlwaysOff);
}
@@ -352,19 +337,19 @@ void PopupContainer::showPopup(FrameView* view)
if (chromeClient) {
// If the popup would extend past the bottom of the screen, open upwards
// instead.
- FloatRect screen = screenRect(view);
+ FloatRect screen = screenAvailableRect(view);
IntRect widgetRect = chromeClient->windowToScreen(frameRect());
if (widgetRect.bottom() > static_cast<int>(screen.bottom()))
widgetRect.move(0, -(widgetRect.height() + selectHeight));
- chromeClient->popupOpened(this, widgetRect, m_focusOnShow);
+ chromeClient->popupOpened(this, widgetRect, m_settings.focusOnShow);
}
- // Must get called after we have a client and containingWindow.
- addChild(m_listBox.get());
+ if (!m_listBox->parent())
+ addChild(m_listBox.get());
- // Enable scrollbars after the listbox is inserted into the hierarchy, so
- // it has a proper WidgetClient.
+ // Enable scrollbars after the listbox is inserted into the hierarchy,
+ // so it has a proper WidgetClient.
m_listBox->setVerticalScrollbarMode(ScrollbarAuto);
m_listBox->scrollToRevealSelection();
@@ -374,12 +359,6 @@ void PopupContainer::showPopup(FrameView* view)
void PopupContainer::hidePopup()
{
- invalidate();
-
- m_listBox->disconnectClient();
- removeChild(m_listBox.get());
- m_listBox = 0;
-
if (client())
client()->popupClosed(this);
}
@@ -495,27 +474,17 @@ void PopupContainer::show(const IntRect& r, FrameView* v, int index)
showPopup(v);
}
-void PopupContainer::setTextOnIndexChange(bool value)
-{
- listBox()->setTextOnIndexChange(value);
-}
-
-void PopupContainer::setAcceptOnAbandon(bool value)
-{
- listBox()->setAcceptOnAbandon(value);
-}
-
-void PopupContainer::setLoopSelectionNavigation(bool value)
-{
- listBox()->setLoopSelectionNavigation(value);
-}
-
void PopupContainer::refresh()
{
listBox()->updateFromElement();
layout();
}
+int PopupContainer::selectedIndex() const
+{
+ return m_listBox->selectedIndex();
+}
+
///////////////////////////////////////////////////////////////////////////////
// PopupListBox implementation
@@ -658,13 +627,14 @@ bool PopupListBox::handleKeyEvent(const PlatformKeyboardEvent& event)
// want to fire the onchange event until the popup is closed, to match
// IE). We change the original index so we revert to that when the
// popup is closed.
- if (m_shouldAcceptOnAbandon)
+ if (m_settings.acceptOnAbandon)
m_willAcceptOnAbandon = true;
setOriginalIndex(m_selectedIndex);
- if (m_setTextOnIndexChange)
+ if (m_settings.setTextOnIndexChange)
m_popupClient->setTextFromItem(m_selectedIndex);
- } else if (!m_setTextOnIndexChange && event.windowsVirtualKeyCode() == VKEY_TAB) {
+ } else if (!m_settings.setTextOnIndexChange &&
+ event.windowsVirtualKeyCode() == VKEY_TAB) {
// TAB is a special case as it should select the current item if any and
// advance focus.
if (m_selectedIndex >= 0)
@@ -683,15 +653,6 @@ HostWindow* PopupListBox::hostWindow() const
return parent() ? parent()->hostWindow() : 0;
}
-void PopupListBox::invalidateRect(const IntRect& rect)
-{
- // Since we are returning the HostWindow of our parent as our own in
- // hostWindow(), we need to invalidate in our parent's coordinates.
- IntRect newRect(rect);
- newRect.move(kBorderSize, kBorderSize);
- FramelessScrollView::invalidateRect(newRect);
-}
-
// From HTMLSelectElement.cpp
static String stripLeadingWhiteSpace(const String& string)
{
@@ -855,12 +816,10 @@ void PopupListBox::abandon()
m_selectedIndex = m_originalIndex;
+ m_popupClient->hidePopup();
+
if (m_willAcceptOnAbandon)
m_popupClient->valueChanged(m_selectedIndex);
-
- // valueChanged may have torn down the popup!
- if (m_popupClient)
- m_popupClient->hidePopup();
}
int PopupListBox::pointToRowIndex(const IntPoint& point)
@@ -892,12 +851,11 @@ void PopupListBox::acceptIndex(int index)
if (isSelectableItem(index)) {
RefPtr<PopupListBox> keepAlive(this);
- // Tell the <select> PopupMenuClient what index was selected, and hide ourself.
- m_popupClient->valueChanged(index);
+ // Hide ourselves first since valueChanged may have numerous side-effects.
+ m_popupClient->hidePopup();
- // valueChanged may have torn down the popup!
- if (m_popupClient)
- m_popupClient->hidePopup();
+ // Tell the <select> PopupMenuClient what index was selected.
+ m_popupClient->valueChanged(index);
}
}
@@ -940,7 +898,9 @@ void PopupListBox::invalidateRow(int index)
if (index < 0)
return;
- invalidateRect(getRowBounds(index));
+ // Invalidate in the window contents, as FramelessScrollView::invalidateRect
+ // paints in the window coordinates.
+ invalidateRect(contentsToWindow(getRowBounds(index)));
}
void PopupListBox::scrollToRevealRow(int index)
@@ -959,7 +919,8 @@ void PopupListBox::scrollToRevealRow(int index)
}
}
-bool PopupListBox::isSelectableItem(int index) {
+bool PopupListBox::isSelectableItem(int index)
+{
return m_items[index]->type == TypeOption && m_popupClient->itemIsEnabled(index);
}
@@ -973,7 +934,7 @@ void PopupListBox::clearSelection()
void PopupListBox::selectNextRow()
{
- if (!m_loopSelectionNavigation || m_selectedIndex != numItems() - 1) {
+ if (!m_settings.loopSelectionNavigation || m_selectedIndex != numItems() - 1) {
adjustSelectedIndex(1);
return;
}
@@ -984,7 +945,7 @@ void PopupListBox::selectNextRow()
void PopupListBox::selectPreviousRow()
{
- if (!m_loopSelectionNavigation || m_selectedIndex > 0) {
+ if (!m_settings.loopSelectionNavigation || m_selectedIndex > 0) {
adjustSelectedIndex(-1);
return;
}
@@ -1156,16 +1117,15 @@ PopupMenu::~PopupMenu()
void PopupMenu::show(const IntRect& r, FrameView* v, int index)
{
- p.popup = PopupContainer::create(client(), true);
+ if (!p.popup)
+ p.popup = PopupContainer::create(client(), dropDownSettings);
p.popup->show(r, v, index);
}
void PopupMenu::hide()
{
- if (p.popup) {
+ if (p.popup)
p.popup->hidePopup();
- p.popup = 0;
- }
}
void PopupMenu::updateFromElement()