Chromium Code Reviews| Index: ash/autoclick/autoclick_controller.cc |
| diff --git a/ash/autoclick/autoclick_controller.cc b/ash/autoclick/autoclick_controller.cc |
| index b0f715d6805d4348437f396974b93b69c956a892..8d8d01021305bfca609b6e1c28dee0f4afaf737a 100644 |
| --- a/ash/autoclick/autoclick_controller.cc |
| +++ b/ash/autoclick/autoclick_controller.cc |
| @@ -5,37 +5,22 @@ |
| #include "ash/autoclick/autoclick_controller.h" |
| #include "ash/aura/wm_window_aura.h" |
| +#include "ash/autoclick/common/autoclick_controller_common.h" |
| +#include "ash/common/shell_window_ids.h" |
| #include "ash/common/wm/root_window_finder.h" |
| #include "ash/shell.h" |
| #include "base/timer/timer.h" |
| -#include "ui/aura/env.h" |
| +#include "ui/aura/window_observer.h" |
| #include "ui/aura/window_tree_host.h" |
| #include "ui/events/event.h" |
| -#include "ui/events/event_constants.h" |
| #include "ui/events/event_handler.h" |
| #include "ui/events/event_processor.h" |
| #include "ui/events/event_utils.h" |
| -#include "ui/gfx/geometry/point.h" |
| -#include "ui/gfx/geometry/vector2d.h" |
| +#include "ui/views/widget/widget.h" |
| #include "ui/wm/core/coordinate_conversion.h" |
| namespace ash { |
| -namespace { |
| - |
| -// The threshold of mouse movement measured in DIP that will |
| -// initiate a new autoclick. |
| -const int kMovementThreshold = 20; |
| - |
| -bool IsModifierKey(ui::KeyboardCode key_code) { |
| - return key_code == ui::VKEY_SHIFT || key_code == ui::VKEY_LSHIFT || |
| - key_code == ui::VKEY_CONTROL || key_code == ui::VKEY_LCONTROL || |
| - key_code == ui::VKEY_RCONTROL || key_code == ui::VKEY_MENU || |
| - key_code == ui::VKEY_LMENU || key_code == ui::VKEY_RMENU; |
| -} |
| - |
| -} // namespace |
| - |
| // static. |
| base::TimeDelta AutoclickController::GetDefaultAutoclickDelay() { |
| return base::TimeDelta::FromMilliseconds(int64_t{kDefaultAutoclickDelayMs}); |
| @@ -44,18 +29,18 @@ base::TimeDelta AutoclickController::GetDefaultAutoclickDelay() { |
| const int AutoclickController::kDefaultAutoclickDelayMs = 1000; |
| class AutoclickControllerImpl : public AutoclickController, |
| - public ui::EventHandler { |
| + public ui::EventHandler, |
| + public AutoclickControllerCommon::Delegate, |
| + public aura::WindowObserver { |
| public: |
| AutoclickControllerImpl(); |
| ~AutoclickControllerImpl() override; |
| private: |
| // AutoclickController overrides: |
| - void SetDelegate(std::unique_ptr<Delegate> delegate) override; |
| void SetEnabled(bool enabled) override; |
| bool IsEnabled() const override; |
| void SetAutoclickDelay(base::TimeDelta delay) override; |
| - base::TimeDelta GetAutoclickDelay() const override; |
| // ui::EventHandler overrides: |
| void OnMouseEvent(ui::MouseEvent* event) override; |
| @@ -64,40 +49,37 @@ class AutoclickControllerImpl : public AutoclickController, |
| void OnGestureEvent(ui::GestureEvent* event) override; |
| void OnScrollEvent(ui::ScrollEvent* event) override; |
| - void StartRingDisplay(); |
| - void StopRingDisplay(); |
| - void ChangeRingDisplayCenter(); |
| + // AutoclickControllerCommon::Delegate overrides: |
| + std::unique_ptr<views::Widget> CreateAutoclickRingWidget( |
| + const gfx::Point& event_location) override; |
| + void UpdateAutoclickRingWidget(views::Widget* widget, |
| + const gfx::Point& event_location) override; |
| + void DoAutoclick(const gfx::Point& event_location, |
| + const int mouse_event_flags) override; |
| + void OnAutoclickCanceled() override; |
| - void InitClickTimer(); |
| + // aura::WindowObserver overrides: |
| + void OnWindowDestroying(aura::Window* window) override; |
| - void DoAutoclick(); |
| + void SetTapDownTarget(aura::Window* target); |
|
sadrul
2016/08/15 17:23:04
Non-override before overrides.
riajiang
2016/08/16 00:44:24
Done.
|
| bool enabled_; |
| - base::TimeDelta delay_; |
| - int mouse_event_flags_; |
| - std::unique_ptr<base::Timer> autoclick_timer_; |
| - std::unique_ptr<Delegate> delegate_; |
| - // The position in screen coordinates used to determine |
| - // the distance the mouse has moved. |
| - gfx::Point anchor_location_; |
| - gfx::Point current_mouse_location_; |
| + // The target window is observed by AutoclickControllerImpl for the duration |
| + // of a autoclick gesture. |
| + aura::Window* tap_down_target_; |
| + std::unique_ptr<AutoclickControllerCommon> autoclick_controller_common_; |
| DISALLOW_COPY_AND_ASSIGN(AutoclickControllerImpl); |
| }; |
| AutoclickControllerImpl::AutoclickControllerImpl() |
| : enabled_(false), |
| - delay_(GetDefaultAutoclickDelay()), |
| - mouse_event_flags_(ui::EF_NONE), |
| - delegate_(nullptr), |
| - anchor_location_(-kMovementThreshold, -kMovementThreshold) { |
| - InitClickTimer(); |
| -} |
| + tap_down_target_(nullptr), |
| + autoclick_controller_common_( |
| + new AutoclickControllerCommon(GetDefaultAutoclickDelay(), this)) {} |
| -AutoclickControllerImpl::~AutoclickControllerImpl() {} |
| - |
| -void AutoclickControllerImpl::SetDelegate(std::unique_ptr<Delegate> delegate) { |
| - delegate_ = std::move(delegate); |
| +AutoclickControllerImpl::~AutoclickControllerImpl() { |
| + SetTapDownTarget(nullptr); |
| } |
| void AutoclickControllerImpl::SetEnabled(bool enabled) { |
| @@ -107,7 +89,7 @@ void AutoclickControllerImpl::SetEnabled(bool enabled) { |
| if (enabled_) { |
| Shell::GetInstance()->AddPreTargetHandler(this); |
| - autoclick_timer_->Stop(); |
| + autoclick_controller_common_->CancelAutoclick(); |
| } else { |
| Shell::GetInstance()->RemovePreTargetHandler(this); |
| } |
| @@ -118,118 +100,83 @@ bool AutoclickControllerImpl::IsEnabled() const { |
| } |
| void AutoclickControllerImpl::SetAutoclickDelay(base::TimeDelta delay) { |
| - delay_ = delay; |
| - InitClickTimer(); |
| -} |
| - |
| -base::TimeDelta AutoclickControllerImpl::GetAutoclickDelay() const { |
| - return delay_; |
| -} |
| - |
| -void AutoclickControllerImpl::StartRingDisplay() { |
| - if (delegate_) |
| - delegate_->StartGesture(delay_, anchor_location_); |
| -} |
| - |
| -void AutoclickControllerImpl::StopRingDisplay() { |
| - if (delegate_) |
| - delegate_->StopGesture(); |
| -} |
| - |
| -void AutoclickControllerImpl::ChangeRingDisplayCenter() { |
| - if (delegate_) |
| - delegate_->SetGestureCenter(current_mouse_location_); |
| -} |
| - |
| -void AutoclickControllerImpl::InitClickTimer() { |
| - autoclick_timer_.reset(new base::Timer( |
| - FROM_HERE, delay_, |
| - base::Bind(&AutoclickControllerImpl::DoAutoclick, base::Unretained(this)), |
| - false)); |
| + autoclick_controller_common_->SetAutoclickDelay(delay); |
| } |
| void AutoclickControllerImpl::OnMouseEvent(ui::MouseEvent* event) { |
| - if (event->type() == ui::ET_MOUSE_MOVED && |
| - !(event->flags() & ui::EF_IS_SYNTHESIZED)) { |
| - mouse_event_flags_ = event->flags(); |
| - |
| - gfx::Point mouse_location = event->location(); |
| - ::wm::ConvertPointToScreen(static_cast<aura::Window*>(event->target()), |
| - &mouse_location); |
| - |
| - // The distance between the mouse location and the anchor location |
| - // must exceed a certain threshold to initiate a new autoclick countdown. |
| - // This ensures that mouse jitter caused by poor motor control does not |
| - // 1. initiate an unwanted autoclick from rest |
| - // 2. prevent the autoclick from ever occuring when the mouse |
| - // arrives at the target. |
| - gfx::Vector2d delta = mouse_location - anchor_location_; |
| - if (delta.LengthSquared() >= kMovementThreshold * kMovementThreshold) { |
| - anchor_location_ = mouse_location; |
| - autoclick_timer_->Reset(); |
| - StartRingDisplay(); |
| - } else if (autoclick_timer_->IsRunning()) { |
| - current_mouse_location_ = mouse_location; |
| - ChangeRingDisplayCenter(); |
| - } |
| - } else if (event->type() == ui::ET_MOUSE_PRESSED) { |
| - autoclick_timer_->Stop(); |
| - StopRingDisplay(); |
| - } else if (event->type() == ui::ET_MOUSEWHEEL && |
| - autoclick_timer_->IsRunning()) { |
| - autoclick_timer_->Reset(); |
| - StartRingDisplay(); |
| - } |
| + autoclick_controller_common_->HandleMouseEvent(*event); |
| } |
| void AutoclickControllerImpl::OnKeyEvent(ui::KeyEvent* event) { |
| - int modifier_mask = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN | |
| - ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN | |
| - ui::EF_IS_EXTENDED_KEY; |
| - int new_modifiers = event->flags() & modifier_mask; |
| - mouse_event_flags_ = (mouse_event_flags_ & ~modifier_mask) | new_modifiers; |
| - |
| - if (!IsModifierKey(event->key_code())) { |
| - autoclick_timer_->Stop(); |
| - StopRingDisplay(); |
| - } |
| + autoclick_controller_common_->HandleKeyEvent(*event); |
| } |
| void AutoclickControllerImpl::OnTouchEvent(ui::TouchEvent* event) { |
| - autoclick_timer_->Stop(); |
| - StopRingDisplay(); |
| + autoclick_controller_common_->HandleTouchEvent(*event); |
| } |
| void AutoclickControllerImpl::OnGestureEvent(ui::GestureEvent* event) { |
| - autoclick_timer_->Stop(); |
| - StopRingDisplay(); |
| + autoclick_controller_common_->HandleGestureEvent(*event); |
| } |
| void AutoclickControllerImpl::OnScrollEvent(ui::ScrollEvent* event) { |
| - autoclick_timer_->Stop(); |
| - StopRingDisplay(); |
| + autoclick_controller_common_->HandleScrollEvent(*event); |
| +} |
| + |
| +std::unique_ptr<views::Widget> |
| +AutoclickControllerImpl::CreateAutoclickRingWidget( |
| + const gfx::Point& event_location) { |
| + aura::Window* target = |
| + WmWindowAura::GetAuraWindow(ash::wm::GetRootWindowAt(event_location)); |
| + SetTapDownTarget(target); |
| + aura::Window* root_window = target->GetRootWindow(); |
| + std::unique_ptr<views::Widget> widget(new views::Widget); |
| + views::Widget::InitParams params; |
| + params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; |
| + params.accept_events = false; |
| + params.activatable = views::Widget::InitParams::ACTIVATABLE_NO; |
| + params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| + params.context = root_window; |
| + params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; |
| + params.parent = |
| + Shell::GetContainer(root_window, kShellWindowId_OverlayContainer); |
| + widget->Init(params); |
| + widget->SetOpacity(1.f); |
| + return widget; |
| +} |
| + |
| +void AutoclickControllerImpl::UpdateAutoclickRingWidget( |
| + views::Widget* widget, |
| + const gfx::Point& event_location) { |
| + aura::Window* target = |
| + WmWindowAura::GetAuraWindow(ash::wm::GetRootWindowAt(event_location)); |
| + SetTapDownTarget(target); |
| + aura::Window* root_window = target->GetRootWindow(); |
| + if (widget->GetNativeView()->GetRootWindow() != root_window) { |
| + views::Widget::ReparentNativeView( |
| + widget->GetNativeView(), |
| + Shell::GetContainer(root_window, kShellWindowId_OverlayContainer)); |
| + } |
| } |
| -void AutoclickControllerImpl::DoAutoclick() { |
| - gfx::Point screen_location = aura::Env::GetInstance()->last_mouse_location(); |
| +void AutoclickControllerImpl::DoAutoclick(const gfx::Point& event_location, |
| + const int mouse_event_flags) { |
| aura::Window* root_window = |
| - WmWindowAura::GetAuraWindow(wm::GetRootWindowAt(screen_location)); |
| + WmWindowAura::GetAuraWindow(wm::GetRootWindowAt(event_location)); |
| DCHECK(root_window) << "Root window not found while attempting autoclick."; |
| - gfx::Point click_location(screen_location); |
| - anchor_location_ = click_location; |
| - |
| + gfx::Point click_location(event_location); |
| ::wm::ConvertPointFromScreen(root_window, &click_location); |
| aura::WindowTreeHost* host = root_window->GetHost(); |
| host->ConvertPointToHost(&click_location); |
| ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, click_location, |
| click_location, ui::EventTimeForNow(), |
| - mouse_event_flags_ | ui::EF_LEFT_MOUSE_BUTTON, |
| + mouse_event_flags | ui::EF_LEFT_MOUSE_BUTTON, |
| ui::EF_LEFT_MOUSE_BUTTON); |
| ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, click_location, |
| click_location, ui::EventTimeForNow(), |
| - mouse_event_flags_ | ui::EF_LEFT_MOUSE_BUTTON, |
| + mouse_event_flags | ui::EF_LEFT_MOUSE_BUTTON, |
| ui::EF_LEFT_MOUSE_BUTTON); |
| ui::EventDispatchDetails details = |
| @@ -240,6 +187,26 @@ void AutoclickControllerImpl::DoAutoclick() { |
| return; |
| } |
| +void AutoclickControllerImpl::OnAutoclickCanceled() { |
| + SetTapDownTarget(nullptr); |
| +} |
| + |
| +void AutoclickControllerImpl::OnWindowDestroying(aura::Window* window) { |
| + DCHECK_EQ(tap_down_target_, window); |
| + autoclick_controller_common_->CancelAutoclick(); |
| +} |
| + |
| +void AutoclickControllerImpl::SetTapDownTarget(aura::Window* target) { |
| + if (tap_down_target_ == target) |
| + return; |
| + |
| + if (tap_down_target_) |
| + tap_down_target_->RemoveObserver(this); |
| + tap_down_target_ = target; |
| + if (tap_down_target_) |
| + tap_down_target_->AddObserver(this); |
| +} |
| + |
| // static. |
| AutoclickController* AutoclickController::CreateInstance() { |
| return new AutoclickControllerImpl(); |