diff options
author | sky <sky@chromium.org> | 2016-01-27 16:13:32 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-28 00:14:46 +0000 |
commit | 77009e2d52f6c4214f1616d2b4840abfa7de6eba (patch) | |
tree | ac09e0159fc5247134926308428e7f05d1e13c20 /components/mus | |
parent | ea1df789e1afcf57a69769b4c4a1d9ef09d112ed (diff) | |
download | chromium_src-77009e2d52f6c4214f1616d2b4840abfa7de6eba.zip chromium_src-77009e2d52f6c4214f1616d2b4840abfa7de6eba.tar.gz chromium_src-77009e2d52f6c4214f1616d2b4840abfa7de6eba.tar.bz2 |
Makes it so each windowtreeclient can use whatever ids it wants
This way clients won't need to wait for OnEmbed() before they can
start using windowtree. This also better isolates the apps.
I haven't updated the client lib to take advantage of this. I will do
that next.
BUG=566155
TEST=covered by tests
Review URL: https://codereview.chromium.org/1639223003
Cr-Commit-Position: refs/heads/master@{#371915}
Diffstat (limited to 'components/mus')
-rw-r--r-- | components/mus/ws/connection_manager.cc | 12 | ||||
-rw-r--r-- | components/mus/ws/connection_manager.h | 10 | ||||
-rw-r--r-- | components/mus/ws/ids.h | 53 | ||||
-rw-r--r-- | components/mus/ws/server_window_surface.cc | 1 | ||||
-rw-r--r-- | components/mus/ws/test_change_tracker.cc | 9 | ||||
-rw-r--r-- | components/mus/ws/window_finder.cc | 1 | ||||
-rw-r--r-- | components/mus/ws/window_tree_apptest.cc | 251 | ||||
-rw-r--r-- | components/mus/ws/window_tree_host_impl.cc | 20 | ||||
-rw-r--r-- | components/mus/ws/window_tree_host_impl.h | 4 | ||||
-rw-r--r-- | components/mus/ws/window_tree_impl.cc | 408 | ||||
-rw-r--r-- | components/mus/ws/window_tree_impl.h | 101 | ||||
-rw-r--r-- | components/mus/ws/window_tree_unittest.cc | 162 |
12 files changed, 644 insertions, 388 deletions
diff --git a/components/mus/ws/connection_manager.cc b/components/mus/ws/connection_manager.cc index c7a6bee..0604537 100644 --- a/components/mus/ws/connection_manager.cc +++ b/components/mus/ws/connection_manager.cc @@ -283,27 +283,29 @@ void ConnectionManager::WindowManagerChangeCompleted( void ConnectionManager::WindowManagerCreatedTopLevelWindow( WindowTreeImpl* wm_connection, uint32_t window_manager_change_id, - Id transport_window_id) { + const ServerWindow* window) { InFlightWindowManagerChange change; if (!GetAndClearInFlightWindowManagerChange(window_manager_change_id, &change)) { return; } + if (!window) { + WindowManagerSentBogusMessage(); + return; + } - const WindowId window_id(WindowIdFromTransportId(transport_window_id)); - const ServerWindow* window = GetWindow(window_id); WindowTreeImpl* connection = GetConnection(change.connection_id); // The window manager should have created the window already, and it should // be ready for embedding. if (!connection->IsWaitingForNewTopLevelWindow(window_manager_change_id) || !window || window->id().connection_id != wm_connection->id() || !window->children().empty() || GetConnectionWithRoot(window)) { - WindowManagerSentBogusMessage(connection); + WindowManagerSentBogusMessage(); return; } connection->OnWindowManagerCreatedTopLevelWindow( - window_manager_change_id, change.client_change_id, window_id); + window_manager_change_id, change.client_change_id, window); } void ConnectionManager::ProcessWindowBoundsChanged( diff --git a/components/mus/ws/connection_manager.h b/components/mus/ws/connection_manager.h index 3e1ba7f..0d93488 100644 --- a/components/mus/ws/connection_manager.h +++ b/components/mus/ws/connection_manager.h @@ -149,7 +149,11 @@ class ConnectionManager : public ServerWindowDelegate, bool success); void WindowManagerCreatedTopLevelWindow(WindowTreeImpl* wm_connection, uint32_t window_manager_change_id, - Id transport_window_id); + const ServerWindow* window); + + // Called when we get an unexpected message from the WindowManager. + // TODO(sky): decide what we want to do here. + void WindowManagerSentBogusMessage() {} // These functions trivially delegate to all WindowTreeImpls, which in // term notify their clients. @@ -200,10 +204,6 @@ class ConnectionManager : public ServerWindowDelegate, uint32_t window_manager_change_id, InFlightWindowManagerChange* change); - // Called when we get an unexpected message from the WindowManager. - // TODO(sky): decide what we want to do here. - void WindowManagerSentBogusMessage(WindowTreeImpl* connection) {} - // Invoked when a connection is about to execute a window server operation. // Subsequently followed by FinishOperation() once the change is done. // diff --git a/components/mus/ws/ids.h b/components/mus/ws/ids.h index fdb3b56..233f24d 100644 --- a/components/mus/ws/ids.h +++ b/components/mus/ws/ids.h @@ -9,18 +9,31 @@ #include <tuple> +#include "base/hash.h" #include "components/mus/common/types.h" #include "components/mus/common/util.h" namespace mus { - namespace ws { // Connection id is used to indicate no connection. That is, no WindowTreeImpl // ever gets this id. const ConnectionSpecificId kInvalidConnectionId = 0; -// Adds a bit of type safety to window ids. +// Every window has a unique id associated with it (WindowId). The id is a +// combination of the id assigned to the connection (the high order bits) and +// a unique id for the window. Each client (WindowTreeImpl) refers to the +// window by an id assigned by the client (ClientWindowId). To facilitate this +// WindowTreeImpl maintains a mapping between WindowId and ClientWindowId. +// +// This model works when the client initiates creation of windows, which is +// the typical use case. Embed roots and the WindowManager are special, they +// get access to windows created by other connections. These clients see the +// id assigned on the server. Such clients have to take care that they only +// create windows using their connection id. To do otherwise could result in +// multiple windows having the same ClientWindowId. WindowTreeImpl enforces +// that embed roots use the connection id in creating the window id to avoid +// possible conflicts. struct WindowId { WindowId(ConnectionSpecificId connection_id, ConnectionSpecificId window_id) : connection_id(connection_id), window_id(window_id) {} @@ -41,10 +54,25 @@ struct WindowId { ConnectionSpecificId window_id; }; +// Used for ids assigned by the client. +struct ClientWindowId { + explicit ClientWindowId(Id id) : id(id) {} + ClientWindowId() : id(0u) {} + + bool operator==(const ClientWindowId& other) const { return other.id == id; } + + bool operator!=(const ClientWindowId& other) const { + return !(*this == other); + } + + bool operator<(const ClientWindowId& other) const { return id < other.id; } + + Id id; +}; + inline WindowId WindowIdFromTransportId(Id id) { return WindowId(HiWord(id), LoWord(id)); } - inline Id WindowIdToTransportId(const WindowId& id) { return (id.connection_id << 16) | id.window_id; } @@ -61,7 +89,24 @@ inline WindowId RootWindowId(uint16_t index) { } } // namespace ws - } // namespace mus +namespace BASE_HASH_NAMESPACE { + +template <> +struct hash<mus::ws::ClientWindowId> { + size_t operator()(const mus::ws::ClientWindowId& id) const { + return hash<mus::Id>()(id.id); + } +}; + +template <> +struct hash<mus::ws::WindowId> { + size_t operator()(const mus::ws::WindowId& id) const { + return hash<mus::Id>()(WindowIdToTransportId(id)); + } +}; + +} // namespace BASE_HASH_NAMESPACE + #endif // COMPONENTS_MUS_WS_IDS_H_ diff --git a/components/mus/ws/server_window_surface.cc b/components/mus/ws/server_window_surface.cc index a3986b9..61208c1 100644 --- a/components/mus/ws/server_window_surface.cc +++ b/components/mus/ws/server_window_surface.cc @@ -101,6 +101,7 @@ bool ServerWindowSurface::ConvertSurfaceDrawQuad( cc::RenderPass* render_pass) { Id id = static_cast<Id>( input->surface_quad_state->surface.To<cc::SurfaceId>().id); + // TODO(sky): this is now wrong, needs mapping from client to window. WindowId other_window_id = WindowIdFromTransportId(id); ServerWindow* other_window = window()->GetChildWindow(other_window_id); if (!other_window) { diff --git a/components/mus/ws/test_change_tracker.cc b/components/mus/ws/test_change_tracker.cc index 2ea6796..6a7100c 100644 --- a/components/mus/ws/test_change_tracker.cc +++ b/components/mus/ws/test_change_tracker.cc @@ -149,9 +149,12 @@ std::string SingleChangeToDescription(const std::vector<Change>& changes) { } std::string SingleWindowDescription(const std::vector<TestWindow>& windows) { - if (windows.size() != 1u) - return "more than one changes and expected only one"; - return windows[0].ToString(); + if (windows.empty()) + return "no windows"; + std::string result; + for (const TestWindow& window : windows) + result += window.ToString(); + return result; } std::string ChangeWindowDescription(const std::vector<Change>& changes) { diff --git a/components/mus/ws/window_finder.cc b/components/mus/ws/window_finder.cc index 592d753..ff61e471 100644 --- a/components/mus/ws/window_finder.cc +++ b/components/mus/ws/window_finder.cc @@ -98,6 +98,7 @@ ServerWindow* FindDeepestVisibleWindowForEvents( ->GetSurfacesState() ->hit_tester() ->GetTargetSurfaceAtPoint(display_surface_id, *location, &transform); + // TODO(sky): this is now wrong, needs mapping from client to window. WindowId id = WindowIdFromTransportId( cc::SurfaceIdAllocator::NamespaceForId(target_surface)); // TODO(fsamuel): This should be a DCHECK but currently we use stale diff --git a/components/mus/ws/window_tree_apptest.cc b/components/mus/ws/window_tree_apptest.cc index 340aa41..c28fb33 100644 --- a/components/mus/ws/window_tree_apptest.cc +++ b/components/mus/ws/window_tree_apptest.cc @@ -129,7 +129,8 @@ class TestWindowTreeClientImpl : public mojom::WindowTreeClient, // want. next_change_id_(10000), waiting_change_id_(0), - on_change_completed_result_(false) { + on_change_completed_result_(false), + track_root_bounds_changes_(false) { tracker_.set_delegate(this); } @@ -139,6 +140,14 @@ class TestWindowTreeClientImpl : public mojom::WindowTreeClient, mojom::WindowTree* tree() { return tree_.get(); } TestChangeTracker* tracker() { return &tracker_; } + Id root_window_id() const { return root_window_id_; } + + // Sets whether changes to the bounds of the root should be tracked. Normally + // they are ignored (as during startup we often times get random size + // changes). + void set_track_root_bounds_changes(bool value) { + track_root_bounds_changes_ = value; + } // Runs a nested MessageLoop until |count| changes (calls to // WindowTreeClient functions) have been received. @@ -222,8 +231,6 @@ class TestWindowTreeClientImpl : public mojom::WindowTreeClient, return WaitForChangeCompleted(change_id) ? id : 0; } - void set_root_window(Id root_window_id) { root_window_id_ = root_window_id; } - bool SetWindowProperty(Id window_id, const std::string& name, const std::vector<uint8_t>* data) { @@ -272,6 +279,8 @@ class TestWindowTreeClientImpl : public mojom::WindowTreeClient, Id focused_window_id, uint32_t access_policy) override { // TODO(sky): add coverage of |focused_window_id|. + ASSERT_TRUE(root); + root_window_id_ = root->window_id; tree_ = std::move(tree); connection_id_ = connection_id; tracker()->OnEmbed(connection_id, std::move(root)); @@ -292,7 +301,7 @@ class TestWindowTreeClientImpl : public mojom::WindowTreeClient, // The bounds of the root may change during startup on Android at random // times. As this doesn't matter, and shouldn't impact test exepctations, // it is ignored. - if (window_id == root_window_id_) + if (window_id == root_window_id_ && !track_root_bounds_changes_) return; tracker()->OnWindowBoundsChanged(window_id, std::move(old_bounds), std::move(new_bounds)); @@ -381,6 +390,7 @@ class TestWindowTreeClientImpl : public mojom::WindowTreeClient, uint32_t next_change_id_; uint32_t waiting_change_id_; bool on_change_completed_result_; + bool track_root_bounds_changes_; scoped_ptr<base::RunLoop> change_completed_run_loop_; DISALLOW_COPY_AND_ASSIGN(TestWindowTreeClientImpl); @@ -458,7 +468,6 @@ class WindowTreeAppTest : public mojo::test::ApplicationTestBase, EstablishConnectionViaEmbed(ws1(), root_id, &connection_id_2_); ASSERT_GT(connection_id_2_, 0); ASSERT_TRUE(ws_client2_.get() != nullptr); - ws_client2_->set_root_window(root_window_id_); } void EstablishSecondConnection(bool create_initial_window) { @@ -480,7 +489,6 @@ class WindowTreeAppTest : public mojo::test::ApplicationTestBase, ASSERT_TRUE(ws_client3_.get() == nullptr); ws_client3_ = EstablishConnectionViaEmbed(owner, root_id, nullptr); ASSERT_TRUE(ws_client3_.get() != nullptr); - ws_client3_->set_root_window(root_window_id_); } scoped_ptr<TestWindowTreeClientImpl> WaitForWindowTreeClient() { @@ -551,7 +559,7 @@ class WindowTreeAppTest : public mojo::test::ApplicationTestBase, connection_id_1_ = (*changes1())[0].connection_id; ASSERT_FALSE((*changes1())[0].windows.empty()); root_window_id_ = (*changes1())[0].windows[0].window_id; - ws_client1_->set_root_window(root_window_id_); + ASSERT_EQ(root_window_id_, ws_client1_->root_window_id()); changes1()->clear(); } @@ -649,8 +657,7 @@ TEST_F(WindowTreeAppTest, WindowsRemovedWhenEmbedding) { { std::vector<TestWindow> windows; GetWindowTree(ws3(), window_2_3, &windows); - EXPECT_EQ(WindowParentToString(window_2_3, kNullParentId), - SingleWindowDescription(windows)); + EXPECT_EQ("no windows", SingleWindowDescription(windows)); } } @@ -668,7 +675,8 @@ TEST_F(WindowTreeAppTest, CantAccessChildrenOfEmbeddedWindow) { Id window_3_3 = ws_client3()->NewWindow(3); ASSERT_TRUE(window_3_3); - ASSERT_TRUE(ws_client3()->AddWindow(window_2_2, window_3_3)); + ASSERT_TRUE( + ws_client3()->AddWindow(ws_client3()->root_window_id(), window_3_3)); // Even though 3 is a child of 2 connection 2 can't see 3 as it's from a // different connection. @@ -693,10 +701,13 @@ TEST_F(WindowTreeAppTest, CantAccessChildrenOfEmbeddedWindow) { ASSERT_EQ(3u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), windows[0].ToString()); - EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), - windows[1].ToString()); - EXPECT_EQ(WindowParentToString(window_3_3, window_2_2), - windows[2].ToString()); + // NOTE: we expect a match of WindowParentToString(window_2_2, window_1_1), + // but the ids are in the id space of client2, which is not the same as + // the id space of ws1(). + EXPECT_EQ("window=2,1 parent=1,1", windows[1].ToString()); + // Same thing here, we really want to test for + // WindowParentToString(window_3_3, window_2_2). + EXPECT_EQ("window=3,1 parent=2,1", windows[2].ToString()); } } @@ -705,24 +716,24 @@ TEST_F(WindowTreeAppTest, CantModifyChildrenOfEmbeddedWindow) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = ws_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); + Id window_2_1 = ws_client2()->NewWindow(1); + ASSERT_TRUE(window_2_1); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_1)); - Id window_2_3 = ws_client2()->NewWindow(3); - ASSERT_TRUE(window_2_3); + Id window_2_2 = ws_client2()->NewWindow(2); + ASSERT_TRUE(window_2_2); // Connection 2 shouldn't be able to add anything to the window anymore. - ASSERT_FALSE(ws_client2()->AddWindow(window_2_2, window_2_3)); + ASSERT_FALSE(ws_client2()->AddWindow(window_2_1, window_2_2)); // Create window 3 in connection 3 and add it to window 3. - Id window_3_3 = ws_client3()->NewWindow(3); - ASSERT_TRUE(window_3_3); - ASSERT_TRUE(ws_client3()->AddWindow(window_2_2, window_3_3)); + Id window_3_1 = ws_client3()->NewWindow(1); + ASSERT_TRUE(window_3_1); + ASSERT_TRUE(ws_client3()->AddWindow(window_2_1, window_3_1)); // Connection 2 shouldn't be able to remove window 3. - ASSERT_FALSE(ws_client2()->RemoveWindowFromParent(window_3_3)); + ASSERT_FALSE(ws_client2()->RemoveWindowFromParent(window_3_1)); } // Verifies client gets a valid id. @@ -743,12 +754,14 @@ TEST_F(WindowTreeAppTest, NewWindow) { // Verifies AddWindow fails when window is already in position. TEST_F(WindowTreeAppTest, AddWindowWithNoChange) { + // Create the embed point now so that the ids line up. + ASSERT_TRUE(ws_client1()->NewWindow(1)); Id window_1_2 = ws_client1()->NewWindow(2); Id window_1_3 = ws_client1()->NewWindow(3); ASSERT_TRUE(window_1_2); ASSERT_TRUE(window_1_3); - ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); + ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); // Make 3 a child of 2. ASSERT_TRUE(ws_client1()->AddWindow(window_1_2, window_1_3)); @@ -759,12 +772,14 @@ TEST_F(WindowTreeAppTest, AddWindowWithNoChange) { // Verifies AddWindow fails when window is already in position. TEST_F(WindowTreeAppTest, AddAncestorFails) { + // Create the embed point now so that the ids line up. + ASSERT_TRUE(ws_client1()->NewWindow(1)); Id window_1_2 = ws_client1()->NewWindow(2); Id window_1_3 = ws_client1()->NewWindow(3); ASSERT_TRUE(window_1_2); ASSERT_TRUE(window_1_3); - ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); + ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); // Make 3 a child of 2. ASSERT_TRUE(ws_client1()->AddWindow(window_1_2, window_1_3)); @@ -775,13 +790,15 @@ TEST_F(WindowTreeAppTest, AddAncestorFails) { // Verifies adding to root sends right notifications. TEST_F(WindowTreeAppTest, AddToRoot) { + // Create the embed point now so that the ids line up. + Id window_1_1 = ws_client1()->NewWindow(1); + ASSERT_TRUE(window_1_1); Id window_1_21 = ws_client1()->NewWindow(21); Id window_1_3 = ws_client1()->NewWindow(3); ASSERT_TRUE(window_1_21); ASSERT_TRUE(window_1_3); - Id window_1_1 = BuildWindowId(connection_id_1(), 1); - ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); + ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); changes2()->clear(); // Make 3 a child of 21. @@ -799,6 +816,8 @@ TEST_F(WindowTreeAppTest, AddToRoot) { // Verifies HierarchyChanged is correctly sent for various adds/removes. TEST_F(WindowTreeAppTest, WindowHierarchyChangedWindows) { + // Create the embed point now so that the ids line up. + Id window_1_1 = ws_client1()->NewWindow(1); // 1,2->1,11. Id window_1_2 = ws_client1()->NewWindow(2); ASSERT_TRUE(window_1_2); @@ -808,8 +827,7 @@ TEST_F(WindowTreeAppTest, WindowHierarchyChangedWindows) { ASSERT_TRUE(ws_client1()->SetWindowVisibility(window_1_11, true)); ASSERT_TRUE(ws_client1()->AddWindow(window_1_2, window_1_11)); - Id window_1_1 = BuildWindowId(connection_id_1(), 1); - ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); + ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false)); ASSERT_TRUE(ws_client1()->SetWindowVisibility(window_1_1, true)); ASSERT_TRUE(ws_client2()->WaitForAllMessages()); @@ -892,8 +910,10 @@ TEST_F(WindowTreeAppTest, WindowHierarchyChangedAddingKnownToUnknown) { ASSERT_TRUE(ws_client2()->RemoveWindowFromParent(window_2_11)); ws_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_11) + - " new_parent=null old_parent=" + IdToString(window_1_1), + // 2,1 should be IdToString(window_2_11), but window_2_11 is in the id + // space of client2, not client1. + EXPECT_EQ("HierarchyChanged window=2,1 new_parent=null old_parent=" + + IdToString(window_1_1), SingleChangeToDescription(*changes1())); } @@ -905,8 +925,11 @@ TEST_F(WindowTreeAppTest, WindowHierarchyChangedAddingKnownToUnknown) { EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); - EXPECT_EQ("[" + WindowParentToString(window_2_2, window_1_1) + "],[" + - WindowParentToString(window_2_21, window_2_2) + "]", + // "window=2,3 parent=2,2]" should be, + // WindowParentToString(window_2_21, window_2_2), but isn't because of + // differing id spaces. + EXPECT_EQ("[" + WindowParentToString(window_2_2, window_1_1) + + "],[window=2,3 parent=2,2]", ChangeWindowDescription(*changes1())); } } @@ -936,7 +959,8 @@ TEST_F(WindowTreeAppTest, ReorderWindow) { ASSERT_TRUE(ws_client2()->AddWindow(window_2_1, window_2_3)); ASSERT_TRUE(ws_client1()->AddWindow(root_window_id(), window_1_4)); ASSERT_TRUE(ws_client1()->AddWindow(root_window_id(), window_1_5)); - ASSERT_TRUE(ws_client1()->AddWindow(root_window_id(), window_2_1)); + ASSERT_TRUE( + ws_client2()->AddWindow(BuildWindowId(connection_id_1(), 1), window_2_1)); { changes1()->clear(); @@ -986,15 +1010,15 @@ TEST_F(WindowTreeAppTest, ReorderWindow) { TEST_F(WindowTreeAppTest, DeleteWindow) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = ws_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); + Id window_2_1 = ws_client2()->NewWindow(1); + ASSERT_TRUE(window_2_1); // Make 2 a child of 1. { changes1()->clear(); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); ws_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + + EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_1) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); } @@ -1003,11 +1027,11 @@ TEST_F(WindowTreeAppTest, DeleteWindow) { { changes1()->clear(); changes2()->clear(); - ASSERT_TRUE(ws_client2()->DeleteWindow(window_2_2)); + ASSERT_TRUE(ws_client2()->DeleteWindow(window_2_1)); EXPECT_TRUE(changes2()->empty()); ws_client1_->WaitForChangeCount(1); - EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_2), + EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_1), SingleChangeToDescription(*changes1())); } } @@ -1023,43 +1047,43 @@ TEST_F(WindowTreeAppTest, DeleteWindowFromAnotherConnectionDisallowed) { TEST_F(WindowTreeAppTest, ReuseDeletedWindowId) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = ws_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); + Id window_2_1 = ws_client2()->NewWindow(1); + ASSERT_TRUE(window_2_1); // Add 2 to 1. { changes1()->clear(); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); ws_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + + EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_1) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); - EXPECT_EQ("[" + WindowParentToString(window_2_2, window_1_1) + "]", + EXPECT_EQ("[" + WindowParentToString(window_2_1, window_1_1) + "]", ChangeWindowDescription(*changes1())); } // Delete 2. { changes1()->clear(); - ASSERT_TRUE(ws_client2()->DeleteWindow(window_2_2)); + ASSERT_TRUE(ws_client2()->DeleteWindow(window_2_1)); ws_client1_->WaitForChangeCount(1); - EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_2), + EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_1), SingleChangeToDescription(*changes1())); } // Create 2 again, and add it back to 1. Should get the same notification. - window_2_2 = ws_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); + window_2_1 = ws_client2()->NewWindow(2); + ASSERT_TRUE(window_2_1); { changes1()->clear(); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); ws_client1_->WaitForChangeCount(1); - EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_2) + + EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_1) + " new_parent=" + IdToString(window_1_1) + " old_parent=null", SingleChangeToDescription(*changes1())); - EXPECT_EQ("[" + WindowParentToString(window_2_2, window_1_1) + "]", + EXPECT_EQ("[" + WindowParentToString(window_2_1, window_1_1) + "]", ChangeWindowDescription(*changes1())); } } @@ -1076,12 +1100,12 @@ TEST_F(WindowTreeAppTest, GetWindowTree) { ASSERT_TRUE(ws_client1()->AddWindow(window_1_1, window_1_11)); // Create two windows in second connection, 2 and 3, both children of 1. + Id window_2_1 = ws_client2()->NewWindow(1); Id window_2_2 = ws_client2()->NewWindow(2); - Id window_2_3 = ws_client2()->NewWindow(3); + ASSERT_TRUE(window_2_1); ASSERT_TRUE(window_2_2); - ASSERT_TRUE(window_2_3); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_3)); // Verifies GetWindowTree() on the root. The root connection sees all. { @@ -1094,9 +1118,9 @@ TEST_F(WindowTreeAppTest, GetWindowTree) { windows[1].ToString()); EXPECT_EQ(WindowParentToString(window_1_11, window_1_1), windows[2].ToString()); - EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), + EXPECT_EQ(WindowParentToString(window_2_1, window_1_1), windows[3].ToString()); - EXPECT_EQ(WindowParentToString(window_2_3, window_1_1), + EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), windows[4].ToString()); } @@ -1109,9 +1133,9 @@ TEST_F(WindowTreeAppTest, GetWindowTree) { ASSERT_EQ(3u, windows.size()); EXPECT_EQ(WindowParentToString(window_1_1, kNullParentId), windows[0].ToString()); - EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), + EXPECT_EQ(WindowParentToString(window_2_1, window_1_1), windows[1].ToString()); - EXPECT_EQ(WindowParentToString(window_2_3, window_1_1), + EXPECT_EQ(WindowParentToString(window_2_2, window_1_1), windows[2].ToString()); } @@ -1132,6 +1156,8 @@ TEST_F(WindowTreeAppTest, SetWindowBounds) { changes2()->clear(); + ws_client2_->set_track_root_bounds_changes(true); + ws1()->SetWindowBounds(10, window_1_1, mojo::Rect::From(gfx::Rect(0, 0, 100, 100))); ASSERT_TRUE(ws_client1()->WaitForChangeCompleted(10)); @@ -1442,10 +1468,10 @@ TEST_F(WindowTreeAppTest, SetWindowVisibilityNotifications) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnectionWithRoot(window_1_2)); // Add 2,3 as a child of 1,2. - Id window_2_3 = ws_client2()->NewWindow(3); - ASSERT_TRUE(window_2_3); - ASSERT_TRUE(ws_client2()->SetWindowVisibility(window_2_3, true)); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_2, window_2_3)); + Id window_2_1 = ws_client2()->NewWindow(1); + ASSERT_TRUE(window_2_1); + ASSERT_TRUE(ws_client2()->SetWindowVisibility(window_2_1, true)); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_2, window_2_1)); ASSERT_TRUE(ws_client1()->WaitForAllMessages()); changes2()->clear(); @@ -1490,11 +1516,11 @@ TEST_F(WindowTreeAppTest, SetWindowVisibilityNotifications) { // Change visibility of 2,3, connection 1 should see this. changes1()->clear(); - ASSERT_TRUE(ws_client2()->SetWindowVisibility(window_2_3, false)); + ASSERT_TRUE(ws_client2()->SetWindowVisibility(window_2_1, false)); { ws_client1_->WaitForChangeCount(1); EXPECT_EQ( - "VisibilityChanged window=" + IdToString(window_2_3) + " visible=false", + "VisibilityChanged window=" + IdToString(window_2_1) + " visible=false", SingleChangeToDescription(*changes1())); } @@ -1571,13 +1597,13 @@ TEST_F(WindowTreeAppTest, OnEmbeddedAppDisconnected) { // Create connection 2 and 3. ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = ws_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); + Id window_2_1 = ws_client2()->NewWindow(1); + ASSERT_TRUE(window_2_1); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); changes2()->clear(); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_1)); - // Connection 1 should get a hierarchy change for window_2_2. + // Connection 1 should get a hierarchy change for window_2_1. ws_client1_->WaitForChangeCount(1); changes1()->clear(); @@ -1585,11 +1611,11 @@ TEST_F(WindowTreeAppTest, OnEmbeddedAppDisconnected) { // be notified of this. ws_client3_.reset(); ws_client2_->WaitForChangeCount(1); - EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_2_2), + EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_2_1), SingleChangeToDescription(*changes2())); ws_client1_->WaitForChangeCount(1); - EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_2_2), + EXPECT_EQ("OnEmbeddedAppDisconnected window=" + IdToString(window_2_1), SingleChangeToDescription(*changes1())); } @@ -1600,20 +1626,20 @@ TEST_F(WindowTreeAppTest, OnParentOfEmbedDisconnects) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); ASSERT_TRUE(ws_client1()->AddWindow(root_window_id(), window_1_1)); + Id window_2_1 = ws_client2()->NewWindow(1); Id window_2_2 = ws_client2()->NewWindow(2); - Id window_2_3 = ws_client2()->NewWindow(3); + ASSERT_TRUE(window_2_1); ASSERT_TRUE(window_2_2); - ASSERT_TRUE(window_2_3); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); - ASSERT_TRUE(ws_client2()->AddWindow(window_2_2, window_2_3)); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); + ASSERT_TRUE(ws_client2()->AddWindow(window_2_1, window_2_2)); changes2()->clear(); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_3)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); changes3()->clear(); // Close connection 2. Connection 3 should get a delete (for its root). ws_client2_.reset(); ws_client3_->WaitForChangeCount(1); - EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_3), + EXPECT_EQ("WindowDeleted window=" + IdToString(window_2_2), SingleChangeToDescription(*changes3())); } @@ -1651,14 +1677,14 @@ TEST_F(WindowTreeAppTest, EmbedFailsFromOtherConnection) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = ws_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_2)); + Id window_2_1 = ws_client2()->NewWindow(1); + ASSERT_TRUE(window_2_1); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws2(), window_2_1)); Id window_3_3 = ws_client3()->NewWindow(3); ASSERT_TRUE(window_3_3); - ASSERT_TRUE(ws_client3()->AddWindow(window_2_2, window_3_3)); + ASSERT_TRUE(ws_client3()->AddWindow(window_2_1, window_3_3)); // 2 should not be able to embed in window_3_3 as window_3_3 was not created // by @@ -1672,14 +1698,14 @@ TEST_F(WindowTreeAppTest, EmbedFromOtherConnection) { ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(true)); Id window_1_1 = BuildWindowId(connection_id_1(), 1); - Id window_2_2 = ws_client2()->NewWindow(2); - ASSERT_TRUE(window_2_2); - ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_2)); + Id window_2_1 = ws_client2()->NewWindow(1); + ASSERT_TRUE(window_2_1); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_1, window_2_1)); changes2()->clear(); - // Establish a third connection in window_2_2. - ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws1(), window_2_2)); + // Establish a third connection in window_2_1. + ASSERT_NO_FATAL_FAILURE(EstablishThirdConnection(ws1(), window_2_1)); ASSERT_TRUE(ws_client2()->WaitForAllMessages()); EXPECT_EQ(std::string(), SingleChangeToDescription(*changes2())); @@ -1711,7 +1737,6 @@ TEST_F(WindowTreeAppTest, CantEmbedFromConnectionRoot) { ws_client3_ = EstablishConnectionViaEmbedWithPolicyBitmask( ws1(), window_1_2, mojom::WindowTree::kAccessPolicyEmbedRoot, nullptr); ASSERT_TRUE(ws_client3_.get() != nullptr); - ws_client3_->set_root_window(root_window_id()); // window_1_2 is ws3's root, so even though v3 is an embed root it should not // be able to Embed into itself. @@ -1765,6 +1790,50 @@ TEST_F(WindowTreeAppTest, TransientWindowTracksTransientParentLifetime) { ChangesToDescription1(*changes1())[1]); } +TEST_F(WindowTreeAppTest, Ids) { + const Id window_1_100 = ws_client1()->NewWindow(100); + ASSERT_TRUE(window_1_100); + ASSERT_TRUE(ws_client1()->AddWindow(root_window_id(), window_1_100)); + + // Establish the second connection at 1,100. + ASSERT_NO_FATAL_FAILURE(EstablishSecondConnectionWithRoot(window_1_100)); + + // 1,100 is the id in the ws_client1's id space. The new client should see + // 2,1 (the server id). + const Id window_1_100_in_ws2 = BuildWindowId(connection_id_1(), 1); + EXPECT_EQ(window_1_100_in_ws2, ws_client2()->root_window_id()); + + // The first window created in the second connection gets a server id of 2,1 + // regardless of the id the client uses. + const Id window_2_101 = ws_client2()->NewWindow(101); + ASSERT_TRUE(ws_client2()->AddWindow(window_1_100_in_ws2, window_2_101)); + const Id window_2_101_in_ws1 = BuildWindowId(connection_id_2(), 1); + ws_client1()->WaitForChangeCount(1); + EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_101_in_ws1) + + " new_parent=" + IdToString(window_1_100) + " old_parent=null", + SingleChangeToDescription(*changes1())); + changes1()->clear(); + + // Change the bounds of window_2_101 and make sure server gets it. + ws2()->SetWindowBounds(11, window_2_101, + mojo::Rect::From(gfx::Rect(1, 2, 3, 4))); + ASSERT_TRUE(ws_client2()->WaitForChangeCompleted(11)); + ws_client1()->WaitForChangeCount(1); + EXPECT_EQ("BoundsChanged window=" + IdToString(window_2_101_in_ws1) + + " old_bounds=0,0 0x0 new_bounds=1,2 3x4", + SingleChangeToDescription(*changes1())); + changes2()->clear(); + + // Remove 2_101 from wm, client1 should see the change. + ws1()->RemoveWindowFromParent(12, window_2_101_in_ws1); + ASSERT_TRUE(ws_client1()->WaitForChangeCompleted(12)); + ws_client2()->WaitForChangeCount(1); + EXPECT_EQ("HierarchyChanged window=" + IdToString(window_2_101) + + " new_parent=null old_parent=" + + IdToString(window_1_100_in_ws2), + SingleChangeToDescription(*changes2())); +} + // TODO(sky): need to better track changes to initial connection. For example, // that SetBounsdWindows/AddWindow and the like don't result in messages to the // originating connection. diff --git a/components/mus/ws/window_tree_host_impl.cc b/components/mus/ws/window_tree_host_impl.cc index 1c5de03..330ad06 100644 --- a/components/mus/ws/window_tree_host_impl.cc +++ b/components/mus/ws/window_tree_host_impl.cc @@ -249,15 +249,13 @@ void WindowTreeHostImpl::RemoveAccelerator(uint32_t id) { } void WindowTreeHostImpl::AddActivationParent(Id transport_window_id) { - ServerWindow* window = connection_manager_->GetWindow( - MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = GetWindowFromWindowTreeHost(transport_window_id); if (window) activation_parents_.insert(window->id()); } void WindowTreeHostImpl::RemoveActivationParent(Id transport_window_id) { - ServerWindow* window = connection_manager_->GetWindow( - MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = GetWindowFromWindowTreeHost(transport_window_id); if (window) activation_parents_.erase(window->id()); } @@ -271,8 +269,7 @@ void WindowTreeHostImpl::SetUnderlaySurfaceOffsetAndExtendedHitArea( int32_t x_offset, int32_t y_offset, mojo::InsetsPtr hit_area) { - ServerWindow* window = - connection_manager_->GetWindow(WindowIdFromTransportId(window_id)); + ServerWindow* window = GetWindowFromWindowTreeHost(window_id); if (!window) return; @@ -280,11 +277,12 @@ void WindowTreeHostImpl::SetUnderlaySurfaceOffsetAndExtendedHitArea( window->set_extended_hit_test_region(hit_area.To<gfx::Insets>()); } -WindowId WindowTreeHostImpl::MapWindowIdFromClient( - Id transport_window_id) const { - const WindowTreeImpl* connection = GetWindowTree(); - return connection ? connection->MapWindowIdFromClient(transport_window_id) - : WindowIdFromTransportId(transport_window_id); +ServerWindow* WindowTreeHostImpl::GetWindowFromWindowTreeHost( + Id transport_window_id) { + WindowTreeImpl* connection = GetWindowTree(); + if (!connection) + return nullptr; + return connection->GetWindowByClientId(ClientWindowId(transport_window_id)); } void WindowTreeHostImpl::OnClientClosed() { diff --git a/components/mus/ws/window_tree_host_impl.h b/components/mus/ws/window_tree_host_impl.h index 6c7580e..69e298b 100644 --- a/components/mus/ws/window_tree_host_impl.h +++ b/components/mus/ws/window_tree_host_impl.h @@ -157,7 +157,9 @@ class WindowTreeHostImpl : public DisplayManagerDelegate, scoped_ptr<ProcessedEventTarget> processed_target; }; - WindowId MapWindowIdFromClient(Id transport_window_id) const; + // Returns the ServerWindow with the specified transport id. Use this *only* + // if the call originates WindowTreeImpl associated with GetWindowTree(). + ServerWindow* GetWindowFromWindowTreeHost(Id transport_window_id); void OnClientClosed(); diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc index 2df84a5..7cfa5e3 100644 --- a/components/mus/ws/window_tree_impl.cc +++ b/components/mus/ws/window_tree_impl.cc @@ -67,6 +67,7 @@ WindowTreeImpl::WindowTreeImpl(ConnectionManager* connection_manager, uint32_t policy_bitmask) : connection_manager_(connection_manager), id_(connection_manager_->GetAndAdvanceNextConnectionId()), + next_window_id_(1), client_(nullptr), event_ack_id_(0), event_source_host_(nullptr), @@ -100,26 +101,47 @@ void WindowTreeImpl::Init(mojom::WindowTreeClient* client, host ? host->GetFocusedWindow() : nullptr; if (focused_window) focused_window = access_policy_->GetWindowForFocusChange(focused_window); - const Id focused_window_transport_id(MapWindowIdToClient(focused_window)); + ClientWindowId focused_window_id; + if (focused_window) + IsWindowKnown(focused_window, &focused_window_id); client->OnEmbed(id_, WindowToWindowData(to_send.front()), std::move(tree), - focused_window_transport_id, + focused_window_id.id, is_embed_root_ ? WindowTree::kAccessPolicyEmbedRoot : WindowTree::kAccessPolicyDefault); } const ServerWindow* WindowTreeImpl::GetWindow(const WindowId& id) const { if (id_ == id.connection_id) { - WindowMap::const_iterator i = window_map_.find(id.window_id); - return i == window_map_.end() ? NULL : i->second; + auto iter = created_window_map_.find(id); + return iter == created_window_map_.end() ? nullptr : iter->second; } return connection_manager_->GetWindow(id); } +bool WindowTreeImpl::IsWindowKnown(const ServerWindow* window, + ClientWindowId* id) const { + if (!window) + return false; + auto iter = window_id_to_client_id_map_.find(window->id()); + if (iter == window_id_to_client_id_map_.end()) + return false; + if (id) + *id = iter->second; + return true; +} + bool WindowTreeImpl::HasRoot(const ServerWindow* window) const { return roots_.count(window) > 0; } +const ServerWindow* WindowTreeImpl::GetWindowByClientId( + const ClientWindowId& id) const { + auto iter = client_id_to_window_id_map_.find(id); + return iter == client_id_to_window_id_map_.end() ? nullptr + : GetWindow(iter->second); +} + const WindowTreeHostImpl* WindowTreeImpl::GetHost( const ServerWindow* window) const { return window ? connection_manager_->GetWindowTreeHostByWindow(window) @@ -131,11 +153,10 @@ void WindowTreeImpl::OnWindowDestroyingTreeImpl(WindowTreeImpl* connection) { for (const auto* connection_root : connection->roots_) { const bool owns_connection_root = connection_root->id().connection_id == id_; - const bool knows_about_connection_root = - window_map_.count(connection_root->id().window_id) > 0; - if ((owns_connection_root && knows_about_connection_root) || + if (owns_connection_root || (is_embed_root_ && IsWindowKnown(connection_root))) { - client_->OnEmbeddedAppDisconnected(MapWindowIdToClient(connection_root)); + client_->OnEmbeddedAppDisconnected( + ClientWindowIdForWindow(connection_root).id); } } } @@ -154,20 +175,24 @@ void WindowTreeImpl::NotifyChangeCompleted( } bool WindowTreeImpl::NewWindow( - const WindowId& window_id, + const ClientWindowId& client_window_id, const std::map<std::string, std::vector<uint8_t>>& properties) { - if (!IsValidIdForNewWindow(window_id)) + if (!IsValidIdForNewWindow(client_window_id)) return false; - window_map_[window_id.window_id] = + const WindowId window_id = GenerateNewWindowId(); + DCHECK(!GetWindow(window_id)); + ServerWindow* window = connection_manager_->CreateServerWindow(window_id, properties); - known_windows_.insert(WindowIdToTransportId(window_id)); + created_window_map_[window_id] = window; + client_id_to_window_id_map_[client_window_id] = window_id; + window_id_to_client_id_map_[window_id] = client_window_id; return true; } -bool WindowTreeImpl::AddWindow(const WindowId& parent_id, - const WindowId& child_id) { - ServerWindow* parent = GetWindow(MapWindowIdFromClient(parent_id)); - ServerWindow* child = GetWindow(MapWindowIdFromClient(child_id)); +bool WindowTreeImpl::AddWindow(const ClientWindowId& parent_id, + const ClientWindowId& child_id) { + ServerWindow* parent = GetWindowByClientId(parent_id); + ServerWindow* child = GetWindowByClientId(child_id); if (parent && child && child->parent() != parent && !child->Contains(parent) && access_policy_->CanAddWindow(parent, child)) { Operation op(this, connection_manager_, OperationType::ADD_WINDOW); @@ -177,11 +202,11 @@ bool WindowTreeImpl::AddWindow(const WindowId& parent_id, return false; } -bool WindowTreeImpl::AddTransientWindow(const WindowId& window_id, - const WindowId& transient_window_id) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(window_id)); - ServerWindow* transient_window = - GetWindow(MapWindowIdFromClient(transient_window_id)); +bool WindowTreeImpl::AddTransientWindow( + const ClientWindowId& window_id, + const ClientWindowId& transient_window_id) { + ServerWindow* window = GetWindowByClientId(window_id); + ServerWindow* transient_window = GetWindowByClientId(transient_window_id); if (window && transient_window && !transient_window->Contains(window) && access_policy_->CanAddTransientWindow(window, transient_window)) { Operation op(this, connection_manager_, @@ -193,17 +218,17 @@ bool WindowTreeImpl::AddTransientWindow(const WindowId& window_id, } std::vector<const ServerWindow*> WindowTreeImpl::GetWindowTree( - const WindowId& window_id) const { - const ServerWindow* window = GetWindow(window_id); + const ClientWindowId& window_id) const { + const ServerWindow* window = GetWindowByClientId(window_id); std::vector<const ServerWindow*> windows; if (window) GetWindowTreeImpl(window, &windows); return windows; } -bool WindowTreeImpl::SetWindowVisibility(const WindowId& window_id, +bool WindowTreeImpl::SetWindowVisibility(const ClientWindowId& window_id, bool visible) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(window_id)); + ServerWindow* window = GetWindowByClientId(window_id); if (!window || window->visible() == visible || !access_policy_->CanChangeWindowVisibility(window)) { return false; @@ -213,16 +238,17 @@ bool WindowTreeImpl::SetWindowVisibility(const WindowId& window_id, return true; } -bool WindowTreeImpl::Embed(const WindowId& window_id, +bool WindowTreeImpl::Embed(const ClientWindowId& window_id, mojom::WindowTreeClientPtr client, uint32_t policy_bitmask, ConnectionSpecificId* connection_id) { *connection_id = kInvalidConnectionId; if (!client || !CanEmbed(window_id, policy_bitmask)) return false; - PrepareForEmbed(window_id); + ServerWindow* window = GetWindowByClientId(window_id); + PrepareForEmbed(window); WindowTreeImpl* new_connection = connection_manager_->EmbedAtWindow( - GetWindow(window_id), policy_bitmask, std::move(client)); + window, policy_bitmask, std::move(client)); if (is_embed_root_) *connection_id = new_connection->id(); return true; @@ -259,40 +285,23 @@ bool WindowTreeImpl::IsWaitingForNewTopLevelWindow(uint32_t wm_change_id) { void WindowTreeImpl::OnWindowManagerCreatedTopLevelWindow( uint32_t wm_change_id, uint32_t client_change_id, - const WindowId& window_id) { + const ServerWindow* window) { DCHECK(IsWaitingForNewTopLevelWindow(wm_change_id)); scoped_ptr<WaitingForTopLevelWindowInfo> waiting_for_top_level_window_info( std::move(waiting_for_top_level_window_info_)); connection_manager_->GetClientConnection(this) ->SetIncomingMethodCallProcessingPaused(false); - embed_to_real_id_map_[waiting_for_top_level_window_info->window_id] = - window_id; - std::vector<const ServerWindow*> unused; - const ServerWindow* window = GetWindow(window_id); + // We were paused, so the id should still be valid. + DCHECK(IsValidIdForNewWindow( + waiting_for_top_level_window_info->client_window_id)); + client_id_to_window_id_map_[waiting_for_top_level_window_info + ->client_window_id] = window->id(); + window_id_to_client_id_map_[window->id()] = + waiting_for_top_level_window_info->client_window_id; roots_.insert(window); - GetUnknownWindowsFrom(window, &unused); client_->OnTopLevelCreated(client_change_id, WindowToWindowData(window)); } -WindowId WindowTreeImpl::MapWindowIdFromClient(const WindowId& id) const { - auto iter = embed_to_real_id_map_.find(id); - return iter == embed_to_real_id_map_.end() ? id : iter->second; -} - -Id WindowTreeImpl::MapWindowIdToClient(const ServerWindow* window) const { - return MapWindowIdToClient(window ? window->id() : WindowId()); -} - -Id WindowTreeImpl::MapWindowIdToClient(const WindowId& id) const { - // Clients typically don't have many embed windows, so we don't maintain an - // inverse mapping. - for (const auto& pair : embed_to_real_id_map_) { - if (pair.second == id) - return WindowIdToTransportId(pair.first); - } - return WindowIdToTransportId(id); -} - void WindowTreeImpl::OnChangeCompleted(uint32_t change_id, bool success) { client_->OnChangeCompleted(change_id, success); } @@ -301,10 +310,10 @@ void WindowTreeImpl::ProcessWindowBoundsChanged(const ServerWindow* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds, bool originated_change) { - if (originated_change || !IsWindowKnown(window)) + ClientWindowId client_window_id; + if (originated_change || !IsWindowKnown(window, &client_window_id)) return; - client_->OnWindowBoundsChanged(MapWindowIdToClient(window), - Rect::From(old_bounds), + client_->OnWindowBoundsChanged(client_window_id.id, Rect::From(old_bounds), Rect::From(new_bounds)); } @@ -313,10 +322,11 @@ void WindowTreeImpl::ProcessClientAreaChanged( const gfx::Insets& new_client_area, const std::vector<gfx::Rect>& new_additional_client_areas, bool originated_change) { - if (originated_change || !IsWindowKnown(window)) + ClientWindowId client_window_id; + if (originated_change || !IsWindowKnown(window, &client_window_id)) return; client_->OnClientAreaChanged( - MapWindowIdToClient(window), mojo::Insets::From(new_client_area), + client_window_id.id, mojo::Insets::From(new_client_area), mojo::Array<mojo::RectPtr>::From(new_additional_client_areas)); } @@ -327,8 +337,12 @@ void WindowTreeImpl::ProcessViewportMetricsChanged( bool originated_change) { mojo::Array<Id> window_ids; for (const ServerWindow* root : roots_) { - if (GetHost(root) == host) - window_ids.push_back(MapWindowIdToClient(root->id())); + if (GetHost(root) == host) { + ClientWindowId client_window_id; + const bool known = IsWindowKnown(root, &client_window_id); + DCHECK(known); + window_ids.push_back(client_window_id.id); + } } if (window_ids.size() == 0u) return; @@ -362,12 +376,16 @@ void WindowTreeImpl::ProcessWindowPropertyChanged( if (originated_change) return; + ClientWindowId client_window_id; + if (!IsWindowKnown(window, &client_window_id)) + return; + Array<uint8_t> data; if (new_data) data = Array<uint8_t>::From(*new_data); - client_->OnWindowSharedPropertyChanged(MapWindowIdToClient(window), - String(name), std::move(data)); + client_->OnWindowSharedPropertyChanged(client_window_id.id, String(name), + std::move(data)); } void WindowTreeImpl::ProcessWindowHierarchyChanged( @@ -396,11 +414,15 @@ void WindowTreeImpl::ProcessWindowHierarchyChanged( std::vector<const ServerWindow*> to_send; if (!IsWindowKnown(window)) GetUnknownWindowsFrom(window, &to_send); - const WindowId new_parent_id(new_parent ? new_parent->id() : WindowId()); - const WindowId old_parent_id(old_parent ? old_parent->id() : WindowId()); + const ClientWindowId new_parent_client_window_id = + new_parent ? ClientWindowIdForWindow(new_parent) : ClientWindowId(); + const ClientWindowId old_parent_client_window_id = + old_parent ? ClientWindowIdForWindow(old_parent) : ClientWindowId(); + const ClientWindowId client_window_id = + window ? ClientWindowIdForWindow(window) : ClientWindowId(); client_->OnWindowHierarchyChanged( - MapWindowIdToClient(window), MapWindowIdToClient(new_parent_id), - MapWindowIdToClient(old_parent_id), WindowsToWindowDatas(to_send)); + client_window_id.id, new_parent_client_window_id.id, + old_parent_client_window_id.id, WindowsToWindowDatas(to_send)); connection_manager_->OnConnectionMessagedClient(id_); } @@ -409,8 +431,9 @@ void WindowTreeImpl::ProcessWindowReorder(const ServerWindow* window, mojom::OrderDirection direction, bool originated_change) { DCHECK_EQ(window->parent(), relative_window->parent()); - if (originated_change || !IsWindowKnown(window) || - !IsWindowKnown(relative_window) || + ClientWindowId client_window_id, relative_client_window_id; + if (originated_change || !IsWindowKnown(window, &client_window_id) || + !IsWindowKnown(relative_window, &relative_client_window_id) || connection_manager_->DidConnectionMessageClient(id_)) return; @@ -420,31 +443,30 @@ void WindowTreeImpl::ProcessWindowReorder(const ServerWindow* window, if (HasRoot(window) || HasRoot(relative_window)) return; - client_->OnWindowReordered(MapWindowIdToClient(window), - MapWindowIdToClient(relative_window), direction); + client_->OnWindowReordered(client_window_id.id, relative_client_window_id.id, + direction); connection_manager_->OnConnectionMessagedClient(id_); } void WindowTreeImpl::ProcessWindowDeleted(const ServerWindow* window, bool originated_change) { if (window->id().connection_id == id_) - window_map_.erase(window->id().window_id); - - const Id transport_id = MapWindowIdToClient(window); + created_window_map_.erase(window->id()); - const bool in_known = - known_windows_.erase(WindowIdToTransportId(window->id())) > 0; + ClientWindowId client_window_id; + if (!IsWindowKnown(window, &client_window_id)) + return; if (HasRoot(window)) RemoveRoot(window, RemoveRootReason::DELETED); + else + RemoveFromMaps(window); if (originated_change) return; - if (in_known) { - client_->OnWindowDeleted(transport_id); - connection_manager_->OnConnectionMessagedClient(id_); - } + client_->OnWindowDeleted(client_window_id.id); + connection_manager_->OnConnectionMessagedClient(id_); } void WindowTreeImpl::ProcessWillChangeWindowVisibility( @@ -453,9 +475,9 @@ void WindowTreeImpl::ProcessWillChangeWindowVisibility( if (originated_change) return; - if (IsWindowKnown(window)) { - client_->OnWindowVisibilityChanged(MapWindowIdToClient(window), - !window->visible()); + ClientWindowId client_window_id; + if (IsWindowKnown(window, &client_window_id)) { + client_->OnWindowVisibilityChanged(client_window_id.id, !window->visible()); return; } @@ -476,7 +498,11 @@ void WindowTreeImpl::ProcessCursorChanged(const ServerWindow* window, bool originated_change) { if (originated_change) return; - client_->OnWindowPredefinedCursorChanged(MapWindowIdToClient(window), + ClientWindowId client_window_id; + if (!IsWindowKnown(window, &client_window_id)) + return; + + client_->OnWindowPredefinedCursorChanged(client_window_id.id, mojom::Cursor(cursor_id)); } @@ -487,8 +513,12 @@ void WindowTreeImpl::ProcessFocusChanged( new_focused_window ? access_policy_->GetWindowForFocusChange(new_focused_window) : nullptr; - client_->OnWindowFocused(window ? MapWindowIdToClient(window) - : MapWindowIdToClient(WindowId())); + ClientWindowId client_window_id; + // If the window isn't known we'll supply null, which is ok. + IsWindowKnown(window, &client_window_id); + // TODO(sky): this should only notify if this results in a change of focus + // for the client. + client_->OnWindowFocused(client_window_id.id); } void WindowTreeImpl::ProcessTransientWindowAdded( @@ -497,8 +527,14 @@ void WindowTreeImpl::ProcessTransientWindowAdded( bool originated_change) { if (originated_change) return; - client_->OnTransientWindowAdded(MapWindowIdToClient(window), - MapWindowIdToClient(transient_window)); + + ClientWindowId client_window_id, transient_client_window_id; + if (!IsWindowKnown(window, &client_window_id) || + !IsWindowKnown(transient_window, &transient_client_window_id)) { + return; + } + client_->OnTransientWindowAdded(client_window_id.id, + transient_client_window_id.id); } void WindowTreeImpl::ProcessTransientWindowRemoved( @@ -507,8 +543,13 @@ void WindowTreeImpl::ProcessTransientWindowRemoved( bool originated_change) { if (originated_change) return; - client_->OnTransientWindowRemoved(MapWindowIdToClient(window), - MapWindowIdToClient(transient_window)); + ClientWindowId client_window_id, transient_client_window_id; + if (!IsWindowKnown(window, &client_window_id) || + !IsWindowKnown(transient_window, &transient_client_window_id)) { + return; + } + client_->OnTransientWindowRemoved(client_window_id.id, + transient_client_window_id.id); } WindowTreeHostImpl* WindowTreeImpl::GetHostForWindowManager() { @@ -549,13 +590,27 @@ bool WindowTreeImpl::ShouldRouteToWindowManager( return is_wm ? false : true; } -bool WindowTreeImpl::IsWindowKnown(const ServerWindow* window) const { - return known_windows_.count(WindowIdToTransportId(window->id())) > 0; +ClientWindowId WindowTreeImpl::ClientWindowIdForWindow( + const ServerWindow* window) const { + auto iter = window_id_to_client_id_map_.find(window->id()); + DCHECK(iter != window_id_to_client_id_map_.end()); + return iter->second; +} + +bool WindowTreeImpl::IsValidIdForNewWindow(const ClientWindowId& id) const { + if (is_embed_root_ && WindowIdFromTransportId(id.id).connection_id != id_) { + // Embed roots see windows created from other connections. If they don't + // use the connection id when creating windows the client could end up with + // two windows with the same id. Because of this we restrict the ids such + // connections can create. + return false; + } + return client_id_to_window_id_map_.count(id) == 0u; } -bool WindowTreeImpl::IsValidIdForNewWindow(const WindowId& id) const { - return id.connection_id == id_ && embed_to_real_id_map_.count(id) == 0 && - window_map_.count(id.window_id) == 0; +WindowId WindowTreeImpl::GenerateNewWindowId() { + // TODO(sky): deal with wrapping and uniqueness. + return WindowId(id_, next_window_id_++); } bool WindowTreeImpl::CanReorderWindow(const ServerWindow* window, @@ -599,7 +654,17 @@ void WindowTreeImpl::GetUnknownWindowsFrom( if (IsWindowKnown(window) || !access_policy_->CanGetWindowTree(window)) return; windows->push_back(window); - known_windows_.insert(WindowIdToTransportId(window->id())); + // There are two cases where this gets hit: + // . During init, in which case using the window id as the client id is + // fine. + // . When a window is moved to a parent of a window we know about. This is + // only encountered for the WM or embed roots. We assume such clients want + // to see the real id of the window and are only created ClientWindowIds + // with the connection_id. + const ClientWindowId client_window_id(WindowIdToTransportId(window->id())); + DCHECK_EQ(0u, client_id_to_window_id_map_.count(client_window_id)); + client_id_to_window_id_map_[client_window_id] = window->id(); + window_id_to_client_id_map_[window->id()] = client_window_id; if (!access_policy_->CanDescendIntoWindowForWindowTree(window)) return; std::vector<const ServerWindow*> children(window->GetChildren()); @@ -607,6 +672,16 @@ void WindowTreeImpl::GetUnknownWindowsFrom( GetUnknownWindowsFrom(children[i], windows); } +bool WindowTreeImpl::RemoveFromMaps(const ServerWindow* window) { + auto iter = window_id_to_client_id_map_.find(window->id()); + if (iter == window_id_to_client_id_map_.end()) + return false; + + client_id_to_window_id_map_.erase(iter->second); + window_id_to_client_id_map_.erase(iter); + return true; +} + void WindowTreeImpl::RemoveFromKnown( const ServerWindow* window, std::vector<ServerWindow*>* local_windows) { @@ -615,7 +690,9 @@ void WindowTreeImpl::RemoveFromKnown( local_windows->push_back(GetWindow(window->id())); return; } - known_windows_.erase(WindowIdToTransportId(window->id())); + + RemoveFromMaps(window); + std::vector<const ServerWindow*> children = window->GetChildren(); for (size_t i = 0; i < children.size(); ++i) RemoveFromKnown(children[i], local_windows); @@ -625,22 +702,16 @@ void WindowTreeImpl::RemoveRoot(const ServerWindow* window, RemoveRootReason reason) { DCHECK(roots_.count(window) > 0); roots_.erase(window); - const Id transport_id = MapWindowIdToClient(window); - for (auto& pair : embed_to_real_id_map_) { - if (pair.second == window->id()) { - embed_to_real_id_map_.erase(pair.first); - break; - } - } + const ClientWindowId client_window_id(ClientWindowIdForWindow(window)); // No need to do anything if we created the window. if (window->id().connection_id == id_) return; if (reason == RemoveRootReason::EMBED) { - client_->OnUnembed(transport_id); - client_->OnWindowDeleted(transport_id); + client_->OnUnembed(client_window_id.id); + client_->OnWindowDeleted(client_window_id.id); connection_manager_->OnConnectionMessagedClient(id_); } @@ -667,10 +738,12 @@ mojom::WindowDataPtr WindowTreeImpl::WindowToWindowData( // If the parent isn't known, it means the parent is not visible to us (not // in roots), and should not be sent over. if (parent && !IsWindowKnown(parent)) - parent = NULL; + parent = nullptr; mojom::WindowDataPtr window_data(mojom::WindowData::New()); - window_data->parent_id = MapWindowIdToClient(parent); - window_data->window_id = MapWindowIdToClient(window); + window_data->parent_id = + parent ? ClientWindowIdForWindow(parent).id : ClientWindowId().id; + window_data->window_id = + window ? ClientWindowIdForWindow(window).id : ClientWindowId().id; window_data->bounds = Rect::From(window->bounds()); window_data->properties = mojo::Map<String, Array<uint8_t>>::From(window->properties()); @@ -708,40 +781,39 @@ void WindowTreeImpl::NotifyDrawnStateChanged(const ServerWindow* window, for (auto* root : roots_) { if (window->Contains(root) && (new_drawn_value != root->IsDrawn())) { - client_->OnWindowDrawnStateChanged(MapWindowIdToClient(root), + client_->OnWindowDrawnStateChanged(ClientWindowIdForWindow(root).id, new_drawn_value); } } } void WindowTreeImpl::DestroyWindows() { - if (window_map_.empty()) + if (created_window_map_.empty()) return; Operation op(this, connection_manager_, OperationType::DELETE_WINDOW); // If we get here from the destructor we're not going to get // ProcessWindowDeleted(). Copy the map and delete from the copy so that we - // don't have to worry about whether |window_map_| changes or not. - WindowMap window_map_copy; - window_map_.swap(window_map_copy); + // don't have to worry about whether |created_window_map_| changes or not. + base::hash_map<WindowId, ServerWindow*> created_window_map_copy; + created_window_map_.swap(created_window_map_copy); // A sibling can be a transient parent of another window so we detach windows // from their transient parents to avoid double deletes. - for (auto& pair : window_map_copy) { + for (auto& pair : created_window_map_copy) { ServerWindow* transient_parent = pair.second->transient_parent(); if (transient_parent) transient_parent->RemoveTransientWindow(pair.second); } - STLDeleteValues(&window_map_copy); + STLDeleteValues(&created_window_map_copy); } -bool WindowTreeImpl::CanEmbed(const WindowId& window_id, +bool WindowTreeImpl::CanEmbed(const ClientWindowId& window_id, uint32_t policy_bitmask) const { - const ServerWindow* window = GetWindow(window_id); + const ServerWindow* window = GetWindowByClientId(window_id); return window && access_policy_->CanEmbed(window, policy_bitmask); } -void WindowTreeImpl::PrepareForEmbed(const WindowId& window_id) { - const ServerWindow* window = GetWindow(window_id); +void WindowTreeImpl::PrepareForEmbed(ServerWindow* window) { DCHECK(window); // Only allow a node to be the root for one connection. @@ -749,7 +821,7 @@ void WindowTreeImpl::PrepareForEmbed(const WindowId& window_id) { connection_manager_->GetConnectionWithRoot(window); Operation op(this, connection_manager_, OperationType::EMBED); - RemoveChildrenAsPartOfEmbed(window_id); + RemoveChildrenAsPartOfEmbed(window); if (existing_owner) { // Never message the originating connection. connection_manager_->OnConnectionMessagedClient(id_); @@ -757,10 +829,8 @@ void WindowTreeImpl::PrepareForEmbed(const WindowId& window_id) { } } -void WindowTreeImpl::RemoveChildrenAsPartOfEmbed(const WindowId& window_id) { - ServerWindow* window = GetWindow(window_id); +void WindowTreeImpl::RemoveChildrenAsPartOfEmbed(ServerWindow* window) { CHECK(window); - CHECK(window->id().connection_id == window_id.connection_id); std::vector<ServerWindow*> children = window->GetChildren(); for (size_t i = 0; i < children.size(); ++i) window->Remove(children[i]); @@ -777,7 +847,7 @@ void WindowTreeImpl::DispatchInputEventImpl(ServerWindow* target, event_source_host_ = GetHost(target); // Should only get events from windows attached to a host. DCHECK(event_source_host_); - client_->OnWindowInputEvent(event_ack_id_, MapWindowIdToClient(target), + client_->OnWindowInputEvent(event_ack_id_, ClientWindowIdForWindow(target).id, std::move(event)); } @@ -791,8 +861,7 @@ void WindowTreeImpl::NewWindow( transport_properties.To<std::map<std::string, std::vector<uint8_t>>>(); } client_->OnChangeCompleted( - change_id, - NewWindow(MapWindowIdFromClient(transport_window_id), properties)); + change_id, NewWindow(ClientWindowId(transport_window_id), properties)); } void WindowTreeImpl::NewTopLevelWindow( @@ -800,12 +869,12 @@ void WindowTreeImpl::NewTopLevelWindow( Id transport_window_id, mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) { DCHECK(!waiting_for_top_level_window_info_); - const WindowId window_id(MapWindowIdFromClient(transport_window_id)); + const ClientWindowId client_window_id(transport_window_id); // TODO(sky): need a way for client to provide context. WindowTreeHostImpl* tree_host = connection_manager_->GetActiveWindowTreeHost(); if (!tree_host || tree_host->GetWindowTree() == this || - !IsValidIdForNewWindow(window_id)) { + !IsValidIdForNewWindow(client_window_id)) { client_->OnChangeCompleted(change_id, false); return; } @@ -821,14 +890,15 @@ void WindowTreeImpl::NewTopLevelWindow( connection_manager_->GenerateWindowManagerChangeId(this, change_id); waiting_for_top_level_window_info_.reset( - new WaitingForTopLevelWindowInfo(window_id, wm_change_id)); + new WaitingForTopLevelWindowInfo(client_window_id, wm_change_id)); tree_host->GetWindowTree()->window_manager_internal_->WmCreateTopLevelWindow( wm_change_id, std::move(transport_properties)); } void WindowTreeImpl::DeleteWindow(uint32_t change_id, Id transport_window_id) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); bool success = false; bool should_close = window && (access_policy_->CanDeleteWindow(window) || ShouldRouteToWindowManager(window)); @@ -841,14 +911,13 @@ void WindowTreeImpl::DeleteWindow(uint32_t change_id, Id transport_window_id) { } void WindowTreeImpl::AddWindow(uint32_t change_id, Id parent_id, Id child_id) { - client_->OnChangeCompleted(change_id, - AddWindow(MapWindowIdFromClient(parent_id), - MapWindowIdFromClient(child_id))); + client_->OnChangeCompleted(change_id, AddWindow(ClientWindowId(parent_id), + ClientWindowId(child_id))); } void WindowTreeImpl::RemoveWindowFromParent(uint32_t change_id, Id window_id) { bool success = false; - ServerWindow* window = GetWindow(MapWindowIdFromClient(window_id)); + ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id)); if (window && window->parent() && access_policy_->CanRemoveWindowFromParent(window)) { success = true; @@ -863,16 +932,16 @@ void WindowTreeImpl::AddTransientWindow(uint32_t change_id, Id window, Id transient_window) { client_->OnChangeCompleted( - change_id, AddTransientWindow(MapWindowIdFromClient(window), - MapWindowIdFromClient(transient_window))); + change_id, AddTransientWindow(ClientWindowId(window), + ClientWindowId(transient_window))); } void WindowTreeImpl::RemoveTransientWindowFromParent(uint32_t change_id, Id transient_window_id) { bool success = false; ServerWindow* transient_window = - GetWindow(MapWindowIdFromClient(transient_window_id)); - if (transient_window->transient_parent() && + GetWindowByClientId(ClientWindowId(transient_window_id)); + if (transient_window && transient_window->transient_parent() && access_policy_->CanRemoveTransientWindowFromParent(transient_window)) { success = true; Operation op(this, connection_manager_, @@ -888,9 +957,9 @@ void WindowTreeImpl::ReorderWindow(uint32_t change_id, Id relative_window_id, mojom::OrderDirection direction) { bool success = false; - ServerWindow* window = GetWindow(MapWindowIdFromClient(window_id)); + ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id)); ServerWindow* relative_window = - GetWindow(MapWindowIdFromClient(relative_window_id)); + GetWindowByClientId(ClientWindowId(relative_window_id)); if (CanReorderWindow(window, relative_window, direction)) { success = true; Operation op(this, connection_manager_, OperationType::REORDER_WINDOW); @@ -905,21 +974,23 @@ void WindowTreeImpl::GetWindowTree( Id window_id, const Callback<void(Array<mojom::WindowDataPtr>)>& callback) { std::vector<const ServerWindow*> windows( - GetWindowTree(MapWindowIdFromClient(window_id))); + GetWindowTree(ClientWindowId(window_id))); callback.Run(WindowsToWindowDatas(windows)); } void WindowTreeImpl::SetWindowBounds(uint32_t change_id, Id window_id, mojo::RectPtr bounds) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(window_id)); + ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id)); if (window && ShouldRouteToWindowManager(window)) { const uint32_t wm_change_id = connection_manager_->GenerateWindowManagerChangeId(this, change_id); // |window_id| may be a client id, use the id from the window to ensure // the windowmanager doesn't get an id it doesn't know about. - GetHost(window)->GetWindowTree()->window_manager_internal_->WmSetBounds( - wm_change_id, WindowIdToTransportId(window->id()), std::move(bounds)); + WindowTreeImpl* wm_window_tree = GetHost(window)->GetWindowTree(); + wm_window_tree->window_manager_internal_->WmSetBounds( + wm_change_id, wm_window_tree->ClientWindowIdForWindow(window).id, + std::move(bounds)); return; } @@ -937,19 +1008,21 @@ void WindowTreeImpl::SetWindowVisibility(uint32_t change_id, bool visible) { client_->OnChangeCompleted( change_id, - SetWindowVisibility(MapWindowIdFromClient(transport_window_id), visible)); + SetWindowVisibility(ClientWindowId(transport_window_id), visible)); } void WindowTreeImpl::SetWindowProperty(uint32_t change_id, Id transport_window_id, const mojo::String& name, mojo::Array<uint8_t> value) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); if (window && ShouldRouteToWindowManager(window)) { const uint32_t wm_change_id = connection_manager_->GenerateWindowManagerChangeId(this, change_id); - GetHost(window)->GetWindowTree()->window_manager_internal_->WmSetProperty( - wm_change_id, WindowIdToTransportId(window->id()), name, + WindowTreeImpl* wm_window_tree = GetHost(window)->GetWindowTree(); + wm_window_tree->window_manager_internal_->WmSetProperty( + wm_change_id, wm_window_tree->ClientWindowIdForWindow(window).id, name, std::move(value)); return; } @@ -971,7 +1044,8 @@ void WindowTreeImpl::AttachSurface( mojom::SurfaceType type, mojo::InterfaceRequest<mojom::Surface> surface, mojom::SurfaceClientPtr client) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); const bool success = window && access_policy_->CanSetWindowSurface(window, type); if (!success) @@ -981,7 +1055,8 @@ void WindowTreeImpl::AttachSurface( void WindowTreeImpl::SetWindowTextInputState(Id transport_window_id, mojo::TextInputStatePtr state) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); bool success = window && access_policy_->CanSetWindowTextInputState(window); if (success) window->SetTextInputState(state.To<ui::TextInputState>()); @@ -990,7 +1065,8 @@ void WindowTreeImpl::SetWindowTextInputState(Id transport_window_id, void WindowTreeImpl::SetImeVisibility(Id transport_window_id, bool visible, mojo::TextInputStatePtr state) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); bool success = window && access_policy_->CanSetWindowTextInputState(window); if (success) { if (!state.is_null()) @@ -1034,7 +1110,8 @@ void WindowTreeImpl::SetClientArea( Id transport_window_id, mojo::InsetsPtr insets, mojo::Array<mojo::RectPtr> transport_additional_client_areas) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); if (!window || !access_policy_->CanSetClientArea(window)) return; @@ -1048,13 +1125,14 @@ void WindowTreeImpl::Embed(Id transport_window_id, uint32_t policy_bitmask, const EmbedCallback& callback) { ConnectionSpecificId connection_id = kInvalidConnectionId; - const bool result = Embed(MapWindowIdFromClient(transport_window_id), + const bool result = Embed(ClientWindowId(transport_window_id), std::move(client), policy_bitmask, &connection_id); callback.Run(result, connection_id); } void WindowTreeImpl::SetFocus(uint32_t change_id, Id transport_window_id) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); // TODO(beng): consider shifting non-policy drawn check logic to VTH's // FocusController. // TODO(sky): this doesn't work to clear focus. That is because if window is @@ -1070,7 +1148,8 @@ void WindowTreeImpl::SetFocus(uint32_t change_id, Id transport_window_id) { } void WindowTreeImpl::SetCanFocus(Id transport_window_id, bool can_focus) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); // TODO(sky): there should be an else case (it shouldn't route to wm and // policy allows, then set_can_focus). if (window && ShouldRouteToWindowManager(window)) @@ -1080,7 +1159,8 @@ void WindowTreeImpl::SetCanFocus(Id transport_window_id, bool can_focus) { void WindowTreeImpl::SetPredefinedCursor(uint32_t change_id, Id transport_window_id, mus::mojom::Cursor cursor_id) { - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); // Only the owner of the window can change the bounds. bool success = window && access_policy_->CanSetCursorProperties(window); @@ -1118,11 +1198,13 @@ void WindowTreeImpl::WmRequestClose(Id transport_window_id) { if (!host) return; - ServerWindow* window = GetWindow(MapWindowIdFromClient(transport_window_id)); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); WindowTreeImpl* connection = connection_manager_->GetConnectionWithRoot(window); if (connection && connection != host->GetWindowTree()) - connection->client_->RequestClose(connection->MapWindowIdToClient(window)); + connection->client_->RequestClose( + connection->ClientWindowIdForWindow(window).id); // TODO(sky): think about what else case means. } @@ -1135,8 +1217,14 @@ void WindowTreeImpl::WmSetFrameDecorationValues( void WindowTreeImpl::OnWmCreatedTopLevelWindow(uint32_t change_id, Id transport_window_id) { if (GetHostForWindowManager()) { - connection_manager_->WindowManagerCreatedTopLevelWindow( - this, change_id, transport_window_id); + ServerWindow* window = + GetWindowByClientId(ClientWindowId(transport_window_id)); + if (window && window->id().connection_id != id_) { + connection_manager_->WindowManagerSentBogusMessage(); + window = nullptr; + } + connection_manager_->WindowManagerCreatedTopLevelWindow(this, change_id, + window); } // TODO(sky): think about what else case means. } diff --git a/components/mus/ws/window_tree_impl.h b/components/mus/ws/window_tree_impl.h index af39c28..2ebc383 100644 --- a/components/mus/ws/window_tree_impl.h +++ b/components/mus/ws/window_tree_impl.h @@ -64,6 +64,23 @@ class WindowTreeImpl : public mojom::WindowTree, } const ServerWindow* GetWindow(const WindowId& id) const; + // Returns the Window with the specified client id *only* if known to this + // client, returns null if not known. + ServerWindow* GetWindowByClientId(const ClientWindowId& id) { + return const_cast<ServerWindow*>( + const_cast<const WindowTreeImpl*>(this)->GetWindowByClientId(id)); + } + const ServerWindow* GetWindowByClientId(const ClientWindowId& id) const; + + bool IsWindowKnown(const ServerWindow* window) const { + return IsWindowKnown(window, nullptr); + } + // Returns whether |window| is known to this connection. If |window| is + // known and |client_window_id| is non-null |client_window_id| is set to + // the ClientWindowId of the window. + bool IsWindowKnown(const ServerWindow* window, + ClientWindowId* client_window_id) const; + // Returns true if |window| is one of this connections roots. bool HasRoot(const ServerWindow* window) const; @@ -84,15 +101,16 @@ class WindowTreeImpl : public mojom::WindowTree, // These functions are synchronous variants of those defined in the mojom. The // WindowTree implementations all call into these. See the mojom for details. - bool NewWindow(const WindowId& window_id, + bool NewWindow(const ClientWindowId& client_window_id, const std::map<std::string, std::vector<uint8_t>>& properties); - bool AddWindow(const WindowId& parent_id, const WindowId& child_id); - bool AddTransientWindow(const WindowId& window_id, - const WindowId& transient_window_id); + bool AddWindow(const ClientWindowId& parent_id, + const ClientWindowId& child_id); + bool AddTransientWindow(const ClientWindowId& window_id, + const ClientWindowId& transient_window_id); std::vector<const ServerWindow*> GetWindowTree( - const WindowId& window_id) const; - bool SetWindowVisibility(const WindowId& window_id, bool visible); - bool Embed(const WindowId& window_id, + const ClientWindowId& window_id) const; + bool SetWindowVisibility(const ClientWindowId& window_id, bool visible); + bool Embed(const ClientWindowId& window_id, mojom::WindowTreeClientPtr client, uint32_t policy_bitmask, ConnectionSpecificId* connection_id); @@ -101,18 +119,7 @@ class WindowTreeImpl : public mojom::WindowTree, bool IsWaitingForNewTopLevelWindow(uint32_t wm_change_id); void OnWindowManagerCreatedTopLevelWindow(uint32_t wm_change_id, uint32_t client_change_id, - const WindowId& window_id); - - // Maps the window id from the client to the server. Normally the ids are the - // same, but there may be a different id at the embed point. - WindowId MapWindowIdFromClient(Id transport_window_id) const { - return MapWindowIdFromClient(WindowIdFromTransportId(transport_window_id)); - } - WindowId MapWindowIdFromClient(const WindowId& id) const; - - // Maps the window id to the client. - Id MapWindowIdToClient(const ServerWindow* window) const; - Id MapWindowIdToClient(const WindowId& id) const; + const ServerWindow* window); // Calls through to the client. void OnChangeCompleted(uint32_t change_id, bool success); @@ -165,17 +172,16 @@ class WindowTreeImpl : public mojom::WindowTree, bool originated_change); private: - using WindowIdSet = base::hash_set<Id>; - using WindowMap = std::map<ConnectionSpecificId, ServerWindow*>; friend class WindowTreeTest; struct WaitingForTopLevelWindowInfo { - WaitingForTopLevelWindowInfo(WindowId window_id, uint32_t wm_change_id) - : window_id(window_id), wm_change_id(wm_change_id) {} + WaitingForTopLevelWindowInfo(const ClientWindowId& client_window_id, + uint32_t wm_change_id) + : client_window_id(client_window_id), wm_change_id(wm_change_id) {} ~WaitingForTopLevelWindowInfo() {} // Id supplied from the client. - WindowId window_id; + ClientWindowId client_window_id; // Change id we created for the window manager. uint32_t wm_change_id; @@ -194,10 +200,12 @@ class WindowTreeImpl : public mojom::WindowTree, bool ShouldRouteToWindowManager(const ServerWindow* window) const; - bool IsWindowKnown(const ServerWindow* window) const; + ClientWindowId ClientWindowIdForWindow(const ServerWindow* window) const; // Returns true if |id| is a valid WindowId for a new window. - bool IsValidIdForNewWindow(const WindowId& id) const; + bool IsValidIdForNewWindow(const ClientWindowId& id) const; + + WindowId GenerateNewWindowId(); // These functions return true if the corresponding mojom function is allowed // for this connection. @@ -209,13 +217,17 @@ class WindowTreeImpl : public mojom::WindowTree, // |source| is the connection that originated the change. bool DeleteWindowImpl(WindowTreeImpl* source, ServerWindow* window); - // If |window| is known (in |known_windows_|) does nothing. Otherwise adds - // |window| to |windows|, marks |window| as known and recurses. + // If |window| is known does nothing. Otherwise adds |window| to |windows|, + // marks |window| as known and recurses. void GetUnknownWindowsFrom(const ServerWindow* window, std::vector<const ServerWindow*>* windows); - // Removes |window| and all its descendants from |known_windows_|. This does - // not recurse through windows that were created by this connection. All + // Removes |window| from the appropriate maps. If |window| is known to this + // client true is returned. + bool RemoveFromMaps(const ServerWindow* window); + + // Removes |window| and all its descendants from the necessary maps. This + // does not recurse through windows that were created by this connection. All // windows owned by this connection are added to |local_windows|. void RemoveFromKnown(const ServerWindow* window, std::vector<ServerWindow*>* local_windows); @@ -244,9 +256,9 @@ class WindowTreeImpl : public mojom::WindowTree, // Deletes all Windows we own. void DestroyWindows(); - bool CanEmbed(const WindowId& window_id, uint32_t policy_bitmask) const; - void PrepareForEmbed(const WindowId& window_id); - void RemoveChildrenAsPartOfEmbed(const WindowId& window_id); + bool CanEmbed(const ClientWindowId& window_id, uint32_t policy_bitmask) const; + void PrepareForEmbed(ServerWindow* window); + void RemoveChildrenAsPartOfEmbed(ServerWindow* window); void DispatchInputEventImpl(ServerWindow* target, mojom::EventPtr event); @@ -267,8 +279,8 @@ class WindowTreeImpl : public mojom::WindowTree, void AddWindow(uint32_t change_id, Id parent_id, Id child_id) override; void RemoveWindowFromParent(uint32_t change_id, Id window_id) override; void AddTransientWindow(uint32_t change_id, - Id window_id, - Id transient_window_id) override; + Id window, + Id transient_window) override; void RemoveTransientWindowFromParent(uint32_t change_id, Id transient_window_id) override; void ReorderWindow(uint32_t change_Id, @@ -336,20 +348,25 @@ class WindowTreeImpl : public mojom::WindowTree, // Id of this connection as assigned by ConnectionManager. const ConnectionSpecificId id_; + ConnectionSpecificId next_window_id_; + mojom::WindowTreeClient* client_; scoped_ptr<mus::ws::AccessPolicy> access_policy_; - // The windows created by this connection. This connection owns these objects. - WindowMap window_map_; - - // The set of windows that has been communicated to the client. - WindowIdSet known_windows_; - // The roots, or embed points, of this connection. A WindowTreeImpl may have // any number of roots, including 0. std::set<const ServerWindow*> roots_; + // The windows created by this connection. This connection owns these objects. + base::hash_map<WindowId, ServerWindow*> created_window_map_; + + // The client is allowed to assign ids. These two maps providing the mapping + // from the ids native to the server (WindowId) to those understood by the + // client (ClientWindowId). + base::hash_map<ClientWindowId, WindowId> client_id_to_window_id_map_; + base::hash_map<WindowId, ClientWindowId> window_id_to_client_id_map_; + uint32_t event_ack_id_; // WindowTreeHostImpl the current event came from. @@ -363,8 +380,6 @@ class WindowTreeImpl : public mojom::WindowTree, window_manager_internal_client_binding_; mojom::WindowManagerInternal* window_manager_internal_; - std::map<WindowId, WindowId> embed_to_real_id_map_; - scoped_ptr<WaitingForTopLevelWindowInfo> waiting_for_top_level_window_info_; DISALLOW_COPY_AND_ASSIGN(WindowTreeImpl); diff --git a/components/mus/ws/window_tree_unittest.cc b/components/mus/ws/window_tree_unittest.cc index d985e6e..0bd503f 100644 --- a/components/mus/ws/window_tree_unittest.cc +++ b/components/mus/ws/window_tree_unittest.cc @@ -50,6 +50,19 @@ std::string WindowIdToString(const WindowId& id) { return base::StringPrintf("%d,%d", id.connection_id, id.window_id); } +ClientWindowId BuildClientWindowId(WindowTreeImpl* tree, + ConnectionSpecificId window_id) { + return ClientWindowId(WindowIdToTransportId(WindowId(tree->id(), window_id))); +} + +ClientWindowId ClientWindowIdForWindow(WindowTreeImpl* tree, + const ServerWindow* window) { + ClientWindowId client_window_id; + // If window isn't known we'll return 0, which should then error out. + tree->IsWindowKnown(window, &client_window_id); + return client_window_id; +} + class TestWindowManagerInternal : public mojom::WindowManagerInternal { public: TestWindowManagerInternal() @@ -379,6 +392,13 @@ const ServerWindow* FirstRoot(WindowTreeImpl* connection) { : nullptr; } +ClientWindowId FirstRootId(WindowTreeImpl* connection) { + return connection->roots().size() == 1u + ? ClientWindowIdForWindow(connection, + *(connection->roots().begin())) + : ClientWindowId(); +} + } // namespace // ----------------------------------------------------------------------------- @@ -477,16 +497,19 @@ class WindowTreeTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(WindowTreeTest); }; +// Creates a new window in wm_connection(), adds it to the root, embeds a +// new client in the window and creates a child of said window. |window| is +// set to the child of |window_tree_connection| that is created. void WindowTreeTest::SetupEventTargeting( TestWindowTreeClient** out_client, WindowTreeImpl** window_tree_connection, ServerWindow** window) { - const WindowId embed_window_id(wm_connection()->id(), 1); + const ClientWindowId embed_window_id = + BuildClientWindowId(wm_connection(), 1); EXPECT_TRUE( wm_connection()->NewWindow(embed_window_id, ServerWindow::Properties())); EXPECT_TRUE(wm_connection()->SetWindowVisibility(embed_window_id, true)); - ASSERT_TRUE(FirstRoot(wm_connection())); - EXPECT_TRUE(wm_connection()->AddWindow(FirstRoot(wm_connection())->id(), + EXPECT_TRUE(wm_connection()->AddWindow(FirstRootId(wm_connection()), embed_window_id)); host_connection()->window_tree_host()->root_window()->SetBounds( gfx::Rect(0, 0, 100, 100)); @@ -498,25 +521,26 @@ void WindowTreeTest::SetupEventTargeting( wm_connection()->Embed(embed_window_id, std::move(client), mojom::WindowTree::kAccessPolicyDefault, &connection_id); - WindowTreeImpl* connection1 = connection_manager()->GetConnectionWithRoot( - GetWindowById(embed_window_id)); + ServerWindow* embed_window = + wm_connection()->GetWindowByClientId(embed_window_id); + WindowTreeImpl* connection1 = + connection_manager()->GetConnectionWithRoot(embed_window); ASSERT_TRUE(connection1 != nullptr); ASSERT_NE(connection1, wm_connection()); - connection_manager() - ->GetWindow(embed_window_id) - ->SetBounds(gfx::Rect(0, 0, 50, 50)); + embed_window->SetBounds(gfx::Rect(0, 0, 50, 50)); - const WindowId child1(connection1->id(), 1); - EXPECT_TRUE(connection1->NewWindow(child1, ServerWindow::Properties())); - EXPECT_TRUE(connection1->AddWindow(embed_window_id, child1)); - connection1->GetHost(GetWindowById(embed_window_id)) - ->AddActivationParent(WindowIdToTransportId(embed_window_id)); + const ClientWindowId child1_id(BuildClientWindowId(connection1, 1)); + EXPECT_TRUE(connection1->NewWindow(child1_id, ServerWindow::Properties())); + ServerWindow* child1 = connection1->GetWindowByClientId(child1_id); + ASSERT_TRUE(child1); + EXPECT_TRUE(connection1->AddWindow( + ClientWindowIdForWindow(connection1, embed_window), child1_id)); + connection1->GetHost(embed_window)->AddActivationParent(embed_window_id.id); - ServerWindow* v1 = connection1->GetWindow(child1); - v1->SetVisible(true); - v1->SetBounds(gfx::Rect(20, 20, 20, 20)); - EnableHitTest(v1); + child1->SetVisible(true); + child1->SetBounds(gfx::Rect(20, 20, 20, 20)); + EnableHitTest(child1); TestWindowTreeClient* embed_connection = last_window_tree_client(); embed_connection->tracker()->changes()->clear(); @@ -524,18 +548,22 @@ void WindowTreeTest::SetupEventTargeting( *out_client = embed_connection; *window_tree_connection = connection1; - *window = v1; + *window = child1; } // Verifies focus correctly changes on pointer events. TEST_F(WindowTreeTest, FocusOnPointer) { - const WindowId embed_window_id(wm_connection()->id(), 1); + const ClientWindowId embed_window_id = + BuildClientWindowId(wm_connection(), 1); EXPECT_TRUE( wm_connection()->NewWindow(embed_window_id, ServerWindow::Properties())); + ServerWindow* embed_window = + wm_connection()->GetWindowByClientId(embed_window_id); + ASSERT_TRUE(embed_window); EXPECT_TRUE(wm_connection()->SetWindowVisibility(embed_window_id, true)); ASSERT_TRUE(FirstRoot(wm_connection())); - EXPECT_TRUE(wm_connection()->AddWindow(FirstRoot(wm_connection())->id(), - embed_window_id)); + const ClientWindowId wm_root_id = FirstRootId(wm_connection()); + EXPECT_TRUE(wm_connection()->AddWindow(wm_root_id, embed_window_id)); host_connection()->window_tree_host()->root_window()->SetBounds( gfx::Rect(0, 0, 100, 100)); mojom::WindowTreeClientPtr client; @@ -546,22 +574,22 @@ TEST_F(WindowTreeTest, FocusOnPointer) { wm_connection()->Embed(embed_window_id, std::move(client), mojom::WindowTree::kAccessPolicyDefault, &connection_id); - WindowTreeImpl* connection1 = connection_manager()->GetConnectionWithRoot( - GetWindowById(embed_window_id)); + WindowTreeImpl* connection1 = + connection_manager()->GetConnectionWithRoot(embed_window); ASSERT_TRUE(connection1 != nullptr); ASSERT_NE(connection1, wm_connection()); - connection_manager() - ->GetWindow(embed_window_id) - ->SetBounds(gfx::Rect(0, 0, 50, 50)); + embed_window->SetBounds(gfx::Rect(0, 0, 50, 50)); - const WindowId child1(connection1->id(), 1); - EXPECT_TRUE(connection1->NewWindow(child1, ServerWindow::Properties())); - EXPECT_TRUE(connection1->AddWindow(embed_window_id, child1)); - ServerWindow* v1 = connection1->GetWindow(child1); - v1->SetVisible(true); - v1->SetBounds(gfx::Rect(20, 20, 20, 20)); - EnableHitTest(v1); + const ClientWindowId child1_id(BuildClientWindowId(connection1, 1)); + EXPECT_TRUE(connection1->NewWindow(child1_id, ServerWindow::Properties())); + EXPECT_TRUE(connection1->AddWindow( + ClientWindowIdForWindow(connection1, embed_window), child1_id)); + ServerWindow* child1 = connection1->GetWindowByClientId(child1_id); + ASSERT_TRUE(child1); + child1->SetVisible(true); + child1->SetBounds(gfx::Rect(20, 20, 20, 20)); + EnableHitTest(child1); TestWindowTreeClient* connection1_client = last_window_tree_client(); connection1_client->tracker()->changes()->clear(); @@ -570,19 +598,18 @@ TEST_F(WindowTreeTest, FocusOnPointer) { // Focus should not go to |child1| yet, since the parent still doesn't allow // active children. DispatchEventAndAckImmediately(CreatePointerDownEvent(21, 22)); - WindowTreeHostImpl* host1 = - connection1->GetHost(GetWindowById(embed_window_id)); + WindowTreeHostImpl* host1 = connection1->GetHost(embed_window); EXPECT_EQ(nullptr, host1->GetFocusedWindow()); DispatchEventAndAckImmediately(CreatePointerUpEvent(21, 22)); connection1_client->tracker()->changes()->clear(); wm_client()->tracker()->changes()->clear(); - host1->AddActivationParent(WindowIdToTransportId(embed_window_id)); + host1->AddActivationParent(embed_window_id.id); // Focus should go to child1. This result in notifying both the window // manager and client connection being notified. DispatchEventAndAckImmediately(CreatePointerDownEvent(21, 22)); - EXPECT_EQ(v1, host1->GetFocusedWindow()); + EXPECT_EQ(child1, host1->GetFocusedWindow()); ASSERT_GE(wm_client()->tracker()->changes()->size(), 1u); EXPECT_EQ("Focused id=2,1", ChangesToDescription1(*wm_client()->tracker()->changes())[0]); @@ -598,7 +625,7 @@ TEST_F(WindowTreeTest, FocusOnPointer) { // Press outside of the embedded window. Note that root cannot be focused // (because it cannot be activated). So the focus would not move in this case. DispatchEventAndAckImmediately(CreatePointerDownEvent(61, 22)); - EXPECT_EQ(v1, host_connection()->window_tree_host()->GetFocusedWindow()); + EXPECT_EQ(child1, host_connection()->window_tree_host()->GetFocusedWindow()); DispatchEventAndAckImmediately(CreatePointerUpEvent(21, 22)); wm_client()->tracker()->changes()->clear(); @@ -607,7 +634,7 @@ TEST_F(WindowTreeTest, FocusOnPointer) { // Press in the same location. Should not get a focus change event (only input // event). DispatchEventAndAckImmediately(CreatePointerDownEvent(61, 22)); - EXPECT_EQ(v1, host_connection()->window_tree_host()->GetFocusedWindow()); + EXPECT_EQ(child1, host_connection()->window_tree_host()->GetFocusedWindow()); ASSERT_EQ(wm_client()->tracker()->changes()->size(), 1u) << SingleChangeToDescription(*wm_client()->tracker()->changes()); EXPECT_EQ("InputEvent window=0,2 event_action=4", @@ -749,39 +776,39 @@ TEST_F(WindowTreeTest, WindowReorderingChangesCursor) { &embed_connection, &window_tree_connection, &window1)); // Create a second window right over the first. - const WindowId embed_window_id(wm_connection()->id(), 1); - const WindowId child2(window_tree_connection->id(), 2); + const ClientWindowId embed_window_id(FirstRootId(window_tree_connection)); + const ClientWindowId child2_id( + BuildClientWindowId(window_tree_connection, 2)); EXPECT_TRUE( - window_tree_connection->NewWindow(child2, ServerWindow::Properties())); - EXPECT_TRUE(window_tree_connection->AddWindow(embed_window_id, child2)); - window_tree_connection->GetHost( - GetWindowById(WindowId(wm_connection()->id(), 1))) - ->AddActivationParent(WindowIdToTransportId(embed_window_id)); - ServerWindow* window2 = window_tree_connection->GetWindow(child2); - window2->SetVisible(true); - window2->SetBounds(gfx::Rect(20, 20, 20, 20)); - EnableHitTest(window2); + window_tree_connection->NewWindow(child2_id, ServerWindow::Properties())); + ServerWindow* child2 = window_tree_connection->GetWindowByClientId(child2_id); + ASSERT_TRUE(child2); + EXPECT_TRUE(window_tree_connection->AddWindow(embed_window_id, child2_id)); + child2->SetVisible(true); + child2->SetBounds(gfx::Rect(20, 20, 20, 20)); + EnableHitTest(child2); // Give each window a different cursor. window1->SetPredefinedCursor(mojom::Cursor::IBEAM); - window2->SetPredefinedCursor(mojom::Cursor::HAND); + child2->SetPredefinedCursor(mojom::Cursor::HAND); // We expect window2 to be over window1 now. DispatchEventAndAckImmediately(CreateMouseMoveEvent(22, 22)); EXPECT_EQ(mojom::Cursor::HAND, cursor_id()); // But when we put window2 at the bottom, we should adapt window1's cursor. - window2->parent()->StackChildAtBottom(window2); + child2->parent()->StackChildAtBottom(child2); EXPECT_EQ(mojom::Cursor::IBEAM, cursor_id()); } TEST_F(WindowTreeTest, EventAck) { - const WindowId embed_window_id(wm_connection()->id(), 1); + const ClientWindowId embed_window_id = + BuildClientWindowId(wm_connection(), 1); EXPECT_TRUE( wm_connection()->NewWindow(embed_window_id, ServerWindow::Properties())); EXPECT_TRUE(wm_connection()->SetWindowVisibility(embed_window_id, true)); ASSERT_TRUE(FirstRoot(wm_connection())); - EXPECT_TRUE(wm_connection()->AddWindow(FirstRoot(wm_connection())->id(), + EXPECT_TRUE(wm_connection()->AddWindow(FirstRootId(wm_connection()), embed_window_id)); host_connection()->window_tree_host()->root_window()->SetBounds( gfx::Rect(0, 0, 100, 100)); @@ -821,10 +848,10 @@ TEST_F(WindowTreeTest, NewTopLevelWindow) { mojo::Map<mojo::String, mojo::Array<uint8_t>> properties; properties.mark_non_null(); const uint32_t initial_change_id = 17; - const WindowId embed_window_id2_in_child(window_tree_connection->id(), 101); + // Explicitly use an id that does not contain the connection id. + const ClientWindowId embed_window_id2_in_child(45 << 16 | 27); static_cast<mojom::WindowTree*>(window_tree_connection) - ->NewTopLevelWindow(initial_change_id, - WindowIdToTransportId(embed_window_id2_in_child), + ->NewTopLevelWindow(initial_change_id, embed_window_id2_in_child.id, std::move(properties)); // The binding should be paused until the wm acks the change. @@ -833,31 +860,36 @@ TEST_F(WindowTreeTest, NewTopLevelWindow) { EXPECT_TRUE(last_client_connection()->is_paused()); // Create the window for |embed_window_id2_in_child|. - const WindowId embed_window_id2(wm_connection()->id(), 2); + const ClientWindowId embed_window_id2 = + BuildClientWindowId(wm_connection(), 2); EXPECT_TRUE( wm_connection()->NewWindow(embed_window_id2, ServerWindow::Properties())); - EXPECT_TRUE(wm_connection()->AddWindow(FirstRoot(wm_connection())->id(), + EXPECT_TRUE(wm_connection()->AddWindow(FirstRootId(wm_connection()), embed_window_id2)); // Ack the change, which should resume the binding. static_cast<mojom::WindowManagerInternalClient*>(wm_connection()) - ->OnWmCreatedTopLevelWindow(wm_change_id, - WindowIdToTransportId(embed_window_id2)); + ->OnWmCreatedTopLevelWindow(wm_change_id, embed_window_id2.id); EXPECT_FALSE(last_client_connection()->is_paused()); EXPECT_EQ("TopLevelCreated id=17 window_id=" + - WindowIdToString(embed_window_id2_in_child), + WindowIdToString( + WindowIdFromTransportId(embed_window_id2_in_child.id)), SingleChangeToDescription(*embed_connection->tracker()->changes())); embed_connection->tracker()->changes()->clear(); // Change the visibility of the window from the owner and make sure the // client sees the right id. - ServerWindow* embed_window = wm_connection()->GetWindow(embed_window_id2); + ServerWindow* embed_window = + wm_connection()->GetWindowByClientId(embed_window_id2); ASSERT_TRUE(embed_window); EXPECT_FALSE(embed_window->visible()); - ASSERT_TRUE(wm_connection()->SetWindowVisibility(embed_window->id(), true)); + ASSERT_TRUE(wm_connection()->SetWindowVisibility( + ClientWindowIdForWindow(wm_connection(), embed_window), true)); EXPECT_TRUE(embed_window->visible()); EXPECT_EQ("VisibilityChanged window=" + - WindowIdToString(embed_window_id2_in_child) + " visible=true", + WindowIdToString( + WindowIdFromTransportId(embed_window_id2_in_child.id)) + + " visible=true", SingleChangeToDescription(*embed_connection->tracker()->changes())); // Set the visibility from the child using the client assigned id. |