summaryrefslogtreecommitdiffstats
path: root/views/widget
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-20 20:56:11 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-20 20:56:11 +0000
commit893160d54cb5b2c1c68d3b69ec8ebc9b25b68b82 (patch)
tree0f29c1776a2f34f06ba60ba53a20691d261b6366 /views/widget
parent22332192088e1e897d02a4bc7a2983e3864ab3b6 (diff)
downloadchromium_src-893160d54cb5b2c1c68d3b69ec8ebc9b25b68b82.zip
chromium_src-893160d54cb5b2c1c68d3b69ec8ebc9b25b68b82.tar.gz
chromium_src-893160d54cb5b2c1c68d3b69ec8ebc9b25b68b82.tar.bz2
Minor gtk-views cleanup:
. Makes closing widget work. . Makes clicking button send action. . Fixes ownership of native controls. BUG=none TEST=none Review URL: http://codereview.chromium.org/113657 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16532 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views/widget')
-rw-r--r--views/widget/widget_gtk.cc78
-rw-r--r--views/widget/widget_gtk.h19
2 files changed, 83 insertions, 14 deletions
diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc
index 0b24657..1f8790e 100644
--- a/views/widget/widget_gtk.cc
+++ b/views/widget/widget_gtk.cc
@@ -4,6 +4,7 @@
#include "views/widget/widget_gtk.h"
+#include "base/compiler_specific.h"
#include "views/fill_layout.h"
#include "views/widget/root_view.h"
#include "views/window/window_gtk.h"
@@ -57,15 +58,12 @@ WidgetGtk::WidgetGtk(Type type)
child_widget_parent_(NULL),
is_mouse_down_(false),
has_capture_(false),
- last_mouse_event_was_move_(false) {
+ last_mouse_event_was_move_(false),
+ ALLOW_THIS_IN_INITIALIZER_LIST(close_widget_factory_(this)),
+ delete_on_destroy_(true) {
}
WidgetGtk::~WidgetGtk() {
- if (widget_) {
- // TODO: make sure this is right.
- gtk_widget_destroy(widget_);
- child_widget_parent_ = widget_ = NULL;
- }
MessageLoopForUI::current()->RemoveObserver(this);
}
@@ -79,10 +77,10 @@ void WidgetGtk::Init(const gfx::Rect& bounds,
// Make sure we receive our motion events.
- // We register everything on the parent of all widgets. At a minimum we need
- // painting to happen on the parent (otherwise painting doesn't work at all),
- // and similarly we need mouse release events on the parent as windows don't
- // get mouse releases.
+ // In general we register most events on the parent of all widgets. At a
+ // minimum we need painting to happen on the parent (otherwise painting
+ // doesn't work at all), and similarly we need mouse release events on the
+ // parent as windows don't get mouse releases.
gtk_widget_add_events(child_widget_parent_,
GDK_ENTER_NOTIFY_MASK |
GDK_LEAVE_NOTIFY_MASK |
@@ -114,10 +112,6 @@ void WidgetGtk::Init(const gfx::Rect& bounds,
G_CALLBACK(CallButtonPress), NULL);
g_signal_connect(G_OBJECT(child_widget_parent_), "button_release_event",
G_CALLBACK(CallButtonRelease), NULL);
- g_signal_connect(G_OBJECT(child_widget_parent_), "focus_in_event",
- G_CALLBACK(CallFocusIn), NULL);
- g_signal_connect(G_OBJECT(child_widget_parent_), "focus_out_event",
- G_CALLBACK(CallFocusOut), NULL);
g_signal_connect(G_OBJECT(child_widget_parent_), "grab_broke_event",
G_CALLBACK(CallGrabBrokeEvent), NULL);
g_signal_connect(G_OBJECT(child_widget_parent_), "grab_notify",
@@ -133,6 +127,17 @@ void WidgetGtk::Init(const gfx::Rect& bounds,
g_signal_connect(G_OBJECT(child_widget_parent_), "visibility_notify_event",
G_CALLBACK(CallVisibilityNotify), NULL);
+ // In order to receive notification when the window is no longer the front
+ // window, we need to install these on the widget.
+ // NOTE: this doesn't work with focus follows mouse.
+ g_signal_connect(G_OBJECT(widget_), "focus_in_event",
+ G_CALLBACK(CallFocusIn), NULL);
+ g_signal_connect(G_OBJECT(widget_), "focus_out_event",
+ G_CALLBACK(CallFocusOut), NULL);
+
+ g_signal_connect(G_OBJECT(widget_), "destroy",
+ G_CALLBACK(CallDestroy), NULL);
+
// TODO(erg): Ignore these signals for now because they're such a drag.
//
// g_signal_connect(G_OBJECT(widget_), "drag_motion",
@@ -174,6 +179,35 @@ void WidgetGtk::SetContentsView(View* view) {
OnSizeAllocate(widget_, &(widget_->allocation));
}
+void WidgetGtk::Close() {
+ if (!widget_)
+ return; // No need to do anything.
+
+ // Hide first.
+ Hide();
+ if (close_widget_factory_.empty()) {
+ // And we delay the close just in case we're on the stack.
+ MessageLoop::current()->PostTask(FROM_HERE,
+ close_widget_factory_.NewRunnableMethod(
+ &WidgetGtk::CloseNow));
+ }
+}
+
+void WidgetGtk::CloseNow() {
+ if (widget_)
+ gtk_widget_destroy(widget_);
+}
+
+void WidgetGtk::Show() {
+ if (widget_)
+ gtk_widget_show(widget_);
+}
+
+void WidgetGtk::Hide() {
+ if (widget_)
+ gtk_widget_hide(widget_);
+}
+
void WidgetGtk::GetBounds(gfx::Rect* out, bool including_frame) const {
DCHECK(widget_);
@@ -368,6 +402,13 @@ void WidgetGtk::OnGrabNotify(GtkWidget* widget, gboolean was_grabbed) {
HandleGrabBroke();
}
+void WidgetGtk::OnDestroy(GtkWidget* widget) {
+ widget_ = child_widget_parent_ = NULL;
+ root_view_->OnWidgetDestroyed();
+ if (delete_on_destroy_)
+ delete this;
+}
+
// static
WindowGtk* WidgetGtk::GetWindowForNative(GtkWidget* widget) {
gpointer user_data = g_object_get_data(G_OBJECT(widget), "chrome-window");
@@ -572,6 +613,15 @@ void WidgetGtk::CallGrabNotify(GtkWidget* widget, gboolean was_grabbed) {
}
// static
+void WidgetGtk::CallDestroy(GtkObject* object) {
+ WidgetGtk* widget_gtk = GetViewForNative(GTK_WIDGET(object));
+ if (!widget_gtk)
+ return;
+
+ return widget_gtk->OnDestroy(GTK_WIDGET(object));
+}
+
+// static
Window* WidgetGtk::GetWindowImpl(GtkWidget* widget) {
GtkWidget* parent = widget;
while (parent) {
diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h
index cebc686..e1a7468 100644
--- a/views/widget/widget_gtk.h
+++ b/views/widget/widget_gtk.h
@@ -39,6 +39,12 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
// Initializes this widget.
void Init(const gfx::Rect& bounds, bool has_own_focus_manager);
+ // 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) {
+ delete_on_destroy_ = delete_on_destroy;
+ }
+
void AddChild(GtkWidget* child);
void RemoveChild(GtkWidget* child);
@@ -51,6 +57,11 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
virtual void SetContentsView(View* view);
+ virtual void Close();
+ void CloseNow();
+ virtual void Show();
+ virtual void Hide();
+
// Overridden from Widget:
virtual void GetBounds(gfx::Rect* out, bool including_frame) const;
virtual gfx::NativeView GetNativeView() const;
@@ -93,6 +104,7 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
}
virtual gboolean OnGrabBrokeEvent(GtkWidget* widget, GdkEvent* event);
virtual void OnGrabNotify(GtkWidget* widget, gboolean was_grabbed);
+ virtual void OnDestroy(GtkWidget* widget);
// Returns whether capture should be released on mouse release. The default
// is true.
@@ -136,6 +148,7 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
GdkEventVisibility* event);
static gboolean CallGrabBrokeEvent(GtkWidget* widget, GdkEvent* event);
static void CallGrabNotify(GtkWidget* widget, gboolean was_grabbed);
+ static void CallDestroy(GtkObject* object);
// Returns the first ancestor of |widget| that is a window.
static Window* GetWindowImpl(GtkWidget* widget);
@@ -173,6 +186,12 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer {
int last_mouse_move_x_;
int last_mouse_move_y_;
+ // The following factory is used to delay destruction.
+ ScopedRunnableMethodFactory<WidgetGtk> close_widget_factory_;
+
+ // See description above setter.
+ bool delete_on_destroy_;
+
DISALLOW_COPY_AND_ASSIGN(WidgetGtk);
};