diff options
-rw-r--r-- | views/widget/widget_gtk.cc | 41 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 15 |
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. |