| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "services/ui/ws/user_display_manager.h" |
| |
| #include <stdint.h> |
| |
| #include <string> |
| |
| #include "base/macros.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "mojo/public/cpp/bindings/binding.h" |
| #include "mojo/public/cpp/bindings/interface_request.h" |
| #include "services/ui/common/task_runner_test_base.h" |
| #include "services/ui/common/types.h" |
| #include "services/ui/common/util.h" |
| #include "services/ui/display/screen_manager.h" |
| #include "services/ui/ws/display_manager.h" |
| #include "services/ui/ws/ids.h" |
| #include "services/ui/ws/server_window.h" |
| #include "services/ui/ws/test_utils.h" |
| #include "services/ui/ws/window_manager_state.h" |
| #include "services/ui/ws/window_manager_window_tree_factory_set.h" |
| #include "services/ui/ws/window_server.h" |
| #include "services/ui/ws/window_server_delegate.h" |
| #include "services/ui/ws/window_tree.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/geometry/rect.h" |
| |
| namespace ui { |
| namespace ws { |
| namespace test { |
| namespace { |
| |
| const char kUserId1[] = "123"; |
| |
| class TestDisplayManagerObserver : public mojom::DisplayManagerObserver { |
| public: |
| TestDisplayManagerObserver() : binding_(this) {} |
| ~TestDisplayManagerObserver() override {} |
| |
| mojom::DisplayManagerObserverPtr GetPtr() { |
| return binding_.CreateInterfacePtrAndBind(); |
| } |
| |
| std::string GetAndClearObserverCalls() { |
| std::string result; |
| std::swap(observer_calls_, result); |
| return result; |
| } |
| |
| private: |
| void AddCall(const std::string& call) { |
| if (!observer_calls_.empty()) |
| observer_calls_ += "\n"; |
| observer_calls_ += call; |
| } |
| |
| std::string DisplayIdsToString( |
| const std::vector<mojom::WsDisplayPtr>& wm_displays) { |
| std::string display_ids; |
| for (const auto& wm_display : wm_displays) { |
| if (!display_ids.empty()) |
| display_ids += " "; |
| display_ids += base::Int64ToString(wm_display->display.id()); |
| } |
| return display_ids; |
| } |
| |
| // mojom::DisplayManagerObserver: |
| void OnDisplays(std::vector<mojom::WsDisplayPtr> displays, |
| int64_t primary_display_id, |
| int64_t internal_display_id) override { |
| AddCall("OnDisplays " + DisplayIdsToString(displays)); |
| } |
| void OnDisplaysChanged(std::vector<mojom::WsDisplayPtr> displays) override { |
| AddCall("OnDisplaysChanged " + DisplayIdsToString(displays)); |
| } |
| void OnDisplayRemoved(int64_t id) override { |
| AddCall("OnDisplayRemoved " + base::Int64ToString(id)); |
| } |
| void OnPrimaryDisplayChanged(int64_t id) override { |
| AddCall("OnPrimaryDisplayChanged " + base::Int64ToString(id)); |
| } |
| |
| mojo::Binding<mojom::DisplayManagerObserver> binding_; |
| std::string observer_calls_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestDisplayManagerObserver); |
| }; |
| |
| mojom::FrameDecorationValuesPtr CreateDefaultFrameDecorationValues() { |
| return mojom::FrameDecorationValues::New(); |
| } |
| |
| } // namespace |
| |
| // ----------------------------------------------------------------------------- |
| |
| class UserDisplayManagerTest : public TaskRunnerTestBase { |
| public: |
| UserDisplayManagerTest() {} |
| ~UserDisplayManagerTest() override {} |
| |
| WindowServer* window_server() { return ws_test_helper_.window_server(); } |
| TestWindowServerDelegate* window_server_delegate() { |
| return ws_test_helper_.window_server_delegate(); |
| } |
| |
| TestScreenManager& screen_manager() { return screen_manager_; } |
| |
| private: |
| // testing::Test: |
| void SetUp() override { |
| TaskRunnerTestBase::SetUp(); |
| screen_manager_.Init(window_server()->display_manager()); |
| } |
| |
| WindowServerTestHelper ws_test_helper_; |
| TestScreenManager screen_manager_; |
| DISALLOW_COPY_AND_ASSIGN(UserDisplayManagerTest); |
| }; |
| |
| TEST_F(UserDisplayManagerTest, OnlyNotifyWhenFrameDecorationsSet) { |
| screen_manager().AddDisplay(); |
| |
| TestDisplayManagerObserver display_manager_observer1; |
| DisplayManager* display_manager = window_server()->display_manager(); |
| AddWindowManager(window_server(), kUserId1); |
| UserDisplayManager* user_display_manager1 = |
| display_manager->GetUserDisplayManager(kUserId1); |
| ASSERT_TRUE(user_display_manager1); |
| user_display_manager1->AddObserver(display_manager_observer1.GetPtr()); |
| RunUntilIdle(); |
| |
| // Observer should not have been notified yet. |
| EXPECT_EQ(std::string(), |
| display_manager_observer1.GetAndClearObserverCalls()); |
| |
| // Set the frame decoration values, which should trigger sending immediately. |
| ASSERT_EQ(1u, display_manager->displays().size()); |
| window_server() |
| ->window_manager_window_tree_factory_set() |
| ->GetWindowManagerStateForUser(kUserId1) |
| ->SetFrameDecorationValues(CreateDefaultFrameDecorationValues()); |
| RunUntilIdle(); |
| |
| EXPECT_EQ("OnDisplays 1", |
| display_manager_observer1.GetAndClearObserverCalls()); |
| } |
| |
| TEST_F(UserDisplayManagerTest, AddObserverAfterFrameDecorationsSet) { |
| screen_manager().AddDisplay(); |
| |
| TestDisplayManagerObserver display_manager_observer1; |
| DisplayManager* display_manager = window_server()->display_manager(); |
| AddWindowManager(window_server(), kUserId1); |
| UserDisplayManager* user_display_manager1 = |
| display_manager->GetUserDisplayManager(kUserId1); |
| ASSERT_TRUE(user_display_manager1); |
| ASSERT_EQ(1u, display_manager->displays().size()); |
| window_server() |
| ->window_manager_window_tree_factory_set() |
| ->GetWindowManagerStateForUser(kUserId1) |
| ->SetFrameDecorationValues(CreateDefaultFrameDecorationValues()); |
| |
| user_display_manager1->AddObserver(display_manager_observer1.GetPtr()); |
| RunUntilIdle(); |
| |
| EXPECT_EQ("OnDisplays 1", |
| display_manager_observer1.GetAndClearObserverCalls()); |
| } |
| |
| TEST_F(UserDisplayManagerTest, AddRemoveDisplay) { |
| screen_manager().AddDisplay(); |
| |
| TestDisplayManagerObserver display_manager_observer1; |
| DisplayManager* display_manager = window_server()->display_manager(); |
| AddWindowManager(window_server(), kUserId1); |
| UserDisplayManager* user_display_manager1 = |
| display_manager->GetUserDisplayManager(kUserId1); |
| ASSERT_TRUE(user_display_manager1); |
| ASSERT_EQ(1u, display_manager->displays().size()); |
| window_server() |
| ->window_manager_window_tree_factory_set() |
| ->GetWindowManagerStateForUser(kUserId1) |
| ->SetFrameDecorationValues(CreateDefaultFrameDecorationValues()); |
| user_display_manager1->AddObserver(display_manager_observer1.GetPtr()); |
| RunUntilIdle(); |
| |
| EXPECT_EQ("OnDisplays 1", |
| display_manager_observer1.GetAndClearObserverCalls()); |
| |
| // Add another display. |
| const int64_t second_display_id = screen_manager().AddDisplay(); |
| RunUntilIdle(); |
| |
| // Observer should be notified immediately as frame decorations were set. |
| EXPECT_EQ("OnDisplaysChanged 2", |
| display_manager_observer1.GetAndClearObserverCalls()); |
| |
| // Remove the display and verify observer is notified. |
| screen_manager().RemoveDisplay(second_display_id); |
| RunUntilIdle(); |
| |
| EXPECT_EQ("OnDisplayRemoved 2", |
| display_manager_observer1.GetAndClearObserverCalls()); |
| } |
| |
| } // namespace test |
| } // namespace ws |
| } // namespace ui |