diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-22 17:13:12 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-05-22 17:13:12 +0000 |
commit | 802e6c55549dcd03d8b6e80a3e3d5358fab33c39 (patch) | |
tree | 19876d7d1d43c4e3d4017afff24b2d0a88977c3c /mojo/services | |
parent | e2e47e9c92cc282a77231e59066ba7258085a00d (diff) | |
download | chromium_src-802e6c55549dcd03d8b6e80a3e3d5358fab33c39.zip chromium_src-802e6c55549dcd03d8b6e80a3e3d5358fab33c39.tar.gz chromium_src-802e6c55549dcd03d8b6e80a3e3d5358fab33c39.tar.bz2 |
SetBounds for ViewTreeNode.
R=sky@chromium.org
http://crbug.com/365012
Review URL: https://codereview.chromium.org/287053004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@272209 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo/services')
18 files changed, 393 insertions, 4 deletions
diff --git a/mojo/services/public/cpp/view_manager/DEPS b/mojo/services/public/cpp/view_manager/DEPS new file mode 100644 index 0000000..8ce1d20 --- /dev/null +++ b/mojo/services/public/cpp/view_manager/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+ui/gfx/geometry" +] diff --git a/mojo/services/public/cpp/view_manager/lib/DEPS b/mojo/services/public/cpp/view_manager/lib/DEPS index 2661b64..a3f6c8f 100644 --- a/mojo/services/public/cpp/view_manager/lib/DEPS +++ b/mojo/services/public/cpp/view_manager/lib/DEPS @@ -1,3 +1,8 @@ +include_rules = [ + "+mojo/geometry", + "+ui/gfx/geometry" +] + specific_include_rules = { "view_manager_test_suite.cc": [ "+ui/gl", diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc index 8eea829..76a6b52 100644 --- a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc +++ b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc @@ -99,7 +99,9 @@ class ViewManagerTransaction { // parent.) TYPE_HIERARCHY, // View replacement. - TYPE_SET_ACTIVE_VIEW + TYPE_SET_ACTIVE_VIEW, + // Node bounds. + TYPE_SET_BOUNDS }; ViewManagerTransaction(TransactionType transaction_type, @@ -305,6 +307,32 @@ class SetActiveViewTransaction : public ViewManagerTransaction { DISALLOW_COPY_AND_ASSIGN(SetActiveViewTransaction); }; +class SetBoundsTransaction : public ViewManagerTransaction { + public: + SetBoundsTransaction(TransportNodeId node_id, + const gfx::Rect& bounds, + ViewManagerSynchronizer* synchronizer) + : ViewManagerTransaction(TYPE_SET_BOUNDS, synchronizer), + node_id_(node_id), + bounds_(bounds) {} + virtual ~SetBoundsTransaction() {} + + private: + // Overridden from ViewManagerTransaction: + virtual void DoCommit() OVERRIDE { + AllocationScope scope; + service()->SetNodeBounds(node_id_, bounds_, ActionCompletedCallback()); + } + virtual void DoActionCompleted(bool success) OVERRIDE { + // TODO(beng): recovery? + } + + const TransportNodeId node_id_; + const gfx::Rect bounds_; + + DISALLOW_COPY_AND_ASSIGN(SetBoundsTransaction); +}; + ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager) : view_manager_(view_manager), connected_(false), @@ -399,6 +427,14 @@ void ViewManagerSynchronizer::SetActiveView(TransportNodeId node_id, Sync(); } +void ViewManagerSynchronizer::SetBounds(TransportNodeId node_id, + const gfx::Rect& bounds) { + DCHECK(connected_); + pending_transactions_.push_back( + new SetBoundsTransaction(node_id, bounds, this)); + Sync(); +} + //////////////////////////////////////////////////////////////////////////////// // ViewManagerSynchronizer, IViewManagerClient implementation: @@ -423,6 +459,13 @@ void ViewManagerSynchronizer::OnServerChangeIdAdvanced( next_server_change_id_ = next_server_change_id; } +void ViewManagerSynchronizer::OnNodeBoundsChanged(uint32 node_id, + const Rect& old_bounds, + const Rect& new_bounds) { + ViewTreeNode* node = view_manager_->GetNodeById(node_id); + ViewTreeNodePrivate(node).LocalSetBounds(old_bounds, new_bounds); +} + void ViewManagerSynchronizer::OnNodeHierarchyChanged( uint32_t node_id, uint32_t new_parent_id, diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h index 7a82a44..5e5c79f 100644 --- a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h +++ b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h @@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" +#include "mojo/geometry/geometry_type_converters.h" #include "mojo/services/public/cpp/view_manager/view_manager_types.h" #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" @@ -48,6 +49,7 @@ class ViewManagerSynchronizer : public IViewManagerClient { bool OwnsView(TransportViewId id) const; void SetActiveView(TransportNodeId node_id, TransportViewId view_id); + void SetBounds(TransportNodeId node_id, const gfx::Rect& bounds); void set_changes_acked_callback(const base::Callback<void(void)>& callback) { changes_acked_callback_ = callback; @@ -67,6 +69,9 @@ class ViewManagerSynchronizer : public IViewManagerClient { const mojo::Array<INode>& nodes) OVERRIDE; virtual void OnServerChangeIdAdvanced( uint32_t next_server_change_id) OVERRIDE; + virtual void OnNodeBoundsChanged(uint32 node_id, + const Rect& old_bounds, + const Rect& new_bounds) OVERRIDE; virtual void OnNodeHierarchyChanged( uint32 node_id, uint32 new_parent_id, diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc b/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc index e501ea6..66331a7 100644 --- a/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc +++ b/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc @@ -124,6 +124,40 @@ class ScopedSetActiveViewNotifier { DISALLOW_COPY_AND_ASSIGN(ScopedSetActiveViewNotifier); }; +class ScopedSetBoundsNotifier { + public: + ScopedSetBoundsNotifier(ViewTreeNode* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) + : node_(node), + old_bounds_(old_bounds), + new_bounds_(new_bounds) { + FOR_EACH_OBSERVER( + ViewTreeNodeObserver, + *ViewTreeNodePrivate(node_).observers(), + OnNodeBoundsChange(node_, + old_bounds_, + new_bounds_, + ViewTreeNodeObserver::DISPOSITION_CHANGING)); + } + ~ScopedSetBoundsNotifier() { + FOR_EACH_OBSERVER( + ViewTreeNodeObserver, + *ViewTreeNodePrivate(node_).observers(), + OnNodeBoundsChange(node_, + old_bounds_, + new_bounds_, + ViewTreeNodeObserver::DISPOSITION_CHANGED)); + } + + private: + ViewTreeNode* node_; + const gfx::Rect old_bounds_; + const gfx::Rect new_bounds_; + + DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier); +}; + class ScopedDestructionNotifier { public: explicit ScopedDestructionNotifier(ViewTreeNode* node) @@ -159,6 +193,7 @@ ViewTreeNode* ViewTreeNode::Create(ViewManager* view_manager) { } void ViewTreeNode::Destroy() { + // TODO(beng): only proceed if |manager_| OwnsNode(this). if (manager_) ViewManagerPrivate(manager_).synchronizer()->DestroyViewTreeNode(id_); while (!children_.empty()) @@ -166,6 +201,13 @@ void ViewTreeNode::Destroy() { LocalDestroy(); } +void ViewTreeNode::SetBounds(const gfx::Rect& bounds) { + // TODO(beng): only proceed if |manager_| OwnsNode(this). + if (manager_) + ViewManagerPrivate(manager_).synchronizer()->SetBounds(id_, bounds); + LocalSetBounds(bounds_, bounds); +} + void ViewTreeNode::AddObserver(ViewTreeNodeObserver* observer) { observers_.AddObserver(observer); } @@ -276,6 +318,13 @@ void ViewTreeNode::LocalSetActiveView(View* view) { ViewPrivate(active_view_).set_node(this); } +void ViewTreeNode::LocalSetBounds(const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + DCHECK(old_bounds == bounds_); + ScopedSetBoundsNotifier notifier(this, old_bounds, new_bounds); + bounds_ = new_bounds; +} + } // namespace view_manager } // namespace mojo diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h b/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h index ab2daaf..ec825d8 100644 --- a/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h +++ b/mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h @@ -39,10 +39,13 @@ class ViewTreeNodePrivate { void LocalRemoveChild(ViewTreeNode* child) { node_->LocalRemoveChild(child); } - void LocalSetActiveView(View* view) { node_->LocalSetActiveView(view); } + void LocalSetBounds(const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + node_->LocalSetBounds(old_bounds, new_bounds); + } private: ViewTreeNode* node_; diff --git a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc index f86820a..d28dca2 100644 --- a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc +++ b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc @@ -18,6 +18,7 @@ namespace mojo { namespace view_manager { +namespace { base::RunLoop* current_run_loop = NULL; @@ -72,6 +73,36 @@ void WaitForActiveViewToChange(ViewTreeNode* node) { node->RemoveObserver(&observer); } +class BoundsChangeObserver : public ViewTreeNodeObserver { + public: + explicit BoundsChangeObserver(ViewTreeNode* node) : node_(node) {} + virtual ~BoundsChangeObserver() {} + + private: + // Overridden from ViewTreeNodeObserver: + virtual void OnNodeBoundsChange(ViewTreeNode* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + DispositionChangePhase phase) OVERRIDE { + DCHECK_EQ(node, node_); + if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) + return; + QuitRunLoop(); + } + + ViewTreeNode* node_; + + DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); +}; + +// Wait until the bounds of the supplied node change. +void WaitForBoundsToChange(ViewTreeNode* node) { + BoundsChangeObserver observer(node); + node->AddObserver(&observer); + DoRunLoop(); + node->RemoveObserver(&observer); +} + // Spins a runloop until the tree beginning at |root| has |tree_size| nodes // (including |root|). class TreeSizeMatchesObserver : public ViewTreeNodeObserver { @@ -185,6 +216,8 @@ void WaitForDestruction(ViewManager* view_manager, DoRunLoop(); } +} // namespace + // ViewManager ----------------------------------------------------------------- // These tests model synchronization of two peer connections to the view manager @@ -528,5 +561,21 @@ TEST_F(ViewManagerTest, MapSubtreeOnAttach) { EXPECT_EQ(view11_2, node11_2->active_view()); } +// Verifies that bounds changes applied to a node hierarchy in one connection +// are reflected to another. +TEST_F(ViewManagerTest, SetBounds) { + ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); + WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); + + ViewTreeNode* node1_2 = view_manager_2()->GetNodeById(node1->id()); + EXPECT_EQ(node1->bounds(), node1_2->bounds()); + + node1->SetBounds(gfx::Rect(0, 0, 100, 100)); + WaitForBoundsToChange(node1_2); + EXPECT_EQ(node1->bounds(), node1_2->bounds()); + + +} + } // namespace view_manager } // namespace mojo diff --git a/mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc index 2f4ec3e..b548690 100644 --- a/mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc +++ b/mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc @@ -5,7 +5,9 @@ #include "mojo/services/public/cpp/view_manager/view_tree_node.h" #include "base/logging.h" +#include "base/strings/stringprintf.h" #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" +#include "mojo/services/public/cpp/view_manager/util.h" #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,7 +21,9 @@ typedef testing::Test ViewTreeNodeTest; // Subclass with public ctor/dtor. class TestViewTreeNode : public ViewTreeNode { public: - TestViewTreeNode() {} + TestViewTreeNode() { + ViewTreeNodePrivate(this).set_id(1); + } ~TestViewTreeNode() {} private: @@ -342,5 +346,79 @@ TEST_F(ViewTreeNodeObserverTest, TreeChange_Reparent) { EXPECT_TRUE(TreeChangeParamsMatch(p111, o111.received_params().back())); } +namespace { + +typedef std::vector<std::string> Changes; + +std::string NodeIdToString(TransportNodeId id) { + return (id == 0) ? "null" : + base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); +} + +std::string RectToString(const gfx::Rect& rect) { + return base::StringPrintf("%d,%d %dx%d", + rect.x(), rect.y(), rect.width(), rect.height()); +} + +std::string PhaseToString(ViewTreeNodeObserver::DispositionChangePhase phase) { + return phase == ViewTreeNodeObserver::DISPOSITION_CHANGING ? + "changing" : "changed"; +} + +class BoundsChangeObserver : public ViewTreeNodeObserver { + public: + explicit BoundsChangeObserver(ViewTreeNode* node) : node_(node) { + node_->AddObserver(this); + } + virtual ~BoundsChangeObserver() { + node_->RemoveObserver(this); + } + + Changes GetAndClearChanges() { + Changes changes; + changes.swap(changes_); + return changes; + } + + private: + // Overridden from ViewTreeNodeObserver: + virtual void OnNodeBoundsChange(ViewTreeNode* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + DispositionChangePhase phase) OVERRIDE { + changes_.push_back( + base::StringPrintf( + "node=%s old_bounds=%s new_bounds=%s phase=%s", + NodeIdToString(node->id()).c_str(), + RectToString(old_bounds).c_str(), + RectToString(new_bounds).c_str(), + PhaseToString(phase).c_str())); + } + + ViewTreeNode* node_; + Changes changes_; + + DISALLOW_COPY_AND_ASSIGN(BoundsChangeObserver); +}; + +} // namespace + +TEST_F(ViewTreeNodeObserverTest, SetBounds) { + TestViewTreeNode v1; + { + BoundsChangeObserver observer(&v1); + v1.SetBounds(gfx::Rect(0, 0, 100, 100)); + + Changes changes = observer.GetAndClearChanges(); + EXPECT_EQ(2U, changes.size()); + EXPECT_EQ( + "node=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changing", + changes[0]); + EXPECT_EQ( + "node=0,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100 phase=changed", + changes[1]); + } +} + } // namespace view_manager } // namespace mojo diff --git a/mojo/services/public/cpp/view_manager/util.h b/mojo/services/public/cpp/view_manager/util.h index 1c85035..87382e2 100644 --- a/mojo/services/public/cpp/view_manager/util.h +++ b/mojo/services/public/cpp/view_manager/util.h @@ -7,6 +7,14 @@ #include "mojo/services/public/cpp/view_manager/view_manager_types.h" +// TODO(beng): #$*&@#(@ MacOSX SDK! +#if defined(HiWord) +#undef HiWord +#endif +#if defined(LoWord) +#undef LoWord +#endif + namespace mojo { namespace view_manager { diff --git a/mojo/services/public/cpp/view_manager/view_tree_node.h b/mojo/services/public/cpp/view_manager/view_tree_node.h index 695b450..a5d9b36 100644 --- a/mojo/services/public/cpp/view_manager/view_tree_node.h +++ b/mojo/services/public/cpp/view_manager/view_tree_node.h @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/observer_list.h" #include "mojo/services/public/cpp/view_manager/view_manager_types.h" +#include "ui/gfx/geometry/rect.h" namespace mojo { namespace view_manager { @@ -34,6 +35,10 @@ class ViewTreeNode { // Configuration. TransportNodeId id() const { return id_; } + // Geometric disposition. + const gfx::Rect& bounds() { return bounds_; } + void SetBounds(const gfx::Rect& bounds); + // Observation. void AddObserver(ViewTreeNodeObserver* observer); void RemoveObserver(ViewTreeNodeObserver* observer); @@ -68,6 +73,7 @@ class ViewTreeNode { void LocalAddChild(ViewTreeNode* child); void LocalRemoveChild(ViewTreeNode* child); void LocalSetActiveView(View* view); + void LocalSetBounds(const gfx::Rect& old_bounds, const gfx::Rect& new_bounds); ViewManager* manager_; TransportNodeId id_; @@ -76,6 +82,7 @@ class ViewTreeNode { ObserverList<ViewTreeNodeObserver> observers_; + gfx::Rect bounds_; View* active_view_; DISALLOW_COPY_AND_ASSIGN(ViewTreeNode); diff --git a/mojo/services/public/cpp/view_manager/view_tree_node_observer.h b/mojo/services/public/cpp/view_manager/view_tree_node_observer.h index 461d29d..116e156 100644 --- a/mojo/services/public/cpp/view_manager/view_tree_node_observer.h +++ b/mojo/services/public/cpp/view_manager/view_tree_node_observer.h @@ -9,6 +9,10 @@ #include "base/basictypes.h" +namespace gfx { +class Rect; +} + namespace mojo { namespace view_manager { @@ -41,6 +45,11 @@ class ViewTreeNodeObserver { View* new_view, DispositionChangePhase phase) {} + virtual void OnNodeBoundsChange(ViewTreeNode* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + DispositionChangePhase phase) {} + protected: virtual ~ViewTreeNodeObserver() {} }; diff --git a/mojo/services/public/interfaces/view_manager/view_manager.mojom b/mojo/services/public/interfaces/view_manager/view_manager.mojom index 39748a1..7e0f9f7 100644 --- a/mojo/services/public/interfaces/view_manager/view_manager.mojom +++ b/mojo/services/public/interfaces/view_manager/view_manager.mojom @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import "../../../../public/interfaces/geometry/geometry.mojom" + module mojo.view_manager { struct INode { @@ -33,6 +35,9 @@ interface IViewManager { // delete it. DeleteNode(uint32 node_id) => (bool success); + // Sets the specified bounds of the specified node. + SetNodeBounds(uint32 node_id, mojo.Rect bounds) => (bool success); + // Reparents a node. See description above class for details of |change_id|. // This fails for any of the following reasons: // . |server_change_id| is not the expected id. @@ -108,6 +113,9 @@ interface IViewManagerClient { // OnServerChangeIdAdvanced(). OnServerChangeIdAdvanced(uint32 next_server_change_id); + // Invoked when a node's bounds have changed. + OnNodeBoundsChanged(uint32 node, mojo.Rect old_bounds, mojo.Rect new_bounds); + // Invoked when a change is done to the hierarchy. A value of 0 is used to // identify a null node. For example, if the old_parent is NULL, 0 is // supplied. See description above ViewManager for details on the change ids. diff --git a/mojo/services/view_manager/DEPS b/mojo/services/view_manager/DEPS index 248384f..81d1c97 100644 --- a/mojo/services/view_manager/DEPS +++ b/mojo/services/view_manager/DEPS @@ -1,5 +1,6 @@ include_rules = [ "+mojo/aura", + "+mojo/geometry", "+mojo/services", "+third_party/skia", "+ui/aura", diff --git a/mojo/services/view_manager/root_node_manager.cc b/mojo/services/view_manager/root_node_manager.cc index 791576e..710839b 100644 --- a/mojo/services/view_manager/root_node_manager.cc +++ b/mojo/services/view_manager/root_node_manager.cc @@ -81,6 +81,16 @@ View* RootNodeManager::GetView(const ViewId& id) { return i == connection_map_.end() ? NULL : i->second->GetView(id); } +void RootNodeManager::ProcessNodeBoundsChanged(const Node* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds) { + for (ConnectionMap::iterator i = connection_map_.begin(); + i != connection_map_.end(); ++i) { + i->second->ProcessNodeBoundsChanged(node, old_bounds, new_bounds, + IsChangeSource(i->first)); + } +} + void RootNodeManager::ProcessNodeHierarchyChanged(const Node* node, const Node* new_parent, const Node* old_parent) { diff --git a/mojo/services/view_manager/root_node_manager.h b/mojo/services/view_manager/root_node_manager.h index 75ad4e0..1163ca1 100644 --- a/mojo/services/view_manager/root_node_manager.h +++ b/mojo/services/view_manager/root_node_manager.h @@ -82,6 +82,9 @@ class MOJO_VIEW_MANAGER_EXPORT RootNodeManager : public NodeDelegate { // These functions trivially delegate to all ViewManagerConnections, which in // term notify their clients. + void ProcessNodeBoundsChanged(const Node* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds); void ProcessNodeHierarchyChanged(const Node* node, const Node* new_parent, const Node* old_parent); @@ -116,7 +119,7 @@ class MOJO_VIEW_MANAGER_EXPORT RootNodeManager : public NodeDelegate { return connection_id == change_source_; } - // Overriden from NodeDelegate: + // Overridden from NodeDelegate: virtual void OnNodeHierarchyChanged(const Node* node, const Node* new_parent, const Node* old_parent) OVERRIDE; diff --git a/mojo/services/view_manager/view_manager_connection.cc b/mojo/services/view_manager/view_manager_connection.cc index bb9c4de..e8ce02c 100644 --- a/mojo/services/view_manager/view_manager_connection.cc +++ b/mojo/services/view_manager/view_manager_connection.cc @@ -5,6 +5,7 @@ #include "mojo/services/view_manager/view_manager_connection.h" #include "base/stl_util.h" +#include "mojo/geometry/geometry_type_converters.h" #include "mojo/public/cpp/bindings/allocation_scope.h" #include "mojo/services/view_manager/node.h" #include "mojo/services/view_manager/root_node_manager.h" @@ -99,6 +100,20 @@ const View* ViewManagerConnection::GetView(const ViewId& id) const { return root_node_manager_->GetView(id); } +void ViewManagerConnection::ProcessNodeBoundsChanged( + const Node* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + bool originated_change) { + if (originated_change) + return; + TransportNodeId node_id = NodeIdToTransportId(node->id()); + if (known_nodes_.count(node_id) > 0) { + AllocationScope scope; + client()->OnNodeBoundsChanged(node_id, old_bounds, new_bounds); + } +} + void ViewManagerConnection::ProcessNodeHierarchyChanged( const Node* node, const Node* new_parent, @@ -582,6 +597,30 @@ void ViewManagerConnection::SetRoots( connection->ProcessSetRoots(id_, transport_node_ids)); } +void ViewManagerConnection::SetNodeBounds( + TransportNodeId node_id, + const Rect& bounds, + const Callback<void(bool)>& callback) { + if (NodeIdFromTransportId(node_id).connection_id != id_) { + callback.Run(false); + return; + } + + Node* node = GetNode(NodeIdFromTransportId(node_id)); + if (!node) { + callback.Run(false); + return; + } + + RootNodeManager::ScopedChange change( + this, root_node_manager_, + RootNodeManager::CHANGE_TYPE_DONT_ADVANCE_SERVER_CHANGE_ID, false); + gfx::Rect old_bounds = node->window()->bounds(); + node->window()->SetBounds(bounds); + root_node_manager_->ProcessNodeBoundsChanged(node, old_bounds, bounds); + callback.Run(true); +} + void ViewManagerConnection::OnNodeHierarchyChanged(const Node* node, const Node* new_parent, const Node* old_parent) { diff --git a/mojo/services/view_manager/view_manager_connection.h b/mojo/services/view_manager/view_manager_connection.h index 7aae7d8..5653ac5 100644 --- a/mojo/services/view_manager/view_manager_connection.h +++ b/mojo/services/view_manager/view_manager_connection.h @@ -16,6 +16,10 @@ #include "mojo/services/view_manager/node_delegate.h" #include "mojo/services/view_manager/view_manager_export.h" +namespace gfx { +class Rect; +} + namespace mojo { namespace view_manager { namespace service { @@ -60,6 +64,10 @@ class MOJO_VIEW_MANAGER_EXPORT ViewManagerConnection // The following methods are invoked after the corresponding change has been // processed. They do the appropriate bookkeeping and update the client as // necessary. + void ProcessNodeBoundsChanged(const Node* node, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + bool originated_change); void ProcessNodeHierarchyChanged(const Node* node, const Node* new_parent, const Node* old_parent, @@ -157,6 +165,9 @@ class MOJO_VIEW_MANAGER_EXPORT ViewManagerConnection TransportConnectionId connection_id, const Array<TransportNodeId>& transport_node_ids, const Callback<void(bool)>& callback) OVERRIDE; + virtual void SetNodeBounds(TransportNodeId node_id, + const Rect& bounds, + const Callback<void(bool)>& callback) OVERRIDE; // Overridden from NodeDelegate: virtual void OnNodeHierarchyChanged(const Node* node, diff --git a/mojo/services/view_manager/view_manager_connection_unittest.cc b/mojo/services/view_manager/view_manager_connection_unittest.cc index 56ab6a3..56caa8b 100644 --- a/mojo/services/view_manager/view_manager_connection_unittest.cc +++ b/mojo/services/view_manager/view_manager_connection_unittest.cc @@ -11,6 +11,7 @@ #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "mojo/common/common_type_converters.h" +#include "mojo/geometry/geometry_type_converters.h" #include "mojo/public/cpp/bindings/allocation_scope.h" #include "mojo/public/cpp/environment/environment.h" #include "mojo/public/cpp/shell/connect.h" @@ -19,6 +20,7 @@ #include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h" #include "mojo/shell/shell_test_helper.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/rect.h" namespace mojo { @@ -60,6 +62,15 @@ std::string NodeIdToString(TransportNodeId id) { base::StringPrintf("%d,%d", HiWord(id), LoWord(id)); } +// Converts |rect| into a string. +std::string RectToString(const Rect& rect) { + return base::StringPrintf("%d,%d %dx%d", + rect.position().x(), + rect.position().y(), + rect.size().width(), + rect.size().height()); +} + // Boolean callback. Sets |result_cache| to the value of |result| and quits // the run loop. void BooleanCallback(bool* result_cache, bool result) { @@ -139,6 +150,16 @@ bool DeleteView(IViewManager* view_manager, TransportViewId view_id) { return result; } +bool SetNodeBounds(IViewManager* view_manager, + TransportNodeId node_id, + const gfx::Rect& bounds) { + bool result = false; + view_manager->SetNodeBounds(node_id, bounds, + base::Bind(&BooleanCallback, &result)); + DoRunLoop(); + return result; +} + // Adds a node, blocking until done. bool AddNode(IViewManager* view_manager, TransportNodeId parent, @@ -270,6 +291,17 @@ class ViewManagerClientImpl : public IViewManagerClient { static_cast<int>(next_server_change_id))); QuitIfNecessary(); } + virtual void OnNodeBoundsChanged(TransportNodeId node_id, + const Rect& old_bounds, + const Rect& new_bounds) OVERRIDE { + changes_.push_back( + base::StringPrintf( + "BoundsChanged node=%s old_bounds=%s new_bounds=%s", + NodeIdToString(node_id).c_str(), + RectToString(old_bounds).c_str(), + RectToString(new_bounds).c_str())); + QuitIfNecessary(); + } virtual void OnNodeHierarchyChanged( TransportNodeId node, TransportNodeId new_parent, @@ -1146,6 +1178,32 @@ TEST_F(ViewManagerConnectionTest, GetNodeTree) { } } +TEST_F(ViewManagerConnectionTest, SetNodeBounds) { + ASSERT_TRUE(CreateNode(view_manager_.get(), 1, 1)); + ASSERT_TRUE(AddNode(view_manager_.get(), + CreateNodeId(0, 1), + CreateNodeId(1, 1), + 1)); + EstablishSecondConnection(); + + AllocationScope scope; + ASSERT_TRUE(SetNodeBounds(view_manager_.get(), + CreateNodeId(1, 1), + gfx::Rect(0, 0, 100, 100))); + + client2_.DoRunLoopUntilChangesCount(1); + Changes changes(client2_.GetAndClearChanges()); + ASSERT_EQ(1u, changes.size()); + EXPECT_EQ("BoundsChanged node=1,1 old_bounds=0,0 0x0 new_bounds=0,0 100x100", + changes[0]); + + // Should not be possible to change the bounds of a node created by another + // connection. + ASSERT_FALSE(SetNodeBounds(view_manager2_.get(), + CreateNodeId(1, 1), + gfx::Rect(0, 0, 0, 0))); +} + // Various assertions around SetRoots. TEST_F(ViewManagerConnectionTest, SetRoots) { // Create 1, 2, and 3 in the first connection. |