[go: nahoru, domu]

blob: 7655c7eaa2ad8c82722c49422af39bd8da2bbd7c [file] [log] [blame]
// Copyright 2017 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 "ash/wm/splitview/split_view_drag_indicators.h"
#include <utility>
#include "ash/display/screen_orientation_controller.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/public/cpp/window_animation_types.h"
#include "ash/screen_util.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/style/default_color_constants.h"
#include "ash/style/default_colors.h"
#include "ash/wm/splitview/split_view_constants.h"
#include "ash/wm/splitview/split_view_highlight_view.h"
#include "ash/wm/splitview/split_view_utils.h"
#include "ash/wm/window_animations.h"
#include "ash/wm/window_util.h"
#include "base/i18n/rtl.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/display/display_observer.h"
#include "ui/views/background.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/core/coordinate_conversion.h"
#include "ui/wm/core/window_animations.h"
namespace ash {
namespace {
// When a preview is shown, the opposite highlight shall contract to this ratio
// of the screen length.
constexpr float kOtherHighlightScreenPrimaryAxisRatio = 0.03f;
// Creates the widget responsible for displaying the indicators.
std::unique_ptr<views::Widget> CreateWidget(aura::Window* root_window) {
auto widget = std::make_unique<views::Widget>();
views::Widget::InitParams params;
params.type = views::Widget::InitParams::TYPE_POPUP;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
params.accept_events = false;
params.layer_type = ui::LAYER_NOT_DRAWN;
params.parent =
Shell::GetContainer(root_window, kShellWindowId_OverlayContainer);
widget->set_focus_on_creation(false);
widget->Init(std::move(params));
return widget;
}
// Computes the transform which rotates the labels |angle| degrees. The point
// of rotation is the relative center point of |bounds|.
gfx::Transform ComputeRotateAroundCenterTransform(const gfx::Rect& bounds,
double angle) {
gfx::Transform transform;
const gfx::Vector2dF center_point_vector =
bounds.CenterPoint() - bounds.origin();
transform.Translate(center_point_vector);
transform.Rotate(angle);
transform.Translate(-center_point_vector);
return transform;
}
// Returns the work area bounds that has no overlap with shelf.
gfx::Rect GetWorkAreaBoundsNoOverlapWithShelf(aura::Window* root_window) {
aura::Window* window =
root_window->GetChildById(kShellWindowId_OverlayContainer);
gfx::Rect bounds = screen_util::GetDisplayWorkAreaBoundsInParent(window);
::wm::ConvertRectToScreen(root_window, &bounds);
bounds.Subtract(Shelf::ForWindow(root_window)->GetIdealBounds());
return bounds;
}
} // namespace
// static
SplitViewController::SnapPosition SplitViewDragIndicators::GetSnapPosition(
WindowDraggingState window_dragging_state) {
switch (window_dragging_state) {
case WindowDraggingState::kToSnapLeft:
return SplitViewController::LEFT;
case WindowDraggingState::kToSnapRight:
return SplitViewController::RIGHT;
default:
return SplitViewController::NONE;
}
}
// static
SplitViewDragIndicators::WindowDraggingState
SplitViewDragIndicators::ComputeWindowDraggingState(
bool is_dragging,
WindowDraggingState non_snap_state,
SplitViewController::SnapPosition snap_position) {
if (!is_dragging || !ShouldAllowSplitView())
return WindowDraggingState::kNoDrag;
switch (snap_position) {
case SplitViewController::NONE:
return non_snap_state;
case SplitViewController::LEFT:
return WindowDraggingState::kToSnapLeft;
case SplitViewController::RIGHT:
return WindowDraggingState::kToSnapRight;
}
}
// View which contains a label and can be rotated. Used by and rotated by
// SplitViewDragIndicatorsView.
class SplitViewDragIndicators::RotatedImageLabelView : public views::View {
public:
explicit RotatedImageLabelView(bool is_right_or_bottom)
: is_right_or_bottom_(is_right_or_bottom) {
// TODO(sammiequon): Remove this extra intermediate layer.
SetPaintToLayer(ui::LAYER_NOT_DRAWN);
layer()->SetFillsBoundsOpaquely(false);
// Use |label_parent_| to add padding and rounded edges to the text. Create
// this extra view so that we can rotate the label, while having a slide
// animation at times on the whole thing.
label_parent_ = AddChildView(std::make_unique<views::View>());
label_parent_->SetPaintToLayer();
label_parent_->layer()->SetFillsBoundsOpaquely(false);
label_parent_->SetBackground(views::CreateRoundedRectBackground(
DeprecatedGetBaseLayerColor(
AshColorProvider::BaseLayerType::kTransparent80,
kSplitviewLabelBackgroundColor),
kSplitviewLabelRoundRectRadiusDp));
label_parent_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical,
gfx::Insets(kSplitviewLabelVerticalInsetDp,
kSplitviewLabelHorizontalInsetDp)));
label_ = label_parent_->AddChildView(std::make_unique<views::Label>(
std::u16string(), views::style::CONTEXT_LABEL));
label_->SetEnabledColor(DeprecatedGetContentLayerColor(
AshColorProvider::ContentLayerType::kTextColorPrimary,
kSplitviewLabelEnabledColor));
label_->SetBackgroundColor(DeprecatedGetBaseLayerColor(
AshColorProvider::BaseLayerType::kTransparent80,
kSplitviewLabelBackgroundColor));
}
~RotatedImageLabelView() override = default;
void SetLabelText(const std::u16string& text) { label_->SetText(text); }
// Called when the view's bounds are altered. Rotates the view by |angle|
// degrees.
void OnBoundsUpdated(const gfx::Rect& bounds, double angle) {
SetBoundsRect(bounds);
label_parent_->SetBoundsRect(gfx::Rect(bounds.size()));
label_parent_->SetTransform(
ComputeRotateAroundCenterTransform(bounds, angle));
}
// Called to update the opacity of the labels view on |indicator_state|.
void OnWindowDraggingStateChanged(
WindowDraggingState window_dragging_state,
WindowDraggingState previous_window_dragging_state,
bool can_dragged_window_be_snapped) {
// No top label for dragging from the top in portrait orientation.
if (window_dragging_state == WindowDraggingState::kFromTop &&
!IsCurrentScreenOrientationLandscape() && !is_right_or_bottom_) {
return;
}
// If there is no drag currently in this display, any label that is showing
// shall fade out with the corresponding indicator.
if (window_dragging_state == WindowDraggingState::kNoDrag ||
window_dragging_state == WindowDraggingState::kOtherDisplay) {
DoSplitviewOpacityAnimation(
layer(), SPLITVIEW_ANIMATION_TEXT_FADE_OUT_WITH_HIGHLIGHT);
return;
}
// When a snap preview is shown, any label that is showing shall fade out.
if (GetSnapPosition(window_dragging_state) != SplitViewController::NONE) {
DoSplitviewOpacityAnimation(layer(), SPLITVIEW_ANIMATION_TEXT_FADE_OUT);
return;
}
// Set the text according to |can_dragged_window_be_snapped|.
SetLabelText(l10n_util::GetStringUTF16(
can_dragged_window_be_snapped ? IDS_ASH_SPLIT_VIEW_GUIDANCE
: IDS_ASH_SPLIT_VIEW_CANNOT_SNAP));
// When dragging begins in this display or comes in from another display, if
// there is now no snap preview, fade in with an indicator.
if (previous_window_dragging_state == WindowDraggingState::kNoDrag ||
previous_window_dragging_state == WindowDraggingState::kOtherDisplay) {
DoSplitviewOpacityAnimation(
layer(), SPLITVIEW_ANIMATION_TEXT_FADE_IN_WITH_HIGHLIGHT);
return;
}
// If a snap preview was shown, the labels shall now fade in.
if (GetSnapPosition(previous_window_dragging_state) !=
SplitViewController::NONE) {
DoSplitviewOpacityAnimation(layer(), SPLITVIEW_ANIMATION_TEXT_FADE_IN);
return;
}
}
protected:
gfx::Size CalculatePreferredSize() const override {
return label_parent_->GetPreferredSize();
}
private:
// True if the label view is the right/bottom side one, false if it is the
// left/top one.
const bool is_right_or_bottom_;
views::View* label_parent_ = nullptr;
views::Label* label_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(RotatedImageLabelView);
};
// View which contains two highlights on each side indicator where a user should
// drag a selected window in order to initiate splitview. Each highlight has a
// label with instructions to further guide users. The highlights are on the
// left and right of the display in landscape mode, and on the top and bottom of
// the display in landscape mode. The highlights can expand and shrink if a
// window has entered a snap region to display the bounds of the window, if it
// were to get snapped.
class SplitViewDragIndicators::SplitViewDragIndicatorsView
: public views::View,
public aura::WindowObserver {
public:
SplitViewDragIndicatorsView() {
left_highlight_view_ = AddChildView(
std::make_unique<SplitViewHighlightView>(/*is_right_or_bottom=*/false));
right_highlight_view_ = AddChildView(
std::make_unique<SplitViewHighlightView>(/*is_right_or_bottom=*/true));
left_rotated_view_ = AddChildView(
std::make_unique<RotatedImageLabelView>(/*is_right_or_bottom=*/false));
right_rotated_view_ = AddChildView(
std::make_unique<RotatedImageLabelView>(/*is_right_or_bottom=*/true));
// Nothing is shown initially.
left_highlight_view_->layer()->SetOpacity(0.f);
right_highlight_view_->layer()->SetOpacity(0.f);
left_rotated_view_->layer()->SetOpacity(0.f);
right_rotated_view_->layer()->SetOpacity(0.f);
}
~SplitViewDragIndicatorsView() override {
if (dragged_window_)
dragged_window_->RemoveObserver(this);
}
SplitViewHighlightView* left_highlight_view() { return left_highlight_view_; }
// Called by parent widget when the state machine changes. Handles setting the
// opacity and bounds of the highlights and labels.
void OnWindowDraggingStateChanged(WindowDraggingState window_dragging_state) {
DCHECK_NE(window_dragging_state_, window_dragging_state);
previous_window_dragging_state_ = window_dragging_state_;
window_dragging_state_ = window_dragging_state;
SplitViewController* split_view_controller =
SplitViewController::Get(GetWidget()->GetNativeWindow());
const bool previews_only =
window_dragging_state == WindowDraggingState::kFromShelf ||
window_dragging_state == WindowDraggingState::kFromTop ||
split_view_controller->InSplitViewMode();
const bool can_dragged_window_be_snapped =
dragged_window_ &&
split_view_controller->CanSnapWindow(dragged_window_);
if (!previews_only) {
left_rotated_view_->OnWindowDraggingStateChanged(
window_dragging_state, previous_window_dragging_state_,
can_dragged_window_be_snapped);
right_rotated_view_->OnWindowDraggingStateChanged(
window_dragging_state, previous_window_dragging_state_,
can_dragged_window_be_snapped);
}
left_highlight_view_->OnWindowDraggingStateChanged(
window_dragging_state, previous_window_dragging_state_, previews_only,
can_dragged_window_be_snapped);
right_highlight_view_->OnWindowDraggingStateChanged(
window_dragging_state, previous_window_dragging_state_, previews_only,
can_dragged_window_be_snapped);
if (window_dragging_state != WindowDraggingState::kNoDrag ||
GetSnapPosition(previous_window_dragging_state_) !=
SplitViewController::NONE) {
Layout(previous_window_dragging_state_ != WindowDraggingState::kNoDrag);
}
}
views::View* GetViewForIndicatorType(IndicatorType type) {
switch (type) {
case IndicatorType::kLeftHighlight:
return left_highlight_view_;
case IndicatorType::kLeftText:
return left_rotated_view_;
case IndicatorType::kRightHighlight:
return right_highlight_view_;
case IndicatorType::kRightText:
return right_rotated_view_;
}
NOTREACHED();
return nullptr;
}
void SetDraggedWindow(aura::Window* dragged_window) {
if (dragged_window_)
dragged_window_->RemoveObserver(this);
dragged_window_ = dragged_window;
if (dragged_window)
dragged_window->AddObserver(this);
}
// views::View:
void Layout() override { Layout(/*animate=*/false); }
// aura::WindowObserver:
void OnWindowDestroyed(aura::Window* window) override {
DCHECK_EQ(dragged_window_, window);
dragged_window_ = nullptr;
}
private:
// Layout the bounds of the highlight views and helper labels. One should
// animate when changing states, but not when bounds or orientation is
// changed.
void Layout(bool animate) {
// TODO(xdai|afakhry): Attempt to simplify this logic.
const bool horizontal = SplitViewController::IsLayoutHorizontal();
const int display_width = horizontal ? width() : height();
const int display_height = horizontal ? height() : width();
// Calculate the bounds of the two highlight regions.
const int highlight_width =
display_width * kHighlightScreenPrimaryAxisRatio;
const int highlight_height =
display_height - 2 * kHighlightScreenEdgePaddingDp;
gfx::Size highlight_size(highlight_width, highlight_height);
// When one highlight expands to become a preview area, the other highlight
// contracts to this width.
const int other_highlight_width =
display_width * kOtherHighlightScreenPrimaryAxisRatio;
// The origin of the right highlight view in horizontal split view layout,
// or the bottom highlight view in vertical split view layout.
gfx::Point right_bottom_origin(
display_width - highlight_width - kHighlightScreenEdgePaddingDp,
kHighlightScreenEdgePaddingDp);
const gfx::Point highlight_padding_point(kHighlightScreenEdgePaddingDp,
kHighlightScreenEdgePaddingDp);
gfx::Rect left_highlight_bounds(highlight_padding_point, highlight_size);
gfx::Rect right_highlight_bounds(right_bottom_origin, highlight_size);
if (!horizontal) {
left_highlight_bounds.Transpose();
right_highlight_bounds.Transpose();
}
// True when the drag ends in a snap area, meaning that the dragged window
// actually becomes snapped.
const bool drag_ending_in_snap =
window_dragging_state_ == WindowDraggingState::kNoDrag &&
GetSnapPosition(previous_window_dragging_state_) !=
SplitViewController::NONE;
SplitViewController::SnapPosition snap_position =
GetSnapPosition(window_dragging_state_);
if (snap_position == SplitViewController::NONE)
snap_position = GetSnapPosition(previous_window_dragging_state_);
gfx::Rect preview_area_bounds;
base::Optional<SplitviewAnimationType> left_highlight_animation_type;
base::Optional<SplitviewAnimationType> right_highlight_animation_type;
if (GetSnapPosition(window_dragging_state_) != SplitViewController::NONE ||
drag_ending_in_snap) {
// Get the preview area bounds from the split view controller.
preview_area_bounds =
SplitViewController::Get(GetWidget()->GetNativeWindow())
->GetSnappedWindowBoundsInScreen(snap_position, dragged_window_);
aura::Window* root_window =
GetWidget()->GetNativeWindow()->GetRootWindow();
wm::ConvertRectFromScreen(root_window, &preview_area_bounds);
// Preview area should have no overlap with the shelf.
preview_area_bounds.Subtract(
Shelf::ForWindow(root_window)->GetIdealBounds());
gfx::Rect work_area_bounds =
GetWorkAreaBoundsNoOverlapWithShelf(root_window);
wm::ConvertRectFromScreen(root_window, &work_area_bounds);
preview_area_bounds.set_y(preview_area_bounds.y() - work_area_bounds.y());
if (!drag_ending_in_snap) {
preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp,
kHighlightScreenEdgePaddingDp);
}
// Calculate the bounds of the other highlight, which is the one that
// shrinks and fades away, while the other one, the preview area, expands
// and takes up half the screen.
gfx::Rect other_bounds(
display_width - other_highlight_width - kHighlightScreenEdgePaddingDp,
kHighlightScreenEdgePaddingDp, other_highlight_width,
display_height - 2 * kHighlightScreenEdgePaddingDp);
if (!horizontal)
other_bounds.Transpose();
if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) {
left_highlight_bounds = preview_area_bounds;
right_highlight_bounds = other_bounds;
if (animate) {
if (drag_ending_in_snap) {
left_highlight_animation_type =
SPLITVIEW_ANIMATION_PREVIEW_AREA_NIX_INSET;
} else {
left_highlight_animation_type =
SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN;
right_highlight_animation_type =
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT;
}
}
} else {
other_bounds.set_origin(highlight_padding_point);
left_highlight_bounds = other_bounds;
right_highlight_bounds = preview_area_bounds;
if (animate) {
if (drag_ending_in_snap) {
right_highlight_animation_type =
SPLITVIEW_ANIMATION_PREVIEW_AREA_NIX_INSET;
} else {
left_highlight_animation_type =
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT;
right_highlight_animation_type =
SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN;
}
}
}
} else if (GetSnapPosition(previous_window_dragging_state_) !=
SplitViewController::NONE &&
animate) {
if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) {
left_highlight_animation_type =
SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_OUT;
right_highlight_animation_type =
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN;
} else {
left_highlight_animation_type =
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN;
right_highlight_animation_type =
SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_OUT;
}
}
left_highlight_view_->SetBounds(GetMirroredRect(left_highlight_bounds),
left_highlight_animation_type);
right_highlight_view_->SetBounds(GetMirroredRect(right_highlight_bounds),
right_highlight_animation_type);
// Calculate the bounds of the views which contain the guidance text and
// icon. Rotate the two views in horizontal split view layout.
const gfx::Size size(right_rotated_view_->GetPreferredSize().width(),
kSplitviewLabelPreferredHeightDp);
if (!horizontal)
highlight_size.SetSize(highlight_size.height(), highlight_size.width());
gfx::Rect left_rotated_bounds(
highlight_size.width() / 2 - size.width() / 2,
highlight_size.height() / 2 - size.height() / 2, size.width(),
size.height());
gfx::Rect right_rotated_bounds = left_rotated_bounds;
left_rotated_bounds.Offset(highlight_padding_point.x(),
highlight_padding_point.y());
if (!horizontal) {
right_bottom_origin.SetPoint(right_bottom_origin.y(),
right_bottom_origin.x());
}
right_rotated_bounds.Offset(right_bottom_origin.x(),
right_bottom_origin.y());
// In portrait mode, there is no need to rotate the text and warning icon.
// In horizontal split view layout, rotate the left text 90 degrees
// clockwise in rtl and 90 degress anti clockwise in ltr. The right text is
// rotated 90 degrees in the opposite direction of the left text.
double left_rotation_angle = 0.0;
if (horizontal)
left_rotation_angle = 90.0 * (base::i18n::IsRTL() ? 1 : -1);
left_rotated_view_->OnBoundsUpdated(left_rotated_bounds,
/*angle=*/left_rotation_angle);
right_rotated_view_->OnBoundsUpdated(right_rotated_bounds,
/*angle=*/-left_rotation_angle);
if (drag_ending_in_snap) {
// Reset the label transforms, in preparation for the next drag (if any).
left_rotated_view_->layer()->SetTransform(gfx::Transform());
right_rotated_view_->layer()->SetTransform(gfx::Transform());
return;
}
ui::Layer* preview_label_layer;
ui::Layer* other_highlight_label_layer;
if (snap_position == SplitViewController::NONE) {
preview_label_layer = nullptr;
other_highlight_label_layer = nullptr;
} else if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) {
preview_label_layer = left_rotated_view_->layer();
other_highlight_label_layer = right_rotated_view_->layer();
} else {
preview_label_layer = right_rotated_view_->layer();
other_highlight_label_layer = left_rotated_view_->layer();
}
// Slide out the labels when a snap preview appears. This code also adjusts
// the label transforms for things like display rotation while there is a
// snap preview.
if (GetSnapPosition(window_dragging_state_) != SplitViewController::NONE) {
// How far each label shall slide to stay centered in the corresponding
// highlight as it expands/contracts. Include distance traveled with zero
// opacity (whence a label still slides, not only for simplicity in
// calculating the values below, but also to facilitate that the label
// transform and the highlight transform have matching easing).
const float preview_label_distance =
0.5f * (preview_area_bounds.width() - highlight_width);
const float other_highlight_label_distance =
0.5f * (highlight_width - other_highlight_width);
// Positive for right or down; negative for left or up.
float preview_label_delta, other_highlight_label_delta;
if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) {
preview_label_delta = preview_label_distance;
other_highlight_label_delta = other_highlight_label_distance;
} else {
preview_label_delta = -preview_label_distance;
other_highlight_label_delta = -other_highlight_label_distance;
}
// x-axis if |horizontal|; else y-axis.
gfx::Transform preview_label_transform, other_highlight_label_transform;
if (horizontal) {
preview_label_transform.Translate(preview_label_delta, 0.f);
other_highlight_label_transform.Translate(other_highlight_label_delta,
0.f);
} else {
preview_label_transform.Translate(0.f, preview_label_delta);
other_highlight_label_transform.Translate(0.f,
other_highlight_label_delta);
}
if (animate) {
// Animate the labels sliding out.
DoSplitviewTransformAnimation(
preview_label_layer,
SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_OUT,
preview_label_transform, /*animation_observer=*/nullptr);
DoSplitviewTransformAnimation(
other_highlight_label_layer,
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_OUT,
other_highlight_label_transform, /*animation_observer=*/nullptr);
} else {
// Put the labels where they belong.
preview_label_layer->SetTransform(preview_label_transform);
other_highlight_label_layer->SetTransform(
other_highlight_label_transform);
}
return;
}
// Slide in the labels when a snap preview disappears because you drag
// inward. (Having reached this code, we know that the window is not
// becoming snapped, because that case is handled earlier and we bail out.)
if (GetSnapPosition(previous_window_dragging_state_) !=
SplitViewController::NONE) {
if (animate) {
// Animate the labels sliding in.
DoSplitviewTransformAnimation(
preview_label_layer, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_IN,
gfx::Transform(), /*animation_observer=*/nullptr);
DoSplitviewTransformAnimation(
other_highlight_label_layer,
SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN, gfx::Transform(),
/*animation_observer=*/nullptr);
} else {
// Put the labels where they belong.
preview_label_layer->SetTransform(gfx::Transform());
other_highlight_label_layer->SetTransform(gfx::Transform());
}
return;
}
}
SplitViewHighlightView* left_highlight_view_ = nullptr;
SplitViewHighlightView* right_highlight_view_ = nullptr;
RotatedImageLabelView* left_rotated_view_ = nullptr;
RotatedImageLabelView* right_rotated_view_ = nullptr;
WindowDraggingState window_dragging_state_ = WindowDraggingState::kNoDrag;
WindowDraggingState previous_window_dragging_state_ =
WindowDraggingState::kNoDrag;
aura::Window* dragged_window_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(SplitViewDragIndicatorsView);
};
SplitViewDragIndicators::SplitViewDragIndicators(aura::Window* root_window) {
widget_ = CreateWidget(root_window);
widget_->SetBounds(GetWorkAreaBoundsNoOverlapWithShelf(root_window));
indicators_view_ =
widget_->SetContentsView(std::make_unique<SplitViewDragIndicatorsView>());
widget_->Show();
}
SplitViewDragIndicators::~SplitViewDragIndicators() {
// Allow some extra time for animations to finish.
aura::Window* window = widget_->GetNativeWindow();
if (window == nullptr)
return;
wm::SetWindowVisibilityAnimationType(
window, WINDOW_VISIBILITY_ANIMATION_TYPE_STEP_END);
AnimateOnChildWindowVisibilityChanged(window, /*visible=*/false);
}
void SplitViewDragIndicators::SetDraggedWindow(aura::Window* dragged_window) {
DCHECK_EQ(WindowDraggingState::kNoDrag, current_window_dragging_state_);
indicators_view_->SetDraggedWindow(dragged_window);
}
void SplitViewDragIndicators::SetWindowDraggingState(
WindowDraggingState window_dragging_state) {
if (window_dragging_state == current_window_dragging_state_)
return;
current_window_dragging_state_ = window_dragging_state;
indicators_view_->OnWindowDraggingStateChanged(window_dragging_state);
}
void SplitViewDragIndicators::OnDisplayBoundsChanged() {
aura::Window* root_window = widget_->GetNativeView()->GetRootWindow();
widget_->SetBounds(GetWorkAreaBoundsNoOverlapWithShelf(root_window));
}
bool SplitViewDragIndicators::GetIndicatorTypeVisibilityForTesting(
IndicatorType type) const {
return indicators_view_->GetViewForIndicatorType(type)->layer()->opacity() >
0.f;
}
gfx::Rect SplitViewDragIndicators::GetLeftHighlightViewBounds() const {
return indicators_view_->left_highlight_view()->bounds();
}
} // namespace ash