Commit ab4edf57 authored by Katie D's avatar Katie D Committed by Commit Bot

Refactor AutoclickControllerCommon into AutoclickController.

This cleans up Autoclick code, resolving a TODO, by refactoring
AutoclickControllerCommon into AutoclickController and eliminating
the need for the delegate. Also makes AutoclickController into
a concrete class, removing the need for AutoclickControllerImpl
and improving readability.

Bug: 876115
Change-Id: Id38917adc38aafcb4f4602e8827f0ad43d1f1dba
Reviewed-on: https://chromium-review.googlesource.com/c/1277961
Commit-Queue: Katie Dektar <katie@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Cr-Commit-Position: refs/heads/master@{#599251}
parent 77e3a8b3
This diff is collapsed.
...@@ -8,35 +8,77 @@ ...@@ -8,35 +8,77 @@
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "ui/aura/window_observer.h"
#include "ui/events/event_handler.h"
#include "ui/gfx/geometry/point.h"
namespace base {
class RetainingOneShotTimer;
} // namespace base
namespace views {
class Widget;
} // namespace views
namespace ash { namespace ash {
// Controls the autoclick a11y feature in ash. class AutoclickRingHandler;
// If enabled, we will automatically send a click event a short time after
// the mouse had been at rest. // Autoclick is one of the accessibility features. If enabled, two circles will
class ASH_EXPORT AutoclickController { // animate at the mouse event location and an automatic click event will happen
// after a certain amount of time at that location.
class ASH_EXPORT AutoclickController : public ui::EventHandler,
public aura::WindowObserver {
public: public:
virtual ~AutoclickController() {} AutoclickController();
~AutoclickController() override;
// Set whether autoclicking is enabled. // Set whether autoclicking is enabled.
virtual void SetEnabled(bool enabled) = 0; void SetEnabled(bool enabled);
// Returns true if autoclicking is enabled. // Returns true if autoclicking is enabled.
virtual bool IsEnabled() const = 0; bool IsEnabled() const;
// Set the time to wait in milliseconds from when the mouse stops moving // Set the time to wait in milliseconds from when the mouse stops moving
// to when the autoclick event is sent. // to when the autoclick event is sent.
virtual void SetAutoclickDelay(base::TimeDelta delay) = 0; void SetAutoclickDelay(base::TimeDelta delay);
static AutoclickController* CreateInstance();
// Gets the default wait time as a base::TimeDelta object. // Gets the default wait time as a base::TimeDelta object.
static base::TimeDelta GetDefaultAutoclickDelay(); static base::TimeDelta GetDefaultAutoclickDelay();
protected:
AutoclickController() {}
private: private:
void SetTapDownTarget(aura::Window* target);
void CreateAutoclickRingWidget(const gfx::Point& point_in_screen);
void UpdateAutoclickRingWidget(views::Widget* widget,
const gfx::Point& point_in_screen);
void DoAutoclick();
void CancelAutoclick();
void InitClickTimer();
void UpdateRingWidget(const gfx::Point& mouse_location);
// ui::EventHandler overrides:
void OnMouseEvent(ui::MouseEvent* event) override;
void OnKeyEvent(ui::KeyEvent* event) override;
void OnTouchEvent(ui::TouchEvent* event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void OnScrollEvent(ui::ScrollEvent* event) override;
// aura::WindowObserver overrides:
void OnWindowDestroying(aura::Window* window) override;
bool enabled_;
// The target window is observed by AutoclickController for the duration
// of a autoclick gesture.
aura::Window* tap_down_target_;
std::unique_ptr<views::Widget> widget_;
base::TimeDelta delay_;
int mouse_event_flags_;
std::unique_ptr<base::RetainingOneShotTimer> autoclick_timer_;
// The position in screen coordinates used to determine
// the distance the mouse has moved.
gfx::Point anchor_location_;
std::unique_ptr<AutoclickRingHandler> autoclick_ring_handler_;
DISALLOW_COPY_AND_ASSIGN(AutoclickController); DISALLOW_COPY_AND_ASSIGN(AutoclickController);
}; };
......
...@@ -6,9 +6,6 @@ import("//build/config/ui.gni") ...@@ -6,9 +6,6 @@ import("//build/config/ui.gni")
source_set("autoclick") { source_set("autoclick") {
sources = [ sources = [
"autoclick_controller_common.cc",
"autoclick_controller_common.h",
"autoclick_controller_common_delegate.h",
"autoclick_ring_handler.cc", "autoclick_ring_handler.cc",
"autoclick_ring_handler.h", "autoclick_ring_handler.h",
] ]
......
// Copyright 2016 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/autoclick/common/autoclick_controller_common.h"
#include "ash/autoclick/common/autoclick_controller_common_delegate.h"
#include "ui/aura/window.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/geometry/vector2d.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(const 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
AutoclickControllerCommon::AutoclickControllerCommon(
base::TimeDelta delay,
AutoclickControllerCommonDelegate* delegate)
: delay_(delay),
mouse_event_flags_(ui::EF_NONE),
delegate_(delegate),
widget_(nullptr),
anchor_location_(-kMovementThreshold, -kMovementThreshold),
autoclick_ring_handler_(new AutoclickRingHandler()) {
InitClickTimer();
}
AutoclickControllerCommon::~AutoclickControllerCommon() = default;
void AutoclickControllerCommon::HandleMouseEvent(const ui::MouseEvent& event) {
gfx::Point mouse_location = event.location();
if (event.type() == ui::ET_MOUSE_MOVED &&
!(event.flags() & ui::EF_IS_SYNTHESIZED)) {
mouse_event_flags_ = event.flags();
// TODO(riajiang): Make getting screen location work for mus as well.
// Also switch to take in a PointerEvent instead of a MouseEvent after
// this is done. (crbug.com/608547)
if (event.target() != nullptr) {
::wm::ConvertPointToScreen(static_cast<aura::Window*>(event.target()),
&mouse_location);
}
UpdateRingWidget(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 occurring 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();
autoclick_ring_handler_->StartGesture(delay_, anchor_location_, widget_);
} else if (autoclick_timer_->IsRunning()) {
autoclick_ring_handler_->SetGestureCenter(mouse_location, widget_);
}
} else if (event.type() == ui::ET_MOUSE_PRESSED) {
CancelAutoclick();
} else if (event.type() == ui::ET_MOUSEWHEEL &&
autoclick_timer_->IsRunning()) {
autoclick_timer_->Reset();
UpdateRingWidget(mouse_location);
autoclick_ring_handler_->StartGesture(delay_, anchor_location_, widget_);
}
}
void AutoclickControllerCommon::HandleKeyEvent(const 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()))
CancelAutoclick();
}
void AutoclickControllerCommon::SetAutoclickDelay(const base::TimeDelta delay) {
delay_ = delay;
InitClickTimer();
}
void AutoclickControllerCommon::CancelAutoclick() {
autoclick_timer_->Stop();
autoclick_ring_handler_->StopGesture();
delegate_->OnAutoclickCanceled();
}
void AutoclickControllerCommon::InitClickTimer() {
autoclick_timer_.reset(new base::RetainingOneShotTimer(
FROM_HERE, delay_,
base::Bind(&AutoclickControllerCommon::DoAutoclick,
base::Unretained(this))));
}
void AutoclickControllerCommon::DoAutoclick() {
gfx::Point screen_location =
display::Screen::GetScreen()->GetCursorScreenPoint();
anchor_location_ = screen_location;
delegate_->DoAutoclick(screen_location, mouse_event_flags_);
}
void AutoclickControllerCommon::UpdateRingWidget(
const gfx::Point& mouse_location) {
if (!widget_) {
widget_ = delegate_->CreateAutoclickRingWidget(mouse_location);
} else {
delegate_->UpdateAutoclickRingWidget(widget_, mouse_location);
}
}
} // namespace ash
// Copyright 2016 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.
#ifndef ASH_AUTOCLICK_COMMON_AUTOCLICK_CONTROLLER_COMMON_H
#define ASH_AUTOCLICK_COMMON_AUTOCLICK_CONTROLLER_COMMON_H
#include "ash/autoclick/common/autoclick_ring_handler.h"
#include "base/macros.h"
#include "base/timer/timer.h"
#include "ui/gfx/geometry/point.h"
namespace views {
class Widget;
}
namespace ui {
class MouseEvent;
class KeyEvent;
}
namespace ash {
class AutoclickControllerCommonDelegate;
// Autoclick is one of the accessibility features. If enabled, two circles will
// animate at the mouse event location and an automatic click event will happen
// after a certain amout of time at that location.
// AutoclickControllerCommon is the common code for both ash and mus to handle
// events and to manage autoclick time delay and timer.
// TODO(jamescook): Collapse with AutoclickController. https://crbug.com/876115
class AutoclickControllerCommon {
public:
AutoclickControllerCommon(base::TimeDelta delay,
AutoclickControllerCommonDelegate* delegate);
~AutoclickControllerCommon();
void HandleMouseEvent(const ui::MouseEvent& event);
void HandleKeyEvent(const ui::KeyEvent& event);
void SetAutoclickDelay(const base::TimeDelta delay);
void CancelAutoclick();
private:
void InitClickTimer();
void DoAutoclick();
void UpdateRingWidget(const gfx::Point& mouse_location);
base::TimeDelta delay_;
int mouse_event_flags_;
std::unique_ptr<base::RetainingOneShotTimer> autoclick_timer_;
AutoclickControllerCommonDelegate* delegate_;
views::Widget* widget_;
// The position in screen coordinates used to determine
// the distance the mouse has moved.
gfx::Point anchor_location_;
std::unique_ptr<AutoclickRingHandler> autoclick_ring_handler_;
DISALLOW_COPY_AND_ASSIGN(AutoclickControllerCommon);
};
} // namespace ash
#endif // ASH_AUTOCLICK_COMMON_AUTOCLICK_CONTROLLER_COMMON_H
// Copyright 2016 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.
#ifndef ASH_AUTOCLICK_COMMON_AUTOCLICK_CONTROLLER_COMMON_DELEGATE_H
#define ASH_AUTOCLICK_COMMON_AUTOCLICK_CONTROLLER_COMMON_DELEGATE_H
namespace views {
class Widget;
}
namespace gfx {
class Point;
}
namespace ash {
class AutoclickControllerCommonDelegate {
public:
// Creates a ring widget at |point_in_screen|.
// AutoclickControllerCommonDelegate still has ownership of the widget they
// created.
virtual views::Widget* CreateAutoclickRingWidget(
const gfx::Point& point_in_screen) = 0;
// Moves |widget| to |point_in_screen|. The point may be on a different
// display.
virtual void UpdateAutoclickRingWidget(views::Widget* widget,
const gfx::Point& point_in_screen) = 0;
// Generates a click at |point_in_screen|. |mouse_event_flags| may contain key
// modifiers (e.g. shift, control) for the click.
virtual void DoAutoclick(const gfx::Point& point_in_screen,
const int mouse_event_flags) = 0;
virtual void OnAutoclickCanceled() = 0;
protected:
virtual ~AutoclickControllerCommonDelegate() {}
};
} // namespace ash
#endif // ASH_AUTOCLICK_COMMON_AUTOCLICK_CONTROLLER_COMMON_DELEGATE_H
...@@ -1177,7 +1177,7 @@ void Shell::Init( ...@@ -1177,7 +1177,7 @@ void Shell::Init(
magnification_controller_ = std::make_unique<MagnificationController>(); magnification_controller_ = std::make_unique<MagnificationController>();
mru_window_tracker_ = std::make_unique<MruWindowTracker>(); mru_window_tracker_ = std::make_unique<MruWindowTracker>();
autoclick_controller_.reset(AutoclickController::CreateInstance()); autoclick_controller_ = std::make_unique<AutoclickController>();
high_contrast_controller_.reset(new HighContrastController); high_contrast_controller_.reset(new HighContrastController);
......
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