chromium/ash/wm/splitview/split_view_drag_indicators.h

// Copyright 2017 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_DRAG_INDICATORS_H_
#define ASH_WM_SPLITVIEW_SPLIT_VIEW_DRAG_INDICATORS_H_

#include <memory>

#include "ash/ash_export.h"
#include "ash/wm/splitview/split_view_controller.h"
#include "ash/wm/splitview/split_view_types.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"

namespace aura {
class Window;
}  // namespace aura

namespace gfx {
class Rect;
}  // namespace gfx

namespace views {
class Widget;
}  // namespace views

namespace ash {

// Enum which contains the indicators that SplitViewDragIndicators can display.
// Converted to a bitmask to make testing easier.
enum class IndicatorType {
  kLeftHighlight = 1,
  kLeftText = 2,
  kRightHighlight = 4,
  kRightText = 8
};

// An overlay in which guides users while they are attempting to enter
// splitview. Displays text and highlights when dragging an overview window.
// Displays a highlight of where the window will end up when a window has
// entered a snap region. Shown when the user is dragging an overview window,
// dragging a floated window, or dragging a window from the shelf.
class ASH_EXPORT SplitViewDragIndicators {
 public:
  // Enum for purposes of providing |SplitViewDragIndicators| with information
  // about window dragging.
  enum class WindowDraggingState {
    // Not dragging, or split view is unsupported (see |ShouldAllowSplitView|).
    kNoDrag,

    // Dragging is in another display. Split view is supported.
    // Note: The distinction between |kNoDrag| and |kOtherDisplay| affects
    // animation when the previous state is |kToSnapLeft| or |kToSnapRight|.
    kOtherDisplay,

    // Started dragging from overview or from the shelf. Split view is
    // supported. Not currently dragging in a snap area, or the dragged window
    // is not eligible to be snapped in split view.
    kFromOverview,

    // Started dragging from the top. Split view is supported. Not currently
    // dragging in a snap area, or the dragged window is not eligible to be
    // snapped in split view.
    kFromTop,

    // Started dragging from the shelf. Split view is supported. Not currently
    // dragging in a snap area, or the dragged window is not eligible to be
    // snapped in split view.
    kFromShelf,

    // Started dragging from the float window state via the caption. Split view
    // is supported. If this is the state, the window will not be snapped when
    // released; it will either not be in the snapping region, or in the
    // snapping region but not snappable.
    kFromFloat,

    // Currently dragging in the |SnapPosition::kPrimary|
    // snap area, and the dragged window is eligible to be snapped in split
    // view.
    kToSnapPrimary,

    // Currently dragging in the |SnapPosition::kSecondary|
    // snap area, and the dragged window is eligible to be snapped in split
    // view.
    kToSnapSecondary
  };

  // |SnapPosition::kPrimary|, if |window_dragging_state|
  // is |kToSnapLeft| |SnapPosition::kSecondary|, if
  // |window_dragging_state| is |kToSnapRight|
  // |SnapPosition::kNone| otherwise
  static SnapPosition GetSnapPosition(
      WindowDraggingState window_dragging_state);

  // |kNoDrag| if |is_dragging| is false or split view is unsupported. If
  // |is_dragging| is true and split view is supported, then:
  // |non_snap_state|, if |snap_position| is
  // |SnapPosition::kNone|
  // |kToSnapLeft|, if |snap_position| is
  // |SnapPosition::kPrimary|
  // |kToSnapRight|, if |snap_position| is
  // |SnapPosition::kSecondary|
  static WindowDraggingState ComputeWindowDraggingState(
      bool is_dragging,
      WindowDraggingState non_snap_state,
      SnapPosition snap_position);

  explicit SplitViewDragIndicators(aura::Window* root_window);

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

  ~SplitViewDragIndicators();

  WindowDraggingState current_window_dragging_state() const {
    return current_window_dragging_state_;
  }

  void SetDraggedWindow(aura::Window* dragged_window);
  void SetWindowDraggingState(WindowDraggingState window_dragging_state);
  void OnDisplayBoundsChanged();
  gfx::Rect GetLeftHighlightViewBounds() const;

  gfx::Rect GetRightHighlightViewBoundsForTesting() const;
  bool GetIndicatorTypeVisibilityForTesting(IndicatorType type) const;

 private:
  FRIEND_TEST_ALL_PREFIXES(SplitViewDragIndicatorsTest,
                           SplitViewDragIndicatorsWidgetReparenting);
  class RotatedImageLabelView;
  class SplitViewDragIndicatorsView;

  // The root content view of |widget_|.
  raw_ptr<SplitViewDragIndicatorsView, DanglingUntriaged> indicators_view_ =
      nullptr;

  WindowDraggingState current_window_dragging_state_ =
      WindowDraggingState::kNoDrag;

  // The SplitViewDragIndicators widget. It covers the entire root window
  // and displays regions and text indicating where users should drag windows
  // enter split view.
  std::unique_ptr<views::Widget> widget_;
};

}  // namespace ash

#endif  // ASH_WM_SPLITVIEW_SPLIT_VIEW_DRAG_INDICATORS_H_