Chromium Code Reviews| Index: content/browser/web_contents/aura/native_view_screen_bounds_observer.cc |
| diff --git a/content/browser/web_contents/aura/native_view_screen_bounds_observer.cc b/content/browser/web_contents/aura/native_view_screen_bounds_observer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..c1322fe2d68ab4bc80d8947088c1259197bc96a1 |
| --- /dev/null |
| +++ b/content/browser/web_contents/aura/native_view_screen_bounds_observer.cc |
| @@ -0,0 +1,135 @@ |
| +// Copyright (c) 2013 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 "content/browser/web_contents/aura/native_view_screen_bounds_observer.h" |
| + |
| +#include <algorithm> |
| + |
| +#include "content/browser/web_contents/web_contents_view_aura.h" |
| +#include "ui/aura/test/aura_test_base.h" |
| +#include "ui/aura/window.h" |
| + |
| + |
| +namespace content { |
| + |
| +NativeViewScreenBoundsObserver::NativeViewScreenBoundsObserver() |
| + : delegate_(NULL) { |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::Init( |
| + NativeViewScreenBoundsObserverDelegate* delegate) { |
| + DCHECK(delegate); |
| + delegate_ = delegate; |
| + delegate_->AddDelegateWindowObserver(this); |
| + std::set<aura::Window*> ancestors = GenerateAncestors( |
| + delegate_->GetDelegateWindow()); |
| + if (delegate_->GetDelegateWindow()) |
| + ancestors.insert(delegate_->GetDelegateWindow()); |
| + AddToObserved(ancestors); |
| +} |
| + |
| + |
| +NativeViewScreenBoundsObserver::~NativeViewScreenBoundsObserver() { |
| + RemoveFromObserved(observed_); |
| + delegate_->RemoveRootWindowObserver(this); |
| + delegate_->RemoveDelegateWindowObserver(this); |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::OnWindowParentChanged( |
| + aura::Window* window, |
| + aura::Window* parent) { |
| + std::set<aura::Window*> ancestors = GenerateAncestors( |
| + delegate_->GetDelegateWindow()); |
| + if (delegate_->GetDelegateWindow()) |
| + ancestors.insert(delegate_->GetDelegateWindow()); |
| + std::set<aura::Window*> difference; |
| + std::set_difference( |
| + observed_.begin(), |
| + observed_.end(), |
| + ancestors.begin(), |
| + ancestors.end(), |
| + std::inserter(difference, difference.end())); |
| + RemoveFromObserved(difference); |
| + |
| + difference.clear(); |
| + std::set_difference( |
| + ancestors.begin(), |
| + ancestors.end(), |
| + observed_.begin(), |
| + observed_.end(), |
| + std::inserter(difference, difference.end())); |
| + AddToObserved(difference); |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::OnWindowBoundsChanged( |
| + aura::Window* window, |
| + const gfx::Rect& old_bounds, |
| + const gfx::Rect& new_bounds) { |
| + if (old_bounds.size() == new_bounds.size()) { |
| + delegate_->OnScreenPositionChanged(); |
| + } else { |
| + delegate_->OnScreenBoundsChanged(); |
| + } |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::OnWindowAddedToRootWindow( |
| + aura::Window* window) { |
| + if (window == delegate_->GetDelegateWindow()) |
| + delegate_->AddRootWindowObserver(this); |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::OnWindowRemovingFromRootWindow( |
| + aura::Window* window) { |
| + if (window == delegate_->GetDelegateWindow()) |
| + delegate_->RemoveRootWindowObserver(this); |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::OnRootWindowHostMoved( |
| + const aura::RootWindow* root, |
| + const gfx::Point& new_origin) { |
| + // This is for the desktop case (i.e. Aura desktop). |
| + delegate_->OnScreenPositionChanged(); |
| +} |
| + |
| +std::set<aura::Window*> NativeViewScreenBoundsObserver::GenerateAncestors( |
|
sadrul
2013/11/08 02:16:26
Call this CollectAllWindowsToRoot (or something li
rharrison
2013/11/12 22:16:29
Done.
|
| + aura::Window* window) { |
| + std::set<aura::Window*> ret_val; |
| + while (window && window->parent()) { |
| + ret_val.insert(window->parent()); |
| + window = window->parent(); |
| + } |
| + return ret_val; |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::AddToObserved( |
| + const std::set<aura::Window*>& windows) { |
| + for (std::set<aura::Window*>::iterator iter = windows.begin(); |
| + iter != windows.end(); |
| + ++iter) { |
| + if (observed_.end() == observed_.find(*iter)) { |
| + (*iter)->AddObserver(this); |
| + observed_.insert(*iter); |
| + } |
| + } |
| +} |
| + |
| +void NativeViewScreenBoundsObserver::RemoveFromObserved( |
| + const std::set<aura::Window*>& windows) { |
| + // Since windows can possibly be |observer_| we cannot blindly iterate and |
| + // delete, since const & means that |windows| is a reference to |
| + // |observer_|. Thus if we erase an entry from |observed_| it may be erased |
| + // from |windows| which we are iterating. |
| + for (std::set<aura::Window*>::iterator iter = windows.begin(); |
| + iter != windows.end();) { |
| + std::set<aura::Window*>::iterator next = iter; |
| + next++; |
| + if (observed_.end() != observed_.find(*iter)) { |
| + (*iter)->RemoveObserver(this); |
| + observed_.erase(*iter); |
| + } |
| + iter = next; |
| + } |
| +} |
| + |
| +} // namespace content |