Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/magnifier/magnification_controller.h" | 5 #include "ash/magnifier/magnification_controller.h" |
| 6 | 6 |
| 7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
| 8 #include "ui/aura/event.h" | |
| 8 #include "ui/aura/root_window.h" | 9 #include "ui/aura/root_window.h" |
| 10 #include "ui/aura/shared/root_window_event_filter.h" | |
| 9 #include "ui/aura/window.h" | 11 #include "ui/aura/window.h" |
| 10 #include "ui/aura/window_property.h" | 12 #include "ui/aura/window_property.h" |
| 13 #include "ui/gfx/point3.h" | |
| 14 #include "ui/compositor/dip_util.h" | |
| 11 #include "ui/compositor/layer.h" | 15 #include "ui/compositor/layer.h" |
| 16 #include "ui/compositor/layer_animation_observer.h" | |
| 12 #include "ui/compositor/scoped_layer_animation_settings.h" | 17 #include "ui/compositor/scoped_layer_animation_settings.h" |
| 13 | 18 |
| 14 namespace { | 19 namespace { |
| 15 | 20 |
| 16 const float kMaximumMagnifiScale = 4.0f; | 21 const float kMaximumMagnifiScale = 4.0f; |
| 17 const float kMaximumMagnifiScaleThreshold = 4.0f; | 22 const float kMaximumMagnifiScaleThreshold = 4.0f; |
| 18 const float kMinimumMagnifiScale = 1.0f; | 23 const float kMinimumMagnifiScale = 1.0f; |
| 19 const float kMinimumMagnifiScaleThreshold = 1.1f; | 24 const float kMinimumMagnifiScaleThreshold = 1.1f; |
| 20 | 25 |
| 21 } // namespace | 26 } // namespace |
| 22 | 27 |
| 23 namespace ash { | 28 namespace ash { |
| 24 namespace internal { | 29 namespace internal { |
| 25 | 30 |
| 26 MagnificationController::MagnificationController() | 31 //////////////////////////////////////////////////////////////////////////////// |
| 32 // MagnificationControllerImpl: | |
| 33 | |
| 34 class MagnificationControllerImpl : virtual public MagnificationController, | |
| 35 public ui::ImplicitAnimationObserver { | |
| 36 public: | |
| 37 MagnificationControllerImpl(); | |
| 38 virtual ~MagnificationControllerImpl() {} | |
| 39 | |
| 40 // MagnificationController overrides: | |
| 41 virtual void SetScale(float scale, bool animation) OVERRIDE; | |
| 42 float GetScale() const { return scale_; } | |
|
sky
2012/06/11 16:19:14
virtual OVERRIDE on all these.
yoshiki
2012/06/19 17:56:16
Done.
| |
| 43 void MoveWindow(int x, int y, bool animation); | |
| 44 void MoveWindow(const gfx::Point& point, bool animation); | |
| 45 gfx::Point GetWindowPosition() const { return gfx::Point(x_, y_); } | |
| 46 void EnsureShowRect(const gfx::Rect& rect, bool animation); | |
| 47 virtual void EnsureShowPoint(const gfx::Point& point, | |
| 48 bool animation) OVERRIDE; | |
| 49 | |
| 50 private: | |
| 51 aura::RootWindow* root_window_; | |
| 52 bool is_on_zooming_; | |
|
sky
2012/06/11 16:19:14
Add description.
yoshiki
2012/06/19 17:56:16
Done.
| |
| 53 | |
| 54 // Current scale, position of the magnification window. | |
| 55 float scale_; | |
| 56 int x_; | |
|
sky
2012/06/11 16:19:14
Any reason you're not using gfx::Point?
yoshiki
2012/06/19 17:56:16
Done.
| |
| 57 int y_; | |
| 58 | |
| 59 // ui::ImplicitAnimationObserver overrides: | |
|
sky
2012/06/11 16:19:14
methods before fields.
yoshiki
2012/06/19 17:56:16
Done.
| |
| 60 virtual void OnImplicitAnimationsCompleted() OVERRIDE; | |
| 61 | |
| 62 // should be called internally just after the scale and/or the position are | |
| 63 // changed. | |
| 64 bool Redraw(const gfx::Point& position, float scale, bool animation); | |
| 65 bool RedrawDIP(const gfx::Point& position, float scale, bool animation); | |
| 66 | |
| 67 // Ensures that the given point, rect or last mouse location is inside | |
| 68 // magnification window. If not, the controller moves the window to contain | |
| 69 // the given point/rect. | |
| 70 void EnsureShowRectWithScale( | |
| 71 const gfx::Rect& target_rect, float scale, bool animation); | |
| 72 void EnsureShowRectDIP( | |
| 73 const gfx::Rect& target_rect_in_dip, float scale, bool animation); | |
|
sky
2012/06/11 16:19:14
If you can't fill all arguments on the first line,
yoshiki
2012/06/19 17:56:16
Done.
| |
| 74 void EnsureShowPointWithScale( | |
| 75 const gfx::Point& point, float scale, bool animation); | |
| 76 void OnMouseMove(); | |
| 77 | |
| 78 // Returns if the magnification scale is 1.0 or not (larger then 1.0). | |
| 79 bool IsMagnified() const; | |
| 80 | |
| 81 // Returns the rect of the magnification window. | |
| 82 gfx::Rect GetWindowRectDIP(float scale) const; | |
| 83 // Returns the size of the root window. | |
| 84 gfx::Size GetHostSizeDIP() const; | |
| 85 | |
| 86 // Correct the givin scale value if nessesary. | |
| 87 void ValidateScale(float* scale); | |
| 88 | |
| 89 // aura::EventFilter overrides: | |
| 90 virtual bool PreHandleKeyEvent(aura::Window* target, | |
| 91 aura::KeyEvent* event) OVERRIDE; | |
| 92 virtual bool PreHandleMouseEvent(aura::Window* target, | |
| 93 aura::MouseEvent* event) OVERRIDE; | |
| 94 virtual ui::TouchStatus PreHandleTouchEvent(aura::Window* target, | |
| 95 aura::TouchEvent* event) OVERRIDE; | |
| 96 virtual ui::GestureStatus PreHandleGestureEvent( | |
| 97 aura::Window* target, | |
| 98 aura::GestureEvent* event) OVERRIDE; | |
| 99 | |
| 100 DISALLOW_COPY_AND_ASSIGN(MagnificationControllerImpl); | |
| 101 }; | |
| 102 | |
| 103 //////////////////////////////////////////////////////////////////////////////// | |
| 104 // MagnificationControllerImpl: | |
| 105 | |
| 106 MagnificationControllerImpl::MagnificationControllerImpl() | |
| 27 : scale_(1.0f), x_(0), y_(0) { | 107 : scale_(1.0f), x_(0), y_(0) { |
|
sky
2012/06/11 16:19:14
each arg on its own line.
sky
2012/06/11 16:19:14
Set root_window_ and is_on_zooming_ in the member
yoshiki
2012/06/19 17:56:16
Done.
yoshiki
2012/06/19 17:56:16
Done.
| |
| 28 root_window_ = ash::Shell::GetRootWindow(); | 108 root_window_ = ash::Shell::GetRootWindow(); |
| 29 } | 109 } |
| 30 | 110 |
| 31 void MagnificationController::SetScale(float scale) { | 111 bool MagnificationControllerImpl::Redraw( |
| 112 const gfx::Point& position, float scale, bool animation) { | |
| 113 const gfx::Point position_in_dip = | |
| 114 ui::ConvertPointToDIP(root_window_->layer(), position); | |
| 115 return RedrawDIP(position_in_dip, scale, animation); | |
| 116 } | |
| 117 | |
| 118 bool MagnificationControllerImpl::RedrawDIP( | |
| 119 const gfx::Point& position_in_dip, float scale, bool animation) { | |
| 120 int x = position_in_dip.x(); | |
| 121 int y = position_in_dip.y(); | |
| 122 | |
| 123 ValidateScale(&scale); | |
| 124 | |
| 125 if (x < 0) | |
| 126 x = 0; | |
| 127 if (y < 0) | |
| 128 y = 0; | |
| 129 | |
| 130 const gfx::Size host_size_in_dip = GetHostSizeDIP(); | |
| 131 const gfx::Size window_size_in_dip = GetWindowRectDIP(scale).size(); | |
| 132 int max_x = host_size_in_dip.width() - window_size_in_dip.width(); | |
| 133 int max_y = host_size_in_dip.height() - window_size_in_dip.height(); | |
| 134 if (x > max_x) | |
| 135 x = max_x; | |
| 136 if (y > max_y) | |
| 137 y = max_y; | |
| 138 | |
| 139 // Ignores 1 px diffirence because it may be error on calculation. | |
| 140 if (std::abs(x_ - x) <= 1 && std::abs(y_ - y) <= 1 && scale == scale_) | |
| 141 return false; | |
| 142 | |
| 143 x_ = x; | |
| 144 y_ = y; | |
| 32 scale_ = scale; | 145 scale_ = scale; |
| 33 RedrawScreen(true); | |
| 34 } | |
| 35 | |
| 36 void MagnificationController::MoveWindow(int x, int y) { | |
| 37 y_ = y; | |
| 38 x_ = x; | |
| 39 RedrawScreen(true); | |
| 40 } | |
| 41 | |
| 42 void MagnificationController::MoveWindow(const gfx::Point& point) { | |
| 43 MoveWindow(point.x(), point.y()); | |
| 44 } | |
| 45 | |
| 46 void MagnificationController::EnsureShowRect(const gfx::Rect& target_rect) { | |
| 47 gfx::Rect rect = GetWindowRect().AdjustToFit(target_rect); | |
| 48 MoveWindow(rect.x(), rect.y()); | |
| 49 } | |
| 50 | |
| 51 void MagnificationController::EnsureShowPoint(const gfx::Point& point, | |
| 52 bool animation) { | |
| 53 gfx::Rect rect = GetWindowRect(); | |
| 54 | |
| 55 if (rect.Contains(point)) | |
| 56 return; | |
| 57 | |
| 58 if (point.x() < rect.x()) | |
| 59 x_ = point.x(); | |
| 60 else if(rect.right() < point.x()) | |
| 61 x_ = point.x() - rect.width(); | |
| 62 | |
| 63 if (point.y() < rect.y()) | |
| 64 y_ = point.y(); | |
| 65 else if(rect.bottom() < point.y()) | |
| 66 y_ = point.y() - rect.height(); | |
| 67 | |
| 68 RedrawScreen(animation); | |
| 69 } | |
| 70 | |
| 71 void MagnificationController::RedrawScreen(bool animation) { | |
| 72 | |
| 73 // Adjust the scale to just |kMinimumMagnifiScale| if scale is smaller than | |
| 74 // |kMinimumMagnifiScaleThreshold|; | |
| 75 if (scale_ < kMinimumMagnifiScaleThreshold) | |
| 76 scale_ = kMinimumMagnifiScale; | |
| 77 // Adjust the scale to just |kMinimumMagnifiScale| if scale is bigger than | |
| 78 // |kMinimumMagnifiScaleThreshold|; | |
| 79 if (scale_ > kMaximumMagnifiScaleThreshold) | |
| 80 scale_ = kMaximumMagnifiScale; | |
| 81 | |
| 82 if (x_ < 0) | |
| 83 x_ = 0; | |
| 84 if (y_ < 0) | |
| 85 y_ = 0; | |
| 86 | |
| 87 gfx::Size host_size = root_window_->GetHostSize(); | |
| 88 gfx::Size window_size = GetWindowRect().size(); | |
| 89 int max_x = host_size.width() - window_size.width(); | |
| 90 int max_y = host_size.height() - window_size.height(); | |
| 91 if (x_ > max_x) | |
| 92 x_ = max_x; | |
| 93 if (y_ > max_y) | |
| 94 y_ = max_y; | |
| 95 | |
| 96 | |
| 97 float scale = scale_; | |
| 98 int x = x_; | |
| 99 int y = y_; | |
| 100 | 146 |
| 101 // Creates transform matrix. | 147 // Creates transform matrix. |
| 102 ui::Transform transform; | 148 ui::Transform transform; |
| 103 // Flips the signs intentionally to convert them from the position of the | 149 // Flips the signs intentionally to convert them from the position of the |
| 104 // magnification window. | 150 // magnification window. |
| 105 transform.ConcatTranslate(-x, -y); | 151 transform.ConcatTranslate(-x_, -y_); |
| 106 transform.ConcatScale(scale, scale); | 152 transform.ConcatScale(scale_, scale_); |
| 107 | 153 |
| 108 if (animation) { | 154 ui::ScopedLayerAnimationSettings settings( |
| 109 ui::ScopedLayerAnimationSettings settings( | 155 root_window_->layer()->GetAnimator()); |
| 110 root_window_->layer()->GetAnimator()); | 156 settings.AddObserver(this); |
| 111 settings.SetPreemptionStrategy( | 157 settings.SetPreemptionStrategy( |
| 112 ui::LayerAnimator::REPLACE_QUEUED_ANIMATIONS); | 158 ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 113 settings.SetTweenType(ui::Tween::EASE_IN_OUT); | 159 settings.SetTweenType(ui::Tween::EASE_OUT); |
| 114 settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100)); | 160 settings.SetTransitionDuration( |
| 161 base::TimeDelta::FromMilliseconds(animation ? 100 : 0)); | |
| 162 | |
| 163 root_window_->layer()->SetTransform(transform); | |
| 164 | |
| 165 return true; | |
| 166 } | |
| 167 | |
| 168 void MagnificationControllerImpl::EnsureShowRectWithScale( | |
| 169 const gfx::Rect& target_rect, float scale, bool animation) { | |
| 170 const gfx::Rect target_rect_in_dip = | |
| 171 ui::ConvertRectToDIP(root_window_->layer(), target_rect); | |
| 172 EnsureShowRectDIP(target_rect_in_dip, scale, animation); | |
| 173 } | |
| 174 | |
| 175 void MagnificationControllerImpl::EnsureShowRectDIP( | |
| 176 const gfx::Rect& target_rect, float scale, bool animation) { | |
| 177 ValidateScale(&scale); | |
| 178 | |
| 179 const gfx::Rect window_rect = GetWindowRectDIP(scale); | |
| 180 if (scale == scale_ && window_rect.Contains(target_rect)) | |
| 181 return; | |
| 182 | |
| 183 gfx::Rect rect = window_rect; | |
| 184 if (target_rect.width() > rect.width()) | |
| 185 rect.set_x(target_rect.CenterPoint().x() - rect.x() / 2); | |
| 186 else if (target_rect.right() < rect.x()) | |
| 187 rect.set_x(target_rect.right()); | |
| 188 else if (rect.right() < target_rect.x()) | |
| 189 rect.set_x(target_rect.x() - rect.width()); | |
| 190 | |
| 191 if (rect.height() > window_rect.height()) | |
| 192 rect.set_y(target_rect.CenterPoint().y() - rect.y() / 2); | |
| 193 else if (target_rect.bottom() < rect.y()) | |
| 194 rect.set_y(target_rect.bottom()); | |
| 195 else if (rect.bottom() < target_rect.y()) | |
| 196 rect.set_y(target_rect.y() - rect.height()); | |
| 197 | |
| 198 RedrawDIP(rect.origin(), scale, animation); | |
| 199 } | |
| 200 | |
| 201 void MagnificationControllerImpl::EnsureShowPointWithScale( | |
| 202 const gfx::Point& point, float scale, bool animation) { | |
| 203 EnsureShowRectWithScale(gfx::Rect(point, gfx::Size(0, 0)), scale, animation); | |
| 204 } | |
| 205 | |
| 206 void MagnificationControllerImpl::OnMouseMove() { | |
| 207 gfx::Point mouse = root_window_->last_mouse_location(); | |
|
oshima
2012/06/11 21:48:30
please use the mouse event instead of using last m
yoshiki
2012/06/19 17:56:16
Done.
| |
| 208 | |
| 209 int x = x_; | |
| 210 int y = y_; | |
| 211 bool start_zoom = false; | |
| 212 | |
| 213 const gfx::Rect window_rect = GetWindowRectDIP(scale_); | |
| 214 const int left = window_rect.x(); | |
| 215 const int right = window_rect.right(); | |
| 216 const int width_margin = static_cast<int>(0.1f * window_rect.width()); | |
| 217 const int width_offset = static_cast<int>(0.5f * window_rect.width()); | |
| 218 | |
| 219 if (mouse.x() < left + width_margin) { | |
| 220 x -= width_offset; | |
| 221 start_zoom = true; | |
| 222 } else if (right - width_margin < mouse.x()) { | |
| 223 x += width_offset; | |
| 224 start_zoom = true; | |
| 115 } | 225 } |
| 116 | 226 |
| 117 root_window_->layer()->SetTransform(transform); | 227 const int top = window_rect.y(); |
| 118 } | 228 const int bottom = window_rect.bottom(); |
| 119 | 229 // Uses same margin with x-axis's one. |
| 120 gfx::Rect MagnificationController::GetWindowRect() { | 230 const int height_margin = width_margin; |
| 121 gfx::Size size = root_window_->GetHostSize(); | 231 const int height_offset = static_cast<int>(0.5f * window_rect.height()); |
| 122 int width = size.width() / scale_; | 232 |
| 123 int height = size.height() / scale_; | 233 if (mouse.y() < top + height_margin) { |
| 234 y -= height_offset; | |
| 235 start_zoom = true; | |
| 236 } else if (bottom - height_margin < mouse.y()) { | |
| 237 y += height_offset; | |
| 238 start_zoom = true; | |
| 239 } | |
| 240 | |
| 241 if (start_zoom && !is_on_zooming_) { | |
| 242 bool ret = Redraw(gfx::Point(x, y), scale_, true); | |
| 243 | |
| 244 if (ret) { | |
| 245 is_on_zooming_ = true; | |
| 246 | |
| 247 int x_diff = x_ - window_rect.x(); | |
| 248 int y_diff = y_ - window_rect.y(); | |
| 249 // If the magnified region is moved, hides the mouse cursor and moves it. | |
| 250 if (x_diff != 0 || y_diff != 0) { | |
| 251 ash::Shell::GetInstance()-> | |
| 252 root_filter()->set_update_cursor_visibility(false); | |
| 253 root_window_->ShowCursor(false); | |
| 254 mouse.set_x(mouse.x() - (x_ - window_rect.x())); | |
| 255 mouse.set_y(mouse.y() - (y_ - window_rect.y())); | |
| 256 root_window_->MoveCursorTo(mouse); | |
| 257 } | |
| 258 } | |
| 259 } | |
| 260 } | |
| 261 | |
| 262 gfx::Size MagnificationControllerImpl::GetHostSizeDIP() const { | |
| 263 return ui::ConvertSizeToDIP(root_window_->layer(), | |
| 264 root_window_->GetHostSize()); | |
| 265 } | |
| 266 | |
| 267 gfx::Rect MagnificationControllerImpl::GetWindowRectDIP(float scale) const { | |
| 268 const gfx::Size size_in_dip = | |
| 269 ui::ConvertSizeToDIP(root_window_->layer(), | |
| 270 root_window_->GetHostSize()); | |
| 271 const int width = size_in_dip.width() / scale; | |
| 272 const int height = size_in_dip.height() / scale; | |
| 124 | 273 |
| 125 return gfx::Rect(x_, y_, width, height); | 274 return gfx::Rect(x_, y_, width, height); |
| 126 } | 275 } |
| 127 | 276 |
| 277 bool MagnificationControllerImpl::IsMagnified() const { | |
| 278 return scale_ >= kMinimumMagnifiScaleThreshold; | |
| 279 } | |
| 280 | |
| 281 void MagnificationControllerImpl::ValidateScale(float* scale) { | |
| 282 // Adjust the scale to just |kMinimumMagnifiScale| if scale is smaller than | |
| 283 // |kMinimumMagnifiScaleThreshold|; | |
| 284 if (*scale < kMinimumMagnifiScaleThreshold) | |
| 285 *scale = kMinimumMagnifiScale; | |
| 286 | |
| 287 // Adjust the scale to just |kMinimumMagnifiScale| if scale is bigger than | |
| 288 // |kMinimumMagnifiScaleThreshold|; | |
| 289 if (*scale > kMaximumMagnifiScaleThreshold) | |
| 290 *scale = kMaximumMagnifiScale; | |
| 291 } | |
| 292 | |
| 293 void MagnificationControllerImpl::OnImplicitAnimationsCompleted() { | |
| 294 root_window_->ShowCursor(true); | |
| 295 is_on_zooming_ = false; | |
| 296 } | |
| 297 | |
| 298 //////////////////////////////////////////////////////////////////////////////// | |
| 299 // MagnificationControllerImpl: MagnificationController implementation | |
| 300 | |
| 301 void MagnificationControllerImpl::SetScale(float scale, bool animation) { | |
| 302 ValidateScale(&scale); | |
| 303 | |
| 304 // Try not to change the point which the mouse cursor indicates to. | |
| 305 const gfx::Rect window_rect = GetWindowRectDIP(scale); | |
| 306 const gfx::Point mouse = root_window_->last_mouse_location(); | |
| 307 const gfx::Point origin = gfx::Point(mouse.x() * (1.0f - 1.0f / scale), | |
| 308 mouse.y() * (1.0f - 1.0f / scale)); | |
| 309 Redraw(origin, scale, animation); | |
| 310 } | |
| 311 | |
| 312 void MagnificationControllerImpl::MoveWindow(int x, int y, bool animation) { | |
| 313 Redraw(gfx::Point(x, y), scale_, animation); | |
| 314 } | |
| 315 | |
| 316 void MagnificationControllerImpl::MoveWindow( | |
| 317 const gfx::Point& point, bool animation) { | |
| 318 Redraw(point, scale_, animation); | |
| 319 } | |
| 320 | |
| 321 void MagnificationControllerImpl::EnsureShowRect( | |
| 322 const gfx::Rect& target_rect, bool animation) { | |
| 323 EnsureShowRectWithScale(target_rect, scale_, animation); | |
| 324 } | |
| 325 | |
| 326 void MagnificationControllerImpl::EnsureShowPoint( | |
| 327 const gfx::Point& point, bool animation) { | |
| 328 EnsureShowPointWithScale(point, scale_, animation); | |
| 329 } | |
| 330 | |
| 331 //////////////////////////////////////////////////////////////////////////////// | |
| 332 // MagnificationControllerImpl: aura::EventFilter implementation | |
| 333 | |
| 334 bool MagnificationControllerImpl::PreHandleKeyEvent( | |
| 335 aura::Window* target, aura::KeyEvent* event) { | |
| 336 return false; | |
| 337 } | |
| 338 | |
| 339 bool MagnificationControllerImpl::PreHandleMouseEvent( | |
| 340 aura::Window* target, aura::MouseEvent* event) { | |
| 341 if (IsMagnified()) | |
| 342 OnMouseMove(); | |
| 343 return false; | |
| 344 } | |
| 345 | |
| 346 ui::TouchStatus MagnificationControllerImpl::PreHandleTouchEvent( | |
| 347 aura::Window* target, aura::TouchEvent* event) { | |
| 348 return ui::TOUCH_STATUS_UNKNOWN; | |
| 349 } | |
| 350 | |
| 351 ui::GestureStatus MagnificationControllerImpl::PreHandleGestureEvent( | |
| 352 aura::Window* target, | |
| 353 aura::GestureEvent* event) { | |
| 354 return ui::GESTURE_STATUS_UNKNOWN; | |
| 355 } | |
| 356 | |
| 357 //////////////////////////////////////////////////////////////////////////////// | |
| 358 // MagnificationController: | |
| 359 | |
| 360 // static | |
| 361 MagnificationController* MagnificationController::CreateInstance() { | |
| 362 return new MagnificationControllerImpl(); | |
| 363 } | |
| 364 | |
| 128 } // namespace internal | 365 } // namespace internal |
| 129 } // namespace ash | 366 } // namespace ash |
| OLD | NEW |