diff options
author | Steve Block <steveblock@google.com> | 2011-05-18 13:36:51 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-24 15:38:28 +0100 |
commit | 2fc2651226baac27029e38c9d6ef883fa32084db (patch) | |
tree | e396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/platform/chromium/PopupMenuChromium.cpp | |
parent | b3725cedeb43722b3b175aaeff70552e562d2c94 (diff) | |
download | external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2 |
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/platform/chromium/PopupMenuChromium.cpp')
-rw-r--r-- | Source/WebCore/platform/chromium/PopupMenuChromium.cpp | 119 |
1 files changed, 41 insertions, 78 deletions
diff --git a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp index 075cef0..59441d0 100644 --- a/Source/WebCore/platform/chromium/PopupMenuChromium.cpp +++ b/Source/WebCore/platform/chromium/PopupMenuChromium.cpp @@ -32,7 +32,6 @@ #include "config.h" #include "PopupMenuChromium.h" -#include "CharacterNames.h" #include "Chrome.h" #include "ChromeClientChromium.h" #include "Font.h" @@ -56,8 +55,8 @@ #include "SystemTime.h" #include "TextRun.h" #include "UserGestureIndicator.h" - #include <wtf/CurrentTime.h> +#include <wtf/unicode/CharacterNames.h> using namespace WTF; using namespace Unicode; @@ -74,17 +73,16 @@ static const int kMaxHeight = 500; static const int kBorderSize = 1; static const int kTextToLabelPadding = 10; static const int kLabelToIconPadding = 5; +static const int kMinEndOfLinePadding = 2; 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, // setTextOnIndexChange - true, // acceptOnAbandon - false, // loopSelectionNavigation - false, // restrictWidthOfListBox - // display item text in its first strong directional character's directionality. - PopupContainerSettings::FirstStrongDirectionalCharacterDirection, + true, // setTextOnIndexChange + true, // acceptOnAbandon + false, // loopSelectionNavigation + false // restrictWidthOfListBox }; // This class uses WebCore code to paint and handle events for a drop-down list @@ -330,7 +328,7 @@ PopupContainer::~PopupContainer() removeChild(m_listBox.get()); } -IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, const IntPoint& popupInitialCoordinate) +IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, int popupInitialY) { // Reset the max height to its default value, it will be recomputed below // if necessary. @@ -350,8 +348,10 @@ IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, co // If the popup would extend past the bottom of the screen, open upwards // instead. FloatRect screen = screenAvailableRect(m_frameView.get()); - widgetRect = chromeClient->windowToScreen(IntRect(popupInitialCoordinate, targetSize)); - if (widgetRect.bottom() > static_cast<int>(screen.bottom())) { + // Use this::x() for location because RTL position is considered + // in layout(). + widgetRect = chromeClient->windowToScreen(IntRect(x(), popupInitialY, targetSize.width(), targetSize.height())); + if (widgetRect.maxY() > static_cast<int>(screen.maxY())) { if (widgetRect.y() - widgetRect.height() - targetControlHeight > 0) { // There is enough room to open upwards. widgetRect.move(0, -(widgetRect.height() + targetControlHeight)); @@ -359,7 +359,7 @@ IntRect PopupContainer::layoutAndCalculateWidgetRect(int targetControlHeight, co // Figure whether upwards or downwards has more room and set the // maximum number of items. int spaceAbove = widgetRect.y() - targetControlHeight; - int spaceBelow = screen.bottom() - widgetRect.y(); + int spaceBelow = screen.maxY() - widgetRect.y(); if (spaceAbove > spaceBelow) m_listBox->setMaxHeight(spaceAbove); else @@ -383,7 +383,7 @@ void PopupContainer::showPopup(FrameView* view) ChromeClientChromium* chromeClient = chromeClientChromium(); if (chromeClient) { IntRect popupRect = frameRect(); - chromeClient->popupOpened(this, layoutAndCalculateWidgetRect(popupRect.height(), popupRect.location()), false); + chromeClient->popupOpened(this, layoutAndCalculateWidgetRect(popupRect.height(), popupRect.y()), false); m_popupOpen = true; } @@ -399,34 +399,6 @@ void PopupContainer::showPopup(FrameView* view) invalidate(); } -void PopupContainer::showExternal(const IntRect& rect, FrameView* v, int index) -{ - if (!listBox()) - return; - - listBox()->setBaseWidth(rect.width()); - listBox()->updateFromElement(); - - if (listBox()->numItems() < 1) { - hidePopup(); - return; - } - - // Adjust the popup position to account for scrolling. - IntPoint location = v->contentsToWindow(rect.location()); - IntRect popupRect(location, rect.size()); - - // Get the ChromeClient and pass it the popup menu's listbox data. - m_frameView = v; - chromeClientChromium()->popupOpened(this, popupRect, true); - - // The popup sends its "closed" notification through its parent. Set the - // parent, even though external popups have no real on-screen widget but a - // native menu (see |PopupListBox::hidePopup()|); - if (!m_listBox->parent()) - addChild(m_listBox.get()); -} - void PopupContainer::hidePopup() { listBox()->hidePopup(); @@ -581,7 +553,7 @@ void PopupContainer::refresh(const IntRect& targetControlRect) listBox()->updateFromElement(); // Store the original height to check if we need to request the location. int originalHeight = height(); - IntRect widgetRect = layoutAndCalculateWidgetRect(targetControlRect.height(), location); + IntRect widgetRect = layoutAndCalculateWidgetRect(targetControlRect.height(), location.y()); if (originalHeight != widgetRect.height()) setFrameRect(widgetRect); @@ -967,20 +939,15 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd } // Prepare the directionality to draw text. - bool rtl = false; - if (m_settings.itemTextDirectionalityHint == PopupContainerSettings::DOMElementDirection) - rtl = style.textDirection() == RTL; - else if (m_settings.itemTextDirectionalityHint == - PopupContainerSettings::FirstStrongDirectionalCharacterDirection) - rtl = itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft; - TextRun textRun(itemText.characters(), itemText.length(), false, 0, 0, rtl); + bool rtl = style.textDirection() == RTL; + TextRun textRun(itemText.characters(), itemText.length(), false, 0, 0, TextRun::AllowTrailingExpansion, rtl, style.hasTextDirectionOverride()); // If the text is right-to-left, make it right-aligned by adjusting its // beginning position. if (rightAligned) textX += maxWidth - itemFont.width(textRun); // Draw the item text. - int textY = rowRect.y() + itemFont.ascent() + (rowRect.height() - itemFont.height()) / 2; + int textY = rowRect.y() + itemFont.fontMetrics().ascent() + (rowRect.height() - itemFont.fontMetrics().height()) / 2; gc->drawBidiText(itemFont, textRun, IntPoint(textX, textY)); // We are using the left padding as the right padding includes room for the scroll-bar which @@ -1001,7 +968,7 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd // Draw the the label if applicable. if (itemLabel.isEmpty()) return; - TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, rtl); + TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, TextRun::AllowTrailingExpansion, rtl, style.hasTextDirectionOverride()); if (rightAligned) textX = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft()); else @@ -1120,7 +1087,7 @@ int PopupListBox::getRowHeight(int index) String icon = m_popupClient->itemIcon(index); RefPtr<Image> image(Image::loadPlatformResource(icon.utf8().data())); - int fontHeight = getRowFont(index).height(); + int fontHeight = getRowFont(index).fontMetrics().height(); int iconHeight = (image && !image->isNull()) ? image->rect().height() : 0; return max(fontHeight, iconHeight); @@ -1154,9 +1121,9 @@ void PopupListBox::scrollToRevealRow(int index) if (rowRect.y() < scrollY()) { // Row is above current scroll position, scroll up. ScrollView::setScrollPosition(IntPoint(0, rowRect.y())); - } else if (rowRect.bottom() > scrollY() + visibleHeight()) { + } else if (rowRect.maxY() > scrollY() + visibleHeight()) { // Row is below current scroll position, scroll down. - ScrollView::setScrollPosition(IntPoint(0, rowRect.bottom() - visibleHeight())); + ScrollView::setScrollPosition(IntPoint(0, rowRect.maxY() - visibleHeight())); } } @@ -1267,6 +1234,9 @@ void PopupListBox::updateFromElement() type = PopupItem::TypeOption; m_items.append(new PopupItem(m_popupClient->itemText(i), type)); m_items[i]->enabled = isSelectableItem(i); + PopupMenuStyle style = m_popupClient->itemStyle(i); + m_items[i]->textDirection = style.textDirection(); + m_items[i]->hasTextDirectionOverride = style.hasTextDirectionOverride(); } m_selectedIndex = m_popupClient->selectedIndex(); @@ -1277,9 +1247,12 @@ void PopupListBox::updateFromElement() void PopupListBox::layout() { + bool isRightAligned = m_popupClient->menuStyle().textDirection() == RTL; + // Size our child items. int baseWidth = 0; int paddingWidth = 0; + int lineEndPaddingWidth = 0; int y = 0; for (int i = 0; i < numItems(); ++i) { // Place the item vertically. @@ -1312,58 +1285,56 @@ void PopupListBox::layout() // FIXME: http://b/1210481 We should get the padding of individual option elements. paddingWidth = max(paddingWidth, m_popupClient->clientPaddingLeft() + m_popupClient->clientPaddingRight()); + lineEndPaddingWidth = max(lineEndPaddingWidth, + isRightAligned ? m_popupClient->clientPaddingLeft() : m_popupClient->clientPaddingRight()); } // Calculate scroll bar width. int windowHeight = 0; - -#if OS(DARWIN) - // Set the popup's window to contain all available items on Mac only, which - // uses native controls that manage their own scrolling. This allows hit - // testing to work when selecting items in popups that have more menu entries - // than the maximum window size. - m_visibleRows = numItems(); -#else m_visibleRows = min(numItems(), kMaxVisibleRows); -#endif for (int i = 0; i < m_visibleRows; ++i) { int rowHeight = getRowHeight(i); -#if !OS(DARWIN) // Only clip the window height for non-Mac platforms. if (windowHeight + rowHeight > m_maxHeight) { m_visibleRows = i; break; } -#endif windowHeight += rowHeight; } // Set our widget and scrollable contents sizes. int scrollbarWidth = 0; - if (m_visibleRows < numItems()) + if (m_visibleRows < numItems()) { scrollbarWidth = ScrollbarTheme::nativeTheme()->scrollbarThickness(); + // Use kMinEndOfLinePadding when there is a scrollbar so that we use + // as much as (lineEndPaddingWidth - kMinEndOfLinePadding) padding + // space for scrollbar and allow user to use CSS padding to make the + // popup listbox align with the select element. + paddingWidth = paddingWidth - lineEndPaddingWidth + kMinEndOfLinePadding; + } + int windowWidth; int contentWidth; if (m_settings.restrictWidthOfListBox) { windowWidth = m_baseWidth; - contentWidth = m_baseWidth - scrollbarWidth - paddingWidth; + contentWidth = m_baseWidth - scrollbarWidth; } else { windowWidth = baseWidth + scrollbarWidth + paddingWidth; - contentWidth = baseWidth; + contentWidth = baseWidth + paddingWidth; if (windowWidth < m_baseWidth) { windowWidth = m_baseWidth; - contentWidth = m_baseWidth - scrollbarWidth - paddingWidth; + contentWidth = m_baseWidth - scrollbarWidth; } else m_baseWidth = baseWidth; } resize(windowWidth, windowHeight); - setContentsSize(IntSize(contentWidth, getRowBounds(numItems() - 1).bottom())); + setContentsSize(IntSize(contentWidth, getRowBounds(numItems() - 1).maxY())); if (hostWindow()) scrollToRevealSelection(); @@ -1404,19 +1375,11 @@ PopupMenuChromium::~PopupMenuChromium() hide(); } -// The Mac Chromium implementation relies on external control (a Cocoa control) -// to display, handle the input tracking and menu item selection for the popup. -// Windows and Linux Chromium let our WebKit port handle the display, while -// another process manages the popup window and input handling. void PopupMenuChromium::show(const IntRect& r, FrameView* v, int index) { if (!p.popup) p.popup = PopupContainer::create(client(), PopupContainer::Select, dropDownSettings); -#if OS(DARWIN) - p.popup->showExternal(r, v, index); -#else p.popup->show(r, v, index); -#endif } void PopupMenuChromium::hide() |