[GTK][WebKit2] Initial windowed plugins implementation
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Apr 2012 10:58:03 +0000 (10:58 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Apr 2012 10:58:03 +0000 (10:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=61065

Reviewed by Philippe Normand.

* PluginProcess/PluginControllerProxy.cpp:
(WebKit::PluginControllerProxy::createPluginContainer):
(WebKit::PluginControllerProxy::windowedPluginGeometryDidChange):
* PluginProcess/PluginControllerProxy.h:
* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseContainerAdd): Implement GtkContainer::add().
(webkitWebViewBaseContainerRemove): Implement GtkContainer::remove().
(webkitWebViewBaseContainerForall): Implement GtkContainer::forall().
(webkitWebViewBaseChildMoveResize): Set a new geometry for a child widget.
(webkitWebViewBaseChildAllocate): Allocate a child widget.
(resizeWebKitWebViewBaseFromAllocation): Allocate child widgets.
(webkit_web_view_base_class_init):
* UIProcess/API/gtk/WebKitWebViewBasePrivate.h: Add webkitWebViewBaseSizeAllocate().
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in: Add createPluginContainer
and windowedPluginGeometryDidChange messages.
* UIProcess/gtk/WebPageProxyGtk.cpp:
(WebKit::pluginWindowMap):
(WebKit::pluginContainerPlugRemoved): Remove the socket from the
hash map when its plug is removed.
(WebKit::WebPageProxy::createPluginContainer): Create a GtkSocket
as container widget for windowed plugins.
(WebKit::WebPageProxy::windowedPluginGeometryDidChange): Call
webkitWebViewBaseSizeAllocate() to update the plugin widget
geometry.
* UIProcess/qt/WebPageProxyQt.cpp:
(WebKit::WebPageProxy::createPluginContainer):
(WebKit::WebPageProxy::windowedPluginGeometryDidChange):
* WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
(WebKit::NetscapePlugin::NetscapePlugin):
* WebProcess/Plugins/Netscape/NetscapePlugin.h:
* WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp:
(WebKit::socketPlugRemovedCallback): Return TRUE to avoid the
socket to be destroyed, since we need to reuse it.
(WebKit::NetscapePlugin::platformPostInitializeWindowed): Ask the
ui process to create a plugin container.
(WebKit::NetscapePlugin::platformPostInitializeWindowless):
(WebKit::NetscapePlugin::platformPostInitialize):
(WebKit::NetscapePlugin::platformGeometryDidChange): For windowed
plugins notify the ui process that the plugin geometry has
changed.
(WebKit::NetscapePlugin::platformPaint): Do nothing for windowed
plugins, the caller already calls callSetWindow().
* WebProcess/Plugins/PluginController.h:
* WebProcess/Plugins/PluginProxy.cpp:
(WebKit::PluginProxy::createPluginContainer):
(WebKit::PluginProxy::windowedPluginGeometryDidChange):
* WebProcess/Plugins/PluginProxy.h:
* WebProcess/Plugins/PluginProxy.messages.in:
* WebProcess/Plugins/PluginView.cpp:
(WebKit::PluginView::createPluginContainer):
(WebKit::PluginView::windowedPluginGeometryDidChange):
* WebProcess/Plugins/PluginView.h:

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

18 files changed:
Source/WebKit2/ChangeLog
Source/WebKit2/PluginProcess/PluginControllerProxy.cpp
Source/WebKit2/PluginProcess/PluginControllerProxy.h
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBasePrivate.h
Source/WebKit2/UIProcess/WebPageProxy.h
Source/WebKit2/UIProcess/WebPageProxy.messages.in
Source/WebKit2/UIProcess/gtk/WebPageProxyGtk.cpp
Source/WebKit2/UIProcess/qt/WebPageProxyQt.cpp
Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.cpp
Source/WebKit2/WebProcess/Plugins/Netscape/NetscapePlugin.h
Source/WebKit2/WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp
Source/WebKit2/WebProcess/Plugins/PluginController.h
Source/WebKit2/WebProcess/Plugins/PluginProxy.cpp
Source/WebKit2/WebProcess/Plugins/PluginProxy.h
Source/WebKit2/WebProcess/Plugins/PluginProxy.messages.in
Source/WebKit2/WebProcess/Plugins/PluginView.cpp
Source/WebKit2/WebProcess/Plugins/PluginView.h

index 56716b4..a8359f2 100644 (file)
@@ -1,3 +1,64 @@
+2012-04-26  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK][WebKit2] Initial windowed plugins implementation
+        https://bugs.webkit.org/show_bug.cgi?id=61065
+
+        Reviewed by Philippe Normand.
+
+        * PluginProcess/PluginControllerProxy.cpp:
+        (WebKit::PluginControllerProxy::createPluginContainer):
+        (WebKit::PluginControllerProxy::windowedPluginGeometryDidChange):
+        * PluginProcess/PluginControllerProxy.h:
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (webkitWebViewBaseContainerAdd): Implement GtkContainer::add().
+        (webkitWebViewBaseContainerRemove): Implement GtkContainer::remove().
+        (webkitWebViewBaseContainerForall): Implement GtkContainer::forall().
+        (webkitWebViewBaseChildMoveResize): Set a new geometry for a child widget.
+        (webkitWebViewBaseChildAllocate): Allocate a child widget.
+        (resizeWebKitWebViewBaseFromAllocation): Allocate child widgets.
+        (webkit_web_view_base_class_init):
+        * UIProcess/API/gtk/WebKitWebViewBasePrivate.h: Add webkitWebViewBaseSizeAllocate().
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in: Add createPluginContainer
+        and windowedPluginGeometryDidChange messages.
+        * UIProcess/gtk/WebPageProxyGtk.cpp:
+        (WebKit::pluginWindowMap):
+        (WebKit::pluginContainerPlugRemoved): Remove the socket from the
+        hash map when its plug is removed.
+        (WebKit::WebPageProxy::createPluginContainer): Create a GtkSocket
+        as container widget for windowed plugins.
+        (WebKit::WebPageProxy::windowedPluginGeometryDidChange): Call
+        webkitWebViewBaseSizeAllocate() to update the plugin widget
+        geometry.
+        * UIProcess/qt/WebPageProxyQt.cpp:
+        (WebKit::WebPageProxy::createPluginContainer):
+        (WebKit::WebPageProxy::windowedPluginGeometryDidChange):
+        * WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
+        (WebKit::NetscapePlugin::NetscapePlugin):
+        * WebProcess/Plugins/Netscape/NetscapePlugin.h:
+        * WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp:
+        (WebKit::socketPlugRemovedCallback): Return TRUE to avoid the
+        socket to be destroyed, since we need to reuse it.
+        (WebKit::NetscapePlugin::platformPostInitializeWindowed): Ask the
+        ui process to create a plugin container.
+        (WebKit::NetscapePlugin::platformPostInitializeWindowless):
+        (WebKit::NetscapePlugin::platformPostInitialize):
+        (WebKit::NetscapePlugin::platformGeometryDidChange): For windowed
+        plugins notify the ui process that the plugin geometry has
+        changed.
+        (WebKit::NetscapePlugin::platformPaint): Do nothing for windowed
+        plugins, the caller already calls callSetWindow().
+        * WebProcess/Plugins/PluginController.h:
+        * WebProcess/Plugins/PluginProxy.cpp:
+        (WebKit::PluginProxy::createPluginContainer):
+        (WebKit::PluginProxy::windowedPluginGeometryDidChange):
+        * WebProcess/Plugins/PluginProxy.h:
+        * WebProcess/Plugins/PluginProxy.messages.in:
+        * WebProcess/Plugins/PluginView.cpp:
+        (WebKit::PluginView::createPluginContainer):
+        (WebKit::PluginView::windowedPluginGeometryDidChange):
+        * WebProcess/Plugins/PluginView.h:
+
 2012-04-26  Chris Fleizach2  <cfleizach@apple.com>
 
         CrashTracer: [USER] 157 crashes in WebProcess at com.apple.WebCore: WebCore::AccessibilityRenderObject::isAttachment const + 29
