Commit 16869bea authored by Sammie Quon's avatar Sammie Quon Committed by Commit Bot

splitview: Animate phantom windows p1.

spec: https://mccanny.users.x20web.corp.google.com/www/splitscreen-motion/index.html

The attached spec wants phantom windows to animate out from the "Drag window here"
indicators. This changes phantom windows from being a separate widget to being part
of the same widget which controls the splitview text. This will allow the animations
in the spec to happen.

The phantom windows are now part of those highlights which are part of the splitview
text. When an item reaches the phantom threshold, the highlight will expand and the
text will disappear. There is some difficult getting the phantom windows to have
rounded corners like they should, but the old ones did not either, so I think it is
ok for now.

The highlights and text layers have their transform and opacity altered rather than
using SetBounds or SetVisible so it will be easier to animate in a follow up cl.

Manually tested using all orientations and multiple divider positions.

Test: ash_unittests SplitViewWindowSelectorTest.*
Bug: 808283
Change-Id: I4b61e5dce394ac05abd4038aee3a07067727f625
Reviewed-on: https://chromium-review.googlesource.com/898247Reviewed-by: default avatarMitsuru Oshima (In Tokyo) <oshima@chromium.org>
Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Commit-Queue: Sammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#537160}
parent 08bc2525
......@@ -16,7 +16,6 @@
#include "ash/wm/splitview/split_view_overview_overlay.h"
#include "ash/wm/window_positioning_utils.h"
#include "ash/wm/wm_event.h"
#include "ash/wm/workspace/phantom_window_controller.h"
#include "ui/aura/window.h"
#include "ui/wm/core/coordinate_conversion.h"
......@@ -54,10 +53,10 @@ void OverviewWindowDragController::InitiateDrag(
? base::nullopt
: base::make_optional(location_in_screen);
window_selector_->SetSplitViewOverviewOverlayIndicatorType(
window_selector_->SetSplitViewOverviewOverlayIndicatorState(
split_view_controller_->CanSnap(item->GetWindow())
? IndicatorType::DRAG_AREA
: IndicatorType::CANNOT_SNAP,
? IndicatorState::kDragArea
: IndicatorState::kCannotSnap,
location_in_screen);
}
......@@ -80,31 +79,16 @@ void OverviewWindowDragController::Drag(const gfx::Point& location_in_screen) {
item_->SetBounds(bounds, OverviewAnimationType::OVERVIEW_ANIMATION_NONE);
previous_event_location_ = location_in_screen;
if (ShouldUpdatePhantomWindowOrSnap(location_in_screen)) {
UpdatePhantomWindowAndWindowGrid(location_in_screen);
// Show the CANNOT_SNAP ui on the split view overview overlay if the window
// cannot be snapped, otherwise show the drag ui only while the phantom
// window is hidden.
IndicatorType indicator_type = IndicatorType::CANNOT_SNAP;
if (split_view_controller_->CanSnap(item_->GetWindow())) {
indicator_type = IsPhantomWindowShowing() ? IndicatorType::NONE
: IndicatorType::DRAG_AREA;
}
window_selector_->SetSplitViewOverviewOverlayIndicatorType(indicator_type,
gfx::Point());
}
UpdateOverlayAndWindowGrid(location_in_screen);
}
void OverviewWindowDragController::CompleteDrag(
const gfx::Point& location_in_screen) {
// Update window grid bounds and |snap_position_| in case the screen
// orientation was changed.
if (ShouldUpdatePhantomWindowOrSnap(location_in_screen))
UpdatePhantomWindowAndWindowGrid(location_in_screen);
phantom_window_controller_.reset();
window_selector_->SetSplitViewOverviewOverlayIndicatorType(
IndicatorType::NONE, gfx::Point());
UpdateOverlayAndWindowGrid(location_in_screen);
window_selector_->SetSplitViewOverviewOverlayIndicatorState(
IndicatorState::kNone, gfx::Point());
if (!did_move_) {
ActivateDraggedWindow();
......@@ -112,9 +96,9 @@ void OverviewWindowDragController::CompleteDrag(
did_move_ = false;
// If the window was dragged around but should not be snapped, move it back
// to overview window grid.
if (!ShouldUpdatePhantomWindowOrSnap(location_in_screen) ||
if (!ShouldUpdateOverlayOrSnap(location_in_screen) ||
snap_position_ == SplitViewController::NONE) {
window_selector_->PositionWindows(true /* animate */);
window_selector_->PositionWindows(/*animate=*/true);
} else {
SnapWindow(snap_position_);
}
......@@ -143,23 +127,24 @@ void OverviewWindowDragController::ActivateDraggedWindow() {
}
void OverviewWindowDragController::ResetGesture() {
phantom_window_controller_.reset();
window_selector_->PositionWindows(true /* animate */);
window_selector_->SetSplitViewOverviewOverlayIndicatorType(
IndicatorType::NONE, gfx::Point());
window_selector_->PositionWindows(/*animate=*/true);
window_selector_->SetSplitViewOverviewOverlayIndicatorState(
IndicatorState::kNone, gfx::Point());
}
void OverviewWindowDragController::ResetWindowSelector() {
window_selector_ = nullptr;
}
void OverviewWindowDragController::UpdatePhantomWindowAndWindowGrid(
void OverviewWindowDragController::UpdateOverlayAndWindowGrid(
const gfx::Point& location_in_screen) {
// Attempt to show phantom window and move window grid only if the window is
// snappable.
if (!ShouldUpdateOverlayOrSnap(location_in_screen))
return;
// Attempt to update the overlay and move the window grid only if the window
// is snappable.
if (!split_view_controller_->CanSnap(item_->GetWindow())) {
snap_position_ = SplitViewController::NONE;
phantom_window_controller_.reset();
return;
}
......@@ -174,7 +159,8 @@ void OverviewWindowDragController::UpdatePhantomWindowAndWindowGrid(
(snap_position_ == SplitViewController::RIGHT &&
snapped_state == SplitViewController::RIGHT_SNAPPED)) {
snap_position_ = SplitViewController::NONE;
phantom_window_controller_.reset();
window_selector_->SetSplitViewOverviewOverlayIndicatorState(
IndicatorState::kNone, gfx::Point());
return;
}
......@@ -187,26 +173,27 @@ void OverviewWindowDragController::UpdatePhantomWindowAndWindowGrid(
GetGridBounds(snap_position_), item_);
}
if (snap_position_ == SplitViewController::NONE ||
snap_position_ != last_snap_position) {
phantom_window_controller_.reset();
if (snap_position_ == SplitViewController::NONE)
return;
// Show the cannot snap ui on the split view overview overlay if the window
// cannot be snapped, otherwise show the drag ui.
if (snap_position_ == SplitViewController::NONE) {
window_selector_->SetSplitViewOverviewOverlayIndicatorState(
split_view_controller_->CanSnap(item_->GetWindow())
? IndicatorState::kDragArea
: IndicatorState::kCannotSnap,
gfx::Point());
return;
}
aura::Window* target_window = item_->GetWindow();
gfx::Rect phantom_bounds_in_screen =
split_view_controller_->GetSnappedWindowBoundsInScreen(target_window,
snap_position_);
if (!phantom_window_controller_) {
phantom_window_controller_ =
std::make_unique<PhantomWindowController>(target_window);
}
phantom_window_controller_->Show(phantom_bounds_in_screen);
// Display the phantom window on the split view overview overlay. The split
// view overview overlay will calculate the phantom window bounds.
window_selector_->SetSplitViewOverviewOverlayIndicatorState(
snap_position_ == SplitViewController::LEFT
? IndicatorState::kPhantomLeft
: IndicatorState::kPhantomRight,
gfx::Point());
}
bool OverviewWindowDragController::ShouldUpdatePhantomWindowOrSnap(
bool OverviewWindowDragController::ShouldUpdateOverlayOrSnap(
const gfx::Point& event_location) {
if (initial_event_location_ == base::nullopt)
return true;
......@@ -215,15 +202,15 @@ bool OverviewWindowDragController::ShouldUpdatePhantomWindowOrSnap(
if (snap_position == SplitViewController::NONE) {
// If the event started in a snap region, but has since moved out set
// |initial_event_location_| to |event_location| which is guarenteed to not
// be in a snap region so that the phantom window or snap mechanism works
// normally for the rest of the drag.
// be in a snap region so that the overlay is shown correctly and the snap
// mechanism works normally for the rest of the drag.
initial_event_location_ = base::nullopt;
return true;
}
// The phantom window can update or the item can snap even if the drag events
// are in the snap region, if the event has traveled past the threshold in the
// direction of the attempted snap region.
// The overlay can update or the item can snap even if the drag events
// are in the snap region, if the event has travelled past the threshold in
// the direction of the attempted snap region.
const gfx::Vector2d distance = event_location - *initial_event_location_;
// Check the x-axis distance for landscape, y-axis distance for portrait.
int distance_scalar =
......
......@@ -15,13 +15,15 @@
namespace ash {
class PhantomWindowController;
class WindowSelector;
class WindowSelectorItem;
// The drag controller for an overview window item in overview mode. It updates
// the position of the corresponding window item using transform while dragging
// and shows/hides the phantom window accordingly.
// the position of the corresponding window item using transform while dragging.
// It also updates the split view overview overlay, which handles showing
// indicators where to drag, and phantom windows showing the bounds of the
// window about to be snapped.
// TODO(sammiequon): Find better names for phantom window and overlay.
class ASH_EXPORT OverviewWindowDragController {
public:
// The minimum offset that will be considered as a drag event.
......@@ -48,18 +50,14 @@ class ASH_EXPORT OverviewWindowDragController {
WindowSelectorItem* item() { return item_; }
bool IsPhantomWindowShowing() const {
return phantom_window_controller_ != nullptr;
}
private:
// Updates visuals for the user while dragging items around.
void UpdatePhantomWindowAndWindowGrid(const gfx::Point& location_in_screen);
void UpdateOverlayAndWindowGrid(const gfx::Point& location_in_screen);
// Dragged items should not attempt to show the phantom window or snap if
// Dragged items should not attempt to update the overlay or snap if
// the drag started in a snap region and has not been dragged pass the
// threshold.
bool ShouldUpdatePhantomWindowOrSnap(const gfx::Point& event_location);
bool ShouldUpdateOverlayOrSnap(const gfx::Point& event_location);
SplitViewController::SnapPosition GetSnapPosition(
const gfx::Point& location_in_screen) const;
......@@ -73,9 +71,6 @@ class ASH_EXPORT OverviewWindowDragController {
SplitViewController* split_view_controller_;
// Shows a highlight of where the dragged window will end up.
std::unique_ptr<PhantomWindowController> phantom_window_controller_;
// The drag target window in the overview mode.
WindowSelectorItem* item_ = nullptr;
......
......@@ -36,4 +36,12 @@ void RoundedRectView::SetBackgroundColor(SkColor background_color) {
SchedulePaint();
}
void RoundedRectView::SetCornerRadius(int radius) {
if (corner_radius_ == radius)
return;
corner_radius_ = radius;
SchedulePaint();
}
} // namespace ash
......@@ -23,6 +23,7 @@ class RoundedRectView : public views::View {
~RoundedRectView() override;
void SetBackgroundColor(SkColor background_color);
void SetCornerRadius(int radius);
// views::View:
void OnPaint(gfx::Canvas* canvas) override;
......
......@@ -489,12 +489,12 @@ void WindowSelector::SetBoundsForWindowGridsInScreenIgnoringWindow(
grid->SetBoundsAndUpdatePositionsIgnoringWindow(bounds, ignored_item);
}
void WindowSelector::SetSplitViewOverviewOverlayIndicatorType(
IndicatorType indicator_type,
void WindowSelector::SetSplitViewOverviewOverlayIndicatorState(
IndicatorState indicator_state,
const gfx::Point& event_location) {
DCHECK(split_view_overview_overlay_);
split_view_overview_overlay_->SetIndicatorType(indicator_type,
event_location);
split_view_overview_overlay_->SetIndicatorState(indicator_state,
event_location);
}
WindowGrid* WindowSelector::GetGridWithRootWindow(aura::Window* root_window) {
......
......@@ -41,7 +41,7 @@ class WindowSelectorDelegate;
class WindowSelectorItem;
class WindowSelectorTest;
enum class IndicatorType;
enum class IndicatorState;
// The WindowSelector shows a grid of all of your windows, allowing to select
// one by clicking or tapping on it.
......@@ -101,8 +101,8 @@ class ASH_EXPORT WindowSelector : public display::DisplayObserver,
// Called to show or hide the split view overview overlay. This will do
// nothing if split view is not enabled. |event_location| is used to reparent
// |split_view_overview_overlays_|'s widget, if necessary.
void SetSplitViewOverviewOverlayIndicatorType(
IndicatorType indicator_type,
void SetSplitViewOverviewOverlayIndicatorState(
IndicatorState indicator_state,
const gfx::Point& event_location);
// Retrieves the window grid whose root window matches |root_window|. Returns
// nullptr if the window grid is not found.
......
This diff is collapsed.
......@@ -11,6 +11,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
namespace views {
class Widget;
......@@ -18,10 +19,28 @@ class Widget;
namespace ash {
enum class IndicatorType { NONE, DRAG_AREA, CANNOT_SNAP };
// Enum which contains the possible states SplitViewOverviewOverlay can be in.
enum class IndicatorState {
kNone,
kDragArea,
kCannotSnap,
kPhantomLeft,
kPhantomRight
};
// Enum which contains the indicators that SplitViewOverviewOverlay can display.
// Converted to a bitmask to make testing easier.
enum class IndicatorType {
kLeftHighlight = 1,
kLeftText = 2,
kRightHighlight = 4,
kRightText = 8
};
// An overlay in overview mode which guides users while they are attempting to
// enter splitview.
// enter splitview. Displays text and highlights when dragging an overview
// window. Displays a highlight of where the window will end up when an overview
// window has entered a snap region.
class ASH_EXPORT SplitViewOverviewOverlay {
public:
SplitViewOverviewOverlay();
......@@ -30,16 +49,18 @@ class ASH_EXPORT SplitViewOverviewOverlay {
// Sets visiblity. The correct indicators will become visible based on the
// split view controllers state. If |event_location| is located on a different
// root window than |widget_|, |widget_| will reparent.
void SetIndicatorType(IndicatorType indicator_type,
const gfx::Point& event_location);
IndicatorType current_indicator_type() const {
return current_indicator_type_;
void SetIndicatorState(IndicatorState indicator_state,
const gfx::Point& event_location);
IndicatorState current_indicator_state() const {
return current_indicator_state_;
}
// Called by owner of this class when display bounds changes are observed, so
// that this class can relayout accordingly.
void OnDisplayBoundsChanged();
bool GetIndicatorTypeVisibilityForTesting(IndicatorType type) const;
private:
FRIEND_TEST_ALL_PREFIXES(SplitViewWindowSelectorTest,
SplitViewOverviewOverlayWidgetReparenting);
......@@ -49,7 +70,7 @@ class ASH_EXPORT SplitViewOverviewOverlay {
// The root content view of |widget_|.
SplitViewOverviewOverlayView* overlay_view_ = nullptr;
IndicatorType current_indicator_type_ = IndicatorType::NONE;
IndicatorState current_indicator_state_ = IndicatorState::kNone;
// The SplitViewOverviewOverlay widget. It covers the entire root window
// and displays regions and text indicating where users should drag windows
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment