2011-06-13 Carlos Garcia Campos <cgarcia@igalia.com>
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Jun 2011 09:35:30 +0000 (09:35 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 13 Jun 2011 09:35:30 +0000 (09:35 +0000)
        Reviewed by Martin Robinson.

        [GTK] Add context menu support for Webkit2
        https://bugs.webkit.org/show_bug.cgi?id=54827

        * platform/ContextMenuItem.h: Add gtkAction().
        * platform/gtk/ContextMenuGtk.cpp:
        (WebCore::ContextMenu::ContextMenu): Implement constructor that
        receives a platform menu.
        (WebCore::ContextMenu::setPlatformDescription): Make sure we don't
        destroy the menu if the new context menu is the current one.
        (WebCore::contextMenuItemVector): Implement this method to return
        the list of menu items in the given context menu, required by WebKit2.
        (WebCore::platformMenuDescription): Implement this method to
        return a platform menu for the given menu items.
        * platform/gtk/ContextMenuItemGtk.cpp:
        (WebCore::createPlatformMenuItemDescription): Helper function to
        create a platform context menu item.
        (WebCore::ContextMenuItem::ContextMenuItem): Use
        createPlatformMenuItemDescription().
        (WebCore::ContextMenuItem::title): Convert the title from UTF-8.
        (WebCore::ContextMenuItem::setTitle): Use gtkAction().
        (WebCore::ContextMenuItem::setSubMenu): Implement setSubMenu()
        that receives a list of items.
        (WebCore::ContextMenuItem::setChecked): Use gtkAction().
        (WebCore::ContextMenuItem::checked): Implement this, required by WebKit2.
        (WebCore::ContextMenuItem::enabled): Ditto.
        (WebCore::ContextMenuItem::setEnabled): Use gtkAction().
        (WebCore::ContextMenuItem::gtkAction): Return the GtkAction
        associated to the context menu item.
2011-06-13  Carlos Garcia Campos  <cgarcia@igalia.com>

        Reviewed by Martin Robinson.

        [GTK] Add context menu support for Webkit2
        https://bugs.webkit.org/show_bug.cgi?id=54827

        * GNUmakefile.am: Add new files to compilation.
        * UIProcess/API/gtk/PageClientImpl.cpp:
        (WebKit::PageClientImpl::createContextMenuProxy): Create a context
        menu proxy.
        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
        (globalPointForClientPoint): Function copied from webkit1 to
        convert a point in widget coordinates to global coordinates.
        (popupMenuPositionFunction):
        (webkitWebViewBaseShowContextMenu): Show the given context menu at
        the given position.
        * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
        * UIProcess/gtk/WebContextMenuProxyGtk.cpp: Added.
        (WebKit::contextMenuItemActivatedCallback):
        (WebKit::WebContextMenuProxyGtk::createGtkMenu):
        (WebKit::WebContextMenuProxyGtk::showContextMenu):
        (WebKit::WebContextMenuProxyGtk::hideContextMenu):
        (WebKit::WebContextMenuProxyGtk::WebContextMenuProxyGtk):
        (WebKit::WebContextMenuProxyGtk::~WebContextMenuProxyGtk):
        * UIProcess/gtk/WebContextMenuProxyGtk.h: Copied from Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h.
        (WebKit::WebContextMenuProxyGtk::create):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@88634 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/ContextMenuItem.h
Source/WebCore/platform/gtk/ContextMenuGtk.cpp
Source/WebCore/platform/gtk/ContextMenuItemGtk.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/GNUmakefile.am
Source/WebKit2/UIProcess/API/gtk/PageClientImpl.cpp
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.h [new file with mode: 0644]

index e55ae73..04832ac 100644 (file)
@@ -1,3 +1,36 @@
+2011-06-13  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        Reviewed by Martin Robinson.
+
+        [GTK] Add context menu support for Webkit2
+        https://bugs.webkit.org/show_bug.cgi?id=54827
+
+        * platform/ContextMenuItem.h: Add gtkAction().
+        * platform/gtk/ContextMenuGtk.cpp:
+        (WebCore::ContextMenu::ContextMenu): Implement constructor that
+        receives a platform menu.
+        (WebCore::ContextMenu::setPlatformDescription): Make sure we don't
+        destroy the menu if the new context menu is the current one.
+        (WebCore::contextMenuItemVector): Implement this method to return
+        the list of menu items in the given context menu, required by WebKit2.
+        (WebCore::platformMenuDescription): Implement this method to
+        return a platform menu for the given menu items.
+        * platform/gtk/ContextMenuItemGtk.cpp:
+        (WebCore::createPlatformMenuItemDescription): Helper function to
+        create a platform context menu item.
+        (WebCore::ContextMenuItem::ContextMenuItem): Use
+        createPlatformMenuItemDescription().
+        (WebCore::ContextMenuItem::title): Convert the title from UTF-8.
+        (WebCore::ContextMenuItem::setTitle): Use gtkAction().
+        (WebCore::ContextMenuItem::setSubMenu): Implement setSubMenu()
+        that receives a list of items.
+        (WebCore::ContextMenuItem::setChecked): Use gtkAction().
+        (WebCore::ContextMenuItem::checked): Implement this, required by WebKit2.
+        (WebCore::ContextMenuItem::enabled): Ditto.
+        (WebCore::ContextMenuItem::setEnabled): Use gtkAction().
+        (WebCore::ContextMenuItem::gtkAction): Return the GtkAction
+        associated to the context menu item.
+
 2011-06-13  Keishi Hattori  <keishi@webkit.org>
 
         Sort WebCore.xcodeproj
index 46a6987..7b33d0c 100644 (file)
@@ -43,6 +43,7 @@ class NSMenuItem;
 typedef struct tagMENUITEMINFOW MENUITEMINFO;
 #elif PLATFORM(GTK)
 typedef struct _GtkMenuItem GtkMenuItem;
+typedef struct _GtkAction GtkAction;
 #elif PLATFORM(QT)
 #include <QAction>
 #elif PLATFORM(WX)
@@ -248,6 +249,10 @@ namespace WebCore {
 
         void setSubMenu(ContextMenu*);
 
+#if PLATFORM(GTK)
+        GtkAction* gtkAction() const;
+#endif
+
 #if USE(CROSS_PLATFORM_CONTEXT_MENUS)
 #if PLATFORM(WIN)
         typedef MENUITEMINFO NativeItem;
index b34631d..6f168fe 100644 (file)
@@ -20,7 +20,7 @@
 #include "config.h"
 #include "ContextMenu.h"
 
-#include "NotImplemented.h"
+#include "GOwnPtr.h"
 #include <gtk/gtk.h>
 
 namespace WebCore {
@@ -30,6 +30,11 @@ ContextMenu::ContextMenu()
     m_platformDescription = GTK_MENU(gtk_menu_new());
 }
 
+ContextMenu::ContextMenu(const PlatformMenuDescription menu)
+    : m_platformDescription(menu)
+{
+}
+
 ContextMenu::~ContextMenu()
 {
     if (m_platformDescription)
@@ -49,6 +54,8 @@ void ContextMenu::appendItem(ContextMenuItem& item)
 void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
 {
     ASSERT(menu);
+    if (m_platformDescription == menu)
+        return;
     if (m_platformDescription)
         gtk_widget_destroy(GTK_WIDGET(m_platformDescription));
 
@@ -68,12 +75,33 @@ PlatformMenuDescription ContextMenu::releasePlatformDescription()
     return description;
 }
 
-Vector<ContextMenuItem> contextMenuItemVector(const PlatformMenuDescription)
+Vector<ContextMenuItem> contextMenuItemVector(const PlatformMenuDescription menu)
 {
-    notImplemented();
-
     Vector<ContextMenuItem> menuItemVector;
+
+    GOwnPtr<GList> children(gtk_container_get_children(GTK_CONTAINER(menu)));
+    int itemCount = g_list_length(children.get());
+    menuItemVector.reserveCapacity(itemCount);
+
+    for (GList* item = children.get(); item; item = g_list_next(item)) {
+        GtkWidget* widget = static_cast<GtkWidget*>(item->data);
+        if (!GTK_IS_MENU_ITEM(widget))
+            continue;
+        menuItemVector.append(ContextMenuItem(GTK_MENU_ITEM(widget)));
+    }
+
     return menuItemVector;
 }
 
+PlatformMenuDescription platformMenuDescription(Vector<ContextMenuItem>& subMenuItems)
+{
+    GtkMenu* menu = GTK_MENU(gtk_menu_new());
+    for (size_t i = 0; i < subMenuItems.size(); i++) {
+        GtkWidget* platformItem = GTK_WIDGET(subMenuItems[i].releasePlatformDescription());
+        gtk_menu_shell_append(GTK_MENU_SHELL(menu), platformItem);
+        gtk_widget_show(platformItem);
+    }
+    return menu;
+}
+
 }
index bdd3962..227a7a1 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "ContextMenu.h"
 #include "GOwnPtr.h"
-#include "NotImplemented.h"
+#include "GRefPtr.h"
 #include <gtk/gtk.h>
 #include <wtf/text/CString.h>
 
@@ -117,51 +117,56 @@ static const char* gtkStockIDFromContextMenuAction(const ContextMenuAction& acti
     }
 }
 
+static PlatformMenuItemDescription createPlatformMenuItemDescription(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
+{
+    if (type == SeparatorType)
+        return GTK_MENU_ITEM(gtk_separator_menu_item_new());
+
+    GOwnPtr<char> actionName(g_strdup_printf("context-menu-action-%d", action));
+    GRefPtr<GtkAction> platformAction;
+
+    if (type == CheckableActionType) {
+        platformAction = adoptGRef(GTK_ACTION(gtk_toggle_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action))));
+        gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(platformAction.get()), checked);
+    } else
+        platformAction = adoptGRef(gtk_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action)));
+    gtk_action_set_sensitive(platformAction.get(), enabled);
+
+    GtkMenuItem* item = GTK_MENU_ITEM(gtk_action_create_menu_item(platformAction.get()));
+    g_object_set_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
+
+    return item;
+}
+
 // Extract the ActionType from the menu item
 ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
     : m_platformDescription(item)
 {
 }
 