index 7e02533..81b290a 100644 (file)
@@ -540,6 +540,20 @@ void PluginControllerProxy::getFormValue(bool& returnValue, String& formValue)
     returnValue = m_plugin->getFormValue(formValue);
 }
 
+#if PLUGIN_ARCHITECTURE(X11)
+uint64_t PluginControllerProxy::createPluginContainer()
+{
+    uint64_t windowID = 0;
+    m_connection->connection()->sendSync(Messages::PluginProxy::CreatePluginContainer(), Messages::PluginProxy::CreatePluginContainer::Reply(windowID), m_pluginInstanceID);
+    return windowID;
+}
+
+void PluginControllerProxy::windowedPluginGeometryDidChange(const IntRect& frameRect, const IntRect& clipRect, uint64_t windowID)
+{
+    m_connection->connection()->send(Messages::PluginProxy::WindowedPluginGeometryDidChange(frameRect, clipRect, windowID), m_pluginInstanceID);
+}
+#endif
+
 } // namespace WebKit
 
 #endif // ENABLE(PLUGIN_PROCESS)
index 7877989..7022fd0 100644 (file)
@@ -103,6 +103,10 @@ private:
     virtual bool getAuthenticationInfo(const WebCore::ProtectionSpace&, String& username, String& password);
     virtual void protectPluginFromDestruction();
     virtual void unprotectPluginFromDestruction();
