focus_manager_unittest.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <utility>
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/utf_string_conversions.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/accelerators/accelerator.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/keycodes/keyboard_codes.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/button/text_button.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/textfield/textfield.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/focus/accelerator_handler.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/focus/focus_manager_factory.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/views/focus/focus_manager_test.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/focus/widget_focus_manager.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/widget/widget.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/client/focus_client.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace views {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FocusNativeView(gfx::NativeView view) {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  aura::client::GetFocusClient(view)->FocusWindow(view);
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_WIN)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetFocus(view);
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#error
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)enum FocusTestEventType {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ON_FOCUS = 0,
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ON_BLUR
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)struct FocusTestEvent {
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FocusTestEvent(FocusTestEventType type, int view_id)
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : type(type),
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        view_id(view_id) {
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  FocusTestEventType type;
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int view_id;
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class SimpleTestView : public View {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SimpleTestView(std::vector<FocusTestEvent>* event_list, int view_id)
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : event_list_(event_list) {
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    set_focusable(true);
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    set_id(view_id);
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnFocus() OVERRIDE {
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event_list_->push_back(FocusTestEvent(ON_FOCUS, id()));
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnBlur() OVERRIDE {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    event_list_->push_back(FocusTestEvent(ON_BLUR, id()));
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<FocusTestEvent>* event_list_;
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests that the appropriate Focus related methods are called when a View
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// gets/loses focus.
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(FocusManagerTest, ViewFocusCallbacks) {
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<FocusTestEvent> event_list;
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kView1ID = 1;
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kView2ID = 2;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  SimpleTestView* view1 = new SimpleTestView(&event_list, kView1ID);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SimpleTestView* view2 = new SimpleTestView(&event_list, kView2ID);
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetContentsView()->AddChildView(view1);
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetContentsView()->AddChildView(view2);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  view1->RequestFocus();
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1, static_cast<int>(event_list.size()));
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ON_FOCUS, event_list[0].type);
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kView1ID, event_list[0].view_id);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  event_list.clear();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  view2->RequestFocus();
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(2, static_cast<int>(event_list.size()));
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ON_BLUR, event_list[0].type);
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kView1ID, event_list[0].view_id);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ON_FOCUS, event_list[1].type);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(kView2ID, event_list[1].view_id);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_list.clear();
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetFocusManager()->ClearFocus();
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1, static_cast<int>(event_list.size()));
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(ON_BLUR, event_list[0].type);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kView2ID, event_list[0].view_id);
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(FocusManagerTest, FocusChangeListener) {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  View* view1 = new View();
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  view1->set_focusable(true);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  View* view2 = new View();
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  view2->set_focusable(true);
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetContentsView()->AddChildView(view1);
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetContentsView()->AddChildView(view2);
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  TestFocusChangeListener listener;
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  AddFocusChangeListener(&listener);
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::View* null_view = NULL;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  view1->RequestFocus();
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(null_view, view1));
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listener.ClearFocusChanges();
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  view2->RequestFocus();
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view1, view2));
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  listener.ClearFocusChanges();
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetFocusManager()->ClearFocus();
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(1, static_cast<int>(listener.focus_changes().size()));
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(listener.focus_changes()[0] == ViewPair(view2, null_view));
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(FocusManagerTest, WidgetFocusChangeListener) {
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestWidgetFocusChangeListener widget_listener;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddWidgetFocusChangeListener(&widget_listener);
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.bounds = gfx::Rect(10, 10, 100, 100);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  params.parent = GetWidget()->GetNativeView();
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Widget> widget1(new Widget);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  widget1->Init(params);
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  widget1->Show();
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<Widget> widget2(new Widget);
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  widget2->Init(params);
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  widget2->Show();
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  widget_listener.ClearFocusChanges();
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::NativeView native_view1 = widget1->GetNativeView();
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FocusNativeView(native_view1);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size()));
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(native_view1, widget_listener.focus_changes()[0].second);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(native_view1, widget_listener.focus_changes()[1].second);
155
156  widget_listener.ClearFocusChanges();
157  gfx::NativeView native_view2 = widget2->GetNativeView();
158  FocusNativeView(native_view2);
159  ASSERT_EQ(2, static_cast<int>(widget_listener.focus_changes().size()));
160  EXPECT_EQ(NativeViewPair(native_view1, native_view2),
161            widget_listener.focus_changes()[0]);
162  EXPECT_EQ(NativeViewPair(native_view1, native_view2),
163            widget_listener.focus_changes()[1]);
164}
165
166#if !defined(USE_AURA)
167class TestTextfield : public Textfield {
168 public:
169  TestTextfield() {}
170  virtual gfx::NativeView TestGetNativeControlView() {
171    return native_wrapper_->GetTestingHandle();
172  }
173};
174
175// Tests that NativeControls do set the focused View appropriately on the
176// FocusManager.
177TEST_F(FocusManagerTest, DISABLED_FocusNativeControls) {
178  TestTextfield* textfield = new TestTextfield();
179  GetContentsView()->AddChildView(textfield);
180  // Simulate the native view getting the native focus (such as by user click).
181  FocusNativeView(textfield->TestGetNativeControlView());
182  EXPECT_EQ(textfield, GetFocusManager()->GetFocusedView());
183}
184#endif
185
186// Counts accelerator calls.
187class TestAcceleratorTarget : public ui::AcceleratorTarget {
188 public:
189  explicit TestAcceleratorTarget(bool process_accelerator)
190      : accelerator_count_(0),
191        process_accelerator_(process_accelerator),
192        can_handle_accelerators_(true) {}
193
194  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
195    ++accelerator_count_;
196    return process_accelerator_;
197  }
198
199  virtual bool CanHandleAccelerators() const OVERRIDE {
200    return can_handle_accelerators_;
201  }
202
203  int accelerator_count() const { return accelerator_count_; }
204
205  void set_can_handle_accelerators(bool can_handle_accelerators) {
206    can_handle_accelerators_ = can_handle_accelerators;
207  }
208
209 private:
210  int accelerator_count_;  // number of times that the accelerator is activated
211  bool process_accelerator_;  // return value of AcceleratorPressed
212  bool can_handle_accelerators_;  // return value of CanHandleAccelerators
213
214  DISALLOW_COPY_AND_ASSIGN(TestAcceleratorTarget);
215};
216
217TEST_F(FocusManagerTest, CallsNormalAcceleratorTarget) {
218  FocusManager* focus_manager = GetFocusManager();
219  ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
220  ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, ui::EF_NONE);
221
222  TestAcceleratorTarget return_target(true);
223  TestAcceleratorTarget escape_target(true);
224  EXPECT_EQ(return_target.accelerator_count(), 0);
225  EXPECT_EQ(escape_target.accelerator_count(), 0);
226  EXPECT_EQ(NULL,
227            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
228  EXPECT_EQ(NULL,
229            focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
230
231  // Register targets.
232  focus_manager->RegisterAccelerator(return_accelerator,
233                                     ui::AcceleratorManager::kNormalPriority,
234                                     &return_target);
235  focus_manager->RegisterAccelerator(escape_accelerator,
236                                     ui::AcceleratorManager::kNormalPriority,
237                                     &escape_target);
238
239  // Checks if the correct target is registered.
240  EXPECT_EQ(&return_target,
241            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
242  EXPECT_EQ(&escape_target,
243            focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
244
245  // Hitting the return key.
246  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
247  EXPECT_EQ(return_target.accelerator_count(), 1);
248  EXPECT_EQ(escape_target.accelerator_count(), 0);
249
250  // Hitting the escape key.
251  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
252  EXPECT_EQ(return_target.accelerator_count(), 1);
253  EXPECT_EQ(escape_target.accelerator_count(), 1);
254
255  // Register another target for the return key.
256  TestAcceleratorTarget return_target2(true);
257  EXPECT_EQ(return_target2.accelerator_count(), 0);
258  focus_manager->RegisterAccelerator(return_accelerator,
259                                     ui::AcceleratorManager::kNormalPriority,
260                                     &return_target2);
261  EXPECT_EQ(&return_target2,
262            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
263
264  // Hitting the return key; return_target2 has the priority.
265  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
266  EXPECT_EQ(return_target.accelerator_count(), 1);
267  EXPECT_EQ(return_target2.accelerator_count(), 1);
268
269  // Register a target that does not process the accelerator event.
270  TestAcceleratorTarget return_target3(false);
271  EXPECT_EQ(return_target3.accelerator_count(), 0);
272  focus_manager->RegisterAccelerator(return_accelerator,
273                                     ui::AcceleratorManager::kNormalPriority,
274                                     &return_target3);
275  EXPECT_EQ(&return_target3,
276            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
277
278  // Hitting the return key.
279  // Since the event handler of return_target3 returns false, return_target2
280  // should be called too.
281  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
282  EXPECT_EQ(return_target.accelerator_count(), 1);
283  EXPECT_EQ(return_target2.accelerator_count(), 2);
284  EXPECT_EQ(return_target3.accelerator_count(), 1);
285
286  // Unregister return_target2.
287  focus_manager->UnregisterAccelerator(return_accelerator, &return_target2);
288  EXPECT_EQ(&return_target3,
289            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
290
291  // Hitting the return key. return_target3 and return_target should be called.
292  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
293  EXPECT_EQ(return_target.accelerator_count(), 2);
294  EXPECT_EQ(return_target2.accelerator_count(), 2);
295  EXPECT_EQ(return_target3.accelerator_count(), 2);
296
297  // Unregister targets.
298  focus_manager->UnregisterAccelerator(return_accelerator, &return_target);
299  focus_manager->UnregisterAccelerator(return_accelerator, &return_target3);
300  focus_manager->UnregisterAccelerator(escape_accelerator, &escape_target);
301
302  // Now there is no target registered.
303  EXPECT_EQ(NULL,
304            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
305  EXPECT_EQ(NULL,
306            focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
307
308  // Hitting the return key and the escape key. Nothing should happen.
309  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
310  EXPECT_EQ(return_target.accelerator_count(), 2);
311  EXPECT_EQ(return_target2.accelerator_count(), 2);
312  EXPECT_EQ(return_target3.accelerator_count(), 2);
313  EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator));
314  EXPECT_EQ(escape_target.accelerator_count(), 1);
315}
316
317TEST_F(FocusManagerTest, HighPriorityHandlers) {
318  FocusManager* focus_manager = GetFocusManager();
319  ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, ui::EF_NONE);
320
321  TestAcceleratorTarget escape_target_high(true);
322  TestAcceleratorTarget escape_target_normal(true);
323  EXPECT_EQ(escape_target_high.accelerator_count(), 0);
324  EXPECT_EQ(escape_target_normal.accelerator_count(), 0);
325  EXPECT_EQ(NULL,
326      focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
327  EXPECT_FALSE(focus_manager->HasPriorityHandler(escape_accelerator));
328
329  // Register high priority target.
330  focus_manager->RegisterAccelerator(escape_accelerator,
331                                     ui::AcceleratorManager::kHighPriority,
332                                     &escape_target_high);
333  EXPECT_EQ(&escape_target_high,
334     focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
335  EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator));
336
337  // Hit the escape key.
338  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
339  EXPECT_EQ(escape_target_high.accelerator_count(), 1);
340  EXPECT_EQ(escape_target_normal.accelerator_count(), 0);
341
342  // Add a normal priority target and make sure it doesn't see the key.
343  focus_manager->RegisterAccelerator(escape_accelerator,
344                                     ui::AcceleratorManager::kNormalPriority,
345                                     &escape_target_normal);
346
347  // Checks if the correct target is registered (same as before, the high
348  // priority one).
349  EXPECT_EQ(&escape_target_high,
350      focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
351  EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator));
352
353  // Hit the escape key.
354  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
355  EXPECT_EQ(escape_target_high.accelerator_count(), 2);
356  EXPECT_EQ(escape_target_normal.accelerator_count(), 0);
357
358  // Unregister the high priority accelerator.
359  focus_manager->UnregisterAccelerator(escape_accelerator, &escape_target_high);
360  EXPECT_EQ(&escape_target_normal,
361      focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
362  EXPECT_FALSE(focus_manager->HasPriorityHandler(escape_accelerator));
363
364  // Hit the escape key.
365  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
366  EXPECT_EQ(escape_target_high.accelerator_count(), 2);
367  EXPECT_EQ(escape_target_normal.accelerator_count(), 1);
368
369  // Add the high priority target back and make sure it starts seeing the key.
370  focus_manager->RegisterAccelerator(escape_accelerator,
371                                     ui::AcceleratorManager::kHighPriority,
372                                     &escape_target_high);
373  EXPECT_EQ(&escape_target_high,
374      focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
375  EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator));
376
377  // Hit the escape key.
378  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
379  EXPECT_EQ(escape_target_high.accelerator_count(), 3);
380  EXPECT_EQ(escape_target_normal.accelerator_count(), 1);
381
382  // Unregister the normal priority accelerator.
383  focus_manager->UnregisterAccelerator(
384      escape_accelerator, &escape_target_normal);
385  EXPECT_EQ(&escape_target_high,
386      focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
387  EXPECT_TRUE(focus_manager->HasPriorityHandler(escape_accelerator));
388
389  // Hit the escape key.
390  EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator));
391  EXPECT_EQ(escape_target_high.accelerator_count(), 4);
392  EXPECT_EQ(escape_target_normal.accelerator_count(), 1);
393
394  // Unregister the high priority accelerator.
395  focus_manager->UnregisterAccelerator(escape_accelerator, &escape_target_high);
396  EXPECT_EQ(NULL,
397      focus_manager->GetCurrentTargetForAccelerator(escape_accelerator));
398  EXPECT_FALSE(focus_manager->HasPriorityHandler(escape_accelerator));
399
400  // Hit the escape key (no change, no targets registered).
401  EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator));
402  EXPECT_EQ(escape_target_high.accelerator_count(), 4);
403  EXPECT_EQ(escape_target_normal.accelerator_count(), 1);
404}
405
406TEST_F(FocusManagerTest, CallsEnabledAcceleratorTargetsOnly) {
407  FocusManager* focus_manager = GetFocusManager();
408  ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
409
410  TestAcceleratorTarget return_target1(true);
411  TestAcceleratorTarget return_target2(true);
412
413  focus_manager->RegisterAccelerator(return_accelerator,
414                                     ui::AcceleratorManager::kNormalPriority,
415                                     &return_target1);
416  focus_manager->RegisterAccelerator(return_accelerator,
417                                     ui::AcceleratorManager::kNormalPriority,
418                                     &return_target2);
419  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
420  EXPECT_EQ(0, return_target1.accelerator_count());
421  EXPECT_EQ(1, return_target2.accelerator_count());
422
423  // If CanHandleAccelerators() return false, FocusManager shouldn't call
424  // AcceleratorPressed().
425  return_target2.set_can_handle_accelerators(false);
426  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
427  EXPECT_EQ(1, return_target1.accelerator_count());
428  EXPECT_EQ(1, return_target2.accelerator_count());
429
430  // If no accelerator targets are enabled, ProcessAccelerator() should fail.
431  return_target1.set_can_handle_accelerators(false);
432  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
433  EXPECT_EQ(1, return_target1.accelerator_count());
434  EXPECT_EQ(1, return_target2.accelerator_count());
435
436  // Enabling the target again causes the accelerators to be processed again.
437  return_target1.set_can_handle_accelerators(true);
438  return_target2.set_can_handle_accelerators(true);
439  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
440  EXPECT_EQ(1, return_target1.accelerator_count());
441  EXPECT_EQ(2, return_target2.accelerator_count());
442}
443
444// Unregisters itself when its accelerator is invoked.
445class SelfUnregisteringAcceleratorTarget : public ui::AcceleratorTarget {
446 public:
447  SelfUnregisteringAcceleratorTarget(ui::Accelerator accelerator,
448                                     FocusManager* focus_manager)
449      : accelerator_(accelerator),
450        focus_manager_(focus_manager),
451        accelerator_count_(0) {
452  }
453
454  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE {
455    ++accelerator_count_;
456    focus_manager_->UnregisterAccelerator(accelerator, this);
457    return true;
458  }
459
460  virtual bool CanHandleAccelerators() const OVERRIDE {
461    return true;
462  }
463
464  int accelerator_count() const { return accelerator_count_; }
465
466 private:
467  ui::Accelerator accelerator_;
468  FocusManager* focus_manager_;
469  int accelerator_count_;
470
471  DISALLOW_COPY_AND_ASSIGN(SelfUnregisteringAcceleratorTarget);
472};
473
474TEST_F(FocusManagerTest, CallsSelfDeletingAcceleratorTarget) {
475  FocusManager* focus_manager = GetFocusManager();
476  ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE);
477  SelfUnregisteringAcceleratorTarget target(return_accelerator, focus_manager);
478  EXPECT_EQ(target.accelerator_count(), 0);
479  EXPECT_EQ(NULL,
480            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
481
482  // Register the target.
483  focus_manager->RegisterAccelerator(return_accelerator,
484                                     ui::AcceleratorManager::kNormalPriority,
485                                     &target);
486  EXPECT_EQ(&target,
487            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
488
489  // Hitting the return key. The target will be unregistered.
490  EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator));
491  EXPECT_EQ(target.accelerator_count(), 1);
492  EXPECT_EQ(NULL,
493            focus_manager->GetCurrentTargetForAccelerator(return_accelerator));
494
495  // Hitting the return key again; nothing should happen.
496  EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator));
497  EXPECT_EQ(target.accelerator_count(), 1);
498}
499
500class FocusManagerDtorTest : public FocusManagerTest {
501 protected:
502  typedef std::vector<std::string> DtorTrackVector;
503
504  class FocusManagerDtorTracked : public FocusManager {
505   public:
506    FocusManagerDtorTracked(Widget* widget, DtorTrackVector* dtor_tracker)
507      : FocusManager(widget, NULL /* delegate */),
508        dtor_tracker_(dtor_tracker) {
509    }
510
511    virtual ~FocusManagerDtorTracked() {
512      dtor_tracker_->push_back("FocusManagerDtorTracked");
513    }
514
515    DtorTrackVector* dtor_tracker_;
516
517   private:
518    DISALLOW_COPY_AND_ASSIGN(FocusManagerDtorTracked);
519  };
520
521  class TestFocusManagerFactory : public FocusManagerFactory {
522   public:
523    explicit TestFocusManagerFactory(DtorTrackVector* dtor_tracker)
524        : dtor_tracker_(dtor_tracker) {
525    }
526
527    virtual FocusManager* CreateFocusManager(Widget* widget) OVERRIDE {
528      return new FocusManagerDtorTracked(widget, dtor_tracker_);
529    }
530
531   private:
532    DtorTrackVector* dtor_tracker_;
533    DISALLOW_COPY_AND_ASSIGN(TestFocusManagerFactory);
534  };
535
536  class NativeButtonDtorTracked : public NativeTextButton {
537   public:
538    NativeButtonDtorTracked(const string16& text,
539                            DtorTrackVector* dtor_tracker)
540        : NativeTextButton(NULL, text),
541          dtor_tracker_(dtor_tracker) {
542    };
543    virtual ~NativeButtonDtorTracked() {
544      dtor_tracker_->push_back("NativeButtonDtorTracked");
545    }
546
547    DtorTrackVector* dtor_tracker_;
548  };
549
550  class WindowDtorTracked : public Widget {
551   public:
552    explicit WindowDtorTracked(DtorTrackVector* dtor_tracker)
553        : dtor_tracker_(dtor_tracker) {
554    }
555
556    virtual ~WindowDtorTracked() {
557      dtor_tracker_->push_back("WindowDtorTracked");
558    }
559
560    DtorTrackVector* dtor_tracker_;
561  };
562
563  virtual void SetUp() {
564    ViewsTestBase::SetUp();
565    FocusManagerFactory::Install(new TestFocusManagerFactory(&dtor_tracker_));
566    // Create WindowDtorTracked that uses FocusManagerDtorTracked.
567    Widget* widget = new WindowDtorTracked(&dtor_tracker_);
568    Widget::InitParams params;
569    params.delegate = this;
570    params.bounds = gfx::Rect(0, 0, 100, 100);
571    widget->Init(params);
572
573    tracked_focus_manager_ =
574        static_cast<FocusManagerDtorTracked*>(GetFocusManager());
575    widget->Show();
576  }
577
578  virtual void TearDown() {
579    FocusManagerFactory::Install(NULL);
580    ViewsTestBase::TearDown();
581  }
582
583  FocusManager* tracked_focus_manager_;
584  DtorTrackVector dtor_tracker_;
585};
586
587#if !defined(USE_AURA)
588TEST_F(FocusManagerDtorTest, FocusManagerDestructedLast) {
589  // Setup views hierarchy.
590  GetContentsView()->AddChildView(new TestTextfield());
591  GetContentsView()->AddChildView(new NativeButtonDtorTracked(
592      ASCIIToUTF16("button"), &dtor_tracker_));
593
594  // Close the window.
595  GetWidget()->Close();
596  RunPendingMessages();
597
598  // Test window, button and focus manager should all be destructed.
599  ASSERT_EQ(3, static_cast<int>(dtor_tracker_.size()));
600
601  // Focus manager should be the last one to destruct.
602  ASSERT_STREQ("FocusManagerDtorTracked", dtor_tracker_[2].c_str());
603}
604#endif
605
606namespace {
607
608class FocusInAboutToRequestFocusFromTabTraversalView : public View {
609 public:
610  FocusInAboutToRequestFocusFromTabTraversalView() : view_to_focus_(NULL) {}
611
612  void set_view_to_focus(View* view) { view_to_focus_ = view; }
613
614  virtual void AboutToRequestFocusFromTabTraversal(bool reverse) OVERRIDE {
615    view_to_focus_->RequestFocus();
616  }
617
618 private:
619  views::View* view_to_focus_;
620
621  DISALLOW_COPY_AND_ASSIGN(FocusInAboutToRequestFocusFromTabTraversalView);
622};
623}  // namespace
624
625// Verifies a focus change done during a call to
626// AboutToRequestFocusFromTabTraversal() is honored.
627TEST_F(FocusManagerTest, FocusInAboutToRequestFocusFromTabTraversal) {
628  // Create 3 views focuses the 3 and advances to the second. The 2nd views
629  // implementation of AboutToRequestFocusFromTabTraversal() focuses the first.
630  views::View* v1 = new View;
631  v1->set_focusable(true);
632  GetContentsView()->AddChildView(v1);
633
634  FocusInAboutToRequestFocusFromTabTraversalView* v2 =
635      new FocusInAboutToRequestFocusFromTabTraversalView;
636  v2->set_focusable(true);
637  v2->set_view_to_focus(v1);
638  GetContentsView()->AddChildView(v2);
639
640  views::View* v3 = new View;
641  v3->set_focusable(true);
642  GetContentsView()->AddChildView(v3);
643
644  v3->RequestFocus();
645  GetWidget()->GetFocusManager()->AdvanceFocus(true);
646  EXPECT_TRUE(v1->HasFocus());
647}
648
649}  // namespace views
650