diff options
author | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-07 15:34:42 +0000 |
---|---|---|
committer | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-07 15:34:42 +0000 |
commit | b18d98d7de474db2a2057d0e3aaaac9bd87a2f41 (patch) | |
tree | 04e6c078a7ae91c8317ad7456bdc92b0f495d0f8 /views/controls/native | |
parent | bed227921947929deb99b9706a45c01d584eb881 (diff) | |
download | chromium_src-b18d98d7de474db2a2057d0e3aaaac9bd87a2f41.zip chromium_src-b18d98d7de474db2a2057d0e3aaaac9bd87a2f41.tar.gz chromium_src-b18d98d7de474db2a2057d0e3aaaac9bd87a2f41.tar.bz2 |
Fix flicker on tab switch on chromeos.
BUG=84721
TEST=Switch tabs...no flicker
Review URL: http://codereview.chromium.org/7171025
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@91710 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/controls/native')
-rw-r--r-- | views/controls/native/native_view_host_gtk.cc | 112 | ||||
-rw-r--r-- | views/controls/native/native_view_host_gtk.h | 3 |
2 files changed, 67 insertions, 48 deletions
diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc index 50255f9..1290752 100644 --- a/views/controls/native/native_view_host_gtk.cc +++ b/views/controls/native/native_view_host_gtk.cc @@ -85,6 +85,11 @@ void UnblockFocusSignals(GtkWidget* widget, gpointer data) { gtk_container_foreach(GTK_CONTAINER(widget), UnblockFocusSignals, data); } +// Removes |child| from |parent|. +void RemoveFromParent(GtkWidget* child, gpointer parent) { + gtk_container_remove(GTK_CONTAINER(parent), child); +} + } // namespace //////////////////////////////////////////////////////////////////////////////// @@ -100,31 +105,31 @@ NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host) } NativeViewHostGtk::~NativeViewHostGtk() { - if (fixed_) + if (fixed_) { + gtk_container_foreach(GTK_CONTAINER(fixed_), RemoveFromParent, fixed_); 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()); + AttachHostWidget(); + + GtkWidget* host_widget = host_->native_view(); // 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); } @@ -132,35 +137,20 @@ void NativeViewHostGtk::NativeViewAttached() { // Always layout though. host_->Layout(); - // 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()); - // TODO(port): figure out focus. } void NativeViewHostGtk::NativeViewDetaching(bool destroyed) { - DCHECK(host_->native_view()); + GtkWidget* host_widget = 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())); } void NativeViewHostGtk::AddedToWidget() { @@ -174,15 +164,14 @@ void NativeViewHostGtk::AddedToWidget() { if (!host_->native_view()) return; - 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()); + AttachHostWidget(); - if (host_->IsVisibleInRootView()) + if (host_->IsVisibleInRootView()) { + gtk_widget_show(host_->native_view()); gtk_widget_show(fixed_); - else + } else { gtk_widget_hide(fixed_); + } host_->Layout(); } @@ -235,18 +224,19 @@ void NativeViewHostGtk::ShowWidget(int x, int y, int w, int h) { fixed_h = std::min(installed_clip_bounds_.height(), h); } + GtkWidget* host_widget = host_->native_view(); // Don't call gtk_widget_size_allocate now, as we're possibly in the // 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 +245,9 @@ void NativeViewHostGtk::HideWidget() { } void NativeViewHostGtk::SetFocus() { - DCHECK(host_->native_view()); - gtk_widget_grab_focus(host_->native_view()); + GtkWidget* host_widget = host_->native_view(); + DCHECK(host_widget); + gtk_widget_grab_focus(host_widget); } gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() { @@ -290,19 +281,24 @@ 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()); + AttachHostWidget(); - if (widget_gtk && host_->native_view() && focused_widget) { + if (widget_gtk && host_->native_view() && 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 +311,9 @@ void NativeViewHostGtk::DestroyFixed() { return; gtk_widget_hide(fixed_); + gtk_container_foreach(GTK_CONTAINER(fixed_), RemoveFromParent, fixed_); GetHostWidget()->RemoveChild(fixed_); - if (host_->native_view()) { - // 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()); - } // fixed_ should not have any children this point. DCHECK_EQ(0U, g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_)))); @@ -349,6 +341,30 @@ GtkWidget* NativeViewHostGtk::GetFocusedDescendant() { focused : NULL; } +void NativeViewHostGtk::AttachHostWidget() { + GtkWidget* host_widget = host_->native_view(); + DCHECK(host_widget); + + GtkWidget* host_parent = gtk_widget_get_parent(host_widget); + bool parent_changed = true; + if (host_parent) { + if (host_parent != fixed_) + gtk_widget_reparent(host_widget, fixed_); + else + parent_changed = false; + } else { + gtk_container_add(GTK_CONTAINER(fixed_), host_widget); + } + + if (parent_changed) { + // 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); + } +} + // static void NativeViewHostGtk::CallDestroy(GtkObject* object, NativeViewHostGtk* host) { diff --git a/views/controls/native/native_view_host_gtk.h b/views/controls/native/native_view_host_gtk.h index 0ecfd99..84b0a36 100644 --- a/views/controls/native/native_view_host_gtk.h +++ b/views/controls/native/native_view_host_gtk.h @@ -57,6 +57,9 @@ class NativeViewHostGtk : public NativeViewHostWrapper { // on a descendant of fixed_. GtkWidget* GetFocusedDescendant(); + // Connects a new host widget. + void AttachHostWidget(); + // Invoked from the 'destroy' signal. static void CallDestroy(GtkObject* object, NativeViewHostGtk* host); |