| 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 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 } | 208 } |
| 209 | 209 |
| 210 MenuRunner* runner_; | 210 MenuRunner* runner_; |
| 211 Widget* owner_; | 211 Widget* owner_; |
| 212 | 212 |
| 213 DISALLOW_COPY_AND_ASSIGN(MenuLauncherEventHandler); | 213 DISALLOW_COPY_AND_ASSIGN(MenuLauncherEventHandler); |
| 214 }; | 214 }; |
| 215 | 215 |
| 216 } // namespace | 216 } // namespace |
| 217 | 217 |
| 218 // Test harness that includes a parent Widget and View invoking the menu. |
| 219 class MenuRunnerWidgetTest : public MenuRunnerTest { |
| 220 public: |
| 221 MenuRunnerWidgetTest() {} |
| 222 |
| 223 Widget* widget() { return widget_; } |
| 224 EventCountView* event_count_view() { return event_count_view_; } |
| 225 |
| 226 std::unique_ptr<ui::test::EventGenerator> EventGeneratorForWidget( |
| 227 Widget* widget) { |
| 228 return base::MakeUnique<ui::test::EventGenerator>( |
| 229 IsMus() ? widget->GetNativeWindow() : GetContext(), |
| 230 widget->GetNativeWindow()); |
| 231 } |
| 232 |
| 233 void AddMenuLauncherEventHandler(Widget* widget) { |
| 234 consumer_ = |
| 235 base::MakeUnique<MenuLauncherEventHandler>(menu_runner(), widget); |
| 236 event_count_view_->AddPostTargetHandler(consumer_.get()); |
| 237 } |
| 238 |
| 239 // ViewsTestBase: |
| 240 void SetUp() override { |
| 241 MenuRunnerTest::SetUp(); |
| 242 widget_ = new Widget; |
| 243 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
| 244 widget_->Init(params); |
| 245 widget_->Show(); |
| 246 widget_->SetSize(gfx::Size(300, 300)); |
| 247 |
| 248 event_count_view_ = new EventCountView(); |
| 249 event_count_view_->SetBounds(0, 0, 300, 300); |
| 250 widget_->GetRootView()->AddChildView(event_count_view_); |
| 251 |
| 252 InitMenuRunner(MenuRunner::ASYNC); |
| 253 } |
| 254 |
| 255 void TearDown() override { |
| 256 widget_->CloseNow(); |
| 257 MenuRunnerTest::TearDown(); |
| 258 } |
| 259 |
| 260 private: |
| 261 Widget* widget_ = nullptr; |
| 262 EventCountView* event_count_view_ = nullptr; |
| 263 std::unique_ptr<MenuLauncherEventHandler> consumer_; |
| 264 |
| 265 DISALLOW_COPY_AND_ASSIGN(MenuRunnerWidgetTest); |
| 266 }; |
| 267 |
| 218 // Tests that when a mouse press launches a menu, that the target widget does | 268 // Tests that when a mouse press launches a menu, that the target widget does |
| 219 // not take explicit capture, nor closes the menu. | 269 // not take explicit capture, nor closes the menu. |
| 220 TEST_F(MenuRunnerTest, WidgetDoesntTakeCapture) { | 270 TEST_F(MenuRunnerWidgetTest, WidgetDoesntTakeCapture) { |
| 221 Widget* widget = new Widget; | 271 AddMenuLauncherEventHandler(owner()); |
| 222 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); | |
| 223 widget->Init(params); | |
| 224 widget->Show(); | |
| 225 widget->SetSize(gfx::Size(300, 300)); | |
| 226 | 272 |
| 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( | 273 EXPECT_EQ(nullptr, internal::NativeWidgetPrivate::GetGlobalCapture( |
| 237 widget->GetNativeView())); | 274 widget()->GetNativeView())); |
| 238 std::unique_ptr<ui::test::EventGenerator> generator( | 275 auto generator(EventGeneratorForWidget(widget())); |
| 239 new ui::test::EventGenerator( | |
| 240 IsMus() ? widget->GetNativeWindow() : GetContext(), | |
| 241 widget->GetNativeWindow())); | |
| 242 // Implicit capture should not be held by |widget|. | 276 // Implicit capture should not be held by |widget|. |
| 243 generator->PressLeftButton(); | 277 generator->PressLeftButton(); |
| 244 EXPECT_EQ(1, event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); | 278 EXPECT_EQ(1, event_count_view()->GetEventCount(ui::ET_MOUSE_PRESSED)); |
| 245 EXPECT_NE( | 279 EXPECT_NE(widget()->GetNativeView(), |
| 246 widget->GetNativeView(), | 280 internal::NativeWidgetPrivate::GetGlobalCapture( |
| 247 internal::NativeWidgetPrivate::GetGlobalCapture(widget->GetNativeView())); | 281 widget()->GetNativeView())); |
| 248 | 282 |
| 249 // The menu should still be open. | 283 // The menu should still be open. |
| 250 TestMenuDelegate* delegate = menu_delegate(); | 284 TestMenuDelegate* delegate = menu_delegate(); |
| 251 EXPECT_TRUE(runner->IsRunning()); | 285 EXPECT_TRUE(menu_runner()->IsRunning()); |
| 252 EXPECT_EQ(0, delegate->on_menu_closed_called()); | 286 EXPECT_EQ(0, delegate->on_menu_closed_called()); |
| 287 } |
| 253 | 288 |
| 254 widget->CloseNow(); | 289 // Tests that after showing a menu on mouse press, that the subsequent mouse |
| 290 // will be delivered to the correct view, and not to the one that showed the |
| 291 // menu. |
| 292 // |
| 293 // The original bug is reproducible only when showing the menu on mouse press, |
| 294 // as RootView::OnMouseReleased() doesn't have the same behavior. |
| 295 TEST_F(MenuRunnerWidgetTest, ClearsMouseHandlerOnRun) { |
| 296 AddMenuLauncherEventHandler(widget()); |
| 297 |
| 298 // Create a second view that's supposed to get the second mouse press. |
| 299 EventCountView* second_event_count_view = new EventCountView(); |
| 300 widget()->GetRootView()->AddChildView(second_event_count_view); |
| 301 |
| 302 widget()->SetBounds(gfx::Rect(0, 0, 200, 100)); |
| 303 event_count_view()->SetBounds(0, 0, 100, 100); |
| 304 second_event_count_view->SetBounds(100, 0, 100, 100); |
| 305 |
| 306 // Click on the first view to show the menu. |
| 307 auto generator(EventGeneratorForWidget(widget())); |
| 308 generator->MoveMouseTo(event_count_view()->bounds().CenterPoint()); |
| 309 generator->PressLeftButton(); |
| 310 |
| 311 // Pretend we dismissed the menu using normal means, as it doesn't matter. |
| 312 EXPECT_TRUE(menu_runner()->IsRunning()); |
| 313 menu_runner()->Cancel(); |
| 314 |
| 315 // EventGenerator won't allow us to re-send the left button press without |
| 316 // releasing it first. We can't send the release event using the same |
| 317 // generator as it would be handled by the RootView in the main Widget. |
| 318 // In actual application the RootView doesn't see the release event. |
| 319 generator.reset(); |
| 320 generator = EventGeneratorForWidget(widget()); |
| 321 |
| 322 generator->MoveMouseTo(second_event_count_view->bounds().CenterPoint()); |
| 323 generator->PressLeftButton(); |
| 324 EXPECT_EQ(1, second_event_count_view->GetEventCount(ui::ET_MOUSE_PRESSED)); |
| 255 } | 325 } |
| 256 | 326 |
| 257 typedef MenuRunnerTest MenuRunnerImplTest; | 327 typedef MenuRunnerTest MenuRunnerImplTest; |
| 258 | 328 |
| 259 // Tests that when nested menu runners are destroyed out of order, that | 329 // Tests that when nested menu runners are destroyed out of order, that |
| 260 // MenuController is not accessed after it has been destroyed. This should not | 330 // MenuController is not accessed after it has been destroyed. This should not |
| 261 // crash on ASAN bots. | 331 // crash on ASAN bots. |
| 262 TEST_F(MenuRunnerImplTest, NestedMenuRunnersDestroyedOutOfOrder) { | 332 TEST_F(MenuRunnerImplTest, NestedMenuRunnersDestroyedOutOfOrder) { |
| 263 internal::MenuRunnerImpl* menu_runner = | 333 internal::MenuRunnerImpl* menu_runner = |
| 264 new internal::MenuRunnerImpl(menu_item_view()); | 334 new internal::MenuRunnerImpl(menu_item_view()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 285 menu_runner->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, | 355 menu_runner->OnMenuClosed(internal::MenuControllerDelegate::NOTIFY_DELEGATE, |
| 286 nullptr, 0); | 356 nullptr, 0); |
| 287 | 357 |
| 288 // This should not access the destroyed MenuController | 358 // This should not access the destroyed MenuController |
| 289 menu_runner2->Release(); | 359 menu_runner2->Release(); |
| 290 menu_runner->Release(); | 360 menu_runner->Release(); |
| 291 } | 361 } |
| 292 | 362 |
| 293 } // namespace test | 363 } // namespace test |
| 294 } // namespace views | 364 } // namespace views |
| OLD | NEW |