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

bweinstein at apple.com bweinstein at apple.com
Wed Dec 22 18:26:05 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit c4728817f74c4e3cb1395db4307aedfb5b48b104
Author: bweinstein at apple.com <bweinstein at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Dec 10 22:21:00 2010 +0000

    JavaScriptCore: Turn on USE(CROSS_PLATFORM_CONTEXT_MENUS) for Windows.
    
    Reviewed by Adam Roben.
    
    * wtf/Platform.h:
    
    WebCore: Prep for WebKit2: Context menu support on Windows
    https://bugs.webkit.org/show_bug.cgi?id=50514
    
    Reviewed by Adam Roben.
    
    Before this patch ContextMenu on Windows were backed by HMENUs, and ContextMenuItems
    were backed by MENUITEMINFOs. This meant they couldn't be copied, and they needed to
    be to work in WebKit2.
    
    This patch adds a new USE flag - CROSS_PLATFORM_CONTEXT_MENUS that are for a cross-platform
    representation of context menus. This patch also has Windows adopt them.
    
    Cross-platform context menus change the API of context menus and the ContextMenuClient. There
    is no more idea of a PlatformMenuDescription or a PlatformMenuItemDescription. Menus are backed
    by a Vector of ContextMenuItems, and menu items are backed by the variables they need (enabled, checked
    title, action, type, and submenu).
    
    This patch also refactors the ContextMenuClient interface to use a variation on the getCustomMenuFromDefaultItems
    function to allow for customization of the context menu.
    
    For other ports to use CROSS_PLATFORM_CONTEXT_MENUS, all they need to do is write conversion functions from
    a ContextMenu <-> native menu type, and ContextMenuItem <-> native menu item type. For Windows, this is done
    in ContextMenuWin.cpp and ContextMenuItemWin.cpp.
    
    No new tests, no change in behavior.
    
    * WebCore.vcproj/WebCore.vcproj: Add new files (only needed on Windows for now).
    * loader/EmptyClients.h:
    (WebCore::EmptyContextMenuClient::customizeMenu): Define this function if CROSS_PLATFORM_CONTEXT_MENUS
        is on.
    * page/ContextMenuClient.h: Ditto.
    * page/ContextMenuController.cpp:
    (WebCore::ContextMenuController::showContextMenu): Call customizeMenu instead of
        getCustomMenuFromDefaultItems if CROSS_PLATFORM_CONTEXT_MENUS is on.
    * platform/ContextMenu.cpp: Added.
    (WebCore::ContextMenu::ContextMenu): Empty constructor.
    (WebCore::ContextMenu::setItems): Sets the items in the menu.
    (WebCore::ContextMenu::items): Returns the items in the menu.
    (WebCore::ContextMenu::itemAtIndex):
    (WebCore::itemWithActionInMenu): Returns the item with the correct action, recursively descending
        into submenus.
    (WebCore::ContextMenu::itemWithAction): Calls through to itemWithActionInMenu.
    * platform/ContextMenu.h: Added a new set of functions and member variables that are defined for
        CROSS_PLATFORM_CONTEXT_MENUS.
    (WebCore::ContextMenu::appendItem): Appends an item to the menu.
    * platform/ContextMenuItem.cpp: Added.
    (WebCore::ContextMenuItem::ContextMenuItem):
    (WebCore::ContextMenuItem::~ContextMenuItem):
    (WebCore::ContextMenuItem::setSubMenu):
    * platform/ContextMenuItem.h:
    (WebCore::ContextMenuItem::type): Returns the type.
    (WebCore::ContextMenuItem::setType): Sets the type.
    (WebCore::ContextMenuItem::action): Returns the action.
    (WebCore::ContextMenuItem::setAction): Sets the action.
    (WebCore::ContextMenuItem::title): Returns the title.
    (WebCore::ContextMenuItem::setTitle): Sets the title.
    (WebCore::ContextMenuItem::checked): Returns whether or not the menu item is checked.
    (WebCore::ContextMenuItem::setChecked): Sets whether ot not the menu item is checked.
    (WebCore::ContextMenuItem::enabled): Returns whether or not the menu item is enabled.
    (WebCore::ContextMenuItem::setEnabled): Sets whether or not the menu item is enabled.
    (WebCore::ContextMenuItem::submenu): Returns the submenu.
    * platform/PlatformMenuDescription.h: Remove the idea if a PlatformMenuDescription if
        CROSS_PLATFORM_CONTEXT_MENUS is on.
    * platform/win/ContextMenuItemWin.cpp:
    (WebCore::ContextMenuItem::ContextMenuItem): Creates a ContextMenuItem from a MENUITEMINFO.
    (WebCore::ContextMenuItem::nativeMenuItem): Creates and returns a MENUITEMINFO.
    * platform/win/ContextMenuWin.cpp:
    (WebCore::ContextMenu::ContextMenu): Creates a ContextMenu from an HMENU.
    (WebCore::ContextMenu::nativeMenu): Creates and returns an HMENU.
    
    WebKit/win: Prep for WebKit2: Context menu support on Windows
    https://bugs.webkit.org/show_bug.cgi?id=50514
    
    Reviewed by Adam Roben.
    
    Update WebKit for the new CROSS_PLATFORM_CONTEXT_MENUS flag, and define customizeMenu
    instead of getCustomMenuFromDefaultItems.
    
    * WebCoreSupport/WebContextMenuClient.cpp:
    (WebContextMenuClient::customizeMenu): getCustomMenuFromDefaultItems was turned into
        this function, with refactoring using nativeMenu instead of platformDescription.
    (WebContextMenuClient::contextMenuItemSelected):  Use nativeMenu instead of platformDescription.
    * WebCoreSupport/WebContextMenuClient.h:
    * WebView.cpp:
    (WebView::handleContextMenuEvent): Call nativeMenu instead of platformDescription.
    (WebView::performContextMenuAction): Only call itemAtIndex with one argument, no need
        for the second.
    
    WebKit2: Prep for WebKit2: Context menu support on Windows
    https://bugs.webkit.org/show_bug.cgi?id=50514
    
    Reviewed by Adam Roben.
    
    Update WebKit2 to call the correct code when CROSS_PLATFORM_CONTEXT_MENUS is set.
    
    * Shared/WebContextMenuItemData.cpp:
    (WebKit::WebContextMenuItemData::WebContextMenuItemData): Add a branch based on whether or not
        CROSS_PLATFORM_CONTEXT_MENUS is set.
    * WebProcess/WebCoreSupport/WebContextMenuClient.cpp:
    (WebKit::WebContextMenuClient::customizeMenu): Define different functions based on
        whether or not CROSS_PLATFORM_CONTEXT_MENUS. Both of these are stubs, so functionality
        doesn't need to be shared.
    * WebProcess/WebCoreSupport/WebContextMenuClient.h: Define different functions based on
        whether or not CROSS_PLATFORM_CONTEXT_MENUS.
    * WebProcess/WebPage/WebContextMenu.cpp:
    (WebKit::WebContextMenu::show): Add a branch based on whether or not
        CROSS_PLATFORM_CONTEXT_MENUS is set.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@73802 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index db27b8a..dd6fe49 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,11 @@
+2010-12-10  Brian Weinstein  <bweinstein at apple.com>
+
+        Reviewed by Adam Roben.
+
+        Turn on USE(CROSS_PLATFORM_CONTEXT_MENUS) for Windows.
+
+        * wtf/Platform.h:
+
 2010-12-10  Martin Robinson  <mrobinson at igalia.com>
 
         Unreviewed, rolling out r73703.
diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h
index 5c4aec2..87a12cc 100644
--- a/JavaScriptCore/wtf/Platform.h
+++ b/JavaScriptCore/wtf/Platform.h
@@ -1106,6 +1106,10 @@
 #define WTF_USE_PLATFORM_STRATEGIES 1
 #endif
 
+#if PLATFORM(WIN)
+#define WTF_USE_CROSS_PLATFORM_CONTEXT_MENUS 1
+#endif
+
 /* Geolocation request policy. pre-emptive policy is to acquire user permission before acquiring location.
    Client based implementations will have option to choose between pre-emptive and nonpre-emptive permission policy.
    pre-emptive permission policy is enabled by default for all client-based implementations. */
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 03e65ae..b548514 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,75 @@
+2010-12-09  Brian Weinstein  <bweinstein at apple.com>
+
+        Reviewed by Adam Roben.
+
+        Prep for WebKit2: Context menu support on Windows
+        https://bugs.webkit.org/show_bug.cgi?id=50514
+        
+        Before this patch ContextMenu on Windows were backed by HMENUs, and ContextMenuItems
+        were backed by MENUITEMINFOs. This meant they couldn't be copied, and they needed to
+        be to work in WebKit2.
+        
+        This patch adds a new USE flag - CROSS_PLATFORM_CONTEXT_MENUS that are for a cross-platform
+        representation of context menus. This patch also has Windows adopt them.
+        
+        Cross-platform context menus change the API of context menus and the ContextMenuClient. There
+        is no more idea of a PlatformMenuDescription or a PlatformMenuItemDescription. Menus are backed
+        by a Vector of ContextMenuItems, and menu items are backed by the variables they need (enabled, checked
+        title, action, type, and submenu).
+        
+        This patch also refactors the ContextMenuClient interface to use a variation on the getCustomMenuFromDefaultItems
+        function to allow for customization of the context menu.
+        
+        For other ports to use CROSS_PLATFORM_CONTEXT_MENUS, all they need to do is write conversion functions from
+        a ContextMenu <-> native menu type, and ContextMenuItem <-> native menu item type. For Windows, this is done
+        in ContextMenuWin.cpp and ContextMenuItemWin.cpp.
+
+        No new tests, no change in behavior.
+
+        * WebCore.vcproj/WebCore.vcproj: Add new files (only needed on Windows for now).
+        * loader/EmptyClients.h:
+        (WebCore::EmptyContextMenuClient::customizeMenu): Define this function if CROSS_PLATFORM_CONTEXT_MENUS
+            is on.
+        * page/ContextMenuClient.h: Ditto. 
+        * page/ContextMenuController.cpp:
+        (WebCore::ContextMenuController::showContextMenu): Call customizeMenu instead of 
+            getCustomMenuFromDefaultItems if CROSS_PLATFORM_CONTEXT_MENUS is on.
+        * platform/ContextMenu.cpp: Added.
+        (WebCore::ContextMenu::ContextMenu): Empty constructor.
+        (WebCore::ContextMenu::setItems): Sets the items in the menu.
+        (WebCore::ContextMenu::items): Returns the items in the menu.
+        (WebCore::ContextMenu::itemAtIndex):
+        (WebCore::itemWithActionInMenu): Returns the item with the correct action, recursively descending
+            into submenus.
+        (WebCore::ContextMenu::itemWithAction): Calls through to itemWithActionInMenu.
+        * platform/ContextMenu.h: Added a new set of functions and member variables that are defined for
+            CROSS_PLATFORM_CONTEXT_MENUS.
+        (WebCore::ContextMenu::appendItem): Appends an item to the menu.
+        * platform/ContextMenuItem.cpp: Added.
+        (WebCore::ContextMenuItem::ContextMenuItem):
+        (WebCore::ContextMenuItem::~ContextMenuItem):
+        (WebCore::ContextMenuItem::setSubMenu):
+        * platform/ContextMenuItem.h:
+        (WebCore::ContextMenuItem::type): Returns the type.
+        (WebCore::ContextMenuItem::setType): Sets the type.
+        (WebCore::ContextMenuItem::action): Returns the action.
+        (WebCore::ContextMenuItem::setAction): Sets the action.
+        (WebCore::ContextMenuItem::title): Returns the title.
+        (WebCore::ContextMenuItem::setTitle): Sets the title.
+        (WebCore::ContextMenuItem::checked): Returns whether or not the menu item is checked.
+        (WebCore::ContextMenuItem::setChecked): Sets whether ot not the menu item is checked.
+        (WebCore::ContextMenuItem::enabled): Returns whether or not the menu item is enabled.
+        (WebCore::ContextMenuItem::setEnabled): Sets whether or not the menu item is enabled.
+        (WebCore::ContextMenuItem::submenu): Returns the submenu.
+        * platform/PlatformMenuDescription.h: Remove the idea if a PlatformMenuDescription if 
+            CROSS_PLATFORM_CONTEXT_MENUS is on.
+        * platform/win/ContextMenuItemWin.cpp:
+        (WebCore::ContextMenuItem::ContextMenuItem): Creates a ContextMenuItem from a MENUITEMINFO.
+        (WebCore::ContextMenuItem::nativeMenuItem): Creates and returns a MENUITEMINFO.
+        * platform/win/ContextMenuWin.cpp:
+        (WebCore::ContextMenu::ContextMenu): Creates a ContextMenu from an HMENU.
+        (WebCore::ContextMenu::nativeMenu): Creates and returns an HMENU.
+
 2010-12-10  Emil Eklund  <eae at chromium.org>
 
         Reviewed by Adam Barth.
diff --git a/WebCore/WebCore.vcproj/WebCore.vcproj b/WebCore/WebCore.vcproj/WebCore.vcproj
index d06596c..348242d 100755
--- a/WebCore/WebCore.vcproj/WebCore.vcproj
+++ b/WebCore/WebCore.vcproj/WebCore.vcproj
@@ -25305,10 +25305,18 @@
 				RelativePath="..\platform\ContentType.h"
 				>
 			</File>
+            <File
+				RelativePath="..\platform\ContextMenu.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\platform\ContextMenu.h"
 				>
 			</File>
+            <File
+				RelativePath="..\platform\ContextMenuItem.cpp"
+				>
+			</File>
 			<File
 				RelativePath="..\platform\ContextMenuItem.h"
 				>
diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h
index 2ac8dd0..d3884f5 100644
--- a/WebCore/loader/EmptyClients.h
+++ b/WebCore/loader/EmptyClients.h
@@ -501,7 +501,11 @@ public:
     virtual ~EmptyContextMenuClient() {  }
     virtual void contextMenuDestroyed() { }
 
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+    virtual PassOwnPtr<ContextMenu> customizeMenu(PassOwnPtr<ContextMenu>) { return 0; }
+#else
     virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*) { return 0; }
+#endif
     virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) { }
 
     virtual void downloadURL(const KURL&) { }
diff --git a/WebCore/page/ContextMenuClient.h b/WebCore/page/ContextMenuClient.h
index f91536b..c9389c0 100644
--- a/WebCore/page/ContextMenuClient.h
+++ b/WebCore/page/ContextMenuClient.h
@@ -26,11 +26,12 @@
 #ifndef ContextMenuClient_h
 #define ContextMenuClient_h
 
+#include "ContextMenu.h"
 #include "PlatformMenuDescription.h"
 #include <wtf/Forward.h>