-ContextMenuItem::ContextMenuItem(ContextMenu*)
+ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
 {
-    notImplemented();
+    m_platformDescription = GTK_MENU_ITEM(gtk_menu_item_new());
+    if (subMenu)
+        setSubMenu(subMenu);
 }
 
 ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
 {
-    if (type == SeparatorType) {
-        m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
-        return;
-    }
-
-    GOwnPtr<char> actionName(g_strdup_printf("context-menu-action-%d", action));
-    GtkAction* platformAction = 0;
-
-    if (type == CheckableActionType)
-        platformAction = GTK_ACTION(gtk_toggle_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action)));
-    else
-        platformAction = gtk_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action));
-
-    m_platformDescription = GTK_MENU_ITEM(gtk_action_create_menu_item(platformAction));
-    g_object_unref(platformAction);
-
-    g_object_set_data(G_OBJECT(m_platformDescription), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
-
+    m_platformDescription = createPlatformMenuItemDescription(type, action, title, true, false);
     if (subMenu)
         setSubMenu(subMenu);
 }
 
-ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool, bool)
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
 {
-    // FIXME: Implement with WebKit2 ContextMenu changes.
-    notImplemented();
+    m_platformDescription = createPlatformMenuItemDescription(type, action, title, enabled, checked);
 }
 