+#if PLUGIN_ARCHITECTURE(X11)
+    virtual uint64_t createPluginContainer();
+    virtual void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID);
+#endif
     
     // Message handlers.
     void frameDidFinishLoading(uint64_t requestID);
index 51f5c54..b2cdde5 100644 (file)
@@ -55,6 +55,7 @@
 #include <WebCore/Region.h>
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
+#include <wtf/HashMap.h>
 #include <wtf/gobject/GOwnPtr.h>
 #include <wtf/gobject/GRefPtr.h>
 #include <wtf/text/CString.h>
 using namespace WebKit;
 using namespace WebCore;
 
+typedef HashMap<GtkWidget*, IntRect> WebKitWebViewChildrenMap;
+
 struct _WebKitWebViewBasePrivate {
+    WebKitWebViewChildrenMap children;
     OwnPtr<PageClientImpl> pageClient;
     RefPtr<WebPageProxy> pageProxy;
     bool isPageActive;
@@ -163,9 +167,53 @@ static void webkitWebViewBaseRealize(GtkWidget* widget)
 
 static void webkitWebViewBaseContainerAdd(GtkContainer* container, GtkWidget* widget)
 {
+    WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
+    WebKitWebViewBasePrivate* priv = webView->priv;
+
+    GtkAllocation childAllocation;
+    gtk_widget_get_allocation(widget, &childAllocation);
+    priv->children.set(widget, childAllocation);
+
     gtk_widget_set_parent(widget, GTK_WIDGET(container));
 }
 
+static void webkitWebViewBaseContainerRemove(GtkContainer* container, GtkWidget* widget)
+{
+    WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
+    WebKitWebViewBasePrivate* priv = webView->priv;
+    GtkWidget* widgetContainer = GTK_WIDGET(container);
+
+    ASSERT(priv->children.contains(widget));
+    gboolean wasVisible = gtk_widget_get_visible(widget);
+    gtk_widget_unparent(widget);
+
+    priv->children.remove(widget);
+    if (wasVisible && gtk_widget_get_visible(widgetContainer))
+        gtk_widget_queue_resize(widgetContainer);
+}
+
+static void webkitWebViewBaseContainerForall(GtkContainer* container, gboolean includeInternals, GtkCallback callback, gpointer callbackData)
+{
+    WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(container);
+    WebKitWebViewBasePrivate* priv = webView->priv;
+
+    WebKitWebViewChildrenMap children = priv->children;
+    WebKitWebViewChildrenMap::const_iterator end = children.end();
+    for (WebKitWebViewChildrenMap::const_iterator current = children.begin(); current != end; ++current)
+        (*callback)(current->first, callbackData);
+}
+
+void webkitWebViewBaseChildMoveResize(WebKitWebViewBase* webView, GtkWidget* child, const IntRect& childRect)
+{
+    const IntRect& geometry = webView->priv->children.get(child);
+
+    if (geometry == childRect)
+        return;
+
+    webView->priv->children.set(child, childRect);
+    gtk_widget_queue_resize_no_redraw(GTK_WIDGET(webView));
+}
+
 static void webkitWebViewBaseFinalize(GObject* gobject)
 {
     WebKitWebViewBase* webkitWebViewBase = WEBKIT_WEB_VIEW_BASE(gobject);
@@ -214,10 +262,27 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
     return FALSE;
 }
 
-static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation)
+static void webkitWebViewBaseChildAllocate(GtkWidget* child, gpointer userData)
 {
+    if (!gtk_widget_get_visible(child))
+        return;
+
+    WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(userData);
     WebKitWebViewBasePrivate* priv = webViewBase->priv;
+    const IntRect& geometry = priv->children.get(child);
+    if (geometry.isEmpty())
+        return;
+
+    GtkAllocation childAllocation = geometry;
+    gtk_widget_size_allocate(child, &childAllocation);
+    priv->children.set(child, IntRect());
+}
+
+static void resizeWebKitWebViewBaseFromAllocation(WebKitWebViewBase* webViewBase, GtkAllocation* allocation)
+{
+    gtk_container_foreach(GTK_CONTAINER(webViewBase), webkitWebViewBaseChildAllocate, webViewBase);
 
+    WebKitWebViewBasePrivate* priv = webViewBase->priv;
     if (priv->pageProxy->drawingArea())
         priv->pageProxy->drawingArea()->setSize(IntSize(allocation->width, allocation->height), IntSize());
 
@@ -250,7 +315,6 @@ static void webkitWebViewBaseMap(GtkWidget* widget)
     gtk_widget_get_allocation(widget, &allocation);
     resizeWebKitWebViewBaseFromAllocation(webViewBase, &allocation);
     webViewBase->priv->needsResizeOnMap = false;
-
 }
 
 static gboolean webkitWebViewBaseFocusInEvent(GtkWidget* widget, GdkEventFocus* event)
