Commit ed6a0274 authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

chromeos: makes window-service notify of screen bounds

Screen bounds are sent at embed points to the embedded client.

BUG=none
TEST=covered by tests

Change-Id: I85a3d214708d8b28d288496edd2ec4be561ef533
Reviewed-on: https://chromium-review.googlesource.com/c/1357644
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613149}
parent 1de33dea
...@@ -84,6 +84,7 @@ component("lib") { ...@@ -84,6 +84,7 @@ component("lib") {
"//services/ws/input_devices", "//services/ws/input_devices",
"//services/ws/public/mojom", "//services/ws/public/mojom",
"//ui/aura", "//ui/aura",
"//ui/aura_extra:window_position_in_root_monitor",
"//ui/base/mojo:lib", "//ui/base/mojo:lib",
"//ui/wm", "//ui/wm",
"//ui/wm/public", "//ui/wm/public",
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "services/ws/client_root.h" #include "services/ws/client_root.h"
#include "base/bind.h"
#include "base/callback_forward.h"
#include "components/viz/common/surfaces/surface_info.h" #include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/host/host_frame_sink_manager.h" #include "components/viz/host/host_frame_sink_manager.h"
#include "services/ws/client_change.h" #include "services/ws/client_change.h"
...@@ -17,6 +19,7 @@ ...@@ -17,6 +19,7 @@
#include "ui/aura/mus/property_converter.h" #include "ui/aura/mus/property_converter.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h" #include "ui/aura/window_tree_host.h"
#include "ui/aura_extra/window_position_in_root_monitor.h"
#include "ui/compositor/compositor.h" #include "ui/compositor/compositor.h"
#include "ui/compositor/dip_util.h" #include "ui/compositor/dip_util.h"
#include "ui/compositor/property_change_reason.h" #include "ui/compositor/property_change_reason.h"
...@@ -35,6 +38,12 @@ ClientRoot::ClientRoot(WindowTree* window_tree, ...@@ -35,6 +38,12 @@ ClientRoot::ClientRoot(WindowTree* window_tree,
window_, is_top_level, gfx::Insets()); window_, is_top_level, gfx::Insets());
// Ensure there is a valid LocalSurfaceId (if necessary). // Ensure there is a valid LocalSurfaceId (if necessary).
UpdateLocalSurfaceIdIfNecessary(); UpdateLocalSurfaceIdIfNecessary();
if (!is_top_level) {
root_position_monitor_ =
std::make_unique<aura_extra::WindowPositionInRootMonitor>(
window, base::BindRepeating(&ClientRoot::OnPositionInRootChanged,
base::Unretained(this)));
}
} }
ClientRoot::~ClientRoot() { ClientRoot::~ClientRoot() {
...@@ -187,12 +196,23 @@ void ClientRoot::HandleBoundsOrScaleFactorChange(const gfx::Rect& old_bounds) { ...@@ -187,12 +196,23 @@ void ClientRoot::HandleBoundsOrScaleFactorChange(const gfx::Rect& old_bounds) {
client_surface_embedder_->UpdateSizeAndGutters(); client_surface_embedder_->UpdateSizeAndGutters();
// See comments in WindowTree::SetWindowBoundsImpl() for details on // See comments in WindowTree::SetWindowBoundsImpl() for details on
// why this always notifies the client. // why this always notifies the client.
NotifyClientOfNewBounds(old_bounds);
}
void ClientRoot::NotifyClientOfNewBounds(const gfx::Rect& old_bounds) {
last_bounds_ = window_->GetBoundsInScreen();
window_tree_->window_tree_client_->OnWindowBoundsChanged( window_tree_->window_tree_client_->OnWindowBoundsChanged(
window_tree_->TransportIdForWindow(window_), old_bounds, window_tree_->TransportIdForWindow(window_), old_bounds, last_bounds_,
is_top_level_ ? window_->GetBoundsInScreen() : window_->bounds(),
ServerWindow::GetMayBeNull(window_)->local_surface_id()); ServerWindow::GetMayBeNull(window_)->local_surface_id());
} }
void ClientRoot::OnPositionInRootChanged() {
DCHECK(!is_top_level_);
gfx::Rect bounds_in_screen = window_->GetBoundsInScreen();
if (bounds_in_screen.origin() != last_bounds_.origin())
NotifyClientOfNewBounds(last_bounds_);
}
void ClientRoot::OnWindowPropertyChanged(aura::Window* window, void ClientRoot::OnWindowPropertyChanged(aura::Window* window,
const void* key, const void* key,
intptr_t old) { intptr_t old) {
......
...@@ -23,6 +23,10 @@ class ClientSurfaceEmbedder; ...@@ -23,6 +23,10 @@ class ClientSurfaceEmbedder;
class Window; class Window;
} // namespace aura } // namespace aura
namespace aura_extra {
class WindowPositionInRootMonitor;
}
namespace gfx { namespace gfx {
class Insets; class Insets;
} }
...@@ -93,6 +97,12 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ClientRoot ...@@ -93,6 +97,12 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ClientRoot
// previous bounds, which may not have changed if the scale factor changes. // previous bounds, which may not have changed if the scale factor changes.
void HandleBoundsOrScaleFactorChange(const gfx::Rect& old_bounds); void HandleBoundsOrScaleFactorChange(const gfx::Rect& old_bounds);
void NotifyClientOfNewBounds(const gfx::Rect& old_bounds);
// Callback when the position of |window_|, relative to the root, changes.
// This is *only* called for non-top-levels.
void OnPositionInRootChanged();
// aura::WindowObserver: // aura::WindowObserver:
void OnWindowPropertyChanged(aura::Window* window, void OnWindowPropertyChanged(aura::Window* window,
const void* key, const void* key,
...@@ -136,6 +146,13 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ClientRoot ...@@ -136,6 +146,13 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) ClientRoot
// supplied. // supplied.
std::unique_ptr<viz::SurfaceInfo> fallback_surface_info_; std::unique_ptr<viz::SurfaceInfo> fallback_surface_info_;
// Used for non-top-levels to watch for changes in screen coordinates.
std::unique_ptr<aura_extra::WindowPositionInRootMonitor>
root_position_monitor_;
// Last bounds sent to the client.
gfx::Rect last_bounds_;
DISALLOW_COPY_AND_ASSIGN(ClientRoot); DISALLOW_COPY_AND_ASSIGN(ClientRoot);
}; };
......
...@@ -85,5 +85,40 @@ TEST(ClientRoot, CascadingPropertyChange) { ...@@ -85,5 +85,40 @@ TEST(ClientRoot, CascadingPropertyChange) {
EXPECT_TRUE(top_level->GetProperty(aura::client::kAlwaysOnTopKey)); EXPECT_TRUE(top_level->GetProperty(aura::client::kAlwaysOnTopKey));
} }
// Verifies embedded clients are notified of changes in screen bounds.
TEST(ClientRoot, EmbedBoundsInScreen) {
WindowServiceTestSetup setup;
aura::Window* embed_window = setup.window_tree_test_helper()->NewWindow();
embed_window->SetBounds(gfx::Rect(1, 2, 3, 4));
aura::Window* window = setup.window_tree_test_helper()->NewWindow();
aura::Window* top_level =
setup.window_tree_test_helper()->NewTopLevelWindow();
std::unique_ptr<EmbeddingHelper> embedding_helper =
setup.CreateEmbedding(embed_window);
embedding_helper->window_tree_client.set_track_root_bounds_changes(true);
ASSERT_TRUE(embedding_helper);
embedding_helper->changes()->clear();
window->AddChild(embed_window);
EXPECT_TRUE(embedding_helper->changes()->empty());
top_level->AddChild(window);
std::vector<Change>* embedding_changes = embedding_helper->changes();
auto iter =
FirstChangeOfType(*embedding_changes, CHANGE_TYPE_NODE_BOUNDS_CHANGED);
ASSERT_NE(iter, embedding_changes->end());
EXPECT_EQ(gfx::Rect(1, 2, 3, 4), iter->bounds2);
embedding_changes->clear();
window->SetBounds(gfx::Rect(11, 12, 100, 100));
iter = FirstChangeOfType(*embedding_changes, CHANGE_TYPE_NODE_BOUNDS_CHANGED);
ASSERT_NE(iter, embedding_changes->end());
EXPECT_EQ(gfx::Rect(12, 14, 3, 4), iter->bounds2);
embedding_changes->clear();
top_level->SetBounds(gfx::Rect(100, 50, 100, 100));
iter = FirstChangeOfType(*embedding_changes, CHANGE_TYPE_NODE_BOUNDS_CHANGED);
ASSERT_NE(iter, embedding_changes->end());
EXPECT_EQ(gfx::Rect(112, 64, 3, 4), iter->bounds2);
}
} // namespace } // namespace
} // namespace ws } // namespace ws
...@@ -294,6 +294,14 @@ bool ContainsChange(const std::vector<Change>& changes, ...@@ -294,6 +294,14 @@ bool ContainsChange(const std::vector<Change>& changes,
return false; return false;
} }
std::vector<Change>::const_iterator FirstChangeOfType(
const std::vector<Change>& changes,
ChangeType type) {
return std::find_if(
changes.begin(), changes.end(),
[&type](const Change& change) { return type == change.type; });
}
Change::Change() = default; Change::Change() = default;
Change::Change(const Change& other) = default; Change::Change(const Change& other) = default;
......
...@@ -151,6 +151,10 @@ void WindowDatasToTestWindows(const std::vector<mojom::WindowDataPtr>& data, ...@@ -151,6 +151,10 @@ void WindowDatasToTestWindows(const std::vector<mojom::WindowDataPtr>& data,
bool ContainsChange(const std::vector<Change>& changes, bool ContainsChange(const std::vector<Change>& changes,
const std::string& change_description); const std::string& change_description);
std::vector<Change>::const_iterator FirstChangeOfType(
const std::vector<Change>& changes,
ChangeType type);
// TestChangeTracker is used to record WindowTreeClient functions. It notifies // TestChangeTracker is used to record WindowTreeClient functions. It notifies
// a delegate any time a change is added. // a delegate any time a change is added.
class TestChangeTracker { class TestChangeTracker {
......
...@@ -379,7 +379,6 @@ executable("demo") { ...@@ -379,7 +379,6 @@ executable("demo") {
test("aura_unittests") { test("aura_unittests") {
sources = [ sources = [
"../compositor_extra/shadow_unittest.cc", "../compositor_extra/shadow_unittest.cc",
"//ui/aura_extra/window_occlusion_impl_unittest_win.cc",
"gestures/gesture_recognizer_unittest.cc", "gestures/gesture_recognizer_unittest.cc",
"mouse_location_manager_unittest.cc", "mouse_location_manager_unittest.cc",
"mus/drag_drop_controller_mus_unittest.cc", "mus/drag_drop_controller_mus_unittest.cc",
...@@ -417,6 +416,7 @@ test("aura_unittests") { ...@@ -417,6 +416,7 @@ test("aura_unittests") {
"//skia", "//skia",
"//testing/gtest", "//testing/gtest",
"//ui/aura_extra", "//ui/aura_extra",
"//ui/aura_extra:tests",
"//ui/base:test_support", "//ui/base:test_support",
"//ui/compositor:test_support", "//ui/compositor:test_support",
"//ui/compositor_extra", "//ui/compositor_extra",
......
...@@ -43,3 +43,36 @@ source_set("vector_resource") { ...@@ -43,3 +43,36 @@ source_set("vector_resource") {
"//ui/display", "//ui/display",
] ]
} }
source_set("window_position_in_root_monitor") {
sources = [
"window_position_in_root_monitor.cc",
"window_position_in_root_monitor.h",
]
deps = [
"//base",
"//ui/aura",
]
}
source_set("tests") {
testonly = true
sources = [
"window_occlusion_impl_unittest_win.cc",
"window_position_in_root_monitor_unittest.cc",
]
deps = [
":aura_extra",
":window_position_in_root_monitor",
"//base",
"//base/test:test_support",
"//testing/gtest",
"//ui/aura",
"//ui/aura:test_support",
"//ui/gfx/geometry",
"//ui/platform_window",
]
}
// 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
// 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.
#ifndef UI_AURA_EXTRA_WINDOW_POSITION_IN_ROOT_MONITOR_H_
#define UI_AURA_EXTRA_WINDOW_POSITION_IN_ROOT_MONITOR_H_
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "ui/aura/window_observer.h"
namespace aura_extra {
// WindowPositionInRootMonitor notifies a callback any time the position of a
// window, relative to the root, changes. Changes are only sent when attached
// to a valid root.
class WindowPositionInRootMonitor : public aura::WindowObserver {
public:
WindowPositionInRootMonitor(aura::Window* window,
base::RepeatingClosure callback);
~WindowPositionInRootMonitor() override;
private:
// Adds |window| and all its ancestors to |ancestors_|.
void AddAncestors(aura::Window* window);
// aura::WindowObserver:
void OnWindowDestroyed(aura::Window* window) override;
void OnWindowParentChanged(aura::Window* window,
aura::Window* parent) override;
void OnWindowBoundsChanged(aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) override;
base::RepeatingClosure callback_;
// The windows being watched. This contains the window supplied to the
// constructor and all it's ancestors. This is empty if the window is deleted.
std::vector<aura::Window*> ancestors_;
DISALLOW_COPY_AND_ASSIGN(WindowPositionInRootMonitor);
};
} // namespace aura_extra
#endif // UI_AURA_EXTRA_WINDOW_POSITION_IN_ROOT_MONITOR_H_
// 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 "base/bind.h"
#include "base/callback.h"
#include "base/test/bind_test_util.h"
#include "ui/aura/test/aura_test_base.h"
#include "ui/aura/test/test_windows.h"
#include "ui/aura/window.h"
#include "ui/gfx/geometry/rect.h"
namespace aura_extra {
using WindowPositionInRootMonitorTest = aura::test::AuraTestBase;
TEST_F(WindowPositionInRootMonitorTest, Basic) {
// Changing the position while not in a root should not notify the callback.
std::unique_ptr<aura::Window> w1(
aura::test::CreateTestWindowWithId(1, nullptr));
w1->set_owned_by_parent(false);
bool monitor_notified = false;
WindowPositionInRootMonitor monitor(
w1.get(), base::BindLambdaForTesting([&] { monitor_notified = true; }));
w1->SetBounds(gfx::Rect(1, 2, 3, 4));
EXPECT_FALSE(monitor_notified);
w1->SetBounds(gfx::Rect(11, 2, 3, 4));
EXPECT_FALSE(monitor_notified);
// Adding an ancestor that is not part of the root should not notify the
// callback.
std::unique_ptr<aura::Window> w2(
aura::test::CreateTestWindowWithId(2, nullptr));
w2->set_owned_by_parent(false);
w2->AddChild(w1.get());
EXPECT_FALSE(monitor_notified);
w2->SetBounds(gfx::Rect(21, 10, 20, 20));
EXPECT_FALSE(monitor_notified);
// Adding to the root should immediately notify.
root_window()->AddChild(w2.get());
EXPECT_TRUE(monitor_notified);
monitor_notified = false;
// Changing |w2|'s bounds show notify as |w2| is the parent and |w1| is in a
// root.
w2->SetBounds(gfx::Rect(22, 10, 20, 20));
EXPECT_TRUE(monitor_notified);
monitor_notified = false;
// Removing an ancestor, and changing the ancestors bounds should not notify.
root_window()->RemoveChild(w2.get());
EXPECT_FALSE(monitor_notified);
w2->SetBounds(gfx::Rect(21, 22, 23, 24));
EXPECT_FALSE(monitor_notified);
// Add |w1| directly to the root, should immediately notify.
root_window()->AddChild(w1.get());
EXPECT_TRUE(monitor_notified);
monitor_notified = false;
// Changing |w1|s bounds should notify as in a root.
w1->SetBounds(gfx::Rect(101, 102, 12, 13));
EXPECT_TRUE(monitor_notified);
monitor_notified = false;
// Changing the size should not notify.
w1->SetBounds(gfx::Rect(101, 102, 121, 13));
EXPECT_FALSE(monitor_notified);
}
} // namespace aura_extra
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment