OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ui/views/controls/menu/menu_runner_impl_cocoa.h" | 5 #import "ui/views/controls/menu/menu_runner_impl_cocoa.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 | 8 |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
11 #import "testing/gtest_mac.h" | 11 #import "testing/gtest_mac.h" |
12 #include "ui/base/models/simple_menu_model.h" | 12 #include "ui/base/models/simple_menu_model.h" |
13 #include "ui/events/event_utils.h" | 13 #include "ui/events/event_utils.h" |
14 #include "ui/views/test/views_test_base.h" | 14 #include "ui/views/test/views_test_base.h" |
15 | 15 |
16 namespace views { | 16 namespace views { |
17 namespace test { | 17 namespace test { |
18 namespace { | 18 namespace { |
19 | 19 |
20 void MenuCancelCallback(internal::MenuRunnerImplCocoa* runner) { | |
tapted
2016/04/06 06:38:37
I think these all would be better as member functi
karandeepb
2016/04/06 10:25:16
Done.
| |
21 runner->Cancel(); | |
22 EXPECT_FALSE(runner->IsRunning()); | |
23 } | |
24 | |
25 void MenuDeleteCallback(internal::MenuRunnerImplCocoa** runner) { | |
26 (*runner)->Release(); | |
27 *runner = nullptr; | |
28 } | |
29 | |
30 void RunMenuWrapperCallback(const base::Closure& callback, | |
31 internal::MenuRunnerImplCocoa* runner) { | |
32 EXPECT_TRUE(runner->IsRunning()); | |
33 callback.Run(); | |
34 } | |
35 | |
36 void RunMenuAtCallback(views::Widget* parent, | |
37 internal::MenuRunnerImplCocoa* runner, | |
38 NSRect* last_anchor_frame) { | |
39 NSArray* subviews = [parent->GetNativeView() subviews]; | |
40 EXPECT_EQ(2u, [subviews count]); | |
41 *last_anchor_frame = [[subviews objectAtIndex:1] frame]; | |
42 runner->Cancel(); | |
43 } | |
44 | |
20 class TestModel : public ui::SimpleMenuModel { | 45 class TestModel : public ui::SimpleMenuModel { |
21 public: | 46 public: |
22 TestModel() : ui::SimpleMenuModel(&delegate_), delegate_(this) {} | 47 TestModel() : ui::SimpleMenuModel(&delegate_), delegate_(this) {} |
23 | 48 |
24 void set_checked_command(int command) { checked_command_ = command; } | 49 void set_checked_command(int command) { checked_command_ = command; } |
25 | 50 |
51 void set_menu_open_callback(const base::Closure& callback) { | |
52 menu_open_callback_ = callback; | |
53 } | |
54 | |
26 private: | 55 private: |
27 class Delegate : public ui::SimpleMenuModel::Delegate { | 56 class Delegate : public ui::SimpleMenuModel::Delegate { |
28 public: | 57 public: |
29 explicit Delegate(TestModel* model) : model_(model) {} | 58 explicit Delegate(TestModel* model) : model_(model) {} |
30 bool IsCommandIdChecked(int command_id) const override { | 59 bool IsCommandIdChecked(int command_id) const override { |
31 return command_id == model_->checked_command_; | 60 return command_id == model_->checked_command_; |
32 } | 61 } |
33 bool IsCommandIdEnabled(int command_id) const override { return true; } | 62 bool IsCommandIdEnabled(int command_id) const override { return true; } |
34 bool GetAcceleratorForCommandId(int command_id, | 63 bool GetAcceleratorForCommandId(int command_id, |
35 ui::Accelerator* accelerator) override { | 64 ui::Accelerator* accelerator) override { |
36 return false; | 65 return false; |
37 } | 66 } |
38 void ExecuteCommand(int command_id, int event_flags) override {} | 67 void ExecuteCommand(int command_id, int event_flags) override {} |
39 | 68 |
69 void MenuWillShow(SimpleMenuModel* source) override { | |
70 if (model_->menu_open_callback_.is_null()) | |
tapted
2016/04/06 06:38:37
nit:
if (!model_->menu_open_callback_.is_null(
karandeepb
2016/04/06 10:25:15
Done.
| |
71 return; | |
72 model_->menu_open_callback_.Run(); | |
73 } | |
74 | |
40 private: | 75 private: |
41 TestModel* model_; | 76 TestModel* model_; |
42 | 77 |
43 DISALLOW_COPY_AND_ASSIGN(Delegate); | 78 DISALLOW_COPY_AND_ASSIGN(Delegate); |
44 }; | 79 }; |
45 | 80 |
46 private: | 81 private: |
47 int checked_command_ = -1; | 82 int checked_command_ = -1; |
48 Delegate delegate_; | 83 Delegate delegate_; |
84 base::Closure menu_open_callback_; | |
49 | 85 |
50 DISALLOW_COPY_AND_ASSIGN(TestModel); | 86 DISALLOW_COPY_AND_ASSIGN(TestModel); |
51 }; | 87 }; |
52 | 88 |
53 } // namespace | 89 } // namespace |
54 | 90 |
55 class MenuRunnerCocoaTest : public ViewsTestBase { | 91 class MenuRunnerCocoaTest : public ViewsTestBase { |
56 public: | 92 public: |
57 enum { | 93 enum { |
58 kWindowHeight = 200, | 94 kWindowHeight = 200, |
(...skipping 23 matching lines...) Expand all Loading... | |
82 void TearDown() override { | 118 void TearDown() override { |
83 if (runner_) { | 119 if (runner_) { |
84 runner_->Release(); | 120 runner_->Release(); |
85 runner_ = NULL; | 121 runner_ = NULL; |
86 } | 122 } |
87 | 123 |
88 parent_->CloseNow(); | 124 parent_->CloseNow(); |
89 ViewsTestBase::TearDown(); | 125 ViewsTestBase::TearDown(); |
90 } | 126 } |
91 | 127 |
92 // Runs the menu after scheduling |block| on the run loop. | 128 // Runs the menu after registering |callback| as the menu open callback. |
93 MenuRunner::RunResult RunMenu(dispatch_block_t block) { | 129 MenuRunner::RunResult RunMenu(const base::Closure& callback) { |
94 CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopCommonModes, ^{ | 130 menu_->set_menu_open_callback( |
95 EXPECT_TRUE(runner_->IsRunning()); | 131 base::Bind(&RunMenuWrapperCallback, callback, runner_)); |
96 block(); | 132 return runner_->RunMenuAt(parent_, nullptr, gfx::Rect(), |
97 }); | 133 MENU_ANCHOR_TOPLEFT, MenuRunner::CONTEXT_MENU); |
98 return runner_->RunMenuAt(parent_, NULL, gfx::Rect(), MENU_ANCHOR_TOPLEFT, | |
99 MenuRunner::CONTEXT_MENU); | |
100 } | 134 } |
101 | 135 |
102 // Runs then cancels a combobox menu and captures the frame of the anchoring | 136 // Runs then cancels a combobox menu and captures the frame of the anchoring |
103 // view. | 137 // view. |
104 MenuRunner::RunResult RunMenuAt(const gfx::Rect& anchor) { | 138 MenuRunner::RunResult RunMenuAt(const gfx::Rect& anchor) { |
105 last_anchor_frame_ = NSZeroRect; | 139 last_anchor_frame_ = NSZeroRect; |
106 | 140 |
107 // Should be one child (the compositor layer) before showing, and it should | 141 // Should be one child (the compositor layer) before showing, and it should |
108 // go up by one (the anchor view) while the menu is shown. | 142 // go up by one (the anchor view) while the menu is shown. |
109 EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]); | 143 EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]); |
110 CFRunLoopPerformBlock(CFRunLoopGetCurrent(), kCFRunLoopCommonModes, ^{ | 144 |
111 NSArray* subviews = [parent_->GetNativeView() subviews]; | 145 menu_->set_menu_open_callback( |
112 EXPECT_EQ(2u, [subviews count]); | 146 base::Bind(&RunMenuAtCallback, parent_, runner_, &last_anchor_frame_)); |
113 last_anchor_frame_ = [[subviews objectAtIndex:1] frame]; | 147 |
114 runner_->Cancel(); | |
115 }); | |
116 MenuRunner::RunResult result = runner_->RunMenuAt( | 148 MenuRunner::RunResult result = runner_->RunMenuAt( |
117 parent_, nullptr, anchor, MENU_ANCHOR_TOPLEFT, MenuRunner::COMBOBOX); | 149 parent_, nullptr, anchor, MENU_ANCHOR_TOPLEFT, MenuRunner::COMBOBOX); |
118 | 150 |
119 // Ensure the anchor view is removed. | 151 // Ensure the anchor view is removed. |
120 EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]); | 152 EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]); |
121 return result; | 153 return result; |
122 } | 154 } |
123 | 155 |
124 protected: | 156 protected: |
125 scoped_ptr<TestModel> menu_; | 157 scoped_ptr<TestModel> menu_; |
126 internal::MenuRunnerImplCocoa* runner_ = nullptr; | 158 internal::MenuRunnerImplCocoa* runner_ = nullptr; |
127 views::Widget* parent_ = nullptr; | 159 views::Widget* parent_ = nullptr; |
128 NSRect last_anchor_frame_ = NSZeroRect; | 160 NSRect last_anchor_frame_ = NSZeroRect; |
129 | 161 |
130 private: | 162 private: |
131 DISALLOW_COPY_AND_ASSIGN(MenuRunnerCocoaTest); | 163 DISALLOW_COPY_AND_ASSIGN(MenuRunnerCocoaTest); |
132 }; | 164 }; |
133 | 165 |
134 TEST_F(MenuRunnerCocoaTest, RunMenuAndCancel) { | 166 TEST_F(MenuRunnerCocoaTest, RunMenuAndCancel) { |
135 base::TimeDelta min_time = ui::EventTimeForNow(); | 167 base::TimeDelta min_time = ui::EventTimeForNow(); |
136 | 168 |
137 MenuRunner::RunResult result = RunMenu(^{ | 169 MenuRunner::RunResult result = |
138 runner_->Cancel(); | 170 RunMenu(base::Bind(&MenuCancelCallback, runner_)); |
139 EXPECT_FALSE(runner_->IsRunning()); | |
140 }); | |
141 | 171 |
142 EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); | 172 EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); |
143 EXPECT_FALSE(runner_->IsRunning()); | 173 EXPECT_FALSE(runner_->IsRunning()); |
144 | 174 |
145 EXPECT_GE(runner_->GetClosingEventTime(), min_time); | 175 EXPECT_GE(runner_->GetClosingEventTime(), min_time); |
146 EXPECT_LE(runner_->GetClosingEventTime(), ui::EventTimeForNow()); | 176 EXPECT_LE(runner_->GetClosingEventTime(), ui::EventTimeForNow()); |
147 | 177 |
148 // Cancel again. | 178 // Cancel again. |
149 runner_->Cancel(); | 179 runner_->Cancel(); |
150 EXPECT_FALSE(runner_->IsRunning()); | 180 EXPECT_FALSE(runner_->IsRunning()); |
151 } | 181 } |
152 | 182 |
153 TEST_F(MenuRunnerCocoaTest, RunMenuAndDelete) { | 183 TEST_F(MenuRunnerCocoaTest, RunMenuAndDelete) { |
154 MenuRunner::RunResult result = RunMenu(^{ | 184 MenuRunner::RunResult result = |
155 runner_->Release(); | 185 RunMenu(base::Bind(&MenuDeleteCallback, &runner_)); |
156 runner_ = NULL; | |
157 }); | |
158 | |
159 EXPECT_EQ(MenuRunner::MENU_DELETED, result); | 186 EXPECT_EQ(MenuRunner::MENU_DELETED, result); |
160 } | 187 } |
161 | 188 |
162 TEST_F(MenuRunnerCocoaTest, RunMenuTwice) { | 189 TEST_F(MenuRunnerCocoaTest, RunMenuTwice) { |
163 for (int i = 0; i < 2; ++i) { | 190 for (int i = 0; i < 2; ++i) { |
164 MenuRunner::RunResult result = RunMenu(^{ | 191 MenuRunner::RunResult result = |
165 runner_->Cancel(); | 192 RunMenu(base::Bind(&MenuCancelCallback, runner_)); |
166 }); | |
167 EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); | 193 EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); |
168 EXPECT_FALSE(runner_->IsRunning()); | 194 EXPECT_FALSE(runner_->IsRunning()); |
169 } | 195 } |
170 } | 196 } |
171 | 197 |
172 TEST_F(MenuRunnerCocoaTest, CancelWithoutRunning) { | 198 TEST_F(MenuRunnerCocoaTest, CancelWithoutRunning) { |
173 runner_->Cancel(); | 199 runner_->Cancel(); |
174 EXPECT_FALSE(runner_->IsRunning()); | 200 EXPECT_FALSE(runner_->IsRunning()); |
175 EXPECT_EQ(base::TimeDelta(), runner_->GetClosingEventTime()); | 201 EXPECT_EQ(base::TimeDelta(), runner_->GetClosingEventTime()); |
176 } | 202 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
217 // In RTL, Cocoa messes up the positioning unless the anchor rectangle is | 243 // In RTL, Cocoa messes up the positioning unless the anchor rectangle is |
218 // offset to the right of the view. The offset for the checkmark is also | 244 // offset to the right of the view. The offset for the checkmark is also |
219 // skipped, to give a better match to native behavior. | 245 // skipped, to give a better match to native behavior. |
220 base::i18n::SetICUDefaultLocale("he"); | 246 base::i18n::SetICUDefaultLocale("he"); |
221 RunMenuAt(anchor_rect); | 247 RunMenuAt(anchor_rect); |
222 EXPECT_EQ(combobox_rect.right(), last_anchor_frame_.origin.x); | 248 EXPECT_EQ(combobox_rect.right(), last_anchor_frame_.origin.x); |
223 } | 249 } |
224 | 250 |
225 } // namespace test | 251 } // namespace test |
226 } // namespace views | 252 } // namespace views |
OLD | NEW |