Chromium Code Reviews| 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 |