+#include <wtf/PassOwnPtr.h>
 
 namespace WebCore {
-    class ContextMenu;
     class ContextMenuItem;
     class Frame;
     class HitTestResult;
@@ -41,7 +42,12 @@ namespace WebCore {
         virtual ~ContextMenuClient() {  }
         virtual void contextMenuDestroyed() = 0;
         
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+        virtual PassOwnPtr<ContextMenu> customizeMenu(PassOwnPtr<ContextMenu>) = 0;
+#else
         virtual PlatformMenuDescription getCustomMenuFromDefaultItems(ContextMenu*) = 0;
+#endif
+
         virtual void contextMenuItemSelected(ContextMenuItem*, const ContextMenu*) = 0;
 
         virtual void downloadURL(const KURL& url) = 0;
diff --git a/WebCore/page/ContextMenuController.cpp b/WebCore/page/ContextMenuController.cpp
index 2f95cdf..65399de 100644
--- a/WebCore/page/ContextMenuController.cpp
+++ b/WebCore/page/ContextMenuController.cpp
@@ -144,8 +144,13 @@ void ContextMenuController::showContextMenu(Event* event)
     if (m_page->inspectorController()->enabled())
         addInspectElementItem();
 #endif
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+    m_contextMenu = m_client->customizeMenu(m_contextMenu.release());
+#else
     PlatformMenuDescription customMenu = m_client->getCustomMenuFromDefaultItems(m_contextMenu.get());
     m_contextMenu->setPlatformDescription(customMenu);
+#endif
     event->setDefaultHandled();
 }
 
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp
new file mode 100644
index 0000000..a51d818
--- /dev/null
+++ b/WebCore/platform/ContextMenu.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 "config.h"
+#include "ContextMenu.h"
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+
+namespace WebCore {
+
+ContextMenu::ContextMenu()
+{
+}
+
+static const ContextMenuItem* findItemWithAction(unsigned action, const Vector<ContextMenuItem>& items)
+{
+    for (size_t i = 0; i < items.size(); ++i) {
+        const ContextMenuItem& item = items[i];
+        if (item.action() == action)
+            return &item;
+        if (item.type() != SubmenuType)
+            continue;
+        if (const ContextMenuItem* subMenuItem = findItemWithAction(action, item.subMenuItems()))
+            return subMenuItem;
+    }
+
+    return 0;
+}
+
+ContextMenuItem* ContextMenu::itemWithAction(unsigned action)
+{
+    // FIXME: When more platforms switch over, this fucntion should return a const ContextMenuItem*'s, and the const_cast
+    // won't be needed anymore.
+    return const_cast<ContextMenuItem*>(findItemWithAction(action, m_items));
+}
+
+} // namespace WebCore
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
diff --git a/WebCore/platform/ContextMenu.h b/WebCore/platform/ContextMenu.h
index 3393eab..e452d8f 100644
--- a/WebCore/platform/ContextMenu.h
+++ b/WebCore/platform/ContextMenu.h
@@ -48,13 +48,34 @@ namespace WebCore {
     {
     public:
         ContextMenu();
+
+        ContextMenuItem* itemWithAction(unsigned);
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#if PLATFORM(WIN)
+        typedef HMENU NativeMenu;
+#endif
+        explicit ContextMenu(NativeMenu);
+
+        NativeMenu nativeMenu() const;
+
+        static NativeMenu createNativeMenuFromItems(const Vector<ContextMenuItem>&);
+        static void getContextMenuItems(NativeMenu, Vector<ContextMenuItem>&);
+
+        // FIXME: When more platforms switch over, this should return const ContextMenuItem*'s.
+        ContextMenuItem* itemAtIndex(unsigned index) { return &m_items[index]; }
+
+        void setItems(const Vector<ContextMenuItem>& items) { m_items = items; }
+        const Vector<ContextMenuItem>& items() const { return m_items; }
+
+        void appendItem(const ContextMenuItem& item) { m_items.append(item); } 
+#else
         ContextMenu(const PlatformMenuDescription);
         ~ContextMenu();
 
         void insertItem(unsigned position, ContextMenuItem&);
         void appendItem(ContextMenuItem&);
-        
-        ContextMenuItem* itemWithAction(unsigned);
+
         ContextMenuItem* itemAtIndex(unsigned, const PlatformMenuDescription);
 
         unsigned itemCount() const;
@@ -63,10 +84,17 @@ namespace WebCore {
         void setPlatformDescription(PlatformMenuDescription);
 
         PlatformMenuDescription releasePlatformDescription();
+
 #if PLATFORM(WX)
         static ContextMenuItem* itemWithId(int);
 #endif
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
+
     private:
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+        Vector<ContextMenuItem> m_items;
+#else
 #if PLATFORM(MAC)
         // Keep this in sync with the PlatformMenuDescription typedef
         RetainPtr<NSMutableArray> m_platformDescription;
@@ -83,10 +111,14 @@ namespace WebCore {
         unsigned m_itemCount;
 #endif
 #endif
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
     };
 
+#if !USE(CROSS_PLATFORM_CONTEXT_MENUS)
 Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription);
 PlatformMenuDescription platformMenuDescription(Vector<ContextMenuItem>&);
+#endif
 
 }
 
diff --git a/WebCore/platform/ContextMenuItem.cpp b/WebCore/platform/ContextMenuItem.cpp
new file mode 100644
index 0000000..bd321d9
--- /dev/null
+++ b/WebCore/platform/ContextMenuItem.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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 "config.h"
+#include "ContextMenuItem.h"
+
+#include "ContextMenu.h"
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+
+namespace WebCore {
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
+    : m_type(type)
+    , m_action(action)
+    , m_title(title)
+    , m_enabled(true)
+    , m_checked(false)
+{
+    setSubMenu(subMenu);
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
+    : m_type(type)
+    , m_action(action)
+    , m_title(title)
+    , m_enabled(enabled)
+    , m_checked(checked)
+{
+}
+        
+ContextMenuItem::ContextMenuItem(ContextMenuAction action, const String& title, bool enabled, bool checked, const Vector<ContextMenuItem>& subMenuItems)
+    : m_type(SubmenuType)
+    , m_action(action)
+    , m_title(title)
+    , m_enabled(enabled)
+    , m_checked(checked)
+    , m_subMenuItems(subMenuItems)
+{
+}
+
+ContextMenuItem::~ContextMenuItem()
+{
+}
+
+void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
+{
+    if (subMenu) {
+        m_type = SubmenuType;
+        m_subMenuItems = subMenu->items();
+    } else {
+        m_type = ActionType;
+        m_subMenuItems.clear();
+    }
+}
+
+void ContextMenuItem::setType(ContextMenuItemType type)
+{
+    m_type = type;
+}
+
+ContextMenuItemType ContextMenuItem::type() const
+{
+    return m_type;
+}
+
+void ContextMenuItem::setAction(ContextMenuAction action)
+{
+    m_action = action;
+}
+
+ContextMenuAction ContextMenuItem::action() const
+{
+    return m_action;
+}
+
+void ContextMenuItem::setChecked(bool checked)
+{
+    m_checked = checked;
+}
+
+bool ContextMenuItem::checked() const
+{
+    return m_checked;
+}
+
+void ContextMenuItem::setEnabled(bool enabled)
+{
+    m_enabled = enabled;
+}
+
+bool ContextMenuItem::enabled() const
+{
+    return m_enabled;
+}
+
+} // namespace WebCore
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
diff --git a/WebCore/platform/ContextMenuItem.h b/WebCore/platform/ContextMenuItem.h
index e702921..c1302ea 100644
--- a/WebCore/platform/ContextMenuItem.h
+++ b/WebCore/platform/ContextMenuItem.h
@@ -40,7 +40,7 @@
 class NSMenuItem;
 #endif
 #elif PLATFORM(WIN)
-typedef struct tagMENUITEMINFOW* LPMENUITEMINFO;
+typedef struct tagMENUITEMINFOW MENUITEMINFO;
 #elif PLATFORM(GTK)
 typedef struct _GtkMenuItem GtkMenuItem;
 #elif PLATFORM(QT)
@@ -166,8 +166,6 @@ namespace WebCore {
 
 #if PLATFORM(MAC)
     typedef NSMenuItem* PlatformMenuItemDescription;
-#elif PLATFORM(WIN)
-    typedef LPMENUITEMINFO PlatformMenuItemDescription;
 #elif PLATFORM(QT)
     struct PlatformMenuItemDescription {
         PlatformMenuItemDescription()
@@ -254,49 +252,79 @@ namespace WebCore {
 
     class ContextMenuItem : public FastAllocBase {
     public:
+        ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, ContextMenu* subMenu = 0);
+        ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool enabled, bool checked);
+
+        ~ContextMenuItem();
+
+        void setType(ContextMenuItemType);
+        ContextMenuItemType type() const;
+
+        void setAction(ContextMenuAction);
+        ContextMenuAction action() const;
+
+        void setChecked(bool = true);
+        bool checked() const;
+
+        void setEnabled(bool = true);
+        bool enabled() const;
+
+        void setSubMenu(ContextMenu*);
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#if PLATFORM(WIN)
+        typedef MENUITEMINFO NativeItem;
+#endif
+        ContextMenuItem(ContextMenuAction, const String&, bool enabled, bool checked, const Vector<ContextMenuItem>& subMenuItems);
+        explicit ContextMenuItem(const NativeItem&);
+
+        // On Windows, the title (dwTypeData of the MENUITEMINFO) is not set in this function. Callers can set the title themselves,
+        // and handle the lifetime of the title, if they need it.
+        NativeItem nativeMenuItem() const;
+
+        void setTitle(const String& title) { m_title = title; }
+        const String& title() const { return m_title; }
+
+        const Vector<ContextMenuItem>& subMenuItems() const { return m_subMenuItems; }
+#else
+    public:
         ContextMenuItem(PlatformMenuItemDescription);
         ContextMenuItem(ContextMenu* subMenu = 0);
-        ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu = 0);
-
-        ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool enabled, bool checked);
         ContextMenuItem(ContextMenuAction, const String&, bool enabled, bool checked, Vector<ContextMenuItem>& submenuItems);
+
 #if PLATFORM(GTK)
         ContextMenuItem(GtkMenuItem*);
 #endif
-        ~ContextMenuItem();
 
         PlatformMenuItemDescription releasePlatformDescription();
 
-        ContextMenuItemType type() const;
-        void setType(ContextMenuItemType);
-
-        ContextMenuAction action() const;
-        void setAction(ContextMenuAction);
-
         String title() const;
         void setTitle(const String&);
 
         PlatformMenuDescription platformSubMenu() const;
-        void setSubMenu(ContextMenu*);
         void setSubMenu(Vector<ContextMenuItem>&);
 
-        void setChecked(bool = true);
-        bool checked() const;
-
-        void setEnabled(bool = true);
-        bool enabled() const;
-
         // FIXME: Do we need a keyboard accelerator here?
 #if PLATFORM(GTK)
         static GtkMenuItem* createNativeMenuItem(const PlatformMenuItemDescription&);
 #endif
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
 
     private:
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+        String m_title;
+        bool m_enabled;
+        bool m_checked;
+        ContextMenuAction m_action;
+        ContextMenuItemType m_type;
+        Vector<ContextMenuItem> m_subMenuItems;
+#else
 #if PLATFORM(MAC)
         RetainPtr<NSMenuItem> m_platformDescription;
 #else
         PlatformMenuItemDescription m_platformDescription;
 #endif
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
     };
 
 }
diff --git a/WebCore/platform/PlatformMenuDescription.h b/WebCore/platform/PlatformMenuDescription.h
index 380ded4..f3cc001 100644
--- a/WebCore/platform/PlatformMenuDescription.h
+++ b/WebCore/platform/PlatformMenuDescription.h
@@ -32,8 +32,6 @@
 #else
 class NSMutableArray;
 #endif
-#elif PLATFORM(WIN)
-typedef struct HMENU__* HMENU;
 #elif PLATFORM(QT)
 #include <qlist.h>
 #elif PLATFORM(GTK)
@@ -46,10 +44,9 @@ class BMenu;
 
 namespace WebCore {
 
+#if !USE(CROSS_PLATFORM_CONTEXT_MENUS)
 #if PLATFORM(MAC)
     typedef NSMutableArray* PlatformMenuDescription;
-#elif PLATFORM(WIN)
-    typedef HMENU PlatformMenuDescription;
 #elif PLATFORM(QT)
     class ContextMenuItem;
     typedef const QList<ContextMenuItem>* PlatformMenuDescription;
@@ -62,6 +59,7 @@ namespace WebCore {
 #else
     typedef void* PlatformMenuDescription;
 #endif
+#endif // !USE(CROSS_PLATFORM_CONTEXT_MENUS)
 
 } // namespace
 
diff --git a/WebCore/platform/win/ContextMenuItemWin.cpp b/WebCore/platform/win/ContextMenuItemWin.cpp
index 8d1c175..59aedcd 100644
--- a/WebCore/platform/win/ContextMenuItemWin.cpp
+++ b/WebCore/platform/win/ContextMenuItemWin.cpp
@@ -28,198 +28,66 @@
 
 #include "ContextMenu.h"
 
-#include <wtf/text/CString.h>
-#include <windows.h>
-
-#if OS(WINCE)
-#ifndef MFS_DISABLED
-#define MFS_DISABLED MF_GRAYED
-#endif
-#ifndef MIIM_FTYPE
-#define MIIM_FTYPE MIIM_TYPE
-#endif
-#ifndef MIIM_STRING
-#define MIIM_STRING 0
-#endif
-#endif
-
 namespace WebCore {
 
-ContextMenuItem::ContextMenuItem(LPMENUITEMINFO item)
-    : m_platformDescription(item)
-{
-}
-
-ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
+ContextMenuItem::ContextMenuItem(const MENUITEMINFO& info)
 {
-    m_platformDescription = (LPMENUITEMINFO)malloc(sizeof(MENUITEMINFO));
-    if (!m_platformDescription)
-        return;
+    if (info.fMask & MIIM_FTYPE)
+        m_type = info.fType == MFT_SEPARATOR ? SeparatorType : ActionType;
+    else
+        m_type = SeparatorType;
 
-    memset(m_platformDescription, 0, sizeof(MENUITEMINFO));
-    m_platformDescription->cbSize = sizeof(MENUITEMINFO);
+    if (m_type == ActionType && info.fMask & MIIM_STRING)
+        m_title = String(info.dwTypeData, info.cch);
 
-    m_platformDescription->wID = ContextMenuItemTagNoAction;
-    if (subMenu) {
-        m_platformDescription->fMask |= MIIM_SUBMENU;
-        m_platformDescription->hSubMenu = subMenu->platformDescription();
+    if ((info.fMask & MIIM_SUBMENU) && info.hSubMenu) {
+        m_type = SubmenuType;
+        ContextMenu::getContextMenuItems(info.hSubMenu, m_subMenuItems);
     }
-}
-
-ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
-{
-    m_platformDescription = (LPMENUITEMINFO)malloc(sizeof(MENUITEMINFO));
-    if (!m_platformDescription)
-        return;
 
-    memset(m_platformDescription, 0, sizeof(MENUITEMINFO));
-    m_platformDescription->cbSize = sizeof(MENUITEMINFO);
-    m_platformDescription->fMask = MIIM_FTYPE;
+    if (info.fMask & MIIM_ID)
+        m_action = static_cast<ContextMenuAction>(info.wID);
+    else
+        m_action = ContextMenuItemTagNoAction;
 
-    if (type == SeparatorType) {
-        m_platformDescription->fType = MFT_SEPARATOR;
-        return;
+    if (info.fMask & MIIM_STATE) {
+        m_checked = info.fState & MFS_CHECKED;
+        m_enabled = !(info.fState & MFS_DISABLED);
+    } else {
+        m_checked = false;
+        m_enabled = false;
     }
-    
-    if (subMenu) {
-        m_platformDescription->fMask |= MIIM_STRING | MIIM_SUBMENU;
-        m_platformDescription->hSubMenu = subMenu->platformDescription();
-    } else
-        m_platformDescription->fMask |= MIIM_STRING | MIIM_ID;
-
-    m_platformDescription->fType = MFT_STRING;
-    m_platformDescription->wID = action;
-    
-    String t = title;
-    m_platformDescription->cch = t.length();
-    m_platformDescription->dwTypeData = wcsdup(t.charactersWithNullTermination());
 }
 
-ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool, bool)
+// ContextMenuItem::nativeMenuItem doesn't set the info.dwTypeData. This is
+// done to make the lifetime handling of the returned MENUITEMINFO easier on
+// callers. Callers can set dwTypeData themselves (and make their own decisions
+// about its lifetime) if they need it.
+MENUITEMINFO ContextMenuItem::nativeMenuItem() const
 {
-    // FIXME: Implement
-}
+    MENUITEMINFO info = {0};
+    info.cbSize = sizeof(MENUITEMINFO);
 
-ContextMenuItem::ContextMenuItem(ContextMenuAction, const String&, bool, bool, Vector<ContextMenuItem>&)
-{
-    // FIXME: Implement
-}
-
-ContextMenuItem::~ContextMenuItem()
-{
-    if (m_platformDescription) {
-        if (m_platformDescription->fType == MFT_STRING)
-            free(m_platformDescription->dwTypeData);
-        free(m_platformDescription);
+    if (m_type == SeparatorType) {
+        info.fMask = MIIM_FTYPE;
+        info.fType = MFT_SEPARATOR;
+        return info;
     }
-}
-
-LPMENUITEMINFO ContextMenuItem::releasePlatformDescription()
-{
-    LPMENUITEMINFO info = m_platformDescription;
-    m_platformDescription = 0;
-    return info;
-}
-
-ContextMenuItemType ContextMenuItem::type() const
-{
-    ContextMenuItemType type = ActionType;
-    if (((m_platformDescription->fType & ~MFT_OWNERDRAW) == MFT_STRING) && m_platformDescription->hSubMenu)
-        type = SubmenuType;
-    else if (m_platformDescription->fType & MFT_SEPARATOR)
-        type = SeparatorType;
-
-    return type;
-}
-
-ContextMenuAction ContextMenuItem::action() const
-{ 
-    return static_cast<ContextMenuAction>(m_platformDescription->wID);
-}
-
-String ContextMenuItem::title() const 
-{
-    return String(m_platformDescription->dwTypeData, wcslen(m_platformDescription->dwTypeData));
-}
-
-PlatformMenuDescription ContextMenuItem::platformSubMenu() const
-{
-    return m_platformDescription->hSubMenu;
-}
-
-void ContextMenuItem::setType(ContextMenuItemType type)
-{
-    if (type == SeparatorType)
-        m_platformDescription->fType = MFT_SEPARATOR;
-    else
-        m_platformDescription->fType = MFT_STRING;
-}
-
-void ContextMenuItem::setAction(ContextMenuAction action)
-{
-    m_platformDescription->wID = action; 
-}
-
-void ContextMenuItem::setTitle(const String& title)
-{
-    if (m_platformDescription->dwTypeData)
-        free(m_platformDescription->dwTypeData);
-    
-    m_platformDescription->cch = title.length();
-    String titleCopy = title;
-    m_platformDescription->dwTypeData = wcsdup(titleCopy.charactersWithNullTermination());
-}
-
-void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
-{
-    if (subMenu->platformDescription() == m_platformDescription->hSubMenu)
-        return;
-
-    if (m_platformDescription->hSubMenu)
-        ::DestroyMenu(m_platformDescription->hSubMenu);
 
-    m_platformDescription->fMask |= MIIM_SUBMENU;
-    m_platformDescription->hSubMenu = subMenu->releasePlatformDescription();
-}
+    info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE;
+    info.fType = MFT_STRING;
 
-void ContextMenuItem::setSubMenu(Vector<ContextMenuItem>&)
-{
-    // FIXME: Implement
-}
+    info.wID = m_action;
 
-void ContextMenuItem::setChecked(bool checked)
-{
-    m_platformDescription->fMask |= MIIM_STATE;
-    if (checked) {
-        m_platformDescription->fState &= ~MFS_UNCHECKED;
-        m_platformDescription->fState |= MFS_CHECKED;
-    } else {
-        m_platformDescription->fState &= ~MFS_CHECKED;
-        m_platformDescription->fState |= MFS_UNCHECKED;
+    if (m_type == SubmenuType) {
+        info.fMask |= MIIM_SUBMENU;
+        info.hSubMenu = ContextMenu::createNativeMenuFromItems(m_subMenuItems);
     }
-}
 
-bool ContextMenuItem::checked() const
-{
-    // FIXME - Implement
-    return false;
-}
+    info.fState |= m_enabled ? MFS_ENABLED : MFS_DISABLED;
+    info.fState |= m_checked ? MFS_CHECKED : MFS_UNCHECKED;
 
-void ContextMenuItem::setEnabled(bool enabled)
-{
-    m_platformDescription->fMask |= MIIM_STATE;
-    if (enabled) {
-        m_platformDescription->fState &= ~MFS_DISABLED;
-        m_platformDescription->fState |= MFS_ENABLED;
-    } else {
-        m_platformDescription->fState &= ~MFS_ENABLED;
-        m_platformDescription->fState |= MFS_DISABLED;
-    }
-}
-
-bool ContextMenuItem::enabled() const
-{
-    return !(m_platformDescription->fState & MFS_DISABLED);
+    return info;
 }
 
 }
diff --git a/WebCore/platform/win/ContextMenuWin.cpp b/WebCore/platform/win/ContextMenuWin.cpp
index 781fd6e..24c355d 100644
--- a/WebCore/platform/win/ContextMenuWin.cpp
+++ b/WebCore/platform/win/ContextMenuWin.cpp
@@ -32,6 +32,7 @@
 #include "Node.h"
 #include <tchar.h>
 #include <windows.h>
+#include <wtf/Vector.h>
 #include <wtf/text/CString.h>
 
 #ifndef MIIM_FTYPE
@@ -43,180 +44,67 @@
 
 namespace WebCore {
 
-ContextMenu::ContextMenu()
-    : m_platformDescription(0)
-#if OS(WINCE)
-    , m_itemCount(0)
-#endif
-{
-    setPlatformDescription(::CreatePopupMenu());
-}
-
-ContextMenu::ContextMenu(const PlatformMenuDescription menu)
-    : m_platformDescription(0)
-#if OS(WINCE)
-    , m_itemCount(0)
-#endif
-{
-    setPlatformDescription(menu);
-}
-
-ContextMenu::~ContextMenu()
-{
-    if (m_platformDescription)
-        ::DestroyMenu(m_platformDescription);
-}
-
-unsigned ContextMenu::itemCount() const
-{
-#if OS(WINCE)
-    return m_itemCount;
-#else
-    if (!m_platformDescription)
-        return 0;
-
-    return ::GetMenuItemCount(m_platformDescription);
-#endif
-}
-
-#if OS(WINCE)
-static bool insertMenuItem(PlatformMenuDescription menu, unsigned int position, ContextMenuItem& item)
+ContextMenu::ContextMenu(HMENU menu)
 {
-    UINT flags = MF_BYPOSITION;
-    UINT newItem = 0;
-    LPCWSTR title = 0;
-
-    if (item.type() == SeparatorType)
-        flags |= MF_SEPARATOR;
-    else {
-        flags |= MF_STRING;
-        flags |= item.checked() ? MF_CHECKED : MF_UNCHECKED;
-        flags |= item.enabled() ? MF_ENABLED : MF_GRAYED;
-
-        PlatformMenuItemDescription description = item.releasePlatformDescription();
-        title = description->dwTypeData;
-        description->dwTypeData = 0;
-
-        if (description->hSubMenu) {
-            flags |= MF_POPUP;
-            newItem = reinterpret_cast<UINT>(description->hSubMenu);
-            description->hSubMenu = 0;
-        } else
-            newItem = description->wID;
-
-        free(description);
-    }
-
-    return ::InsertMenuW(menu, position, flags, newItem, title);
+    getContextMenuItems(menu, m_items);
 }
-#endif
 
-void ContextMenu::insertItem(unsigned int position, ContextMenuItem& item)
+void ContextMenu::getContextMenuItems(HMENU menu, Vector<ContextMenuItem>& items)
 {
-    if (!m_platformDescription)
+    int count = ::GetMenuItemCount(menu);
+    if (count <= 0)
         return;
 
-#if OS(WINCE)
-    if (insertMenuItem(m_platformDescription, position, item))
-        ++m_itemCount;
-#else
-    ::InsertMenuItem(m_platformDescription, position, TRUE, item.releasePlatformDescription());
-#endif
-}
-
-void ContextMenu::appendItem(ContextMenuItem& item)
-{
-    insertItem(itemCount(), item);
-}
-
-static ContextMenuItem* contextMenuItemByIdOrPosition(HMENU menu, unsigned id, BOOL byPosition)
-{
-    if (!menu)
-        return 0;
-    LPMENUITEMINFO info = static_cast<LPMENUITEMINFO>(malloc(sizeof(MENUITEMINFO)));
-    if (!info)
-        return 0;
-
-    memset(info, 0, sizeof(MENUITEMINFO));
+    for (int i = 0; i < count; ++i) {
+        MENUITEMINFO info = {0};
+        info.cbSize = sizeof(MENUITEMINFO);
+        info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
 
-    info->cbSize = sizeof(MENUITEMINFO);
-
-    // Setting MIIM_DATA which is useful for WebKit clients who store data in this member for their custom menu items.
-    info->fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_DATA;
-
-    if (!::GetMenuItemInfo(menu, id, byPosition, info)) {
-        free(info);
-        return 0;
-    }
+        if (!::GetMenuItemInfo(menu, i, TRUE, &info))
+            continue;
 
-    if (info->fType & MFT_STRING) {
-        LPTSTR buffer = static_cast<LPTSTR>(malloc(++info->cch * sizeof(TCHAR)));
-        if (!buffer) {
-            free(info);
-            return 0;
+        if (info.fType == MFT_SEPARATOR) {
+            items.append(ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String()));
+            continue;
         }
-        info->dwTypeData = buffer;
-        ::GetMenuItemInfo(menu, id, byPosition, info);
-    }
-
-    return new ContextMenuItem(info);
-}
 
-ContextMenuItem* ContextMenu::itemWithAction(unsigned action)
-{
-    return contextMenuItemByIdOrPosition(m_platformDescription, action, FALSE);
-}
+        int menuStringLength = info.cch + 1;
+        OwnArrayPtr<WCHAR> menuString(new WCHAR[menuStringLength]);
+        info.dwTypeData = menuString.get();
+        info.cch = menuStringLength;
 
-ContextMenuItem* ContextMenu::itemAtIndex(unsigned index, const PlatformMenuDescription platformDescription)
-{
-    return contextMenuItemByIdOrPosition(platformDescription, index, TRUE);
+        if (::GetMenuItemInfo(menu, i, TRUE, &info))
+           items.append(ContextMenuItem(info));
+    }
 }
 
-void ContextMenu::setPlatformDescription(HMENU menu)
+HMENU ContextMenu::createNativeMenuFromItems(const Vector<ContextMenuItem>& items)
 {
-    if (menu == m_platformDescription)
-        return;
-    
-    if (m_platformDescription)
-        ::DestroyMenu(m_platformDescription);
+    HMENU menu = ::CreatePopupMenu();
 
-    m_platformDescription = menu;
-    if (!m_platformDescription)
-        return;
+    for (size_t i = 0; i < items.size(); ++i) {
+        const ContextMenuItem& item = items[i];
 
-#if !OS(WINCE)
-    MENUINFO menuInfo = {0};
-    menuInfo.cbSize = sizeof(MENUINFO);
-    menuInfo.fMask = MIM_STYLE;
-    ::GetMenuInfo(m_platformDescription, &menuInfo);
-    menuInfo.fMask = MIM_STYLE;
-    menuInfo.dwStyle |= MNS_NOTIFYBYPOS;
-    ::SetMenuInfo(m_platformDescription, &menuInfo);
-#endif
-}
+        MENUITEMINFO menuItem = item.nativeMenuItem();
 
-HMENU ContextMenu::platformDescription() const
-{
-    return m_platformDescription;
-}
+        // ContextMenuItem::nativeMenuItem doesn't set the title of the MENUITEMINFO to make the
+        // lifetime handling easier for callers.
+        String itemTitle = item.title();
+        if (item.type() != SeparatorType) {
+            menuItem.fMask |= MIIM_STRING;
+            menuItem.cch = itemTitle.length();
+            menuItem.dwTypeData = const_cast<LPWSTR>(itemTitle.charactersWithNullTermination());
+        }
 
-HMENU ContextMenu::releasePlatformDescription()
-{
-    HMENU description = m_platformDescription;
-    m_platformDescription = 0;
-    return description;
-}
+        ::InsertMenuItem(menu, i, TRUE, &menuItem);
+    }
 
-Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription)
-{
-    // FIXME - Implement
-    return Vector<ContextMenuItem>();
+    return menu;
 }
 
-PlatformMenuDescription platformMenuDescription(Vector<ContextMenuItem>& menuItemVector)
+HMENU ContextMenu::nativeMenu() const
 {
-    // FIXME - Implement
-    return 0;
+    return createNativeMenuFromItems(m_items);
 }
 
 } // namespace WebCore
diff --git a/WebKit/win/ChangeLog b/WebKit/win/ChangeLog
index c0280ae..e06c64b 100644
--- a/WebKit/win/ChangeLog
+++ b/WebKit/win/ChangeLog
@@ -1,3 +1,23 @@
+2010-12-09  Brian Weinstein  <bweinstein at apple.com>
+
+        Reviewed by Adam Roben.
+
+        Prep for WebKit2: Context menu support on Windows
+        https://bugs.webkit.org/show_bug.cgi?id=50514
+        
+        Update WebKit for the new CROSS_PLATFORM_CONTEXT_MENUS flag, and define customizeMenu
+        instead of getCustomMenuFromDefaultItems.
+
+        * WebCoreSupport/WebContextMenuClient.cpp:
+        (WebContextMenuClient::customizeMenu): getCustomMenuFromDefaultItems was turned into
+            this function, with refactoring using nativeMenu instead of platformDescription.
+        (WebContextMenuClient::contextMenuItemSelected):  Use nativeMenu instead of platformDescription.
+        * WebCoreSupport/WebContextMenuClient.h:
+        * WebView.cpp:
+        (WebView::handleContextMenuEvent): Call nativeMenu instead of platformDescription.
+        (WebView::performContextMenuAction): Only call itemAtIndex with one argument, no need
+            for the second.
+
 2010-12-07  Brian Weinstein  <bweinstein at apple.com>
 
         Reviewed by John Sullivan.
diff --git a/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp b/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp
index ac92826..9405fc8 100644
--- a/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp
+++ b/WebKit/win/WebCoreSupport/WebContextMenuClient.cpp
@@ -55,21 +55,29 @@ void WebContextMenuClient::contextMenuDestroyed()
     delete this;
 }
 
-HMENU WebContextMenuClient::getCustomMenuFromDefaultItems(ContextMenu* menu)
+PassOwnPtr<ContextMenu> WebContextMenuClient::customizeMenu(PassOwnPtr<ContextMenu> popMenu)
 {
+    OwnPtr<ContextMenu> menu = popMenu;
+
     COMPtr<IWebUIDelegate> uiDelegate;
     if (FAILED(m_webView->uiDelegate(&uiDelegate)))
-        return menu->platformDescription();
+        return menu.release();
 
     ASSERT(uiDelegate);
 
-    HMENU newMenu = 0;
+    HMENU nativeMenu = menu->nativeMenu();
     COMPtr<WebElementPropertyBag> propertyBag;
     propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_webView->page()->contextMenuController()->hitTestResult()));
     // FIXME: We need to decide whether to do the default before calling this delegate method
-    if (FAILED(uiDelegate->contextMenuItemsForElement(m_webView, propertyBag.get(), (OLE_HANDLE)(ULONG64)menu->platformDescription(), (OLE_HANDLE*)&newMenu)))
-        return menu->platformDescription();
-    return newMenu;
+    if (FAILED(uiDelegate->contextMenuItemsForElement(m_webView, propertyBag.get(), (OLE_HANDLE)(ULONG64)nativeMenu, (OLE_HANDLE*)&nativeMenu))) {
+        ::DestroyMenu(nativeMenu);
+        return menu.release();
+    }
+    
+    OwnPtr<ContextMenu> customizedMenu = adoptPtr(new ContextMenu(nativeMenu));
+    ::DestroyMenu(nativeMenu);
+
+    return customizedMenu.release();
 }
 
 void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem* item, const ContextMenu* parentMenu)
@@ -84,8 +92,17 @@ void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem* item, const
 
     COMPtr<WebElementPropertyBag> propertyBag;
     propertyBag.adoptRef(WebElementPropertyBag::createInstance(m_webView->page()->contextMenuController()->hitTestResult()));
-            
-    uiDelegate->contextMenuItemSelected(m_webView, item->releasePlatformDescription(), propertyBag.get());
+
+    // This call would leak the MENUITEMINFO's subMenu if it had one, but on Windows, subMenus can't be selected, so there is
+    // no way we would get to this point. Also, it can't be a separator, because separators cannot be selected.
+    ASSERT(item->type() != SubmenuType);
+    ASSERT(item->type() != SeparatorType);
+
+    // ContextMenuItem::nativeMenuItem doesn't set the dwTypeData of the MENUITEMINFO, but no WebKit clients
+    // use the title in IWebUIDelegate::contextMenuItemSelected, so we don't need to populate it here.
+    MENUITEMINFO selectedItem = item->nativeMenuItem();
+
+    uiDelegate->contextMenuItemSelected(m_webView, &selectedItem, propertyBag.get());
 }
 
 void WebContextMenuClient::downloadURL(const KURL& url)
diff --git a/WebKit/win/WebCoreSupport/WebContextMenuClient.h b/WebKit/win/WebCoreSupport/WebContextMenuClient.h
index 6bcb072..ed41c59 100644
--- a/WebKit/win/WebCoreSupport/WebContextMenuClient.h
+++ b/WebKit/win/WebCoreSupport/WebContextMenuClient.h
@@ -23,8 +23,10 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
+#include <WebCore/ContextMenu.h>
 #include <WebCore/ContextMenuClient.h>
 #include <wtf/Forward.h>
