chromium/ash/wm/tablet_mode/tablet_mode_window_state.h

// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_STATE_H_
#define ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_STATE_H_

#include <memory>

#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_types.h"
#include "ash/wm/window_state.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"

namespace gfx {
class Rect;
}  // namespace gfx

namespace ash {
class TabletModeWindowManager;

// The TabletModeWindowState implementation which reduces all possible window
// states to minimized and maximized. If a window cannot be maximized it will be
// set to normal. If a window cannot fill the entire workspace it will be
// centered within the workspace.
class TabletModeWindowState : public WindowState::State {
 public:
  // The |window|'s state object will be modified to use this new window mode
  // state handler. |snap| is for carrying over a snapped state from clamshell
  // mode to tablet mode. If |snap| is false, then the window will be maximized,
  // unless the original state was MAXIMIZED, MINIMIZED, FULLSCREEN, PINNED, or
  // TRUSTED_PINNED. Use |animate_bounds_on_attach| to specify whether to
  // animate the corresponding bounds update. Call LeaveTabletMode() to restore
  // the previous state handler, whereupon ~TabletModeWindowState() will call
  // |creator::WindowStateDestroyed()| to inform that the window mode was
  // reverted to the old window manager.
  TabletModeWindowState(aura::Window* window,
                        base::WeakPtr<TabletModeWindowManager> creator,
                        bool snap,
                        bool animate_bounds_on_attach,
                        bool entering_tablet_mode);

  TabletModeWindowState(const TabletModeWindowState&) = delete;
  TabletModeWindowState& operator=(const TabletModeWindowState&) = delete;

  ~TabletModeWindowState() override;

  // Called when the window position might need to be updated. Note that this
  // method is not supposed to be called for client-controlled windows (e.g.
  // ARC++) as the bounds change with `SetBoundsDirect` is not ack'ed by the
  // client. (b/264962634)
  // TODO(sammiequon): Consolidate with `UpdateBounds`.
  static void UpdateWindowPosition(
      WindowState* window_state,
      WindowState::BoundsChangeAnimationType animation_type);

  // Returns the maximized/full screen and/or centered bounds of a window.
  static gfx::Rect GetBoundsInTabletMode(WindowState* state_object);

  // Leaves the tablet mode by reverting to previous state object.
  void LeaveTabletMode(WindowState* window_state, bool was_in_overview);

  // WindowState::State:
  void OnWMEvent(WindowState* window_state, const WMEvent* event) override;
  chromeos::WindowStateType GetType() const override;
  void AttachState(WindowState* window_state,
                   WindowState::State* previous_state) override;
  void DetachState(WindowState* window_state) override;

  gfx::Rect old_window_bounds_in_screen() const {
    return old_window_bounds_in_screen_;
  }
  WindowState::State* old_state() { return old_state_.get(); }
  void set_ignore_wm_events(bool ignore) { ignore_wm_events_ = ignore; }

 private:
  // Updates the window to `new_state_type` and resulting bounds:
  // Either full screen, maximized centered or minimized. If the state does not
  // change, only the bounds will be changed. If `animate` is set, the bound
  // change get animated.
  void UpdateWindow(WindowState* window_state,
                    chromeos::WindowStateType new_state_type,
                    bool animate);

  // If `target_state` is PRIMARY/SECONDARY_SNAPPED or TRUSTED_PINNED/PINNED,
  // returns `target_state`. Otherwise depending on the capabilities of the
  // window either returns `WindowStateType::kMaximized` or
  // `WindowStateType::kNormal`.
  chromeos::WindowStateType AdjustStateForTabletMode(
      WindowState* window_state,
      chromeos::WindowStateType target_state);

  // Updates the bounds to the maximum possible bounds according to the current
  // window state. If `animate` is set we animate the change.
  void UpdateBounds(WindowState* window_state,
                    chromeos::WindowStateType previous_state,
                    bool animate);

  // Handles Alt+[ if `snap_position` is
  // `SnapPosition::kPrimary`; handles // Alt+] if
  // `snap_position` is `SnapPosition::kSecondary`.
  void CycleTabletSnap(WindowState* window_state, SnapPosition snap_position);

  // Tries to snap the window in tablet split view if possible. Shows a toast if
  // it cannot be snapped.
  void DoTabletSnap(WindowState* window_state,
                    WMEventType snap_event_type,
                    float snap_ratio,
                    WindowSnapActionSource snap_action_source);

  // Called by `WM_EVENT_RESTORE`, or a `WM_EVENT_NORMAL` that is restoring.
  // Restores to the state in `window_states`'s restore history.
  void DoRestore(WindowState* window_state);

  // The original bounds and state object of the window.
  gfx::Rect old_window_bounds_in_screen_;
  std::unique_ptr<WindowState::State> old_state_;

  // The window whose WindowState owns this instance.
  raw_ptr<aura::Window> window_;

  // The creator which needs to be informed when this state goes away. Use a
  // weak ptr since `creator_` can be destroyed before `this`.
  base::WeakPtr<TabletModeWindowManager> const creator_;

  // The state type to be established in AttachState(), unless
  // previous_state->GetType() is MAXIMIZED, MINIMIZED, FULLSCREEN, PINNED, or
  // TRUSTED_PINNED.
  chromeos::WindowStateType state_type_on_attach_;

  // Whether to animate in case of a bounds update when switching to
  // |state_type_on_attach_|.
  bool animate_bounds_on_attach_;

  // The current state type. Due to the nature of this state, this can only be
  // WM_STATE_TYPE{NORMAL, MINIMIZED, MAXIMIZED}.
  chromeos::WindowStateType current_state_type_;

  // If true, the state will not process events.
  bool ignore_wm_events_ = false;
};

}  // namespace ash

#endif  // ASH_WM_TABLET_MODE_TABLET_MODE_WINDOW_STATE_H_