Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Unified Diff: content/browser/web_contents/aura/constrained_windows_observer.cc

Issue 54623007: Make code path for bounds changes getting to renderer less brittle (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Experimenting with single observer design Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698