+#include <wtf/PassOwnPtr.h>
 
 class WebView;
 
@@ -34,7 +36,7 @@ public:
 
     virtual void contextMenuDestroyed();
 
-    virtual HMENU getCustomMenuFromDefaultItems(WebCore::ContextMenu*);
+    virtual PassOwnPtr<WebCore::ContextMenu> customizeMenu(PassOwnPtr<WebCore::ContextMenu>);
     virtual void contextMenuItemSelected(WebCore::ContextMenuItem*, const WebCore::ContextMenu*);
     
     virtual void downloadURL(const WebCore::KURL&);
diff --git a/WebKit/win/WebView.cpp b/WebKit/win/WebView.cpp
index 73311d5..1b658bf 100644
--- a/WebKit/win/WebView.cpp
+++ b/WebKit/win/WebView.cpp
@@ -1275,12 +1275,12 @@ bool WebView::handleContextMenuEvent(WPARAM wParam, LPARAM lParam)
         m_uiDelegate->hasCustomMenuImplementation(&hasCustomMenus);
 
     if (hasCustomMenus)
-        m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->platformDescription(), &point);
+        m_uiDelegate->trackCustomPopupMenu((IWebView*)this, (OLE_HANDLE)(ULONG64)coreMenu->nativeMenu(), &point);
     else {
         // Surprisingly, TPM_RIGHTBUTTON means that items are selectable with either the right OR left mouse button
         UINT flags = TPM_RIGHTBUTTON | TPM_TOPALIGN | TPM_VERPOSANIMATION | TPM_HORIZONTAL
             | TPM_LEFTALIGN | TPM_HORPOSANIMATION;
-        ::TrackPopupMenuEx(coreMenu->platformDescription(), flags, point.x, point.y, m_viewWindow, 0);
+        ::TrackPopupMenuEx(coreMenu->nativeMenu(), flags, point.x, point.y, m_viewWindow, 0);
     }
 
     return true;
