summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--views/widget/widget_gtk.cc41
-rw-r--r--views/widget/widget_gtk.h15
2 files changed, 55 insertions, 1 deletions
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index daa43d1..78f301a 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -4,6 +4,10 @@
#include "views/widget/widget_gtk.h"
+#include <gdk/gdk.h>
+#include <gdk/gdkx.h>
+#include <X11/extensions/shape.h>
+
#include "app/drag_drop_types.h"
#include "app/gfx/path.h"
#include "app/os_exchange_data.h"
@@ -98,6 +102,7 @@ WidgetGtk::WidgetGtk(Type type)
ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
delete_on_destroy_(true),
transparent_(false),
+ ignore_events_(false),
ignore_drag_leave_(false),
opacity_(255),
drag_data_(NULL),
@@ -151,6 +156,15 @@ bool WidgetGtk::MakeTransparent() {
return true;
}
+bool WidgetGtk::MakeIgnoreEvents() {
+ // Transparency can only be enabled for windows/popups and only if we haven't
+ // realized the widget.
+ DCHECK(!widget_ && type_ != TYPE_CHILD);
+
+ ignore_events_ = true;
+ return true;
+}
+
void WidgetGtk::AddChild(GtkWidget* child) {
gtk_container_add(GTK_CONTAINER(window_contents_), child);
}
@@ -1311,6 +1325,9 @@ void WidgetGtk::CreateGtkWidget(GtkWidget* parent, const gfx::Rect& bounds) {
if (transparent_)
ConfigureWidgetForTransparentBackground();
+
+ if (ignore_events_)
+ ConfigureWidgetForIgnoreEvents();
}
// The widget needs to be realized before handlers like size-allocate can
@@ -1349,6 +1366,26 @@ void WidgetGtk::ConfigureWidgetForTransparentBackground() {
gdk_window_set_back_pixmap(window_contents_->window, NULL, FALSE);
}
+void WidgetGtk::ConfigureWidgetForIgnoreEvents() {
+ gtk_widget_realize(widget_);
+ GdkWindow* gdk_window = widget_->window;
+ Display* display = GDK_WINDOW_XDISPLAY(gdk_window);
+ XID win = GDK_WINDOW_XID(gdk_window);
+
+ // This sets the clickable area to be empty, allowing all events to be
+ // passed to any windows behind this one.
+ XShapeCombineRectangles(
+ display,
+ win,
+ ShapeInput,
+ 0, // x offset
+ 0, // y offset
+ NULL, // rectangles
+ 0, // num rectangles
+ ShapeSet,
+ 0);
+}
+
void WidgetGtk::HandleGrabBroke() {
if (has_capture_) {
if (is_mouse_down_)
@@ -1364,12 +1401,14 @@ void WidgetGtk::HandleGrabBroke() {
// static
Widget* Widget::CreatePopupWidget(TransparencyParam transparent,
- EventsParam /*accept_events*/,
+ EventsParam accept_events,
DeleteParam delete_on_destroy) {
WidgetGtk* popup = new WidgetGtk(WidgetGtk::TYPE_POPUP);
popup->set_delete_on_destroy(delete_on_destroy == DeleteOnDestroy);
if (transparent == Transparent)
popup->MakeTransparent();
+ if (accept_events == NotAcceptEvents)
+ popup->MakeIgnoreEvents();
return popup;
}
diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h
index 87baeb5..185be3f 100644
--- a/views/widget/widget_gtk.h
+++ b/views/widget/widget_gtk.h
@@ -78,6 +78,13 @@ class WidgetGtk
bool MakeTransparent();
bool is_transparent() const { return transparent_; }
+ // Makes the window pass all events through to any windows behind it.
+ // This must be invoked before Init. This does a couple of checks and returns
+ // true if the window can be made to ignore events. The actual work of making
+ // the window ignore events is done by ConfigureWidgetForIgnoreEvents.
+ bool MakeIgnoreEvents();
+ bool is_ignore_events() const { return ignore_events_; }
+
// Sets whether or not we are deleted when the widget is destroyed. The
// default is true.
void set_delete_on_destroy(bool delete_on_destroy) {
@@ -372,6 +379,11 @@ class WidgetGtk
// invoked.
void ConfigureWidgetForTransparentBackground();
+ // Invoked from create widget to enable the various bits needed for a
+ // window which doesn't receive events. This is only invoked if
+ // MakeIgnoreEvents has been invoked.
+ void ConfigureWidgetForIgnoreEvents();
+
// TODO(sky): documentation
void HandleGrabBroke();
@@ -430,6 +442,9 @@ class WidgetGtk
// See description above make_transparent for details.
bool transparent_;
+ // See description above MakeIgnoreEvents for details.
+ bool ignore_events_;
+
scoped_ptr<DefaultThemeProvider> default_theme_provider_;
// See note in DropObserver for details on this.