[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

weinig at apple.com weinig at apple.com
Wed Dec 22 15:37:44 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 6073e7ff414b64d847e002d76093af3bd5bad225
Author: weinig at apple.com <weinig at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Nov 9 17:44:56 2010 +0000

    Windows Popup widget support (<select>)
    <rdar://problem/8559439>
    https://bugs.webkit.org/show_bug.cgi?id=48701
    
    Reviewed by Anders Carlsson.
    
    Port WebCore's PopupMenuWin's implementation to work within the confines of WebKit2.
    Since we currently can't draw text using WebCore in the UIProcess, this approach uses
    the WebProcess to create two bitmaps representing the full popup menu (both unselected and
    selected) and sends them to the UIProcess to be drawn in an HWND.
    
    * Shared/BackingStore.h:
    * Shared/cg/BackingStoreCG.cpp:
    * Shared/qt/BackingStoreQt.cpp:
    
    Add new function to create a flipped graphics context from the backing store,
    and add additional parameters to paint, to allow more control of how the backing
    store is painted into the destination context.
    
    * Shared/PlatformPopupMenuData.cpp: Added.
    (WebKit::PlatformPopupMenuData::PlatformPopupMenuData):
    (WebKit::PlatformPopupMenuData::encode):
    (WebKit::PlatformPopupMenuData::decode):
    * Shared/PlatformPopupMenuData.h: Added.
    Add struct so platforms can send platform specific data to their popup menu implementations.
    
    * Shared/WebPopupItem.cpp:
    (WebKit::WebPopupItem::WebPopupItem):
    (WebKit::WebPopupItem::encode):
    (WebKit::WebPopupItem::decode):
    * Shared/WebPopupItem.h:
    Add isLabel for each menu item.
    
    * UIProcess/FindIndicator.cpp:
    (WebKit::FindIndicator::draw):
    Update for new BackingStore::paint signature.
    
    * UIProcess/WebPageProxy.cpp:
    (WebKit::WebPageProxy::showPopupMenu):
    * UIProcess/WebPageProxy.h:
    * UIProcess/WebPageProxy.messages.in:
    * UIProcess/WebPopupMenuProxy.h:
    * UIProcess/mac/WebPopupMenuProxyMac.h:
    * UIProcess/mac/WebPopupMenuProxyMac.mm:
    (WebKit::WebPopupMenuProxyMac::showPopupMenu):
    * UIProcess/qt/WebPopupMenuProxyQt.cpp:
    (WebKit::WebPopupMenuProxyQt::showPopupMenu):
    * UIProcess/qt/WebPopupMenuProxyQt.h:
    Pass through the new PlatformPopupMenuData.
    
    * UIProcess/win/WebPopupMenuProxyWin.cpp:
    * UIProcess/win/WebPopupMenuProxyWin.h:
    Port implementation from WebCore.
    
    * UIProcess/win/WebView.cpp:
    (WebKit::WebView::createPopupMenuProxy):
    Pass the WebView to the WebPopupMenuProxyWin.
    
    * WebProcess/Plugins/PluginProxy.cpp:
    (WebKit::PluginProxy::paint):
    (WebKit::PluginProxy::update):
    Update for new BackingStore::paint signature.
    
    * WebProcess/WebCoreSupport/WebPopupMenu.cpp:
    (WebKit::WebPopupMenu::populateItems): Add isLabel for each item.
    (WebKit::WebPopupMenu::show): Give each platform a chance to add platform specific data.
    * WebProcess/WebCoreSupport/WebPopupMenu.h:
    
    * WebProcess/WebCoreSupport/mac/WebPopupMenuMac.mm: Added.
    (WebKit::WebPopupMenu::setUpPlatformData):
    * WebProcess/WebCoreSupport/qt/WebPopupMenuQt.cpp: Added.
    (WebKit::WebPopupMenu::setUpPlatformData):
    Add stubbed out setUpPlatformData.
    
    * WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp: Added.
    (WebKit::WebPopupMenu::setUpPlatformData):
    Compute data needed in the UIProcess including generating the bitmaps.
    
    * WebKit2.pro:
    * WebKit2.xcodeproj/project.pbxproj:
    * win/WebKit2.vcproj:
    Add new files.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@71640 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebKit2/ChangeLog b/WebKit2/ChangeLog
index 2414ed4..b7240b5 100644
--- a/WebKit2/ChangeLog
+++ b/WebKit2/ChangeLog
@@ -1,3 +1,88 @@
+2010-11-09  Sam Weinig  <sam at webkit.org>
+
+        Reviewed by Anders Carlsson.
+
+        Windows Popup widget support (<select>)
+        <rdar://problem/8559439>
+        https://bugs.webkit.org/show_bug.cgi?id=48701
+
+        Port WebCore's PopupMenuWin's implementation to work within the confines of WebKit2.
+        Since we currently can't draw text using WebCore in the UIProcess, this approach uses
+        the WebProcess to create two bitmaps representing the full popup menu (both unselected and 
+        selected) and sends them to the UIProcess to be drawn in an HWND.
+
+        * Shared/BackingStore.h:
+        * Shared/cg/BackingStoreCG.cpp:
+        * Shared/qt/BackingStoreQt.cpp:
+
+        Add new function to create a flipped graphics context from the backing store, 
+        and add additional parameters to paint, to allow more control of how the backing
+        store is painted into the destination context.
+
+        * Shared/PlatformPopupMenuData.cpp: Added.
+        (WebKit::PlatformPopupMenuData::PlatformPopupMenuData):
+        (WebKit::PlatformPopupMenuData::encode):
+        (WebKit::PlatformPopupMenuData::decode):
+        * Shared/PlatformPopupMenuData.h: Added.
+        Add struct so platforms can send platform specific data to their popup menu implementations.
+
+        * Shared/WebPopupItem.cpp:
+        (WebKit::WebPopupItem::WebPopupItem):
+        (WebKit::WebPopupItem::encode):
+        (WebKit::WebPopupItem::decode):
+        * Shared/WebPopupItem.h:
+        Add isLabel for each menu item.
+
+        * UIProcess/FindIndicator.cpp:
+        (WebKit::FindIndicator::draw):
+        Update for new BackingStore::paint signature.
+
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::showPopupMenu):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/WebPopupMenuProxy.h:
+        * UIProcess/mac/WebPopupMenuProxyMac.h:
+        * UIProcess/mac/WebPopupMenuProxyMac.mm:
+        (WebKit::WebPopupMenuProxyMac::showPopupMenu):
+        * UIProcess/qt/WebPopupMenuProxyQt.cpp:
+        (WebKit::WebPopupMenuProxyQt::showPopupMenu):
+        * UIProcess/qt/WebPopupMenuProxyQt.h:
+        Pass through the new PlatformPopupMenuData.
+
+        * UIProcess/win/WebPopupMenuProxyWin.cpp:
+        * UIProcess/win/WebPopupMenuProxyWin.h:
+        Port implementation from WebCore.
+
+        * UIProcess/win/WebView.cpp:
+        (WebKit::WebView::createPopupMenuProxy):
+        Pass the WebView to the WebPopupMenuProxyWin.
+
+        * WebProcess/Plugins/PluginProxy.cpp:
+        (WebKit::PluginProxy::paint):
+        (WebKit::PluginProxy::update):
+        Update for new BackingStore::paint signature.
+
+        * WebProcess/WebCoreSupport/WebPopupMenu.cpp:
+        (WebKit::WebPopupMenu::populateItems): Add isLabel for each item.
+        (WebKit::WebPopupMenu::show): Give each platform a chance to add platform specific data.
+        * WebProcess/WebCoreSupport/WebPopupMenu.h:
+
+        * WebProcess/WebCoreSupport/mac/WebPopupMenuMac.mm: Added.
+        (WebKit::WebPopupMenu::setUpPlatformData):
+        * WebProcess/WebCoreSupport/qt/WebPopupMenuQt.cpp: Added.
+        (WebKit::WebPopupMenu::setUpPlatformData):
+        Add stubbed out setUpPlatformData.
+
+        * WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp: Added.
+        (WebKit::WebPopupMenu::setUpPlatformData):
+        Compute data needed in the UIProcess including generating the bitmaps.
+
+        * WebKit2.pro:
+        * WebKit2.xcodeproj/project.pbxproj:
+        * win/WebKit2.vcproj:
+        Add new files.
+
 2010-11-09  Balazs Kelemen  <kbalazs at webkit.org>
 
         Reviewed by Csaba Osztrogonác.
diff --git a/WebKit2/Shared/BackingStore.h b/WebKit2/Shared/BackingStore.h
index bf00519..435cfd3 100644
--- a/WebKit2/Shared/BackingStore.h
+++ b/WebKit2/Shared/BackingStore.h
@@ -62,9 +62,10 @@ public:
 
     // Create a graphics context that can be used to paint into the backing store.
     PassOwnPtr<WebCore::GraphicsContext> createGraphicsContext();
+    PassOwnPtr<WebCore::GraphicsContext> createFlippedGraphicsContext();
 
     // Paint the backing store into the given context.
-    void paint(WebCore::GraphicsContext*, const WebCore::IntRect&);
+    void paint(WebCore::GraphicsContext&, const WebCore::IntPoint& dstPoint, const WebCore::IntRect& srcRect);
 
 private:
     BackingStore(const WebCore::IntSize&, void*);