@@ -527,6 +591,8 @@ static void webkit_web_view_base_class_init(WebKitWebViewBaseClass* webkitWebVie
 
     GtkContainerClass* containerClass = GTK_CONTAINER_CLASS(webkitWebViewBaseClass);
     containerClass->add = webkitWebViewBaseContainerAdd;
+    containerClass->remove = webkitWebViewBaseContainerRemove;
+    containerClass->forall = webkitWebViewBaseContainerForall;
 
     g_type_class_add_private(webkitWebViewBaseClass, sizeof(WebKitWebViewBasePrivate));
 }
index 27f5c1c..cd4c1a1 100644 (file)
@@ -41,6 +41,7 @@ void webkitWebViewBaseCreateWebPage(WebKitWebViewBase*, WKContextRef, WKPageGrou
 void webkitWebViewBaseSetTooltipText(WebKitWebViewBase*, const char*);
 void webkitWebViewBaseForwardNextKeyEvent(WebKitWebViewBase*);
 void webkitWebViewBaseStartDrag(WebKitWebViewBase*, const WebCore::DragData&, PassRefPtr<ShareableBitmap> dragImage);
+void webkitWebViewBaseChildMoveResize(WebKitWebViewBase*, GtkWidget*, const WebCore::IntRect&);
 void webkitWebViewBaseEnterFullScreen(WebKitWebViewBase*);
 void webkitWebViewBaseExitFullScreen(WebKitWebViewBase*);
 void webkitWebViewBaseInitializeFullScreenClient(WebKitWebViewBase*, const WKFullScreenClientGtk*);
index bab6676..eec44e5 100644 (file)
@@ -893,6 +893,11 @@ private:
 
     void setRenderTreeSize(uint64_t treeSize) { m_renderTreeSize = treeSize; }
 
+#if PLUGIN_ARCHITECTURE(X11)
+    void createPluginContainer(uint64_t& windowID);
+    void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID);
+#endif
+
     PageClient* m_pageClient;
     WebLoaderClient m_loaderClient;
     WebPolicyClient m_policyClient;
