// Copyright 2023 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_SPLITVIEW_SPLIT_VIEW_OVERVIEW_SESSION_H_
#define ASH_WM_SPLITVIEW_SPLIT_VIEW_OVERVIEW_SESSION_H_
#include <optional>
#include "ash/wm/overview/overview_metrics.h"
#include "ash/wm/overview/overview_types.h"
#include "ash/wm/window_state_observer.h"
#include "ash/wm/wm_metrics.h"
#include "base/scoped_observation.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/presentation_time_recorder.h"
namespace ui {
class LocatedEvent;
} // namespace ui
namespace ash {
// Defines two ways to get the split overview session in clamshell mode:
// 1. Snap a window and partial overview will automatically show on the other
// side of the screen. Currently behind the feature flag of `kSnapGroup` arm 1
// or `kFasterSplitScreenSetup`;
// 2. In overview session, manually snap a window.
enum class SplitViewOverviewSetupType {
kSnapThenAutomaticOverview,
kOverviewThenManualSnap,
kMaxValue = kOverviewThenManualSnap,
};
// Enumeration of the exit point of the `SplitViewOverviewSession`.
// Please keep in sync with "SplitViewOverviewSessionExitPoint" in
// tools/metrics/histograms/metadata/ash/enums.xml.
enum class SplitViewOverviewSessionExitPoint {
kCompleteByActivating,
kSkip,
kWindowDestroy,
kShutdown,
kUnspecified,
kTabletConversion,
kMaxValue = kTabletConversion,
};
// Encapsulates the split view state with a single snapped window and
// overview in **clamshell**, also known as intermediate split view or the snap
// group creation session.
//
// While `this` is alive, both split view and overview will be active. `this`
// will automatically be destroyed upon split view or overview ending.
//
// There may be at most one SplitViewOverviewSession per root window. Consumers
// should create and manage this via the
// `RootWindowController::ForWindow(aura::Window*)` function.
//
// Note that clamshell split view does *not* have a divider, and resizing
// overview is done via resizing the window directly.
class ASH_EXPORT SplitViewOverviewSession : public aura::WindowObserver,
public WindowStateObserver {
public:
SplitViewOverviewSession(aura::Window* window,
WindowSnapActionSource snap_action_source);
SplitViewOverviewSession(const SplitViewOverviewSession&) = delete;
SplitViewOverviewSession& operator=(const SplitViewOverviewSession&) = delete;
~SplitViewOverviewSession() override;
aura::Window* window() { return window_; }
SplitViewOverviewSetupType setup_type() const { return setup_type_; }
chromeos::WindowStateType GetWindowStateType() const;
// Initializes the session by starting overview. This must be called after the
// constructor, as consumers may check if `this` exists.
void Init(std::optional<OverviewStartAction> action,
std::optional<OverviewEnterExitType> type);
// Records the `SplitViewOverviewSessionExitPoint` in uma metrics.
void RecordSplitViewOverviewSessionExitPointMetrics(
SplitViewOverviewSessionExitPoint user_action);
// Handles mouse or touch event forwarded from `OverviewSession`.
void HandleClickOrTap(const ui::LocatedEvent& event);
// aura::WindowObserver:
void OnResizeLoopStarted(aura::Window* window) override;
void OnResizeLoopEnded(aura::Window* window) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
void OnWindowDestroying(aura::Window* window) override;
// WindowStateObserver:
void OnPreWindowStateTypeChange(WindowState* window_state,
chromeos::WindowStateType old_type) override;
WindowSnapActionSource snap_action_source_for_testing() const {
return snap_action_source_;
}
private:
// Maybe ends overview or `this` based on the `setup_type_`.
void MaybeEndOverview(SplitViewOverviewSessionExitPoint exit_point,
OverviewEnterExitType exit_type);
// True while we are processing a window resize event.
bool is_resizing_ = false;
// Records the presentation time of resize operation in clamshell split view
// mode.
std::unique_ptr<ui::PresentationTimeRecorder> presentation_time_recorder_;
// The single snapped window in intermediate split view, with overview on
// the opposite side.
const raw_ptr<aura::Window> window_;
SplitViewOverviewSetupType setup_type_ =
SplitViewOverviewSetupType::kSnapThenAutomaticOverview;
// Stores the snap action source info for the snapped `window_`.
const WindowSnapActionSource snap_action_source_;
base::ScopedObservation<aura::Window, aura::WindowObserver>
window_observation_{this};
};
} // namespace ash
#endif // ASH_WM_SPLITVIEW_SPLIT_VIEW_OVERVIEW_SESSION_H_