-ContextMenuItem::ContextMenuItem(ContextMenuAction, const String&, bool, bool, Vector<ContextMenuItem>&)
+ContextMenuItem::ContextMenuItem(ContextMenuAction action, const String& title, bool enabled, bool checked, Vector<ContextMenuItem>& subMenuItems)
 {
-    // FIXME: Implement with WebKit2 ContextMenu changes.
-    notImplemented();
+    m_platformDescription = createPlatformMenuItemDescription(SubmenuType, action, title, enabled, checked);
+    setSubMenu(subMenuItems);
 }
 
 ContextMenuItem::~ContextMenuItem()
@@ -204,13 +209,13 @@ void ContextMenuItem::setAction(ContextMenuAction action)
 
 String ContextMenuItem::title() const
 {
-    GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
-    return action ? String(gtk_action_get_label(action)) : String();
+    GtkAction* action = gtkAction();
+    return action ? String::fromUTF8(gtk_action_get_label(action)) : String();
 }
 
 void ContextMenuItem::setTitle(const String& title)
 {
-    GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
+    GtkAction* action = gtkAction();
     if (action)
         gtk_action_set_label(action, title.utf8().data());
 }
@@ -223,35 +228,46 @@ PlatformMenuDescription ContextMenuItem::platformSubMenu() const
 
 void ContextMenuItem::setSubMenu(ContextMenu* menu)
 {
-    gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->platformDescription()));
+    gtk_menu_item_set_submenu(m_platformDescription, GTK_WIDGET(menu->releasePlatformDescription()));
+}
+
+void ContextMenuItem::setSubMenu(Vector<ContextMenuItem>& subMenuItems)
+{
+    ContextMenu menu(platformMenuDescription(subMenuItems));
+    setSubMenu(&menu);
 }
 
 void ContextMenuItem::setChecked(bool shouldCheck)
 {
-    GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
+    GtkAction* action = gtkAction();
     if (action && GTK_IS_TOGGLE_ACTION(action))
         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), shouldCheck);
 }
 
 bool ContextMenuItem::checked() const
 {
-    // FIXME: Implement with WebKit2 ContextMenu changes.
-    notImplemented();
+    GtkAction* action = gtkAction();
+    if (action && GTK_IS_TOGGLE_ACTION(action))
+        return gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action));
     return false;
 }
 
 bool ContextMenuItem::enabled() const
 {
-    // FIXME: Implement with WebKit2 ContextMenu changes.
-    notImplemented();
-    return false;
+    GtkAction* action = gtkAction();
+    return action ? gtk_action_get_sensitive(action) : false;
 }
 
 void ContextMenuItem::setEnabled(bool shouldEnable)
 {
-    GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
+    GtkAction* action = gtkAction();
     if (action)
         gtk_action_set_sensitive(action, shouldEnable);
 }
 
