diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-26 18:22:54 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-26 18:22:54 +0000 |
commit | 140c303f6227f870bb269bd6810c907c99004b55 (patch) | |
tree | ec3522f3193bc2688d7777fcd022e808a530dc49 | |
parent | 487c2873c78595f5ec78629a5ca92304b34ce317 (diff) | |
download | chromium_src-140c303f6227f870bb269bd6810c907c99004b55.zip chromium_src-140c303f6227f870bb269bd6810c907c99004b55.tar.gz chromium_src-140c303f6227f870bb269bd6810c907c99004b55.tar.bz2 |
linux plugins: eliminate GtkWidget* from plugin process
[retry with mac hopefully fixed this time]
GtkWidget* (and its wrapper, gfx::NativeView) only work within a
single process. Plugins already work with a lower-level type that
works across processes -- an X Window id. The parent of a plugin
is an HWND on windows, but it's an X Window id on X. So we
introduce a new typedef wrapping that and push it through all the
places in the code that needs it.
Since we no longer have a GtkSocket in the WebPluginDelegateImpl,
we need to do a bit more work in the WebViewDelegate (aka the
browser process in the multiproc world).
We also need the plugin host (the browser) to track the
GtkSockets that are hosting the plugin, as well as destroy them
when necessary. To do this we require the plugin owner to
grab the plug-removed signal rather than putting its handler in
GtkPluginContainer; this is the way it worked before I'd refactored
into GtkPluginContainer so it shouldn't be so bad.
This change still only works in test_shell, but the refactoring
should translate to the multiprocess case pretty easily.
Review URL: http://codereview.chromium.org/146009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19387 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/gfx/native_widget_types.h | 15 | ||||
-rw-r--r-- | chrome/common/ipc_message_utils.h | 21 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.cc | 10 | ||||
-rw-r--r-- | chrome/plugin/webplugin_proxy.h | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/gtk_plugin_container.cc | 16 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_host.cc | 2 | ||||
-rw-r--r-- | webkit/glue/plugins/plugin_instance.h | 8 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.cc | 4 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 6 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 55 | ||||
-rw-r--r-- | webkit/glue/webplugin.h | 8 | ||||
-rw-r--r-- | webkit/glue/webplugin_delegate.h | 5 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.cc | 2 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.h | 6 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_webview_delegate_gtk.cc | 39 | ||||
-rw-r--r-- | webkit/tools/test_shell/webview_host.h | 30 | ||||
-rw-r--r-- | webkit/tools/test_shell/webview_host_gtk.cc | 37 |
17 files changed, 181 insertions, 87 deletions
diff --git a/base/gfx/native_widget_types.h b/base/gfx/native_widget_types.h index 9444a61..e9a9230 100644 --- a/base/gfx/native_widget_types.h +++ b/base/gfx/native_widget_types.h @@ -114,6 +114,21 @@ static inline NativeViewId IdFromNativeView(NativeView view) { NativeViewId IdFromNativeView(NativeView view); #endif // defined(OS_LINUX) + +// PluginWindowHandle is an abstraction wrapping "the types of windows +// used by NPAPI plugins". On Windows it's an HWND, on X it's an X +// window id. +#if defined(OS_WIN) + typedef HWND PluginWindowHandle; +#elif defined(OS_LINUX) + typedef unsigned long PluginWindowHandle; +#else + // On OS X we don't have windowed plugins. + // Use a gfx::NativeView so the previously-compiling code still works. + // TODO(evanm): remove this and use void* instead. + typedef gfx::NativeView PluginWindowHandle; +#endif + } // namespace gfx #endif // BASE_GFX_NATIVE_WIDGET_TYPES_H_ diff --git a/chrome/common/ipc_message_utils.h b/chrome/common/ipc_message_utils.h index 2ae2ab5..f777d06 100644 --- a/chrome/common/ipc_message_utils.h +++ b/chrome/common/ipc_message_utils.h @@ -176,6 +176,27 @@ struct ParamTraits<long> { } }; +#if defined(OS_LINUX) +// unsigned long is used for serializing X window ids. +template <> +struct ParamTraits<unsigned long> { + typedef unsigned long param_type; + static void Write(Message* m, const param_type& p) { + m->WriteLong(p); + } + static bool Read(const Message* m, void** iter, param_type* r) { + long read_output; + if (!m->ReadLong(iter, &read_output)) + return false; + *r = static_cast<unsigned long>(read_output); + return true; + } + static void Log(const param_type& p, std::wstring* l) { + l->append(StringPrintf(L"%ul", p)); + } +}; +#endif + template <> struct ParamTraits<size_t> { typedef size_t param_type; diff --git a/chrome/plugin/webplugin_proxy.cc b/chrome/plugin/webplugin_proxy.cc index 286659b..57c07fc 100644 --- a/chrome/plugin/webplugin_proxy.cc +++ b/chrome/plugin/webplugin_proxy.cc @@ -56,15 +56,21 @@ bool WebPluginProxy::Send(IPC::Message* msg) { return channel_->Send(msg); } -void WebPluginProxy::SetWindow(gfx::NativeView window) { +void WebPluginProxy::SetWindow(gfx::PluginWindowHandle window) { +#if defined(OS_WIN) Send(new PluginHostMsg_SetWindow(route_id_, gfx::IdFromNativeView(window))); +#else + NOTIMPLEMENTED(); +#endif } -void WebPluginProxy::WillDestroyWindow(gfx::NativeView window) { +void WebPluginProxy::WillDestroyWindow(gfx::PluginWindowHandle window) { #if defined(OS_WIN) PluginThread::current()->Send( new PluginProcessHostMsg_PluginWindowDestroyed( window, ::GetParent(window))); +#else + NOTIMPLEMENTED(); #endif } diff --git a/chrome/plugin/webplugin_proxy.h b/chrome/plugin/webplugin_proxy.h index 46c16d1..e143297 100644 --- a/chrome/plugin/webplugin_proxy.h +++ b/chrome/plugin/webplugin_proxy.h @@ -37,8 +37,8 @@ class WebPluginProxy : public WebPlugin { ~WebPluginProxy(); // WebPlugin overrides - void SetWindow(gfx::NativeView window); - void WillDestroyWindow(gfx::NativeView window); + void SetWindow(gfx::PluginWindowHandle window); + void WillDestroyWindow(gfx::PluginWindowHandle window); #if defined(OS_WIN) void SetWindowlessPumpEvent(HANDLE pump_messages_event); // Returns true on success. diff --git a/webkit/glue/plugins/gtk_plugin_container.cc b/webkit/glue/plugins/gtk_plugin_container.cc index 18bdb30..c487fa0 100644 --- a/webkit/glue/plugins/gtk_plugin_container.cc +++ b/webkit/glue/plugins/gtk_plugin_container.cc @@ -14,13 +14,6 @@ namespace { // through GLib's object management. class GtkPluginContainer : public GtkSocket { public: - static GtkWidget* CreateNewWidget() { - GtkWidget* container = GTK_WIDGET(g_object_new(GetType(), NULL)); - g_signal_connect(GTK_SOCKET(container), "plug-removed", - G_CALLBACK(OnPlugRemoved), NULL); - return container; - } - // Sets the requested size of the widget. void set_size(int width, int height) { width_ = width; @@ -33,7 +26,6 @@ class GtkPluginContainer : public GtkSocket { return G_TYPE_CHECK_INSTANCE_CAST(instance, GetType(), GtkPluginContainer); } - private: // Create and register our custom container type with GTK. static GType GetType() { static GType type = 0; // We only want to register our type once. @@ -74,12 +66,6 @@ class GtkPluginContainer : public GtkSocket { requisition->height = container->height_; } - static gboolean OnPlugRemoved(GtkSocket* socket) { - // This is called when the other side of the socket goes away. - // We return TRUE to indicate that we don't want to destroy our side. - return TRUE; - } - int width_; int height_; DISALLOW_IMPLICIT_CONSTRUCTORS(GtkPluginContainer); @@ -89,7 +75,7 @@ class GtkPluginContainer : public GtkSocket { // Create a new instance of our GTK widget object. GtkWidget* gtk_plugin_container_new() { - return GtkPluginContainer::CreateNewWidget(); + return GTK_WIDGET(g_object_new(GtkPluginContainer::GetType(), NULL)); } void gtk_plugin_container_set_size(GtkWidget *widget, int width, int height) { diff --git a/webkit/glue/plugins/plugin_host.cc b/webkit/glue/plugins/plugin_host.cc index 815b415..2e1c233 100644 --- a/webkit/glue/plugins/plugin_host.cc +++ b/webkit/glue/plugins/plugin_host.cc @@ -711,7 +711,7 @@ NPError NPN_GetValue(NPP id, NPNVariable variable, void *value) { { #if defined(OS_WIN) || defined(OS_LINUX) scoped_refptr<NPAPI::PluginInstance> plugin = FindInstance(id); - gfx::NativeView handle = plugin->window_handle(); + gfx::PluginWindowHandle handle = plugin->window_handle(); *((void**)value) = (void*)handle; rv = NPERR_NO_ERROR; #else diff --git a/webkit/glue/plugins/plugin_instance.h b/webkit/glue/plugins/plugin_instance.h index e73d49f..ba8824f8 100644 --- a/webkit/glue/plugins/plugin_instance.h +++ b/webkit/glue/plugins/plugin_instance.h @@ -70,8 +70,10 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { NPP npp() { return npp_; } // Get/Set for the instance's window handle. - gfx::NativeView window_handle() { return window_handle_; } - void set_window_handle(gfx::NativeView value) { window_handle_ = value; } + gfx::PluginWindowHandle window_handle() const { return window_handle_; } + void set_window_handle(gfx::PluginWindowHandle value) { + window_handle_ = value; + } // Get/Set whether this instance is in Windowless mode. // Default is false. @@ -223,7 +225,7 @@ class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> { scoped_refptr<PluginHost> host_; NPPluginFuncs* npp_functions_; std::vector<scoped_refptr<PluginStream> > open_streams_; - gfx::NativeView window_handle_; + gfx::PluginWindowHandle window_handle_; bool windowless_; bool transparent_; WebPlugin* webplugin_; diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc index 5cf00a5..d197fb11 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl.cc @@ -71,7 +71,7 @@ base::LazyInstance<iat_patch::IATPatchFunction> g_iat_patch_set_cursor( WebPluginDelegate* WebPluginDelegate::Create( const FilePath& filename, const std::string& mime_type, - gfx::NativeView containing_view) { + gfx::PluginWindowHandle containing_view) { scoped_refptr<NPAPI::PluginLib> plugin = NPAPI::PluginLib::CreatePluginLib(filename); if (plugin.get() == NULL) @@ -140,7 +140,7 @@ LRESULT CALLBACK WebPluginDelegateImpl::HandleEventMessageFilterHook( } WebPluginDelegateImpl::WebPluginDelegateImpl( - gfx::NativeView containing_view, + gfx::PluginWindowHandle containing_view, NPAPI::PluginInstance *instance) : parent_(containing_view), instance_(instance), diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index 61a41cd..d3cbdbf 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -91,7 +91,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { private: friend class DeleteTask<WebPluginDelegateImpl>; - WebPluginDelegateImpl(gfx::NativeView containing_view, + WebPluginDelegateImpl(gfx::PluginWindowHandle containing_view, NPAPI::PluginInstance *instance); ~WebPluginDelegateImpl(); @@ -154,7 +154,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { void DestroyInstance(); // used for windowed plugins - gfx::NativeView windowed_handle_; + gfx::PluginWindowHandle windowed_handle_; bool windowed_did_set_window_; #if defined(OS_WIN) gfx::Rect windowed_last_pos_; @@ -190,7 +190,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { void EnsurePixmapAtLeastSize(int width, int height); #endif - gfx::NativeView parent_; + gfx::PluginWindowHandle parent_; NPWindow window_; #if defined(OS_MACOSX) NP_CGContext cg_context_; diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index f583876..49670fc 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -38,7 +38,7 @@ using WebKit::WebMouseEvent; WebPluginDelegate* WebPluginDelegate::Create( const FilePath& filename, const std::string& mime_type, - gfx::NativeView containing_view) { + gfx::PluginWindowHandle containing_view) { scoped_refptr<NPAPI::PluginLib> plugin = NPAPI::PluginLib::CreatePluginLib(filename); if (plugin.get() == NULL) @@ -54,7 +54,7 @@ WebPluginDelegate* WebPluginDelegate::Create( } WebPluginDelegateImpl::WebPluginDelegateImpl( - gfx::NativeView containing_view, + gfx::PluginWindowHandle containing_view, NPAPI::PluginInstance *instance) : windowed_handle_(0), @@ -263,63 +263,40 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() { return false; } - windowed_handle_ = gtk_plugin_container_new(); - gtk_container_add(GTK_CONTAINER(parent_), windowed_handle_); - gtk_widget_show(windowed_handle_); - gtk_widget_realize(windowed_handle_); - - window_.window = GINT_TO_POINTER( - gtk_socket_get_id(GTK_SOCKET(windowed_handle_))); + window_.window = reinterpret_cast<void*>(parent_); + // The remainder of the code expects windowed_handle_ to exist for + // windowed mode, despite not actually ever reaching through + // windowed_handle_. So let's set it to the one window handle we + // actually have available. + windowed_handle_ = parent_; if (!window_.ws_info) window_.ws_info = new NPSetWindowCallbackStruct; NPSetWindowCallbackStruct* extra = static_cast<NPSetWindowCallbackStruct*>(window_.ws_info); - extra->display = GDK_WINDOW_XDISPLAY(windowed_handle_->window); - GdkVisual* visual = gdk_drawable_get_visual(windowed_handle_->window); - extra->visual = GDK_VISUAL_XVISUAL(visual); - extra->depth = visual->depth; - extra->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(windowed_handle_->window)); + extra->display = GDK_DISPLAY(); + extra->visual = DefaultVisual(GDK_DISPLAY(), 0); + extra->depth = DefaultDepth(GDK_DISPLAY(), 0); + extra->colormap = DefaultColormap(GDK_DISPLAY(), 0); return true; } void WebPluginDelegateImpl::WindowedDestroyWindow() { - if (windowed_handle_ != NULL) { - gtk_widget_destroy(windowed_handle_); - windowed_handle_ = NULL; - } + // We have no window to destroy; see comment in WindowedCreatePlugin + // where windowed_handle_ is set. + windowed_handle_ = 0; } bool WebPluginDelegateImpl::WindowedReposition( const gfx::Rect& window_rect, const gfx::Rect& clip_rect) { - if (!windowed_handle_) { - NOTREACHED(); - return false; - } - - if (window_rect_ == window_rect && clip_rect_ == clip_rect) + if (window_rect == window_rect_ && clip_rect == clip_rect_) return false; - // We only set the plugin's size here. Its position is moved elsewhere, which - // allows the window moves/scrolling/clipping to be synchronized with the page - // and other windows. - if (window_rect.size() != window_rect_.size()) { - gtk_plugin_container_set_size(windowed_handle_, window_rect.width(), - window_rect.height()); - GtkAllocation allocation = { 0, 0, - window_rect.width(), window_rect.height() }; - gtk_widget_size_allocate(windowed_handle_, &allocation); - } - window_rect_ = window_rect; clip_rect_ = clip_rect; - // TODO(deanm): Is this really needed? - // Ensure that the entire window gets repainted. - gtk_widget_queue_draw(windowed_handle_); - return true; } diff --git a/webkit/glue/webplugin.h b/webkit/glue/webplugin.h index d6a5b75..2debf9a 100644 --- a/webkit/glue/webplugin.h +++ b/webkit/glue/webplugin.h @@ -25,7 +25,9 @@ struct NPObject; // Describes the new location for a plugin window. struct WebPluginGeometry { - gfx::NativeView window; + // On Windows, this is the plugin window in the plugin process. + // On X11, this is the browser process's hosting window (the GtkSocket). + gfx::PluginWindowHandle window; gfx::Rect window_rect; // Clip rect (include) and cutouts (excludes), relative to // window_rect origin. @@ -54,11 +56,11 @@ class WebPlugin { // windowed (i.e. handle is not NULL) or windowless (handle is NULL). This // tells the WebPlugin to send mouse/keyboard events to the plugin delegate, // as well as the information about the HDC for paint operations. - virtual void SetWindow(gfx::NativeView window) = 0; + virtual void SetWindow(gfx::PluginWindowHandle window) = 0; // Called by the plugin delegate to let it know that the window is being // destroyed. - virtual void WillDestroyWindow(gfx::NativeView window) = 0; + virtual void WillDestroyWindow(gfx::PluginWindowHandle window) = 0; #if defined(OS_WIN) // The pump_messages_event is a event handle which is valid only for // windowless plugins and is used in NPP_HandleEvent calls to pump messages diff --git a/webkit/glue/webplugin_delegate.h b/webkit/glue/webplugin_delegate.h index 385044d..7d0fa88 100644 --- a/webkit/glue/webplugin_delegate.h +++ b/webkit/glue/webplugin_delegate.h @@ -8,10 +8,9 @@ #include <string> #include "base/gfx/native_widget_types.h" +#include "build/build_config.h" #include "third_party/npapi/bindings/npapi.h" -// TODO(port): put in OS_WIN check. -typedef struct HDC__* HDC; struct NPObject; class FilePath; @@ -48,7 +47,7 @@ class WebPluginDelegate { static WebPluginDelegate* Create(const FilePath& filename, const std::string& mime_type, - gfx::NativeView containing_view); + gfx::PluginWindowHandle containing_view); // Initializes the plugin implementation with the given (UTF8) arguments. // Note that the lifetime of WebPlugin must be longer than this delegate. diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc index d3c8d6a..69f6259 100644 --- a/webkit/glue/webplugin_impl.cc +++ b/webkit/glue/webplugin_impl.cc @@ -388,7 +388,7 @@ WebPluginImpl::WebPluginImpl(WebCore::HTMLPlugInElement* element, WebPluginImpl::~WebPluginImpl() { } -void WebPluginImpl::SetWindow(gfx::NativeView window) { +void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) { if (window) { DCHECK(!windowless_); // Make sure not called twice. window_ = window; diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h index ab7ea8f..9082820 100644 --- a/webkit/glue/webplugin_impl.h +++ b/webkit/glue/webplugin_impl.h @@ -148,8 +148,8 @@ class WebPluginImpl : public WebPlugin, int arg_count, char** arg_names, char** arg_values); // WebPlugin implementation: - void SetWindow(gfx::NativeView window); - void WillDestroyWindow(gfx::NativeView window) { } + void SetWindow(gfx::PluginWindowHandle window); + void WillDestroyWindow(gfx::PluginWindowHandle window) { } #if defined(OS_WIN) void SetWindowlessPumpEvent(HANDLE pump_messages_event) { } #endif @@ -333,7 +333,7 @@ class WebPluginImpl : public WebPlugin, std::vector<ClientInfo> clients_; bool windowless_; - gfx::NativeView window_; + gfx::PluginWindowHandle window_; WebCore::HTMLPlugInElement* element_; WebFrameImpl* webframe_; diff --git a/webkit/tools/test_shell/test_webview_delegate_gtk.cc b/webkit/tools/test_shell/test_webview_delegate_gtk.cc index d4a0574..74586e5 100644 --- a/webkit/tools/test_shell/test_webview_delegate_gtk.cc +++ b/webkit/tools/test_shell/test_webview_delegate_gtk.cc @@ -22,6 +22,7 @@ #include "webkit/glue/webplugin.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/webview.h" +#include "webkit/glue/plugins/gtk_plugin_container.h" #include "webkit/glue/plugins/plugin_list.h" #include "webkit/glue/window_open_disposition.h" #include "webkit/glue/plugins/webplugin_delegate_impl.h" @@ -87,12 +88,14 @@ WebPluginDelegate* TestWebViewDelegate::CreatePluginDelegate( actual_mime_type)) return NULL; - if (actual_mime_type && !actual_mime_type->empty()) - return WebPluginDelegateImpl::Create(info.path, *actual_mime_type, - shell_->webViewHost()->view_handle()); - else - return WebPluginDelegateImpl::Create(info.path, mime_type, - shell_->webViewHost()->view_handle()); + const std::string& mtype = + (actual_mime_type && !actual_mime_type->empty()) ? *actual_mime_type + : mime_type; + + GdkNativeWindow plugin_parent = + shell_->webViewHost()->CreatePluginContainer(); + + return WebPluginDelegateImpl::Create(info.path, mtype, plugin_parent); } void TestWebViewDelegate::ShowJavaScriptAlert(const std::wstring& message) { @@ -216,11 +219,24 @@ void TestWebViewDelegate::GetRootWindowResizerRect(WebWidget* webwidget, void TestWebViewDelegate::DidMove(WebWidget* webwidget, const WebPluginGeometry& move) { - // The window on WebPluginGeometry is misnamed, as it's a view. In our case - // it should be the GtkSocket of the plugin window. - GtkWidget* widget = move.window; + WebWidgetHost* host = GetHostForWidget(webwidget); + + // The "window" on WebPluginGeometry is actually the XEmbed parent + // X window id. + GtkWidget* widget = ((WebViewHost*)host)->MapIDToWidget(move.window); + // If we don't know about this plugin (maybe we're shutting down the + // window?), ignore the message. + if (!widget) + return; DCHECK(!GTK_WIDGET_NO_WINDOW(widget) && GTK_WIDGET_REALIZED(widget)); + if (!move.visible) { + gtk_widget_hide(widget); + return; + } else { + gtk_widget_show(widget); + } + // Update the clipping region on the GdkWindow. GdkRectangle clip_rect = move.clip_rect.ToGdkRectangle(); GdkRegion* clip_region = gdk_region_rectangle(&clip_rect); @@ -232,7 +248,6 @@ void TestWebViewDelegate::DidMove(WebWidget* webwidget, // TODO(deanm): Verify that we only need to move and not resize. // TODO(evanm): we should cache the last shape and position and skip all // of this business in the common case where nothing has changed. - WebWidgetHost* host = GetHostForWidget(webwidget); int current_x, current_y; // Until the above TODO is resolved, we can grab the last position @@ -255,6 +270,10 @@ void TestWebViewDelegate::DidMove(WebWidget* webwidget, move.window_rect.x(), move.window_rect.y()); } + + gtk_plugin_container_set_size(widget, + move.window_rect.width(), + move.window_rect.height()); } void TestWebViewDelegate::RunModal(WebWidget* webwidget) { diff --git a/webkit/tools/test_shell/webview_host.h b/webkit/tools/test_shell/webview_host.h index 337a355..0cd62ee 100644 --- a/webkit/tools/test_shell/webview_host.h +++ b/webkit/tools/test_shell/webview_host.h @@ -5,6 +5,8 @@ #ifndef WEBKIT_TOOLS_TEST_SHELL_WEBVIEW_HOST_H_ #define WEBKIT_TOOLS_TEST_SHELL_WEBVIEW_HOST_H_ +#include <map> + #include "base/basictypes.h" #include "base/gfx/native_widget_types.h" #include "base/gfx/rect.h" @@ -14,6 +16,10 @@ struct WebPreferences; class WebView; class WebViewDelegate; +#if defined(OS_LINUX) +typedef struct _GtkSocket GtkSocket; +#endif + // This class is a simple NativeView-based host for a WebView class WebViewHost : public WebWidgetHost { public: @@ -26,12 +32,36 @@ class WebViewHost : public WebWidgetHost { WebView* webview() const; +#if defined(OS_LINUX) + // Create a new plugin parent container, returning its X window id for + // embedders to use. + GdkNativeWindow CreatePluginContainer(); + + // Map a GdkNativeWindow returned by CreatePluginContainer() back to + // the GtkWidget hosting it. Used when we get a message back from the + // renderer indicating a plugin needs to move. + GtkWidget* MapIDToWidget(GdkNativeWindow id); +#endif + protected: #if defined(OS_WIN) virtual bool WndProc(UINT message, WPARAM wparam, LPARAM lparam) { return false; } #endif + +#if defined(OS_LINUX) + // A map used for MapIDToWidget() above. + typedef std::map<GdkNativeWindow, GtkWidget*> NativeWindowToWidgetMap; + NativeWindowToWidgetMap native_window_to_widget_map_; + + // Callback for when one of our plugins goes away. + static gboolean OnPlugRemovedThunk(GtkSocket* socket, + WebViewHost* web_view_host) { + return web_view_host->OnPlugRemoved(socket); + } + gboolean OnPlugRemoved(GtkSocket* socket); +#endif }; #endif // WEBKIT_TOOLS_TEST_SHELL_WEBVIEW_HOST_H_ diff --git a/webkit/tools/test_shell/webview_host_gtk.cc b/webkit/tools/test_shell/webview_host_gtk.cc index 54e3ec8..cd491af 100644 --- a/webkit/tools/test_shell/webview_host_gtk.cc +++ b/webkit/tools/test_shell/webview_host_gtk.cc @@ -6,9 +6,11 @@ #include "webkit/tools/test_shell/webview_host.h" +#include "base/logging.h" #include "base/gfx/rect.h" #include "base/gfx/size.h" #include "skia/ext/platform_canvas.h" +#include "webkit/glue/plugins/gtk_plugin_container.h" #include "webkit/glue/webview.h" // static @@ -29,3 +31,38 @@ WebViewHost* WebViewHost::Create(GtkWidget* parent_view, WebView* WebViewHost::webview() const { return static_cast<WebView*>(webwidget_); } + +GdkNativeWindow WebViewHost::CreatePluginContainer() { + GtkWidget* plugin_container = gtk_plugin_container_new(); + g_signal_connect(G_OBJECT(plugin_container), "plug-removed", + G_CALLBACK(OnPlugRemovedThunk), this); + gtk_container_add(GTK_CONTAINER(view_handle()), plugin_container); + gtk_widget_show(plugin_container); + gtk_widget_realize(plugin_container); + + GdkNativeWindow id = gtk_socket_get_id(GTK_SOCKET(plugin_container)); + + native_window_to_widget_map_.insert(std::make_pair(id, plugin_container)); + + return id; +} + +GtkWidget* WebViewHost::MapIDToWidget(GdkNativeWindow id) { + NativeWindowToWidgetMap::const_iterator i = + native_window_to_widget_map_.find(id); + if (i != native_window_to_widget_map_.end()) + return i->second; + + LOG(ERROR) << "Request for widget host for unknown window id " << id; + + return NULL; +} + +gboolean WebViewHost::OnPlugRemoved(GtkSocket* socket) { + // Remove the socket's id from our list of widgets. + GdkNativeWindow id = gtk_socket_get_id(socket); + native_window_to_widget_map_.erase(id); + + return FALSE; // Destroy our widget. +} + |