1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/views/widget/desktop_aura/desktop_capture_client.h" 6 7 #include "ui/aura/root_window.h" 8 #include "ui/aura/test/aura_test_base.h" 9 #include "ui/aura/test/test_screen.h" 10 #include "ui/aura/test/test_window_delegate.h" 11 #include "ui/base/events/event.h" 12 #include "ui/views/test/views_test_base.h" 13 #include "ui/views/view.h" 14 #include "ui/views/widget/desktop_aura/desktop_screen_position_client.h" 15 #include "ui/views/widget/root_view.h" 16 #include "ui/views/widget/widget.h" 17 18 namespace views { 19 20 typedef ViewsTestBase ViewTest; 21 22 class DesktopCaptureClientTest : public aura::test::AuraTestBase { 23 public: 24 virtual void SetUp() OVERRIDE { 25 AuraTestBase::SetUp(); 26 desktop_capture_client_.reset(new DesktopCaptureClient(root_window())); 27 28 second_root_.reset(new aura::RootWindow( 29 aura::RootWindow::CreateParams(gfx::Rect(0, 0, 800, 600)))); 30 second_root_->Init(); 31 second_root_->Show(); 32 second_root_->SetHostSize(gfx::Size(800, 600)); 33 second_desktop_capture_client_.reset( 34 new DesktopCaptureClient(second_root_.get())); 35 36 desktop_position_client_.reset(new DesktopScreenPositionClient()); 37 aura::client::SetScreenPositionClient(root_window(), 38 desktop_position_client_.get()); 39 40 second_desktop_position_client_.reset(new DesktopScreenPositionClient()); 41 aura::client::SetScreenPositionClient( 42 second_root_.get(), 43 second_desktop_position_client_.get()); 44 } 45 46 virtual void TearDown() OVERRIDE { 47 RunAllPendingInMessageLoop(); 48 49 second_desktop_position_client_.reset(); 50 second_desktop_capture_client_.reset(); 51 52 // Kill any active compositors before we hit the compositor shutdown paths. 53 second_root_.reset(); 54 55 desktop_position_client_.reset(); 56 desktop_capture_client_.reset(); 57 58 AuraTestBase::TearDown(); 59 } 60 61 scoped_ptr<DesktopCaptureClient> desktop_capture_client_; 62 scoped_ptr<aura::RootWindow> second_root_; 63 scoped_ptr<DesktopCaptureClient> second_desktop_capture_client_; 64 scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client_; 65 scoped_ptr<aura::client::ScreenPositionClient> 66 second_desktop_position_client_; 67 }; 68 69 // Makes sure that internal details that are set on mouse down (such as 70 // mouse_pressed_handler()) are cleared when another root window takes capture. 71 TEST_F(DesktopCaptureClientTest, ResetMouseEventHandlerOnCapture) { 72 // Create a window inside the RootWindow. 73 scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); 74 75 // Make a synthesized mouse down event. Ensure that the RootWindow will 76 // dispatch further mouse events to |w1|. 77 ui::MouseEvent mouse_pressed_event(ui::ET_MOUSE_PRESSED, gfx::Point(5, 5), 78 gfx::Point(5, 5), 0); 79 root_window()->AsRootWindowHostDelegate()->OnHostMouseEvent( 80 &mouse_pressed_event); 81 EXPECT_EQ(w1.get(), root_window()->mouse_pressed_handler()); 82 83 // Build a window in the second RootWindow. 84 scoped_ptr<aura::Window> w2(CreateNormalWindow(2, second_root_.get(), NULL)); 85 86 // The act of having the second window take capture should clear out mouse 87 // pressed handler in the first RootWindow. 88 w2->SetCapture(); 89 EXPECT_EQ(NULL, root_window()->mouse_pressed_handler()); 90 } 91 92 // Makes sure that when one window gets capture, it forces the release on the 93 // other. This is needed has to be handled explicitly on Linux, and is a sanity 94 // check on Windows. 95 TEST_F(DesktopCaptureClientTest, ResetOtherWindowCaptureOnCapture) { 96 // Create a window inside the RootWindow. 97 scoped_ptr<aura::Window> w1(CreateNormalWindow(1, root_window(), NULL)); 98 w1->SetCapture(); 99 // Both capture clients should return the same capture window. 100 EXPECT_EQ(w1.get(), desktop_capture_client_->GetCaptureWindow()); 101 EXPECT_EQ(w1.get(), second_desktop_capture_client_->GetCaptureWindow()); 102 103 // Build a window in the second RootWindow and give it capture. Both capture 104 // clients should return the same capture window. 105 scoped_ptr<aura::Window> w2(CreateNormalWindow(2, second_root_.get(), NULL)); 106 w2->SetCapture(); 107 EXPECT_EQ(w2.get(), desktop_capture_client_->GetCaptureWindow()); 108 EXPECT_EQ(w2.get(), second_desktop_capture_client_->GetCaptureWindow()); 109 } 110 111 // This class provides functionality to verify whether the View instance 112 // received the gesture event. 113 class DesktopViewInputTest : public View { 114 public: 115 DesktopViewInputTest() 116 : received_gesture_event_(false) {} 117 118 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { 119 received_gesture_event_ = true; 120 return View::OnGestureEvent(event); 121 } 122 123 // Resets state maintained by this class. 124 void Reset() { 125 received_gesture_event_ = false; 126 } 127 128 bool received_gesture_event() const { return received_gesture_event_; } 129 130 private: 131 bool received_gesture_event_; 132 133 DISALLOW_COPY_AND_ASSIGN(DesktopViewInputTest); 134 }; 135 136 // Tests aura::Window capture and whether gesture events are sent to the window 137 // which has capture. 138 // The test case creates two visible widgets and sets capture to the underlying 139 // aura::Windows one by one. It then sends a gesture event and validates whether 140 // the window which had capture receives the gesture. 141 TEST_F(ViewTest, CaptureWindowInputEventTest) { 142 scoped_ptr<DesktopCaptureClient> desktop_capture_client1; 143 scoped_ptr<DesktopCaptureClient> desktop_capture_client2; 144 scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client1; 145 scoped_ptr<aura::client::ScreenPositionClient> desktop_position_client2; 146 147 scoped_ptr<Widget> widget1(new Widget()); 148 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 149 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 150 params.bounds = gfx::Rect(50, 50, 650, 650); 151 widget1->Init(params); 152 internal::RootView* root1 = 153 static_cast<internal::RootView*>(widget1->GetRootView()); 154 155 desktop_capture_client1.reset(new DesktopCaptureClient( 156 widget1->GetNativeView()->GetRootWindow())); 157 desktop_position_client1.reset(new DesktopScreenPositionClient()); 158 aura::client::SetScreenPositionClient( 159 widget1->GetNativeView()->GetRootWindow(), 160 desktop_position_client1.get()); 161 162 DesktopViewInputTest* v1 = new DesktopViewInputTest(); 163 v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); 164 root1->AddChildView(v1); 165 widget1->Show(); 166 167 scoped_ptr<Widget> widget2(new Widget()); 168 169 params = CreateParams(Widget::InitParams::TYPE_POPUP); 170 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 171 params.bounds = gfx::Rect(50, 50, 650, 650); 172 widget2->Init(params); 173 174 internal::RootView* root2 = 175 static_cast<internal::RootView*>(widget2->GetRootView()); 176 desktop_capture_client2.reset(new DesktopCaptureClient( 177 widget2->GetNativeView()->GetRootWindow())); 178 desktop_position_client2.reset(new DesktopScreenPositionClient()); 179 aura::client::SetScreenPositionClient( 180 widget2->GetNativeView()->GetRootWindow(), 181 desktop_position_client2.get()); 182 183 DesktopViewInputTest* v2 = new DesktopViewInputTest(); 184 v2->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); 185 root2->AddChildView(v2); 186 widget2->Show(); 187 188 EXPECT_FALSE(widget1->GetNativeView()->HasCapture()); 189 EXPECT_FALSE(widget2->GetNativeView()->HasCapture()); 190 EXPECT_EQ(desktop_capture_client1->GetCaptureWindow(), 191 reinterpret_cast<aura::Window*>(0)); 192 EXPECT_EQ(desktop_capture_client2->GetCaptureWindow(), 193 reinterpret_cast<aura::Window*>(0)); 194 195 widget1->GetNativeView()->SetCapture(); 196 EXPECT_TRUE(widget1->GetNativeView()->HasCapture()); 197 EXPECT_FALSE(widget2->GetNativeView()->HasCapture()); 198 EXPECT_EQ(desktop_capture_client1->GetCaptureWindow(), 199 widget1->GetNativeView()); 200 EXPECT_EQ(desktop_capture_client2->GetCaptureWindow(), 201 widget1->GetNativeView()); 202 203 ui::GestureEvent g1(ui::ET_GESTURE_LONG_PRESS, 80, 80, 0, 204 base::TimeDelta(), 205 ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS, 206 0.0f, 0.0f), 0); 207 root1->DispatchGestureEvent(&g1); 208 EXPECT_TRUE(v1->received_gesture_event()); 209 EXPECT_FALSE(v2->received_gesture_event()); 210 v1->Reset(); 211 v2->Reset(); 212 213 widget2->GetNativeView()->SetCapture(); 214 215 EXPECT_FALSE(widget1->GetNativeView()->HasCapture()); 216 EXPECT_TRUE(widget2->GetNativeView()->HasCapture()); 217 EXPECT_EQ(desktop_capture_client1->GetCaptureWindow(), 218 widget2->GetNativeView()); 219 EXPECT_EQ(desktop_capture_client2->GetCaptureWindow(), 220 widget2->GetNativeView()); 221 222 root2->DispatchGestureEvent(&g1); 223 EXPECT_TRUE(v2->received_gesture_event()); 224 EXPECT_FALSE(v1->received_gesture_event()); 225 226 widget1->CloseNow(); 227 widget2->CloseNow(); 228 RunPendingMessages(); 229 } 230 231 } // namespace views 232