+GtkAction* ContextMenuItem::gtkAction() const
+{
+    return gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription));
+}
+
 }
index 0d8ef26..867518b 100644 (file)
@@ -2,6 +2,34 @@
 
         Reviewed by Martin Robinson.
 
+        [GTK] Add context menu support for Webkit2
+        https://bugs.webkit.org/show_bug.cgi?id=54827
+
+        * GNUmakefile.am: Add new files to compilation.
+        * UIProcess/API/gtk/PageClientImpl.cpp:
+        (WebKit::PageClientImpl::createContextMenuProxy): Create a context
+        menu proxy.
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (globalPointForClientPoint): Function copied from webkit1 to
+        convert a point in widget coordinates to global coordinates.
+        (popupMenuPositionFunction):
+        (webkitWebViewBaseShowContextMenu): Show the given context menu at
+        the given position.
+        * UIProcess/API/gtk/WebKitWebViewBasePrivate.h:
+        * UIProcess/gtk/WebContextMenuProxyGtk.cpp: Added.
+        (WebKit::contextMenuItemActivatedCallback):
+        (WebKit::WebContextMenuProxyGtk::createGtkMenu):
+        (WebKit::WebContextMenuProxyGtk::showContextMenu):
+        (WebKit::WebContextMenuProxyGtk::hideContextMenu):
+        (WebKit::WebContextMenuProxyGtk::WebContextMenuProxyGtk):
+        (WebKit::WebContextMenuProxyGtk::~WebContextMenuProxyGtk):
+        * UIProcess/gtk/WebContextMenuProxyGtk.h: Copied from Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h.
+        (WebKit::WebContextMenuProxyGtk::create):
+
+2011-06-13  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        Reviewed by Martin Robinson.
+
         [GTK] Export an API similar to WebKit1
         https://bugs.webkit.org/show_bug.cgi?id=57820
 
index 4220b05..8b2c31f 100644 (file)
@@ -394,6 +394,8 @@ libwebkit2gtk_@WEBKITGTK_API_MAJOR_VERSION@_@WEBKITGTK_API_MINOR_VERSION@_la_SOU
        Source/WebKit2/UIProcess/gtk/BackingStoreGtk.cpp \
        Source/WebKit2/UIProcess/gtk/TextCheckerGtk.cpp \
        Source/WebKit2/UIProcess/gtk/WebContextGtk.cpp \
