Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / views / widget / root_view_unittest.cc
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/views/widget/root_view.h"
6
7 #include "ui/events/event_targeter.h"
8 #include "ui/views/context_menu_controller.h"
9 #include "ui/views/test/views_test_base.h"
10 #include "ui/views/view_targeter.h"
11 #include "ui/views/widget/root_view.h"
12
13 namespace views {
14 namespace test {
15
16 typedef ViewsTestBase RootViewTest;
17
18 class DeleteOnKeyEventView : public View {
19  public:
20   explicit DeleteOnKeyEventView(bool* set_on_key) : set_on_key_(set_on_key) {}
21   virtual ~DeleteOnKeyEventView() {}
22
23   virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE {
24     *set_on_key_ = true;
25     delete this;
26     return true;
27   }
28
29  private:
30   // Set to true in OnKeyPressed().
31   bool* set_on_key_;
32
33   DISALLOW_COPY_AND_ASSIGN(DeleteOnKeyEventView);
34 };
35
36 // Verifies deleting a View in OnKeyPressed() doesn't crash and that the
37 // target is marked as destroyed in the returned EventDispatchDetails.
38 TEST_F(RootViewTest, DeleteViewDuringKeyEventDispatch) {
39   Widget widget;
40   Widget::InitParams init_params =
41       CreateParams(Widget::InitParams::TYPE_POPUP);
42   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
43   widget.Init(init_params);
44
45   bool got_key_event = false;
46
47   View* content = new View;
48   widget.SetContentsView(content);
49
50   View* child = new DeleteOnKeyEventView(&got_key_event);
51   content->AddChildView(child);
52
53   // Give focus to |child| so that it will be the target of the key event.
54   child->SetFocusable(true);
55   child->RequestFocus();
56
57   ui::EventTargeter* targeter = new ViewTargeter();
58   internal::RootView* root_view =
59       static_cast<internal::RootView*>(widget.GetRootView());
60   root_view->SetEventTargeter(make_scoped_ptr(targeter));
61
62   ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_ESCAPE, 0, false);
63   ui::EventDispatchDetails details = root_view->OnEventFromSource(&key_event);
64   EXPECT_TRUE(details.target_destroyed);
65   EXPECT_FALSE(details.dispatcher_destroyed);
66   EXPECT_TRUE(got_key_event);
67 }
68
69 // Used to determine whether or not a context menu is shown as a result of
70 // a keypress.
71 class TestContextMenuController : public ContextMenuController {
72  public:
73   TestContextMenuController()
74       : show_context_menu_calls_(0),
75         menu_source_view_(NULL),
76         menu_source_type_(ui::MENU_SOURCE_NONE) {
77   }
78   virtual ~TestContextMenuController() {}
79
80   int show_context_menu_calls() const { return show_context_menu_calls_; }
81   View* menu_source_view() const { return menu_source_view_; }
82   ui::MenuSourceType menu_source_type() const { return menu_source_type_; }
83
84   void Reset() {
85     show_context_menu_calls_ = 0;
86     menu_source_view_ = NULL;
87     menu_source_type_ = ui::MENU_SOURCE_NONE;
88   }
89
90   // ContextMenuController:
91   virtual void ShowContextMenuForView(
92       View* source,
93       const gfx::Point& point,
94       ui::MenuSourceType source_type) OVERRIDE {
95     show_context_menu_calls_++;
96     menu_source_view_ = source;
97     menu_source_type_ = source_type;
98   }
99
100  private:
101   int show_context_menu_calls_;
102   View* menu_source_view_;
103   ui::MenuSourceType menu_source_type_;
104
105   DISALLOW_COPY_AND_ASSIGN(TestContextMenuController);
106 };
107
108 // Tests that context menus are shown for certain key events (Shift+F10
109 // and VKEY_APPS) by the pre-target handler installed on RootView.
110 TEST_F(RootViewTest, ContextMenuFromKeyEvent) {
111   Widget widget;
112   Widget::InitParams init_params =
113       CreateParams(Widget::InitParams::TYPE_POPUP);
114   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
115   widget.Init(init_params);
116   internal::RootView* root_view =
117       static_cast<internal::RootView*>(widget.GetRootView());
118
119   TestContextMenuController controller;
120   View* focused_view = new View;
121   focused_view->set_context_menu_controller(&controller);
122   widget.SetContentsView(focused_view);
123   focused_view->SetFocusable(true);
124   focused_view->RequestFocus();
125
126   // No context menu should be shown for a keypress of 'A'.
127   ui::KeyEvent nomenu_key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, 0, true);
128   ui::EventDispatchDetails details =
129       root_view->OnEventFromSource(&nomenu_key_event);
130   EXPECT_FALSE(details.target_destroyed);
131   EXPECT_FALSE(details.dispatcher_destroyed);
132   EXPECT_EQ(0, controller.show_context_menu_calls());
133   EXPECT_EQ(NULL, controller.menu_source_view());
134   EXPECT_EQ(ui::MENU_SOURCE_NONE, controller.menu_source_type());
135   controller.Reset();
136
137   // A context menu should be shown for a keypress of Shift+F10.
138   ui::KeyEvent menu_key_event(
139       ui::ET_KEY_PRESSED, ui::VKEY_F10, ui::EF_SHIFT_DOWN, false);
140   details = root_view->OnEventFromSource(&menu_key_event);
141   EXPECT_FALSE(details.target_destroyed);
142   EXPECT_FALSE(details.dispatcher_destroyed);
143   EXPECT_EQ(1, controller.show_context_menu_calls());
144   EXPECT_EQ(focused_view, controller.menu_source_view());
145   EXPECT_EQ(ui::MENU_SOURCE_KEYBOARD, controller.menu_source_type());
146   controller.Reset();
147
148   // A context menu should be shown for a keypress of VKEY_APPS.
149   ui::KeyEvent menu_key_event2(ui::ET_KEY_PRESSED, ui::VKEY_APPS, 0, false);
150   details = root_view->OnEventFromSource(&menu_key_event2);
151   EXPECT_FALSE(details.target_destroyed);
152   EXPECT_FALSE(details.dispatcher_destroyed);
153   EXPECT_EQ(1, controller.show_context_menu_calls());
154   EXPECT_EQ(focused_view, controller.menu_source_view());
155   EXPECT_EQ(ui::MENU_SOURCE_KEYBOARD, controller.menu_source_type());
156   controller.Reset();
157 }
158
159 }  // namespace test
160 }  // namespace views