diff options
author | Feng Qian <> | 2009-04-10 18:11:29 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-04-10 18:11:29 -0700 |
commit | 8f72e70a9fd78eec56623b3a62e68f16b7b27e28 (patch) | |
tree | 181bf9a400c30a1bf34ea6d72560e8d00111d549 /WebCore/platform/chromium/PopupMenuChromium.cpp | |
parent | 7ed56f225e0ade046e1c2178977f72b2d896f196 (diff) | |
download | external_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.cpp | 156 |
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() |