Index: components/mus/ws/window_tree_impl.cc |
diff --git a/components/mus/ws/window_tree_impl.cc b/components/mus/ws/window_tree_impl.cc |
index 2d6611f996c585c053bd37ccc22d6e2fa34559dd..9bf699d8aa22759efe5d5d843e56ff726b2d36c6 100644 |
--- a/components/mus/ws/window_tree_impl.cc |
+++ b/components/mus/ws/window_tree_impl.cc |
@@ -141,6 +141,12 @@ void WindowTreeImpl::OnWillDestroyWindowTreeImpl(WindowTreeImpl* connection) { |
} |
} |
+void WindowTreeImpl::OnWillDestroyWindowTreeHost( |
+ WindowTreeHostImpl* tree_host) { |
+ if (event_source_host_ == tree_host) |
+ event_source_host_ = nullptr; |
+} |
+ |
void WindowTreeImpl::NotifyChangeCompleted( |
uint32_t change_id, |
mojom::WindowManagerErrorCode error_code) { |
@@ -246,8 +252,32 @@ void WindowTreeImpl::DispatchInputEvent(ServerWindow* target, |
DispatchInputEventImpl(target, std::move(event)); |
} |
+bool WindowTreeImpl::IsWaitingForNewTopLevelWindow(uint32_t wm_change_id) { |
+ return waiting_for_top_level_window_info_ && |
+ waiting_for_top_level_window_info_->wm_change_id == wm_change_id; |
+} |
+ |
+void WindowTreeImpl::OnWindowManagerCreatedTopLevelWindow( |
+ uint32_t wm_change_id, |
+ uint32_t client_change_id, |
+ const WindowId& window_id) { |
+ 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); |
+ roots_.insert(window); |
+ GetUnknownWindowsFrom(window, &unused); |
+ client_->OnChangeCompleted(client_change_id, true); |
+} |
+ |
WindowId WindowTreeImpl::MapWindowIdFromClient(const WindowId& id) const { |
- return id; |
+ 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 { |
@@ -255,6 +285,12 @@ Id WindowTreeImpl::MapWindowIdToClient(const ServerWindow* window) const { |
} |
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); |
} |
@@ -512,7 +548,8 @@ bool WindowTreeImpl::IsWindowKnown(const ServerWindow* window) const { |
} |
bool WindowTreeImpl::IsValidIdForNewWindow(const WindowId& id) const { |
- return id.connection_id == id_ && window_map_.count(id.window_id) == 0; |
+ return id.connection_id == id_ && embed_to_real_id_map_.count(id) == 0 && |
+ window_map_.count(id.window_id) == 0; |
} |
bool WindowTreeImpl::CanReorderWindow(const ServerWindow* window, |
@@ -584,6 +621,13 @@ void WindowTreeImpl::RemoveRoot(const ServerWindow* window, |
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; |
+ } |
+ } |
+ |
// No need to do anything if we created the window. |
if (window->id().connection_id == id_) |
return; |
@@ -745,6 +789,38 @@ void WindowTreeImpl::NewWindow( |
NewWindow(MapWindowIdFromClient(transport_window_id), properties)); |
} |
+void WindowTreeImpl::NewTopLevelWindow( |
+ uint32_t change_id, |
+ 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)); |
+ // 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)) { |
+ client_->OnChangeCompleted(change_id, false); |
+ return; |
+ } |
+ |
+ // The server creates the real window. Any further messages from the client |
+ // may try to alter the window. Pause incoming messages so that we know we |
+ // can't get a message for a window before the window is created. Once the |
+ // window is created we'll resume processing. |
+ connection_manager_->GetClientConnection(this) |
+ ->SetIncomingMethodCallProcessingPaused(true); |
+ |
+ const uint32_t wm_change_id = |
+ connection_manager_->GenerateWindowManagerChangeId(this, change_id); |
+ |
+ waiting_for_top_level_window_info_.reset( |
+ new WaitingForTopLevelWindowInfo(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)); |
bool success = false; |
@@ -989,7 +1065,7 @@ 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)); |
- // TODO(sky): there should be an else case (if shouldn't route to wm and |
+ // 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)) |
window->set_can_focus(can_focus); |
@@ -1044,6 +1120,15 @@ void WindowTreeImpl::WmRequestClose(Id transport_window_id) { |
// TODO(sky): think about what else case means. |
} |
+void WindowTreeImpl::OnWmCreatedTopLevelWindow(uint32_t change_id, |
+ Id transport_window_id) { |
+ if (GetHostForWindowManager()) { |
+ connection_manager_->WindowManagerCreatedTopLevelWindow( |
+ this, change_id, transport_window_id); |
+ } |
+ // TODO(sky): think about what else case means. |
+} |
+ |
bool WindowTreeImpl::HasRootForAccessPolicy(const ServerWindow* window) const { |
return HasRoot(window); |
} |