@@ -1355,11 +1355,10 @@ void WebView::performContextMenuAction(WPARAM wParam, LPARAM lParam, bool byPosi
     ContextMenu* menu = m_page->contextMenuController()->contextMenu();
     ASSERT(menu);
 
-    ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam, (HMENU)lParam) : menu->itemWithAction((ContextMenuAction)wParam);
+    ContextMenuItem* item = byPosition ? menu->itemAtIndex((unsigned)wParam) : menu->itemWithAction((ContextMenuAction)wParam);
     if (!item)
         return;
     m_page->contextMenuController()->contextMenuItemSelected(item);
-    delete item;
 }
 
 bool WebView::handleMouseEvent(UINT message, WPARAM wParam, LPARAM lParam)
diff --git a/WebKit2/ChangeLog b/WebKit2/ChangeLog
index 0fc8203..d8c89df 100644
--- a/WebKit2/ChangeLog
+++ b/WebKit2/ChangeLog
@@ -1,3 +1,25 @@
+2010-12-09  Brian Weinstein  <bweinstein at apple.com>
+
+        Reviewed by Adam Roben.
+
+        Prep for WebKit2: Context menu support on Windows
+        https://bugs.webkit.org/show_bug.cgi?id=50514
+        
+        Update WebKit2 to call the correct code when CROSS_PLATFORM_CONTEXT_MENUS is set.
+
+        * Shared/WebContextMenuItemData.cpp:
+        (WebKit::WebContextMenuItemData::WebContextMenuItemData): Add a branch based on whether or not 
+            CROSS_PLATFORM_CONTEXT_MENUS is set.
+        * WebProcess/WebCoreSupport/WebContextMenuClient.cpp:
+        (WebKit::WebContextMenuClient::customizeMenu): Define different functions based on
+            whether or not CROSS_PLATFORM_CONTEXT_MENUS. Both of these are stubs, so functionality
+            doesn't need to be shared.
+        * WebProcess/WebCoreSupport/WebContextMenuClient.h: Define different functions based on
+            whether or not CROSS_PLATFORM_CONTEXT_MENUS. 
+        * WebProcess/WebPage/WebContextMenu.cpp:
+        (WebKit::WebContextMenu::show): Add a branch based on whether or not 
+            CROSS_PLATFORM_CONTEXT_MENUS is set.
+
 2010-12-09  Enrica Casucci  <enrica at apple.com>
 
         Reviewed by Alexey Proskuryakov.
