blob: e152ed9d115afa96c8afdfedd73411469c95a54f [file] [log] [blame]
[email protected]77f7c132012-11-15 06:52:541// 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
3// found in the LICENSE file.
4
5#include "ash/magnifier/partial_magnification_controller.h"
6
7#include "ash/shell.h"
8#include "ash/shell_window_ids.h"
[email protected]77f7c132012-11-15 06:52:549#include "ui/aura/window.h"
[email protected]7a60cd3a2014-03-20 20:54:5710#include "ui/aura/window_event_dispatcher.h"
[email protected]77f7c132012-11-15 06:52:5411#include "ui/aura/window_property.h"
[email protected]7a60cd3a2014-03-20 20:54:5712#include "ui/aura/window_tree_host.h"
[email protected]77f7c132012-11-15 06:52:5413#include "ui/gfx/screen.h"
14#include "ui/compositor/layer.h"
15#include "ui/views/layout/fill_layout.h"
16#include "ui/views/widget/widget.h"
17#include "ui/views/widget/widget_delegate.h"
[email protected]ee3ed10772014-03-11 22:02:0118#include "ui/wm/core/compound_event_filter.h"
[email protected]77f7c132012-11-15 06:52:5419
20namespace {
21
22const float kMinPartialMagnifiedScaleThreshold = 1.1f;
23
24// Number of pixels to make the border of the magnified area.
25const int kZoomInset = 16;
26
27// Width of the magnified area.
28const int kMagnifierWidth = 200;
29
30// Height of the magnified area.
31const int kMagnifierHeight = 200;
32
33// Name of the magnifier window.
34const char kPartialMagniferWindowName[] = "PartialMagnifierWindow";
35
36} // namespace
37
38namespace ash {
39
40PartialMagnificationController::PartialMagnificationController()
tfarinad7f1236f2015-01-16 16:21:2041 : is_enabled_(false),
[email protected]77f7c132012-11-15 06:52:5442 scale_(kNonPartialMagnifiedScale),
43 zoom_widget_(NULL) {
44 Shell::GetInstance()->AddPreTargetHandler(this);
45}
46
47PartialMagnificationController::~PartialMagnificationController() {
48 CloseMagnifierWindow();
49
50 Shell::GetInstance()->RemovePreTargetHandler(this);
51}
52
53void PartialMagnificationController::SetScale(float scale) {
54 if (!is_enabled_)
55 return;
56
57 scale_ = scale;
58
59 if (IsPartialMagnified()) {
60 CreateMagnifierWindow();
61 } else {
62 CloseMagnifierWindow();
63 }
64}
65
66void PartialMagnificationController::SetEnabled(bool enabled) {
67 if (enabled) {
68 is_enabled_ = enabled;
69 SetScale(kDefaultPartialMagnifiedScale);
70 } else {
71 SetScale(kNonPartialMagnifiedScale);
72 is_enabled_ = enabled;
73 }
74}
75
76////////////////////////////////////////////////////////////////////////////////
77// PartialMagnificationController: ui::EventHandler implementation
78
[email protected]d44efe02012-12-18 06:08:1879void PartialMagnificationController::OnMouseEvent(ui::MouseEvent* event) {
[email protected]77f7c132012-11-15 06:52:5480 if (IsPartialMagnified() && event->type() == ui::ET_MOUSE_MOVED) {
81 aura::Window* target = static_cast<aura::Window*>(event->target());
[email protected]bf9cdb362013-10-25 19:22:4582 aura::Window* current_root = target->GetRootWindow();
[email protected]77f7c132012-11-15 06:52:5483 // TODO(zork): Handle the case where the event is captured on a different
84 // display, such as when a menu is opened.
85 gfx::Rect root_bounds = current_root->bounds();
86
87 if (root_bounds.Contains(event->root_location())) {
88 SwitchTargetRootWindow(current_root);
89
90 OnMouseMove(event->root_location());
91 }
92 }
[email protected]77f7c132012-11-15 06:52:5493}
94
[email protected]77f7c132012-11-15 06:52:5495////////////////////////////////////////////////////////////////////////////////
96// PartialMagnificationController: aura::WindowObserver implementation
97
98void PartialMagnificationController::OnWindowDestroying(
99 aura::Window* window) {
100 CloseMagnifierWindow();
101
[email protected]c9390bd2013-11-08 20:33:13102 aura::Window* new_root_window = GetCurrentRootWindow();
[email protected]77f7c132012-11-15 06:52:54103 if (new_root_window != window)
104 SwitchTargetRootWindow(new_root_window);
105}
106
[email protected]846855202013-02-05 22:15:35107void PartialMagnificationController::OnWidgetDestroying(
[email protected]77f7c132012-11-15 06:52:54108 views::Widget* widget) {
109 DCHECK_EQ(widget, zoom_widget_);
110 RemoveZoomWidgetObservers();
111 zoom_widget_ = NULL;
112}
113
114void PartialMagnificationController::OnMouseMove(
115 const gfx::Point& location_in_root) {
116 gfx::Point origin(location_in_root);
117
118 origin.Offset(-kMagnifierWidth / 2, -kMagnifierHeight / 2);
119
120 if (zoom_widget_) {
121 zoom_widget_->SetBounds(gfx::Rect(origin.x(), origin.y(),
122 kMagnifierWidth, kMagnifierHeight));
123 }
124}
125
126bool PartialMagnificationController::IsPartialMagnified() const {
127 return scale_ >= kMinPartialMagnifiedScaleThreshold;
128}
129
130void PartialMagnificationController::CreateMagnifierWindow() {
131 if (zoom_widget_)
132 return;
133
[email protected]c9390bd2013-11-08 20:33:13134 aura::Window* root_window = GetCurrentRootWindow();
[email protected]77f7c132012-11-15 06:52:54135 if (!root_window)
136 return;
137
138 root_window->AddObserver(this);
139
[email protected]2374d1812014-03-04 03:42:27140 gfx::Point mouse(
141 root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot());
[email protected]77f7c132012-11-15 06:52:54142
143 zoom_widget_ = new views::Widget;
144 views::Widget::InitParams params(
145 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
[email protected]4f254232014-05-19 22:59:07146 params.activatable = views::Widget::InitParams::ACTIVATABLE_NO;
[email protected]77f7c132012-11-15 06:52:54147 params.accept_events = false;
[email protected]28fc4732013-06-27 12:15:09148 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
[email protected]77f7c132012-11-15 06:52:54149 params.parent = root_window;
150 zoom_widget_->Init(params);
151 zoom_widget_->SetBounds(gfx::Rect(mouse.x() - kMagnifierWidth / 2,
152 mouse.y() - kMagnifierHeight / 2,
153 kMagnifierWidth, kMagnifierHeight));
154 zoom_widget_->set_focus_on_creation(false);
155 zoom_widget_->Show();
156
157 aura::Window* window = zoom_widget_->GetNativeView();
158 window->SetName(kPartialMagniferWindowName);
159
160 zoom_widget_->GetNativeView()->layer()->SetBounds(
161 gfx::Rect(0, 0,
162 kMagnifierWidth,
163 kMagnifierHeight));
164 zoom_widget_->GetNativeView()->layer()->SetBackgroundZoom(
[email protected]77f7c132012-11-15 06:52:54165 scale_,
166 kZoomInset);
167
168 zoom_widget_->AddObserver(this);
169}
170
171void PartialMagnificationController::CloseMagnifierWindow() {
172 if (zoom_widget_) {
173 RemoveZoomWidgetObservers();
174 zoom_widget_->Close();
175 zoom_widget_ = NULL;
176 }
177}
178
179void PartialMagnificationController::RemoveZoomWidgetObservers() {
180 DCHECK(zoom_widget_);
181 zoom_widget_->RemoveObserver(this);
[email protected]bf9cdb362013-10-25 19:22:45182 aura::Window* root_window =
[email protected]77f7c132012-11-15 06:52:54183 zoom_widget_->GetNativeView()->GetRootWindow();
184 DCHECK(root_window);
185 root_window->RemoveObserver(this);
186}
187
188void PartialMagnificationController::SwitchTargetRootWindow(
[email protected]bf9cdb362013-10-25 19:22:45189 aura::Window* new_root_window) {
[email protected]77f7c132012-11-15 06:52:54190 if (zoom_widget_ &&
191 new_root_window == zoom_widget_->GetNativeView()->GetRootWindow())
192 return;
193
194 CloseMagnifierWindow();
195
196 // Recreate the magnifier window by updating the scale factor.
197 SetScale(GetScale());
198}
199
[email protected]c9390bd2013-11-08 20:33:13200aura::Window* PartialMagnificationController::GetCurrentRootWindow() {
201 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
202 for (aura::Window::Windows::const_iterator iter = root_windows.begin();
[email protected]77f7c132012-11-15 06:52:54203 iter != root_windows.end(); ++iter) {
[email protected]c9390bd2013-11-08 20:33:13204 aura::Window* root_window = *iter;
[email protected]77f7c132012-11-15 06:52:54205 if (root_window->ContainsPointInRoot(
[email protected]2374d1812014-03-04 03:42:27206 root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot()))
[email protected]77f7c132012-11-15 06:52:54207 return root_window;
208 }
209 return NULL;
210}
211
212} // namespace ash