diff options
author | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-15 06:52:54 +0000 |
---|---|---|
committer | zork@chromium.org <zork@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-11-15 06:52:54 +0000 |
commit | 77f7c1339fef15cf6543a07c36a89ea0f09d7b85 (patch) | |
tree | 6ec067b98b4d7a1fea038bce89e6be48980df070 /ash/magnifier | |
parent | 01d0241cb075fe0b27455bfe7b33aa08bf1c4240 (diff) | |
download | chromium_src-77f7c1339fef15cf6543a07c36a89ea0f09d7b85.zip chromium_src-77f7c1339fef15cf6543a07c36a89ea0f09d7b85.tar.gz chromium_src-77f7c1339fef15cf6543a07c36a89ea0f09d7b85.tar.bz2 |
Add the partial screen magnifier to Chrome OS.
BUG=127075
TEST=Set settings->Advanced Settings -> Accessibility -> Screen magnifier to partial. Check that the area around the mouse cursor is magnified
Review URL: https://chromiumcodereview.appspot.com/10915140
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167878 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/magnifier')
-rw-r--r-- | ash/magnifier/magnification_controller.cc | 7 | ||||
-rw-r--r-- | ash/magnifier/magnification_controller.h | 4 | ||||
-rw-r--r-- | ash/magnifier/partial_magnification_controller.cc | 236 | ||||
-rw-r--r-- | ash/magnifier/partial_magnification_controller.h | 99 |
4 files changed, 342 insertions, 4 deletions
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc index d014cd4..d9c7db9 100644 --- a/ash/magnifier/magnification_controller.cc +++ b/ash/magnifier/magnification_controller.cc @@ -33,7 +33,6 @@ const float kScrollScaleChangeFactor = 0.05f; } // namespace namespace ash { -namespace internal { //////////////////////////////////////////////////////////////////////////////// // MagnificationControllerImpl: @@ -47,6 +46,7 @@ class MagnificationControllerImpl : virtual public MagnificationController, // MagnificationController overrides: virtual void SetEnabled(bool enabled) OVERRIDE; + virtual bool IsEnabled() const OVERRIDE; virtual void SetScale(float scale, bool animate) OVERRIDE; virtual float GetScale() const OVERRIDE { return scale_; } virtual void MoveWindow(int x, int y, bool animate) OVERRIDE; @@ -443,6 +443,10 @@ void MagnificationControllerImpl::SetEnabled(bool enabled) { } } +bool MagnificationControllerImpl::IsEnabled() const { + return is_enabled_; +} + //////////////////////////////////////////////////////////////////////////////// // MagnificationControllerImpl: aura::EventFilter implementation @@ -506,5 +510,4 @@ MagnificationController* MagnificationController::CreateInstance() { return new MagnificationControllerImpl(); } -} // namespace internal } // namespace ash diff --git a/ash/magnifier/magnification_controller.h b/ash/magnifier/magnification_controller.h index b274b4c..a110b93 100644 --- a/ash/magnifier/magnification_controller.h +++ b/ash/magnifier/magnification_controller.h @@ -16,7 +16,6 @@ class RootWindow; } namespace ash { -namespace internal { class MagnificationController { public: @@ -29,6 +28,8 @@ class MagnificationController { // Enables (or disables if |enabled| is false) screen magnifier feature. virtual void SetEnabled(bool enabled) = 0; + virtual bool IsEnabled() const = 0; + // Sets the magnification ratio. 1.0f means no magnification. virtual void SetScale(float scale, bool animate) = 0; // Returns the current magnification ratio. @@ -49,7 +50,6 @@ class MagnificationController { MagnificationController() {} }; -} // namespace internal } // namespace ash #endif // ASH_MAGNIFIER_MAGNIFICATION_CONTROLLER_H_ diff --git a/ash/magnifier/partial_magnification_controller.cc b/ash/magnifier/partial_magnification_controller.cc new file mode 100644 index 0000000..7b682a7 --- /dev/null +++ b/ash/magnifier/partial_magnification_controller.cc @@ -0,0 +1,236 @@ +// Copyright (c) 2012 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/magnifier/partial_magnification_controller.h" + +#include "ash/shell.h" +#include "ash/shell_window_ids.h" +#include "ui/aura/root_window.h" +#include "ui/views/corewm/compound_event_filter.h" +#include "ui/aura/window.h" +#include "ui/aura/window_property.h" +#include "ui/gfx/screen.h" +#include "ui/compositor/layer.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" + +namespace { + +const float kMinPartialMagnifiedScaleThreshold = 1.1f; + +// Number of pixels to make the border of the magnified area. +const int kZoomInset = 16; + +// Width of the magnified area. +const int kMagnifierWidth = 200; + +// Height of the magnified area. +const int kMagnifierHeight = 200; + +// Name of the magnifier window. +const char kPartialMagniferWindowName[] = "PartialMagnifierWindow"; + +} // namespace + +namespace ash { + +PartialMagnificationController::PartialMagnificationController() + : is_on_zooming_(false), + is_enabled_(false), + scale_(kNonPartialMagnifiedScale), + zoom_widget_(NULL) { + Shell::GetInstance()->AddPreTargetHandler(this); +} + +PartialMagnificationController::~PartialMagnificationController() { + CloseMagnifierWindow(); + + Shell::GetInstance()->RemovePreTargetHandler(this); +} + +void PartialMagnificationController::SetScale(float scale) { + if (!is_enabled_) + return; + + scale_ = scale; + + if (IsPartialMagnified()) { + CreateMagnifierWindow(); + } else { + CloseMagnifierWindow(); + } +} + +void PartialMagnificationController::SetEnabled(bool enabled) { + if (enabled) { + is_enabled_ = enabled; + SetScale(kDefaultPartialMagnifiedScale); + } else { + SetScale(kNonPartialMagnifiedScale); + is_enabled_ = enabled; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// PartialMagnificationController: ui::EventHandler implementation + +ui::EventResult PartialMagnificationController::OnKeyEvent( + ui::KeyEvent* event) { + return ui::ER_UNHANDLED; +} + +ui::EventResult PartialMagnificationController::OnMouseEvent( + ui::MouseEvent* event) { + if (IsPartialMagnified() && event->type() == ui::ET_MOUSE_MOVED) { + aura::Window* target = static_cast<aura::Window*>(event->target()); + aura::RootWindow* current_root = target->GetRootWindow(); + // TODO(zork): Handle the case where the event is captured on a different + // display, such as when a menu is opened. + gfx::Rect root_bounds = current_root->bounds(); + + if (root_bounds.Contains(event->root_location())) { + SwitchTargetRootWindow(current_root); + + OnMouseMove(event->root_location()); + } + } + + return ui::ER_UNHANDLED; +} + +ui::EventResult PartialMagnificationController::OnScrollEvent( + ui::ScrollEvent* event) { + return ui::ER_UNHANDLED; +} + +ui::EventResult PartialMagnificationController::OnTouchEvent( + ui::TouchEvent* event) { + return ui::ER_UNHANDLED; +} + +ui::EventResult PartialMagnificationController::OnGestureEvent( + ui::GestureEvent* event) { + return ui::ER_UNHANDLED; +} + +//////////////////////////////////////////////////////////////////////////////// +// PartialMagnificationController: aura::WindowObserver implementation + +void PartialMagnificationController::OnWindowDestroying( + aura::Window* window) { + CloseMagnifierWindow(); + + aura::RootWindow* new_root_window = GetCurrentRootWindow(); + if (new_root_window != window) + SwitchTargetRootWindow(new_root_window); +} + +void PartialMagnificationController::OnWidgetClosing( + views::Widget* widget) { + DCHECK_EQ(widget, zoom_widget_); + RemoveZoomWidgetObservers(); + zoom_widget_ = NULL; +} + +void PartialMagnificationController::OnMouseMove( + const gfx::Point& location_in_root) { + gfx::Point origin(location_in_root); + + origin.Offset(-kMagnifierWidth / 2, -kMagnifierHeight / 2); + + if (zoom_widget_) { + zoom_widget_->SetBounds(gfx::Rect(origin.x(), origin.y(), + kMagnifierWidth, kMagnifierHeight)); + } +} + +bool PartialMagnificationController::IsPartialMagnified() const { + return scale_ >= kMinPartialMagnifiedScaleThreshold; +} + +void PartialMagnificationController::CreateMagnifierWindow() { + if (zoom_widget_) + return; + + aura::RootWindow* root_window = GetCurrentRootWindow(); + if (!root_window) + return; + + root_window->AddObserver(this); + + gfx::Point mouse(root_window->GetLastMouseLocationInRoot()); + + zoom_widget_ = new views::Widget; + views::Widget::InitParams params( + views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); + params.can_activate = false; + params.accept_events = false; + params.transparent = true; + params.parent = root_window; + zoom_widget_->Init(params); + zoom_widget_->SetBounds(gfx::Rect(mouse.x() - kMagnifierWidth / 2, + mouse.y() - kMagnifierHeight / 2, + kMagnifierWidth, kMagnifierHeight)); + zoom_widget_->set_focus_on_creation(false); + zoom_widget_->Show(); + + aura::Window* window = zoom_widget_->GetNativeView(); + window->SetName(kPartialMagniferWindowName); + + zoom_widget_->GetNativeView()->layer()->SetBounds( + gfx::Rect(0, 0, + kMagnifierWidth, + kMagnifierHeight)); + zoom_widget_->GetNativeView()->layer()->SetBackgroundZoom( + (kMagnifierWidth - (kMagnifierWidth / scale_)) / 2, + (kMagnifierHeight - (kMagnifierHeight / scale_)) / 2, + scale_, + kZoomInset); + + zoom_widget_->AddObserver(this); +} + +void PartialMagnificationController::CloseMagnifierWindow() { + if (zoom_widget_) { + RemoveZoomWidgetObservers(); + zoom_widget_->Close(); + zoom_widget_ = NULL; + } +} + +void PartialMagnificationController::RemoveZoomWidgetObservers() { + DCHECK(zoom_widget_); + zoom_widget_->RemoveObserver(this); + aura::RootWindow* root_window = + zoom_widget_->GetNativeView()->GetRootWindow(); + DCHECK(root_window); + root_window->RemoveObserver(this); +} + +void PartialMagnificationController::SwitchTargetRootWindow( + aura::RootWindow* new_root_window) { + if (zoom_widget_ && + new_root_window == zoom_widget_->GetNativeView()->GetRootWindow()) + return; + + CloseMagnifierWindow(); + + // Recreate the magnifier window by updating the scale factor. + SetScale(GetScale()); +} + +aura::RootWindow* PartialMagnificationController::GetCurrentRootWindow() { + Shell::RootWindowList root_windows = Shell::GetAllRootWindows(); + for (Shell::RootWindowList::const_iterator iter = root_windows.begin(); + iter != root_windows.end(); ++iter) { + aura::RootWindow* root_window = *iter; + if (root_window->ContainsPointInRoot( + root_window->GetLastMouseLocationInRoot())) + return root_window; + } + return NULL; +} + +} // namespace ash diff --git a/ash/magnifier/partial_magnification_controller.h b/ash/magnifier/partial_magnification_controller.h new file mode 100644 index 0000000..7908d97 --- /dev/null +++ b/ash/magnifier/partial_magnification_controller.h @@ -0,0 +1,99 @@ +// Copyright (c) 2012 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_MAGNIFIER_PARTIAL_MAGNIFICATION_CONTROLLER_H_ +#define ASH_MAGNIFIER_PARTIAL_MAGNIFICATION_CONTROLLER_H_ + +#include "ui/aura/window_observer.h" +#include "ui/base/events/event_handler.h" +#include "ui/gfx/point.h" +#include "ui/views/widget/widget_observer.h" + +namespace aura { +class RootWindow; +} + +namespace ash { + +const float kDefaultPartialMagnifiedScale = 1.5f; +const float kNonPartialMagnifiedScale = 1.0f; + +// Controls the partial screen magnifier, which is a small area of the screen +// which is zoomed in. The zoomed area follows the mouse cursor when enabled. +class PartialMagnificationController + : public ui::EventHandler, + public aura::WindowObserver, + public views::WidgetObserver { + public: + PartialMagnificationController(); + virtual ~PartialMagnificationController(); + + // Enables (or disables if |enabled| is false) partial screen magnifier + // feature. + virtual void SetEnabled(bool enabled); + + bool is_enabled() const { return is_enabled_; } + + // Sets the magnification ratio. 1.0f means no magnification. + void SetScale(float scale); + + // Returns the current magnification ratio. + float GetScale() const { return scale_; } + + private: + void OnMouseMove(const gfx::Point& location_in_root); + + // Switch PartialMagnified RootWindow to |new_root_window|. This does + // following: + // - Remove the magnifier from the current root window. + // - Create a magnifier in the new root_window |new_root_window|. + // - Switch the target window from current window to |new_root_window|. + void SwitchTargetRootWindow(aura::RootWindow* new_root_window); + + // Returns the root window that contains the mouse cursor. + aura::RootWindow* GetCurrentRootWindow(); + + // Return true if the magnification scale > kMinPartialMagnifiedScaleThreshold + bool IsPartialMagnified() const; + + // Create the magnifier window. + void CreateMagnifierWindow(); + + // Cleans up the window if needed. + void CloseMagnifierWindow(); + + // Removes this as an observer of the zoom widget and the root window. + void RemoveZoomWidgetObservers(); + + // ui::EventHandler overrides: + virtual ui::EventResult OnKeyEvent(ui::KeyEvent* event) OVERRIDE; + virtual ui::EventResult OnMouseEvent(ui::MouseEvent* event) OVERRIDE; + virtual ui::EventResult OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; + virtual ui::EventResult OnTouchEvent(ui::TouchEvent* event) OVERRIDE; + virtual ui::EventResult OnGestureEvent(ui::GestureEvent* event) OVERRIDE; + + // Overridden from WindowObserver: + virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; + + // Overridden from WidgetObserver: + virtual void OnWidgetClosing(views::Widget* widget) OVERRIDE; + + // True if the magnified window is in motion of zooming or un-zooming effect. + // Otherwise, false. + bool is_on_zooming_; + + bool is_enabled_; + + // Current scale, origin (left-top) position of the magnification window. + float scale_; + gfx::Point origin_; + + views::Widget* zoom_widget_; + + DISALLOW_COPY_AND_ASSIGN(PartialMagnificationController); +}; + +} // namespace ash + +#endif // ASH_MAGNIFIER_PARTIAL_MAGNIFICATION_CONTROLLER_H_ |