Commit c836048c authored by Peter Kasting's avatar Peter Kasting Committed by Commit Bot

Remove set_owned_by_client() from AutoclickScrollPositionHandler.

This relands http://crrev.com/771122 with compile fixes.

It's safe for the Widget to own the underlying View via
SetContentsView().  This was not immediately obvious; much of this CL is
adjacent refactoring and cleanup that simplifies the ownership/lifetime.

Bug: 1044687
Change-Id: I49820e70df1387cfde6998de6ab67e119b5a451a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2213227
Commit-Queue: Peter Kasting <pkasting@chromium.org>
Auto-Submit: Peter Kasting <pkasting@chromium.org>
Reviewed-by: default avatarKatie Dektar <katie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772107}
parent 6de401cb
...@@ -52,8 +52,7 @@ base::TimeDelta CalculateStartGestureDelay(base::TimeDelta total_delay) { ...@@ -52,8 +52,7 @@ base::TimeDelta CalculateStartGestureDelay(base::TimeDelta total_delay) {
} }
views::Widget::InitParams CreateAutoclickOverlayWidgetParams( views::Widget::InitParams CreateAutoclickOverlayWidgetParams(
aura::Window* target) { aura::Window* root_window) {
aura::Window* root_window = target->GetRootWindow();
views::Widget::InitParams params; views::Widget::InitParams params;
params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
params.accept_events = false; params.accept_events = false;
...@@ -128,7 +127,7 @@ void AutoclickController::SetEnabled(bool enabled, ...@@ -128,7 +127,7 @@ void AutoclickController::SetEnabled(bool enabled,
menu_bubble_controller_->ShowBubble(event_type_, menu_position_); menu_bubble_controller_->ShowBubble(event_type_, menu_position_);
if (event_type_ == AutoclickEventType::kScroll) { if (event_type_ == AutoclickEventType::kScroll) {
InitializeScrollLocation(); InitializeScrollLocation();
UpdateScrollPosition(scroll_location_); UpdateScrollPosition();
} }
enabled_ = enabled; enabled_ = enabled;
} else { } else {
...@@ -190,7 +189,7 @@ void AutoclickController::SetAutoclickEventType(AutoclickEventType type) { ...@@ -190,7 +189,7 @@ void AutoclickController::SetAutoclickEventType(AutoclickEventType type) {
if (type == AutoclickEventType::kScroll) { if (type == AutoclickEventType::kScroll) {
InitializeScrollLocation(); InitializeScrollLocation();
UpdateScrollPosition(scroll_location_); UpdateScrollPosition();
} else { } else {
over_scroll_button_ = false; over_scroll_button_ = false;
HideScrollPosition(); HideScrollPosition();
...@@ -290,32 +289,12 @@ void AutoclickController::UpdateAutoclickMenuBoundsIfNeeded() { ...@@ -290,32 +289,12 @@ void AutoclickController::UpdateAutoclickMenuBoundsIfNeeded() {
menu_bubble_controller_->SetPosition(menu_position_); menu_bubble_controller_->SetPosition(menu_position_);
} }
void AutoclickController::CreateAutoclickRingWidget(
const gfx::Point& point_in_screen) {
aura::Window* target = window_util::GetRootWindowAt(point_in_screen);
SetTapDownTarget(target);
ring_widget_ = std::make_unique<views::Widget>();
ring_widget_->Init(CreateAutoclickOverlayWidgetParams(target));
ring_widget_->SetOpacity(1.f);
}
void AutoclickController::CreateAutoclickScrollPositionWidget(
const gfx::Point& point_in_screen) {
aura::Window* target = window_util::GetRootWindowAt(point_in_screen);
SetTapDownTarget(target);
scroll_position_widget_ = std::make_unique<views::Widget>();
scroll_position_widget_->Init(CreateAutoclickOverlayWidgetParams(target));
}
void AutoclickController::UpdateAutoclickWidgetPosition( void AutoclickController::UpdateAutoclickWidgetPosition(
views::Widget* widget, gfx::NativeView native_view,
const gfx::Point& point_in_screen) { aura::Window* root_window) {
aura::Window* target = window_util::GetRootWindowAt(point_in_screen); if (native_view->GetRootWindow() != root_window) {
SetTapDownTarget(target);
aura::Window* root_window = target->GetRootWindow();
if (widget->GetNativeView()->GetRootWindow() != root_window) {
views::Widget::ReparentNativeView( views::Widget::ReparentNativeView(
widget->GetNativeView(), native_view,
Shell::GetContainer(root_window, kShellWindowId_OverlayContainer)); Shell::GetContainer(root_window, kShellWindowId_OverlayContainer));
} }
} }
...@@ -356,7 +335,7 @@ void AutoclickController::DoAutoclickAction() { ...@@ -356,7 +335,7 @@ void AutoclickController::DoAutoclickAction() {
} else { } else {
scroll_location_ = gesture_anchor_location_; scroll_location_ = gesture_anchor_location_;
is_initial_scroll_location_ = false; is_initial_scroll_location_ = false;
UpdateScrollPosition(scroll_location_); UpdateScrollPosition();
Shell::Get() Shell::Get()
->accessibility_controller() ->accessibility_controller()
->RequestAutoclickScrollableBoundsForPoint(scroll_location_); ->RequestAutoclickScrollableBoundsForPoint(scroll_location_);
...@@ -500,11 +479,17 @@ void AutoclickController::InitClickTimers() { ...@@ -500,11 +479,17 @@ void AutoclickController::InitClickTimers() {
base::Unretained(this))); base::Unretained(this)));
} }
void AutoclickController::UpdateRingWidget(const gfx::Point& point_in_screen) { void AutoclickController::UpdateRingWidget() {
if (!ring_widget_) { aura::Window* const target =
CreateAutoclickRingWidget(point_in_screen); window_util::GetRootWindowAt(last_mouse_location_);
SetTapDownTarget(target);
aura::Window* const root_window = target->GetRootWindow();
if (ring_widget_) {
UpdateAutoclickWidgetPosition(ring_widget_->GetNativeView(), root_window);
} else { } else {
UpdateAutoclickWidgetPosition(ring_widget_.get(), point_in_screen); ring_widget_ = std::make_unique<views::Widget>(
CreateAutoclickOverlayWidgetParams(root_window));
ring_widget_->SetOpacity(1.0f);
} }
} }
...@@ -522,29 +507,28 @@ void AutoclickController::InitializeScrollLocation() { ...@@ -522,29 +507,28 @@ void AutoclickController::InitializeScrollLocation() {
->RequestAutoclickScrollableBoundsForPoint(scroll_location_); ->RequestAutoclickScrollableBoundsForPoint(scroll_location_);
} }
void AutoclickController::UpdateScrollPosition( void AutoclickController::UpdateScrollPosition() {
const gfx::Point& point_in_screen) {
if (!enabled_) if (!enabled_)
return; return;
if (!scroll_position_widget_) {
CreateAutoclickScrollPositionWidget(point_in_screen); aura::Window* const target = window_util::GetRootWindowAt(scroll_location_);
SetTapDownTarget(target);
aura::Window* const root_window = target->GetRootWindow();
if (autoclick_scroll_position_handler_) {
UpdateAutoclickWidgetPosition(
autoclick_scroll_position_handler_->GetNativeView(), root_window);
} else {
autoclick_scroll_position_handler_ = autoclick_scroll_position_handler_ =
std::make_unique<AutoclickScrollPositionHandler>( std::make_unique<AutoclickScrollPositionHandler>(
scroll_location_, scroll_position_widget_.get()); std::make_unique<views::Widget>(
} else { CreateAutoclickOverlayWidgetParams(root_window)));
UpdateAutoclickWidgetPosition(scroll_position_widget_.get(),
point_in_screen);
autoclick_scroll_position_handler_->SetCenter(
scroll_location_, scroll_position_widget_.get());
} }
autoclick_scroll_position_handler_->SetScrollPointCenterInScreen(
scroll_location_);
} }
void AutoclickController::HideScrollPosition() { void AutoclickController::HideScrollPosition() {
// Hide the scroll position UI if it exists. autoclick_scroll_position_handler_.reset();
if (autoclick_scroll_position_handler_)
autoclick_scroll_position_handler_.reset();
if (scroll_position_widget_)
scroll_position_widget_.reset();
// TODO(katie): Clear any Autoclick scroll focus rings here. // TODO(katie): Clear any Autoclick scroll focus rings here.
} }
...@@ -611,7 +595,7 @@ void AutoclickController::OnMouseEvent(ui::MouseEvent* event) { ...@@ -611,7 +595,7 @@ void AutoclickController::OnMouseEvent(ui::MouseEvent* event) {
drag_event_rewriter_->IsEnabled()))) { drag_event_rewriter_->IsEnabled()))) {
mouse_event_flags_ = event->flags(); mouse_event_flags_ = event->flags();
// Update the point even if the animation is not currently being shown. // Update the point even if the animation is not currently being shown.
UpdateRingWidget(last_mouse_location_); UpdateRingWidget();
// The distance between the mouse location and the anchor location // The distance between the mouse location and the anchor location
// must exceed a certain threshold to initiate a new autoclick countdown. // must exceed a certain threshold to initiate a new autoclick countdown.
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "ui/aura/window_observer.h" #include "ui/aura/window_observer.h"
#include "ui/events/event_handler.h" #include "ui/events/event_handler.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point.h"
#include "ui/gfx/native_widget_types.h"
namespace base { namespace base {
class RetainingOneShotTimer; class RetainingOneShotTimer;
...@@ -119,19 +120,17 @@ class ASH_EXPORT AutoclickController ...@@ -119,19 +120,17 @@ class ASH_EXPORT AutoclickController
private: private:
void SetTapDownTarget(aura::Window* target); void SetTapDownTarget(aura::Window* target);
void CreateAutoclickRingWidget(const gfx::Point& point_in_screen); void UpdateAutoclickWidgetPosition(gfx::NativeView native_view,
void CreateAutoclickScrollPositionWidget(const gfx::Point& point_in_screen); aura::Window* root_window);
void UpdateAutoclickWidgetPosition(views::Widget* widget,
const gfx::Point& point_in_screen);
void DoAutoclickAction(); void DoAutoclickAction();
void StartAutoclickGesture(); void StartAutoclickGesture();
void CancelAutoclickAction(); void CancelAutoclickAction();
void OnActionCompleted(AutoclickEventType event_type); void OnActionCompleted(AutoclickEventType event_type);
void InitClickTimers(); void InitClickTimers();
void UpdateRingWidget(const gfx::Point& mouse_location); void UpdateRingWidget();
void UpdateRingSize(); void UpdateRingSize();
void InitializeScrollLocation(); void InitializeScrollLocation();
void UpdateScrollPosition(const gfx::Point& point_in_screen); void UpdateScrollPosition();
void HideScrollPosition(); void HideScrollPosition();
void RecordUserAction(AutoclickEventType event_type) const; void RecordUserAction(AutoclickEventType event_type) const;
bool DragInProgress() const; bool DragInProgress() const;
...@@ -200,8 +199,6 @@ class ASH_EXPORT AutoclickController ...@@ -200,8 +199,6 @@ class ASH_EXPORT AutoclickController
// The widget containing the autoclick ring. // The widget containing the autoclick ring.
std::unique_ptr<views::Widget> ring_widget_; std::unique_ptr<views::Widget> ring_widget_;
// The widget containing the autoclick scroll position indiciator.
std::unique_ptr<views::Widget> scroll_position_widget_;
base::TimeDelta delay_; base::TimeDelta delay_;
// The timer that counts down from the beginning of a gesture until a click. // The timer that counts down from the beginning of a gesture until a click.
std::unique_ptr<base::RetainingOneShotTimer> autoclick_timer_; std::unique_ptr<base::RetainingOneShotTimer> autoclick_timer_;
......
...@@ -6,126 +6,86 @@ ...@@ -6,126 +6,86 @@
#include "ash/resources/vector_icons/vector_icons.h" #include "ash/resources/vector_icons/vector_icons.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPath.h" #include "ui/gfx/animation/tween.h"
#include "third_party/skia/include/core/SkRect.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia.h"
#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/transform.h" #include "ui/views/controls/image_view.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h" #include "ui/views/view.h"
#include "ui/views/widget/widget.h"
namespace ash { namespace ash {
namespace {
constexpr int kScrollBackgroundSizeInDips = 32;
constexpr int kScrollIconSizeInDips = 24;
constexpr SkColor kIconBackgroundColor = SkColorSetARGB(255, 128, 134, 139);
constexpr base::TimeDelta kAnimationTime =
base::TimeDelta::FromMilliseconds(500);
constexpr float kFadedOpacity = 0.5;
} // namespace
// View of the AutoclickScrollPositionHandler. Draws the actual contents and
// maintains the views::Widget that the animation is shown in.
class AutoclickScrollPositionView : public views::View { class AutoclickScrollPositionView : public views::View {
public: public:
AutoclickScrollPositionView(const gfx::Point& event_location, AutoclickScrollPositionView();
views::Widget* widget) AutoclickScrollPositionView(const AutoclickScrollPositionView&) = delete;
: views::View(), widget_(widget) { AutoclickScrollPositionView& operator=(const AutoclickScrollPositionView&) =
image_ = gfx::CreateVectorIcon(kAutoclickScrollIcon, kScrollIconSizeInDips, delete;
SK_ColorWHITE);
widget_->SetContentsView(this);
SetSize(
gfx::Size(kScrollBackgroundSizeInDips, kScrollBackgroundSizeInDips));
// Owned by the AutoclickScrollPositionHandler.
set_owned_by_client();
SetLocation(event_location);
}
~AutoclickScrollPositionView() override = default; ~AutoclickScrollPositionView() override = default;
void SetLocation(const gfx::Point& new_event_location) { protected:
gfx::Point point = new_event_location; // views::View:
widget_->SetBounds(gfx::Rect(point.x() - kScrollBackgroundSizeInDips / 2, void OnPaintBackground(gfx::Canvas* canvas) override;
point.y() - kScrollBackgroundSizeInDips / 2, };
kScrollBackgroundSizeInDips,
kScrollBackgroundSizeInDips));
widget_->Show();
widget_->SetOpacity(1.0);
SchedulePaint();
}
void UpdateForAnimationStep(gfx::Animation* animation) {
widget_->SetOpacity(animation->CurrentValueBetween(1.0, kFadedOpacity));
}
private:
void OnPaint(gfx::Canvas* canvas) override {
gfx::Point center(kScrollBackgroundSizeInDips / 2,
kScrollBackgroundSizeInDips / 2);
canvas->Save();
cc::PaintFlags flags;
flags.setAntiAlias(true);
// Draw the grey background.
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(kIconBackgroundColor);
canvas->DrawCircle(center, kScrollBackgroundSizeInDips / 2, flags);
// Draw the icon on top.
canvas->DrawImageInt(image_, center.x() - kScrollIconSizeInDips / 2,
center.y() - kScrollIconSizeInDips / 2);
canvas->Restore(); AutoclickScrollPositionView::AutoclickScrollPositionView() {
} SetLayoutManager(std::make_unique<views::FillLayout>());
AddChildView(std::make_unique<views::ImageView>())
->SetImage(
gfx::CreateVectorIcon(kAutoclickScrollIcon, 24, SK_ColorWHITE));
}
views::Widget* widget_; void AutoclickScrollPositionView::OnPaintBackground(gfx::Canvas* canvas) {
gfx::ImageSkia image_; cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setColor(gfx::kGoogleGrey600);
canvas->DrawCircle(GetLocalBounds().CenterPoint(), width() / 2, flags);
}
DISALLOW_COPY_AND_ASSIGN(AutoclickScrollPositionView); // static
}; constexpr base::TimeDelta AutoclickScrollPositionHandler::kOpaqueTime;
constexpr base::TimeDelta AutoclickScrollPositionHandler::kFadeTime;
AutoclickScrollPositionHandler::AutoclickScrollPositionHandler( AutoclickScrollPositionHandler::AutoclickScrollPositionHandler(
const gfx::Point& center_point_in_screen, std::unique_ptr<views::Widget> widget)
views::Widget* widget) : widget_(std::move(widget)),
: gfx::LinearAnimation(nullptr) { timer_(FROM_HERE,
view_ = std::make_unique<AutoclickScrollPositionView>(center_point_in_screen, kOpaqueTime,
widget); static_cast<gfx::Animation*>(&animation_),
SetDuration(kAnimationTime); &gfx::Animation::Start) {
animation_state_ = AnimationState::kWait; widget_->SetContentsView(std::make_unique<AutoclickScrollPositionView>());
Start();
} }
AutoclickScrollPositionHandler::~AutoclickScrollPositionHandler() { AutoclickScrollPositionHandler::~AutoclickScrollPositionHandler() = default;
view_.reset();
}
void AutoclickScrollPositionHandler::SetCenter( gfx::NativeView AutoclickScrollPositionHandler::GetNativeView() {
const gfx::Point& center_point_in_screen, return widget_->GetNativeView();
views::Widget* widget) {
view_->SetLocation(center_point_in_screen);
animation_state_ = AnimationState::kWait;
Start();
} }
void AutoclickScrollPositionHandler::AnimateToState(double state) { void AutoclickScrollPositionHandler::SetScrollPointCenterInScreen(
if (animation_state_ == AnimationState::kFade) const gfx::Point& scroll_point_center) {
view_->UpdateForAnimationStep(this); constexpr int kBackgroundSizeDips = 32;
gfx::Rect bounds(gfx::Size(kBackgroundSizeDips, kBackgroundSizeDips));
bounds.set_origin(scroll_point_center -
bounds.CenterPoint().OffsetFromOrigin());
widget_->SetBounds(bounds);
widget_->Show();
widget_->SetOpacity(1.0f);
timer_.Reset();
} }
void AutoclickScrollPositionHandler::AnimationStopped() { void AutoclickScrollPositionHandler::AnimationProgressed(
if (animation_state_ == AnimationState::kWait) { const gfx::Animation* animation) {
animation_state_ = AnimationState::kFade; constexpr float kSteadyStateOpacity = 0.5f;
Start(); widget_->SetOpacity(gfx::Tween::FloatValueBetween(
} else if (animation_state_ == AnimationState::kFade) { animation_.GetCurrentValue(), 1.0f, kSteadyStateOpacity));
animation_state_ = AnimationState::kDone;
}
} }
} // namespace ash } // namespace ash
...@@ -7,43 +7,56 @@ ...@@ -7,43 +7,56 @@
#include <memory> #include <memory>
#include "base/macros.h" #include "base/location.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/linear_animation.h" #include "ui/gfx/animation/linear_animation.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/native_widget_types.h"
#include "ui/views/widget/widget.h"
namespace ash { namespace gfx {
class Point;
} // namespace gfx
namespace views {
class Widget;
} // namespace views
class AutoclickScrollPositionView; namespace ash {
// AutoclickScrollPositionHandler displays the position at which the next scroll // AutoclickScrollPositionHandler displays the position at which the next scroll
// event will occur, giving users a sense of which part of the screen will // event will occur, giving users a sense of which part of the screen will
// receive scroll events. It will display at full opacity for a short time, then // receive scroll events. It will display at full opacity for a short time, then
// partially fade out to keep from blocking content. // partially fade out to keep from blocking content.
class AutoclickScrollPositionHandler : public gfx::LinearAnimation { class AutoclickScrollPositionHandler : public gfx::AnimationDelegate {
public: public:
AutoclickScrollPositionHandler(const gfx::Point& center_point_in_screen, explicit AutoclickScrollPositionHandler(
views::Widget* widget); std::unique_ptr<views::Widget> widget);
AutoclickScrollPositionHandler(const AutoclickScrollPositionHandler&) =
delete;
AutoclickScrollPositionHandler& operator=(
const AutoclickScrollPositionHandler&) = delete;
~AutoclickScrollPositionHandler() override; ~AutoclickScrollPositionHandler() override;
void SetCenter(const gfx::Point& center_point_in_screen, gfx::NativeView GetNativeView();
views::Widget* widget);
void SetScrollPointCenterInScreen(const gfx::Point& scroll_point_center);
private: private:
enum AnimationState { static constexpr auto kOpaqueTime = base::TimeDelta::FromMilliseconds(500);
kWait, static constexpr auto kFadeTime = base::TimeDelta::FromMilliseconds(500);
kFade,
kDone, // gfx::AnimationDelegate:
}; void AnimationProgressed(const gfx::Animation* animation) override;
// Overridden from gfx::LinearAnimation. std::unique_ptr<views::Widget> widget_;
void AnimateToState(double state) override;
void AnimationStopped() override;
std::unique_ptr<AutoclickScrollPositionView> view_; // Animation that fades the scroll indicator from full to partial opacity.
AnimationState animation_state_ = kDone; gfx::LinearAnimation animation_{
kFadeTime, gfx::LinearAnimation::kDefaultFrameRate, this};
DISALLOW_COPY_AND_ASSIGN(AutoclickScrollPositionHandler); // Timer that keeps the indicator at full opacity briefly after updating.
base::DelayTimer timer_;
}; };
} // namespace ash } // namespace ash
......
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