blob: 1a2919c918bd9c160c9ebfbf83b6364d8d545023 [file] [log] [blame]
// Copyright 2018 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 "ui/aura_extra/window_position_in_root_monitor.h"
#include "ui/aura/window.h"
namespace aura_extra {
WindowPositionInRootMonitor::WindowPositionInRootMonitor(
aura::Window* window,
base::RepeatingClosure callback)
: callback_(std::move(callback)) {
DCHECK(window);
AddAncestors(window);
}
WindowPositionInRootMonitor::~WindowPositionInRootMonitor() {
for (aura::Window* ancestor : ancestors_)
ancestor->RemoveObserver(this);
}
void WindowPositionInRootMonitor::AddAncestors(aura::Window* window) {
while (window) {
ancestors_.push_back(window);
window->AddObserver(this);
window = window->parent();
}
}
void WindowPositionInRootMonitor::OnWindowDestroyed(aura::Window* window) {
// This should only be hit when window has no ancestors (because destroying
// a window implicitly removes children).
DCHECK_EQ(1u, ancestors_.size());
DCHECK_EQ(window, ancestors_[0]);
window->RemoveObserver(this);
ancestors_.clear();
}
void WindowPositionInRootMonitor::OnWindowParentChanged(aura::Window* window,
aura::Window* parent) {
// |window|'s parent is now |parent|. Iterate through the list backwards,
// removing windows until |window| is found. Then add all the new ancestors
// of |window|.
while (!ancestors_.empty()) {
if (ancestors_.back() == window) {
AddAncestors(parent);
// When adding to a root, notify the callback.
if (window->GetRootWindow())
callback_.Run();
return;
}
ancestors_.back()->RemoveObserver(this);
ancestors_.pop_back();
}
NOTREACHED();
}
void WindowPositionInRootMonitor::OnWindowBoundsChanged(
aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) {
if (old_bounds.origin() != new_bounds.origin() &&
ancestors_.back()->GetRootWindow()) {
callback_.Run();
}
}
} // namespace aura_extra