diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-08 18:13:50 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-08 18:13:50 +0000 |
commit | cb1e496b84e8f9d702a4f78da65f7a3a5ec18594 (patch) | |
tree | b974c4bb3673c1a3c587544f19a4caa7af8d2394 /views/widget/widget_gtk.cc | |
parent | a1c3c861aea9a429785f40324c93a0d27f12b8a6 (diff) | |
download | chromium_src-cb1e496b84e8f9d702a4f78da65f7a3a5ec18594.zip chromium_src-cb1e496b84e8f9d702a4f78da65f7a3a5ec18594.tar.gz chromium_src-cb1e496b84e8f9d702a4f78da65f7a3a5ec18594.tar.bz2 |
Makes it possible for Widget's on GTK to have a transparent
background. Additionally implements always on top and makes ImageView
support borders.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/119269
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17878 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget/widget_gtk.cc')
-rw-r--r-- | views/widget/widget_gtk.cc | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index b105af8..4928d27 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -64,7 +64,8 @@ WidgetGtk::WidgetGtk(Type type) has_capture_(false), last_mouse_event_was_move_(false), ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)), - delete_on_destroy_(true) { + delete_on_destroy_(true), + transparent_(false) { } WidgetGtk::~WidgetGtk() { @@ -146,6 +147,10 @@ void WidgetGtk::Init(GtkWidget* parent, g_signal_connect(G_OBJECT(widget_), "destroy", G_CALLBACK(CallDestroy), NULL); + if (transparent_) { + g_signal_connect(G_OBJECT(widget_), "expose_event", + G_CALLBACK(CallWindowPaint), this); + } // TODO(erg): Ignore these signals for now because they're such a drag. // @@ -172,6 +177,26 @@ void WidgetGtk::Init(GtkWidget* parent, } } +bool WidgetGtk::MakeTransparent() { + // Transparency can only be enabled for windows/popups and only if we haven't + // realized the widget. + DCHECK(!widget_ && type_ != TYPE_CHILD); + + if (!gdk_screen_is_composited(gdk_screen_get_default())) { + // Transparency is only supported for compositing window managers. + DLOG(WARNING) << "compsiting not supported"; + return false; + } + + if (!gdk_screen_get_rgba_colormap(gdk_screen_get_default())) { + // We need rgba to make the window transparent. + return false; + } + + transparent_ = true; + return true; +} + void WidgetGtk::AddChild(GtkWidget* child) { gtk_container_add(GTK_CONTAINER(child_widget_parent_), child); } @@ -366,8 +391,10 @@ void WidgetGtk::CreateGtkWidget() { gtk_fixed_set_has_window(GTK_FIXED(child_widget_parent_), true); gtk_container_add(GTK_CONTAINER(widget_), child_widget_parent_); gtk_widget_show(child_widget_parent_); - SetViewForNative(child_widget_parent_, this); + + if (transparent_) + ConfigureWidgetForTransparentBackground(); } // The widget needs to be realized before handlers like size-allocate can @@ -483,6 +510,24 @@ RootView* WidgetGtk::CreateRootView() { return new RootView(this); } +void WidgetGtk::OnWindowPaint(GtkWidget* widget, GdkEventExpose* event) { + // NOTE: for reasons I don't understand this code is never hit. It should + // be hit when transparent_, but we never get the expose-event for the + // window in this case, even though a stand alone test case triggers it. I'm + // leaving it in just in case. + + // Fill the background totally transparent. We don't need to paint the root + // view here as that is done by OnPaint. + DCHECK(transparent_); + int width, height; + gtk_window_get_size (GTK_WINDOW (widget), &width, &height); + cairo_t* cr = gdk_cairo_create(widget->window); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba(cr, 0, 0, 0, 0); + cairo_rectangle(cr, 0, 0, width, height); + cairo_fill(cr); +} + bool WidgetGtk::ProcessMousePressed(GdkEventButton* event) { if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS) { // The sequence for double clicks is press, release, press, 2press, release. @@ -557,6 +602,7 @@ void WidgetGtk::CallSizeAllocate(GtkWidget* widget, GtkAllocation* allocation) { widget_gtk->OnSizeAllocate(widget, allocation); } +// static gboolean WidgetGtk::CallPaint(GtkWidget* widget, GdkEventExpose* event) { WidgetGtk* widget_gtk = GetViewForNative(widget); if (widget_gtk) @@ -564,6 +610,14 @@ gboolean WidgetGtk::CallPaint(GtkWidget* widget, GdkEventExpose* event) { return false; // False indicates other widgets should get the event as well. } +// static +gboolean WidgetGtk::CallWindowPaint(GtkWidget* widget, + GdkEventExpose* event, + WidgetGtk* widget_gtk) { + widget_gtk->OnWindowPaint(widget, event); + return false; // False indicates other widgets should get the event as well. +} + gboolean WidgetGtk::CallEnterNotify(GtkWidget* widget, GdkEventCrossing* event) { WidgetGtk* widget_gtk = GetViewForNative(widget); if (!widget_gtk) @@ -692,6 +746,37 @@ Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) { return NULL; } +void WidgetGtk::ConfigureWidgetForTransparentBackground() { + DCHECK(widget_ && child_widget_parent_ && + widget_ != child_widget_parent_); + + GdkColormap* rgba_colormap = + gdk_screen_get_rgba_colormap(gdk_screen_get_default()); + if (!rgba_colormap) { + transparent_ = false; + return; + } + // To make the background transparent we need to install the RGBA colormap + // on both the window and fixed. In addition we need to turn off double + // buffering and make sure no decorations are drawn. The last bit is to make + // sure the widget doesn't attempt to draw a pixmap in it's background. + gtk_widget_set_colormap(widget_, rgba_colormap); + gtk_widget_set_app_paintable(widget_, true); + GTK_WIDGET_UNSET_FLAGS(widget_, GTK_DOUBLE_BUFFERED); + gtk_widget_realize(widget_); + gdk_window_set_decorations(widget_->window, + static_cast<GdkWMDecoration>(0)); + // Widget must be realized before setting pixmap. + gdk_window_set_back_pixmap(widget_->window, NULL, FALSE); + + gtk_widget_set_colormap(child_widget_parent_, rgba_colormap); + gtk_widget_set_app_paintable(child_widget_parent_, true); + GTK_WIDGET_UNSET_FLAGS(child_widget_parent_, GTK_DOUBLE_BUFFERED); + gtk_widget_realize(child_widget_parent_); + // Widget must be realized before setting pixmap. + gdk_window_set_back_pixmap(child_widget_parent_->window, NULL, FALSE); +} + void WidgetGtk::HandleGrabBroke() { if (has_capture_) { if (is_mouse_down_) |