blob: 6ded27fba10b9eb60ad1ddb86365547ea27dd880 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <string>
#include <vector>
#include "base/logging.h"
#include "base/macros.h"
#include "components/viz/client/client_layer_tree_frame_sink.h"
#include "components/viz/common/surfaces/surface_info.h"
#include "services/ui/public/interfaces/cursor/cursor.mojom.h"
#include "services/ui/public/interfaces/window_tree.mojom.h"
#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/mus/mus_types.h"
#include "ui/aura/mus/window_mus.h"
#include "ui/aura/window_port.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/platform_window/mojo/text_input_state.mojom.h"
namespace gfx {
class Insets;
namespace viz {
class ClientLayerTreeFrameSink;
namespace aura {
class ClientSurfaceEmbedder;
class PropertyConverter;
class Window;
class WindowPortMusTestApi;
class WindowTreeClient;
class WindowTreeClientPrivate;
class WindowTreeHostMus;
// WindowPortMus is a WindowPort that forwards calls to WindowTreeClient
// so that changes are propagated to the server. All changes from
// WindowTreeClient to the underlying Window route through this class (by
// way of WindowMus) and are done in such a way that they don't result in
// calling back to WindowTreeClient.
class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
// See WindowMus's constructor for details on |window_mus_type|.
WindowPortMus(WindowTreeClient* client, WindowMusType window_mus_type);
~WindowPortMus() override;
static WindowPortMus* Get(Window* window);
Window* window() { return window_; }
const Window* window() const { return window_; }
ClientSurfaceEmbedder* client_surface_embedder() const {
return client_surface_embedder_.get();
const viz::SurfaceId& PrimarySurfaceIdForTesting() const {
return primary_surface_id_;
void SetTextInputState(ui::mojom::TextInputStatePtr state);
void SetImeVisibility(bool visible, ui::mojom::TextInputStatePtr state);
const ui::CursorData& cursor() const { return cursor_; }
void SetCursor(const ui::CursorData& cursor);
// Sets the EventTargetingPolicy, default is TARGET_AND_DESCENDANTS.
void SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy policy);
// Sets whether this window can accept drops, defaults to false.
void SetCanAcceptDrops(bool can_accept_drops);
// See description in mojom for details on this. Has no effect if not running
// in the window manager.
void SetExtendedHitRegionForChildren(const gfx::Insets& mouse_insets,
const gfx::Insets& touch_insets);
// Embeds a new client in this Window. See WindowTreeClient::Embed() for
// details on arguments.
void Embed(ui::mojom::WindowTreeClientPtr client,
uint32_t flags,
const ui::mojom::WindowTree::EmbedCallback& callback);
std::unique_ptr<viz::ClientLayerTreeFrameSink> RequestLayerTreeFrameSink(
scoped_refptr<viz::ContextProvider> context_provider,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
// WindowPort:
// Returns either the FrameSinkId set by window server or its server_id with
// the client id part 0.
viz::FrameSinkId GetFrameSinkId() const override;
friend class WindowPortMusTestApi;
friend class WindowTreeClient;
friend class WindowTreeClientPrivate;
friend class WindowTreeHostMus;
friend class HitTestDataProviderAuraTest;
using ServerChangeIdType = uint8_t;
// Changes to the underlying Window originating from the server must be done
// in such a way that the same change is not applied back to the server. To
// accomplish this every changes from the server is associated with at least
// one ServerChange. If the underlying Window ends up calling back to this
// class and the change is expected then the change is ignored and not sent to
// the server. For example, here's the flow when the server changes the
// bounds:
// . WindowTreeClient calls SetBoundsFromServer().
// . A ServerChange is added of type BOUNDS and the matching bounds.
// . Window::SetBounds() is called.
// . Window::SetBounds() calls WindowPortMus::OnDidChangeBounds().
// . A ServerChange of type BOUNDS is found, and the request is ignored.
// Additionally the ServerChange is removed at this point so that if another
// bounds change is made it will be propagated. This is important as changes
// to underyling window may generate more changes.
// The typical pattern in implementing a call from the server looks like:
// // Create and configure the data as appropriate to the change:
// ServerChangeData data;
// = window->bar();
// ScopedServerChange change(this, ServerChangeType::FOO, data);
// window_->SetFoo(...);
// And the call from the Window (by way of WindowPort interface) looks like:
// ServerChangeData change_data;
// = ...;
// if (!RemoveChangeByTypeAndData(ServerChangeType::FOO, change_data))
// window_tree_client_->OnFooChanged(this, ...);
enum ServerChangeType {
// Contains data needed to identify a change from the server.
struct ServerChangeData {
Id child_id;
// Applies to BOUNDS. This should be in dip.
gfx::Rect bounds_in_dip;
// Applies to VISIBLE.
bool visible;
// Applies to PROPERTY.
std::string property_name;
// Applies to TRANSFORM.
gfx::Transform transform;
// Used to identify a change the server.
struct ServerChange {
ServerChangeType type;
// A unique id assigned to the change and used later on to identify it for
// removal.
ServerChangeIdType server_change_id;
ServerChangeData data;
using ServerChanges = std::vector<ServerChange>;
// Convenience for adding/removing a ScopedChange.
class ScopedServerChange {
ScopedServerChange(WindowPortMus* window_impl,
const ServerChangeType type,
const ServerChangeData& data)
: window_impl_(window_impl),
server_change_id_(window_impl->ScheduleChange(type, data)) {}
~ScopedServerChange() { window_impl_->RemoveChangeById(server_change_id_); }
WindowPortMus* window_impl_;
const ServerChangeIdType server_change_id_;
struct WindowMusChangeDataImpl : public WindowMusChangeData {
~WindowMusChangeDataImpl() override;
std::unique_ptr<ScopedServerChange> change;
// Creates and adds a ServerChange to |server_changes_|. Returns the id
// assigned to the ServerChange.
ServerChangeIdType ScheduleChange(const ServerChangeType type,
const ServerChangeData& data);
// Removes a ServerChange by id.
void RemoveChangeById(ServerChangeIdType change_id);
// If there is a schedule change matching |type| and |data| it is removed and
// true is returned. If no matching change is scheduled returns false.
bool RemoveChangeByTypeAndData(const ServerChangeType type,
const ServerChangeData& data);
ServerChanges::iterator FindChangeByTypeAndData(const ServerChangeType type,
const ServerChangeData& data);
PropertyConverter* GetPropertyConverter();
// WindowMus:
Window* GetWindow() override;
void AddChildFromServer(WindowMus* window) override;
void RemoveChildFromServer(WindowMus* child) override;
void ReorderFromServer(WindowMus* child,
WindowMus* relative,
ui::mojom::OrderDirection) override;
void SetBoundsFromServer(
const gfx::Rect& bounds,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) override;
void SetTransformFromServer(const gfx::Transform& transform) override;
void SetVisibleFromServer(bool visible) override;
void SetOpacityFromServer(float opacity) override;
void SetCursorFromServer(const ui::CursorData& cursor) override;
void SetPropertyFromServer(
const std::string& property_name,
const std::vector<uint8_t>* property_data) override;
void SetFrameSinkIdFromServer(const viz::FrameSinkId& frame_sink_id) override;
const viz::LocalSurfaceId& GetOrAllocateLocalSurfaceId(
const gfx::Size& surface_size_in_pixels) override;
void SetFallbackSurfaceInfo(const viz::SurfaceInfo& surface_info) override;
void DestroyFromServer() override;
void AddTransientChildFromServer(WindowMus* child) override;
void RemoveTransientChildFromServer(WindowMus* child) override;
ChangeSource OnTransientChildAdded(WindowMus* child) override;
ChangeSource OnTransientChildRemoved(WindowMus* child) override;
std::unique_ptr<WindowMusChangeData> PrepareForServerBoundsChange(
const gfx::Rect& bounds) override;
std::unique_ptr<WindowMusChangeData> PrepareForServerVisibilityChange(
bool value) override;
void PrepareForDestroy() override;
void NotifyEmbeddedAppDisconnected() override;
bool HasLocalLayerTreeFrameSink() override;
float GetDeviceScaleFactor() override;
// WindowPort:
void OnPreInit(Window* window) override;
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override;
void OnWillAddChild(Window* child) override;
void OnWillRemoveChild(Window* child) override;
void OnWillMoveChild(size_t current_index, size_t dest_index) override;
void OnVisibilityChanged(bool visible) override;
void OnDidChangeBounds(const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds) override;
void OnDidChangeTransform(const gfx::Transform& old_transform,
const gfx::Transform& new_transform) override;
std::unique_ptr<ui::PropertyData> OnWillChangeProperty(
const void* key) override;
void OnPropertyChanged(const void* key,
int64_t old_value,
std::unique_ptr<ui::PropertyData> data) override;
std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override;
viz::SurfaceId GetSurfaceId() const override;
void AllocateLocalSurfaceId() override;
const viz::LocalSurfaceId& GetLocalSurfaceId() override;
void OnWindowAddedToRootWindow() override;
void OnWillRemoveWindowFromRootWindow() override;
void OnEventTargetingPolicyChanged() override;
bool ShouldRestackTransientChildren() override;
void UpdatePrimarySurfaceId();
void UpdateClientSurfaceEmbedder();
WindowTreeClient* window_tree_client_;
Window* window_ = nullptr;
// Used when this window is embedding a client.
std::unique_ptr<ClientSurfaceEmbedder> client_surface_embedder_;
ServerChangeIdType next_server_change_id_ = 0;
ServerChanges server_changes_;
viz::SurfaceId primary_surface_id_;
viz::SurfaceInfo fallback_surface_info_;
viz::LocalSurfaceId local_surface_id_;
viz::LocalSurfaceIdAllocator local_surface_id_allocator_;
gfx::Size last_surface_size_in_pixels_;
ui::CursorData cursor_;
// See description in single place that changes the value for details.
bool should_restack_transient_children_ = true;
// When a frame sink is created
// for a local aura::Window, we need keep a weak ptr of it, so we can update
// the local surface id when necessary.
base::WeakPtr<viz::ClientLayerTreeFrameSink> local_layer_tree_frame_sink_;
} // namespace aura