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..5334232c3643e01f29dd4b09af4ab3bd32286a07 |
--- /dev/null |
+++ b/content/browser/web_contents/aura/native_view_screen_bounds_observer.cc |
@@ -0,0 +1,134 @@ |
+// 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 "base/debug/trace_event.h" |
+#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( |
+ NativeViewScreenBoundsObserverDelegate* delegate, |
+ aura::Window* window) |
+ : delegate_(delegate), |
+ window_(window) { |
+ DCHECK(delegate); |
+ DCHECK(window); |
+ delegate_ = delegate; |
+ window_ = window; |
+ std::set<aura::Window*> windows_to_root = CollectAllWindowsToRoot(window_); |
+ AddToObserved(windows_to_root); |
+} |
+ |
+NativeViewScreenBoundsObserver::~NativeViewScreenBoundsObserver() { |
+ RemoveFromObserved(observed_); |
+ if (window_->GetDispatcher()) |
+ window_->GetDispatcher()->RemoveRootWindowObserver(this); |
+} |
+ |
+void NativeViewScreenBoundsObserver::OnWindowParentChanged( |
+ aura::Window* window, |
+ aura::Window* parent) { |
+ std::set<aura::Window*> windows_to_root = CollectAllWindowsToRoot(window_); |
+ std::set<aura::Window*> difference; |
+ std::set_difference( |
+ observed_.begin(), |
+ observed_.end(), |
+ windows_to_root.begin(), |
+ windows_to_root.end(), |
+ std::inserter(difference, difference.end())); |
+ RemoveFromObserved(difference); |
+ |
+ difference.clear(); |
+ std::set_difference( |
+ windows_to_root.begin(), |
+ windows_to_root.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 == window_ && window_->GetDispatcher()) |
+ window_->GetDispatcher()->AddRootWindowObserver(this); |
+} |
+ |
+void NativeViewScreenBoundsObserver::OnWindowRemovingFromRootWindow( |
+ aura::Window* window) { |
+ if (window == window_ && window_->GetDispatcher()) |
+ window_->GetDispatcher()->RemoveRootWindowObserver(this); |
+} |
+ |
+void NativeViewScreenBoundsObserver::OnRootWindowHostMoved( |
+ const aura::RootWindow* root, |
+ const gfx::Point& new_origin) { |
+ TRACE_EVENT1("ui", |
+ "WebContentsViewAura::WindowObserver::OnWindowTreeHostMoved", |
+ "new_origin", new_origin.ToString()); |
+ |
+ // This is for the desktop case (i.e. Aura desktop). |
+ delegate_->OnScreenPositionChanged(); |
+} |
+ |
+std::set<aura::Window*> NativeViewScreenBoundsObserver::CollectAllWindowsToRoot( |
+ aura::Window* window) { |
+ std::set<aura::Window*> ret_val; |
+ if (window) |
+ ret_val.insert(window); |
+ 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 |