diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-07 18:25:51 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-07 18:25:51 +0000 |
commit | 445873cae45fd143a1f1fd936a578b576b6118ec (patch) | |
tree | 40fc63a337afcac36dfce98fabfdd184c26bddb7 /views | |
parent | a3f3079c3fa68dc79831183af4aa7ef79854f2ec (diff) | |
download | chromium_src-445873cae45fd143a1f1fd936a578b576b6118ec.zip chromium_src-445873cae45fd143a1f1fd936a578b576b6118ec.tar.gz chromium_src-445873cae45fd143a1f1fd936a578b576b6118ec.tar.bz2 |
Fixes two related focus bugs on views/gtk:
. Focus was inadvertently getting cleared when a window was shown
because the focus-in event is received asynchronously.
. In some situations we get multiple focus-out events in a row, this
caused us to clear out who we thought would have focus.
BUG=31140, 31130
TEST=see bugs
Review URL: http://codereview.chromium.org/521045
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35714 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/focus/focus_manager_unittest.cc | 3 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 19 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 16 |
3 files changed, 35 insertions, 3 deletions
diff --git a/views/focus/focus_manager_unittest.cc b/views/focus/focus_manager_unittest.cc index bab3cf1..548989a 100644 --- a/views/focus/focus_manager_unittest.cc +++ b/views/focus/focus_manager_unittest.cc @@ -839,6 +839,9 @@ TEST_F(FocusManagerTest, FocusNativeControls) { // Test that when activating/deactivating the top window, the focus is stored/ // restored properly. TEST_F(FocusManagerTest, FocusStoreRestore) { + // Simulate an activate, otherwise the deactivate isn't going to do anything. + SimulateActivateWindow(); + NativeButton* button = new NativeButton(NULL, L"Press me"); View* view = new View(); view->SetFocusable(true); diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index e10bf60..ab88713 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -98,7 +98,9 @@ WidgetGtk::WidgetGtk(Type type) drag_data_(NULL), in_paint_now_(false), is_active_(false), - transient_to_parent_(false) { + transient_to_parent_(false), + got_initial_focus_in_(false), + has_focus_(false) { static bool installed_message_loop_observer = false; if (!installed_message_loop_observer) { installed_message_loop_observer = true; @@ -778,15 +780,26 @@ gboolean WidgetGtk::OnButtonRelease(GtkWidget* widget, GdkEventButton* event) { } gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { + if (has_focus_) + return false; // This is the second focus-in event in a row, ignore it. + has_focus_ = true; + if (type_ == TYPE_CHILD) return false; - // The top-level window got focus, restore the last focused view. - focus_manager_->RestoreFocusedView(); + // See description of got_initial_focus_in_ for details on this. + if (!got_initial_focus_in_) + got_initial_focus_in_ = true; + else + focus_manager_->RestoreFocusedView(); return false; } gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { + if (!has_focus_) + return false; // This is the second focus-out event in a row, ignore it. + has_focus_ = false; + if (type_ == TYPE_CHILD) return false; diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index 4efe515..9d73bf0 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -432,6 +432,22 @@ class WidgetGtk // hasn't changed, we can end up getting stuck in a never ending loop. gfx::Size size_; + // This is initially false and when the first focus-in event is received this + // is set to true and no additional processing is done. Subsequently when + // focus-in is received we do the normal focus manager processing. + // + // This behavior is necessitated by Gtk/X sending focus events + // asynchronously. The initial sequence for windows is typically: show, + // request focus on some widget. Because of async events on Gtk this becomes + // show, request focus, get focus in event which ends up clearing focus + // (first request to FocusManager::RestoreFocusedView ends up clearing focus). + bool got_initial_focus_in_; + + // If true, we've received a focus-in event. If false we've received a + // focus-out event. We can get multiple focus-out events in a row, we use + // this to determine whether we should process the event. + bool has_focus_; + DISALLOW_COPY_AND_ASSIGN(WidgetGtk); }; |