diff options
author | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-04 01:57:59 +0000 |
---|---|---|
committer | estade@chromium.org <estade@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-09-04 01:57:59 +0000 |
commit | 2f4dead0246a6043ad9539ed8a95ab2955aab442 (patch) | |
tree | 0f829467bd0ddd1645f73279bf587b7139185726 /chrome/browser/gtk | |
parent | 29de42c9c4ed71039af911a3331be51c2da9a098 (diff) | |
download | chromium_src-2f4dead0246a6043ad9539ed8a95ab2955aab442.zip chromium_src-2f4dead0246a6043ad9539ed8a95ab2955aab442.tar.gz chromium_src-2f4dead0246a6043ad9539ed8a95ab2955aab442.tar.bz2 |
reland r57885 with a fix for the DCHECK failures observed by nsylvain.
Now we only delay shutdown of the constrained window in the escape case (see constrained_window_gtk.cc). Locally this fixes the DCHECKs in both manual testing and the login prompt ui tests.
BUG=53242, 50799
TEST=ui_tests --gtest_filter=LoginPromptTest*
Review URL: http://codereview.chromium.org/3351006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@58570 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk')
-rw-r--r-- | chrome/browser/gtk/constrained_window_gtk.cc | 50 | ||||
-rw-r--r-- | chrome/browser/gtk/constrained_window_gtk.h | 13 | ||||
-rw-r--r-- | chrome/browser/gtk/focus_store_gtk.cc | 27 | ||||
-rw-r--r-- | chrome/browser/gtk/focus_store_gtk.h | 7 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_util.cc | 7 | ||||
-rw-r--r-- | chrome/browser/gtk/gtk_util.h | 4 |
6 files changed, 53 insertions, 55 deletions
diff --git a/chrome/browser/gtk/constrained_window_gtk.cc b/chrome/browser/gtk/constrained_window_gtk.cc index 321aa16..b901083 100644 --- a/chrome/browser/gtk/constrained_window_gtk.cc +++ b/chrome/browser/gtk/constrained_window_gtk.cc @@ -16,7 +16,7 @@ ConstrainedWindowGtk::ConstrainedWindowGtk( : owner_(owner), delegate_(delegate), visible_(false), - accel_group_(gtk_accel_group_new()) { + factory_(this) { DCHECK(owner); DCHECK(delegate); GtkWidget* dialog = delegate->GetWidgetRoot(); @@ -34,20 +34,14 @@ ConstrainedWindowGtk::ConstrainedWindowGtk( gtk_container_add(GTK_CONTAINER(frame), alignment); gtk_container_add(GTK_CONTAINER(ebox), frame); border_.Own(ebox); - ConnectAccelerators(); + + gtk_widget_add_events(widget(), GDK_KEY_PRESS_MASK); + g_signal_connect(widget(), "key-press-event", G_CALLBACK(OnKeyPressThunk), + this); } ConstrainedWindowGtk::~ConstrainedWindowGtk() { border_.Destroy(); - - gtk_accel_group_disconnect_key(accel_group_, GDK_Escape, - static_cast<GdkModifierType>(0)); - if (ContainingView() && ContainingView()->GetTopLevelNativeWindow()) { - gtk_window_remove_accel_group( - GTK_WINDOW(ContainingView()->GetTopLevelNativeWindow()), - accel_group_); - } - g_object_unref(accel_group_); } void ConstrainedWindowGtk::ShowConstrainedWindow() { @@ -73,29 +67,18 @@ TabContentsViewGtk* ConstrainedWindowGtk::ContainingView() { return static_cast<TabContentsViewGtk*>(owner_->view()); } -void ConstrainedWindowGtk::ConnectAccelerators() { - gtk_accel_group_connect(accel_group_, - GDK_Escape, static_cast<GdkModifierType>(0), - static_cast<GtkAccelFlags>(0), - g_cclosure_new(G_CALLBACK(OnEscapeThunk), - this, NULL)); - gtk_window_add_accel_group( - GTK_WINDOW(ContainingView()->GetTopLevelNativeWindow()), - accel_group_); -} - - -gboolean ConstrainedWindowGtk::OnEscape(GtkAccelGroup* group, - GObject* acceleratable, - guint keyval, - GdkModifierType modifier) { - // Handle this accelerator only if this is on the currently selected tab. - Browser* browser = BrowserList::GetLastActive(); - if (!browser || browser->GetSelectedTabContents() != owner_) - return FALSE; +gboolean ConstrainedWindowGtk::OnKeyPress(GtkWidget* sender, + GdkEventKey* key) { + if (key->keyval == GDK_Escape) { + // Let the stack unwind so the event handler can release its ref + // on widget(). + MessageLoop::current()->PostTask(FROM_HERE, + factory_.NewRunnableMethod( + &ConstrainedWindowGtk::CloseConstrainedWindow)); + return TRUE; + } - CloseConstrainedWindow(); - return TRUE; + return FALSE; } // static @@ -104,4 +87,3 @@ ConstrainedWindow* ConstrainedWindow::CreateConstrainedDialog( ConstrainedWindowGtkDelegate* delegate) { return new ConstrainedWindowGtk(parent, delegate); } - diff --git a/chrome/browser/gtk/constrained_window_gtk.h b/chrome/browser/gtk/constrained_window_gtk.h index 2312cb3..117fd33 100644 --- a/chrome/browser/gtk/constrained_window_gtk.h +++ b/chrome/browser/gtk/constrained_window_gtk.h @@ -10,12 +10,12 @@ #include "app/gtk_signal.h" #include "base/basictypes.h" +#include "base/task.h" #include "chrome/browser/gtk/owned_widget_gtk.h" #include "chrome/browser/tab_contents/constrained_window.h" class TabContents; class TabContentsViewGtk; -typedef struct _GtkWidget GtkWidget; class ConstrainedWindowGtkDelegate { public: @@ -56,12 +56,9 @@ class ConstrainedWindowGtk : public ConstrainedWindow { ConstrainedWindowGtk(TabContents* owner, ConstrainedWindowGtkDelegate* delegate); - // Connects the ESC accelerator to the window. - void ConnectAccelerators(); - - // Handles an ESC accelerator being pressed. - CHROMEG_CALLBACK_3(ConstrainedWindowGtk, gboolean, OnEscape, GtkAccelGroup*, - GObject*, guint, GdkModifierType); + // Handler for Escape. + CHROMEGTK_CALLBACK_1(ConstrainedWindowGtk, gboolean, OnKeyPress, + GdkEventKey*); // The TabContents that owns and constrains this ConstrainedWindow. TabContents* owner_; @@ -75,7 +72,7 @@ class ConstrainedWindowGtk : public ConstrainedWindow { // Stores if |ShowConstrainedWindow()| has been called. bool visible_; - GtkAccelGroup* accel_group_; + ScopedRunnableMethodFactory<ConstrainedWindowGtk> factory_; DISALLOW_COPY_AND_ASSIGN(ConstrainedWindowGtk); }; diff --git a/chrome/browser/gtk/focus_store_gtk.cc b/chrome/browser/gtk/focus_store_gtk.cc index dc099fc..50ebfa7 100644 --- a/chrome/browser/gtk/focus_store_gtk.cc +++ b/chrome/browser/gtk/focus_store_gtk.cc @@ -19,19 +19,22 @@ FocusStoreGtk::~FocusStoreGtk() { } void FocusStoreGtk::Store(GtkWidget* widget) { - DisconnectDestroyHandler(); - if (!widget) { - widget_ = NULL; - return; + GtkWidget* focus_widget = NULL; + if (widget) { + GtkWindow* window = platform_util::GetTopLevel(widget); + if (window) + focus_widget = window->focus_widget; } - GtkWindow* window = platform_util::GetTopLevel(widget); - if (!window) { - widget_ = NULL; - return; - } + SetWidget(focus_widget); +} - widget_ = window->focus_widget; +void FocusStoreGtk::SetWidget(GtkWidget* widget) { + DisconnectDestroyHandler(); + + // We don't add a ref. The signal handler below effectively gives us a weak + // reference. + widget_ = widget; if (widget_) { // When invoked, |gtk_widget_destroyed| will set |widget_| to NULL. destroy_handler_id_ = g_signal_connect(widget_, "destroy", @@ -41,6 +44,8 @@ void FocusStoreGtk::Store(GtkWidget* widget) { } void FocusStoreGtk::DisconnectDestroyHandler() { - if (widget_) + if (widget_) { g_signal_handler_disconnect(widget_, destroy_handler_id_); + widget_ = NULL; + } } diff --git a/chrome/browser/gtk/focus_store_gtk.h b/chrome/browser/gtk/focus_store_gtk.h index ce3b68b..2159f1e 100644 --- a/chrome/browser/gtk/focus_store_gtk.h +++ b/chrome/browser/gtk/focus_store_gtk.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -19,9 +19,12 @@ class FocusStoreGtk { GtkWidget* widget() const { return widget_; } // Save the widget that is currently focused for |widget|'s toplevel (NOT - // |widget|). Call with NULL to clear |widget_|. + // |widget|). void Store(GtkWidget* widget); + // Save |widget| as the focus widget. Call with NULL to clear |widget_|. + void SetWidget(GtkWidget* widget); + private: // Disconnect the previous destroy handler (if any). void DisconnectDestroyHandler(); diff --git a/chrome/browser/gtk/gtk_util.cc b/chrome/browser/gtk/gtk_util.cc index 5a5a815..541d2da 100644 --- a/chrome/browser/gtk/gtk_util.cc +++ b/chrome/browser/gtk/gtk_util.cc @@ -1059,4 +1059,11 @@ string16 GetStockPreferencesMenuLabel() { return preferences; } +bool IsWidgetAncestryVisible(GtkWidget* widget) { + GtkWidget* parent = widget; + while (parent && GTK_WIDGET_VISIBLE(parent)) + parent = parent->parent; + return !parent; +} + } // namespace gtk_util diff --git a/chrome/browser/gtk/gtk_util.h b/chrome/browser/gtk/gtk_util.h index 20d3c6a..95200d4 100644 --- a/chrome/browser/gtk/gtk_util.h +++ b/chrome/browser/gtk/gtk_util.h @@ -315,6 +315,10 @@ gfx::Rect GetDialogBounds(GtkWidget* dialog); // empty string if no stock item found. string16 GetStockPreferencesMenuLabel(); +// Checks whether a widget is actually visible, i.e. whether it and all its +// ancestors up to its toplevel are visible. +bool IsWidgetAncestryVisible(GtkWidget* widget); + } // namespace gtk_util #endif // CHROME_BROWSER_GTK_GTK_UTIL_H_ |