diff --git a/WebKit2/Shared/PlatformPopupMenuData.cpp b/WebKit2/Shared/PlatformPopupMenuData.cpp
new file mode 100644
index 0000000..0a3f6ef
--- /dev/null
+++ b/WebKit2/Shared/PlatformPopupMenuData.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 "PlatformPopupMenuData.h"
+
+#include "WebCoreArgumentCoders.h"
+
+namespace WebKit {
+
+PlatformPopupMenuData::PlatformPopupMenuData()
+#if PLATFORM(WIN)
+    : m_clientPaddingLeft(0)
+    , m_clientPaddingRight(0)
+    , m_clientInsetLeft(0)
+    , m_clientInsetRight(0)
+    , m_popupWidth(0)
+    , m_itemHeight(0)
+#endif
+{
+}
+
+void PlatformPopupMenuData::encode(CoreIPC::ArgumentEncoder* encoder) const
+{
+#if PLATFORM(WIN)
+    encoder->encode(m_clientPaddingLeft);
+    encoder->encode(m_clientPaddingRight);
+    encoder->encode(m_clientInsetLeft);
+    encoder->encode(m_clientInsetRight);
+    encoder->encode(m_popupWidth);
+    encoder->encode(m_itemHeight);
+    encoder->encode(m_backingStoreSize);
+
+    SharedMemory::Handle notSelectedBackingStoreHandle;
+    m_notSelectedBackingStore->createHandle(notSelectedBackingStoreHandle);
+    encoder->encode(notSelectedBackingStoreHandle);
+
+    SharedMemory::Handle selectedBackingStoreHandle;
+    m_selectedBackingStore->createHandle(selectedBackingStoreHandle);
+    encoder->encode(selectedBackingStoreHandle);
+#endif
+}
+
+bool PlatformPopupMenuData::decode(CoreIPC::ArgumentDecoder* decoder, PlatformPopupMenuData& data)
+{
+#if PLATFORM(WIN)
+    PlatformPopupMenuData d;
+    if (!decoder->decode(d.m_clientPaddingLeft))
+        return false;
+    if (!decoder->decode(d.m_clientPaddingRight))
+        return false;
+    if (!decoder->decode(d.m_clientInsetLeft))
+        return false;
+    if (!decoder->decode(d.m_clientInsetRight))
+        return false;
+    if (!decoder->decode(d.m_popupWidth))
+        return false;
+    if (!decoder->decode(d.m_itemHeight))
+        return false;
+    if (!decoder->decode(d.m_backingStoreSize))
+        return false;
+
+    SharedMemory::Handle notSelectedBackingStoreHandle;
+    if (!decoder->decode(notSelectedBackingStoreHandle))
+        return false;
+    d.m_notSelectedBackingStore = BackingStore::create(d.m_backingStoreSize, notSelectedBackingStoreHandle);
+
+    SharedMemory::Handle selectedBackingStoreHandle;
+    if (!decoder->decode(selectedBackingStoreHandle))
+        return false;
+    d.m_selectedBackingStore = BackingStore::create(d.m_backingStoreSize, selectedBackingStoreHandle);
+
+    data = d;
+#endif
+    return true;
+}
+
+} // namespace WebKit
diff --git a/WebKit2/Shared/PlatformPopupMenuData.h b/WebKit2/Shared/PlatformPopupMenuData.h
new file mode 100644
index 0000000..6f743da
--- /dev/null
+++ b/WebKit2/Shared/PlatformPopupMenuData.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#ifndef PlatformPopupMenuData_h
+#define PlatformPopupMenuData_h
+
+#include "BackingStore.h"
+#include <wtf/text/WTFString.h>
+
+namespace CoreIPC {
+    class ArgumentDecoder;
+    class ArgumentEncoder;
+}
+
+namespace WebKit {
+
+struct PlatformPopupMenuData {
+    PlatformPopupMenuData();
+    
+    void encode(CoreIPC::ArgumentEncoder*) const;
+    static bool decode(CoreIPC::ArgumentDecoder*, PlatformPopupMenuData&);
+
+#if PLATFORM(WIN)
+    int m_clientPaddingLeft;
+    int m_clientPaddingRight;
+    int m_clientInsetLeft;
+    int m_clientInsetRight;
+    int m_popupWidth;
+    int m_itemHeight;
+    WebCore::IntSize m_backingStoreSize;
+    RefPtr<BackingStore> m_notSelectedBackingStore;
+    RefPtr<BackingStore> m_selectedBackingStore;
+#endif
+};
+
+} // namespace WebKit
+
+#endif // PlatformPopupMenuData_h
diff --git a/WebKit2/Shared/WebPopupItem.cpp b/WebKit2/Shared/WebPopupItem.cpp
index f691cd8..3a5f178 100644
--- a/WebKit2/Shared/WebPopupItem.cpp
+++ b/WebKit2/Shared/WebPopupItem.cpp
@@ -39,21 +39,23 @@ WebPopupItem::WebPopupItem()
 WebPopupItem::WebPopupItem(Type type)
     : m_type(type)
     , m_isEnabled(true)
+    , m_isLabel(false)
 {
 }
 
-WebPopupItem::WebPopupItem(Type type, const String& text, const String& toolTip, const String& accessibilityText, bool isEnabled)
+WebPopupItem::WebPopupItem(Type type, const String& text, const String& toolTip, const String& accessibilityText, bool isEnabled, bool isLabel)
     : m_type(type)
     , m_text(text)
     , m_toolTip(toolTip)
     , m_accessibilityText(accessibilityText)
     , m_isEnabled(isEnabled)
+    , m_isLabel(isLabel)
 {
 }
 
 void WebPopupItem::encode(CoreIPC::ArgumentEncoder* encoder) const
 {
-    encoder->encode(CoreIPC::In(static_cast<uint32_t>(m_type), m_text, m_toolTip, m_accessibilityText, m_isEnabled));
+    encoder->encode(CoreIPC::In(static_cast<uint32_t>(m_type), m_text, m_toolTip, m_accessibilityText, m_isEnabled, m_isLabel));
 }
 
 bool WebPopupItem::decode(CoreIPC::ArgumentDecoder* decoder, WebPopupItem& item)
@@ -63,10 +65,11 @@ bool WebPopupItem::decode(CoreIPC::ArgumentDecoder* decoder, WebPopupItem& item)
     String toolTip;
     String accessibilityText;
     bool isEnabled;
-    if (!decoder->decode(CoreIPC::Out(type, text, toolTip, accessibilityText, isEnabled)))
+    bool isLabel;
+    if (!decoder->decode(CoreIPC::Out(type, text, toolTip, accessibilityText, isEnabled, isLabel)))
         return false;
 
-    item = WebPopupItem(static_cast<Type>(type), text, toolTip, accessibilityText, isEnabled);
+    item = WebPopupItem(static_cast<Type>(type), text, toolTip, accessibilityText, isEnabled, isLabel);
     return true;
 }
 
diff --git a/WebKit2/Shared/WebPopupItem.h b/WebKit2/Shared/WebPopupItem.h
index 9448bc0..c6874f8 100644
--- a/WebKit2/Shared/WebPopupItem.h
+++ b/WebKit2/Shared/WebPopupItem.h
@@ -43,7 +43,7 @@ struct WebPopupItem {
 
     WebPopupItem();
     WebPopupItem(Type);
-    WebPopupItem(Type, const String& text, const String& toolTip, const String& accessibilityText, bool isEnabled);
+    WebPopupItem(Type, const String& text, const String& toolTip, const String& accessibilityText, bool isEnabled, bool m_isLabel);
 
     void encode(CoreIPC::ArgumentEncoder*) const;
     static bool decode(CoreIPC::ArgumentDecoder*, WebPopupItem&);
@@ -53,6 +53,7 @@ struct WebPopupItem {
     String m_toolTip;
     String m_accessibilityText;
     bool m_isEnabled;
+    bool m_isLabel;
 };
 
 } // namespace WebKit
diff --git a/WebKit2/Shared/cg/BackingStoreCG.cpp b/WebKit2/Shared/cg/BackingStoreCG.cpp
index f2c6db6..8bc21fd 100644
--- a/WebKit2/Shared/cg/BackingStoreCG.cpp
+++ b/WebKit2/Shared/cg/BackingStoreCG.cpp
@@ -45,18 +45,28 @@ PassOwnPtr<GraphicsContext> BackingStore::createGraphicsContext()
     return adoptPtr(new GraphicsContext(bitmapContext.get()));
 }
 
-void BackingStore::paint(WebCore::GraphicsContext* context, const WebCore::IntRect& clipRect)
+PassOwnPtr<GraphicsContext> BackingStore::createFlippedGraphicsContext()
+{
+    RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+    RetainPtr<CGContextRef> bitmapContext(AdoptCF, CGBitmapContextCreate(data(), m_size.width(), m_size.height(), 8,  m_size.width() * 4, colorSpace.get(), 
+                                                                         kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
+
+    return adoptPtr(new GraphicsContext(bitmapContext.get()));
+}
+
+void BackingStore::paint(WebCore::GraphicsContext& context, const WebCore::IntPoint& dstPoint, const WebCore::IntRect& srcRect)
 {
-    // FIXME: Honor the clip rect!
     OwnPtr<GraphicsContext> sourceContext(createGraphicsContext());
 
     // FIXME: This creates an extra copy.
     RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(sourceContext->platformContext()));
 
-    CGContextRef cgContext = context->platformContext();
+    CGContextRef cgContext = context.platformContext();
     
     CGContextSaveGState(cgContext);
-    CGContextDrawImage(context->platformContext(), CGRectMake(0, 0, CGImageGetWidth(image.get()), CGImageGetHeight(image.get())), image.get());
+    CGContextClipToRect(cgContext, CGRectMake(dstPoint.x(), dstPoint.y(), srcRect.width(), srcRect.height()));
+    CGContextTranslateCTM(cgContext, -srcRect.x(), -srcRect.y());
+    CGContextDrawImage(cgContext, CGRectMake(dstPoint.x(), dstPoint.y(), CGImageGetWidth(image.get()), CGImageGetHeight(image.get())), image.get());
     CGContextRestoreGState(cgContext);
 }
         
diff --git a/WebKit2/Shared/qt/BackingStoreQt.cpp b/WebKit2/Shared/qt/BackingStoreQt.cpp
index c493449..105c5e5 100644
--- a/WebKit2/Shared/qt/BackingStoreQt.cpp
+++ b/WebKit2/Shared/qt/BackingStoreQt.cpp
@@ -38,7 +38,13 @@ PassOwnPtr<GraphicsContext> BackingStore::createGraphicsContext()
     return 0;
 }
 
-void BackingStore::paint(WebCore::GraphicsContext* context, const WebCore::IntRect& clipRect)
+PassOwnPtr<GraphicsContext> BackingStore::createFlippedGraphicsContext()
+{
+    notImplemented();
+    return 0;
+}
+
+void BackingStore::paint(GraphicsContext&, const IntPoint&, const IntRect&)
 {
     notImplemented();
 }