index d718115..400aced 100644 (file)
@@ -286,6 +286,12 @@ messages -> WebPageProxy {
     ScheduleChildWindowGeometryUpdate(WebKit::WindowGeometry geometry)
 #endif
 
+#if PLUGIN_ARCHITECTURE(X11)
+    # X11 windowed plugin messages
+    CreatePluginContainer() -> (uint64_t windowID)
+    WindowedPluginGeometryDidChange(WebCore::IntRect frameRect, WebCore::IntRect clipRect, uint64_t windowID)
+#endif
+
     # Search popup menus
     SaveRecentSearches(WTF::String name, Vector<String> searchItems)
     LoadRecentSearches(WTF::String name) -> (Vector<String> result)
index f6b300e..dc82352 100644 (file)
@@ -30,6 +30,8 @@
 #include "NativeWebKeyboardEvent.h"
 #include "NotImplemented.h"
 #include "PageClientImpl.h"
+#include "WebKitWebViewBasePrivate.h"
+#include <gtk/gtkx.h>
 
 namespace WebKit {
 
@@ -64,4 +66,45 @@ void WebPageProxy::loadRecentSearches(const String&, Vector<String>&)
     notImplemented();
 }
 
+typedef HashMap<uint64_t, GtkWidget* > PluginWindowMap;
+static PluginWindowMap& pluginWindowMap()
+{
+    DEFINE_STATIC_LOCAL(PluginWindowMap, map, ());
+    return map;
+}
+
+static gboolean pluginContainerPlugRemoved(GtkSocket* socket)
+{
+    uint64_t windowID = static_cast<uint64_t>(gtk_socket_get_id(socket));
+    pluginWindowMap().remove(windowID);
+    return FALSE;
+}
+
+void WebPageProxy::createPluginContainer(uint64_t& windowID)
+{
+    GtkWidget* socket = gtk_socket_new();
+    g_signal_connect(socket, "plug-removed", G_CALLBACK(pluginContainerPlugRemoved), 0);
+    gtk_container_add(GTK_CONTAINER(viewWidget()), socket);
+    gtk_widget_show(socket);
+
+    windowID = static_cast<uint64_t>(gtk_socket_get_id(GTK_SOCKET(socket)));
+    pluginWindowMap().set(windowID, socket);
+}
+
+void WebPageProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID)
+{
+    GtkWidget* plugin = pluginWindowMap().get(windowID);
+    if (!plugin)
+        return;
+
+    if (gtk_widget_get_realized(plugin)) {
+        GdkRectangle clip = clipRect;
+        cairo_region_t* clipRegion = cairo_region_create_rectangle(&clip);
+        gdk_window_shape_combine_region(gtk_widget_get_window(plugin), clipRegion, 0, 0);
+        cairo_region_destroy(clipRegion);
+    }
+
+    webkitWebViewBaseChildMoveResize(WEBKIT_WEB_VIEW_BASE(viewWidget()), plugin, frameRect);
+}
+
 } // namespace WebKit
index bf86edc..16bb69e 100644 (file)
@@ -102,4 +102,14 @@ void WebPageProxy::sendApplicationSchemeReply(const QQuickNetworkReply* reply)
     }
 }
 
+void WebPageProxy::createPluginContainer(uint64_t& windowID)
+{
+    notImplemented();
+}
+
+void WebPageProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID)
+{
+    notImplemented();
+}
+
 } // namespace WebKit
index db6d8d8..b63c73a 100644 (file)
@@ -89,6 +89,9 @@ NetscapePlugin::NetscapePlugin(PassRefPtr<NetscapePluginModule> pluginModule)
 #elif PLUGIN_ARCHITECTURE(X11)
     , m_drawable(0)
     , m_pluginDisplay(0)
