// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef COMPONENTS_MUS_WS_CONNECTION_MANAGER_H_ #define COMPONENTS_MUS_WS_CONNECTION_MANAGER_H_ #include <map> #include <set> #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/timer/timer.h" #include "components/mus/public/interfaces/window_tree.mojom.h" #include "components/mus/public/interfaces/window_tree_host.mojom.h" #include "components/mus/surfaces/surfaces_state.h" #include "components/mus/ws/focus_controller_delegate.h" #include "components/mus/ws/ids.h" #include "components/mus/ws/server_window_delegate.h" #include "components/mus/ws/server_window_observer.h" #include "components/mus/ws/window_tree_host_impl.h" #include "mojo/converters/surfaces/custom_surface_converter.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/array.h" #include "third_party/mojo/src/mojo/public/cpp/bindings/binding.h" namespace mus { namespace ws { class ClientConnection; class ConnectionManagerDelegate; class ServerWindow; class WindowTreeHostConnection; class WindowTreeImpl; // ConnectionManager manages the set of connections to the window server (all // the WindowTreeImpls) as well as providing the root of the hierarchy. class ConnectionManager : public ServerWindowDelegate, public ServerWindowObserver { public: // Create when a WindowTreeImpl is about to make a change. Ensures clients are // notified correctly. class ScopedChange { public: ScopedChange(WindowTreeImpl* connection, ConnectionManager* connection_manager, bool is_delete_window); ~ScopedChange(); ConnectionSpecificId connection_id() const { return connection_id_; } bool is_delete_window() const { return is_delete_window_; } // Marks the connection with the specified id as having seen a message. void MarkConnectionAsMessaged(ConnectionSpecificId connection_id) { message_ids_.insert(connection_id); } // Returns true if MarkConnectionAsMessaged(connection_id) was invoked. bool DidMessageConnection(ConnectionSpecificId connection_id) const { return message_ids_.count(connection_id) > 0; } private: ConnectionManager* connection_manager_; const ConnectionSpecificId connection_id_; const bool is_delete_window_; // See description of MarkConnectionAsMessaged/DidMessageConnection. std::set<ConnectionSpecificId> message_ids_; DISALLOW_COPY_AND_ASSIGN(ScopedChange); }; ConnectionManager(ConnectionManagerDelegate* delegate, const scoped_refptr<mus::SurfacesState>& surfaces_state); ~ConnectionManager() override; // Adds a WindowTreeHost. void AddHost(WindowTreeHostConnection* connection); // Creates a new ServerWindow. The return value is owned by the caller, but // must be destroyed before ConnectionManager. ServerWindow* CreateServerWindow(const WindowId& id); // Returns the id for the next WindowTreeImpl. ConnectionSpecificId GetAndAdvanceNextConnectionId(); // Returns the id for the next WindowTreeHostImpl. uint16_t GetAndAdvanceNextHostId(); // Invoked when a WindowTreeImpl's connection encounters an error. void OnConnectionError(ClientConnection* connection); // Invoked when a WindowTreeHostConnection encounters an error or the // associated Display window is closed. void OnHostConnectionClosed(WindowTreeHostConnection* connection); // See description of WindowTree::Embed() for details. This assumes // |transport_window_id| is valid. WindowTreeImpl* EmbedAtWindow(ConnectionSpecificId creator_id, const WindowId& window_id, uint32_t policy_bitmask, mojom::WindowTreeClientPtr client); // Returns the connection by id. WindowTreeImpl* GetConnection(ConnectionSpecificId connection_id); // Returns the Window identified by |id|. ServerWindow* GetWindow(const WindowId& id); // Returns whether |window| is a descendant of some root window but not itself // a root window. bool IsWindowAttachedToRoot(const ServerWindow* window) const; // Schedules a paint for the specified region in the coordinates of |window|. void SchedulePaint(const ServerWindow* window, const gfx::Rect& bounds); bool IsProcessingChange() const { return current_change_ != nullptr; } bool is_processing_delete_window() const { return current_change_ && current_change_->is_delete_window(); } // Invoked when the WindowTreeHostImpl's display is closed. void OnDisplayClosed(); // Invoked when a connection messages a client about the change. This is used // to avoid sending ServerChangeIdAdvanced() unnecessarily. void OnConnectionMessagedClient(ConnectionSpecificId id); // Returns true if OnConnectionMessagedClient() was invoked for id. bool DidConnectionMessageClient(ConnectionSpecificId id) const; // Returns the metrics of the viewport where the provided |window| is // displayed. mojom::ViewportMetricsPtr GetViewportMetricsForWindow( const ServerWindow* window); // Returns the WindowTreeImpl that has |id| as a root. WindowTreeImpl* GetConnectionWithRoot(const WindowId& id) { return const_cast<WindowTreeImpl*>( const_cast<const ConnectionManager*>(this)->GetConnectionWithRoot(id)); } const WindowTreeImpl* GetConnectionWithRoot(const WindowId& id) const; WindowTreeHostImpl* GetWindowTreeHostByWindow(const ServerWindow* window); const WindowTreeHostImpl* GetWindowTreeHostByWindow( const ServerWindow* window) const; // Returns the first ancestor of |service| that is marked as an embed root. WindowTreeImpl* GetEmbedRoot(WindowTreeImpl* service); // WindowTreeHost implementation helper; see mojom for details. bool CloneAndAnimate(const WindowId& window_id); // These functions trivially delegate to all WindowTreeImpls, which in // term notify their clients. void ProcessWindowDestroyed(ServerWindow* window); void ProcessWindowBoundsChanged(const ServerWindow* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds); void ProcessClientAreaChanged(const ServerWindow* window, const gfx::Rect& old_client_area, const gfx::Rect& new_client_area); void ProcessViewportMetricsChanged(const mojom::ViewportMetrics& old_metrics, const mojom::ViewportMetrics& new_metrics); void ProcessWillChangeWindowHierarchy(const ServerWindow* window, const ServerWindow* new_parent, const ServerWindow* old_parent); void ProcessWindowHierarchyChanged(const ServerWindow* window, const ServerWindow* new_parent, const ServerWindow* old_parent); void ProcessWindowReorder(const ServerWindow* window, const ServerWindow* relative_window, const mojom::OrderDirection direction); void ProcessWindowDeleted(const WindowId& window); private: using ConnectionMap = std::map<ConnectionSpecificId, ClientConnection*>; using HostConnectionMap = std::map<WindowTreeHostImpl*, WindowTreeHostConnection*>; // Invoked when a connection is about to make a change. Subsequently followed // by FinishChange() once the change is done. // // Changes should never nest, meaning each PrepareForChange() must be // balanced with a call to FinishChange() with no PrepareForChange() // in between. void PrepareForChange(ScopedChange* change); // Balances a call to PrepareForChange(). void FinishChange(); // Returns true if the specified connection originated the current change. bool IsChangeSource(ConnectionSpecificId connection_id) const { return current_change_ && current_change_->connection_id() == connection_id; } // Adds |connection| to internal maps. void AddConnection(ClientConnection* connection); // Overridden from ServerWindowDelegate: mus::SurfacesState* GetSurfacesState() override; void OnScheduleWindowPaint(const ServerWindow* window) override; const ServerWindow* GetRootWindow(const ServerWindow* window) const override; // Overridden from ServerWindowObserver: void OnWindowDestroyed(ServerWindow* window) override; void OnWillChangeWindowHierarchy(ServerWindow* window, ServerWindow* new_parent, ServerWindow* old_parent) override; void OnWindowHierarchyChanged(ServerWindow* window, ServerWindow* new_parent, ServerWindow* old_parent) override; void OnWindowBoundsChanged(ServerWindow* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds) override; void OnWindowClientAreaChanged(ServerWindow* window, const gfx::Rect& old_client_area, const gfx::Rect& new_client_area) override; void OnWindowReordered(ServerWindow* window, ServerWindow* relative, mojom::OrderDirection direction) override; void OnWillChangeWindowVisibility(ServerWindow* window) override; void OnWindowSharedPropertyChanged( ServerWindow* window, const std::string& name, const std::vector<uint8_t>* new_data) override; void OnWindowTextInputStateChanged(ServerWindow* window, const ui::TextInputState& state) override; ConnectionManagerDelegate* delegate_; // State for rendering into a Surface. scoped_refptr<mus::SurfacesState> surfaces_state_; // ID to use for next WindowTreeImpl. ConnectionSpecificId next_connection_id_; // ID to use for next WindowTreeHostImpl. uint16_t next_host_id_; // Set of WindowTreeImpls. ConnectionMap connection_map_; // Set of WindowTreeHostImpls. HostConnectionMap host_connection_map_; // If non-null we're processing a change. The ScopedChange is not owned by us // (it's created on the stack by WindowTreeImpl). ScopedChange* current_change_; bool in_destructor_; DISALLOW_COPY_AND_ASSIGN(ConnectionManager); }; } // namespace ws } // namespace mus #endif // COMPONENTS_MUS_WS_CONNECTION_MANAGER_H_