summaryrefslogtreecommitdiffstats
path: root/views/controls/native
diff options
context:
space:
mode:
authordavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-07 15:34:42 +0000
committerdavemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-07 15:34:42 +0000
commitb18d98d7de474db2a2057d0e3aaaac9bd87a2f41 (patch)
tree04e6c078a7ae91c8317ad7456bdc92b0f495d0f8 /views/controls/native
parentbed227921947929deb99b9706a45c01d584eb881 (diff)
downloadchromium_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.cc112
-rw-r--r--views/controls/native/native_view_host_gtk.h3
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);