Chromium Code Reviews| Index: views/controls/native/native_view_host_gtk.cc |
| diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc |
| index 50255f916e604dbe4401b9e1d460155c4fe99233..e63948f702c4bf26aca75ab3aaff86344488d5a9 100644 |
| --- a/views/controls/native/native_view_host_gtk.cc |
| +++ b/views/controls/native/native_view_host_gtk.cc |
| @@ -95,36 +95,53 @@ NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host) |
| installed_clip_(false), |
| destroy_signal_id_(0), |
| focus_signal_id_(0), |
| - fixed_(NULL) { |
| + fixed_(NULL), |
| + host_widget_(NULL) { |
| CreateFixed(false); |
| } |
| NativeViewHostGtk::~NativeViewHostGtk() { |
| - if (fixed_) |
| + if (fixed_) { |
| + if (host_widget_ && |
| + GTK_IS_WIDGET(host_widget_) && |
| + gtk_widget_get_parent(host_widget_) == fixed_) |
| + gtk_container_remove(GTK_CONTAINER(fixed_), host_widget_); |
|
sky
2011/07/01 20:00:38
Does this mean the host_widget_ is leaked if someo
DaveMoore
2011/07/01 20:13:34
If we don't remove it here it will get destroyed w
|
| gtk_widget_destroy(fixed_); |
| + } |
| } |
| //////////////////////////////////////////////////////////////////////////////// |
| // NativeViewHostGtk, NativeViewHostWrapper implementation: |
| void NativeViewHostGtk::NativeViewAttached() { |
| - DCHECK(host_->native_view()); |
| - if (gtk_widget_get_parent(host_->native_view())) |
| - gtk_widget_reparent(host_->native_view(), fixed_); |
| - else |
| - gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); |
| + host_widget_ = host_->native_view(); |
| + DCHECK(host_widget_); |
| + |
| + GtkWidget* host_parent = gtk_widget_get_parent(host_widget_); |
| + if (host_parent) { |
| + if (host_parent != fixed_) |
| + gtk_widget_reparent(host_widget_, fixed_); |
| + } else { |
| + gtk_container_add(GTK_CONTAINER(fixed_), host_widget_); |
| + } |
| + |
| + // We need to clear the background so we don't get flicker on tab switching. |
| + // To do that we must realize the widget if it's not already. |
| + if (!GTK_WIDGET_REALIZED(host_widget_)) |
| + gtk_widget_realize(host_widget_); |
| + gdk_window_set_back_pixmap(host_widget_->window, NULL, false); |
| // Let the widget know that the native component has been painted. |
| - views::NativeWidgetGtk::RegisterChildExposeHandler(host_->native_view()); |
| + views::NativeWidgetGtk::RegisterChildExposeHandler(host_widget_); |
| if (!destroy_signal_id_) { |
| - destroy_signal_id_ = g_signal_connect(host_->native_view(), |
| + destroy_signal_id_ = g_signal_connect(host_widget_, |
| "destroy", G_CALLBACK(CallDestroy), |
| this); |
| } |
| if (!focus_signal_id_) { |
| - focus_signal_id_ = g_signal_connect(host_->native_view(), |
| + focus_signal_id_ = g_signal_connect(host_widget_, |
| "focus-in-event", |
| G_CALLBACK(CallFocusIn), this); |
| } |
| @@ -134,33 +151,23 @@ void NativeViewHostGtk::NativeViewAttached() { |
| // We own the native view as long as it's attached, so that we can safely |
| // reparent it in multiple passes. |
| - gtk_widget_ref(host_->native_view()); |
| + gtk_widget_ref(host_widget_); |
| // TODO(port): figure out focus. |
| } |
| void NativeViewHostGtk::NativeViewDetaching(bool destroyed) { |
| - DCHECK(host_->native_view()); |
| + DCHECK(host_widget_); |
| - g_signal_handler_disconnect(G_OBJECT(host_->native_view()), |
| - destroy_signal_id_); |
| + g_signal_handler_disconnect(G_OBJECT(host_widget_), destroy_signal_id_); |
| destroy_signal_id_ = 0; |
| - g_signal_handler_disconnect(G_OBJECT(host_->native_view()), |
| - focus_signal_id_); |
| + g_signal_handler_disconnect(G_OBJECT(host_widget_), focus_signal_id_); |
| focus_signal_id_ = 0; |
| installed_clip_ = false; |
| - if (fixed_ && !destroyed) { |
| - DCHECK_NE(static_cast<gfx::NativeView>(NULL), |
| - gtk_widget_get_parent(host_->native_view())); |
| - gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view()); |
| - DCHECK_EQ( |
| - 0U, g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_)))); |
| - } |
| - |
| - g_object_unref(G_OBJECT(host_->native_view())); |
| + g_object_unref(G_OBJECT(host_widget_)); |
| } |
| void NativeViewHostGtk::AddedToWidget() { |
| @@ -174,15 +181,18 @@ void NativeViewHostGtk::AddedToWidget() { |
| if (!host_->native_view()) |
| return; |
| - if (gtk_widget_get_parent(host_->native_view())) |
| - gtk_widget_reparent(host_->native_view(), fixed_); |
| + host_widget_ = host_->native_view(); |
| + if (gtk_widget_get_parent(host_widget_)) |
| + gtk_widget_reparent(host_widget_, fixed_); |
| else |
| - gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); |
| + gtk_container_add(GTK_CONTAINER(fixed_), host_widget_); |
| - if (host_->IsVisibleInRootView()) |
| + if (host_->IsVisibleInRootView()) { |
| + gtk_widget_show(host_widget_); |
| gtk_widget_show(fixed_); |
| - else |
| + } else { |
| gtk_widget_hide(fixed_); |
| + } |
| host_->Layout(); |
| } |
| @@ -239,14 +249,14 @@ void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) { |
| // middle of a re-size, and it kicks off another re-size, and you |
| // get flashing. Instead, we'll set the desired size as properties |
| // on the widget and queue the re-size. |
| - gtk_views_fixed_set_widget_size(host_->native_view(), child_w, child_h); |
| - gtk_fixed_move(GTK_FIXED(fixed_), host_->native_view(), child_x, child_y); |
| + gtk_views_fixed_set_widget_size(host_widget_, child_w, child_h); |
| + gtk_fixed_move(GTK_FIXED(fixed_), host_widget_, child_x, child_y); |
| // Size and place the fixed_. |
| GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h); |
| + gtk_widget_show(host_widget_); |
| gtk_widget_show(fixed_); |
| - gtk_widget_show(host_->native_view()); |
| } |
| void NativeViewHostGtk::HideWidget() { |
| @@ -255,8 +265,8 @@ void NativeViewHostGtk::HideWidget() { |
| } |
| void NativeViewHostGtk::SetFocus() { |
| - DCHECK(host_->native_view()); |
| - gtk_widget_grab_focus(host_->native_view()); |
| + DCHECK(host_widget_); |
| + gtk_widget_grab_focus(host_widget_); |
| } |
| gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() { |
| @@ -290,19 +300,26 @@ void NativeViewHostGtk::CreateFixed(bool needs_window) { |
| fixed_ = gtk_views_fixed_new(); |
| gtk_widget_set_name(fixed_, "views-native-view-host-fixed"); |
| gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window); |
| + |
| // Defeat refcounting. We need to own the fixed. |
| gtk_widget_ref(fixed_); |
| NativeWidgetGtk* widget_gtk = GetHostWidget(); |
| - if (widget_gtk) |
| + if (widget_gtk) { |
| widget_gtk->AddChild(fixed_); |
| + // Clear the background so we don't get flicker. |
| + gtk_widget_realize(fixed_); |
| + gdk_window_set_back_pixmap(fixed_->window, NULL, false); |
| + } |
| - if (host_->native_view()) |
| - gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); |
| + if (host_->native_view()) { |
| + host_widget_ = host_->native_view(); |
| + gtk_container_add(GTK_CONTAINER(fixed_), host_widget_); |
| + } |
| - if (widget_gtk && host_->native_view() && focused_widget) { |
| + if (widget_gtk && host_widget_ && focused_widget) |
| gtk_widget_grab_focus(focused_widget); |
| - } |
| + |
| if (focus_event_blocked) { |
| // Unblocking a signal handler that is not blocked fails. |
| // Unblock only when it's unblocked. |
| @@ -315,13 +332,14 @@ void NativeViewHostGtk::DestroyFixed() { |
| return; |
| gtk_widget_hide(fixed_); |
| - GetHostWidget()->RemoveChild(fixed_); |
| - |
| - if (host_->native_view()) { |
| + if (host_widget_) { |
| // We can safely remove the widget from its container since we own the |
| // widget from the moment it is attached. |
| - gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view()); |
| + gtk_container_remove(GTK_CONTAINER(fixed_), host_widget_); |
| + host_widget_ = NULL; |
| } |
| + GetHostWidget()->RemoveChild(fixed_); |
| + |
| // fixed_ should not have any children this point. |
| DCHECK_EQ(0U, |
| g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_)))); |