summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-12 19:29:35 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-12 19:29:35 +0000
commitf6435d20208dd9f2d56173bbe73dc605aacdea7d (patch)
tree1c8a97ed6d3eeca4bc49af93fb324eb0c4d20ced /mojo
parent052e6b15ee2376e12fcb50298eda43fa98f08474 (diff)
downloadchromium_src-f6435d20208dd9f2d56173bbe73dc605aacdea7d.zip
chromium_src-f6435d20208dd9f2d56173bbe73dc605aacdea7d.tar.gz
chromium_src-f6435d20208dd9f2d56173bbe73dc605aacdea7d.tar.bz2
Implement reordering of nodes.
Note that this doesn't apply to roots. If an app is embedded and its root node is reordered, there is no notification to the app. I figure this is up to the window manager to expose an API for this type of thing. R=sky@chromium.org http://crbug.com/365012 Review URL: https://codereview.chromium.org/327073003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276768 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'mojo')
-rw-r--r--mojo/examples/aura_demo/aura_demo.cc6
-rw-r--r--mojo/mojo_services.gypi1
-rw-r--r--mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc133
-rw-r--r--mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h7
-rw-r--r--mojo/services/public/cpp/view_manager/lib/view_tree_node.cc89
-rw-r--r--mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h3
-rw-r--r--mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc67
-rw-r--r--mojo/services/public/cpp/view_manager/tests/view_tree_node_unittest.cc147
-rw-r--r--mojo/services/public/cpp/view_manager/view_tree_node.h7
-rw-r--r--mojo/services/public/cpp/view_manager/view_tree_node_observer.h7
-rw-r--r--mojo/services/public/interfaces/view_manager/view_manager.mojom16
-rw-r--r--mojo/services/public/interfaces/view_manager/view_manager_constants.mojom12
-rw-r--r--mojo/services/view_manager/node.cc7
-rw-r--r--mojo/services/view_manager/node.h3
-rw-r--r--mojo/services/view_manager/root_node_manager.cc11
-rw-r--r--mojo/services/view_manager/root_node_manager.h3
-rw-r--r--mojo/services/view_manager/test_change_tracker.cc28
-rw-r--r--mojo/services/view_manager/test_change_tracker.h6
-rw-r--r--mojo/services/view_manager/view_manager_connection.cc68
-rw-r--r--mojo/services/view_manager/view_manager_connection.h13
-rw-r--r--mojo/services/view_manager/view_manager_connection_unittest.cc99
21 files changed, 693 insertions, 40 deletions
diff --git a/mojo/examples/aura_demo/aura_demo.cc b/mojo/examples/aura_demo/aura_demo.cc
index fd87f69..d1caecc 100644
--- a/mojo/examples/aura_demo/aura_demo.cc
+++ b/mojo/examples/aura_demo/aura_demo.cc
@@ -168,6 +168,12 @@ class IViewManagerClientImpl
uint32_t server_change_id,
mojo::Array<view_manager::INodePtr> nodes) OVERRIDE {
}
+ virtual void OnNodeReordered(
+ uint32_t node_id,
+ uint32_t relative_node_id,
+ view_manager::OrderDirection direction,
+ uint32_t server_change_id) OVERRIDE {
+ }
virtual void OnNodeDeleted(uint32_t node, uint32_t server_change_id)
OVERRIDE {
}
diff --git a/mojo/mojo_services.gypi b/mojo/mojo_services.gypi
index 1768ccf8..ee73af1 100644
--- a/mojo/mojo_services.gypi
+++ b/mojo/mojo_services.gypi
@@ -250,6 +250,7 @@
'type': 'static_library',
'sources': [
'services/public/interfaces/view_manager/view_manager.mojom',
+ 'services/public/interfaces/view_manager/view_manager_constants.mojom',
],
'includes': [ 'public/tools/bindings/mojom_bindings_generator.gypi' ],
'export_dependent_settings': [
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 baca5a4..16e2321 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
@@ -246,52 +246,92 @@ class DestroyViewTreeNodeTransaction : public ViewManagerTransaction {
DISALLOW_COPY_AND_ASSIGN(DestroyViewTreeNodeTransaction);
};
-class HierarchyTransaction : public ViewManagerTransaction {
+class AddChildTransaction : public ViewManagerTransaction {
public:
- enum HierarchyChangeType {
- TYPE_ADD,
- TYPE_REMOVE
- };
- HierarchyTransaction(HierarchyChangeType hierarchy_change_type,
- Id child_id,
- Id parent_id,
- ViewManagerSynchronizer* synchronizer)
+ AddChildTransaction(Id child_id,
+ Id parent_id,
+ ViewManagerSynchronizer* synchronizer)
: ViewManagerTransaction(synchronizer),
- hierarchy_change_type_(hierarchy_change_type),
child_id_(child_id),
parent_id_(parent_id) {}
- virtual ~HierarchyTransaction() {}
+ virtual ~AddChildTransaction() {}
private:
// Overridden from ViewManagerTransaction:
virtual void DoCommit() OVERRIDE {
- switch (hierarchy_change_type_) {
- case TYPE_ADD:
- service()->AddNode(
- parent_id_,
- child_id_,
- GetAndAdvanceNextServerChangeId(),
- ActionCompletedCallback());
- break;
- case TYPE_REMOVE:
- service()->RemoveNodeFromParent(
- child_id_,
- GetAndAdvanceNextServerChangeId(),
- ActionCompletedCallback());
- break;
- }
+ service()->AddNode(parent_id_,
+ child_id_,
+ GetAndAdvanceNextServerChangeId(),
+ ActionCompletedCallback());
}
virtual void DoActionCompleted(bool success) OVERRIDE {
- // TODO(beng): Failure means either one of the nodes specified didn't exist,
- // or we passed the same node id for both params. Roll back?
+ // TODO(beng): recovery?
}
- const HierarchyChangeType hierarchy_change_type_;
const Id child_id_;
const Id parent_id_;
- DISALLOW_COPY_AND_ASSIGN(HierarchyTransaction);
+ DISALLOW_COPY_AND_ASSIGN(AddChildTransaction);
+};
+
+class RemoveChildTransaction : public ViewManagerTransaction {
+ public:
+ RemoveChildTransaction(Id child_id,
+ ViewManagerSynchronizer* synchronizer)
+ : ViewManagerTransaction(synchronizer),
+ child_id_(child_id) {}
+ virtual ~RemoveChildTransaction() {}
+
+ private:
+ // Overridden from ViewManagerTransaction:
+ virtual void DoCommit() OVERRIDE {
+ service()->RemoveNodeFromParent(
+ child_id_,
+ GetAndAdvanceNextServerChangeId(),
+ ActionCompletedCallback());
+ }
+
+ virtual void DoActionCompleted(bool success) OVERRIDE {
+ // TODO(beng): recovery?
+ }
+
+ const Id child_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(RemoveChildTransaction);
+};
+
+class ReorderNodeTransaction : public ViewManagerTransaction {
+ public:
+ ReorderNodeTransaction(Id node_id,
+ Id relative_id,
+ OrderDirection direction,
+ ViewManagerSynchronizer* synchronizer)
+ : ViewManagerTransaction(synchronizer),
+ node_id_(node_id),
+ relative_id_(relative_id),
+ direction_(direction) {}
+ virtual ~ReorderNodeTransaction() {}
+
+ private:
+ // Overridden from ViewManagerTransaction:
+ virtual void DoCommit() OVERRIDE {
+ service()->ReorderNode(node_id_,
+ relative_id_,
+ direction_,
+ GetAndAdvanceNextServerChangeId(),
+ ActionCompletedCallback());
+ }
+
+ virtual void DoActionCompleted(bool success) OVERRIDE {
+ // TODO(beng): recovery?
+ }
+
+ const Id node_id_;
+ const Id relative_id_;
+ const OrderDirection direction_;
+
+ DISALLOW_COPY_AND_ASSIGN(ReorderNodeTransaction);
};
class SetActiveViewTransaction : public ViewManagerTransaction {
@@ -495,20 +535,23 @@ void ViewManagerSynchronizer::AddChild(Id child_id,
Id parent_id) {
DCHECK(connected_);
pending_transactions_.push_back(
- new HierarchyTransaction(HierarchyTransaction::TYPE_ADD,
- child_id,
- parent_id,
- this));
+ new AddChildTransaction(child_id, parent_id, this));
Sync();
}
void ViewManagerSynchronizer::RemoveChild(Id child_id, Id parent_id) {
DCHECK(connected_);
+ pending_transactions_.push_back(new RemoveChildTransaction(child_id, this));
+ Sync();
+}
+
+void ViewManagerSynchronizer::Reorder(
+ Id node_id,
+ Id relative_node_id,
+ OrderDirection direction) {
+ DCHECK(connected_);
pending_transactions_.push_back(
- new HierarchyTransaction(HierarchyTransaction::TYPE_REMOVE,
- child_id,
- parent_id,
- this));
+ new ReorderNodeTransaction(node_id, relative_node_id, direction, this));
Sync();
}
@@ -638,7 +681,6 @@ void ViewManagerSynchronizer::OnNodeHierarchyChanged(
Id old_parent_id,
Id server_change_id,
mojo::Array<INodePtr> nodes) {
- // TODO: deal with |nodes|.
next_server_change_id_ = server_change_id + 1;
BuildNodeTree(this, nodes);
@@ -652,6 +694,19 @@ void ViewManagerSynchronizer::OnNodeHierarchyChanged(
ViewTreeNodePrivate(old_parent).LocalRemoveChild(node);
}
+void ViewManagerSynchronizer::OnNodeReordered(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id) {
+ next_server_change_id_ = server_change_id + 1;
+
+ ViewTreeNode* node = GetNodeById(node_id);
+ ViewTreeNode* relative_node = GetNodeById(relative_node_id);
+ if (node && relative_node) {
+ ViewTreeNodePrivate(node).LocalReorder(relative_node, direction);
+ }
+}
+
void ViewManagerSynchronizer::OnNodeDeleted(Id node_id, Id server_change_id) {
next_server_change_id_ = server_change_id + 1;
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 69ebd82..f888787 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
@@ -12,6 +12,7 @@
#include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
#include "mojo/services/public/cpp/view_manager/view_manager.h"
#include "mojo/services/public/cpp/view_manager/view_manager_types.h"
+#include "mojo/services/public/cpp/view_manager/view_tree_node.h"
#include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h"
class SkBitmap;
@@ -46,6 +47,8 @@ class ViewManagerSynchronizer : public ViewManager,
void AddChild(Id child_id, Id parent_id);
void RemoveChild(Id child_id, Id parent_id);
+ void Reorder(Id node_id, Id relative_node_id, OrderDirection direction);
+
// Returns true if the specified node/view was created by this connection.
bool OwnsNode(Id id) const;
bool OwnsView(Id id) const;
@@ -106,6 +109,10 @@ class ViewManagerSynchronizer : public ViewManager,
Id old_parent_id,
Id server_change_id,
Array<INodePtr> nodes) OVERRIDE;
+ virtual void OnNodeReordered(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id) OVERRIDE;
virtual void OnNodeDeleted(Id node_id, Id server_change_id) OVERRIDE;
virtual void OnNodeViewReplaced(Id node,
Id new_view_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 27848a3..5a6c1d2 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
@@ -80,6 +80,72 @@ void RemoveChildImpl(ViewTreeNode* child, ViewTreeNode::Children* children) {
}
}
+class ScopedOrderChangedNotifier {
+ public:
+ ScopedOrderChangedNotifier(ViewTreeNode* node,
+ ViewTreeNode* relative_node,
+ OrderDirection direction)
+ : node_(node),
+ relative_node_(relative_node),
+ direction_(direction) {
+ FOR_EACH_OBSERVER(
+ ViewTreeNodeObserver,
+ *ViewTreeNodePrivate(node_).observers(),
+ OnNodeReordered(node_,
+ relative_node_,
+ direction_,
+ ViewTreeNodeObserver::DISPOSITION_CHANGING));
+
+ }
+ ~ScopedOrderChangedNotifier() {
+ FOR_EACH_OBSERVER(
+ ViewTreeNodeObserver,
+ *ViewTreeNodePrivate(node_).observers(),
+ OnNodeReordered(node_,
+ relative_node_,
+ direction_,
+ ViewTreeNodeObserver::DISPOSITION_CHANGED));
+ }
+
+ private:
+ ViewTreeNode* node_;
+ ViewTreeNode* relative_node_;
+ OrderDirection direction_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier);
+};
+
+// Returns true if the order actually changed.
+bool ReorderImpl(ViewTreeNode::Children* children,
+ ViewTreeNode* node,
+ ViewTreeNode* relative,
+ OrderDirection direction) {
+ DCHECK(relative);
+ DCHECK_NE(node, relative);
+ DCHECK_EQ(node->parent(), relative->parent());
+
+ const size_t child_i =
+ std::find(children->begin(), children->end(), node) - children->begin();
+ const size_t target_i =
+ std::find(children->begin(), children->end(), relative) -
+ children->begin();
+ if ((direction == ORDER_ABOVE && child_i == target_i + 1) ||
+ (direction == ORDER_BELOW && child_i + 1 == target_i)) {
+ return false;
+ }
+
+ ScopedOrderChangedNotifier notifier(node, relative, direction);
+
+ const size_t dest_i =
+ direction == ORDER_ABOVE ?
+ (child_i < target_i ? target_i : target_i + 1) :
+ (child_i < target_i ? target_i - 1 : target_i);
+ children->erase(children->begin() + child_i);
+ children->insert(children->begin() + dest_i, node);
+
+ return true;
+}
+
class ScopedSetActiveViewNotifier {
public:
ScopedSetActiveViewNotifier(ViewTreeNode* node,
@@ -238,6 +304,24 @@ void ViewTreeNode::RemoveChild(ViewTreeNode* child) {
}
}
+void ViewTreeNode::MoveToFront() {
+ Reorder(parent_->children_.back(), ORDER_ABOVE);
+}
+
+void ViewTreeNode::MoveToBack() {
+ Reorder(parent_->children_.front(), ORDER_BELOW);
+}
+
+void ViewTreeNode::Reorder(ViewTreeNode* relative, OrderDirection direction) {
+ if (!LocalReorder(relative, direction))
+ return;
+ if (manager_) {
+ static_cast<ViewManagerSynchronizer*>(manager_)->Reorder(id_,
+ relative->id(),
+ direction);
+ }
+}
+
bool ViewTreeNode::Contains(ViewTreeNode* child) const {
if (manager_)
CHECK_EQ(ViewTreeNodePrivate(child).view_manager(), manager_);
@@ -324,6 +408,11 @@ void ViewTreeNode::LocalRemoveChild(ViewTreeNode* child) {
RemoveChildImpl(child, &children_);
}
+bool ViewTreeNode::LocalReorder(ViewTreeNode* relative,
+ OrderDirection direction) {
+ return ReorderImpl(&parent_->children_, this, relative, direction);
+}
+
void ViewTreeNode::LocalSetActiveView(View* view) {
ScopedSetActiveViewNotifier notifier(this, active_view_, view);
if (active_view_)
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 8c8cbdd..e3b84d6 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,6 +39,9 @@ class ViewTreeNodePrivate {
void LocalRemoveChild(ViewTreeNode* child) {
node_->LocalRemoveChild(child);
}
+ void LocalReorder(ViewTreeNode* relative, OrderDirection direction) {
+ node_->LocalReorder(relative, direction);
+ }
void LocalSetActiveView(View* view) {
node_->LocalSetActiveView(view);
}
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 1ce3d0a..1527cd5 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
@@ -250,6 +250,39 @@ void WaitForDestruction(ViewManager* view_manager,
DoRunLoop();
}
+class OrderChangeObserver : public ViewTreeNodeObserver {
+ public:
+ OrderChangeObserver(ViewTreeNode* node) : node_(node) {
+ node_->AddObserver(this);
+ }
+ virtual ~OrderChangeObserver() {
+ node_->RemoveObserver(this);
+ }
+
+ private:
+ // Overridden from ViewTreeNodeObserver:
+ virtual void OnNodeReordered(ViewTreeNode* node,
+ ViewTreeNode* relative_node,
+ OrderDirection direction,
+ DispositionChangePhase phase) OVERRIDE {
+ if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED)
+ return;
+
+ DCHECK_EQ(node, node_);
+ QuitRunLoop();
+ }
+
+ ViewTreeNode* node_;
+
+ DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
+};
+
+void WaitForOrderChange(ViewManager* view_manager,
+ ViewTreeNode* node) {
+ OrderChangeObserver observer(node);
+ DoRunLoop();
+}
+
// Tracks a node's destruction. Query is_valid() for current state.
class NodeTracker : public ViewTreeNodeObserver {
public:
@@ -709,5 +742,39 @@ TEST_F(ViewManagerTest, EmbeddingIdentity) {
EXPECT_EQ(kWindowManagerURL, embedded->GetEmbedderURL());
}
+TEST_F(ViewManagerTest, Reorder) {
+ ViewTreeNode* node1 = ViewTreeNode::Create(window_manager());
+ window_manager()->GetRoots().front()->AddChild(node1);
+
+ ViewTreeNode* node11 = ViewTreeNode::Create(window_manager());
+ node1->AddChild(node11);
+ ViewTreeNode* node12 = ViewTreeNode::Create(window_manager());
+ node1->AddChild(node12);
+
+ ViewManager* embedded = Embed(window_manager(), node1);
+
+ ViewTreeNode* node1_in_embedded = embedded->GetNodeById(node1->id());
+
+ {
+ node11->MoveToFront();
+ WaitForOrderChange(embedded, embedded->GetNodeById(node11->id()));
+
+ EXPECT_EQ(node1_in_embedded->children().front(),
+ embedded->GetNodeById(node12->id()));
+ EXPECT_EQ(node1_in_embedded->children().back(),
+ embedded->GetNodeById(node11->id()));
+ }
+
+ {
+ node11->MoveToBack();
+ WaitForOrderChange(embedded, embedded->GetNodeById(node11->id()));
+
+ EXPECT_EQ(node1_in_embedded->children().front(),
+ embedded->GetNodeById(node11->id()));
+ EXPECT_EQ(node1_in_embedded->children().back(),
+ embedded->GetNodeById(node12->id()));
+ }
+}
+
} // 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 89b8293..d2326dc 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
@@ -348,6 +348,153 @@ TEST_F(ViewTreeNodeObserverTest, TreeChange_Reparent) {
namespace {
+class OrderChangeObserver : public ViewTreeNodeObserver {
+ public:
+ struct Change {
+ ViewTreeNode* node;
+ ViewTreeNode* relative_node;
+ OrderDirection direction;
+ DispositionChangePhase phase;
+ };
+ typedef std::vector<Change> Changes;
+
+ explicit OrderChangeObserver(ViewTreeNode* observee) : observee_(observee) {
+ observee_->AddObserver(this);
+ }
+ virtual ~OrderChangeObserver() {
+ observee_->RemoveObserver(this);
+ }
+
+ Changes GetAndClearChanges() {
+ Changes changes;
+ changes_.swap(changes);
+ return changes;
+ }
+
+ private:
+ // Overridden from ViewTreeNodeObserver:
+ virtual void OnNodeReordered(ViewTreeNode* node,
+ ViewTreeNode* relative_node,
+ OrderDirection direction,
+ DispositionChangePhase phase) OVERRIDE {
+ Change change;
+ change.node = node;
+ change.relative_node = relative_node;
+ change.direction = direction;
+ change.phase = phase;
+ changes_.push_back(change);
+ }
+
+ ViewTreeNode* observee_;
+ Changes changes_;
+
+ DISALLOW_COPY_AND_ASSIGN(OrderChangeObserver);
+};
+
+} // namespace
+
+TEST_F(ViewTreeNodeObserverTest, Order) {
+ TestViewTreeNode v1, v11, v12, v13;
+ v1.AddChild(&v11);
+ v1.AddChild(&v12);
+ v1.AddChild(&v13);
+
+ // Order: v11, v12, v13
+ EXPECT_EQ(3U, v1.children().size());
+ EXPECT_EQ(&v11, v1.children().front());
+ EXPECT_EQ(&v13, v1.children().back());
+
+ {
+ OrderChangeObserver observer(&v11);
+
+ // Move v11 to front.
+ // Resulting order: v12, v13, v11
+ v11.MoveToFront();
+ EXPECT_EQ(&v12, v1.children().front());
+ EXPECT_EQ(&v11, v1.children().back());
+
+ OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
+ EXPECT_EQ(2U, changes.size());
+ EXPECT_EQ(&v11, changes[0].node);
+ EXPECT_EQ(&v13, changes[0].relative_node);
+ EXPECT_EQ(ORDER_ABOVE, changes[0].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGING, changes[0].phase);
+
+ EXPECT_EQ(&v11, changes[1].node);
+ EXPECT_EQ(&v13, changes[1].relative_node);
+ EXPECT_EQ(ORDER_ABOVE, changes[1].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGED, changes[1].phase);
+ }
+
+ {
+ OrderChangeObserver observer(&v11);
+
+ // Move v11 to back.
+ // Resulting order: v11, v12, v13
+ v11.MoveToBack();
+ EXPECT_EQ(&v11, v1.children().front());
+ EXPECT_EQ(&v13, v1.children().back());
+
+ OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
+ EXPECT_EQ(2U, changes.size());
+ EXPECT_EQ(&v11, changes[0].node);
+ EXPECT_EQ(&v12, changes[0].relative_node);
+ EXPECT_EQ(ORDER_BELOW, changes[0].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGING, changes[0].phase);
+
+ EXPECT_EQ(&v11, changes[1].node);
+ EXPECT_EQ(&v12, changes[1].relative_node);
+ EXPECT_EQ(ORDER_BELOW, changes[1].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGED, changes[1].phase);
+ }
+
+ {
+ OrderChangeObserver observer(&v11);
+
+ // Move v11 above v12.
+ // Resulting order: v12. v11, v13
+ v11.Reorder(&v12, ORDER_ABOVE);
+ EXPECT_EQ(&v12, v1.children().front());
+ EXPECT_EQ(&v13, v1.children().back());
+
+ OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
+ EXPECT_EQ(2U, changes.size());
+ EXPECT_EQ(&v11, changes[0].node);
+ EXPECT_EQ(&v12, changes[0].relative_node);
+ EXPECT_EQ(ORDER_ABOVE, changes[0].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGING, changes[0].phase);
+
+ EXPECT_EQ(&v11, changes[1].node);
+ EXPECT_EQ(&v12, changes[1].relative_node);
+ EXPECT_EQ(ORDER_ABOVE, changes[1].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGED, changes[1].phase);
+ }
+
+ {
+ OrderChangeObserver observer(&v11);
+
+ // Move v11 below v12.
+ // Resulting order: v11, v12, v13
+ v11.Reorder(&v12, ORDER_BELOW);
+ EXPECT_EQ(&v11, v1.children().front());
+ EXPECT_EQ(&v13, v1.children().back());
+
+ OrderChangeObserver::Changes changes = observer.GetAndClearChanges();
+ EXPECT_EQ(2U, changes.size());
+ EXPECT_EQ(&v11, changes[0].node);
+ EXPECT_EQ(&v12, changes[0].relative_node);
+ EXPECT_EQ(ORDER_BELOW, changes[0].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGING, changes[0].phase);
+
+ EXPECT_EQ(&v11, changes[1].node);
+ EXPECT_EQ(&v12, changes[1].relative_node);
+ EXPECT_EQ(ORDER_BELOW, changes[1].direction);
+ EXPECT_EQ(ViewTreeNodeObserver::DISPOSITION_CHANGED, changes[1].phase);
+ }
+}
+
+namespace {
+
typedef std::vector<std::string> Changes;
std::string NodeIdToString(Id id) {
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 d3e6ddf..2d9527c 100644
--- a/mojo/services/public/cpp/view_manager/view_tree_node.h
+++ b/mojo/services/public/cpp/view_manager/view_tree_node.h
@@ -11,6 +11,7 @@
#include "base/observer_list.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/services/public/cpp/view_manager/view_manager_types.h"
+#include "mojo/services/public/interfaces/view_manager/view_manager_constants.mojom.h"
#include "ui/gfx/geometry/rect.h"
namespace mojo {
@@ -52,6 +53,10 @@ class ViewTreeNode {
void AddChild(ViewTreeNode* child);
void RemoveChild(ViewTreeNode* child);
+ void Reorder(ViewTreeNode* relative, OrderDirection direction);
+ void MoveToFront();
+ void MoveToBack();
+
bool Contains(ViewTreeNode* child) const;
ViewTreeNode* GetChildById(Id id);
@@ -76,6 +81,8 @@ class ViewTreeNode {
void LocalDestroy();
void LocalAddChild(ViewTreeNode* child);
void LocalRemoveChild(ViewTreeNode* child);
+ // Returns true if the order actually changed.
+ bool LocalReorder(ViewTreeNode* relative, OrderDirection direction);
void LocalSetActiveView(View* view);
void LocalSetBounds(const gfx::Rect& old_bounds, const gfx::Rect& new_bounds);
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 116e156..d39f748 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,8 @@
#include "base/basictypes.h"
+#include "mojo/services/public/cpp/view_manager/view_tree_node.h"
+
namespace gfx {
class Rect;
}
@@ -37,6 +39,11 @@ class ViewTreeNodeObserver {
virtual void OnTreeChange(const TreeChangeParams& params) {}
+ virtual void OnNodeReordered(ViewTreeNode* node,
+ ViewTreeNode* relative_node,
+ OrderDirection direction,
+ DispositionChangePhase phase) {}
+
virtual void OnNodeDestroy(ViewTreeNode* node,
DispositionChangePhase phase) {}
diff --git a/mojo/services/public/interfaces/view_manager/view_manager.mojom b/mojo/services/public/interfaces/view_manager/view_manager.mojom
index df40def..e782798 100644
--- a/mojo/services/public/interfaces/view_manager/view_manager.mojom
+++ b/mojo/services/public/interfaces/view_manager/view_manager.mojom
@@ -4,6 +4,7 @@
import "../geometry/geometry.mojom"
import "../input_events/input_events.mojom"
+import "view_manager_constants.mojom"
module mojo.view_manager {
@@ -72,6 +73,15 @@ interface IViewManager {
RemoveNodeFromParent(uint32 node_id,
uint32 server_change_id) => (bool success);
+ // Reorders a node in its parent, relative to |relative_node_id| according to
+ // |direction|.
+ // Only the connection that created the node's parent can reorder its
+ // children.
+ ReorderNode(uint32 node_id,
+ uint32 relative_node_id,
+ OrderDirection direction,
+ uint32 server_change_id) => (bool success);
+
// Returns the nodes comprising the tree starting at |node_id|. |node_id| is
// the first result in the return value, unless |node_id| is invalid, in which
// case an empty vector is returned. The nodes are visited using a depth first
@@ -148,6 +158,12 @@ interface IViewManagerClient {
uint32 server_change_id,
INode[] nodes);
+ // Invoked when the order of nodes within a parent changes.
+ OnNodeReordered(uint32 node_id,
+ uint32 relative_node_id,
+ OrderDirection direction,
+ uint32 server_change_id);
+
// Invoked when a node is deleted.
OnNodeDeleted(uint32 node, uint32 server_change_id);
diff --git a/mojo/services/public/interfaces/view_manager/view_manager_constants.mojom b/mojo/services/public/interfaces/view_manager/view_manager_constants.mojom
new file mode 100644
index 0000000..5c73190
--- /dev/null
+++ b/mojo/services/public/interfaces/view_manager/view_manager_constants.mojom
@@ -0,0 +1,12 @@
+// Copyright 2014 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.
+
+module mojo.view_manager {
+
+enum OrderDirection {
+ ORDER_ABOVE = 1,
+ ORDER_BELOW,
+};
+
+}
diff --git a/mojo/services/view_manager/node.cc b/mojo/services/view_manager/node.cc
index 208c9c7..cbdd16d 100644
--- a/mojo/services/view_manager/node.cc
+++ b/mojo/services/view_manager/node.cc
@@ -58,6 +58,13 @@ void Node::Remove(Node* child) {
window_.RemoveChild(&child->window_);
}
+void Node::Reorder(Node* child, Node* relative, OrderDirection direction) {
+ if (direction == ORDER_ABOVE)
+ window_.StackChildAbove(child->window(), relative->window());
+ else if (direction == ORDER_BELOW)
+ window_.StackChildBelow(child->window(), relative->window());
+}
+
const Node* Node::GetRoot() const {
const aura::Window* window = &window_;
while (window && window->parent())
diff --git a/mojo/services/view_manager/node.h b/mojo/services/view_manager/node.h
index 533bc3b..bfee675 100644
--- a/mojo/services/view_manager/node.h
+++ b/mojo/services/view_manager/node.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/logging.h"
+#include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h"
#include "mojo/services/view_manager/ids.h"
#include "mojo/services/view_manager/view_manager_export.h"
#include "ui/aura/window.h"
@@ -37,6 +38,8 @@ class MOJO_VIEW_MANAGER_EXPORT Node
void Add(Node* child);
void Remove(Node* child);
+ void Reorder(Node* child, Node* relative, OrderDirection direction);
+
aura::Window* window() { return &window_; }
const gfx::Rect& bounds() const { return window_.bounds(); }
diff --git a/mojo/services/view_manager/root_node_manager.cc b/mojo/services/view_manager/root_node_manager.cc
index ea6cb2c..0d87d38 100644
--- a/mojo/services/view_manager/root_node_manager.cc
+++ b/mojo/services/view_manager/root_node_manager.cc
@@ -151,6 +151,17 @@ void RootNodeManager::ProcessNodeHierarchyChanged(const Node* node,
}
}
+void RootNodeManager::ProcessNodeReorder(const Node* node,
+ const Node* relative_node,
+ const OrderDirection direction) {
+ for (ConnectionMap::iterator i = connection_map_.begin();
+ i != connection_map_.end(); ++i) {
+ i->second->ProcessNodeReorder(
+ node, relative_node, direction, next_server_change_id_,
+ IsChangeSource(i->first));
+ }
+}
+
void RootNodeManager::ProcessNodeViewReplaced(const Node* node,
const View* new_view,
const View* old_view) {
diff --git a/mojo/services/view_manager/root_node_manager.h b/mojo/services/view_manager/root_node_manager.h
index 93988a5..5ade95a 100644
--- a/mojo/services/view_manager/root_node_manager.h
+++ b/mojo/services/view_manager/root_node_manager.h
@@ -137,6 +137,9 @@ class MOJO_VIEW_MANAGER_EXPORT RootNodeManager : public NodeDelegate {
void ProcessNodeHierarchyChanged(const Node* node,
const Node* new_parent,
const Node* old_parent);
+ void ProcessNodeReorder(const Node* node,
+ const Node* relative_node,
+ const OrderDirection direction);
void ProcessNodeViewReplaced(const Node* node,
const View* new_view_id,
const View* old_view_id);
diff --git a/mojo/services/view_manager/test_change_tracker.cc b/mojo/services/view_manager/test_change_tracker.cc
index 133c171..4260edd 100644
--- a/mojo/services/view_manager/test_change_tracker.cc
+++ b/mojo/services/view_manager/test_change_tracker.cc
@@ -26,6 +26,10 @@ std::string RectToString(const gfx::Rect& rect) {
rect.height());
}
+std::string DirectionToString(OrderDirection direction) {
+ return direction == ORDER_ABOVE ? "above" : "below";
+}
+
std::string ChangeToDescription1(const Change& change) {
switch (change.type) {
case CHANGE_TYPE_CONNECTION_ESTABLISHED:
@@ -55,6 +59,14 @@ std::string ChangeToDescription1(const Change& change) {
NodeIdToString(change.node_id2).c_str(),
NodeIdToString(change.node_id3).c_str());
+ case CHANGE_TYPE_NODE_REORDERED:
+ return base::StringPrintf(
+ "Reordered change_id=%d node=%s relative=%s direction=%s",
+ static_cast<int>(change.change_id),
+ NodeIdToString(change.node_id).c_str(),
+ NodeIdToString(change.node_id2).c_str(),
+ DirectionToString(change.direction).c_str());
+
case CHANGE_TYPE_NODE_DELETED:
return base::StringPrintf("NodeDeleted change_id=%d node=%s",
static_cast<int>(change.change_id),
@@ -119,7 +131,8 @@ Change::Change()
node_id3(0),
view_id(0),
view_id2(0),
- event_action(0) {}
+ event_action(0),
+ direction(ORDER_ABOVE) {}
Change::~Change() {
}
@@ -185,6 +198,19 @@ void TestChangeTracker::OnNodeHierarchyChanged(Id node_id,
AddChange(change);
}
+void TestChangeTracker::OnNodeReordered(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id) {
+ Change change;
+ change.type = CHANGE_TYPE_NODE_REORDERED;
+ change.node_id = node_id;
+ change.node_id2 = relative_node_id;
+ change.direction = direction;
+ change.change_id = server_change_id;
+ AddChange(change);
+}
+
void TestChangeTracker::OnNodeDeleted(Id node_id, Id server_change_id) {
Change change;
change.type = CHANGE_TYPE_NODE_DELETED;
diff --git a/mojo/services/view_manager/test_change_tracker.h b/mojo/services/view_manager/test_change_tracker.h
index ef0c002..fbea61d 100644
--- a/mojo/services/view_manager/test_change_tracker.h
+++ b/mojo/services/view_manager/test_change_tracker.h
@@ -23,6 +23,7 @@ enum ChangeType {
CHANGE_TYPE_SERVER_CHANGE_ID_ADVANCED,
CHANGE_TYPE_NODE_BOUNDS_CHANGED,
CHANGE_TYPE_NODE_HIERARCHY_CHANGED,
+ CHANGE_TYPE_NODE_REORDERED,
CHANGE_TYPE_NODE_DELETED,
CHANGE_TYPE_VIEW_DELETED,
CHANGE_TYPE_VIEW_REPLACED,
@@ -57,6 +58,7 @@ struct Change {
gfx::Rect bounds2;
int32 event_action;
String creator_url;
+ OrderDirection direction;
};
// Converts Changes to string descriptions.
@@ -106,6 +108,10 @@ class TestChangeTracker {
Id old_parent_id,
Id server_change_id,
Array<INodePtr> nodes);
+ void OnNodeReordered(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id);
void OnNodeDeleted(Id node_id, Id server_change_id);
void OnViewDeleted(Id view_id);
void OnNodeViewReplaced(Id node_id, Id new_view_id, Id old_view_id);
diff --git a/mojo/services/view_manager/view_manager_connection.cc b/mojo/services/view_manager/view_manager_connection.cc
index 8d4d0a6..0c724bd 100644
--- a/mojo/services/view_manager/view_manager_connection.cc
+++ b/mojo/services/view_manager/view_manager_connection.cc
@@ -170,6 +170,23 @@ void ViewManagerConnection::ProcessNodeHierarchyChanged(
NodesToINodes(to_send));
}
+void ViewManagerConnection::ProcessNodeReorder(const Node* node,
+ const Node* relative_node,
+ OrderDirection direction,
+ Id server_change_id,
+ bool originated_change) {
+ if (originated_change ||
+ !known_nodes_.count(NodeIdToTransportId(node->id())) ||
+ !known_nodes_.count(NodeIdToTransportId(relative_node->id()))) {
+ return;
+ }
+
+ client()->OnNodeReordered(NodeIdToTransportId(node->id()),
+ NodeIdToTransportId(relative_node->id()),
+ direction,
+ server_change_id);
+}
+
void ViewManagerConnection::ProcessNodeViewReplaced(
const Node* node,
const View* new_view,
@@ -267,6 +284,36 @@ bool ViewManagerConnection::CanAddNode(const Node* parent,
return (IsNodeDescendantOfRoots(child) || child->id().connection_id == id_);
}
+bool ViewManagerConnection::CanReorderNode(const Node* node,
+ const Node* relative_node,
+ OrderDirection direction) const {
+ if (!node || !relative_node)
+ return false;
+
+ if (node->id().connection_id != id_)
+ return false;
+
+ const Node* parent = node->GetParent();
+ if (!parent || parent != relative_node->GetParent())
+ return false;
+
+ if (known_nodes_.count(NodeIdToTransportId(parent->id())) == 0)
+ return false;
+
+ std::vector<const Node*> children = parent->GetChildren();
+ const size_t child_i =
+ std::find(children.begin(), children.end(), node) - children.begin();
+ const size_t target_i =
+ std::find(children.begin(), children.end(), relative_node) -
+ children.begin();
+ if ((direction == ORDER_ABOVE && child_i == target_i + 1) ||
+ (direction == ORDER_BELOW && child_i + 1 == target_i)) {
+ return false;
+ }
+
+ return true;
+}
+
bool ViewManagerConnection::CanDeleteNode(const NodeId& node_id) const {
return node_id.connection_id == id_;
}
@@ -553,6 +600,27 @@ void ViewManagerConnection::RemoveNodeFromParent(
callback.Run(success);
}
+void ViewManagerConnection::ReorderNode(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id,
+ const Callback<void(bool)>& callback) {
+ bool success = false;
+ if (server_change_id == root_node_manager_->next_server_change_id()) {
+ Node* node = GetNode(NodeIdFromTransportId(node_id));
+ Node* relative_node = GetNode(NodeIdFromTransportId(relative_node_id));
+ if (CanReorderNode(node, relative_node, direction)) {
+ success = true;
+ RootNodeManager::ScopedChange change(
+ this, root_node_manager_,
+ RootNodeManager::CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, false);
+ node->GetParent()->Reorder(node, relative_node, direction);
+ root_node_manager_->ProcessNodeReorder(node, relative_node, direction);
+ }
+ }
+ callback.Run(success);
+}
+
void ViewManagerConnection::GetNodeTree(
Id node_id,
const Callback<void(Array<INodePtr>)>& callback) {
diff --git a/mojo/services/view_manager/view_manager_connection.h b/mojo/services/view_manager/view_manager_connection.h
index b9eae90..b2f326b 100644
--- a/mojo/services/view_manager/view_manager_connection.h
+++ b/mojo/services/view_manager/view_manager_connection.h
@@ -86,6 +86,11 @@ class MOJO_VIEW_MANAGER_EXPORT ViewManagerConnection
const Node* old_parent,
Id server_change_id,
bool originated_change);
+ void ProcessNodeReorder(const Node* node,
+ const Node* relative_node,
+ OrderDirection direction,
+ Id server_change_id,
+ bool originated_change);
void ProcessNodeViewReplaced(const Node* node,
const View* new_view,
const View* old_view,
@@ -110,6 +115,9 @@ class MOJO_VIEW_MANAGER_EXPORT ViewManagerConnection
// for this connection.
bool CanRemoveNodeFromParent(const Node* node) const;
bool CanAddNode(const Node* parent, const Node* child) const;
+ bool CanReorderNode(const Node* node,
+ const Node* relative_node,
+ OrderDirection direction) const;
bool CanDeleteNode(const NodeId& node_id) const;
bool CanDeleteView(const ViewId& view_id) const;
bool CanSetView(const Node* node, const ViewId& view_id) const;
@@ -170,6 +178,11 @@ class MOJO_VIEW_MANAGER_EXPORT ViewManagerConnection
Id node_id,
Id server_change_id,
const Callback<void(bool)>& callback) OVERRIDE;
+ virtual void ReorderNode(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id,
+ const Callback<void(bool)>& callback) OVERRIDE;
virtual void GetNodeTree(
Id node_id,
const Callback<void(Array<INodePtr>)>& callback) OVERRIDE;
diff --git a/mojo/services/view_manager/view_manager_connection_unittest.cc b/mojo/services/view_manager/view_manager_connection_unittest.cc
index 4f5d1c9..d9280d8 100644
--- a/mojo/services/view_manager/view_manager_connection_unittest.cc
+++ b/mojo/services/view_manager/view_manager_connection_unittest.cc
@@ -22,6 +22,7 @@
#include "mojo/services/public/cpp/view_manager/util.h"
#include "mojo/services/public/cpp/view_manager/view_manager_types.h"
#include "mojo/services/public/interfaces/view_manager/view_manager.mojom.h"
+#include "mojo/services/view_manager/ids.h"
#include "mojo/services/view_manager/test_change_tracker.h"
#include "mojo/shell/shell_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -112,6 +113,19 @@ class ViewManagerProxy : public TestChangeTracker::Delegate {
RunMainLoop();
return result;
}
+ bool ReorderNode(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id) {
+ changes_.clear();
+ bool result = false;
+ view_manager_->ReorderNode(node_id, relative_node_id, direction,
+ server_change_id,
+ base::Bind(&ViewManagerProxy::GotResult,
+ base::Unretained(this), &result));
+ RunMainLoop();
+ return result;
+ }
bool SetView(Id node_id, Id view_id) {
changes_.clear();
bool result = false;
@@ -305,6 +319,13 @@ class TestViewManagerClientConnection
tracker_.OnNodeHierarchyChanged(node, new_parent, old_parent,
server_change_id, nodes.Pass());
}
+ virtual void OnNodeReordered(Id node_id,
+ Id relative_node_id,
+ OrderDirection direction,
+ Id server_change_id) OVERRIDE {
+ tracker_.OnNodeReordered(node_id, relative_node_id, direction,
+ server_change_id);
+ }
virtual void OnNodeDeleted(Id node, Id server_change_id) OVERRIDE {
tracker_.OnNodeDeleted(node, server_change_id);
}
@@ -758,6 +779,84 @@ TEST_F(ViewManagerConnectionTest, NodeHierarchyChangedAddingKnownToUnknown) {
}
}
+TEST_F(ViewManagerConnectionTest, ReorderNode) {
+ Id node1_id = BuildNodeId(1, 1);
+ Id node2_id = BuildNodeId(1, 2);
+ Id node3_id = BuildNodeId(1, 3);
+ Id node4_id = BuildNodeId(1, 4); // Peer to 1,1
+ Id node5_id = BuildNodeId(1, 5); // Peer to 1,1
+ Id node6_id = BuildNodeId(1, 6); // Child of 1,2.
+ Id node7_id = BuildNodeId(1, 7); // Unparented.
+ Id node8_id = BuildNodeId(1, 8); // Unparented.
+ ASSERT_TRUE(connection_->CreateNode(node1_id));
+ ASSERT_TRUE(connection_->CreateNode(node2_id));
+ ASSERT_TRUE(connection_->CreateNode(node3_id));
+ ASSERT_TRUE(connection_->CreateNode(node4_id));
+ ASSERT_TRUE(connection_->CreateNode(node5_id));
+ ASSERT_TRUE(connection_->CreateNode(node6_id));
+ ASSERT_TRUE(connection_->CreateNode(node7_id));
+ ASSERT_TRUE(connection_->CreateNode(node8_id));
+ ASSERT_TRUE(connection_->AddNode(node1_id, node2_id, 1));
+ ASSERT_TRUE(connection_->AddNode(node2_id, node6_id, 2));
+ ASSERT_TRUE(connection_->AddNode(node1_id, node3_id, 3));
+ ASSERT_TRUE(connection_->AddNode(
+ NodeIdToTransportId(RootNodeId()), node4_id, 4));
+ ASSERT_TRUE(connection_->AddNode(
+ NodeIdToTransportId(RootNodeId()), node5_id, 5));
+
+ ASSERT_NO_FATAL_FAILURE(EstablishSecondConnection(false));
+
+ {
+ connection_->ReorderNode(node2_id, node3_id, ORDER_ABOVE, 6);
+
+ connection2_->DoRunLoopUntilChangesCount(1);
+ const Changes changes(ChangesToDescription1(connection2_->changes()));
+ ASSERT_EQ(1u, changes.size());
+ EXPECT_EQ(
+ "Reordered change_id=6 node=1,2 relative=1,3 direction=above",
+ changes[0]);
+ }
+
+ {
+ connection_->ReorderNode(node2_id, node3_id, ORDER_BELOW, 7);
+
+ connection2_->DoRunLoopUntilChangesCount(1);
+ const Changes changes(ChangesToDescription1(connection2_->changes()));
+ ASSERT_EQ(1u, changes.size());
+ EXPECT_EQ(
+ "Reordered change_id=7 node=1,2 relative=1,3 direction=below",
+ changes[0]);
+ }
+
+ {
+ // node2 is already below node3.
+ EXPECT_FALSE(connection_->ReorderNode(node2_id, node3_id, ORDER_BELOW, 8));
+ }
+
+ {
+ // node4 & 5 are unknown to connection2_.
+ EXPECT_FALSE(connection2_->ReorderNode(node4_id, node5_id, ORDER_ABOVE, 8));
+ }
+
+ {
+ // node6 & node3 have different parents.
+ EXPECT_FALSE(connection_->ReorderNode(node3_id, node6_id, ORDER_ABOVE, 8));
+ }
+
+ {
+ // Non-existent node-ids
+ EXPECT_FALSE(connection_->ReorderNode(BuildNodeId(1, 27),
+ BuildNodeId(1, 28),
+ ORDER_ABOVE,
+ 8));
+ }
+
+ {
+ // node7 & node8 are un-parented.
+ EXPECT_FALSE(connection_->ReorderNode(node7_id, node8_id, ORDER_ABOVE, 8));
+ }
+}
+
// Verifies DeleteNode works.
TEST_F(ViewManagerConnectionTest, DeleteNode) {
ASSERT_TRUE(connection_->CreateNode(BuildNodeId(1, 2)));