Commit 7cf9c53c authored by Toni Barzic's avatar Toni Barzic Committed by Commit Bot

Reland "Better coordinate swipe to home gesture and drag handle nudge"

This is a reland of 57098dce

Original change was crashing asan tests because drag handle was trying
to remove itself from overview controller observers in it's destructor
during shell shutdown, and it was getting destructed after the overview
controller.
This adds a shell observer, and resets the overview observer sooner,
when the shell destruction begins.

Original change's description:
> Better coordinate swipe to home gesture and drag handle nudge
>
> Manages the drag handle nudge during window drag from shelf to home or
> overview (which may end up in a gesture the nudge is describing).
>
> If the contextual nudge is shown when the window drag starts, the nudge
> will not be hidden until the gesture completes (end it will get hidden
> when the gesture completes, even if the user does not end up going
> home).
>
> If the contextual nudge is scheduled to be shown when the gesture
> starts, the show request will be canceled.
>
> Adds logic that prevents drag handle nudge from showing up, unless it's
> a result of an explicit user action - tapping the drag handle.
>
> BUG=1058617
>
> Change-Id: I96fa2748308143ec42295dbfb472dc564da5bd03
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2107135
> Commit-Queue: Toni Baržić <tbarzic@chromium.org>
> Reviewed-by: Manu Cornet <manucornet@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#751200}

