text: // 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_SERVER_WINDOW_H_
  #define COMPONENTS_MUS_WS_SERVER_WINDOW_H_
  
  #include <stdint.h>
  
  #include <vector>
  
  #include "base/logging.h"
  #include "base/macros.h"
  #include "base/observer_list.h"
  #include "components/mus/public/interfaces/compositor_frame.mojom.h"
  #include "components/mus/public/interfaces/window_tree.mojom.h"
  #include "components/mus/ws/ids.h"
  #include "components/mus/ws/server_window_surface.h"
  #include "mojo/public/cpp/bindings/binding.h"
  #include "ui/gfx/geometry/insets.h"
  #include "ui/gfx/geometry/rect.h"
  #include "ui/gfx/geometry/vector2d.h"
  #include "ui/gfx/transform.h"
  #include "ui/platform_window/text_input_state.h"
  
  namespace mus {
  namespace ws {
  
  class ServerWindowDelegate;
  class ServerWindowObserver;
  class ServerWindowSurfaceManager;
  
  // Server side representation of a window. Delegate is informed of interesting
  // events.
  //
  // It is assumed that all functions that mutate the tree have validated the
  // mutation is possible before hand. For example, Reorder() assumes the supplied
  // window is a child and not already in position.
  //
  // ServerWindows do not own their children. If you delete a window that has
  // children the children are implicitly removed. Similarly if a window has a
  // parent and the window is deleted the deleted window is implicitly removed
  // from the parent.
  class ServerWindow {
   public:
    using Properties = std::map<std::string, std::vector<uint8_t>>;
    using Windows = std::vector<ServerWindow*>;
  
    ServerWindow(ServerWindowDelegate* delegate, const WindowId& id);
    ServerWindow(ServerWindowDelegate* delegate,
                 const WindowId& id,
                 const Properties& properties);
    ~ServerWindow();
  
    void AddObserver(ServerWindowObserver* observer);
    void RemoveObserver(ServerWindowObserver* observer);
  
    // Creates a new surface of the specified type, replacing the existing.
    void CreateSurface(mojom::SurfaceType surface_type,
                       mojo::InterfaceRequest<mojom::Surface> request,
                       mojom::SurfaceClientPtr client);
  
    const WindowId& id() const { return id_; }
  
    void Add(ServerWindow* child);
    void Remove(ServerWindow* child);
    void Reorder(ServerWindow* relative, mojom::OrderDirection diretion);
    void StackChildAtBottom(ServerWindow* child);
    void StackChildAtTop(ServerWindow* child);
  
    const gfx::Rect& bounds() const { return bounds_; }
    // Sets the bounds. If the size changes this implicitly resets the client
    // area to fill the whole bounds.
    void SetBounds(const gfx::Rect& bounds);
  
    const std::vector<gfx::Rect>& additional_client_areas() const {
      return additional_client_areas_;
    }
    const gfx::Insets& client_area() const { return client_area_; }
    void SetClientArea(const gfx::Insets& insets,
                       const std::vector<gfx::Rect>& additional_client_areas);
  
    int32_t cursor() const { return cursor_id_; }
  
    const ServerWindow* parent() const { return parent_; }
    ServerWindow* parent() { return parent_; }
  
    const ServerWindow* GetRoot() const;
    ServerWindow* GetRoot() {
      return const_cast<ServerWindow*>(
          const_cast<const ServerWindow*>(this)->GetRoot());
    }
  
    std::vector<const ServerWindow*> GetChildren() const;
    std::vector<ServerWindow*> GetChildren();
    const Windows& children() const { return children_; }
  
    // Returns the ServerWindow object with the provided |id| if it lies in a
    // subtree of |this|.
    ServerWindow* GetChildWindow(const WindowId& id);
  
    // Transient window management.
    void AddTransientWindow(ServerWindow* child);
    void RemoveTransientWindow(ServerWindow* child);
  
    ServerWindow* transient_parent() { return transient_parent_; }
    const ServerWindow* transient_parent() const { return transient_parent_; }
  
    const Windows& transient_children() const { return transient_children_; }
  
    // Returns true if this contains |window| or is |window|.
    bool Contains(const ServerWindow* window) const;
  
    // Returns the visibility requested by this window. IsDrawn() returns whether
    // the window is actually visible on screen.
    bool visible() const { return visible_; }
    void SetVisible(bool value);
  
    float opacity() const { return opacity_; }
    void SetOpacity(float value);
  
    void SetPredefinedCursor(mus::mojom::Cursor cursor_id);
  
    const gfx::Transform& transform() const { return transform_; }
    void SetTransform(const gfx::Transform& transform);
  
    const std::map<std::string, std::vector<uint8_t>>& properties() const {
      return properties_;
    }
    void SetProperty(const std::string& name, const std::vector<uint8_t>* value);
  
    void SetTextInputState(const ui::TextInputState& state);
    const ui::TextInputState& text_input_state() const {
      return text_input_state_;
    }
  
    void set_can_focus(bool can_focus) { can_focus_ = can_focus; }
    bool can_focus() const { return can_focus_; }
  
    // Returns true if this window is attached to a root and all ancestors are
    // visible.
    bool IsDrawn() const;
  
    // Called when its appropriate to destroy surfaces scheduled for destruction.
    void DestroySurfacesScheduledForDestruction();
  
    const gfx::Insets& extended_hit_test_region() const {
      return extended_hit_test_region_;
    }
    void set_extended_hit_test_region(const gfx::Insets& insets) {
      extended_hit_test_region_ = insets;
    }
  
    ServerWindowSurfaceManager* GetOrCreateSurfaceManager();
    ServerWindowSurfaceManager* surface_manager() {
      return surface_manager_.get();
    }
    const ServerWindowSurfaceManager* surface_manager() const {
      return surface_manager_.get();
    }
  
    // Offset of the underlay from the the window bounds (used for shadows).
    const gfx::Vector2d& underlay_offset() const { return underlay_offset_; }
    void SetUnderlayOffset(const gfx::Vector2d& offset);
  
    ServerWindowDelegate* delegate() { return delegate_; }
  
  #if !defined(NDEBUG)
    std::string GetDebugWindowHierarchy() const;
    void BuildDebugInfo(const std::string& depth, std::string* result) const;
  #endif
  
   private:
    // Implementation of removing a window. Doesn't send any notification.
    void RemoveImpl(ServerWindow* window);
  
    // Called when this window's stacking order among its siblings is changed.
    void OnStackingChanged();
  
    static void ReorderImpl(ServerWindow* window,
                            ServerWindow* relative,
                            mojom::OrderDirection diretion);
  
    // Returns a pointer to the stacking target that can be used by
    // RestackTransientDescendants.
    static ServerWindow** GetStackingTarget(ServerWindow* window);
  
    ServerWindowDelegate* delegate_;
    const WindowId id_;
    ServerWindow* parent_;
    Windows children_;
  
    // Transient window management.
    // If non-null we're actively restacking transient as the result of a
    // transient ancestor changing.
    ServerWindow* stacking_target_;
    ServerWindow* transient_parent_;
    Windows transient_children_;
  
    bool visible_;
    gfx::Rect bounds_;
    gfx::Insets client_area_;
    std::vector<gfx::Rect> additional_client_areas_;
    scoped_ptr<ServerWindowSurfaceManager> surface_manager_;
    mojom::Cursor cursor_id_;
    float opacity_;
    bool can_focus_;
    gfx::Transform transform_;
    ui::TextInputState text_input_state_;
  
    Properties properties_;
  
    gfx::Vector2d underlay_offset_;
  
    // The hit test for windows extends outside the bounds of the window by this
    // amount.
    gfx::Insets extended_hit_test_region_;
  
    base::ObserverList<ServerWindowObserver> observers_;
  
    DISALLOW_COPY_AND_ASSIGN(ServerWindow);
  };
  
  }  // namespace ws
  }  // namespace mus
  
  #endif  // COMPONENTS_MUS_WS_SERVER_WINDOW_H_
  