// Copyright 2018 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 SERVICES_WS_CLIENT_ROOT_H_ #define SERVICES_WS_CLIENT_ROOT_H_ #include #include "base/component_export.h" #include "base/macros.h" #include "base/optional.h" #include "components/viz/common/surfaces/local_surface_id.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/host/host_frame_sink_client.h" #include "ui/aura/window_observer.h" #include "ui/aura/window_tree_host_observer.h" #include "ui/display/display_observer.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" namespace aura { class ClientSurfaceEmbedder; class Window; } // namespace aura namespace aura_extra { class WindowPositionInRootMonitor; } namespace viz { class LocalSurfaceIdAllocation; class SurfaceInfo; } namespace ws { class ProxyWindow; class ScopedForceVisible; class WindowTree; // WindowTree creates a ClientRoot for each window the client is embedded in. A // ClientRoot is created as the result of another client using Embed(), or this // client requesting a top-level window. ClientRoot is responsible for // maintaining state associated with the root, as well as notifying the client // of any changes to the root Window. class COMPONENT_EXPORT(WINDOW_SERVICE) ClientRoot : public aura::WindowObserver, public aura::WindowTreeHostObserver, public display::DisplayObserver, public viz::HostFrameSinkClient { public: ClientRoot(WindowTree* window_tree, aura::Window* window, bool is_top_level); ~ClientRoot() override; // Registers the necessary state needed for embedding in viz. void RegisterVizEmbeddingSupport(); aura::Window* window() { return window_; } bool is_top_level() const { return is_top_level_; } // Sets the bounds from a client. bool SetBoundsInScreenFromClient( const gfx::Rect& bounds, const base::Optional& allocation); // Updates the LocalSurfaceIdAllocation from the client. void UpdateLocalSurfaceIdFromChild( const viz::LocalSurfaceIdAllocation& local_surface_id_allocation); // Called when the LocalSurfaceId of the embedder changes. void OnLocalSurfaceIdChanged(); void AllocateLocalSurfaceIdAndNotifyClient(); // Attaches/unattaches proxy_window->attached_frame_sink_id() to the // HostFrameSinkManager. void AttachChildFrameSinkId(ProxyWindow* proxy_window); void UnattachChildFrameSinkId(ProxyWindow* proxy_window); // Recurses through all descendants with the same WindowTree calling // AttachChildFrameSinkId()/UnattachChildFrameSinkId(). void AttachChildFrameSinkIdRecursive(ProxyWindow* proxy_window); void UnattachChildFrameSinkIdRecursive(ProxyWindow* proxy_window); // Returns true if the WindowService should assign the LocalSurfaceId. A value // of false means the client is expected to providate the LocalSurfaceId. bool ShouldAssignLocalSurfaceId() const { return parent_local_surface_id_allocator_.has_value(); } // See TopLevelProxyWindow::ForceWindowVisible() for details. std::unique_ptr ForceWindowVisible(); // Called when the WindowTreeHost containing this ClientRoot has changed its // display id. void OnWindowTreeHostDisplayIdChanged(); private: friend class ClientRootTestHelper; friend class ScopedForceVisible; void OnForceVisibleDestroyed(); // If necessary, this generates a new LocalSurfaceId. Generally you should // call UpdateLocalSurfaceIdAndClientSurfaceEmbedder(), not this. If you call // this, you need to ensure the ClientSurfaceEmbedder is updated. void GenerateLocalSurfaceIdIfNecessary(); // Updates cached state specific to the current LocalSurfaceId. This is called // any time |parent_local_surface_id_allocator_| has a new id. void UpdateSurfacePropertiesCache(); // Calls GenerateLocalSurfaceIdIfNecessary() and if the current LocalSurfaceId // is valid, updates ClientSurfaceEmbedder. void UpdateLocalSurfaceIdAndClientSurfaceEmbedder(); // Calls HandleBoundsOrScaleFactorChange() it the scale factor has changed. void CheckForScaleFactorChange(); // Called when the bounds or scale factor changes. void HandleBoundsOrScaleFactorChange(); void NotifyClientOfNewBounds(); // If necessary, notifies the client that the visibility changes. If |visible| // has a value, it is used as the visibility, otherwise IsWindowVisible() is // used. void NotifyClientOfVisibilityChange( base::Optional visible = base::nullopt); // Called when the display id changes. void NotifyClientOfDisplayIdChange(); // Callback when the position of |window_|, relative to the root, changes. // This is *only* called for non-top-levels. void OnPositionInRootChanged(); bool IsWindowVisible(); // aura::WindowObserver: void OnWindowPropertyChanged(aura::Window* window, const void* key, intptr_t old) override; void OnWindowBoundsChanged(aura::Window* window, const gfx::Rect& old_bounds, const gfx::Rect& new_bounds, ui::PropertyChangeReason reason) override; void OnWindowAddedToRootWindow(aura::Window* window) override; void OnWindowRemovingFromRootWindow(aura::Window* window, aura::Window* new_root) override; void OnWindowVisibilityChanged(aura::Window* window, bool visible) override; // aura::WindowTreeHostObserver: void OnHostResized(aura::WindowTreeHost* host) override; // display::DisplayObsever: void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; // viz::HostFrameSinkClient: void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override; void OnFrameTokenChanged(uint32_t frame_token) override; WindowTree* window_tree_; aura::Window* window_; const bool is_top_level_; // |last_surface_size_in_pixels_| and |last_device_scale_factor_| are only // used if a LocalSurfaceId is needed for the window. They represent the size // and device scale factor at the time the LocalSurfaceId was generated. gfx::Size last_surface_size_in_pixels_; float last_device_scale_factor_ = 1.0f; std::unique_ptr client_surface_embedder_; // Set to true in OnWindowRemovingFromRootWindow() when |window_| is moving // to a new root window and reset to false in OnWindowAddedToRootWindow(). bool is_moving_across_displays_ = false; // Used for non-top-levels to watch for changes in screen coordinates. std::unique_ptr root_position_monitor_; // Last bounds sent to the client. gfx::Rect last_bounds_; // Last visibility value sent to the client. This is not used for top-levels. bool last_visible_; // Last display id sent to the client. int64_t last_display_id_; // If true, SetBoundsInScreenFromClient() is setting the window bounds. bool setting_bounds_from_client_ = false; // Only used if ShouldAssignLocalSurfaceId() returns true. This is used // instead of the ParentLocalSurfaceIdAllocator maintained by // WindowPortLocal as ClientRoot needs to control when the allocations happen, // and avoid allocations in the case of resizes and clients supplying their // own LocalSurfaceId. base::Optional parent_local_surface_id_allocator_; // If non-null the client is told the window is visible, regardless of // whether the window is actually visible. ScopedForceVisible* force_visible_ = nullptr; DISALLOW_COPY_AND_ASSIGN(ClientRoot); }; } // namespace ws #endif // SERVICES_WS_CLIENT_ROOT_H_