summaryrefslogtreecommitdiffstats
path: root/views/widget/widget_gtk.cc
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-08 18:13:50 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-08 18:13:50 +0000
commitcb1e496b84e8f9d702a4f78da65f7a3a5ec18594 (patch)
treeb974c4bb3673c1a3c587544f19a4caa7af8d2394 /views/widget/widget_gtk.cc
parenta1c3c861aea9a429785f40324c93a0d27f12b8a6 (diff)
downloadchromium_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.cc89
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_)