diff options
Diffstat (limited to 'Source/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp')
-rw-r--r-- | Source/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/Source/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp b/Source/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp new file mode 100644 index 0000000..9c23133 --- /dev/null +++ b/Source/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "WebPopupMenu.h" + +#include "PlatformPopupMenuData.h" +#include <WebCore/Font.h> +#include <WebCore/GraphicsContext.h> +#include <WebCore/TextRun.h> +#include <WebCore/PopupMenuClient.h> +#include <WebCore/PopupMenuStyle.h> +#include <WebCore/RenderTheme.h> + +using namespace WebCore; + +namespace WebKit { + +static const int separatorPadding = 4; +static const int separatorHeight = 1; +static const int popupWindowBorderWidth = 1; + +void WebPopupMenu::setUpPlatformData(const WebCore::IntRect& pageCoordinates, PlatformPopupMenuData& data) +{ + int itemCount = m_popupClient->listSize(); + + data.m_clientPaddingLeft = m_popupClient->clientPaddingLeft(); + data.m_clientPaddingRight = m_popupClient->clientPaddingRight(); + data.m_clientInsetLeft = m_popupClient->clientInsetLeft(); + data.m_clientInsetRight = m_popupClient->clientInsetRight(); + data.m_itemHeight = m_popupClient->menuStyle().font().height() + 1; + + int popupWidth = 0; + for (size_t i = 0; i < itemCount; ++i) { + String text = m_popupClient->itemText(i); + if (text.isEmpty()) + continue; + + Font itemFont = m_popupClient->menuStyle().font(); + if (m_popupClient->itemIsLabel(i)) { + FontDescription d = itemFont.fontDescription(); + d.setWeight(d.bolderWeight()); + itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing()); + itemFont.update(m_popupClient->fontSelector()); + } + + popupWidth = std::max(popupWidth, itemFont.width(TextRun(text.characters(), text.length()))); + } + + // FIXME: popupWidth should probably take into account monitor constraints as is done with WebPopupMenuProxyWin::calculatePositionAndSize. + + popupWidth += max(0, data.m_clientPaddingRight - data.m_clientInsetRight) + max(0, data.m_clientPaddingLeft - data.m_clientInsetLeft); + popupWidth += 2 * popupWindowBorderWidth; + data.m_popupWidth = popupWidth; + + // The backing stores should be drawn at least as wide as the control on the page to match the width of the popup window we'll create. + int backingStoreWidth = max(pageCoordinates.width() - m_popupClient->clientInsetLeft() - m_popupClient->clientInsetRight(), popupWidth); + + data.m_backingStoreSize = IntSize(backingStoreWidth, (itemCount * data.m_itemHeight)); + data.m_notSelectedBackingStore = ShareableBitmap::createShareable(data.m_backingStoreSize); + data.m_selectedBackingStore = ShareableBitmap::createShareable(data.m_backingStoreSize); + + OwnPtr<GraphicsContext> notSelectedBackingStoreContext = data.m_notSelectedBackingStore->createGraphicsContext(); + OwnPtr<GraphicsContext> selectedBackingStoreContext = data.m_selectedBackingStore->createGraphicsContext(); + + Color activeOptionBackgroundColor = RenderTheme::defaultTheme()->activeListBoxSelectionBackgroundColor(); + Color activeOptionTextColor = RenderTheme::defaultTheme()->activeListBoxSelectionForegroundColor(); + + for (int y = 0; y < data.m_backingStoreSize.height(); y += data.m_itemHeight) { + int index = y / data.m_itemHeight; + + PopupMenuStyle itemStyle = m_popupClient->itemStyle(index); + + Color optionBackgroundColor = itemStyle.backgroundColor(); + Color optionTextColor = itemStyle.foregroundColor(); + + IntRect itemRect(0, y, backingStoreWidth, data.m_itemHeight); + + // Draw the background for this menu item + if (itemStyle.isVisible()) { + notSelectedBackingStoreContext->fillRect(itemRect, optionBackgroundColor, ColorSpaceDeviceRGB); + selectedBackingStoreContext->fillRect(itemRect, activeOptionBackgroundColor, ColorSpaceDeviceRGB); + } + + if (m_popupClient->itemIsSeparator(index)) { + IntRect separatorRect(itemRect.x() + separatorPadding, itemRect.y() + (itemRect.height() - separatorHeight) / 2, itemRect.width() - 2 * separatorPadding, separatorHeight); + + notSelectedBackingStoreContext->fillRect(separatorRect, optionTextColor, ColorSpaceDeviceRGB); + selectedBackingStoreContext->fillRect(separatorRect, activeOptionTextColor, ColorSpaceDeviceRGB); + continue; + } + + String itemText = m_popupClient->itemText(index); + + unsigned length = itemText.length(); + const UChar* string = itemText.characters(); + TextRun textRun(string, length, false, 0, 0, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft); + + notSelectedBackingStoreContext->setFillColor(optionTextColor, ColorSpaceDeviceRGB); + selectedBackingStoreContext->setFillColor(activeOptionTextColor, ColorSpaceDeviceRGB); + + Font itemFont = m_popupClient->menuStyle().font(); + if (m_popupClient->itemIsLabel(index)) { + FontDescription d = itemFont.fontDescription(); + d.setWeight(d.bolderWeight()); + itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing()); + itemFont.update(m_popupClient->fontSelector()); + } + + // Draw the item text + if (itemStyle.isVisible()) { + int textX = std::max(0, data.m_clientPaddingLeft - data.m_clientInsetLeft); + if (RenderTheme::defaultTheme()->popupOptionSupportsTextIndent() && itemStyle.textDirection() == LTR) + textX += itemStyle.textIndent().calcMinValue(itemRect.width()); + int textY = itemRect.y() + itemFont.ascent() + (itemRect.height() - itemFont.height()) / 2; + + notSelectedBackingStoreContext->drawBidiText(itemFont, textRun, IntPoint(textX, textY)); + selectedBackingStoreContext->drawBidiText(itemFont, textRun, IntPoint(textX, textY)); + } + } +} + +} // namespace WebKit |