diff --git a/WebKit2/UIProcess/FindIndicator.cpp b/WebKit2/UIProcess/FindIndicator.cpp
index 59d5546..159e3f0 100644
--- a/WebKit2/UIProcess/FindIndicator.cpp
+++ b/WebKit2/UIProcess/FindIndicator.cpp
@@ -167,7 +167,7 @@ void FindIndicator::draw(GraphicsContext& graphicsContext, const IntRect& dirtyR
         graphicsContext.save();
         graphicsContext.translate(FloatSize(roundf(leftBorderThickness), roundf(topBorderThickness) + m_contentImage->bounds().height()));
         graphicsContext.scale(FloatSize(1, -1));
-        m_contentImage->paint(&graphicsContext, m_contentImage->bounds());
+        m_contentImage->paint(graphicsContext, IntPoint(0, 0), m_contentImage->bounds());
         graphicsContext.restore();
     }
 }
diff --git a/WebKit2/UIProcess/WebPageProxy.cpp b/WebKit2/UIProcess/WebPageProxy.cpp
index 89f27fe..3ce925a 100644
--- a/WebKit2/UIProcess/WebPageProxy.cpp
+++ b/WebKit2/UIProcess/WebPageProxy.cpp
@@ -1121,7 +1121,7 @@ void WebPageProxy::didFailToFindString(const String& string)
     m_findClient.didFailToFindString(this, string);
 }
 
-void WebPageProxy::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex)
+void WebPageProxy::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData& data)
 {
     if (m_activePopupMenu)
         m_activePopupMenu->hidePopupMenu();
@@ -1129,7 +1129,7 @@ void WebPageProxy::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>
         m_activePopupMenu = m_pageClient->createPopupMenuProxy();
 
     int32_t newSelectedIndex = 0;
-    m_activePopupMenu->showPopupMenu(rect, items, selectedIndex, newSelectedIndex);
+    m_activePopupMenu->showPopupMenu(rect, items, data, selectedIndex, newSelectedIndex);
 
     process()->send(Messages::WebPage::DidChangeSelectedIndexForActivePopupMenu(newSelectedIndex), m_pageID);
     m_activePopupMenu = 0;
diff --git a/WebKit2/UIProcess/WebPageProxy.h b/WebKit2/UIProcess/WebPageProxy.h
index 755d2af..83ca536 100644
--- a/WebKit2/UIProcess/WebPageProxy.h
+++ b/WebKit2/UIProcess/WebPageProxy.h
@@ -88,6 +88,7 @@ class WebPopupMenuProxy;
 class WebProcessProxy;
 class WebURLRequest;
 class WebWheelEvent;
+struct PlatformPopupMenuData;
 struct WebNavigationDataStore;
 struct WebPageCreationParameters;
 struct WebPopupItem;
@@ -327,7 +328,7 @@ private:
     void didFailToFindString(const String&);
 
     // Popup Menu.
-    void showPopupMenu(const WebCore::IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex);
+    void showPopupMenu(const WebCore::IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex, const PlatformPopupMenuData&);
     void hidePopupMenu();
 
     // Context Menu.
diff --git a/WebKit2/UIProcess/WebPageProxy.messages.in b/WebKit2/UIProcess/WebPageProxy.messages.in
index a97cd23..1065432 100644
--- a/WebKit2/UIProcess/WebPageProxy.messages.in
+++ b/WebKit2/UIProcess/WebPageProxy.messages.in
@@ -123,7 +123,7 @@ messages -> WebPageProxy {
     DidFailToFindString(WTF::String string)
 
     # PopupMenu.
-    ShowPopupMenu(WebCore::IntRect rect, Vector<WebKit::WebPopupItem> items, int32_t selectedIndex)
+    ShowPopupMenu(WebCore::IntRect rect, Vector<WebKit::WebPopupItem> items, int32_t selectedIndex, WebKit::PlatformPopupMenuData data)
     HidePopupMenu()
     
     # ContextMenu
diff --git a/WebKit2/UIProcess/WebPopupMenuProxy.h b/WebKit2/UIProcess/WebPopupMenuProxy.h
index 2f3a82d..5b28efb 100644
--- a/WebKit2/UIProcess/WebPopupMenuProxy.h
+++ b/WebKit2/UIProcess/WebPopupMenuProxy.h
@@ -36,6 +36,7 @@ namespace WebCore {
 
 namespace WebKit {
 
+struct PlatformPopupMenuData;
 struct WebPopupItem;
 
 class WebPopupMenuProxy : public RefCounted<WebPopupMenuProxy> {
@@ -44,7 +45,7 @@ public:
     {
     }
 
-    virtual void showPopupMenu(const WebCore::IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex, int32_t& newSelectedIndex) = 0;
+    virtual void showPopupMenu(const WebCore::IntRect& rect, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex, int32_t& newSelectedIndex) = 0;
     virtual void hidePopupMenu() = 0;
 
 protected:
diff --git a/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.h b/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.h
index 5723b82..6834c6d 100644
--- a/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.h
+++ b/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.h
@@ -49,7 +49,7 @@ public:
     }
     ~WebPopupMenuProxyMac();
 
-    virtual void showPopupMenu(const WebCore::IntRect&, const Vector<WebPopupItem>&, int32_t selectedIndex, int32_t& newSelectedIndex);
+    virtual void showPopupMenu(const WebCore::IntRect&, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex, int32_t& newSelectedIndex);
     virtual void hidePopupMenu();
 
 private:
diff --git a/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm b/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm
index eb3790f..f15c01d 100644
--- a/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm
+++ b/WebKit2/UIProcess/mac/WebPopupMenuProxyMac.mm
@@ -26,6 +26,7 @@
 #include "WebPopupMenuProxyMac.h"
 
 #include "PageClientImpl.h"
+#include "PlatformPopupMenuData.h"
 #include "WKView.h"
 #include "WebPopupItem.h"
 #include <WebKitSystemInterface.h>
@@ -69,7 +70,7 @@ void WebPopupMenuProxyMac::populate(const Vector<WebPopupItem>& items)
     }
 }
 
-void WebPopupMenuProxyMac::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex, int32_t& newSelectedIndex)
+void WebPopupMenuProxyMac::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex, int32_t& newSelectedIndex)
 {
     populate(items);
 
diff --git a/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp b/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp
index a4e963d..87c0898 100644
--- a/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp
+++ b/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.cpp
@@ -25,6 +25,7 @@
 
 #include "WebPopupMenuProxyQt.h"
 
+#include "PlatformPopupMenuData.h"
 #include "WebPopupItem.h"
 
 using namespace WebCore;
@@ -39,7 +40,7 @@ WebPopupMenuProxyQt::~WebPopupMenuProxyQt()
 {
 }
 
-void WebPopupMenuProxyQt::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex, int32_t& newSelectedIndex)
+void WebPopupMenuProxyQt::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, const PlatformPopupMenuData&, int32_t selectedIndex, int32_t& newSelectedIndex)
 {
 }
 
diff --git a/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h b/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h
index 2d004bd..982f166 100644
--- a/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h
+++ b/WebKit2/UIProcess/qt/WebPopupMenuProxyQt.h
@@ -38,7 +38,7 @@ public:
     }
     ~WebPopupMenuProxyQt();
 
-    virtual void showPopupMenu(const WebCore::IntRect&, const Vector<WebPopupItem>&, int32_t selectedIndex, int32_t& newSelectedIndex);
+    virtual void showPopupMenu(const WebCore::IntRect&, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex, int32_t& newSelectedIndex);
     virtual void hidePopupMenu();
 
 private:
diff --git a/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp b/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp
index 7524b40..601100a 100644
--- a/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp
+++ b/WebKit2/UIProcess/win/WebPopupMenuProxyWin.cpp
@@ -23,28 +23,915 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+// NOTE: This implementation is very similar to the implementation of popups in WebCore::PopupMenuWin.
+// We should try and factor out the common bits and share them.
+
 #include "WebPopupMenuProxyWin.h"
 
-#include "WebPopupItem.h"
+#include "WebView.h"
+#include <WebCore/WebCoreInstanceHandle.h>
+#include <WebCore/ScrollbarTheme.h>
+#include <WebCore/BitmapInfo.h>
+#include <WebCore/PlatformMouseEvent.h>
+#include <windowsx.h>
 
 using namespace WebCore;
