Index: content/browser/web_contents/aura/constrained_windows_observer.cc |
diff --git a/content/browser/web_contents/aura/constrained_windows_observer.cc b/content/browser/web_contents/aura/constrained_windows_observer.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4de9c7859a1eb5d93a033a6a4a10f742c659d2dd |
--- /dev/null |
+++ b/content/browser/web_contents/aura/constrained_windows_observer.cc |
@@ -0,0 +1,197 @@ |
+// 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/constrained_windows_observer.h" |
+ |
+#include "content/browser/renderer_host/render_view_host_factory.h" |
+#include "content/browser/renderer_host/render_widget_host_view_aura.h" |
+#include "content/browser/renderer_host/render_widget_host_view_aura.h" |
+#include "content/browser/web_contents/web_contents_impl.h" |
+#include "content/browser/web_contents/web_contents_view_aura.h" |
+#include "content/public/browser/render_widget_host.h" |
+#include "ui/aura/window.h" |
+ |
+namespace content { |
+namespace { |
+ |
+RenderWidgetHostViewAura* ToRenderWidgetHostViewAura( |
+ RenderWidgetHostView* view) { |
+ if (!view || RenderViewHostFactory::has_factory()) |
+ return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests. |
+ RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>( |
+ view->GetRenderWidgetHost()->GetProcess()); |
+ if (process->IsGuest()) |
+ return NULL; |
+ return static_cast<RenderWidgetHostViewAura*>(view); |
+} |
+ |
+} // namespace |
+ |
+ConstrainedWindowsObserver::ConstrainedWindowsObserver( |
+ WebContentsViewAura* view) |
+ : view_(view), |
+ constrained_parent_(NULL) { |
+ view_->window_->AddObserver(this); |
+ if (view_->window_->GetRootWindow()) |
+ view_->window_->GetRootWindow()->AddObserver(this); |
+} |
+ |
+ConstrainedWindowsObserver::~ConstrainedWindowsObserver() { |
+ view_->window_->RemoveObserver(this); |
+ |
+ if (constrained_parent_) { |
+ constrained_parent_->RemoveObserver(this); |
+ const aura::Window::Windows& children = constrained_parent_->children(); |
+ for (size_t i = 0; i < children.size(); ++i) |
+ children[i]->RemoveObserver(this); |
+ } |
+ |
+ aura::Window* root_window = view_->window_->GetRootWindow(); |
+ if (root_window) { |
+ root_window->RemoveObserver(this); |
+ const aura::Window::Windows& root_children = root_window->children(); |
+ for (size_t i = 0; i < root_children.size(); ++i) |
+ root_children[i]->RemoveObserver(this); |
+ } |
+} |
+ |
+// There are two sets of windows that are of interest, those that are a child |
+// of a root window associated with |view_| and those that are a sibling of the |
+// window for |view_|. Since NPAPI is going to be deprecated in a year, this is |
+// ok for now. The test for this is PrintPreviewTest.WindowedNPAPIPluginHidden. |
+void ConstrainedWindowsObserver::OnWindowAdded(aura::Window* new_window) { |
+ if (new_window == view_->window_) |
+ return; |
+ |
+ if (new_window == constrained_parent_) |
+ return; // This happens if the parent moves to the root window. |
+ |
+ // Observe sibling windows of the WebContents, or children of the root |
+ // window. |
+ if (new_window->parent() == constrained_parent_ || |
+ new_window->parent() == view_->window_->GetRootWindow()) { |
+ new_window->AddObserver(this); |
+ UpdateConstrainedWindows(NULL); |
+ } |
+} |
+ |
+void ConstrainedWindowsObserver::OnWillRemoveWindow(aura::Window* window) { |
+ if (window == view_->window_) |
+ return; |
+ |
+ window->RemoveObserver(this); |
+ UpdateConstrainedWindows(window); |
+} |
+ |
+void ConstrainedWindowsObserver::OnWindowVisibilityChanged( |
+ aura::Window* window, |
+ bool visible) { |
+ if (window == view_->window_) |
+ return; |
+ |
+ if (window->parent() == constrained_parent_ || |
+ window->parent() == view_->window_->GetRootWindow()) { |
+ UpdateConstrainedWindows(NULL); |
+ } |
+} |
+ |
+void ConstrainedWindowsObserver::OnWindowParentChanged(aura::Window* window, |
+ aura::Window* parent) { |
+ if (window != view_->window_) |
+ return; |
+ if (constrained_parent_) |
+ constrained_parent_->RemoveObserver(this); |
+ |
+ if (constrained_parent_) { |
+ const aura::Window::Windows& children = constrained_parent_->children(); |
+ for (size_t i = 0; i < children.size(); ++i) |
+ children[i]->RemoveObserver(this); |
+ |
+ RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( |
+ view_->web_contents_->GetRenderWidgetHostView()); |
+ if (view) |
+ view->UpdateConstrainedWindowRects(std::vector<gfx::Rect>()); |
+ } |
+ |
+ // When we get parented to the root window, the code below will watch the |
+ // parent, aka root window. Since we already watch the root window on |
+ // Windows, unregister first so that the debug check doesn't fire. |
+ if (parent && parent == window->GetRootWindow()) |
+ parent->RemoveObserver(this); |
+ |
+ // We need to undo the above if we were parented to the root window and then |
+ // got parented to another window. At that point, the code before the ifdef |
+ // would have stopped watching the root window. |
+ if (window->GetRootWindow() && |
+ parent != window->GetRootWindow() && |
+ !window->GetRootWindow()->HasObserver(this)) { |
+ window->GetRootWindow()->AddObserver(this); |
+ } |
+ |
+ constrained_parent_ = parent; |
+ |
+ if (constrained_parent_) { |
+ constrained_parent_->AddObserver(this); |
+ if (constrained_parent_ != window->GetRootWindow()) { |
+ const aura::Window::Windows& children = constrained_parent_->children(); |
+ for (size_t i = 0; i < children.size(); ++i) { |
+ if (children[i] != view_->window_) |
+ children[i]->AddObserver(this); |
+ } |
+ } |
+ } |
+} |
+ |
+void ConstrainedWindowsObserver::OnWindowBoundsChanged( |
+ aura::Window* window, |
+ const gfx::Rect& old_bounds, |
+ const gfx::Rect& new_bounds) { |
+ if (window != constrained_parent_ && window != view_->window_) |
+ UpdateConstrainedWindows(NULL); |
+} |
+ |
+void ConstrainedWindowsObserver::OnWindowAddedToRootWindow( |
+ aura::Window* window) { |
+ if (window == view_->window_) { |
+ if (!window->GetRootWindow()->HasObserver(this)) |
+ window->GetRootWindow()->AddObserver(this); |
+ } |
+} |
+ |
+void ConstrainedWindowsObserver::OnWindowRemovingFromRootWindow( |
+ aura::Window* window) { |
+ if (window == view_->window_) { |
+ window->GetRootWindow()->RemoveObserver(this); |
+ |
+ const aura::Window::Windows& root_children = |
+ window->GetRootWindow()->children(); |
+ for (size_t i = 0; i < root_children.size(); ++i) { |
+ if (root_children[i] != view_->window_ && |
+ root_children[i] != constrained_parent_) |
+ root_children[i]->RemoveObserver(this); |
+ } |
+ } |
+} |
+ |
+void ConstrainedWindowsObserver::UpdateConstrainedWindows( |
+ aura::Window* exclude) { |
+ RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura( |
+ view_->web_contents_->GetRenderWidgetHostView()); |
+ if (!view) |
+ return; |
+ |
+ std::vector<gfx::Rect> constrained_windows; |
+ const aura::Window::Windows& children = constrained_parent_->children(); |
+ for (size_t i = 0; i < children.size(); ++i) { |
+ if (children[i] != view_->window_ && |
+ children[i] != exclude && |
+ children[i]->IsVisible()) { |
+ constrained_windows.push_back(children[i]->GetBoundsInRootWindow()); |
+ } |
+ } |
+ |
+ view->UpdateConstrainedWindowRects(constrained_windows); |
+} |
+ |
+} // namespace content |