+       Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.cpp \
+       Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.h \
        Source/WebKit2/UIProcess/gtk/WebFullScreenManagerProxyGtk.cpp \
        Source/WebKit2/UIProcess/gtk/WebInspectorGtk.cpp \
        Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp \
index af554e8..deeb339 100644 (file)
@@ -33,7 +33,7 @@
 #include "NativeWebMouseEvent.h"
 #include "NotImplemented.h"
 #include "WebContext.h"
-#include "WebContextMenuProxy.h"
+#include "WebContextMenuProxyGtk.h"
 #include "WebEventFactory.h"
 #include "WebKitWebViewBasePrivate.h"
 #include "WebPageProxy.h"
@@ -210,10 +210,9 @@ PassRefPtr<WebPopupMenuProxy> PageClientImpl::createPopupMenuProxy(WebPageProxy*
     return WebPopupMenuProxyGtk::create(m_viewWidget, page);
 }
 
-PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy*)
+PassRefPtr<WebContextMenuProxy> PageClientImpl::createContextMenuProxy(WebPageProxy* page)
 {
-    notImplemented();
-    return 0;
+    return WebContextMenuProxyGtk::create(m_viewWidget, page);
 }
 
 void PageClientImpl::setFindIndicator(PassRefPtr<FindIndicator>, bool fadeOut)
index 47ca5b3..0ac6aa5 100644 (file)
@@ -56,6 +56,7 @@ struct _WebKitWebViewBasePrivate {
     GtkIMContext* imContext;
     GtkClickCounter clickCounter;
     CString tooltipText;
+    IntPoint lastPopupPosition;
 };
 
 G_DEFINE_TYPE(WebKitWebViewBase, webkit_web_view_base, GTK_TYPE_CONTAINER)
@@ -378,3 +379,42 @@ void webkitWebViewBaseSetTooltipText(WebKitWebViewBase* webViewBase, const char*
     notImplemented();
 #endif
 }
