1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_ACCESSIBILITY_MAGNIFIER_FULLSCREEN_MAGNIFIER_CONTROLLER_H_
#define ASH_ACCESSIBILITY_MAGNIFIER_FULLSCREEN_MAGNIFIER_CONTROLLER_H_
#include <map>
#include <memory>
#include "ash/ash_export.h"
#include "ash/public/cpp/accessibility_controller_enums.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/events/event_handler.h"
#include "ui/events/event_rewriter.h"
#include "ui/events/gestures/gesture_types.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
namespace aura {
class Window;
} // namespace aura
namespace gfx {
class Transform;
}
namespace ui {
class GestureProviderAura;
} // namespace ui
namespace ash {
// FullscreenMagnifierController implements GestureConsumer as it has its own
// GestureProvider to recognize gestures with screen coordinates of touches.
// Logical coordinates of touches cannot be used as they are changed with
// viewport change: scroll, zoom.
// FullscreenMagnifierController implements EventRewriter to see and rewrite
// touch events. Once the controller detects two fingers pinch or scroll, it
// starts consuming all touch events not to confuse an app or a browser on the
// screen. It needs to rewrite events to dispatch touch cancel events.
class ASH_EXPORT FullscreenMagnifierController
: public ui::EventHandler,
public ui::ImplicitAnimationObserver,
public aura::WindowObserver,
public ui::GestureConsumer,
public ui::EventRewriter {
public:
enum ScrollDirection {
SCROLL_NONE,
SCROLL_LEFT,
SCROLL_RIGHT,
SCROLL_UP,
SCROLL_DOWN
};
FullscreenMagnifierController();
FullscreenMagnifierController(const FullscreenMagnifierController&) = delete;
FullscreenMagnifierController& operator=(
const FullscreenMagnifierController&) = delete;
~FullscreenMagnifierController() override;
void set_mouse_following_mode(
MagnifierMouseFollowingMode mouse_following_mode) {
mouse_following_mode_ = mouse_following_mode;
}
MagnifierMouseFollowingMode mouse_following_mode() const {
return mouse_following_mode_;
}
// Enables (or disables if |enabled| is false) screen magnifier feature.
void SetEnabled(bool enabled);
// Returns if the screen magnifier is enabled or not.
bool IsEnabled() const;
// Sets the magnification ratio. 1.0f means no magnification.
void SetScale(float scale, bool animate);
// Returns the current magnification ratio.
float GetScale() const { return scale_; }
// Maps the current scale value to an index in the range between the minimum
// and maximum scale values, and steps up or down the scale depending on the
// value of |delta_index|.
void StepToNextScaleValue(int delta_index);
// Set the top-left point of the magnification window.
void MoveWindow(int x, int y, bool animate);
void MoveWindow(const gfx::Point& point, bool animate);
// Returns the current top-left point of the magnification window.
gfx::Point GetWindowPosition() const;
void SetScrollDirection(ScrollDirection direction);
// Returns the viewport (i.e. the current visible window)'s Rect in root
// window coordinates.
gfx::Rect GetViewportRect() const;
// Centers the viewport around the given point in screen coordinates.
void CenterOnPoint(const gfx::Point& point_in_screen);
// Move |rect_in_screen| within the magnifier viewport. If |rect_in_screen| is
// already completely within the viewport, do nothing. If any edge of
// |rect_in_screen| is outside the viewport (e.g. if rect is larger than or
// extends partially beyond the viewport), center the overflowing dimensions
// of the viewport on center of |rect_in_screen| (e.g. center viewport
// vertically if |rect| extends beyond bottom of screen). Called from
// Accessibility Common extension. Called from Accessibility Common extension.
void HandleMoveMagnifierToRect(const gfx::Rect& rect_in_screen);
// Switch the magnified root window to |new_root_window|. This does following:
// - Unzoom the current root_window.
// - Zoom the given new root_window |new_root_window|.
// - Switch the target window from current window to |new_root_window|.
void SwitchTargetRootWindow(aura::Window* new_root_window,
bool redraw_original_root);
// Returns the magnification transformation for the root window. If
// magnification is disabled, return an empty Transform.
gfx::Transform GetMagnifierTransform() const;
// Returns the last mouse cursor (or last touched) location.
gfx::Point GetPointOfInterestForTesting() {
return point_of_interest_in_root_;
}
// Returns true if magnifier is still on animation for moving viewport.
bool IsOnAnimationForTesting() const { return is_on_animation_; }
// Returns the current number of touch points.
int32_t GetTouchPointsForTesting() const { return touch_points_; }
void set_cursor_moved_callback_for_testing(
base::RepeatingCallback<void(const gfx::Point&)> callback) {
cursor_moved_callback_for_testing_ = std::move(callback);
}
private:
friend class FullscreenMagnifierControllerTest;
class GestureProviderClient;
// ui::ImplicitAnimationObserver overrides:
void OnImplicitAnimationsCompleted() override;
// aura::WindowObserver overrides:
void OnWindowDestroying(aura::Window* root_window) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
// ui::EventHandler overrides:
void OnMouseEvent(ui::MouseEvent* event) override;
void OnScrollEvent(ui::ScrollEvent* event) override;
void OnTouchEvent(ui::TouchEvent* event) override;
// ui::EventRewriter overrides:
ui::EventDispatchDetails RewriteEvent(
const ui::Event& event,
const Continuation continuation) override;
// ui::GestureConsumer:
const std::string& GetName() const override;
// Redraws the magnification window with the given origin position and the
// given scale. Returns true if the window is changed; otherwise, false.
// These methods should be called internally just after the scale and/or
// the position are changed to redraw the window.
bool Redraw(const gfx::PointF& position_in_pixels, float scale, bool animate);
// Redraws the magnification window with the given origin position in dip and
// the given scale. Returns true if the window is changed; otherwise, false.
// The last two parameters specify the animation duration and tween type.
// If |animation_in_ms| is zero, there will be no animation, and |tween_type|
// will be ignored.
bool RedrawDIP(const gfx::PointF& position_in_dip,
float scale,
int animation_in_ms,
gfx::Tween::Type tween_type);
// 1) If the screen is scrolling (i.e. animating) and should scroll further,
// it does nothing.
// 2) If the screen is scrolling (i.e. animating) and the direction is NONE,
// it stops the scrolling animation.
// 3) If the direction is set to value other than NONE, it starts the
// scrolling/ animation towards that direction.
void StartOrStopScrollIfNecessary();
// Redraw with the given zoom scale keeping the mouse cursor location. In
// other words, zoom (or unzoom) centering around the cursor.
// Ignore mouse position change after redrawing if |ignore_mouse_change| is
// true.
void RedrawKeepingMousePosition(float scale,
bool animate,
bool ignore_mouse_change);
// Takes mouse root `location` in floating-point DIP. Note at higher zoom
// levels, the floating point values matter more, because the ratio of px to
// DIP increases.
void OnMouseMove(const gfx::PointF& location);
// Move the mouse cursot to the given point. Actual move will be done when
// the animation is completed. This should be called after animation is
// started.
void AfterAnimationMoveCursorTo(const gfx::Point& location);
// Returns if the magnification scale is 1.0 or not (larger then 1.0).
bool IsMagnified() const;
// Returns the rect of the magnification window.
gfx::RectF GetWindowRectDIP(float scale) const;
// Returns the size of the root window.
gfx::Size GetHostSizeDIP() const;
// Correct the given scale value if necessary.
void ValidateScale(float* scale);
// Process pending gestures in |gesture_provider_|. This method returns true
// if the controller needs to cancel existing touches.
bool ProcessGestures();
// Moves the viewport when |point| is located within
// |x_margin| and |y_margin| to the edge of the visible
// window region. The viewport will be moved so that the |point| will be
// moved to the point where it has |x_margin| and |y_margin|
// to the edge of the visible region if possible (less if the mouse is closer
// to the edge of the screen). If |reduce_bottom_margin| is true,
// then a reduced value will be used as the |y_margin| and
// |y_target_margin| for the bottom edge.
void MoveMagnifierWindowFollowPoint(const gfx::Point& point,
int x_margin,
int y_margin,
bool reduce_bottom_margin);
// Moves the viewport to center |point| in magnifier screen.
void MoveMagnifierWindowCenterPoint(const gfx::Point& point);
// Moves the viewport so that |rect| is fully visible. If |rect| is larger
// than the viewport horizontally or vertically, the viewport will be moved
// to center the |rect| in that dimension.
void MoveMagnifierWindowFollowRect(const gfx::Rect& rect);
// Moves the cursor to the given location in the root window.
void MoveCursorTo(const gfx::Point& root_location);
// Target root window. This must not be NULL.
raw_ptr<aura::Window> root_window_;
// True if the magnified window is currently animating a change. Otherwise,
// false.
bool is_on_animation_ = false;
bool is_enabled_ = false;
bool keep_focus_centered_ = false;
// The current mouse following mode (e.g. continuous, centered, edge).
MagnifierMouseFollowingMode mouse_following_mode_ =
MagnifierMouseFollowingMode::kEdge;
// True if the cursor needs to move the given position after the animation
// will be finished. When using this, set |position_after_animation_| as well.
bool move_cursor_after_animation_ = false;
// Stores the position of cursor to be moved after animation.
gfx::Point position_after_animation_;
// Stores the last mouse cursor (or last touched) location. This value is
// used on zooming to keep this location visible.
gfx::Point point_of_interest_in_root_;
// Current scale, origin (left-top) position of the magnification window.
float scale_;
gfx::PointF origin_;
float original_scale_;
gfx::PointF original_origin_;
ScrollDirection scroll_direction_ = SCROLL_NONE;
// If true, FullscreenMagnifierController consumes all touch events.
bool consume_touch_event_ = false;
// Number of touch points on the screen.
int32_t touch_points_ = 0;
// Map for holding EventType::kTouchPress events. Those events are used to
// dispatch EventType::kTouchCancelled events. Events will be removed from
// this map when press events are cancelled, i.e. size of this map can be
// different from number of touches on the screen. Key is pointer id.
std::map<int32_t, std::unique_ptr<ui::TouchEvent>> press_event_map_;
std::unique_ptr<GestureProviderClient> gesture_provider_client_;
// MagnificationCotroller owns its GestureProvider to detect gestures with
// screen coordinates of touch events. As FullscreenMagnifierController
// changes zoom level and moves viewport, logical coordinates of touches
// cannot be used for gesture detection as they are changed if the controller
// reacts to gestures.
std::unique_ptr<ui::GestureProviderAura> gesture_provider_;
// Most recent caret position in |root_window_| coordinates.
gfx::Point caret_point_;
// Flag to draw a preview box around magnifier viewport area instead of
// magnifying the screen for debugging.
bool magnifier_debug_draw_rect_ = false;
// Called every time MoveCursorTo is called, when set in tests.
base::RepeatingCallback<void(const gfx::Point&)>
cursor_moved_callback_for_testing_;
};
} // namespace ash
#endif // ASH_ACCESSIBILITY_MAGNIFIER_FULLSCREEN_MAGNIFIER_CONTROLLER_H_
|