Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc

Issue 1747803003: MacViews: Implement Tab Dragging (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix review issues. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h" 5 #include "chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
11 #include "ash/wm/window_state.h" 11 #include "ash/wm/window_state.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/callback.h" 13 #include "base/callback.h"
14 #include "base/command_line.h" 14 #include "base/command_line.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/run_loop.h" 16 #include "base/run_loop.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "chrome/browser/chrome_notification_types.h" 19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/platform_util.h"
20 #include "chrome/browser/ui/browser.h" 21 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_commands.h" 22 #include "chrome/browser/ui/browser_commands.h"
22 #include "chrome/browser/ui/browser_list.h" 23 #include "chrome/browser/ui/browser_list.h"
23 #include "chrome/browser/ui/browser_tabstrip.h" 24 #include "chrome/browser/ui/browser_tabstrip.h"
24 #include "chrome/browser/ui/tabs/tab_strip_model.h" 25 #include "chrome/browser/ui/tabs/tab_strip_model.h"
25 #include "chrome/browser/ui/views/frame/browser_view.h" 26 #include "chrome/browser/ui/views/frame/browser_view.h"
26 #include "chrome/browser/ui/views/frame/native_browser_frame_factory.h" 27 #include "chrome/browser/ui/views/frame/native_browser_frame_factory.h"
27 #include "chrome/browser/ui/views/tabs/tab.h" 28 #include "chrome/browser/ui/views/tabs/tab.h"
28 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h" 29 #include "chrome/browser/ui/views/tabs/tab_drag_controller.h"
29 #include "chrome/browser/ui/views/tabs/tab_strip.h" 30 #include "chrome/browser/ui/views/tabs/tab_strip.h"
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 } 175 }
175 176
176 Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() { 177 Browser* TabDragControllerTest::CreateAnotherWindowBrowserAndRelayout() {
177 // Create another browser. 178 // Create another browser.
178 Browser* browser2 = CreateBrowser(browser()->profile()); 179 Browser* browser2 = CreateBrowser(browser()->profile());
179 ResetIDs(browser2->tab_strip_model(), 100); 180 ResetIDs(browser2->tab_strip_model(), 100);
180 181
181 // Resize the two windows so they're right next to each other. 182 // Resize the two windows so they're right next to each other.
182 gfx::Rect work_area = 183 gfx::Rect work_area =
183 gfx::Screen::GetScreen() 184 gfx::Screen::GetScreen()
184 ->GetDisplayNearestWindow(browser()->window()->GetNativeWindow()) 185 ->GetDisplayNearestWindow(platform_util::GetViewForWindow(
186 browser()->window()->GetNativeWindow()))
185 .work_area(); 187 .work_area();
186 gfx::Size half_size = 188 gfx::Size half_size =
187 gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10); 189 gfx::Size(work_area.width() / 3 - 10, work_area.height() / 2 - 10);
188 browser()->window()->SetBounds(gfx::Rect(work_area.origin(), half_size)); 190 browser()->window()->SetBounds(gfx::Rect(work_area.origin(), half_size));
189 browser2->window()->SetBounds(gfx::Rect( 191 browser2->window()->SetBounds(gfx::Rect(
190 work_area.x() + half_size.width(), work_area.y(), 192 work_area.x() + half_size.width(), work_area.y(),
191 half_size.width(), half_size.height())); 193 half_size.width(), half_size.height()));
192 return browser2; 194 return browser2;
193 } 195 }
194 196
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 } 244 }
243 245
244 private: 246 private:
245 aura::Window* root_window_; 247 aura::Window* root_window_;
246 248
247 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate); 249 DISALLOW_COPY_AND_ASSIGN(ScreenEventGeneratorDelegate);
248 }; 250 };
249 251
250 #endif 252 #endif
251 253
252 #if !defined(OS_CHROMEOS) 254 #if !defined(OS_CHROMEOS) && defined(USE_AURA)
253 255
254 // Following classes verify a crash scenario. Specifically on Windows when focus 256 // Following classes verify a crash scenario. Specifically on Windows when focus
255 // changes it can trigger capture being lost. This was causing a crash in tab 257 // changes it can trigger capture being lost. This was causing a crash in tab
256 // dragging as it wasn't set up to handle this scenario. These classes 258 // dragging as it wasn't set up to handle this scenario. These classes
257 // synthesize this scenario. 259 // synthesize this scenario.
258 260
259 // Allows making ClearNativeFocus() invoke ReleaseCapture(). 261 // Allows making ClearNativeFocus() invoke ReleaseCapture().
260 class TestDesktopBrowserFrameAura : public DesktopBrowserFrameAura { 262 class TestDesktopBrowserFrameAura : public DesktopBrowserFrameAura {
261 public: 263 public:
262 TestDesktopBrowserFrameAura( 264 TestDesktopBrowserFrameAura(
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
855 #else 857 #else
856 #define MAYBE_DetachFromFullsizeWindow DetachFromFullsizeWindow 858 #define MAYBE_DetachFromFullsizeWindow DetachFromFullsizeWindow
857 #endif 859 #endif
858 // Tests that a tab can be dragged from a browser window that is resized to full 860 // Tests that a tab can be dragged from a browser window that is resized to full
859 // screen. 861 // screen.
860 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, 862 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
861 MAYBE_DetachFromFullsizeWindow) { 863 MAYBE_DetachFromFullsizeWindow) {
862 // Resize the browser window so that it is as big as the work area. 864 // Resize the browser window so that it is as big as the work area.
863 gfx::Rect work_area = 865 gfx::Rect work_area =
864 gfx::Screen::GetScreen() 866 gfx::Screen::GetScreen()
865 ->GetDisplayNearestWindow(browser()->window()->GetNativeWindow()) 867 ->GetDisplayNearestWindow(platform_util::GetViewForWindow(
868 browser()->window()->GetNativeWindow()))
866 .work_area(); 869 .work_area();
867 browser()->window()->SetBounds(work_area); 870 browser()->window()->SetBounds(work_area);
868 const gfx::Rect initial_bounds(browser()->window()->GetBounds()); 871 const gfx::Rect initial_bounds(browser()->window()->GetBounds());
869 // Add another tab. 872 // Add another tab.
870 AddTabAndResetBrowser(browser()); 873 AddTabAndResetBrowser(browser());
871 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 874 TabStrip* tab_strip = GetTabStripForBrowser(browser());
872 875
873 // Move to the first tab and drag it enough so that it detaches. 876 // Move to the first tab and drag it enough so that it detaches.
874 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 877 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
875 ASSERT_TRUE(PressInput(tab_0_center)); 878 ASSERT_TRUE(PressInput(tab_0_center));
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 #else 1218 #else
1216 #define MAYBE_DragAll DragAll 1219 #define MAYBE_DragAll DragAll
1217 #endif 1220 #endif
1218 // Selects multiple tabs and starts dragging the window. 1221 // Selects multiple tabs and starts dragging the window.
1219 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) { 1222 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, MAYBE_DragAll) {
1220 // Add another tab. 1223 // Add another tab.
1221 AddTabAndResetBrowser(browser()); 1224 AddTabAndResetBrowser(browser());
1222 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1225 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1223 browser()->tab_strip_model()->AddTabAtToSelection(0); 1226 browser()->tab_strip_model()->AddTabAtToSelection(0);
1224 browser()->tab_strip_model()->AddTabAtToSelection(1); 1227 browser()->tab_strip_model()->AddTabAtToSelection(1);
1228 const gfx::Rect initial_bounds = browser()->window()->GetBounds();
1225 1229
1226 // Move to the first tab and drag it enough so that it would normally 1230 // Move to the first tab and drag it enough so that it would normally
1227 // detach. 1231 // detach.
1228 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1232 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1229 ASSERT_TRUE(PressInput(tab_0_center)); 1233 ASSERT_TRUE(PressInput(tab_0_center));
1230 ASSERT_TRUE(DragInputToNotifyWhenDone( 1234 ASSERT_TRUE(DragInputToNotifyWhenDone(
1231 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1235 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1232 base::Bind(&DragAllStep2, this, browser_list))); 1236 base::Bind(&DragAllStep2, this, browser_list)));
1233 QuitWhenNotDragging(); 1237 QuitWhenNotDragging();
1234 1238
1235 // Should not be dragging. 1239 // Should not be dragging.
1236 ASSERT_FALSE(tab_strip->IsDragSessionActive()); 1240 ASSERT_FALSE(tab_strip->IsDragSessionActive());
1237 ASSERT_FALSE(TabDragController::IsActive()); 1241 ASSERT_FALSE(TabDragController::IsActive());
1238 1242
1239 // And there should only be one window. 1243 // And there should only be one window.
1240 EXPECT_EQ(1u, browser_list->size()); 1244 EXPECT_EQ(1u, browser_list->size());
1241 1245
1242 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model())); 1246 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1243 1247
1244 EXPECT_FALSE(GetIsDragged(browser())); 1248 EXPECT_FALSE(GetIsDragged(browser()));
1245 1249
1246 // Remaining browser window should not be maximized 1250 // Remaining browser window should not be maximized
1247 EXPECT_FALSE(browser()->window()->IsMaximized()); 1251 EXPECT_FALSE(browser()->window()->IsMaximized());
1252
1253 const gfx::Rect final_bounds = browser()->window()->GetBounds();
1254 EXPECT_EQ(initial_bounds.size(), final_bounds.size());
1255 EXPECT_EQ(initial_bounds.origin().x(), final_bounds.origin().x());
1256 EXPECT_EQ(initial_bounds.origin().y() + GetDetachY(tab_strip),
1257 final_bounds.origin().y());
1248 } 1258 }
1249 1259
1260 #if defined(OS_MACOSX)
1261 // Makes sure we can drag the window using WindowServer by dragging on a tab.
1262 //
1263 // All other tests move the windows without relying on the WindowServer, because
1264 // BridgedNativeWidget::RunMoveLoop() immediately offsets the window on first
1265 // mouse drag. If we generate more mouse move events after that, it's presumed
1266 // that the WindowServer will move the window. In order for that to work we need
1267 // to generate global CGEvents instead of app-specific NSEvents, that's what
1268 // ui_test_utils::DragAndDrop() is for.
1269 //
1270 // If the WindowServer fails to move the window, the final window bounds won't
1271 // match the expected ones.
1272 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1273 MacDragsWindowUsingCocoaMoveLoop) {
1274 // Add another tab.
1275 AddTabAndResetBrowser(browser());
1276
1277 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1278 browser()->tab_strip_model()->AddTabAtToSelection(0);
1279 browser()->tab_strip_model()->AddTabAtToSelection(1);
1280 const gfx::Rect initial_bounds = browser()->window()->GetBounds();
1281
1282 // Move to the first tab and drag it enough so that it would normally
1283 // detach.
1284 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1285
1286 // If we don't make the interactive_ui_tests the active application, we won't
1287 // be able to monitor NSMouseMoved events and ui_test_utils::DragAndDrop()
1288 // will deadlock.
1289 EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
1290
1291 // We need to move the window using multiple intermediate events in order
1292 // to verify that CocoaWindowMoveLoop is working correctly.
1293 const int steps = 10;
1294 ui_test_utils::DragAndDrop(
1295 tab_0_center,
1296 gfx::Point(tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip)),
1297 steps);
1298
1299 // Should not be dragging.
1300 EXPECT_FALSE(tab_strip->IsDragSessionActive());
1301 EXPECT_FALSE(TabDragController::IsActive());
1302 EXPECT_FALSE(GetIsDragged(browser()));
1303
1304 // And there should only be one window.
1305 EXPECT_EQ(1u, browser_list->size());
1306 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1307
1308 // Remaining browser window should not be maximized
1309 EXPECT_FALSE(browser()->window()->IsMaximized());
1310
1311 const gfx::Rect final_bounds = browser()->window()->GetBounds();
1312 EXPECT_EQ(initial_bounds.size(), final_bounds.size());
1313 EXPECT_EQ(initial_bounds.origin().x(), final_bounds.origin().x());
1314 EXPECT_EQ(initial_bounds.origin().y() + GetDetachY(tab_strip),
1315 final_bounds.origin().y());
1316 }
1317
1318 // Tests that when the first mouse event that starts RunMoveLoop does not
1319 // overlap the Mac menu bar. BridgedNativeWidget::RunMoveLoop() shifts both the
1320 // mouse position and the expected window frame after detachment.
1321 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1322 MacDetachesWindowOnTopOfMacMenuBar) {
1323 // Add another tab.
1324 AddTabAndResetBrowser(browser());
1325
1326 // Make sure there's enough space to trigger detachment.
1327 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1328 browser()->window()->SetBounds(gfx::Rect(100, 100, 400, 200));
1329 DCHECK_GT(browser()->window()->GetBounds().y(), GetDetachY(tab_strip));
1330
1331 // If we don't make the interactive_ui_tests the active application, we won't
1332 // be able to monitor NSMouseMoved events and ui_test_utils::DragAndDrop()
1333 // will deadlock.
1334 EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
1335
1336 gfx::Point tab_0_center(GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1337 gfx::Point on_top_of_menu_bar(tab_0_center.x(), 0);
1338 ui_test_utils::DragAndDrop(tab_0_center, on_top_of_menu_bar);
1339
1340 // Should not be dragging.
1341 EXPECT_FALSE(tab_strip->IsDragSessionActive());
1342 EXPECT_FALSE(TabDragController::IsActive());
1343 EXPECT_FALSE(GetIsDragged(browser()));
1344
1345 // Second tab should successfully detach.
1346 EXPECT_EQ(2u, browser_list->size());
1347 EXPECT_EQ("1", IDString(browser()->tab_strip_model()));
1348 }
1349
1350 // Detaches and reattaches second tab. Will fail if detached window is not moved
1351 // synchronously at the start of BridgedNativeWidget::RunMoveLoop(): the check
1352 // for expected WindowServerFrame() will fail.
1353 IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest,
1354 MacDetachesAndReattachesSecondTab) {
1355 using namespace ui_test_utils;
1356
1357 // Add another tab.
1358 AddTabAndResetBrowser(browser());
1359
1360 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1361 browser()->window()->SetBounds(gfx::Rect(100, 100, 400, 200));
1362 const gfx::Rect initial_bounds = browser()->window()->GetBounds();
1363
1364 gfx::Point tab_1_center(GetCenterInScreenCoordinates(tab_strip->tab_at(1)));
1365 gfx::Point tab_1_shake(tab_1_center.x(),
1366 tab_1_center.y() + GetDetachY(tab_strip) * 2);
1367
1368 // If we don't make the interactive_ui_tests the active application, we won't
1369 // be able to monitor NSMouseMoved events and ui_test_utils::DragAndDrop()
1370 // will deadlock.
1371 EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
1372
1373 std::list<DragAndDropOperation> operations;
1374 operations.emplace_back(DragAndDropOperation::Move(tab_1_center));
1375 operations.emplace_back(DragAndDropOperation::MouseDown());
1376 operations.emplace_back(DragAndDropOperation::Move(tab_1_shake));
1377 operations.emplace_back(DragAndDropOperation::Move(tab_1_center));
1378 operations.emplace_back(DragAndDropOperation::MouseUp());
1379
1380 ui_test_utils::DragAndDrop(operations);
1381
1382 // Should not be dragging.
1383 EXPECT_FALSE(tab_strip->IsDragSessionActive());
1384 EXPECT_FALSE(TabDragController::IsActive());
1385 EXPECT_FALSE(GetIsDragged(browser()));
1386
1387 // And there should only be one window.
1388 EXPECT_EQ(1u, browser_list->size());
1389 EXPECT_EQ("0 1", IDString(browser()->tab_strip_model()));
1390
1391 // The window should remain in its original place.
1392 const gfx::Rect final_bounds = browser()->window()->GetBounds();
1393 EXPECT_EQ(initial_bounds, final_bounds);
1394 }
1395 #endif // OS_MACOSX
1396
1250 namespace { 1397 namespace {
1251 1398
1252 // Invoked from the nested message loop. 1399 // Invoked from the nested message loop.
1253 void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test, 1400 void DragAllToSeparateWindowStep2(DetachToBrowserTabDragControllerTest* test,
1254 TabStrip* attached_tab_strip, 1401 TabStrip* attached_tab_strip,
1255 TabStrip* target_tab_strip, 1402 TabStrip* target_tab_strip,
1256 const BrowserList* browser_list) { 1403 const BrowserList* browser_list) {
1257 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive()); 1404 ASSERT_TRUE(attached_tab_strip->IsDragSessionActive());
1258 ASSERT_FALSE(target_tab_strip->IsDragSessionActive()); 1405 ASSERT_FALSE(target_tab_strip->IsDragSessionActive());
1259 ASSERT_TRUE(TabDragController::IsActive()); 1406 ASSERT_TRUE(TabDragController::IsActive());
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
1468 MAYBE_DragSingleTabToSeparateWindow) { 1615 MAYBE_DragSingleTabToSeparateWindow) {
1469 TabStrip* tab_strip = GetTabStripForBrowser(browser()); 1616 TabStrip* tab_strip = GetTabStripForBrowser(browser());
1470 1617
1471 ResetIDs(browser()->tab_strip_model(), 0); 1618 ResetIDs(browser()->tab_strip_model(), 0);
1472 1619
1473 // Create another browser. 1620 // Create another browser.
1474 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout(); 1621 Browser* browser2 = CreateAnotherWindowBrowserAndRelayout();
1475 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2); 1622 TabStrip* tab_strip2 = GetTabStripForBrowser(browser2);
1476 const gfx::Rect initial_bounds(browser2->window()->GetBounds()); 1623 const gfx::Rect initial_bounds(browser2->window()->GetBounds());
1477 1624
1625 EXPECT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
1626
1478 // Move to the first tab and drag it enough so that it detaches, but not 1627 // Move to the first tab and drag it enough so that it detaches, but not
1479 // enough that it attaches to browser2. 1628 // enough that it attaches to browser2.
1480 gfx::Point tab_0_center( 1629 gfx::Point tab_0_center(
1481 GetCenterInScreenCoordinates(tab_strip->tab_at(0))); 1630 GetCenterInScreenCoordinates(tab_strip->tab_at(0)));
1482 ASSERT_TRUE(PressInput(tab_0_center)); 1631 ASSERT_TRUE(PressInput(tab_0_center));
1483 ASSERT_TRUE(DragInputToNotifyWhenDone( 1632 ASSERT_TRUE(DragInputToNotifyWhenDone(
1484 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip), 1633 tab_0_center.x(), tab_0_center.y() + GetDetachY(tab_strip),
1485 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2, 1634 base::Bind(&DragAllToSeparateWindowStep2, this, tab_strip, tab_strip2,
1486 browser_list))); 1635 browser_list)));
1487 QuitWhenNotDragging(); 1636 QuitWhenNotDragging();
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after
2411 DetachToBrowserTabDragControllerTest, 2560 DetachToBrowserTabDragControllerTest,
2412 ::testing::Values("mouse", "touch")); 2561 ::testing::Values("mouse", "touch"));
2413 INSTANTIATE_TEST_CASE_P(TabDragging, 2562 INSTANTIATE_TEST_CASE_P(TabDragging,
2414 DetachToBrowserTabDragControllerTestTouch, 2563 DetachToBrowserTabDragControllerTestTouch,
2415 ::testing::Values("touch")); 2564 ::testing::Values("touch"));
2416 #else 2565 #else
2417 INSTANTIATE_TEST_CASE_P(TabDragging, 2566 INSTANTIATE_TEST_CASE_P(TabDragging,
2418 DetachToBrowserTabDragControllerTest, 2567 DetachToBrowserTabDragControllerTest,
2419 ::testing::Values("mouse")); 2568 ::testing::Values("mouse"));
2420 #endif 2569 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698