+
+static IntPoint globalPointForClientPoint(GdkWindow* window, const IntPoint& clientPoint)
+{
+    int x, y;
+    gdk_window_get_origin(window, &x, &y);
+    return clientPoint + IntSize(x, y);
+}
+
+static void popupMenuPositionFunction(GtkMenu* menu, gint* x, gint* y, gboolean* pushIn, gpointer userData)
+{
+    WebKitWebViewBase* view = WEBKIT_WEB_VIEW_BASE(userData);
+    WebKitWebViewBasePrivate* priv = view->priv;
+    GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(view));
+    GtkRequisition menuSize;
+
+#ifdef GTK_API_VERSION_2
+    gtk_widget_size_request(GTK_WIDGET(menu), &menuSize);
+#else
+    gtk_widget_get_preferred_size(GTK_WIDGET(menu), &menuSize, 0);
+#endif
+
+    *x = priv->lastPopupPosition.x();
+    if ((*x + menuSize.width) >= gdk_screen_get_width(screen))
+        *x -= menuSize.width;
+
+    *y = priv->lastPopupPosition.y();
+    if ((*y + menuSize.height) >= gdk_screen_get_height(screen))
+        *y -= menuSize.height;
+
+    *pushIn = FALSE;
+}
+
+void webkitWebViewBaseShowContextMenu(WebKitWebViewBase* webViewBase, GtkMenu* menu, const IntPoint& position)
+{
+    webViewBase->priv->lastPopupPosition = globalPointForClientPoint(gtk_widget_get_window(GTK_WIDGET(webViewBase)), position);
+
+    // Display menu initiated by right click (mouse button pressed = 3).
+    gtk_menu_popup(menu, 0, 0, &popupMenuPositionFunction, webViewBase, 3, gtk_get_current_event_time());
+}
index 6996738..152582f 100644 (file)
@@ -46,6 +46,8 @@ void webkitWebViewBaseCreateWebPage(WebKitWebViewBase*, WKContextRef, WKPageGrou
 
 void webkitWebViewBaseSetTooltipText(WebKitWebViewBase*, const char*);
 
+void webkitWebViewBaseShowContextMenu(WebKitWebViewBase*, GtkMenu*, const WebCore::IntPoint&);
+
 G_END_DECLS
 
 #endif // WebKitWebViewBasePrivate_h
diff --git a/Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.cpp b/Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.cpp
new file mode 100644 (file)
index 0000000..e2e5774
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 "WebContextMenuProxyGtk.h"
+
+#include "IntPoint.h"
+#include "WebContextMenuItemData.h"
+#include "WebKitWebViewBasePrivate.h"
+#include "WebPageProxy.h"
+#include <WebCore/ContextMenu.h>
+#include <gtk/gtk.h>
+#include <wtf/text/CString.h>
+
+
+static const char* gContextMenuActionId = "webkit-context-menu-action";
+
+using namespace WebCore;
+
+namespace WebKit {
+
+static void contextMenuItemActivatedCallback(GtkAction* action, WebPageProxy* page)
+{
+    gboolean isToggle = GTK_IS_TOGGLE_ACTION(action);
+    WebKit::WebContextMenuItemData item(isToggle ? WebCore::CheckableActionType : WebCore::ActionType,
+                                        static_cast<WebCore::ContextMenuAction>(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(action), gContextMenuActionId))),
+                                        gtk_action_get_label(action), gtk_action_get_sensitive(action),
+                                        isToggle ? gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)) : false);
+    page->contextMenuItemSelected(item);
+}
+
+GtkMenu* WebContextMenuProxyGtk::createGtkMenu(const Vector<WebContextMenuItemData>& items)
+{
+    ContextMenu menu;
+    for (size_t i = 0; i < items.size(); i++) {
+        const WebContextMenuItemData& item = items.at(i);
+        ContextMenuItem menuItem(item.type(), item.action(), item.title(), item.enabled(), item.checked());
+        GtkAction* action = menuItem.gtkAction();
+
+        if (action) {
+            g_object_set_data(G_OBJECT(action), gContextMenuActionId, GINT_TO_POINTER(item.action()));
+            g_signal_connect(action, "activate", G_CALLBACK(contextMenuItemActivatedCallback), m_page);
+        }
+
+        if (item.type() == WebCore::SubmenuType) {
+            ContextMenu subMenu(createGtkMenu(item.submenu()));
+            menuItem.setSubMenu(&subMenu);
+        }
+        menu.appendItem(menuItem);
+    }
+    return menu.releasePlatformDescription();
+}
+
+void WebContextMenuProxyGtk::showContextMenu(const WebCore::IntPoint& position, const Vector<WebContextMenuItemData>& items)
+{
+    if (items.isEmpty())
+        return;
+
+    webkitWebViewBaseShowContextMenu(WEBKIT_WEB_VIEW_BASE(m_webView), createGtkMenu(items), position);
+}
+
+void WebContextMenuProxyGtk::hideContextMenu()
+{
+}
+
+WebContextMenuProxyGtk::WebContextMenuProxyGtk(GtkWidget* webView, WebPageProxy* page)
+    : m_webView(webView)
+    , m_page(page)
+{
+}
+
+WebContextMenuProxyGtk::~WebContextMenuProxyGtk()
+{
+}
+
+} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.h b/Source/WebKit2/UIProcess/gtk/WebContextMenuProxyGtk.h
new file mode 100644 (file)
index 0000000..63d0db0
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Igalia S.L.
+ *
+ * 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 WebContextMenuProxyGtk_h
+#define WebContextMenuProxyGtk_h
+
+#include "WebContextMenuProxy.h"
+
+namespace WebKit {
+
+class WebContextMenuItemData;
+class WebPageProxy;
+
+class WebContextMenuProxyGtk : public WebContextMenuProxy {
+public:
+    static PassRefPtr<WebContextMenuProxyGtk> create(GtkWidget* webView, WebPageProxy* page)
+    {
+        return adoptRef(new WebContextMenuProxyGtk(webView, page));
+    }
+    ~WebContextMenuProxyGtk();
+
+    virtual void showContextMenu(const WebCore::IntPoint&, const Vector<WebContextMenuItemData>&);
+    virtual void hideContextMenu();
+
+private:
+    WebContextMenuProxyGtk(GtkWidget*, WebPageProxy*);
+    GtkMenu* createGtkMenu(const Vector<WebContextMenuItemData>&);
+
+    GtkWidget* m_webView;
+    WebPageProxy* m_page;
+};
+
+
+} // namespace WebKit
+
+#endif // WebContextMenuProxyGtk_h