Index: ash/magnifier/magnification_controller.cc |
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc |
index 487aa7a3221d9c4fd82fd95b4b09b715ee89f904..8a1a4e99fba977674969320d39e5855cf800f9c4 100644 |
--- a/ash/magnifier/magnification_controller.cc |
+++ b/ash/magnifier/magnification_controller.cc |
@@ -4,6 +4,7 @@ |
#include "ash/magnifier/magnification_controller.h" |
+#include "ash/display/display_controller.h" |
#include "ash/shell.h" |
#include "ash/shell_delegate.h" |
#include "ash/system/tray/system_tray_delegate.h" |
@@ -37,6 +38,16 @@ const float kScrollScaleChangeFactor = 0.05f; |
// |kPanningMergin| from the edge, the view-port moves. |
const int kPanningMergin = 100; |
+bool IsRootWindowValid(aura::RootWindow* root_window) { |
+ if (!root_window) |
+ return false; |
+ |
+ std::vector<aura::RootWindow*> root_windows = |
+ ash::Shell::GetInstance()->display_controller()->GetAllRootWindows(); |
+ return std::find(root_windows.begin(), root_windows.end(), root_window) != |
+ root_windows.end(); |
+} |
+ |
} // namespace |
namespace ash { |
@@ -46,7 +57,8 @@ namespace ash { |
class MagnificationControllerImpl : virtual public MagnificationController, |
public ui::EventHandler, |
- public ui::ImplicitAnimationObserver { |
+ public ui::ImplicitAnimationObserver, |
+ public aura::WindowObserver { |
public: |
MagnificationControllerImpl(); |
virtual ~MagnificationControllerImpl(); |
@@ -70,6 +82,9 @@ class MagnificationControllerImpl : virtual public MagnificationController, |
// ui::ImplicitAnimationObserver overrides: |
virtual void OnImplicitAnimationsCompleted() OVERRIDE; |
+ // aura::WindowObserver overrides: |
+ virtual void OnWindowDestroying(aura::Window* root_window) 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 |
@@ -122,6 +137,8 @@ class MagnificationControllerImpl : virtual public MagnificationController, |
virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; |
virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; |
+ // Target root window. This might be NULL when all root windows has been gone |
+ // at shutdown. |
oshima
2013/02/26 18:57:38
can't you destroy this object before all root wind
|
aura::RootWindow* root_window_; |
// True if the magnified window is currently animating a change. Otherwise, |
@@ -158,16 +175,23 @@ MagnificationControllerImpl::MagnificationControllerImpl() |
scale_(kNonMagnifiedScale) { |
Shell::GetInstance()->AddPreTargetHandler(this); |
- if (root_window_) |
+ if (root_window_) { |
+ root_window_->AddObserver(this); |
point_of_interest_ = root_window_->bounds().CenterPoint(); |
+ } |
} |
MagnificationControllerImpl::~MagnificationControllerImpl() { |
+ if (root_window_) |
+ root_window_->RemoveObserver(this); |
+ |
Shell::GetInstance()->RemovePreTargetHandler(this); |
} |
void MagnificationControllerImpl::RedrawKeepingMousePosition( |
float scale, bool animate) { |
+ CHECK(root_window_); // |root_window_| should be checked at the caller. |
+ |
gfx::Point mouse_in_root = point_of_interest_; |
// mouse_in_root is invalid value when the cursor is hidden. |
@@ -187,6 +211,8 @@ void MagnificationControllerImpl::RedrawKeepingMousePosition( |
bool MagnificationControllerImpl::Redraw(const gfx::PointF& position, |
float scale, |
bool animate) { |
+ CHECK(root_window_); // |root_window_| should be checked at the caller. |
+ |
const gfx::PointF position_in_dip = |
ui::ConvertPointToDIP(root_window_->layer(), position); |
return RedrawDIP(position_in_dip, scale, animate); |
@@ -195,6 +221,8 @@ bool MagnificationControllerImpl::Redraw(const gfx::PointF& position, |
bool MagnificationControllerImpl::RedrawDIP(const gfx::PointF& position_in_dip, |
float scale, |
bool animate) { |
+ CHECK(root_window_); // |root_window_| should be checked at the caller. |
+ |
float x = position_in_dip.x(); |
float y = position_in_dip.y(); |
@@ -253,6 +281,8 @@ void MagnificationControllerImpl::EnsureRectIsVisibleWithScale( |
const gfx::Rect& target_rect, |
float scale, |
bool animate) { |
+ CHECK(root_window_); // |root_window_| should be checked at the caller. |
+ |
const gfx::Rect target_rect_in_dip = |
ui::ConvertRectToDIP(root_window_->layer(), target_rect); |
EnsureRectIsVisibleDIP(target_rect_in_dip, scale, animate); |
@@ -299,6 +329,8 @@ void MagnificationControllerImpl::EnsurePointIsVisibleWithScale( |
} |
void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) { |
+ CHECK(root_window_); // |root_window_| should be checked at the caller. |
+ |
gfx::Point mouse(location); |
int x = origin_.x(); |
@@ -353,6 +385,8 @@ void MagnificationControllerImpl::OnMouseMove(const gfx::Point& location) { |
void MagnificationControllerImpl::AfterAnimationMoveCursorTo( |
const gfx::Point& location) { |
+ CHECK(root_window_); // |root_window_| should be checked at the caller. |
+ |
aura::client::CursorClient* cursor_client = |
aura::client::GetCursorClient(root_window_); |
if (cursor_client) { |
@@ -416,23 +450,49 @@ void MagnificationControllerImpl::OnImplicitAnimationsCompleted() { |
is_on_animation_ = false; |
} |
+void MagnificationControllerImpl::OnWindowDestroying( |
+ aura::Window* root_window) { |
+ if (root_window == root_window_) { |
+ aura::RootWindow* active_root_window = Shell::GetActiveRootWindow(); |
+ // The destroyed root window must not be active. |
+ CHECK_NE(active_root_window, root_window); |
+ |
+ if (active_root_window) { |
+ SwitchTargetRootWindow(active_root_window); |
+ point_of_interest_ = active_root_window->bounds().CenterPoint(); |
+ } else { |
+ // No need to call |root_window_.removeObserver(this)| because the root |
+ // window is being destroyed. |
+ |
+ root_window_ = NULL; |
+ } |
+ } |
+} |
+ |
void MagnificationControllerImpl::SwitchTargetRootWindow( |
aura::RootWindow* new_root_window) { |
if (new_root_window == root_window_) |
return; |
+ // Stores the previous scale. |
float scale = GetScale(); |
- RedrawKeepingMousePosition(1.0f, true); |
+ // Unmagnify the previous root window if it exists. |
+ if (IsRootWindowValid(root_window_)) { |
+ root_window_->RemoveObserver(this); |
+ RedrawKeepingMousePosition(1.0f, true); |
+ } |
+ |
root_window_ = new_root_window; |
RedrawKeepingMousePosition(scale, true); |
+ root_window_->AddObserver(this); |
} |
//////////////////////////////////////////////////////////////////////////////// |
// MagnificationControllerImpl: MagnificationController implementation |
void MagnificationControllerImpl::SetScale(float scale, bool animate) { |
- if (!is_enabled_) |
+ if (!is_enabled_ || root_window_ == NULL) |
return; |
ValidateScale(&scale); |
@@ -441,7 +501,7 @@ void MagnificationControllerImpl::SetScale(float scale, bool animate) { |
} |
void MagnificationControllerImpl::MoveWindow(int x, int y, bool animate) { |
- if (!is_enabled_) |
+ if (!is_enabled_ || root_window_ == NULL) |
return; |
Redraw(gfx::Point(x, y), scale_, animate); |
@@ -449,7 +509,7 @@ void MagnificationControllerImpl::MoveWindow(int x, int y, bool animate) { |
void MagnificationControllerImpl::MoveWindow(const gfx::Point& point, |
bool animate) { |
- if (!is_enabled_) |
+ if (!is_enabled_ || root_window_ == NULL) |
return; |
Redraw(point, scale_, animate); |
@@ -458,7 +518,7 @@ void MagnificationControllerImpl::MoveWindow(const gfx::Point& point, |
void MagnificationControllerImpl::EnsureRectIsVisible( |
const gfx::Rect& target_rect, |
bool animate) { |
- if (!is_enabled_) |
+ if (!is_enabled_ || root_window_ == NULL) |
return; |
EnsureRectIsVisibleWithScale(target_rect, scale_, animate); |
@@ -467,13 +527,16 @@ void MagnificationControllerImpl::EnsureRectIsVisible( |
void MagnificationControllerImpl::EnsurePointIsVisible( |
const gfx::Point& point, |
bool animate) { |
- if (!is_enabled_) |
+ if (!is_enabled_ || root_window_ == NULL) |
return; |
EnsurePointIsVisibleWithScale(point, scale_, animate); |
} |
void MagnificationControllerImpl::SetEnabled(bool enabled) { |
+ if (root_window_ == NULL) |
+ return; |
+ |
if (enabled) { |
float scale = |
ash::Shell::GetInstance()->delegate()->GetSavedScreenMagnifierScale(); |
@@ -511,12 +574,13 @@ void MagnificationControllerImpl::OnMouseEvent(ui::MouseEvent* event) { |
gfx::Rect root_bounds = current_root->bounds(); |
if (root_bounds.Contains(event->root_location())) { |
+ // This must be before |SwitchTargetRootWindow()|. |
+ point_of_interest_ = event->root_location(); |
+ |
if (current_root != root_window_) |
SwitchTargetRootWindow(current_root); |
- point_of_interest_ = event->root_location(); |
- |
- if (IsMagnified() && event->type() == ui::ET_MOUSE_MOVED) |
+ if (IsMagnified() && root_window_ && event->type() == ui::ET_MOUSE_MOVED) |
OnMouseMove(event->root_location()); |
} |
} |
@@ -543,7 +607,7 @@ void MagnificationControllerImpl::OnScrollEvent(ui::ScrollEvent* event) { |
void MagnificationControllerImpl::OnTouchEvent(ui::TouchEvent* event) { |
aura::Window* target = static_cast<aura::Window*>(event->target()); |
aura::RootWindow* current_root = target->GetRootWindow(); |
- if (current_root == root_window_) { |
+ if (current_root && current_root == root_window_) { |
gfx::Rect root_bounds = current_root->bounds(); |
if (root_bounds.Contains(event->root_location())) |
point_of_interest_ = event->root_location(); |