| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include "ui/views/controls/menu/menu_runner.h" | 5 #include "ui/views/controls/menu/menu_runner.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "ui/base/ui_base_types.h" | 13 #include "ui/base/ui_base_types.h" |
| 14 #include "ui/events/test/event_generator.h" | 14 #include "ui/events/test/event_generator.h" |
| 15 #include "ui/views/controls/menu/menu_delegate.h" | 15 #include "ui/views/controls/menu/menu_delegate.h" |
| 16 #include "ui/views/controls/menu/menu_item_view.h" | 16 #include "ui/views/controls/menu/menu_item_view.h" |
| 17 #include "ui/views/controls/menu/menu_runner_impl.h" | 17 #include "ui/views/controls/menu/menu_runner_impl.h" |
| 18 #include "ui/views/controls/menu/menu_types.h" | 18 #include "ui/views/controls/menu/menu_types.h" |
| 19 #include "ui/views/controls/menu/submenu_view.h" | 19 #include "ui/views/controls/menu/submenu_view.h" |
| 20 #include "ui/views/test/menu_test_utils.h" | 20 #include "ui/views/test/menu_test_utils.h" |
| 21 #include "ui/views/test/test_views.h" |
| 21 #include "ui/views/test/views_test_base.h" | 22 #include "ui/views/test/views_test_base.h" |
| 23 #include "ui/views/widget/native_widget_private.h" |
| 22 #include "ui/views/widget/widget.h" | 24 #include "ui/views/widget/widget.h" |
| 23 | 25 |
| 24 namespace views { | 26 namespace views { |
| 25 namespace test { | 27 namespace test { |
| 26 | 28 |
| 27 class MenuRunnerTest : public ViewsTestBase { | 29 class MenuRunnerTest : public ViewsTestBase { |
| 28 public: | 30 public: |
| 29 MenuRunnerTest(); | 31 MenuRunnerTest(); |
| 30 ~MenuRunnerTest() override; | 32 ~MenuRunnerTest() override; |
| 31 | 33 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE); | 181 MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_NONE); |
| 180 EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); | 182 EXPECT_EQ(MenuRunner::NORMAL_EXIT, result); |
| 181 EXPECT_TRUE(nested_runner->IsRunning()); | 183 EXPECT_TRUE(nested_runner->IsRunning()); |
| 182 EXPECT_FALSE(runner->IsRunning()); | 184 EXPECT_FALSE(runner->IsRunning()); |
| 183 TestMenuDelegate* delegate = menu_delegate(); | 185 TestMenuDelegate* delegate = menu_delegate(); |
| 184 EXPECT_EQ(1, delegate->on_menu_closed_called()); | 186 EXPECT_EQ(1, delegate->on_menu_closed_called()); |
| 185 EXPECT_NE(nullptr, delegate->on_menu_closed_menu()); | 187 EXPECT_NE(nullptr, delegate->on_menu_closed_menu()); |
| 186 EXPECT_EQ(MenuRunner::NORMAL_EXIT, delegate->on_menu_closed_run_result()); | 188 EXPECT_EQ(MenuRunner::NORMAL_EXIT, delegate->on_menu_closed_run_result()); |
| 187 } | 189 } |
| 188 | 190 |
| 191 namespace { |
| 192 |
| 193 // An EventHandler that launches a menu in response to a mouse press. |
| 194 class MenuLauncherEventHandler : public ui::EventHandler { |
| 195 public: |
| 196 MenuLauncherEventHandler(MenuRunner* runner, Widget* owner) |
| 197 : runner_(runner), owner_(owner) {} |
| 198 ~MenuLauncherEventHandler() override {} |
| 199 |
| 200 private: |
| 201 // ui::EventHandler: |
| 202 void OnMouseEvent(ui::MouseEvent* event) override { |
| 203 if (event->type() == ui::ET_MOUSE_PRESSED) { |
| 204 runner_->RunMenuAt(owner_, nullptr, gfx::Rect(), MENU_ANCHOR_TOPLEFT, |
| 205 ui::MENU_SOURCE_NONE); |
| 206 event->SetHandled(); |
| 207 } |
| 208 } |
| 209 |
| 210 MenuRunner* runner_; |
| 211 Widget* owner_; |
| 212 |
| 213 DISALLOW_COPY_AND_ASSIGN(MenuLauncherEventHandler); |
| 214 }; |
| 215 |
| 216 } // namespace |
| 217 |
| 218 // Tests that when a mouse press launches a menu, that the target widget does |
| 219 // not take explicit capture, nor closes the menu. |
| 220 TEST_F(MenuRunnerTest, WidgetDoesntTakeCapture) { |
| 221 Widget* widget = new Widget; |
| 222 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
| 223 widget->Init(params); |
| 224 widget->Show(); |
| 225 widget->SetSize(gfx::Size(300, 300)); |
| 226 |
| 227 EventCountView* event_count_view = new EventCountView(); |
| 228 event_count_view->SetBounds(0, 0, 300, 300); |
| 229 widget->GetRootView()->AddChildView(event_count_view); |
| 230 |
| 231 InitMenuRunner(MenuRunner::ASYNC); |
| 232 MenuRunner* runner = menu_runner(); |
| 233 |
| 234 MenuLauncherEventHandler consumer(runner, owner()); |
| 235 event_count_view->AddPostTargetHandler(&consumer); |
| 236 EXPECT_EQ(nullptr, internal::NativeWidgetPrivate::GetGlobalCapture( |
| 237 widget->GetNativeView())); |
| 238 std::unique_ptr<ui::test::EventGenerator> generator( |
| 239 new ui::test::EventGenerator( |
| 240 IsMus() ? widget->GetNativeWindow() : GetContext(), |
| 241 widget->GetNativeWindow())); |
| 242 // Implicit capture should not be held by |widget|. |
| 243 generator->PressLeftButton(); |
| 244 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); |
| 245 EXPECT_NE( |
| 246 widget->GetNativeView(), |
| 247 internal::NativeWidgetPrivate::GetGlobalCapture(widget->GetNativeView())); |
| 248 |
| 249 // The menu should still be open. |
| 250 TestMenuDelegate* delegate = menu_delegate(); |
| 251 EXPECT_TRUE(runner->IsRunning()); |
| 252 EXPECT_EQ(0, delegate->on_menu_closed_called()); |
| 253 |
| 254 widget->CloseNow(); |
| 255 } |
| 256 |
| 189 typedef MenuRunnerTest MenuRunnerImplTest; | 257 typedef MenuRunnerTest MenuRunnerImplTest; |
| 190 | 258 |
| 191 // Tests that when nested menu runners are destroyed out of order, that | 259 // Tests that when nested menu runners are destroyed out of order, that |
| 192 // MenuController is not accessed after it has been destroyed. This should not | 260 // MenuController is not accessed after it has been destroyed. This should not |
| 193 // crash on ASAN bots. | 261 // crash on ASAN bots. |
| 194 TEST_F(MenuRunnerImplTest, NestedMenuRunnersDestroyedOutOfOrder) { | 262 TEST_F(MenuRunnerImplTest, NestedMenuRunnersDestroyedOutOfOrder) { |
| 195 internal::MenuRunnerImpl* menu_runner = | 263 internal::MenuRunnerImpl* menu_runner = |
| 196 new internal::MenuRunnerImpl(menu_item_view()); | 264 new internal::MenuRunnerImpl(menu_item_view()); |
| 197 EXPECT_EQ(MenuRunner::NORMAL_EXIT, | 265 EXPECT_EQ(MenuRunner::NORMAL_EXIT, |
| 198 menu_runner->RunMenuAt(owner(), nullptr, gfx::Rect(), | 266 menu_runner->RunMenuAt(owner(), nullptr, gfx::Rect(), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 217 menu_runner->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 285 menu_runner->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
| 218 nullptr, 0); | 286 nullptr, 0); |
| 219 | 287 |
| 220 // This should not access the destroyed MenuController | 288 // This should not access the destroyed MenuController |
| 221 menu_runner2->Release(); | 289 menu_runner2->Release(); |
| 222 menu_runner->Release(); | 290 menu_runner->Release(); |
| 223 } | 291 } |
| 224 | 292 |
| 225 } // namespace test | 293 } // namespace test |
| 226 } // namespace views | 294 } // namespace views |
| OLD | NEW |