165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch/* 265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Copyright (C) 2010 Apple Inc. All rights reserved. 365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Redistribution and use in source and binary forms, with or without 565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * modification, are permitted provided that the following conditions 665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * are met: 765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 1. Redistributions of source code must retain the above copyright 865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * notice, this list of conditions and the following disclaimer. 965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 2. Redistributions in binary form must reproduce the above copyright 1065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * notice, this list of conditions and the following disclaimer in the 1165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * documentation and/or other materials provided with the distribution. 1265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * 1365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 1465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 1565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 1765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 1865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 1965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * THE POSSIBILITY OF SUCH DAMAGE. 2465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch */ 2565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "config.h" 2765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "WebPopupMenu.h" 2865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 2965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "PlatformPopupMenuData.h" 3065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <WebCore/Font.h> 3165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <WebCore/GraphicsContext.h> 3265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <WebCore/TextRun.h> 3365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <WebCore/PopupMenuClient.h> 3465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <WebCore/PopupMenuStyle.h> 3565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include <WebCore/RenderTheme.h> 3665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 3765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochusing namespace WebCore; 3865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 3965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochnamespace WebKit { 4065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 4165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const int separatorPadding = 4; 4265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const int separatorHeight = 1; 4365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic const int popupWindowBorderWidth = 1; 4465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 4565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochvoid WebPopupMenu::setUpPlatformData(const WebCore::IntRect& pageCoordinates, PlatformPopupMenuData& data) 4665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch{ 4765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch int itemCount = m_popupClient->listSize(); 4865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 4965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch data.m_clientPaddingLeft = m_popupClient->clientPaddingLeft(); 5065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch data.m_clientPaddingRight = m_popupClient->clientPaddingRight(); 5165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch data.m_clientInsetLeft = m_popupClient->clientInsetLeft(); 5265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch data.m_clientInsetRight = m_popupClient->clientInsetRight(); 532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block data.m_itemHeight = m_popupClient->menuStyle().font().fontMetrics().height() + 1; 5465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 5565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch int popupWidth = 0; 5665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch for (size_t i = 0; i < itemCount; ++i) { 5765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch String text = m_popupClient->itemText(i); 5865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (text.isEmpty()) 5965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch continue; 6065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 6165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Font itemFont = m_popupClient->menuStyle().font(); 6265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (m_popupClient->itemIsLabel(i)) { 6365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch FontDescription d = itemFont.fontDescription(); 6465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch d.setWeight(d.bolderWeight()); 6565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing()); 6665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch itemFont.update(m_popupClient->fontSelector()); 6765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 6865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 6981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch popupWidth = std::max<float>(popupWidth, ceilf(itemFont.width(TextRun(text.characters(), text.length())))); 7065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 7165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 7265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch // FIXME: popupWidth should probably take into account monitor constraints as is done with WebPopupMenuProxyWin::calculatePositionAndSize. 7365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 7465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch popupWidth += max(0, data.m_clientPaddingRight - data.m_clientInsetRight) + max(0, data.m_clientPaddingLeft - data.m_clientInsetLeft); 7565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch popupWidth += 2 * popupWindowBorderWidth; 7665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch data.m_popupWidth = popupWidth; 7765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 7865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch // 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. 7965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch int backingStoreWidth = max(pageCoordinates.width() - m_popupClient->clientInsetLeft() - m_popupClient->clientInsetRight(), popupWidth); 8065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 812bde8e466a4451c7319e3a072d118917957d6554Steve Block IntSize backingStoreSize(backingStoreWidth, (itemCount * data.m_itemHeight)); 822bde8e466a4451c7319e3a072d118917957d6554Steve Block data.m_notSelectedBackingStore = ShareableBitmap::createShareable(backingStoreSize, ShareableBitmap::SupportsAlpha); 832bde8e466a4451c7319e3a072d118917957d6554Steve Block data.m_selectedBackingStore = ShareableBitmap::createShareable(backingStoreSize, ShareableBitmap::SupportsAlpha); 8465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 8565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch OwnPtr<GraphicsContext> notSelectedBackingStoreContext = data.m_notSelectedBackingStore->createGraphicsContext(); 8665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch OwnPtr<GraphicsContext> selectedBackingStoreContext = data.m_selectedBackingStore->createGraphicsContext(); 8765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 8865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Color activeOptionBackgroundColor = RenderTheme::defaultTheme()->activeListBoxSelectionBackgroundColor(); 8965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Color activeOptionTextColor = RenderTheme::defaultTheme()->activeListBoxSelectionForegroundColor(); 9065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 912bde8e466a4451c7319e3a072d118917957d6554Steve Block for (int y = 0; y < backingStoreSize.height(); y += data.m_itemHeight) { 9265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch int index = y / data.m_itemHeight; 9365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 9465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch PopupMenuStyle itemStyle = m_popupClient->itemStyle(index); 9565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 9665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Color optionBackgroundColor = itemStyle.backgroundColor(); 9765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Color optionTextColor = itemStyle.foregroundColor(); 9865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 9965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch IntRect itemRect(0, y, backingStoreWidth, data.m_itemHeight); 10065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 10165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch // Draw the background for this menu item 10265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (itemStyle.isVisible()) { 10365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch notSelectedBackingStoreContext->fillRect(itemRect, optionBackgroundColor, ColorSpaceDeviceRGB); 10465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch selectedBackingStoreContext->fillRect(itemRect, activeOptionBackgroundColor, ColorSpaceDeviceRGB); 10565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 10665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 10765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (m_popupClient->itemIsSeparator(index)) { 10865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch IntRect separatorRect(itemRect.x() + separatorPadding, itemRect.y() + (itemRect.height() - separatorHeight) / 2, itemRect.width() - 2 * separatorPadding, separatorHeight); 10965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 11065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch notSelectedBackingStoreContext->fillRect(separatorRect, optionTextColor, ColorSpaceDeviceRGB); 11165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch selectedBackingStoreContext->fillRect(separatorRect, activeOptionTextColor, ColorSpaceDeviceRGB); 11265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch continue; 11365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 11465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 11565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch String itemText = m_popupClient->itemText(index); 11665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 11765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch unsigned length = itemText.length(); 11865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch const UChar* string = itemText.characters(); 1192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft); 12065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 12165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch notSelectedBackingStoreContext->setFillColor(optionTextColor, ColorSpaceDeviceRGB); 12265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch selectedBackingStoreContext->setFillColor(activeOptionTextColor, ColorSpaceDeviceRGB); 12365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 12465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch Font itemFont = m_popupClient->menuStyle().font(); 12565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (m_popupClient->itemIsLabel(index)) { 12665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch FontDescription d = itemFont.fontDescription(); 12765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch d.setWeight(d.bolderWeight()); 12865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing()); 12965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch itemFont.update(m_popupClient->fontSelector()); 13065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 13165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 13265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch // Draw the item text 13365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (itemStyle.isVisible()) { 13465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch int textX = std::max(0, data.m_clientPaddingLeft - data.m_clientInsetLeft); 13565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch if (RenderTheme::defaultTheme()->popupOptionSupportsTextIndent() && itemStyle.textDirection() == LTR) 13665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch textX += itemStyle.textIndent().calcMinValue(itemRect.width()); 1372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block int textY = itemRect.y() + itemFont.fontMetrics().ascent() + (itemRect.height() - itemFont.fontMetrics().height()) / 2; 13865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 13965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch notSelectedBackingStoreContext->drawBidiText(itemFont, textRun, IntPoint(textX, textY)); 14065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch selectedBackingStoreContext->drawBidiText(itemFont, textRun, IntPoint(textX, textY)); 14165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 14265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch } 14365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch} 14465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch 14565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch} // namespace WebKit 146