diff options
-rw-r--r-- | chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc | 4 | ||||
-rw-r--r-- | views/controls/native/native_view_host_gtk.cc | 5 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 50 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 16 |
4 files changed, 70 insertions, 5 deletions
diff --git a/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc b/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc index 2b2bdb9..18f815c 100644 --- a/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc +++ b/chrome/browser/ui/views/tab_contents/tab_contents_view_gtk.cc @@ -30,6 +30,7 @@ #include "views/focus/view_storage.h" #include "views/screen.h" #include "views/widget/root_view.h" +#include "views/widget/widget_gtk.h" using WebKit::WebDragOperation; using WebKit::WebDragOperationsMask; @@ -189,6 +190,9 @@ RenderWidgetHostView* TabContentsViewGtk::CreateViewForWidget( gtk_widget_add_events(view->native_view(), GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); + // Let widget know that the tab contents has been painted. + views::WidgetGtk::RegisterChildExposeHandler(view->native_view()); + // Renderer target DnD. if (tab_contents()->ShouldAcceptDragAndDrop()) drag_dest_.reset(new WebDragDestGtk(tab_contents(), view->native_view())); diff --git a/views/controls/native/native_view_host_gtk.cc b/views/controls/native/native_view_host_gtk.cc index 4a6d155..d5e4110 100644 --- a/views/controls/native/native_view_host_gtk.cc +++ b/views/controls/native/native_view_host_gtk.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -111,6 +111,9 @@ void NativeViewHostGtk::NativeViewAttached() { else gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); + // Let the widget know that the native component has been painted. + views::WidgetGtk::RegisterChildExposeHandler(host_->native_view()); + if (!destroy_signal_id_) { destroy_signal_id_ = g_signal_connect(host_->native_view(), "destroy", G_CALLBACK(CallDestroy), diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index 6a31bb8..d6655da 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -60,14 +60,20 @@ namespace { // Links the GtkWidget to its NativeWidget. const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__"; + // A g_object data key to associate a CompositePainter object to a GtkWidget. const char* kCompositePainterKey = "__VIEWS_COMPOSITE_PAINTER__"; + // A g_object data key to associate the flag whether or not the widget // is composited to a GtkWidget. gtk_widget_is_composited simply tells // if x11 supports composition and cannot be used to tell if given widget // is composited. const char* kCompositeEnabledKey = "__VIEWS_COMPOSITE_ENABLED__"; +// A g_object data key to associate the expose handler id that is +// used to remove FREEZE_UPDATE property on the window. +const char* kExposeHandlerIdKey = "__VIEWS_EXPOSE_HANDLER_ID__"; + // CompositePainter draws a composited child widgets image into its // drawing area. This object is created at most once for a widget and kept // until the widget is destroyed. @@ -164,6 +170,15 @@ void EnumerateChildWidgetsForNativeWidgets(GtkWidget* child_widget, } } +void RemoveExposeHandlerIfExists(GtkWidget* widget) { + gulong id = reinterpret_cast<gulong>(g_object_get_data(G_OBJECT(widget), + kExposeHandlerIdKey)); + if (id) { + g_signal_handler_disconnect(G_OBJECT(widget), id); + g_object_set_data(G_OBJECT(widget), kExposeHandlerIdKey, 0); + } +} + } // namespace // During drag and drop GTK sends a drag-leave during a drop. This means we @@ -713,9 +728,6 @@ void WidgetGtk::EnableDebugPaint() { void WidgetGtk::UpdateFreezeUpdatesProperty(GtkWindow* window, bool enable) { if (!GTK_WIDGET_REALIZED(GTK_WIDGET(window))) gtk_widget_realize(GTK_WIDGET(window)); -#if 0 - // Temporarily disabling the FREEZE_UPDATE as this is causing - // problem in panels. see crosbug.com/13750. GdkWindow* gdk_window = GTK_WIDGET(window)->window; static GdkAtom freeze_atom_ = @@ -736,7 +748,15 @@ void WidgetGtk::UpdateFreezeUpdatesProperty(GtkWindow* window, bool enable) { GDK_WINDOW_XID(gdk_window); gdk_property_delete(gdk_window, freeze_atom_); } -#endif +} + +// static +void WidgetGtk::RegisterChildExposeHandler(GtkWidget* child) { + RemoveExposeHandlerIfExists(child); + gulong id = g_signal_connect_after(child, "expose-event", + G_CALLBACK(&ChildExposeHandler), NULL); + g_object_set_data(G_OBJECT(child), kExposeHandlerIdKey, + reinterpret_cast<void*>(id)); } //////////////////////////////////////////////////////////////////////////////// @@ -1380,6 +1400,28 @@ gboolean WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) { return false; } +void WidgetGtk::OnChildExpose(GtkWidget* child) { + DCHECK(type_ != TYPE_CHILD); + if (!painted_) { + painted_ = true; + UpdateFreezeUpdatesProperty(GTK_WINDOW(widget_), false /* remove */); + } + RemoveExposeHandlerIfExists(child); +} + +// static +gboolean WidgetGtk::ChildExposeHandler(GtkWidget* widget, + GdkEventExpose* event) { + GtkWidget* toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW); + CHECK(toplevel); + NativeWidget* native_widget = + NativeWidget::GetNativeWidgetForNativeView(toplevel); + CHECK(native_widget); + WidgetGtk* widget_gtk = static_cast<WidgetGtk*>(native_widget); + widget_gtk->OnChildExpose(widget); + return false; +} + // static Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) { GtkWidget* parent = widget; diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index 14eab68..597ec58 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -187,6 +187,17 @@ class WidgetGtk : public Widget, // which does not support this property. static void UpdateFreezeUpdatesProperty(GtkWindow* window, bool enable); + // Registers a expose handler that removes FREEZE_UPDATES property. + // If you are adding a GtkWidget with its own GdkWindow that may + // fill the entire area of the WidgetGtk to the view hierachy, you + // need use this function to tell WM that when the widget is ready + // to be shown. + // Caller of this method do not need to disconnect this because the + // handler will be removed upon the first invocation of the handler, + // or when the widget is re-attached, and expose won't be emitted on + // detached widget. + static void RegisterChildExposeHandler(GtkWidget* widget); + // Overridden from NativeWidget: virtual void SetCreateParams(const CreateParams& params) OVERRIDE; virtual Widget* GetWidget() OVERRIDE; @@ -298,6 +309,11 @@ class WidgetGtk : public Widget, // This is called only when the window is transparent. CHROMEGTK_CALLBACK_1(WidgetGtk, gboolean, OnWindowPaint, GdkEventExpose*); + // Callbacks for expose event on child widgets. See the description of + // RegisterChildChildExposeHandler. + void OnChildExpose(GtkWidget* child); + static gboolean ChildExposeHandler(GtkWidget* widget, GdkEventExpose* event); + // Returns the first ancestor of |widget| that is a window. static Window* GetWindowImpl(GtkWidget* widget); |