diff options
author | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 22:53:51 +0000 |
---|---|---|
committer | jcampan@chromium.org <jcampan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 22:53:51 +0000 |
commit | dc5e89230025a8202e0314410a388ad91138020c (patch) | |
tree | 41630518a44295112141de14f595c50e11fb84de | |
parent | 668dd15b25cf7fd94fede92dd140b59c62009390 (diff) | |
download | chromium_src-dc5e89230025a8202e0314410a388ad91138020c.zip chromium_src-dc5e89230025a8202e0314410a388ad91138020c.tar.gz chromium_src-dc5e89230025a8202e0314410a388ad91138020c.tar.bz2 |
The FocusManager stores/restores focus when the top window becomes inactive/active.
BUG=None
TEST=Run the focus manager unit-tests.
Review URL: http://codereview.chromium.org/164448
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25108 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | app/resources/app_resources.grd | 6 | ||||
-rw-r--r-- | chrome/chrome.gyp | 3 | ||||
-rw-r--r-- | views/controls/button/native_button_gtk.cc | 7 | ||||
-rw-r--r-- | views/controls/native_control_gtk.cc | 18 | ||||
-rw-r--r-- | views/controls/native_control_gtk.h | 6 | ||||
-rw-r--r-- | views/focus/focus_manager.cc | 45 | ||||
-rw-r--r-- | views/focus/focus_manager_gtk.cc | 19 | ||||
-rw-r--r-- | views/focus/focus_manager_unittest.cc | 95 | ||||
-rw-r--r-- | views/view_unittest.cc | 46 | ||||
-rw-r--r-- | views/views.gyp | 3 | ||||
-rw-r--r-- | views/widget/root_view.cc | 7 | ||||
-rw-r--r-- | views/widget/widget_gtk.cc | 18 | ||||
-rw-r--r-- | views/widget/widget_gtk.h | 14 |
13 files changed, 204 insertions, 83 deletions
diff --git a/app/resources/app_resources.grd b/app/resources/app_resources.grd index 086ebb4..9bf6b54 100644 --- a/app/resources/app_resources.grd +++ b/app/resources/app_resources.grd @@ -36,9 +36,9 @@ <include name="IDR_CLOSE" file="linux_close.png" type="BINDATA" /> <include name="IDR_CLOSE_H" file="linux_close_h.png" type="BINDATA" /> <include name="IDR_CLOSE_P" file="linux_close_p.png" type="BINDATA" /> - <include name="IDR_CLOSE_SA" file="close_sa.png" type="BINDATA" /> - <include name="IDR_CLOSE_SA_H" file="close_sa_h.png" type="BINDATA" /> - <include name="IDR_CLOSE_SA_P" file="close_sa_p.png" type="BINDATA" /> + <include name="IDR_CLOSE_SA" file="linux_close.png" type="BINDATA" /> + <include name="IDR_CLOSE_SA_H" file="linux_close_h.png" type="BINDATA" /> + <include name="IDR_CLOSE_SA_P" file="linux_close_p.png" type="BINDATA" /> <include name="IDR_RESTORE" file="linux_restore.png" type="BINDATA" /> <include name="IDR_RESTORE_H" file="linux_restore_h.png" type="BINDATA" /> <include name="IDR_RESTORE_P" file="linux_restore_p.png" type="BINDATA" /> diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 47a521b..b16ac73 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -4222,7 +4222,8 @@ ['exclude', 'browser/gtk/bookmark_editor_gtk_unittest\\.cc$'], ['exclude', 'browser/gtk/go_button_gtk_unittest\\.cc$'], ['exclude', 'browser/gtk/tabs/tab_renderer_gtk_unittest\\.cc$'], - ['exclude', 'browser/gtk/options/cookies_view_unittest\\.cc$'], + ['exclude', 'browser/gtk/options/cookies_view_unittest\\.cc$'], + ['exclude', 'browser/gtk/options/languages_page_gtk_unittest\\.cc$'], ], }], ['OS=="mac"', { diff --git a/views/controls/button/native_button_gtk.cc b/views/controls/button/native_button_gtk.cc index 4ed3138..900a2b2 100644 --- a/views/controls/button/native_button_gtk.cc +++ b/views/controls/button/native_button_gtk.cc @@ -142,4 +142,11 @@ NativeButtonWrapper* NativeButtonWrapper::CreateCheckboxWrapper( return new NativeCheckboxGtk(checkbox); } +// static +NativeButtonWrapper* NativeButtonWrapper::CreateRadioButtonWrapper( + RadioButton* radio_button) { + NOTIMPLEMENTED(); + return NULL; +} + } // namespace views diff --git a/views/controls/native_control_gtk.cc b/views/controls/native_control_gtk.cc index e95278d..a13c870 100644 --- a/views/controls/native_control_gtk.cc +++ b/views/controls/native_control_gtk.cc @@ -7,6 +7,7 @@ #include <gtk/gtk.h> #include "base/logging.h" +#include "views/focus/focus_manager.h" namespace views { @@ -63,6 +64,23 @@ void NativeControlGtk::NativeControlCreated(GtkWidget* native_control) { // Update the newly created GtkWdigetwith any resident enabled state. gtk_widget_set_sensitive(native_view(), IsEnabled()); + + // Listen for focus change event to update the FocusManager focused view. + g_signal_connect(G_OBJECT(native_control), "focus-in-event", + G_CALLBACK(CallFocusIn), this); +} + +// static +void NativeControlGtk::CallFocusIn(GtkWidget* widget, + GdkEventFocus* event, + NativeControlGtk* control) { + FocusManager* focus_manager = + FocusManager::GetFocusManagerForNativeView(widget); + if (!focus_manager) { + NOTREACHED(); + return; + } + focus_manager->SetFocusedView(control->focus_view()); } } // namespace views diff --git a/views/controls/native_control_gtk.h b/views/controls/native_control_gtk.h index 2f0ffab..ce2f187 100644 --- a/views/controls/native_control_gtk.h +++ b/views/controls/native_control_gtk.h @@ -5,6 +5,8 @@ #ifndef VIEWS_CONTROLS_NATIVE_CONTROL_GTK_H_ #define VIEWS_CONTROLS_NATIVE_CONTROL_GTK_H_ +#include <gtk/gtk.h> + #include "views/controls/native/native_view_host.h" namespace views { @@ -34,6 +36,10 @@ class NativeControlGtk : public NativeViewHost { virtual void NativeControlCreated(GtkWidget* widget); private: + static void CallFocusIn(GtkWidget* widget, + GdkEventFocus* event, + NativeControlGtk* button); + DISALLOW_COPY_AND_ASSIGN(NativeControlGtk); }; diff --git a/views/focus/focus_manager.cc b/views/focus/focus_manager.cc index 1a0f7ae..dffb392 100644 --- a/views/focus/focus_manager.cc +++ b/views/focus/focus_manager.cc @@ -224,31 +224,32 @@ View* FocusManager::GetNextFocusableView(View* original_starting_view, } void FocusManager::SetFocusedView(View* view) { - if (focused_view_ != view) { - View* prev_focused_view = focused_view_; - if (focused_view_) - focused_view_->WillLoseFocus(); - - if (view) - view->WillGainFocus(); - - // Notified listeners that the focus changed. - FocusChangeListenerList::const_iterator iter; - for (iter = focus_change_listeners_.begin(); - iter != focus_change_listeners_.end(); ++iter) { - (*iter)->FocusWillChange(prev_focused_view, view); - } + if (focused_view_ == view) + return; - focused_view_ = view; + View* prev_focused_view = focused_view_; + if (focused_view_) + focused_view_->WillLoseFocus(); - if (prev_focused_view) - prev_focused_view->SchedulePaint(); // Remove focus artifacts. + if (view) + view->WillGainFocus(); - if (view) { - view->SchedulePaint(); - view->Focus(); - view->DidGainFocus(); - } + // Notified listeners that the focus changed. + FocusChangeListenerList::const_iterator iter; + for (iter = focus_change_listeners_.begin(); + iter != focus_change_listeners_.end(); ++iter) { + (*iter)->FocusWillChange(prev_focused_view, view); + } + + focused_view_ = view; + + if (prev_focused_view) + prev_focused_view->SchedulePaint(); // Remove focus artifacts. + + if (view) { + view->SchedulePaint(); + view->Focus(); + view->DidGainFocus(); } } diff --git a/views/focus/focus_manager_gtk.cc b/views/focus/focus_manager_gtk.cc index 8017961..eb25654 100644 --- a/views/focus/focus_manager_gtk.cc +++ b/views/focus/focus_manager_gtk.cc @@ -2,14 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <gtk/gtk.h> + #include "views/focus/focus_manager.h" #include "base/logging.h" +#include "views/widget/widget_gtk.h" namespace views { void FocusManager::ClearNativeFocus() { - NOTIMPLEMENTED(); + gtk_widget_grab_focus(widget_->GetNativeView()); } void FocusManager::FocusNativeView(gfx::NativeView native_view) { @@ -19,8 +22,18 @@ void FocusManager::FocusNativeView(gfx::NativeView native_view) { // static FocusManager* FocusManager::GetFocusManagerForNativeView( gfx::NativeView native_view) { - NOTIMPLEMENTED(); - return NULL; + GtkWidget* parent; + while ((parent = gtk_widget_get_parent(native_view)) != NULL) { + native_view = parent; + } + WidgetGtk* widget = WidgetGtk::GetViewForNative(native_view); + if (!widget) { + NOTREACHED(); + return NULL; + } + FocusManager* focus_manager = widget->GetFocusManager(); + DCHECK(focus_manager) << "no FocusManager for top level Widget"; + return focus_manager; } } // namespace views diff --git a/views/focus/focus_manager_unittest.cc b/views/focus/focus_manager_unittest.cc index 720e9f8..215ed00 100644 --- a/views/focus/focus_manager_unittest.cc +++ b/views/focus/focus_manager_unittest.cc @@ -25,12 +25,10 @@ #include "views/controls/label.h" #include "views/controls/link.h" #include "views/controls/native/native_view_host.h" -#if defined(OS_WIN) +#include "views/controls/textfield/textfield.h" #include "views/controls/scroll_view.h" #include "views/controls/tabbed_pane/native_tabbed_pane_wrapper.h" #include "views/controls/tabbed_pane/tabbed_pane.h" -#include "views/controls/textfield/textfield.h" -#endif #include "views/focus/accelerator_handler.h" #include "views/widget/root_view.h" #include "views/window/window.h" @@ -45,10 +43,10 @@ namespace views { -#if defined(OS_WIN) static const int kWindowWidth = 600; static const int kWindowHeight = 500; +#if defined(OS_WIN) static int count = 1; static const int kTopCheckBoxID = count++; // 1 @@ -72,37 +70,36 @@ static const int kCauliflowerButtonID = count++; static const int kInnerContainerID = count++; static const int kScrollViewID = count++; -static const int kScrollContentViewID = count++; // 20 -static const int kRosettaLinkID = count++; +static const int kRosettaLinkID = count++; // 20 static const int kStupeurEtTremblementLinkID = count++; static const int kDinerGameLinkID = count++; static const int kRidiculeLinkID = count++; -static const int kClosetLinkID = count++; // 25 -static const int kVisitingLinkID = count++; +static const int kClosetLinkID = count++; +static const int kVisitingLinkID = count++; // 25 static const int kAmelieLinkID = count++; static const int kJoyeuxNoelLinkID = count++; static const int kCampingLinkID = count++; -static const int kBriceDeNiceLinkID = count++; // 30 -static const int kTaxiLinkID = count++; +static const int kBriceDeNiceLinkID = count++; +static const int kTaxiLinkID = count++; // 30 static const int kAsterixLinkID = count++; static const int kOKButtonID = count++; static const int kCancelButtonID = count++; -static const int kHelpButtonID = count++; // 35 +static const int kHelpButtonID = count++; -static const int kStyleContainerID = count++; +static const int kStyleContainerID = count++; // 35 static const int kBoldCheckBoxID = count++; static const int kItalicCheckBoxID = count++; static const int kUnderlinedCheckBoxID = count++; -static const int kStyleHelpLinkID = count++; // 40 -static const int kStyleTextEditID = count++; +static const int kStyleHelpLinkID = count++; +static const int kStyleTextEditID = count++; // 40 static const int kSearchContainerID = count++; static const int kSearchTextfieldID = count++; static const int kSearchButtonID = count++; -static const int kHelpLinkID = count++; // 45 +static const int kHelpLinkID = count++; -static const int kThumbnailContainerID = count++; +static const int kThumbnailContainerID = count++; // 45 static const int kThumbnailStarID = count++; static const int kThumbnailSuperStarID = count++; #endif @@ -153,7 +150,8 @@ class FocusManagerTest : public testing::Test, public WindowDelegate { #if defined(OS_WIN) ::SendMessage(native_view, WM_SETFOCUS, NULL, NULL); #else - NOTIMPLEMENTED(); + gtk_widget_grab_focus(native_view); + message_loop()->RunAllPending(); #endif } @@ -177,14 +175,18 @@ class FocusManagerTest : public testing::Test, public WindowDelegate { #if defined(OS_WIN) ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL); #else - NOTIMPLEMENTED(); + gboolean result; + g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()), + "focus_in_event", 0, &result); #endif } void SimulateDeactivateWindow() { #if defined(OS_WIN) ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_INACTIVE, NULL); #else - NOTIMPLEMENTED(); + gboolean result; + g_signal_emit_by_name(G_OBJECT(window_->GetNativeWindow()), + "focus_out_event", 0, & result); #endif } @@ -234,11 +236,16 @@ class BorderView : public NativeViewHost { #if defined(OS_WIN) WidgetWin* widget_win = new WidgetWin(); widget_win->Init(parent->GetRootView()->GetWidget()->GetNativeView(), - gfx::Rect(0, 0, 100, 100)); + gfx::Rect(0, 0, 0, 0)); widget_win->SetFocusTraversableParentView(this); widget_ = widget_win; #else - widget_ = new WidgetGtk(WidgetGtk::TYPE_WINDOW); + WidgetGtk* widget_gtk = new WidgetGtk(WidgetGtk::TYPE_CHILD); + // TODO(jcampan): implement WidgetGtk::SetFocusTraversableParentView() + // widget_gtk->SetFocusTraversableParentView(this); + widget_ = widget_gtk; + widget_->Init(parent->GetRootView()->GetWidget()->GetNativeView(), + gfx::Rect(0, 0, 0, 0)); #endif widget_->SetContentsView(child_); } @@ -266,6 +273,7 @@ class DummyComboboxModel : public ComboboxModel { } }; +#if defined(OS_WIN) class FocusTraversalTest : public FocusManagerTest { public: ~FocusTraversalTest(); @@ -472,7 +480,7 @@ void FocusTraversalTest::InitContentView() { DCHECK(arraysize(kTitles) == arraysize(kIDs)); y = 5; - for (int i = 0; i < arraysize(kTitles); ++i) { + for (size_t i = 0; i < arraysize(kTitles); ++i) { Link* link = new Link(kTitles[i]); link->SetHorizontalAlignment(Label::ALIGN_LEFT); link->SetID(kIDs[i]); @@ -579,6 +587,7 @@ void FocusTraversalTest::InitContentView() { content_view_->AddChildView(contents); contents->SetBounds(250, y, 200, 50); } +#endif //////////////////////////////////////////////////////////////////////////////// // The tests @@ -637,7 +646,7 @@ TEST_F(FocusManagerTest, ViewFocusCallbacks) { content_view_->AddChildView(view2); view1->RequestFocus(); - ASSERT_EQ(2, event_list.size()); + ASSERT_EQ(2, static_cast<int>(event_list.size())); EXPECT_EQ(WILL_GAIN_FOCUS, event_list[0].type); EXPECT_EQ(kView1ID, event_list[0].view_id); EXPECT_EQ(DID_GAIN_FOCUS, event_list[1].type); @@ -645,7 +654,7 @@ TEST_F(FocusManagerTest, ViewFocusCallbacks) { event_list.clear(); view2->RequestFocus(); - ASSERT_EQ(3, event_list.size()); + ASSERT_EQ(3, static_cast<int>(event_list.size())); EXPECT_EQ(WILL_LOSE_FOCUS, event_list[0].type); EXPECT_EQ(kView1ID, event_list[0].view_id); EXPECT_EQ(WILL_GAIN_FOCUS, event_list[1].type); @@ -655,7 +664,7 @@ TEST_F(FocusManagerTest, ViewFocusCallbacks) { event_list.clear(); GetFocusManager()->ClearFocus(); - ASSERT_EQ(1, event_list.size()); + ASSERT_EQ(1, static_cast<int>(event_list.size())); EXPECT_EQ(WILL_LOSE_FOCUS, event_list[0].type); EXPECT_EQ(kView2ID, event_list[0].view_id); } @@ -687,17 +696,17 @@ TEST_F(FocusManagerTest, FocusChangeListener) { AddFocusChangeListener(&listener); view1->RequestFocus(); - ASSERT_EQ(1, listener.focus_changes().size()); + ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(NULL, view1)); listener.ClearFocusChanges(); view2->RequestFocus(); - ASSERT_EQ(1, listener.focus_changes().size()); + ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view1, view2)); listener.ClearFocusChanges(); GetFocusManager()->ClearFocus(); - ASSERT_EQ(1, listener.focus_changes().size()); + ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view2, NULL)); } @@ -729,6 +738,7 @@ class TestRadioButton : public RadioButton { } }; +#if defined(OS_WIN) class TestTextfield : public Textfield { public: TestTextfield() { } @@ -758,25 +768,30 @@ class TestTabbedPane : public TabbedPane { return native_tabbed_pane_->GetTestingHandle(); } }; +#endif // Tests that NativeControls do set the focus View appropriately on the // FocusManager. TEST_F(FocusManagerTest, FocusNativeControls) { TestNativeButton* button = new TestNativeButton(L"Press me"); TestCheckbox* checkbox = new TestCheckbox(L"Checkbox"); +#if defined(OS_WIN) TestRadioButton* radio_button = new TestRadioButton(L"RadioButton"); TestTextfield* textfield = new TestTextfield(); TestCombobox* combobox = new TestCombobox(); TestTabbedPane* tabbed_pane = new TestTabbedPane(); TestNativeButton* tab_button = new TestNativeButton(L"tab button"); +#endif content_view_->AddChildView(button); content_view_->AddChildView(checkbox); +#if defined(OS_WIN) content_view_->AddChildView(radio_button); content_view_->AddChildView(textfield); content_view_->AddChildView(combobox); content_view_->AddChildView(tabbed_pane); tabbed_pane->AddTab(L"Awesome tab", tab_button); +#endif // Simulate the native view getting the native focus (such as by user click). FocusNativeView(button->TestGetNativeControlView()); @@ -785,6 +800,7 @@ TEST_F(FocusManagerTest, FocusNativeControls) { FocusNativeView(checkbox->TestGetNativeControlView()); EXPECT_EQ(checkbox, GetFocusManager()->GetFocusedView()); +#if defined(OS_WIN) FocusNativeView(radio_button->TestGetNativeControlView()); EXPECT_EQ(radio_button, GetFocusManager()->GetFocusedView()); @@ -799,6 +815,7 @@ TEST_F(FocusManagerTest, FocusNativeControls) { FocusNativeView(tab_button->TestGetNativeControlView()); EXPECT_EQ(tab_button, GetFocusManager()->GetFocusedView()); +#endif } // Test that when activating/deactivating the top window, the focus is stored/ @@ -809,17 +826,21 @@ TEST_F(FocusManagerTest, FocusStoreRestore) { view->SetFocusable(true); content_view_->AddChildView(button); + button->SetBounds(10, 10, 200, 30); content_view_->AddChildView(view); + message_loop()->RunAllPending(); TestFocusChangeListener listener; AddFocusChangeListener(&listener); view->RequestFocus(); + message_loop()->RunAllPending(); + // MessageLoopForUI::current()->Run(new AcceleratorHandler()); // Deacivate the window, it should store its focus. SimulateDeactivateWindow(); EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, listener.focus_changes().size()); + ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(NULL, view)); EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(view, NULL)); listener.ClearFocusChanges(); @@ -827,7 +848,7 @@ TEST_F(FocusManagerTest, FocusStoreRestore) { // Reactivate, focus should come-back to the previously focused view. SimulateActivateWindow(); EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(1, listener.focus_changes().size()); + ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(NULL, view)); listener.ClearFocusChanges(); @@ -835,14 +856,14 @@ TEST_F(FocusManagerTest, FocusStoreRestore) { button->RequestFocus(); SimulateDeactivateWindow(); EXPECT_EQ(NULL, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, listener.focus_changes().size()); + ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view, button)); EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(button, NULL)); listener.ClearFocusChanges(); SimulateActivateWindow(); EXPECT_EQ(button, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(1, listener.focus_changes().size()); + ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(NULL, button)); listener.ClearFocusChanges(); @@ -856,12 +877,13 @@ TEST_F(FocusManagerTest, FocusStoreRestore) { ::SendMessage(window_->GetNativeWindow(), WM_ACTIVATE, WA_ACTIVE, NULL); EXPECT_EQ(view, GetFocusManager()->GetFocusedView()); - ASSERT_EQ(2, listener.focus_changes().size()); + ASSERT_EQ(2, static_cast<int>(listener.focus_changes().size())); EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(button, NULL)); EXPECT_TRUE(listener.focus_changes()[1] == ViewPair(NULL, view)); */ } +#if defined(OS_WIN) TEST_F(FocusManagerTest, ContainsView) { View* view = new View(); scoped_ptr<View> detached_view(new View()); @@ -904,7 +926,7 @@ TEST_F(FocusTraversalTest, NormalTraversal) { // loops OK). GetFocusManager()->SetFocusedView(NULL); for (int i = 0; i < 3; ++i) { - for (int j = 0; j < arraysize(kTraversalIDs); j++) { + for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { GetFocusManager()->AdvanceFocus(false); View* focused_view = GetFocusManager()->GetFocusedView(); EXPECT_TRUE(focused_view != NULL); @@ -943,7 +965,7 @@ TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) { kThumbnailSuperStarID }; // Let's disable some views. - for (int i = 0; i < arraysize(kDisabledIDs); i++) { + for (size_t i = 0; i < arraysize(kDisabledIDs); i++) { View* v = FindViewByID(kDisabledIDs[i]); ASSERT_TRUE(v != NULL); if (v) @@ -958,7 +980,7 @@ TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) { // Let's do one traversal (several times, to make sure it loops ok). GetFocusManager()->SetFocusedView(NULL); for (int i = 0; i < 3; ++i) { - for (int j = 0; j < arraysize(kTraversalIDs); j++) { + for (size_t j = 0; j < arraysize(kTraversalIDs); j++) { GetFocusManager()->AdvanceFocus(false); focused_view = GetFocusManager()->GetFocusedView(); EXPECT_TRUE(focused_view != NULL); @@ -979,6 +1001,7 @@ TEST_F(FocusTraversalTest, TraversalWithNonEnabledViews) { } } } +#endif // Counts accelerator calls. class TestAcceleratorTarget : public AcceleratorTarget { diff --git a/views/view_unittest.cc b/views/view_unittest.cc index 64b5848..9d2fa87 100644 --- a/views/view_unittest.cc +++ b/views/view_unittest.cc @@ -1185,3 +1185,49 @@ TEST_F(DefaultButtonTest, DialogDefaultButtonTest) { SimularePressingEnterAndCheckDefaultButton(CANCEL); } #endif + +#if defined(OS_LINUX) +class TestViewWithControls : public View { + public: + TestViewWithControls() { + button_ = new NativeButton(NULL, L"Button"); + checkbox_ = new Checkbox(L"My checkbox"); + text_field_ = new Textfield(); + AddChildView(button_); + button_->SetBounds(0, 0, 100, 30); + AddChildView(checkbox_); + checkbox_->SetBounds(0, 100, 100, 30); + AddChildView(text_field_); + text_field_->SetBounds(0, 200, 100, 30); + text_field_->SetBackgroundColor(SK_ColorYELLOW); + text_field_->SetFont(gfx::Font::CreateFont(L"Arial", 30)); + } + + Button* button_; + Checkbox* checkbox_; + Textfield* text_field_; +}; + +class SimpleWindowDelegate : public WindowDelegate { + public: + SimpleWindowDelegate(View* contents) : contents_(contents) { } + + virtual void DeleteDelegate() { delete this; } + + virtual View* GetContentsView() { return contents_; } + + private: + View* contents_; +}; + +TEST_F(ViewTest, DISABLED_Stupid) { + TestViewWithControls* view_with_controls = new TestViewWithControls(); + views::Window* window = + views::Window::CreateChromeWindow( + NULL, gfx::Rect(200, 200, 500, 500), + new SimpleWindowDelegate(view_with_controls)); + window->Show(); + AcceleratorHandler accelerator_handler; + MessageLoopForUI::current()->Run(&accelerator_handler); +} +#endif diff --git a/views/views.gyp b/views/views.gyp index 4deb5aa..946c9bd 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -292,7 +292,6 @@ 'accessibility/view_accessibility.cc', 'accessibility/view_accessibility_wrapper.cc', 'controls/scrollbar/bitmap_scroll_bar.cc', - 'controls/button/radio_button.cc', 'controls/combo_box.cc', 'controls/hwnd_view.cc', 'controls/message_box_view.cc', @@ -300,9 +299,7 @@ 'controls/table/group_table_view.cc', 'controls/native_control.cc', 'controls/scrollbar/native_scroll_bar.cc', - 'controls/button/radio_button.cc', 'controls/separator.cc', - 'controls/tabbed_pane.cc', 'controls/table/table_model.cc', 'controls/table/table_view.cc', 'controls/table/group_table_view.cc', diff --git a/views/widget/root_view.cc b/views/widget/root_view.cc index a0d19ca..4469051 100644 --- a/views/widget/root_view.cc +++ b/views/widget/root_view.cc @@ -510,19 +510,12 @@ void RootView::ProcessMouseDragCanceled() { void RootView::FocusView(View* view) { if (view != GetFocusedView()) { -#if defined(OS_WIN) FocusManager* focus_manager = GetFocusManager(); DCHECK(focus_manager) << "No Focus Manager for Window " << (GetWidget() ? GetWidget()->GetNativeView() : 0); if (!focus_manager) return; - - View* prev_focused_view = focus_manager->GetFocusedView(); focus_manager->SetFocusedView(view); -#else - // TODO(port): Port the focus manager and this goes away. - NOTIMPLEMENTED(); -#endif } } diff --git a/views/widget/widget_gtk.cc b/views/widget/widget_gtk.cc index 7ab2c31..49720f3 100644 --- a/views/widget/widget_gtk.cc +++ b/views/widget/widget_gtk.cc @@ -570,6 +570,24 @@ gboolean WidgetGtk::OnButtonRelease(GtkWidget* widget, GdkEventButton* event) { return true; } +gboolean WidgetGtk::OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { + if (type_ == TYPE_CHILD) + return false; + + // The top-level window got focus, restore the last focused view. + focus_manager_->RestoreFocusedView(); + return false; +} + +gboolean WidgetGtk::OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { + if (type_ == TYPE_CHILD) + return false; + + // The top-level window lost focus, store the focused view. + focus_manager_->StoreFocusedView(); + return false; +} + void WidgetGtk::OnPaint(GtkWidget* widget, GdkEventExpose* event) { root_view_->OnPaint(event); } diff --git a/views/widget/widget_gtk.h b/views/widget/widget_gtk.h index a7e905e..7a3738a 100644 --- a/views/widget/widget_gtk.h +++ b/views/widget/widget_gtk.h @@ -110,6 +110,9 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer { virtual void WillProcessEvent(GdkEvent* event); virtual void DidProcessEvent(GdkEvent* event); + // Retrieves the WidgetGtk associated with |widget|. + static WidgetGtk* GetViewForNative(GtkWidget* widget); + // Retrieves the WindowGtk associated with |widget|. static WindowGtk* GetWindowForNative(GtkWidget* widget); @@ -148,12 +151,8 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer { virtual gboolean OnMotionNotify(GtkWidget* widget, GdkEventMotion* event); virtual gboolean OnButtonPress(GtkWidget* widget, GdkEventButton* event); virtual gboolean OnButtonRelease(GtkWidget* widget, GdkEventButton* event); - virtual gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event) { - return false; - } - virtual gboolean OnFocusOut(GtkWidget* widget, GdkEventFocus* event) { - return false; - } + virtual gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event); + virtual gboolean OnFocusOut(GtkWidget* widget, GdkEventFocus* event); virtual gboolean OnKeyPress(GtkWidget* widget, GdkEventKey* event); virtual gboolean OnKeyRelease(GtkWidget* widget, GdkEventKey* event); virtual gboolean OnScroll(GtkWidget* widget, GdkEventScroll* event) { @@ -200,8 +199,7 @@ class WidgetGtk : public Widget, public MessageLoopForUI::Observer { bool ProcessMousePressed(GdkEventButton* event); void ProcessMouseReleased(GdkEventButton* event); - // Sets and retrieves the WidgetGtk in the userdata section of the widget. - static WidgetGtk* GetViewForNative(GtkWidget* widget); + // Sets the WidgetGtk in the userdata section of the widget. static void SetViewForNative(GtkWidget* widget, WidgetGtk* view); static RootView* GetRootViewForWidget(GtkWidget* widget); |