From b595ba77947ee0881ae8ce16ee92b47d1c48f10a Mon Sep 17 00:00:00 2001 From: "deanm@chromium.org" Date: Mon, 9 Feb 2009 20:05:26 +0000 Subject: This changes the approach for our webkit widget area, from using a custom GtkContainer to a GtkFixed container. Our previous custom container did not track its children, which meant it couldn't propagate size-request and size-allocate. In some ways this is what we wanted, however it prevented GtkSocket from running some important code. Specifically an expose event wouldn't trigger initially on the GtkSocket, leaving the widget window unpainted. Instead of writing / copying container code to manage children, it is much easier if we can reuse an existing container. This changes makes the drawing area a GtkFixed backed by a GdkWindow, and we paint into its window. We implement a small custom widget around GtkSocket, which allows us to control the size requisition phase. This solves the problem of controlling the GtkSocket layout within the container. Plugins are now painted correctly, without having to jiggle the scrollbar. This change additionally groups all of the widget code in a class of statics. GtkFixedSocket implements the GtkSocket with custom size requisition. WebWidgetHostGtkWidget is just a GtkFixed with a window, along with the signal connection handlers. This also means we'll have no custom container implementation to share across test_shell and the browser. It seems we still don't handle keyboard focus exactly right, and youtube videos still need mouse events to repaint. I believe these are subtle issues, and can be solved while keeping the GtkFixed container approach. Review URL: http://codereview.chromium.org/20128 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9407 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 61 ++++++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) (limited to 'webkit/glue/plugins') diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index 741ba99..58207c6 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc @@ -21,6 +21,7 @@ #include #include +#include "base/basictypes.h" #include "base/file_util.h" #include "base/message_loop.h" #include "base/process_util.h" @@ -241,13 +242,60 @@ void WebPluginDelegateImpl::WindowedUpdateGeometry( namespace { +// This is just a GtkSocket, with size_request overridden, so that we always +// control the size of the widget. +class GtkFixedSocket { + public: + // Create a new instance of our GTK widget object. + static GtkWidget* CreateNewWidget() { + return GTK_WIDGET(g_object_new(GetType(), NULL)); + } + + 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. + if (!type) { + static const GTypeInfo info = { + sizeof(GtkSocketClass), + NULL, NULL, + static_cast(&ClassInit), + NULL, NULL, + sizeof(GtkSocket), // We are identical to a GtkSocket. + 0, NULL, + }; + type = g_type_register_static(GTK_TYPE_SOCKET, + "GtkFixedSocket", + &info, + static_cast(0)); + } + return type; + } + + // Implementation of the class initializer. + static void ClassInit(gpointer klass, gpointer class_data_unusued) { + GtkWidgetClass* widget_class = reinterpret_cast(klass); + widget_class->size_request = &HandleSizeRequest; + } + + // Report our allocation size during size requisition. This means we control + // the size, from calling gtk_widget_size_allocate in WindowedReposition(). + static void HandleSizeRequest(GtkWidget* widget, + GtkRequisition* requisition) { + requisition->width = widget->allocation.width; + requisition->height = widget->allocation.height; + } + + DISALLOW_IMPLICIT_CONSTRUCTORS(GtkFixedSocket); +}; + gboolean PlugRemovedCallback(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; } -} +} // namespace bool WebPluginDelegateImpl::WindowedCreatePlugin() { DCHECK(!windowed_handle_); @@ -260,16 +308,18 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() { return false; } - windowed_handle_ = gtk_socket_new(); - gtk_widget_set_parent(windowed_handle_, parent_); + windowed_handle_ = GtkFixedSocket::CreateNewWidget(); g_signal_connect(GTK_SOCKET(windowed_handle_), "plug-removed", G_CALLBACK(PlugRemovedCallback), NULL); + gtk_container_add(GTK_CONTAINER(parent_), windowed_handle_); // TODO(evanm): connect to signals on the socket, like when the other side // goes away. + gtk_widget_show(windowed_handle_); + gtk_widget_realize(windowed_handle_); + window_.window = GINT_TO_POINTER( gtk_socket_get_id(GTK_SOCKET(windowed_handle_))); - gtk_widget_show(windowed_handle_); NPSetWindowCallbackStruct* extra = new NPSetWindowCallbackStruct; extra->display = GDK_WINDOW_XDISPLAY(windowed_handle_->window); @@ -303,6 +353,9 @@ bool WebPluginDelegateImpl::WindowedReposition( // Clipping is handled by WebPlugin. GtkAllocation allocation = { window_rect.x(), window_rect.y(), window_rect.width(), window_rect.height() }; + // Tell our parent GtkFixed container where to place the widget. + gtk_fixed_move( + GTK_FIXED(parent_), windowed_handle_, window_rect.x(), window_rect.y()); gtk_widget_size_allocate(windowed_handle_, &allocation); window_rect_ = window_rect; -- cgit v1.1