| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/aura/window_event_dispatcher.h" | 5 #include "ui/aura/window_event_dispatcher.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 EXPECT_EQ(2, filter->num_scroll_events()); | 424 EXPECT_EQ(2, filter->num_scroll_events()); |
| 425 } | 425 } |
| 426 | 426 |
| 427 namespace { | 427 namespace { |
| 428 | 428 |
| 429 // FilterFilter that tracks the types of events it's seen. | 429 // FilterFilter that tracks the types of events it's seen. |
| 430 class EventFilterRecorder : public ui::EventHandler { | 430 class EventFilterRecorder : public ui::EventHandler { |
| 431 public: | 431 public: |
| 432 typedef std::vector<ui::EventType> Events; | 432 typedef std::vector<ui::EventType> Events; |
| 433 typedef std::vector<gfx::Point> EventLocations; | 433 typedef std::vector<gfx::Point> EventLocations; |
| 434 typedef std::vector<int> EventFlags; |
| 434 | 435 |
| 435 EventFilterRecorder() | 436 EventFilterRecorder() |
| 436 : wait_until_event_(ui::ET_UNKNOWN) { | 437 : wait_until_event_(ui::ET_UNKNOWN) { |
| 437 } | 438 } |
| 438 | 439 |
| 439 const Events& events() const { return events_; } | 440 const Events& events() const { return events_; } |
| 440 | 441 |
| 441 const EventLocations& mouse_locations() const { return mouse_locations_; } | 442 const EventLocations& mouse_locations() const { return mouse_locations_; } |
| 442 gfx::Point mouse_location(int i) const { return mouse_locations_[i]; } | 443 gfx::Point mouse_location(int i) const { return mouse_locations_[i]; } |
| 443 const EventLocations& touch_locations() const { return touch_locations_; } | 444 const EventLocations& touch_locations() const { return touch_locations_; } |
| 445 const EventFlags& mouse_event_flags() const { return mouse_event_flags_; } |
| 444 | 446 |
| 445 void WaitUntilReceivedEvent(ui::EventType type) { | 447 void WaitUntilReceivedEvent(ui::EventType type) { |
| 446 wait_until_event_ = type; | 448 wait_until_event_ = type; |
| 447 run_loop_.reset(new base::RunLoop()); | 449 run_loop_.reset(new base::RunLoop()); |
| 448 run_loop_->Run(); | 450 run_loop_->Run(); |
| 449 } | 451 } |
| 450 | 452 |
| 451 Events GetAndResetEvents() { | 453 Events GetAndResetEvents() { |
| 452 Events events = events_; | 454 Events events = events_; |
| 453 Reset(); | 455 Reset(); |
| 454 return events; | 456 return events; |
| 455 } | 457 } |
| 456 | 458 |
| 457 void Reset() { | 459 void Reset() { |
| 458 events_.clear(); | 460 events_.clear(); |
| 459 mouse_locations_.clear(); | 461 mouse_locations_.clear(); |
| 460 touch_locations_.clear(); | 462 touch_locations_.clear(); |
| 463 mouse_event_flags_.clear(); |
| 461 } | 464 } |
| 462 | 465 |
| 463 // ui::EventHandler overrides: | 466 // ui::EventHandler overrides: |
| 464 virtual void OnEvent(ui::Event* event) OVERRIDE { | 467 virtual void OnEvent(ui::Event* event) OVERRIDE { |
| 465 ui::EventHandler::OnEvent(event); | 468 ui::EventHandler::OnEvent(event); |
| 466 events_.push_back(event->type()); | 469 events_.push_back(event->type()); |
| 467 if (wait_until_event_ == event->type() && run_loop_) { | 470 if (wait_until_event_ == event->type() && run_loop_) { |
| 468 run_loop_->Quit(); | 471 run_loop_->Quit(); |
| 469 wait_until_event_ = ui::ET_UNKNOWN; | 472 wait_until_event_ = ui::ET_UNKNOWN; |
| 470 } | 473 } |
| 471 } | 474 } |
| 472 | 475 |
| 473 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { | 476 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { |
| 474 mouse_locations_.push_back(event->location()); | 477 mouse_locations_.push_back(event->location()); |
| 478 mouse_event_flags_.push_back(event->flags()); |
| 475 } | 479 } |
| 476 | 480 |
| 477 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE { | 481 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE { |
| 478 touch_locations_.push_back(event->location()); | 482 touch_locations_.push_back(event->location()); |
| 479 } | 483 } |
| 480 | 484 |
| 481 private: | 485 private: |
| 482 scoped_ptr<base::RunLoop> run_loop_; | 486 scoped_ptr<base::RunLoop> run_loop_; |
| 483 ui::EventType wait_until_event_; | 487 ui::EventType wait_until_event_; |
| 484 | 488 |
| 485 Events events_; | 489 Events events_; |
| 486 EventLocations mouse_locations_; | 490 EventLocations mouse_locations_; |
| 487 EventLocations touch_locations_; | 491 EventLocations touch_locations_; |
| 492 EventFlags mouse_event_flags_; |
| 488 | 493 |
| 489 DISALLOW_COPY_AND_ASSIGN(EventFilterRecorder); | 494 DISALLOW_COPY_AND_ASSIGN(EventFilterRecorder); |
| 490 }; | 495 }; |
| 491 | 496 |
| 492 // Converts an EventType to a string. | 497 // Converts an EventType to a string. |
| 493 std::string EventTypeToString(ui::EventType type) { | 498 std::string EventTypeToString(ui::EventType type) { |
| 494 switch (type) { | 499 switch (type) { |
| 495 case ui::ET_TOUCH_RELEASED: | 500 case ui::ET_TOUCH_RELEASED: |
| 496 return "TOUCH_RELEASED"; | 501 return "TOUCH_RELEASED"; |
| 497 | 502 |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 DispatchEventUsingWindowDispatcher(&mouse2); | 837 DispatchEventUsingWindowDispatcher(&mouse2); |
| 833 EXPECT_FALSE(filter->events().empty()); | 838 EXPECT_FALSE(filter->events().empty()); |
| 834 filter->Reset(); | 839 filter->Reset(); |
| 835 | 840 |
| 836 // Dispatch a synthetic mouse event when mouse events are disabled. | 841 // Dispatch a synthetic mouse event when mouse events are disabled. |
| 837 cursor_client.DisableMouseEvents(); | 842 cursor_client.DisableMouseEvents(); |
| 838 DispatchEventUsingWindowDispatcher(&mouse2); | 843 DispatchEventUsingWindowDispatcher(&mouse2); |
| 839 EXPECT_TRUE(filter->events().empty()); | 844 EXPECT_TRUE(filter->events().empty()); |
| 840 } | 845 } |
| 841 | 846 |
| 847 // Tests synthetic mouse events generated when window bounds changes such that |
| 848 // the cursor previously outside the window becomes inside, or vice versa. |
| 849 // - Synthesize MOVED events when the mouse button is up; |
| 850 // - Synthesize DRAGGED events with correct flags when mouse button is down; |
| 851 // - Do not synthesize events if the window ignores events or is invisible. |
| 852 TEST_F(WindowEventDispatcherTest, SynthesizeMouseEventsOnWindowBoundsChanged) { |
| 853 test::TestWindowDelegate delegate; |
| 854 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
| 855 &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window())); |
| 856 window->Show(); |
| 857 window->SetCapture(); |
| 858 |
| 859 EventFilterRecorder* filter = new EventFilterRecorder; |
| 860 window->SetEventFilter(filter); // passes ownership |
| 861 |
| 862 // Dispatch a non-synthetic mouse event to place cursor inside window bounds. |
| 863 ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, gfx::Point(10, 10), |
| 864 gfx::Point(10, 10), 0, 0); |
| 865 DispatchEventUsingWindowDispatcher(&mouse); |
| 866 EXPECT_FALSE(filter->events().empty()); |
| 867 filter->Reset(); |
| 868 |
| 869 // Update the window bounds so that cursor is now outside the window. |
| 870 // This should trigger a synthetic MOVED event. |
| 871 gfx::Rect bounds1(20, 20, 100, 100); |
| 872 window->SetBounds(bounds1); |
| 873 RunAllPendingInMessageLoop(); |
| 874 ASSERT_FALSE(filter->events().empty()); |
| 875 ASSERT_FALSE(filter->mouse_event_flags().empty()); |
| 876 EXPECT_EQ(ui::ET_MOUSE_MOVED, filter->events().back()); |
| 877 EXPECT_EQ(ui::EF_IS_SYNTHESIZED, filter->mouse_event_flags().back()); |
| 878 filter->Reset(); |
| 879 |
| 880 // Hold down the LEFT mouse button. |
| 881 Env::GetInstance()->set_mouse_button_flags(ui::EF_LEFT_MOUSE_BUTTON); |
| 882 |
| 883 // Update the window bounds so that cursor is back inside the window. |
| 884 // This should trigger a synthetic DRAGGED event with the left button flag. |
| 885 gfx::Rect bounds2(5, 5, 100, 100); |
| 886 window->SetBounds(bounds2); |
| 887 RunAllPendingInMessageLoop(); |
| 888 ASSERT_FALSE(filter->events().empty()); |
| 889 ASSERT_FALSE(filter->mouse_event_flags().empty()); |
| 890 EXPECT_EQ(ui::ET_MOUSE_DRAGGED, filter->events().back()); |
| 891 EXPECT_EQ(ui::EF_IS_SYNTHESIZED | ui::EF_LEFT_MOUSE_BUTTON, |
| 892 filter->mouse_event_flags().back()); |
| 893 filter->Reset(); |
| 894 |
| 895 // Hold down the RIGHT mouse button. |
| 896 Env::GetInstance()->set_mouse_button_flags(ui::EF_RIGHT_MOUSE_BUTTON); |
| 897 |
| 898 // Update the window bounds so that cursor is outside the window. |
| 899 // This should trigger a synthetic DRAGGED event with the right button flag. |
| 900 window->SetBounds(bounds1); |
| 901 RunAllPendingInMessageLoop(); |
| 902 ASSERT_FALSE(filter->events().empty()); |
| 903 ASSERT_FALSE(filter->mouse_event_flags().empty()); |
| 904 EXPECT_EQ(ui::ET_MOUSE_DRAGGED, filter->events().back()); |
| 905 EXPECT_EQ(ui::EF_IS_SYNTHESIZED | ui::EF_RIGHT_MOUSE_BUTTON, |
| 906 filter->mouse_event_flags().back()); |
| 907 filter->Reset(); |
| 908 |
| 909 // Release mouse button and set window to ignore events. |
| 910 Env::GetInstance()->set_mouse_button_flags(0); |
| 911 window->set_ignore_events(true); |
| 912 |
| 913 // Update the window bounds so that cursor is back inside the window. |
| 914 // This should not trigger a synthetic event. |
| 915 window->SetBounds(bounds2); |
| 916 RunAllPendingInMessageLoop(); |
| 917 EXPECT_TRUE(filter->events().empty()); |
| 918 filter->Reset(); |
| 919 |
| 920 // Set window to accept events but invisible. |
| 921 window->set_ignore_events(false); |
| 922 window->Hide(); |
| 923 filter->Reset(); |
| 924 |
| 925 // Update the window bounds so that cursor is outside the window. |
| 926 // This should not trigger a synthetic event. |
| 927 window->SetBounds(bounds1); |
| 928 RunAllPendingInMessageLoop(); |
| 929 EXPECT_TRUE(filter->events().empty()); |
| 930 } |
| 931 |
| 842 // Tests that a mouse exit is dispatched to the last known cursor location | 932 // Tests that a mouse exit is dispatched to the last known cursor location |
| 843 // when the cursor becomes invisible. | 933 // when the cursor becomes invisible. |
| 844 TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenCursorHidden) { | 934 TEST_F(WindowEventDispatcherTest, DispatchMouseExitWhenCursorHidden) { |
| 845 EventFilterRecorder* filter = new EventFilterRecorder; | 935 EventFilterRecorder* filter = new EventFilterRecorder; |
| 846 root_window()->SetEventFilter(filter); // passes ownership | 936 root_window()->SetEventFilter(filter); // passes ownership |
| 847 | 937 |
| 848 test::TestWindowDelegate delegate; | 938 test::TestWindowDelegate delegate; |
| 849 gfx::Point window_origin(7, 18); | 939 gfx::Point window_origin(7, 18); |
| 850 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( | 940 scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate( |
| 851 &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)), | 941 &delegate, 1234, gfx::Rect(window_origin, gfx::Size(100, 100)), |
| (...skipping 1175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 delegate.GetMouseMotionCountsAndReset(); | 2117 delegate.GetMouseMotionCountsAndReset(); |
| 2028 | 2118 |
| 2029 // Notify both hosts that the cursor is now hidden. This should send a single | 2119 // Notify both hosts that the cursor is now hidden. This should send a single |
| 2030 // mouse-exit event to |window|. | 2120 // mouse-exit event to |window|. |
| 2031 host()->OnCursorVisibilityChanged(false); | 2121 host()->OnCursorVisibilityChanged(false); |
| 2032 second_host->OnCursorVisibilityChanged(false); | 2122 second_host->OnCursorVisibilityChanged(false); |
| 2033 EXPECT_EQ("0 0 1", delegate.GetMouseMotionCountsAndReset()); | 2123 EXPECT_EQ("0 0 1", delegate.GetMouseMotionCountsAndReset()); |
| 2034 } | 2124 } |
| 2035 | 2125 |
| 2036 } // namespace aura | 2126 } // namespace aura |
| OLD | NEW |