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 |