+using namespace std;
 
 namespace WebKit {
 
-WebPopupMenuProxyWin::WebPopupMenuProxyWin()
+static const LPCWSTR kWebKit2WebPopupMenuProxyWindowClassName = L"WebKit2WebPopupMenuProxyWindowClass";
+
+static const int defaultAnimationDuration = 200;
+static const int maxPopupHeight = 320;
+static const int popupWindowBorderWidth = 1;
+static const int separatorPadding = 4;
+static const int separatorHeight = 1;
+
+// This is used from within our custom message pump when we want to send a
+// message to the web view and not have our message stolen and sent to
+// the popup window.
+static const UINT WM_HOST_WINDOW_FIRST = WM_USER;
+static const UINT WM_HOST_WINDOW_CHAR = WM_USER + WM_CHAR; 
+static const UINT WM_HOST_WINDOW_MOUSEMOVE = WM_USER + WM_MOUSEMOVE;
+
+static inline bool isASCIIPrintable(unsigned c)
+{
+    return c >= 0x20 && c <= 0x7E;
+}
+
+static void translatePoint(LPARAM& lParam, HWND from, HWND to)
+{
+    POINT pt;
+    pt.x = static_cast<short>(GET_X_LPARAM(lParam));
+    pt.y = static_cast<short>(GET_Y_LPARAM(lParam));
+    ::MapWindowPoints(from, to, &pt, 1);
+    lParam = MAKELPARAM(pt.x, pt.y);
+}
+
+LRESULT CALLBACK WebPopupMenuProxyWin::WebPopupMenuProxyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
+   
+    if (WebPopupMenuProxyWin* popupMenuProxy = reinterpret_cast<WebPopupMenuProxyWin*>(longPtr))
+        return popupMenuProxy->wndProc(hWnd, message, wParam, lParam);
+
+    if (message == WM_CREATE) {
+        LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
+
+        // Associate the WebView with the window.
+        ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
+        return 0;
+    }
+
+    return ::DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+LRESULT WebPopupMenuProxyWin::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+    LRESULT lResult = 0;
+    bool handled = true;
+
+    switch (message) {
+        case WM_MOUSEACTIVATE:
+            lResult = onMouseActivate(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_SIZE:
+            lResult = onSize(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_KEYDOWN:
+            lResult = onKeyDown(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_CHAR:
+            lResult = onChar(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_MOUSEMOVE:
+            lResult = onMouseMove(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_LBUTTONDOWN:
+            lResult = onLButtonDown(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_LBUTTONUP:
+            lResult = onLButtonUp(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_MOUSEWHEEL:
+            lResult = onMouseWheel(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_PAINT:
+            lResult = onPaint(hWnd, message, wParam, lParam, handled);
+            break;
+        case WM_PRINTCLIENT:
+            lResult = onPrintClient(hWnd, message, wParam, lParam, handled);
+            break;
+        default:
+            handled = false;
+            break;
+    }
+
+    if (!handled)
+        lResult = ::DefWindowProc(hWnd, message, wParam, lParam);
+
+    return lResult;
+}
+
+bool WebPopupMenuProxyWin::registerWindowClass()
+{
+    static bool haveRegisteredWindowClass = false;
+    if (haveRegisteredWindowClass)
+        return true;
+    haveRegisteredWindowClass = true;
+
+    WNDCLASSEX wcex;
+    wcex.cbSize         = sizeof(WNDCLASSEX);
+    wcex.style          = CS_DROPSHADOW;
+    wcex.lpfnWndProc    = WebPopupMenuProxyWin::WebPopupMenuProxyWndProc;
+    wcex.cbClsExtra     = 0;
+    wcex.cbWndExtra     = sizeof(WebPopupMenuProxyWin*);
+    wcex.hInstance      = instanceHandle();
+    wcex.hIcon          = 0;
+    wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
+    wcex.hbrBackground  = 0;
+    wcex.lpszMenuName   = 0;
+    wcex.lpszClassName  = kWebKit2WebPopupMenuProxyWindowClassName;
+    wcex.hIconSm        = 0;
+
+    return !!::RegisterClassEx(&wcex);
+}
+
+WebPopupMenuProxyWin::WebPopupMenuProxyWin(WebView* webView)
+    : m_webView(webView)
+    , m_newSelectedIndex(0)
+    , m_popup(0)
+    , m_DC(0)
+    , m_bmp(0)
+    , m_itemHeight(0)
+    , m_scrollOffset(0)
+    , m_wheelDelta(0)
+    , m_focusedIndex(0)
+    , m_wasClicked(false)
+    , m_scrollbarCapturingMouse(false)
+    , m_showPopup(false)
 {
 }
 
 WebPopupMenuProxyWin::~WebPopupMenuProxyWin()
 {
+    if (m_bmp)
+        ::DeleteObject(m_bmp);
+    if (m_DC)
+        ::DeleteDC(m_DC);
+    if (m_popup)
+        ::DestroyWindow(m_popup);
+    if (m_scrollbar)
+        m_scrollbar->setParent(0);
 }
 
-void WebPopupMenuProxyWin::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, int32_t selectedIndex, int32_t& newSelectedIndex)
+void WebPopupMenuProxyWin::showPopupMenu(const IntRect& rect, const Vector<WebPopupItem>& items, const PlatformPopupMenuData& data, int32_t selectedIndex, int32_t& newSelectedIndex)
 {
+    m_items = items;
+    m_data = data;
+    m_newSelectedIndex = selectedIndex;
+
+    calculatePositionAndSize(rect);
+    if (clientRect().isEmpty())
+        return;
+
+    HWND hostWindow = m_webView->window();
+
+    if (!m_scrollbar && visibleItems() < m_items.size()) {
+        m_scrollbar = Scrollbar::createNativeScrollbar(this, VerticalScrollbar, SmallScrollbar);
+        m_scrollbar->styleChanged();
+    }
+
+    if (!m_popup) {
+        registerWindowClass();
+
+        DWORD exStyle = WS_EX_LTRREADING;
+
+        m_popup = ::CreateWindowEx(exStyle, kWebKit2WebPopupMenuProxyWindowClassName, TEXT("PopupMenu"),
+            WS_POPUP | WS_BORDER,
+            m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(),
+            hostWindow, 0, instanceHandle(), this);
+
+        if (!m_popup)
+            return;
+    }
+
+    BOOL shouldAnimate = FALSE;
+    ::SystemParametersInfo(SPI_GETCOMBOBOXANIMATION, 0, &shouldAnimate, 0);
+
+    if (shouldAnimate) {
+        RECT viewRect = {0};
+        ::GetWindowRect(hostWindow, &viewRect);
+
+        if (!::IsRectEmpty(&viewRect)) {
+            // Popups should slide into view away from the <select> box
+            // NOTE: This may have to change for Vista
+            DWORD slideDirection = (m_windowRect.y() < viewRect.top + rect.location().y()) ? AW_VER_NEGATIVE : AW_VER_POSITIVE;
+
+            ::AnimateWindow(m_popup, defaultAnimationDuration, AW_SLIDE | slideDirection);
+        }
+    } else
+        ::ShowWindow(m_popup, SW_SHOWNOACTIVATE);
+
+
+    int index = selectedIndex;
+    if (index >= 0)
+        setFocusedIndex(index);
+
+    m_showPopup = true;
+
+    // Protect the popup menu in case its owner is destroyed while we're running the message pump.
+    RefPtr<WebPopupMenuProxyWin> protect(this);
+
+    ::SetCapture(hostWindow);
+
+    MSG msg;
+    HWND activeWindow;
+
+    while (::GetMessage(&msg, 0, 0, 0)) {
+        switch (msg.message) {
+        case WM_HOST_WINDOW_MOUSEMOVE:
+        case WM_HOST_WINDOW_CHAR: 
+            if (msg.hwnd == m_popup) {
+                // This message should be sent to the host window.
+                msg.hwnd = hostWindow;
+                msg.message -= WM_HOST_WINDOW_FIRST;
+            }
+            break;
+
+        // Steal mouse messages.
+        case WM_NCMOUSEMOVE:
+        case WM_NCLBUTTONDOWN:
+        case WM_NCLBUTTONUP:
+        case WM_NCLBUTTONDBLCLK:
+        case WM_NCRBUTTONDOWN:
+        case WM_NCRBUTTONUP:
+        case WM_NCRBUTTONDBLCLK:
+        case WM_NCMBUTTONDOWN:
+        case WM_NCMBUTTONUP:
+        case WM_NCMBUTTONDBLCLK:
+        case WM_MOUSEWHEEL:
+            msg.hwnd = m_popup;
+            break;
+
+        // These mouse messages use client coordinates so we need to convert them.
+        case WM_MOUSEMOVE:
+        case WM_LBUTTONDOWN:
+        case WM_LBUTTONUP:
+        case WM_LBUTTONDBLCLK:
+        case WM_RBUTTONDOWN:
+        case WM_RBUTTONUP:
+        case WM_RBUTTONDBLCLK:
+        case WM_MBUTTONDOWN:
+        case WM_MBUTTONUP:
+        case WM_MBUTTONDBLCLK: {
+            // Translate the coordinate.
+            translatePoint(msg.lParam, msg.hwnd, m_popup);
+            msg.hwnd = m_popup;
+            break;
+        }
+
+        // Steal all keyboard messages.
+        case WM_KEYDOWN:
+        case WM_KEYUP:
+        case WM_CHAR:
+        case WM_DEADCHAR:
+        case WM_SYSKEYUP:
+        case WM_SYSCHAR:
+        case WM_SYSDEADCHAR:
+            msg.hwnd = m_popup;
+            break;
+        }
+
+        ::TranslateMessage(&msg);
+        ::DispatchMessage(&msg);
+
+        if (!m_showPopup)
+            break;
+        activeWindow = ::GetActiveWindow();
+        if (activeWindow != hostWindow && !::IsChild(activeWindow, hostWindow))
+            break;
+        if (::GetCapture() != hostWindow)
+            break;
+    }
+
+    if (::GetCapture() == hostWindow)
+        ::ReleaseCapture();
+
+    m_showPopup = false;
+    ::ShowWindow(m_popup, SW_HIDE);
+
+    newSelectedIndex = m_newSelectedIndex;
 }
 
 void WebPopupMenuProxyWin::hidePopupMenu()
 {
+    if (!m_showPopup)
+        return;
+    m_showPopup = false;
+
+    ::ShowWindow(m_popup, SW_HIDE);
+
+    // Post a WM_NULL message to wake up the message pump if necessary.
+    ::PostMessage(m_popup, WM_NULL, 0, 0);
+}
+
+void WebPopupMenuProxyWin::calculatePositionAndSize(const IntRect& rect)
+{
+    // Convert the rect (which is in view cooridates) into screen coordinates.
+    IntRect rectInScreenCoords = rect;
+    POINT location(rectInScreenCoords .location());
+    if (!::ClientToScreen(m_webView->window(), &location))
+        return;
+    rectInScreenCoords.setLocation(location);
+
+    int itemCount = m_items.size();
+    m_itemHeight = m_data.m_itemHeight;
+
+    int naturalHeight = m_itemHeight * itemCount;
+    int popupHeight = min(maxPopupHeight, naturalHeight);
+
+    // The popup should show an integral number of items (i.e. no partial items should be visible)
+    popupHeight -= popupHeight % m_itemHeight;
+
+    // Next determine its width
+    int popupWidth = m_data.m_popupWidth;
+
+    if (naturalHeight > maxPopupHeight) {
+        // We need room for a scrollbar
+        popupWidth += ScrollbarTheme::nativeTheme()->scrollbarThickness(SmallScrollbar);
+    }
+
+    popupHeight += 2 * popupWindowBorderWidth;
+
+    // The popup should be at least as wide as the control on the page
+    popupWidth = max(rectInScreenCoords.width() - m_data.m_clientInsetLeft - m_data.m_clientInsetRight, popupWidth);
+
+    // Always left-align items in the popup.  This matches popup menus on the mac.
+    int popupX = rectInScreenCoords.x() + m_data.m_clientInsetLeft;
+
+    IntRect popupRect(popupX, rectInScreenCoords.bottom(), popupWidth, popupHeight);
+
+    // The popup needs to stay within the bounds of the screen and not overlap any toolbars
+    HMONITOR monitor = ::MonitorFromWindow(m_webView->window(), MONITOR_DEFAULTTOPRIMARY);
+    MONITORINFOEX monitorInfo;
+    monitorInfo.cbSize = sizeof(MONITORINFOEX);
+    ::GetMonitorInfo(monitor, &monitorInfo);
+    FloatRect screen = monitorInfo.rcWork;
+
+    // Check that we don't go off the screen vertically
+    if (popupRect.bottom() > screen.height()) {
+        // The popup will go off the screen, so try placing it above the client
+        if (rectInScreenCoords.y() - popupRect.height() < 0) {
+            // The popup won't fit above, either, so place it whereever's bigger and resize it to fit
+            if ((rectInScreenCoords.y() + rectInScreenCoords.height() / 2) < (screen.height() / 2)) {
+                // Below is bigger
+                popupRect.setHeight(screen.height() - popupRect.y());
+            } else {
+                // Above is bigger
+                popupRect.setY(0);
+                popupRect.setHeight(rectInScreenCoords.y());
+            }
+        } else {
+            // The popup fits above, so reposition it
+            popupRect.setY(rectInScreenCoords.y() - popupRect.height());
+        }
+    }
+
+    // Check that we don't go off the screen horizontally
+    if (popupRect.x() < screen.x()) {
+        popupRect.setWidth(popupRect.width() - (screen.x() - popupRect.x()));
+        popupRect.setX(screen.x());
+    }
+
+    m_windowRect = popupRect;
+}
+
+IntRect WebPopupMenuProxyWin::clientRect() const
+{
+    IntRect clientRect = m_windowRect;
+    clientRect.inflate(-popupWindowBorderWidth);
+    clientRect.setLocation(IntPoint(0, 0));
+    return clientRect;
+}
+
+void WebPopupMenuProxyWin::invalidateItem(int index)
+{
+    if (!m_popup)
+        return;
+
+    IntRect damageRect(clientRect());
+    damageRect.setY(m_itemHeight * (index - m_scrollOffset));
+    damageRect.setHeight(m_itemHeight);
+    if (m_scrollbar)
+        damageRect.setWidth(damageRect.width() - m_scrollbar->frameRect().width());
+
+    RECT r = damageRect;
+    ::InvalidateRect(m_popup, &r, TRUE);
+}
+
+// ScrollbarClient
+
+int WebPopupMenuProxyWin::scrollSize(ScrollbarOrientation orientation) const
+{
+    return ((orientation == VerticalScrollbar) && m_scrollbar) ? (m_scrollbar->totalSize() - m_scrollbar->visibleSize()) : 0;
+}
+
+void WebPopupMenuProxyWin::setScrollOffsetFromAnimation(const IntPoint& offset)
+{
+    if (m_scrollbar)
+        m_scrollbar->setValue(offset.y(), Scrollbar::FromScrollAnimator);
+}
+
+void WebPopupMenuProxyWin::valueChanged(Scrollbar* scrollBar)
+{
+    ASSERT(m_scrollbar);
+
+    if (!m_popup)
+        return;
+
+    int offset = scrollBar->value();
+
+    if (m_scrollOffset == offset)
+        return;
+
+    int scrolledLines = m_scrollOffset - offset;
+    m_scrollOffset = offset;
+
+    UINT flags = SW_INVALIDATE;
+
+#ifdef CAN_SET_SMOOTH_SCROLLING_DURATION
+    BOOL shouldSmoothScroll = FALSE;
+    ::SystemParametersInfo(SPI_GETLISTBOXSMOOTHSCROLLING, 0, &shouldSmoothScroll, 0);
+    if (shouldSmoothScroll)
+        flags |= MAKEWORD(SW_SMOOTHSCROLL, smoothScrollAnimationDuration);
+#endif
+
+    IntRect listRect = clientRect();
+    if (m_scrollbar)
+        listRect.setWidth(listRect.width() - m_scrollbar->frameRect().width());
+    RECT r = listRect;
+    ::ScrollWindowEx(m_popup, 0, scrolledLines * m_itemHeight, &r, 0, 0, 0, flags);
+    if (m_scrollbar) {
+        r = m_scrollbar->frameRect();
+        ::InvalidateRect(m_popup, &r, TRUE);
+    }
+    ::UpdateWindow(m_popup);
+}
+
+void WebPopupMenuProxyWin::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
+{
+    IntRect scrollRect = rect;
+    scrollRect.move(scrollbar->x(), scrollbar->y());
+    RECT r = scrollRect;
+    ::InvalidateRect(m_popup, &r, false);
+}
+
+// Message pump messages.
+
+LRESULT WebPopupMenuProxyWin::onMouseActivate(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled)
+{
+    handled = true;
+    return MA_NOACTIVATE;
+}
+
+LRESULT WebPopupMenuProxyWin::onSize(HWND hWnd, UINT message, WPARAM, LPARAM lParam, bool& handled)
+{
+    handled = true;
+    if (!scrollbar())
+        return 0;
+
+    IntSize size(LOWORD(lParam), HIWORD(lParam));
+    scrollbar()->setFrameRect(IntRect(size.width() - scrollbar()->width(), 0, scrollbar()->width(), size.height()));
+
+    int visibleItems = this->visibleItems();
+    scrollbar()->setEnabled(visibleItems < m_items.size());
+    scrollbar()->setSteps(1, max(1, visibleItems - 1));
+    scrollbar()->setProportion(visibleItems, m_items.size());
+    return 0;
+}
+
+LRESULT WebPopupMenuProxyWin::onKeyDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
+{
+    handled = true;
+
+    LRESULT lResult = 0;
+    switch (LOWORD(wParam)) {
+    case VK_DOWN:
+    case VK_RIGHT:
+        down();
+        break;
+    case VK_UP:
+    case VK_LEFT:
+        up();
+        break;
+    case VK_HOME:
+        focusFirst();
+        break;
+    case VK_END:
+        focusLast();
+        break;
+    case VK_PRIOR:
+        if (focusedIndex() != scrollOffset()) {
+            // Set the selection to the first visible item
+            int firstVisibleItem = scrollOffset();
+            up(focusedIndex() - firstVisibleItem);
+        } else {
+            // The first visible item is selected, so move the selection back one page
+            up(visibleItems());
+        }
+        break;
+    case VK_NEXT: {
+        int lastVisibleItem = scrollOffset() + visibleItems() - 1;
+        if (focusedIndex() != lastVisibleItem) {
+            // Set the selection to the last visible item
+            down(lastVisibleItem - focusedIndex());
+        } else {
+            // The last visible item is selected, so move the selection forward one page
+            down(visibleItems());
+        }
+        break;
+    }
+    case VK_TAB:
+        ::SendMessage(m_webView->window(), message, wParam, lParam);
+        hide();
+        break;
+    case VK_ESCAPE:
+        hide();
+        break;
+    default:
+        if (isASCIIPrintable(wParam)) {
+            // Send the keydown to the WebView so it can be used for type-to-select.
+            // Since we know that the virtual key is ASCII printable, it's OK to convert this to
+            // a WM_CHAR message. (We don't want to call TranslateMessage because that will post a
+            // WM_CHAR message that will be stolen and redirected to the popup HWND.
+            ::PostMessage(m_popup, WM_HOST_WINDOW_CHAR, wParam, lParam);
+        } else
+            lResult = 1;
+        break;
+    }
+
+    return lResult;
+}
+
+LRESULT WebPopupMenuProxyWin::onChar(HWND hWnd, UINT message, WPARAM wParam, LPARAM, bool& handled)
+{
+    handled = true;
+
+    LRESULT lResult = 0;
+    int index;
+    switch (wParam) {
+    case 0x0D:   // Enter/Return
+        hide();
+        index = focusedIndex();
+        ASSERT(index >= 0);
+        // FIXME: Do we need to send back the index right away?
+        m_newSelectedIndex = index;
+        break;
+    case 0x1B:   // Escape
+        hide();
+        break;
+    case 0x09:   // TAB
+    case 0x08:   // Backspace
+    case 0x0A:   // Linefeed
+    default:     // Character
+        lResult = 1;
+        break;
+    }
+
+    return lResult;
+}
+
+LRESULT WebPopupMenuProxyWin::onMouseMove(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
+{
+    handled = true;
+
+    IntPoint mousePoint(MAKEPOINTS(lParam));
+    if (scrollbar()) {
+        IntRect scrollBarRect = scrollbar()->frameRect();
+        if (scrollbarCapturingMouse() || scrollBarRect.contains(mousePoint)) {
+            // Put the point into coordinates relative to the scroll bar
+            mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y());
+            PlatformMouseEvent event(hWnd, message, wParam, MAKELPARAM(mousePoint.x(), mousePoint.y()));
+            scrollbar()->mouseMoved(event);
+            return 0;
+        }
+    }
+
+    BOOL shouldHotTrack = FALSE;
+    ::SystemParametersInfo(SPI_GETHOTTRACKING, 0, &shouldHotTrack, 0);
+
+    RECT bounds;
+    ::GetClientRect(m_popup, &bounds);
+    if (!::PtInRect(&bounds, mousePoint) && !(wParam & MK_LBUTTON)) {
+        // When the mouse is not inside the popup menu and the left button isn't down, just
+        // repost the message to the web view.
+
+        // Translate the coordinate.
+        translatePoint(lParam, m_popup, m_webView->window());
+
+        ::PostMessage(m_popup, WM_HOST_WINDOW_MOUSEMOVE, wParam, lParam);
+        return 0;
+    }
+
+    if ((shouldHotTrack || wParam & MK_LBUTTON) && ::PtInRect(&bounds, mousePoint))
+        setFocusedIndex(listIndexAtPoint(mousePoint), true);
+
+    return 0;
+}
+
+LRESULT WebPopupMenuProxyWin::onLButtonDown(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
+{
+    handled = true;
+
+    IntPoint mousePoint(MAKEPOINTS(lParam));
+    if (scrollbar()) {
+        IntRect scrollBarRect = scrollbar()->frameRect();
+        if (scrollBarRect.contains(mousePoint)) {
+            // Put the point into coordinates relative to the scroll bar
+            mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y());
+            PlatformMouseEvent event(hWnd, message, wParam, MAKELPARAM(mousePoint.x(), mousePoint.y()));
+            scrollbar()->mouseDown(event);
+            setScrollbarCapturingMouse(true);
+            return 0;
+        }
+    }
+
+    // If the mouse is inside the window, update the focused index. Otherwise, 
+    // hide the popup.
+    RECT bounds;
+    ::GetClientRect(m_popup, &bounds);
+    if (::PtInRect(&bounds, mousePoint))
+        setFocusedIndex(listIndexAtPoint(mousePoint), true);
+    else
+        hide();
+
+    return 0;
+}
+
+
+LRESULT WebPopupMenuProxyWin::onLButtonUp(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, bool& handled)
+{
+    handled = true;
+
+    IntPoint mousePoint(MAKEPOINTS(lParam));
+    if (scrollbar()) {
+        IntRect scrollBarRect = scrollbar()->frameRect();
+        if (scrollbarCapturingMouse() || scrollBarRect.contains(mousePoint)) {
+            setScrollbarCapturingMouse(false);
+            // Put the point into coordinates relative to the scroll bar
+            mousePoint.move(-scrollBarRect.x(), -scrollBarRect.y());
+            PlatformMouseEvent event(hWnd, message, wParam, MAKELPARAM(mousePoint.x(), mousePoint.y()));
+            scrollbar()->mouseUp();
+            // FIXME: This is a hack to work around Scrollbar not invalidating correctly when it doesn't have a parent widget
+            RECT r = scrollBarRect;
+            ::InvalidateRect(m_popup, &r, TRUE);
+            return 0;
+        }
+    }
+    // Only hide the popup if the mouse is inside the popup window.
+    RECT bounds;
+    ::GetClientRect(m_popup, &bounds);
+    if (::PtInRect(&bounds, mousePoint)) {
+        hide();
+        int index = focusedIndex();
+        if (index >= 0) {
+            // FIXME: Do we need to send back the index right away?
+             m_newSelectedIndex = index;
+        }
+    }
+
+    return 0;
+}
+
+LRESULT WebPopupMenuProxyWin::onMouseWheel(HWND hWnd, UINT message, WPARAM wParam, LPARAM, bool& handled)
+{
+    handled = true;
+
+    if (!scrollbar())
+        return 0;
+
+    int i = 0;
+    for (incrementWheelDelta(GET_WHEEL_DELTA_WPARAM(wParam)); abs(wheelDelta()) >= WHEEL_DELTA; reduceWheelDelta(WHEEL_DELTA)) {
+        if (wheelDelta() > 0)
+            ++i;
+        else
+            --i;
+    }
+    scrollbar()->scroll(i > 0 ? ScrollUp : ScrollDown, ScrollByLine, abs(i));
+    return 0;
+}
+
+LRESULT WebPopupMenuProxyWin::onPaint(HWND hWnd, UINT message, WPARAM, LPARAM, bool& handled)
+{
+    handled = true;
+
+    PAINTSTRUCT paintStruct;
+    ::BeginPaint(m_popup, &paintStruct);
+    paint(paintStruct.rcPaint, paintStruct.hdc);
+    ::EndPaint(m_popup, &paintStruct);
+
+    return 0;
+}
+
+LRESULT WebPopupMenuProxyWin::onPrintClient(HWND hWnd, UINT, WPARAM wParam, LPARAM, bool& handled)
+{
+    handled = true;
+
+    HDC hdc = reinterpret_cast<HDC>(wParam);
+    paint(clientRect(), hdc);
+
+    return 0;
+}
+
+bool WebPopupMenuProxyWin::down(unsigned lines)
+{
+    int size = m_items.size();
+
+    int lastSelectableIndex, selectedListIndex;
+    lastSelectableIndex = selectedListIndex = focusedIndex();
+    for (int i = selectedListIndex + 1; i >= 0 && i < size; ++i) {
+        if (m_items[i].m_isEnabled) {
+            lastSelectableIndex = i;
+            if (i >= selectedListIndex + (int)lines)
+                break;
+        }
+    }
+
+    return setFocusedIndex(lastSelectableIndex);
+}
+
+bool WebPopupMenuProxyWin::up(unsigned lines)
+{
+    int size = m_items.size();
+
+    int lastSelectableIndex, selectedListIndex;
+    lastSelectableIndex = selectedListIndex = focusedIndex();
+    for (int i = selectedListIndex - 1; i >= 0 && i < size; --i) {
+        if (m_items[i].m_isEnabled) {
+            lastSelectableIndex = i;
+            if (i <= selectedListIndex - (int)lines)
+                break;
+        }
+    }
+
+    return setFocusedIndex(lastSelectableIndex);
+}
+
+void WebPopupMenuProxyWin::paint(const IntRect& damageRect, HDC hdc)
+{
+    if (!m_popup)
+        return;
+
+    if (!m_DC) {
+        m_DC = ::CreateCompatibleDC(::GetDC(m_popup));
+        if (!m_DC)
+            return;
+    }
+
+    if (m_bmp) {
+        bool keepBitmap = false;
+        BITMAP bitmap;
+        if (::GetObject(m_bmp, sizeof(bitmap), &bitmap))
+            keepBitmap = bitmap.bmWidth == clientRect().width() && bitmap.bmHeight == clientRect().height();
+        if (!keepBitmap) {
+            ::DeleteObject(m_bmp);
+            m_bmp = 0;
+        }
+    }
+
+    if (!m_bmp) {
+        BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(clientRect().size());
+        void* pixels = 0;
+        m_bmp = ::CreateDIBSection(m_DC, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
+        if (!m_bmp)
+            return;
+        ::SelectObject(m_DC, m_bmp);
+    }
+
+    GraphicsContext context(m_DC);
+
+    IntRect translatedDamageRect = damageRect;
+    translatedDamageRect.move(IntSize(0, m_scrollOffset * m_itemHeight));
+    m_data.m_notSelectedBackingStore->paint(context, damageRect.location(), translatedDamageRect);
+
+    IntRect selectedIndexRectInBackingStore(0, focusedIndex() * m_itemHeight, m_data.m_popupWidth, m_itemHeight);
+    IntPoint selectedIndexDstPoint = selectedIndexRectInBackingStore.location();
+    selectedIndexDstPoint.move(0, -m_scrollOffset * m_itemHeight);
+
+    m_data.m_selectedBackingStore->paint(context, selectedIndexDstPoint, selectedIndexRectInBackingStore);
+
+    if (m_scrollbar)
+        m_scrollbar->paint(&context, damageRect);
+
+    HDC localDC = hdc ? hdc : ::GetDC(m_popup);
+
+    ::BitBlt(localDC, damageRect.x(), damageRect.y(), damageRect.width(), damageRect.height(), m_DC, damageRect.x(), damageRect.y(), SRCCOPY);
+
+    if (!hdc)
+        ::ReleaseDC(m_popup, localDC);
+}
+
+bool WebPopupMenuProxyWin::setFocusedIndex(int i, bool hotTracking)
+{
+    if (i < 0 || i >= m_items.size() || i == focusedIndex())
+        return false;
+
+    if (!m_items[i].m_isEnabled)
+        return false;
+
+    invalidateItem(focusedIndex());
+    invalidateItem(i);
+
+    m_focusedIndex = i;
+
+    // FIXME: If we are not hotTracking, we need to send a message back to the WebProcess to
+    // call the popupMenuClient's setTextFromItem function of this index.  This will update
+    // the currently displayed item at the top of the list.
+
+    if (!scrollToRevealSelection())
+        ::UpdateWindow(m_popup);
+
+    return true;
+}
+
+int WebPopupMenuProxyWin::visibleItems() const
+{
+    return clientRect().height() / m_itemHeight;
+}
+
+int WebPopupMenuProxyWin::listIndexAtPoint(const IntPoint& point) const
+{
+    return m_scrollOffset + point.y() / m_itemHeight;
+}
+
+int WebPopupMenuProxyWin::focusedIndex() const
+{
+    return m_focusedIndex;
+}
+
+void WebPopupMenuProxyWin::focusFirst()
+{
+    int size = m_items.size();
+
+    for (int i = 0; i < size; ++i) {
+        if (m_items[i].m_isEnabled) {
+            setFocusedIndex(i);
+            break;
+        }
+    }
+}
+
+void WebPopupMenuProxyWin::focusLast()
+{
+    int size = m_items.size();
+
+    for (int i = size - 1; i > 0; --i) {
+        if (m_items[i].m_isEnabled) {
+            setFocusedIndex(i);
+            break;
+        }
+    }
+}
+
+
+void WebPopupMenuProxyWin::incrementWheelDelta(int delta)
+{
+    m_wheelDelta += delta;
+}
+
+void WebPopupMenuProxyWin::reduceWheelDelta(int delta)
+{
+    ASSERT(delta >= 0);
+    ASSERT(delta <= abs(m_wheelDelta));
+
+    if (m_wheelDelta > 0)
+        m_wheelDelta -= delta;
+    else if (m_wheelDelta < 0)
+        m_wheelDelta += delta;
+    else
+        return;
+}
+
+bool WebPopupMenuProxyWin::scrollToRevealSelection()
+{
+    if (!m_scrollbar)
+        return false;
+
+    int index = focusedIndex();
+
+    if (index < m_scrollOffset) {
+        m_scrollbar->setValue(index, Scrollbar::NotFromScrollAnimator);
+        return true;
+    }
+
+    if (index >= m_scrollOffset + visibleItems()) {
+        m_scrollbar->setValue(index - visibleItems() + 1, Scrollbar::NotFromScrollAnimator);
+        return true;
+    }
+
+    return false;
 }
 
 } // namespace WebKit
diff --git a/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h b/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h
index 3106aa6..07e3767 100644
--- a/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h
+++ b/WebKit2/UIProcess/win/WebPopupMenuProxyWin.h
@@ -26,23 +26,109 @@
 #ifndef WebPopupMenuProxyWin_h
 #define WebPopupMenuProxyWin_h
 
+#include "PlatformPopupMenuData.h"
+#include "WebPopupItem.h"
 #include "WebPopupMenuProxy.h"
+#include <WebCore/Scrollbar.h>
+#include <WebCore/ScrollbarClient.h>
+
+typedef struct HWND__* HWND;
+typedef struct HDC__* HDC;
+typedef struct HBITMAP__* HBITMAP;
 
 namespace WebKit {
 
-class WebPopupMenuProxyWin : public WebPopupMenuProxy {
+class WebView;
+
+class WebPopupMenuProxyWin : public WebPopupMenuProxy, private WebCore::ScrollbarClient  {
 public:
-    static PassRefPtr<WebPopupMenuProxyWin> create()
+    static PassRefPtr<WebPopupMenuProxyWin> create(WebView* webView)
     {
-        return adoptRef(new WebPopupMenuProxyWin());
+        return adoptRef(new WebPopupMenuProxyWin(webView));
     }
     ~WebPopupMenuProxyWin();
 
-    virtual void showPopupMenu(const WebCore::IntRect&, const Vector<WebPopupItem>&, int32_t selectedIndex, int32_t& newSelectedIndex);
+    virtual void showPopupMenu(const WebCore::IntRect&, const Vector<WebPopupItem>&, const PlatformPopupMenuData&, int32_t selectedIndex, int32_t& newSelectedIndex);
     virtual void hidePopupMenu();
 
+    void hide() { hidePopupMenu(); }
+
 private:
-    WebPopupMenuProxyWin();
+    WebPopupMenuProxyWin(WebView*);
+
+    WebCore::Scrollbar* scrollbar() const { return m_scrollbar.get(); }
+
+    // ScrollBarClient
+    virtual int scrollSize(WebCore::ScrollbarOrientation orientation) const;
+    virtual void setScrollOffsetFromAnimation(const WebCore::IntPoint&);
+    virtual void valueChanged(WebCore::Scrollbar*);
+    virtual void invalidateScrollbarRect(WebCore::Scrollbar*, const WebCore::IntRect&);
+    virtual bool isActive() const { return true; }
+    virtual bool scrollbarCornerPresent() const { return false; }
+
+    static bool registerWindowClass();
+    static LRESULT CALLBACK WebPopupMenuProxyWndProc(HWND, UINT, WPARAM, LPARAM);
+    LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
+
+    // Message pump messages.
+    LRESULT onMouseActivate(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onSize(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onKeyDown(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onChar(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onMouseMove(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onLButtonDown(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onLButtonUp(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onMouseWheel(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onPaint(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+    LRESULT onPrintClient(HWND, UINT message, WPARAM, LPARAM, bool& handled);
+
+    void calculatePositionAndSize(const WebCore::IntRect&);
+    WebCore::IntRect clientRect() const;
+    void invalidateItem(int index);
+
+    int itemHeight() const { return m_itemHeight; }
+    const WebCore::IntRect& windowRect() const { return m_windowRect; }
+    int wheelDelta() const { return m_wheelDelta; }
+    void setWasClicked(bool b = true) { m_wasClicked = b; }
+    bool wasClicked() const { return m_wasClicked; }
+    void setScrollOffset(int offset) { m_scrollOffset = offset; }
+    int scrollOffset() const { return m_scrollOffset; }
+    bool scrollbarCapturingMouse() const { return m_scrollbarCapturingMouse; }
+    void setScrollbarCapturingMouse(bool b) { m_scrollbarCapturingMouse = b; }
+
+
+    bool up(unsigned lines = 1);
+    bool down(unsigned lines = 1);
+
+    void paint(const WebCore::IntRect& damageRect, HDC = 0);
+    int visibleItems() const;
+    int listIndexAtPoint(const WebCore::IntPoint&) const;
+    bool setFocusedIndex(int index, bool hotTracking = false);
+    int focusedIndex() const;
+    void focusFirst();
+    void focusLast();
+    bool scrollToRevealSelection();
+    void incrementWheelDelta(int delta);
+    void reduceWheelDelta(int delta);
+
+    WebView* m_webView;
+    Vector<WebPopupItem> m_items;
+    PlatformPopupMenuData m_data;
+    int m_newSelectedIndex;
+
+    RefPtr<WebCore::Scrollbar> m_scrollbar;
+    HWND m_popup;
+    HDC m_DC;
+    HBITMAP m_bmp;
+    WebCore::IntRect m_windowRect;
+
+    int m_itemHeight;
+    int m_scrollOffset;
+    int m_wheelDelta;
+    int m_focusedIndex;
+    bool m_wasClicked;
+    bool m_scrollbarCapturingMouse;
+    bool m_showPopup;
 };
 
 } // namespace WebKit
diff --git a/WebKit2/UIProcess/win/WebView.cpp b/WebKit2/UIProcess/win/WebView.cpp
index a926ebf..3938e29 100644
--- a/WebKit2/UIProcess/win/WebView.cpp
+++ b/WebKit2/UIProcess/win/WebView.cpp
@@ -628,7 +628,7 @@ void WebView::didNotHandleKeyEvent(const NativeWebKeyboardEvent& event)
 
 PassRefPtr<WebPopupMenuProxy> WebView::createPopupMenuProxy()
 {
-    return WebPopupMenuProxyWin::create();
+    return WebPopupMenuProxyWin::create(this);
 }
 
 PassRefPtr<WebContextMenuProxy> WebView::createContextMenuProxy(WebPageProxy*)
diff --git a/WebKit2/WebKit2.pro b/WebKit2/WebKit2.pro
index 06e0c1c..399ffd8 100644
--- a/WebKit2/WebKit2.pro
+++ b/WebKit2/WebKit2.pro
@@ -224,6 +224,7 @@ HEADERS += \
     Shared/qt/PlatformCertificateInfo.h \
     Shared/qt/UpdateChunk.h \
     Shared/qt/WebEventFactoryQt.h \
+    Shared/PlatformPopupMenuData.h \
     Shared/UserMessageCoders.h \
     Shared/VisitedLinkTable.h \
     Shared/WebCertificateInfo.h \
@@ -398,6 +399,7 @@ SOURCES += \
     Shared/qt/WebEventFactoryQt.cpp \
     Shared/qt/WebURLRequestQt.cpp \
     Shared/qt/WebURLResponseQt.cpp \
+    Shared/PlatformPopupMenuData.cpp \
     Shared/VisitedLinkTable.cpp \
     Shared/WebContextMenuItemData.cpp \
     Shared/WebError.cpp \
diff --git a/WebKit2/WebKit2.xcodeproj/project.pbxproj b/WebKit2/WebKit2.xcodeproj/project.pbxproj
index d5307e0..7a15bbe 100644
--- a/WebKit2/WebKit2.xcodeproj/project.pbxproj
+++ b/WebKit2/WebKit2.xcodeproj/project.pbxproj
@@ -431,6 +431,9 @@
 		BCBD3914125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCBD3912125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp */; };
 		BCBD3915125BB1A800D2C29F /* WebPageProxyMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = BCBD3913125BB1A800D2C29F /* WebPageProxyMessages.h */; };
 		BCBD3C3B125BFA7A00D2C29F /* StringPairVector.h in Headers */ = {isa = PBXBuildFile; fileRef = BCBD3C3A125BFA7A00D2C29F /* StringPairVector.h */; };
+		BCC43ABA127B95DC00317F16 /* PlatformPopupMenuData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCC43AB8127B95DC00317F16 /* PlatformPopupMenuData.cpp */; };
+		BCC43ABB127B95DC00317F16 /* PlatformPopupMenuData.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC43AB9127B95DC00317F16 /* PlatformPopupMenuData.h */; };
+		BCC43AC7127B99DE00317F16 /* WebPopupMenuMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCC43AC6127B99DE00317F16 /* WebPopupMenuMac.mm */; };
 		BCC56F791159957D001CCAF9 /* MachPort.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC56F771159957D001CCAF9 /* MachPort.h */; };
 		BCC5715B115ADAEF001CCAF9 /* WebSystemInterface.h in Headers */ = {isa = PBXBuildFile; fileRef = BCC57159115ADAEF001CCAF9 /* WebSystemInterface.h */; };
 		BCC5715C115ADAEF001CCAF9 /* WebSystemInterface.mm in Sources */ = {isa = PBXBuildFile; fileRef = BCC5715A115ADAEF001CCAF9 /* WebSystemInterface.mm */; };
@@ -978,6 +981,9 @@
 		BCBD3912125BB1A800D2C29F /* WebPageProxyMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageProxyMessageReceiver.cpp; sourceTree = "<group>"; };
 		BCBD3913125BB1A800D2C29F /* WebPageProxyMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageProxyMessages.h; sourceTree = "<group>"; };
 		BCBD3C3A125BFA7A00D2C29F /* StringPairVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringPairVector.h; sourceTree = "<group>"; };
+		BCC43AB8127B95DC00317F16 /* PlatformPopupMenuData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlatformPopupMenuData.cpp; sourceTree = "<group>"; };
+		BCC43AB9127B95DC00317F16 /* PlatformPopupMenuData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlatformPopupMenuData.h; sourceTree = "<group>"; };
+		BCC43AC6127B99DE00317F16 /* WebPopupMenuMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPopupMenuMac.mm; sourceTree = "<group>"; };
 		BCC56F771159957D001CCAF9 /* MachPort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachPort.h; sourceTree = "<group>"; };
 		BCC57159115ADAEF001CCAF9 /* WebSystemInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSystemInterface.h; sourceTree = "<group>"; };
 		BCC5715A115ADAEF001CCAF9 /* WebSystemInterface.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebSystemInterface.mm; sourceTree = "<group>"; };
@@ -1353,6 +1359,8 @@
 				BCB0AEE7122F53E300B1341E /* MutableDictionary.h */,
 				C02BFF1512514FD8009CCBEA /* NativeWebKeyboardEvent.h */,
 				BCC57161115ADB42001CCAF9 /* NotImplemented.h */,
+				BCC43AB8127B95DC00317F16 /* PlatformPopupMenuData.cpp */,
+				BCC43AB9127B95DC00317F16 /* PlatformPopupMenuData.h */,
 				BCBD3C3A125BFA7A00D2C29F /* StringPairVector.h */,
 				BCB0B0DF12305AB100B1341E /* UserMessageCoders.h */,
 				1A0F29C9120B37160053D1B9 /* VisitedLinkTable.cpp */,
@@ -1718,6 +1726,7 @@
 				BC111ADF112F5BC200337BAB /* WebErrorsMac.mm */,
 				9391F283121B38F500EBF7E8 /* WebFrameNetworkingContext.h */,
 				9391F284121B38F500EBF7E8 /* WebFrameNetworkingContext.mm */,
+				BCC43AC6127B99DE00317F16 /* WebPopupMenuMac.mm */,
 				BCC57159115ADAEF001CCAF9 /* WebSystemInterface.h */,
 				BCC5715A115ADAEF001CCAF9 /* WebSystemInterface.mm */,
 			);
@@ -2334,6 +2343,7 @@
 				51ACBB82127A8BAD00D203B9 /* WebContextMenuProxy.h in Headers */,
 				51ACBBA0127A8F2C00D203B9 /* WebContextMenuProxyMac.h in Headers */,
 				1A119A95127B796200A9ECB1 /* MessageSender.h in Headers */,
+				BCC43ABB127B95DC00317F16 /* PlatformPopupMenuData.h in Headers */,
 				51871B5C127CB89D00F76232 /* WebContextMenu.h in Headers */,
 				1A2D82A5127F4EAB001EB962 /* NPObjectMessageReceiver.h in Headers */,
 				1A2D82A7127F4EAB001EB962 /* NPObjectProxy.h in Headers */,
@@ -2678,6 +2688,8 @@
 				C0337DD3127A2A0E008FF4F4 /* WebKeyboardEvent.cpp in Sources */,
 				C0337DD8127A51B6008FF4F4 /* WebTouchEvent.cpp in Sources */,
 				C0337DDD127A521C008FF4F4 /* WebPlatformTouchPoint.cpp in Sources */,
+				BCC43ABA127B95DC00317F16 /* PlatformPopupMenuData.cpp in Sources */,
+				BCC43AC7127B99DE00317F16 /* WebPopupMenuMac.mm in Sources */,
 				51871B5B127CB89D00F76232 /* WebContextMenu.cpp in Sources */,
 				51A84CE3127F386B00CA6EA4 /* WebContextMenuProxy.cpp in Sources */,
 				1A2D82A4127F4EAB001EB962 /* NPObjectMessageReceiver.cpp in Sources */,
diff --git a/WebKit2/WebProcess/Plugins/PluginProxy.cpp b/WebKit2/WebProcess/Plugins/PluginProxy.cpp
index 345b3c8..c9d9a59 100644
--- a/WebKit2/WebProcess/Plugins/PluginProxy.cpp
+++ b/WebKit2/WebProcess/Plugins/PluginProxy.cpp
@@ -124,20 +124,15 @@ void PluginProxy::paint(GraphicsContext* graphicsContext, const IntRect& dirtyRe
         // Blit the plug-in backing store into our own backing store.
         OwnPtr<WebCore::GraphicsContext> graphicsContext = m_backingStore->createGraphicsContext();
         
-        m_pluginBackingStore->paint(graphicsContext.get(), IntRect(0, 0, m_frameRect.width(), m_frameRect.height()));
-        
+        m_pluginBackingStore->paint(*graphicsContext, IntPoint(), IntRect(0, 0, m_frameRect.width(), m_frameRect.height()));
+
         m_pluginBackingStoreContainsValidData = true;
     }
 
     IntRect dirtyRectInPluginCoordinates = dirtyRect;
     dirtyRectInPluginCoordinates.move(-m_frameRect.x(), -m_frameRect.y());
 
-    graphicsContext->save();
-
-    graphicsContext->translate(m_frameRect.x(), m_frameRect.y());
-    m_backingStore->paint(graphicsContext, dirtyRectInPluginCoordinates);
-
-    graphicsContext->restore();
+    m_backingStore->paint(*graphicsContext, m_frameRect.location(), dirtyRectInPluginCoordinates);
 
     if (m_waitingForPaintInResponseToUpdate) {
         m_waitingForPaintInResponseToUpdate = false;
@@ -409,9 +404,9 @@ void PluginProxy::update(const IntRect& paintedRect)
 
     if (m_backingStore) {
         // Blit the plug-in backing store into our own backing store.
-        OwnPtr<WebCore::GraphicsContext> graphicsContext = m_backingStore->createGraphicsContext();
+        OwnPtr<GraphicsContext> graphicsContext = m_backingStore->createGraphicsContext();
 
-        m_pluginBackingStore->paint(graphicsContext.get(), paintedRectPluginCoordinates);
+        m_pluginBackingStore->paint(*graphicsContext, IntPoint(), paintedRectPluginCoordinates);
     }
 
     // Ask the controller to invalidate the rect for us.
diff --git a/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.cpp b/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.cpp
index 8a5509a..49a5a31 100644
--- a/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.cpp
+++ b/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.cpp
@@ -21,6 +21,7 @@
 
 #include "WebPopupMenu.h"
 
+#include "PlatformPopupMenuData.h"
 #include "WebCoreArgumentCoders.h"
 #include "WebPage.h"
 #include "WebPageProxyMessages.h"
@@ -76,7 +77,7 @@ Vector<WebPopupItem> WebPopupMenu::populateItems()
             // FIXME: Add support for styling the font.
             // FIXME: Add support for styling the foreground and background colors.
             // FIXME: Find a way to customize text color when an item is highlighted.
-            items.append(WebPopupItem(WebPopupItem::Item, m_popupClient->itemText(i), m_popupClient->itemToolTip(i), m_popupClient->itemAccessibilityText(i), m_popupClient->itemIsEnabled(i)));
+            items.append(WebPopupItem(WebPopupItem::Item, m_popupClient->itemText(i), m_popupClient->itemToolTip(i), m_popupClient->itemAccessibilityText(i), m_popupClient->itemIsEnabled(i), m_popupClient->itemIsLabel(i)));
         }
     }
 
@@ -97,7 +98,11 @@ void WebPopupMenu::show(const IntRect& rect, FrameView* view, int index)
 
     // Move to page coordinates
     IntRect pageCoordinates(view->contentsToWindow(rect.location()), rect.size());
-    WebProcess::shared().connection()->send(Messages::WebPageProxy::ShowPopupMenu(pageCoordinates, items, index), m_page->pageID());
+
+    PlatformPopupMenuData platformData;
+    setUpPlatformData(platformData);
+
+    WebProcess::shared().connection()->send(Messages::WebPageProxy::ShowPopupMenu(pageCoordinates, items, index, platformData), m_page->pageID());
 }
 
 void WebPopupMenu::hide()
diff --git a/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.h b/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.h
index d4ca770..c3ff1ca 100644
--- a/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.h
+++ b/WebKit2/WebProcess/WebCoreSupport/WebPopupMenu.h
@@ -35,6 +35,7 @@ class PopupMenuClient;
 namespace WebKit {
 
 class WebPage;
+struct PlatformPopupMenuData;
 struct WebPopupItem;
 
 class WebPopupMenu : public WebCore::PopupMenu {
@@ -54,6 +55,7 @@ private:
     WebPopupMenu(WebPage*, WebCore::PopupMenuClient*);
 
     Vector<WebPopupItem> populateItems();
+    void setUpPlatformData(PlatformPopupMenuData&);
 
     WebCore::PopupMenuClient* m_popupClient;
     WebPage* m_page;
diff --git a/WebKit2/WebProcess/WebCoreSupport/mac/WebPopupMenuMac.mm b/WebKit2/WebProcess/WebCoreSupport/mac/WebPopupMenuMac.mm
new file mode 100644
index 0000000..9d6c520
--- /dev/null
+++ b/WebKit2/WebProcess/WebCoreSupport/mac/WebPopupMenuMac.mm
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+namespace WebKit {
+
+void WebPopupMenu::setUpPlatformData(PlatformPopupMenuData&)
+{
+}
+
+} // namespace WebKit
diff --git a/WebKit2/WebProcess/WebCoreSupport/qt/WebPopupMenuQt.cpp b/WebKit2/WebProcess/WebCoreSupport/qt/WebPopupMenuQt.cpp
new file mode 100644
index 0000000..9d6c520
--- /dev/null
+++ b/WebKit2/WebProcess/WebCoreSupport/qt/WebPopupMenuQt.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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"
+
+namespace WebKit {
+
+void WebPopupMenu::setUpPlatformData(PlatformPopupMenuData&)
+{
+}
+
+} // namespace WebKit
diff --git a/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp b/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp
new file mode 100644
index 0000000..96bac62
--- /dev/null
+++ b/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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(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 constraits 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;
+
+    data.m_backingStoreSize = IntSize(data.m_popupWidth, (itemCount * data.m_itemHeight));
+    data.m_notSelectedBackingStore = BackingStore::createSharable(data.m_backingStoreSize);
+    data.m_selectedBackingStore = BackingStore::createSharable(data.m_backingStoreSize);
+
+    OwnPtr<GraphicsContext> notSelectedBackingStoreContext = data.m_notSelectedBackingStore->createFlippedGraphicsContext();
+    OwnPtr<GraphicsContext> selectedBackingStoreContext = data.m_selectedBackingStore->createFlippedGraphicsContext();
+
+    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, data.m_popupWidth, 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
diff --git a/WebKit2/win/WebKit2.vcproj b/WebKit2/win/WebKit2.vcproj
index 50ff5f5..c26200d 100755
--- a/WebKit2/win/WebKit2.vcproj
+++ b/WebKit2/win/WebKit2.vcproj
@@ -477,6 +477,14 @@
 				>
 			</File>
 			<File
+				RelativePath="..\Shared\PlatformPopupMenuData.cpp"
+				>
+			</File>
+			<File
+				RelativePath="..\Shared\PlatformPopupMenuData.h"
+				>
+			</File>
+			<File
 				RelativePath="..\Shared\StringPairVector.h"
 				>
 			</File>
@@ -1150,6 +1158,10 @@
 						RelativePath="..\WebProcess\WebCoreSupport\win\WebFrameNetworkingContext.h"
 						>
 					</File>
+					<File
+						RelativePath=".\WebProcess\WebCoreSupport\win\WebPopupMenuWin.cpp"
+						>
+					</File>
 				</Filter>
 			</Filter>
 			<Filter

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list