| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "services/ui/ws/window_tree.h" | 5 #include "services/ui/ws/window_tree.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 126 | 126 |
| 127 class WindowTreeTest : public testing::Test { | 127 class WindowTreeTest : public testing::Test { |
| 128 public: | 128 public: |
| 129 WindowTreeTest() {} | 129 WindowTreeTest() {} |
| 130 ~WindowTreeTest() override {} | 130 ~WindowTreeTest() override {} |
| 131 | 131 |
| 132 ui::mojom::Cursor cursor_id() { | 132 ui::mojom::Cursor cursor_id() { |
| 133 return window_event_targeting_helper_.cursor(); | 133 return window_event_targeting_helper_.cursor(); |
| 134 } | 134 } |
| 135 Display* display() { return window_event_targeting_helper_.display(); } | 135 Display* display() { return window_event_targeting_helper_.display(); } |
| 136 TestWindowTreeBinding* last_binding() { | |
| 137 return window_event_targeting_helper_.last_binding(); | |
| 138 } | |
| 139 TestWindowTreeClient* last_window_tree_client() { | 136 TestWindowTreeClient* last_window_tree_client() { |
| 140 return window_event_targeting_helper_.last_window_tree_client(); | 137 return window_event_targeting_helper_.last_window_tree_client(); |
| 141 } | 138 } |
| 142 TestWindowTreeClient* wm_client() { | 139 TestWindowTreeClient* wm_client() { |
| 143 return window_event_targeting_helper_.wm_client(); | 140 return window_event_targeting_helper_.wm_client(); |
| 144 } | 141 } |
| 145 WindowServer* window_server() { | 142 WindowServer* window_server() { |
| 146 return window_event_targeting_helper_.window_server(); | 143 return window_event_targeting_helper_.window_server(); |
| 147 } | 144 } |
| 148 WindowTree* wm_tree() { | 145 WindowTree* wm_tree() { |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 469 TEST_F(WindowTreeTest, CursorChangesWhenMouseOverWindowAndWindowSetsCursor) { | 466 TEST_F(WindowTreeTest, CursorChangesWhenMouseOverWindowAndWindowSetsCursor) { |
| 470 TestWindowTreeClient* embed_client = nullptr; | 467 TestWindowTreeClient* embed_client = nullptr; |
| 471 WindowTree* tree = nullptr; | 468 WindowTree* tree = nullptr; |
| 472 ServerWindow* window = nullptr; | 469 ServerWindow* window = nullptr; |
| 473 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); | 470 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); |
| 474 | 471 |
| 475 // Like in BasicInputEventTarget, we send a pointer down event to be | 472 // Like in BasicInputEventTarget, we send a pointer down event to be |
| 476 // dispatched. This is only to place the mouse cursor over that window though. | 473 // dispatched. This is only to place the mouse cursor over that window though. |
| 477 DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); | 474 DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); |
| 478 | 475 |
| 479 window->SetPredefinedCursor(mojom::Cursor::IBEAM); | 476 // Set the cursor on the parent as that is where the cursor is picked up from. |
| 477 window->parent()->SetPredefinedCursor(mojom::Cursor::IBEAM); |
| 480 | 478 |
| 481 // Because the cursor is over the window when SetCursor was called, we should | 479 // Because the cursor is over the window when SetCursor was called, we should |
| 482 // have immediately changed the cursor. | 480 // have immediately changed the cursor. |
| 483 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); | 481 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 484 } | 482 } |
| 485 | 483 |
| 486 TEST_F(WindowTreeTest, CursorChangesWhenEnteringWindowWithDifferentCursor) { | 484 TEST_F(WindowTreeTest, CursorChangesWhenEnteringWindowWithDifferentCursor) { |
| 487 TestWindowTreeClient* embed_client = nullptr; | 485 TestWindowTreeClient* embed_client = nullptr; |
| 488 WindowTree* tree = nullptr; | 486 WindowTree* tree = nullptr; |
| 489 ServerWindow* window = nullptr; | 487 ServerWindow* window = nullptr; |
| 490 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); | 488 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); |
| 491 | 489 |
| 492 // Let's create a pointer event outside the window and then move the pointer | 490 // Let's create a pointer event outside the window and then move the pointer |
| 493 // inside. | 491 // inside. |
| 494 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); | 492 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); |
| 495 window->SetPredefinedCursor(mojom::Cursor::IBEAM); | 493 // Set the cursor on the parent as that is where the cursor is picked up from. |
| 494 window->parent()->SetPredefinedCursor(mojom::Cursor::IBEAM); |
| 496 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); | 495 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); |
| 497 | 496 |
| 498 DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); | 497 DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); |
| 499 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); | 498 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 500 } | 499 } |
| 501 | 500 |
| 502 TEST_F(WindowTreeTest, TouchesDontChangeCursor) { | 501 TEST_F(WindowTreeTest, TouchesDontChangeCursor) { |
| 503 TestWindowTreeClient* embed_client = nullptr; | 502 TestWindowTreeClient* embed_client = nullptr; |
| 504 WindowTree* tree = nullptr; | 503 WindowTree* tree = nullptr; |
| 505 ServerWindow* window = nullptr; | 504 ServerWindow* window = nullptr; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 518 | 517 |
| 519 TEST_F(WindowTreeTest, DragOutsideWindow) { | 518 TEST_F(WindowTreeTest, DragOutsideWindow) { |
| 520 TestWindowTreeClient* embed_client = nullptr; | 519 TestWindowTreeClient* embed_client = nullptr; |
| 521 WindowTree* tree = nullptr; | 520 WindowTree* tree = nullptr; |
| 522 ServerWindow* window = nullptr; | 521 ServerWindow* window = nullptr; |
| 523 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); | 522 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); |
| 524 | 523 |
| 525 // Start with the cursor outside the window. Setting the cursor shouldn't | 524 // Start with the cursor outside the window. Setting the cursor shouldn't |
| 526 // change the cursor. | 525 // change the cursor. |
| 527 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); | 526 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); |
| 528 window->SetPredefinedCursor(mojom::Cursor::IBEAM); | 527 // Set the cursor on the parent as that is where the cursor is picked up from. |
| 528 window->parent()->SetPredefinedCursor(mojom::Cursor::IBEAM); |
| 529 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); | 529 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); |
| 530 | 530 |
| 531 // Move the pointer to the inside of the window | 531 // Move the pointer to the inside of the window |
| 532 DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); | 532 DispatchEventAndAckImmediately(CreateMouseMoveEvent(21, 22)); |
| 533 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); | 533 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 534 | 534 |
| 535 // Start the drag. | 535 // Start the drag. |
| 536 DispatchEventAndAckImmediately(CreateMouseDownEvent(21, 22)); | 536 DispatchEventAndAckImmediately(CreateMouseDownEvent(21, 22)); |
| 537 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); | 537 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 538 | 538 |
| 539 // Move the cursor (mouse is still down) outside the window. | 539 // Move the cursor (mouse is still down) outside the window. |
| 540 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); | 540 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); |
| 541 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); | 541 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 542 | 542 |
| 543 // Release the cursor. We should now adapt the cursor of the window | 543 // Release the cursor. We should now adapt the cursor of the window |
| 544 // underneath the pointer. | 544 // underneath the pointer. |
| 545 DispatchEventAndAckImmediately(CreateMouseUpEvent(5, 5)); | 545 DispatchEventAndAckImmediately(CreateMouseUpEvent(5, 5)); |
| 546 EXPECT_EQ(mojom::Cursor::CURSOR_NULL, cursor_id()); | 546 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); |
| 547 } | 547 } |
| 548 | 548 |
| 549 TEST_F(WindowTreeTest, ChangingWindowBoundsChangesCursor) { | 549 TEST_F(WindowTreeTest, ChangingWindowBoundsChangesCursor) { |
| 550 TestWindowTreeClient* embed_client = nullptr; | 550 TestWindowTreeClient* embed_client = nullptr; |
| 551 WindowTree* tree = nullptr; | 551 WindowTree* tree = nullptr; |
| 552 ServerWindow* window = nullptr; | 552 ServerWindow* window = nullptr; |
| 553 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); | 553 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window)); |
| 554 | 554 |
| 555 // Put the cursor just outside the bounds of the window. | 555 // Put the cursor just outside the bounds of the window. |
| 556 DispatchEventAndAckImmediately(CreateMouseMoveEvent(41, 41)); | 556 DispatchEventAndAckImmediately(CreateMouseMoveEvent(41, 41)); |
| 557 window->SetPredefinedCursor(mojom::Cursor::IBEAM); | 557 // Sets the cursor on the root as that is where the cursor is picked up from. |
| 558 window->parent()->SetPredefinedCursor(mojom::Cursor::IBEAM); |
| 558 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); | 559 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); |
| 559 | 560 |
| 560 // Expand the bounds of the window so they now include where the cursor now | 561 // Expand the bounds of the window so they now include where the cursor now |
| 561 // is. | 562 // is. |
| 562 window->SetBounds(gfx::Rect(20, 20, 25, 25)); | 563 window->SetBounds(gfx::Rect(20, 20, 25, 25)); |
| 563 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); | 564 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 564 | 565 |
| 565 // Contract the bounds again. | 566 // Contract the bounds again. |
| 566 window->SetBounds(gfx::Rect(20, 20, 20, 20)); | 567 window->SetBounds(gfx::Rect(20, 20, 20, 20)); |
| 567 EXPECT_EQ(mojom::Cursor::CURSOR_NULL, cursor_id()); | 568 EXPECT_EQ(mojom::Cursor::POINTER, cursor_id()); |
| 568 } | 569 } |
| 569 | 570 |
| 570 TEST_F(WindowTreeTest, WindowReorderingChangesCursor) { | 571 TEST_F(WindowTreeTest, WindowReorderingChangesCursor) { |
| 571 TestWindowTreeClient* embed_client = nullptr; | 572 // Setup two trees parented to the root with the same bounds. |
| 572 WindowTree* tree = nullptr; | 573 ServerWindow* embed_window1 = |
| 573 ServerWindow* window1 = nullptr; | 574 window_event_targeting_helper_.CreatePrimaryTree( |
| 574 EXPECT_NO_FATAL_FAILURE(SetupEventTargeting(&embed_client, &tree, &window1)); | 575 gfx::Rect(0, 0, 200, 200), gfx::Rect(0, 0, 50, 50)); |
| 576 ServerWindow* embed_window2 = |
| 577 window_event_targeting_helper_.CreatePrimaryTree( |
| 578 gfx::Rect(0, 0, 200, 200), gfx::Rect(0, 0, 50, 50)); |
| 575 | 579 |
| 576 // Create a second window right over the first. | 580 ASSERT_EQ(embed_window1->parent(), embed_window2->parent()); |
| 577 const ClientWindowId embed_window_id(FirstRootId(tree)); | 581 embed_window1->set_event_targeting_policy( |
| 578 const ClientWindowId child2_id(BuildClientWindowId(tree, 2)); | 582 mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); |
| 579 EXPECT_TRUE(tree->NewWindow(child2_id, ServerWindow::Properties())); | 583 embed_window2->set_event_targeting_policy( |
| 580 ServerWindow* child2 = tree->GetWindowByClientId(child2_id); | 584 mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); |
| 581 ASSERT_TRUE(child2); | 585 embed_window1->SetPredefinedCursor(mojom::Cursor::IBEAM); |
| 582 EXPECT_TRUE(tree->AddWindow(embed_window_id, child2_id)); | 586 embed_window2->SetPredefinedCursor(mojom::Cursor::CROSS); |
| 583 child2->SetVisible(true); | 587 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); |
| 584 child2->SetBounds(gfx::Rect(20, 20, 20, 20)); | 588 // Cursor should match that of top-most window, which is |embed_window2|. |
| 585 | 589 EXPECT_EQ(mojom::Cursor::CROSS, cursor_id()); |
| 586 // Give each window a different cursor. | 590 // Move |embed_window1| on top, cursor should now match it. |
| 587 window1->SetPredefinedCursor(mojom::Cursor::IBEAM); | 591 embed_window1->parent()->StackChildAtTop(embed_window1); |
| 588 child2->SetPredefinedCursor(mojom::Cursor::HAND); | |
| 589 | |
| 590 // We expect window2 to be over window1 now. | |
| 591 DispatchEventAndAckImmediately(CreateMouseMoveEvent(22, 22)); | |
| 592 EXPECT_EQ(mojom::Cursor::HAND, cursor_id()); | |
| 593 | |
| 594 // But when we put window2 at the bottom, we should adapt window1's cursor. | |
| 595 child2->parent()->StackChildAtBottom(child2); | |
| 596 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); | 592 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 597 } | 593 } |
| 598 | 594 |
| 595 // Assertions around moving cursor between trees with roots. |
| 596 TEST_F(WindowTreeTest, CursorMultipleTrees) { |
| 597 // Setup two trees parented to the root with the same bounds. |
| 598 ServerWindow* embed_window1 = |
| 599 window_event_targeting_helper_.CreatePrimaryTree( |
| 600 gfx::Rect(0, 0, 200, 200), gfx::Rect(0, 0, 10, 10)); |
| 601 ServerWindow* embed_window2 = |
| 602 window_event_targeting_helper_.CreatePrimaryTree( |
| 603 gfx::Rect(0, 0, 200, 200), gfx::Rect(20, 20, 20, 20)); |
| 604 embed_window1->set_event_targeting_policy( |
| 605 mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); |
| 606 embed_window2->set_event_targeting_policy( |
| 607 mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); |
| 608 embed_window2->parent()->set_event_targeting_policy( |
| 609 mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS); |
| 610 embed_window1->SetPredefinedCursor(mojom::Cursor::IBEAM); |
| 611 embed_window2->SetPredefinedCursor(mojom::Cursor::CROSS); |
| 612 embed_window1->parent()->SetPredefinedCursor(mojom::Cursor::COPY); |
| 613 |
| 614 // Create a child of |embed_window1|. |
| 615 ServerWindow* embed_window1_child = NewWindowInTreeWithParent( |
| 616 window_server()->GetTreeWithRoot(embed_window1), embed_window1); |
| 617 ASSERT_TRUE(embed_window1_child); |
| 618 embed_window1_child->SetBounds(gfx::Rect(0, 0, 10, 10)); |
| 619 embed_window1_child->SetVisible(true); |
| 620 |
| 621 // Move mouse into |embed_window1|. |
| 622 DispatchEventAndAckImmediately(CreateMouseMoveEvent(5, 5)); |
| 623 EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); |
| 624 |
| 625 // Move mouse into |embed_window2|. |
| 626 DispatchEventAndAckImmediately(CreateMouseMoveEvent(25, 25)); |
| 627 EXPECT_EQ(mojom::Cursor::CROSS, cursor_id()); |
| 628 |
| 629 // Move mouse into area between, which should use cursor set on parent. |
| 630 DispatchEventAndAckImmediately(CreateMouseMoveEvent(15, 15)); |
| 631 EXPECT_EQ(mojom::Cursor::COPY, cursor_id()); |
| 632 } |
| 633 |
| 599 TEST_F(WindowTreeTest, EventAck) { | 634 TEST_F(WindowTreeTest, EventAck) { |
| 600 const ClientWindowId embed_window_id = BuildClientWindowId(wm_tree(), 1); | 635 const ClientWindowId embed_window_id = BuildClientWindowId(wm_tree(), 1); |
| 601 EXPECT_TRUE( | 636 EXPECT_TRUE( |
| 602 wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); | 637 wm_tree()->NewWindow(embed_window_id, ServerWindow::Properties())); |
| 603 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id, true)); | 638 EXPECT_TRUE(wm_tree()->SetWindowVisibility(embed_window_id, true)); |
| 604 ASSERT_TRUE(FirstRoot(wm_tree())); | 639 ASSERT_TRUE(FirstRoot(wm_tree())); |
| 605 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id)); | 640 EXPECT_TRUE(wm_tree()->AddWindow(FirstRootId(wm_tree()), embed_window_id)); |
| 606 ASSERT_EQ(1u, display()->root_window()->children().size()); | 641 ASSERT_EQ(1u, display()->root_window()->children().size()); |
| 607 ServerWindow* wm_root = FirstRoot(wm_tree()); | 642 ServerWindow* wm_root = FirstRoot(wm_tree()); |
| 608 ASSERT_TRUE(wm_root); | 643 ASSERT_TRUE(wm_root); |
| (...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1387 client->tracker()->changes()->clear(); | 1422 client->tracker()->changes()->clear(); |
| 1388 } | 1423 } |
| 1389 | 1424 |
| 1390 // Client should not have got any messages after shutdown. | 1425 // Client should not have got any messages after shutdown. |
| 1391 EXPECT_TRUE(client->tracker()->changes()->empty()); | 1426 EXPECT_TRUE(client->tracker()->changes()->empty()); |
| 1392 } | 1427 } |
| 1393 | 1428 |
| 1394 } // namespace test | 1429 } // namespace test |
| 1395 } // namespace ws | 1430 } // namespace ws |
| 1396 } // namespace ui | 1431 } // namespace ui |
| OLD | NEW |