Bug: 1058617
Change-Id: I80222105bda946113248f17a93758cec20387ef3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2108629
Commit-Queue: Toni Baržić <tbarzic@chromium.org>
Reviewed-by: default avatarManu Cornet <manucornet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751468}
parent 09ca64de
......@@ -9,9 +9,9 @@
#include "ash/session/session_controller_impl.h"
#include "ash/shelf/contextual_tooltip.h"
#include "ash/shelf/shelf_observer.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/wm/overview/overview_controller.h"
#include "base/bind.h"
#include "base/debug/stack_trace.h"
#include "base/timer/timer.h"
......@@ -88,6 +88,7 @@ DragHandle::DragHandle(int drag_handle_corner_radius) {
drag_handle_corner_radius, drag_handle_corner_radius});
SetSize(ShelfConfig::Get()->DragHandleSize());
SetEventTargeter(std::make_unique<views::ViewTargeter>(this));
shell_observer_.Add(Shell::Get());
}
DragHandle::~DragHandle() = default;
......@@ -103,11 +104,18 @@ bool DragHandle::DoesIntersectRect(const views::View* target,
}
bool DragHandle::ShowDragHandleNudge() {
// Stop observing overview state if nudge show timer has fired.
if (!show_drag_handle_nudge_timer_.IsRunning())
overview_observer_.RemoveAll();
// Do not show drag handle nudge if it is already shown or drag handle is not
// visible.
if (ShowingNudge() || !GetVisible())
if (ShowingNudge() || window_drag_from_shelf_in_progress_ || !GetVisible())
return false;
showing_nudge_ = true;
StopDragHandleNudgeShowTimer();
PrefService* pref =
Shell::Get()->session_controller()->GetLastActiveUserPrefService();
base::TimeDelta nudge_duration = contextual_tooltip::GetNudgeTimeout(
......@@ -127,8 +135,16 @@ bool DragHandle::ShowDragHandleNudge() {
}
void DragHandle::ScheduleShowDragHandleNudge() {
if (showing_nudge_)
if (showing_nudge_ || show_drag_handle_nudge_timer_.IsRunning() ||
window_drag_from_shelf_in_progress_ ||
Shell::Get()->overview_controller()->InOverviewSession()) {
return;
}
// Observe overview controller to detect overview session start - this should
// cancel the scheduled nudge show.
overview_observer_.Add(Shell::Get()->overview_controller());
show_drag_handle_nudge_timer_.Start(
FROM_HERE, kShowNudgeDelay,
base::BindOnce(base::IgnoreResult(&DragHandle::ShowDragHandleNudge),
......@@ -141,7 +157,8 @@ void DragHandle::SetColorAndOpacity(SkColor color, float opacity) {
}
void DragHandle::HideDragHandleNudge(bool hidden_by_tap) {
show_drag_handle_nudge_timer_.Stop();
StopDragHandleNudgeShowTimer();
if (!ShowingNudge())
return;
hide_drag_handle_nudge_timer_.Stop();
......@@ -149,6 +166,28 @@ void DragHandle::HideDragHandleNudge(bool hidden_by_tap) {
showing_nudge_ = false;
}
void DragHandle::SetWindowDragFromShelfInProgress(bool gesture_in_progress) {
if (window_drag_from_shelf_in_progress_ == gesture_in_progress)
return;
window_drag_from_shelf_in_progress_ = gesture_in_progress;
// If the contextual nudge is not yet shown, make sure that any scheduled
// nudge show request is canceled.
if (!ShowingNudge()) {
StopDragHandleNudgeShowTimer();
return;
}
// If the drag handle nudge is shown when the gesture to home or overview
// starts, keep it around until the gesture completes.
if (window_drag_from_shelf_in_progress_) {
hide_drag_handle_nudge_timer_.Stop();
} else {
HideDragHandleNudge(/*hidden_by_tap=*/false);
}
}
void DragHandle::OnGestureEvent(ui::GestureEvent* event) {
if (!features::AreContextualNudgesEnabled())
return;
......@@ -180,6 +219,17 @@ gfx::Rect DragHandle::GetAnchorBoundsInScreen() const {
return anchor_bounds;
}
void DragHandle::OnOverviewModeStarting() {
StopDragHandleNudgeShowTimer();
}
void DragHandle::OnShellDestroying() {
shell_observer_.RemoveAll();
// Removes the overview controller observer.
StopDragHandleNudgeShowTimer();
hide_drag_handle_nudge_timer_.Stop();
}
void DragHandle::ShowDragHandleTooltip() {
DCHECK(!drag_handle_nudge_);
drag_handle_nudge_ = new ContextualNudge(
......@@ -251,7 +301,7 @@ void DragHandle::HideDragHandleNudgeHelper(bool hidden_by_tap) {
ui::ScopedLayerAnimationSettings opacity_animation_settings(
opacity_animator);
opacity_animation_settings.SetPreemptionStrategy(
ui::LayerAnimator::ENQUEUE_NEW_ANIMATION);
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
opacity_animation_settings.SetTweenType(gfx::Tween::LINEAR);
opacity_animation_settings.SetTransitionDuration(
hidden_by_tap ? kDragHandleHideOnTapAnimationDuration
......@@ -304,4 +354,9 @@ void DragHandle::HandleTapOnNudge() {
HideDragHandleNudge(true /*hidden_by_tap*/);
}
void DragHandle::StopDragHandleNudgeShowTimer() {
show_drag_handle_nudge_timer_.Stop();
overview_observer_.RemoveAll();
}
} // namespace ash
......@@ -8,7 +8,12 @@
#include "ash/ash_export.h"
#include "ash/shelf/contextual_nudge.h"
#include "ash/shelf/shelf_widget.h"
#include "ash/shell.h"
#include "ash/shell_observer.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/overview/overview_observer.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "base/timer/timer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/views/view.h"
......@@ -17,7 +22,9 @@
namespace ash {
class ASH_EXPORT DragHandle : public views::View,
public views::ViewTargeterDelegate {
public views::ViewTargeterDelegate,
public OverviewObserver,
public ShellObserver {
public:
explicit DragHandle(int drag_handle_corner_radius);
DragHandle(const DragHandle&) = delete;
......@@ -45,10 +52,20 @@ class ASH_EXPORT DragHandle : public views::View,
// tapping the nudge.
void HideDragHandleNudge(bool hidden_by_tap);
// Called when the window drag from shelf starts or ends. The drag handle
// contextual nudge will remain visible while the gesture is in progress.
void SetWindowDragFromShelfInProgress(bool gesture_in_progress);
// views::View:
void OnGestureEvent(ui::GestureEvent* event) override;
gfx::Rect GetAnchorBoundsInScreen() const override;
// OverviewObserver:
void OnOverviewModeStarting() override;
// ShellObserver:
void OnShellDestroying() override;
bool ShowingNudge() { return showing_nudge_; }
bool has_show_drag_handle_timer_for_testing() {
......@@ -63,6 +80,10 @@ class ASH_EXPORT DragHandle : public views::View,
return hide_drag_handle_nudge_timer_.IsRunning();
}
void fire_hide_drag_handle_timer_for_testing() {
hide_drag_handle_nudge_timer_.FireNow();
}
ContextualNudge* drag_handle_nudge_for_testing() {
return drag_handle_nudge_;
}
......@@ -90,6 +111,9 @@ class ASH_EXPORT DragHandle : public views::View,
// Handler for tap gesture on the contextual nudge widget. It hides the nudge.
void HandleTapOnNudge();
// Stops the timer to show the drag handle nudge.
void StopDragHandleNudgeShowTimer();
// Timer to hide drag handle nudge if it has a timed life.
base::OneShotTimer hide_drag_handle_nudge_timer_;
......@@ -98,9 +122,22 @@ class ASH_EXPORT DragHandle : public views::View,
bool showing_nudge_ = false;
// Whether window drag from shelf (i.e. gesture from in-app shelf to home or
// overview) is currently in progress. If the contextual nudge is shown when
// the gesture starts, it should remain shown until the gesture ends.
// Set by ShelfLayoutManager using SetWindowDragFromShelfInProgress().
bool window_drag_from_shelf_in_progress_ = false;
// A label used to educate users about swipe gestures on the drag handle.
ContextualNudge* drag_handle_nudge_ = nullptr;
ScopedObserver<OverviewController, OverviewObserver> overview_observer_{this};
ScopedObserver<Shell,
ShellObserver,
&Shell::AddShellObserver,
&Shell::RemoveShellObserver>
shell_observer_{this};
base::WeakPtrFactory<DragHandle> weak_factory_{this};
};
......
This diff is collapsed.
......@@ -2596,6 +2596,8 @@ bool ShelfLayoutManager::MaybeStartDragWindowFromShelf(
return false;
}
shelf_widget_->GetDragHandle()->SetWindowDragFromShelfInProgress(true);
aura::Window* window =
GetWindowForDragToHomeOrOverview(event_in_screen.location());
allow_fling_from_overview_to_home_ = !window;
......@@ -2625,6 +2627,8 @@ base::Optional<ShelfWindowDragResult> ShelfLayoutManager::MaybeEndWindowDrag(
if (!IsWindowDragInProgress())
return base::nullopt;
shelf_widget_->GetDragHandle()->SetWindowDragFromShelfInProgress(false);
DCHECK_EQ(drag_status_, kDragInProgress);
base::Optional<float> velocity_y;
if (event_in_screen.type() == ui::ET_SCROLL_FLING_START) {
......@@ -2646,6 +2650,8 @@ bool ShelfLayoutManager::MaybeEndDragFromOverviewToHome(
return false;
}
shelf_widget_->GetDragHandle()->SetWindowDragFromShelfInProgress(false);
if (event_in_screen.type() != ui::ET_SCROLL_FLING_START)
return false;
......@@ -2678,6 +2684,7 @@ void ShelfLayoutManager::MaybeCancelWindowDrag() {
return;
DCHECK_EQ(drag_status_, kDragInProgress);
shelf_widget_->GetDragHandle()->SetWindowDragFromShelfInProgress(false);
window_drag_controller_->CancelDrag();
}
......
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