+#if PLATFORM(GTK)
+    , m_platformPluginWidget(0)
+#endif
 #endif
 {
     m_npp.ndata = this;
index 569ffd7..660b685 100644 (file)
@@ -234,6 +234,11 @@ private:
     void scheduleWindowedGeometryUpdate();
 #endif
 
+#if PLUGIN_ARCHITECTURE(X11)
+    bool platformPostInitializeWindowed(bool needsXEmbed, uint64_t windowID);
+    bool platformPostInitializeWindowless();
+#endif
+
     uint64_t m_nextRequestID;
 
     typedef HashMap<uint64_t, std::pair<String, void*> > PendingURLNotifyMap;
@@ -343,6 +348,9 @@ private:
 #elif PLUGIN_ARCHITECTURE(X11)
     Pixmap m_drawable;
     Display* m_pluginDisplay;
+#if PLATFORM(GTK)
+    GtkWidget* m_platformPluginWidget;
+#endif
 
 public: // Need to call it in the NPN_GetValue browser callback.
     static Display* x11HostDisplay();
index a1c2a31..6564fd1 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "NetscapePlugin.h"
 
+#include "PluginController.h"
 #include "WebEvent.h"
 #include <WebCore/GraphicsContext.h>
 #include <WebCore/NotImplemented.h>
 #include "PlatformContextCairo.h"
 #include "RefPtrCairo.h"
 #include <cairo/cairo-xlib.h>
+#include <gtk/gtk.h>
+#ifndef GTK_API_VERSION_2
+#include <gtk/gtkx.h>
+#endif
 #include <gdk/gdkx.h>
 #include <WebCore/GtkVersioning.h>
 #endif
@@ -144,26 +149,65 @@ Display* NetscapePlugin::x11HostDisplay()
 #endif
 }
 
-bool NetscapePlugin::platformPostInitialize()
-{
 #if PLATFORM(GTK)
-    if (moduleMixesGtkSymbols(m_pluginModule->module()))
-        return false;
+static gboolean socketPlugRemovedCallback(GtkSocket*)
+{
+    // Default action is to destroy the GtkSocket, so we just return TRUE here
+    // to be able to reuse the socket. For some obscure reason, newer versions
+    // of flash plugin remove the plug from the socket, probably because the plug
+    // created by the plugin is re-parented.
+    return TRUE;
+}
 #endif
 
-    if (m_isWindowed)
+bool NetscapePlugin::platformPostInitializeWindowed(bool needsXEmbed, uint64_t windowID)
+{
+    m_npWindow.type = NPWindowTypeWindow;
+    if (!needsXEmbed) {
+        notImplemented();
         return false;
+    }
 
-    if (!(m_pluginDisplay = getPluginDisplay()))
-        return false;
+    Display* display = x11HostDisplay();
 
-    NPSetWindowCallbackStruct* callbackStruct = new NPSetWindowCallbackStruct;
-    callbackStruct->type = 0;
+#if PLATFORM(GTK)
+    // It seems flash needs the socket to be in the same process,
+    // I guess it uses gdk_window_lookup(), so we create a new socket here
+    // containing a plug with the UI process socket embedded.
+    m_platformPluginWidget = gtk_plug_new(static_cast<Window>(windowID));
+    GtkWidget* socket = gtk_socket_new();
+    g_signal_connect(socket, "plug-removed", G_CALLBACK(socketPlugRemovedCallback), 0);
+    gtk_container_add(GTK_CONTAINER(m_platformPluginWidget), socket);
+    gtk_widget_show(socket);
+    gtk_widget_show(m_platformPluginWidget);
+
+    m_npWindow.window = GINT_TO_POINTER(gtk_socket_get_id(GTK_SOCKET(socket)));
+    GdkWindow* window = gtk_widget_get_window(socket);
+    NPSetWindowCallbackStruct* callbackStruct = static_cast<NPSetWindowCallbackStruct*>(m_npWindow.ws_info);
+    callbackStruct->display = GDK_WINDOW_XDISPLAY(window);
+    callbackStruct->visual = GDK_VISUAL_XVISUAL(gdk_window_get_visual(window));
+    callbackStruct->depth = gdk_visual_get_depth(gdk_window_get_visual(window));
+    callbackStruct->colormap = XCreateColormap(display, GDK_ROOT_WINDOW(), callbackStruct->visual, AllocNone);
+#endif
+
+    XFlush(display);
+
+    callSetWindow();
+
+    return true;
+}
+
+bool NetscapePlugin::platformPostInitializeWindowless()
+{
     Display* display = x11HostDisplay();
+    m_npWindow.type = NPWindowTypeDrawable;
+    m_npWindow.window = 0;
+
     int depth = displayDepth();
 #if PLATFORM(QT)
     ASSERT(depth == 16 || depth == 24 || depth == 32);
 #endif
+    NPSetWindowCallbackStruct* callbackStruct = static_cast<NPSetWindowCallbackStruct*>(m_npWindow.ws_info);
     callbackStruct->display = display;
     callbackStruct->depth = depth;
 
@@ -182,15 +226,45 @@ bool NetscapePlugin::platformPostInitialize()
     callbackStruct->visual = visual;
     callbackStruct->colormap = XCreateColormap(display, rootWindowID(), visual, AllocNone);
 
-    m_npWindow.type = NPWindowTypeDrawable;
-    m_npWindow.window = 0;
-    m_npWindow.ws_info = callbackStruct;
-
     callSetWindow();
 
     return true;
 }
 
+bool NetscapePlugin::platformPostInitialize()
+{
+#if PLATFORM(GTK)
+    if (moduleMixesGtkSymbols(m_pluginModule->module()))
+        return false;
+#endif
+
+    uint64_t windowID = 0;
+    bool needsXEmbed = false;
+    if (m_isWindowed) {
+        NPP_GetValue(NPPVpluginNeedsXEmbed, &needsXEmbed);
+        if (needsXEmbed) {
+            windowID = controller()->createPluginContainer();
+            if (!windowID)
+                return false;
+        } else {
+            notImplemented();
+            return false;
+        }
+    }
+
+    if (!(m_pluginDisplay = getPluginDisplay()))
+        return false;
+
+    NPSetWindowCallbackStruct* callbackStruct = new NPSetWindowCallbackStruct;
+    callbackStruct->type = 0;
+    m_npWindow.ws_info = callbackStruct;
+
+    if (m_isWindowed)
+        return platformPostInitializeWindowed(needsXEmbed, windowID);
+
+    return platformPostInitializeWindowless();
+}
+
 void NetscapePlugin::platformDestroy()
 {
     NPSetWindowCallbackStruct* callbackStruct = static_cast<NPSetWindowCallbackStruct*>(m_npWindow.ws_info);
@@ -213,7 +287,13 @@ bool NetscapePlugin::platformInvalidate(const IntRect&)
 void NetscapePlugin::platformGeometryDidChange()
 {
     if (m_isWindowed) {
-        notImplemented();
+        uint64_t windowID = 0;
+#if PLATFORM(GTK)
+        windowID = static_cast<uint64_t>(GDK_WINDOW_XID(gtk_plug_get_socket_window(GTK_PLUG(m_platformPluginWidget))));
+#endif
+        IntRect clipRect(m_clipRect);
+        clipRect.move(-m_frameRectInWindowCoordinates.x(), -m_frameRectInWindowCoordinates.y());
+        controller()->windowedPluginGeometryDidChange(m_frameRectInWindowCoordinates, clipRect, windowID);
         return;
     }
 
@@ -238,10 +318,8 @@ void NetscapePlugin::platformVisibilityDidChange()
 
 void NetscapePlugin::platformPaint(GraphicsContext* context, const IntRect& dirtyRect, bool /*isSnapshot*/)
 {
-    if (m_isWindowed) {
-        notImplemented();
+    if (m_isWindowed)
         return;
-    }
 
     if (!m_isStarted) {
         // FIXME: we should paint a missing plugin icon.
index 6012ecc..25032cc 100644 (file)
@@ -143,6 +143,12 @@ public:
     // Decrements a counter that, when it reaches 0, stops preventing the plug-in from being destroyed.
     virtual void unprotectPluginFromDestruction() = 0;
 
+#if PLUGIN_ARCHITECTURE(X11)
+    // Create a plugin container for windowed plugins
+    virtual uint64_t createPluginContainer() = 0;
+    virtual void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID) = 0;
+#endif
+
     // Helper class for delaying destruction of a plug-in.
     class PluginDestructionProtector {
     public:
index 638250e..0771bc3 100644 (file)
@@ -523,6 +523,18 @@ void PluginProxy::setStatusbarText(const String& statusbarText)
     controller()->setStatusbarText(statusbarText);
 }
 
+#if PLUGIN_ARCHITECTURE(X11)
+void PluginProxy::createPluginContainer(uint64_t& windowID)
+{
+    windowID = controller()->createPluginContainer();
+}
+
+void PluginProxy::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID)
+{
+    controller()->windowedPluginGeometryDidChange(frameRect, clipRect, windowID);
+}
+#endif
+
 void PluginProxy::update(const IntRect& paintedRect)
 {
     if (paintedRect == pluginBounds())
index 10819d0..e4b4286 100644 (file)
@@ -135,6 +135,10 @@ private:
     void setComplexTextInputState(uint64_t);
     void setLayerHostingContextID(uint32_t);
 #endif
+#if PLUGIN_ARCHITECTURE(X11)
+    void createPluginContainer(uint64_t& windowID);
+    void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID);
+#endif
 
     String m_pluginPath;
 
index 80b3b06..a2ef319 100644 (file)
@@ -66,6 +66,14 @@ messages -> PluginProxy {
     # Update the layer hosting context ID. Called whenever the layer hosting state changes.
     SetLayerHostingContextID(uint32_t layerHostingContextID)
 #endif
+
+#if PLUGIN_ARCHITECTURE(X11)
+    # Create the plugin container for windowed plugins
+    CreatePluginContainer() -> (uint64_t windowID)
+
+    # Update geometry of windowed plugin widget
+    WindowedPluginGeometryDidChange(WebCore::IntRect frameRect, WebCore::IntRect clipRect, uint64_t windowID)
+#endif
 }
 
 #endif
index 53fce84..6799f11 100644 (file)
@@ -29,6 +29,7 @@
 #include "NPRuntimeUtilities.h"
 #include "Plugin.h"
 #include "ShareableBitmap.h"
+#include "WebCoreArgumentCoders.h"
 #include "WebEvent.h"
 #include "WebPage.h"
 #include "WebPageProxyMessages.h"
@@ -1251,4 +1252,18 @@ void PluginView::didFailLoad(WebFrame* webFrame, bool wasCancelled)
     m_plugin->frameDidFail(request->requestID(), wasCancelled);
 }
 
+#if PLUGIN_ARCHITECTURE(X11)
+uint64_t PluginView::createPluginContainer()
+{
+    uint64_t windowID = 0;
+    m_webPage->sendSync(Messages::WebPageProxy::CreatePluginContainer(), Messages::WebPageProxy::CreatePluginContainer::Reply(windowID));
+    return windowID;
+}
+
+void PluginView::windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID)
+{
+    m_webPage->send(Messages::WebPageProxy::WindowedPluginGeometryDidChange(frameRect, clipRect, windowID));
+}
+#endif
+
 } // namespace WebKit
index 27077b4..1bf76ae 100644 (file)
@@ -160,6 +160,10 @@ private:
     virtual bool isPrivateBrowsingEnabled();
     virtual void protectPluginFromDestruction();
     virtual void unprotectPluginFromDestruction();
+#if PLUGIN_ARCHITECTURE(X11)
+    virtual uint64_t createPluginContainer();
+    virtual void windowedPluginGeometryDidChange(const WebCore::IntRect& frameRect, const WebCore::IntRect& clipRect, uint64_t windowID);
+#endif
 
     // WebFrame::LoadListener
     virtual void didFinishLoad(WebFrame*);