diff --git a/WebKit2/Shared/WebContextMenuItemData.cpp b/WebKit2/Shared/WebContextMenuItemData.cpp
index df6c7f2..aec8fa0 100644
--- a/WebKit2/Shared/WebContextMenuItemData.cpp
+++ b/WebKit2/Shared/WebContextMenuItemData.cpp
@@ -63,13 +63,17 @@ WebContextMenuItemData::WebContextMenuItemData(WebCore::ContextMenuAction action
 {
 }
 
-WebContextMenuItemData::WebContextMenuItemData(WebCore::ContextMenuItem& item, WebCore::ContextMenu* menu)
+WebContextMenuItemData::WebContextMenuItemData(const WebCore::ContextMenuItem& item, WebCore::ContextMenu* menu)
     : m_type(item.type())
     , m_action(item.action())
     , m_title(item.title())
 {
     if (m_type == WebCore::SubmenuType) {
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+        const Vector<WebCore::ContextMenuItem>& coreSubmenu = item.subMenuItems();
+#else
         Vector<WebCore::ContextMenuItem> coreSubmenu = WebCore::contextMenuItemVector(item.platformSubMenu());
+#endif
         m_submenu = kitItems(coreSubmenu, menu);
     }
     
@@ -130,7 +134,7 @@ bool WebContextMenuItemData::decode(CoreIPC::ArgumentDecoder* decoder, WebContex
     return true;
 }
 
-Vector<WebContextMenuItemData> kitItems(Vector<WebCore::ContextMenuItem>& coreItemVector, WebCore::ContextMenu* menu)
+Vector<WebContextMenuItemData> kitItems(const Vector<WebCore::ContextMenuItem>& coreItemVector, WebCore::ContextMenu* menu)
 {
     Vector<WebContextMenuItemData> result;
     result.reserveCapacity(coreItemVector.size());
diff --git a/WebKit2/Shared/WebContextMenuItemData.h b/WebKit2/Shared/WebContextMenuItemData.h
index 0aa9e5c..24af288 100644
--- a/WebKit2/Shared/WebContextMenuItemData.h
+++ b/WebKit2/Shared/WebContextMenuItemData.h
@@ -45,7 +45,7 @@ class APIObject;
 class WebContextMenuItemData {
 public:
     WebContextMenuItemData();
-    WebContextMenuItemData(WebCore::ContextMenuItem&, WebCore::ContextMenu* menu);
+    WebContextMenuItemData(const WebCore::ContextMenuItem&, WebCore::ContextMenu* menu);
     WebContextMenuItemData(WebCore::ContextMenuItemType, WebCore::ContextMenuAction, const String& title, bool enabled, bool checked);
     WebContextMenuItemData(WebCore::ContextMenuAction, const String& title, bool enabled, const Vector<WebContextMenuItemData>& submenu);
 
@@ -74,7 +74,7 @@ private:
     RefPtr<APIObject> m_userData;
 };
 
-Vector<WebContextMenuItemData> kitItems(Vector<WebCore::ContextMenuItem>&, WebCore::ContextMenu*);
+Vector<WebContextMenuItemData> kitItems(const Vector<WebCore::ContextMenuItem>&, WebCore::ContextMenu*);
 Vector<WebCore::ContextMenuItem> coreItems(const Vector<WebContextMenuItemData>&);
 
 } // namespace WebKit
diff --git a/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.cpp b/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.cpp
index 839869f..88618d7 100644
--- a/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.cpp
+++ b/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.cpp
@@ -44,11 +44,19 @@ void WebContextMenuClient::contextMenuDestroyed()
     delete this;
 }
 
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+PassOwnPtr<ContextMenu> WebContextMenuClient::customizeMenu(PassOwnPtr<ContextMenu> menu)
+{
+    // WebKit2 ignores this client callback and does context menu customization when it is told to show the menu.
+    return menu;
+}
+#else
 PlatformMenuDescription WebContextMenuClient::getCustomMenuFromDefaultItems(ContextMenu* menu)
 {
     // WebKit2 ignores this client callback and does context menu customization when it is told to show the menu.
     return menu->platformDescription();
 }
+#endif
 
 void WebContextMenuClient::contextMenuItemSelected(ContextMenuItem*, const ContextMenu*)
 {
diff --git a/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.h b/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.h
index c76235a..0545a7d 100644
--- a/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.h
+++ b/WebKit2/WebProcess/WebCoreSupport/WebContextMenuClient.h
@@ -42,7 +42,11 @@ public:
 private:
     virtual void contextMenuDestroyed();
     
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+    virtual PassOwnPtr<WebCore::ContextMenu> customizeMenu(PassOwnPtr<WebCore::ContextMenu>);
+#else
     virtual WebCore::PlatformMenuDescription getCustomMenuFromDefaultItems(WebCore::ContextMenu*);
+#endif
     virtual void contextMenuItemSelected(WebCore::ContextMenuItem*, const WebCore::ContextMenu*);
     
     virtual void downloadURL(const WebCore::KURL& url);
diff --git a/WebKit2/WebProcess/WebPage/WebContextMenu.cpp b/WebKit2/WebProcess/WebPage/WebContextMenu.cpp
index c335fe2..5617f5e 100644
--- a/WebKit2/WebProcess/WebPage/WebContextMenu.cpp
+++ b/WebKit2/WebProcess/WebPage/WebContextMenu.cpp
@@ -64,7 +64,11 @@ void WebContextMenu::show()
         return;
 
     // Give the bundle client a chance to process the menu.
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+    const Vector<ContextMenuItem>& coreItems = menu->items();
+#else
     Vector<ContextMenuItem> coreItems = contextMenuItemVector(menu->platformDescription());
+#endif
     Vector<WebContextMenuItemData> proposedMenu = kitItems(coreItems, menu);
     Vector<WebContextMenuItemData> newMenu;
     RefPtr<APIObject> userData;

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list