Index: mojo/services/view_manager/connection_manager.cc |
diff --git a/mojo/services/view_manager/connection_manager.cc b/mojo/services/view_manager/connection_manager.cc |
index c80c1a30ebeef0f55569f07ca0152a33af097a34..846a80c60f3e70211af1ff076769ae92c1863301 100644 |
--- a/mojo/services/view_manager/connection_manager.cc |
+++ b/mojo/services/view_manager/connection_manager.cc |
@@ -12,10 +12,86 @@ |
#include "mojo/services/view_manager/client_connection.h" |
#include "mojo/services/view_manager/connection_manager_delegate.h" |
#include "mojo/services/view_manager/display_manager.h" |
+#include "mojo/services/view_manager/server_view.h" |
+#include "mojo/services/view_manager/view_coordinate_conversions.h" |
#include "mojo/services/view_manager/view_manager_service_impl.h" |
namespace mojo { |
namespace service { |
+namespace { |
+ |
+// Creates a copy of |view|. The copied view has |delegate| as its delegate. |
+// This does not recurse. |
+ServerView* CloneView(const ServerView* view, ServerViewDelegate* delegate) { |
+ ServerView* clone = new ServerView(delegate, ClonedViewId()); |
msw
2014/11/18 23:37:42
q: should the clone copy any/all ServerView::prope
sky
2014/11/19 00:49:39
Yes, I missed opacity. No need to visibility as we
msw
2014/11/19 01:27:51
Good catch, but I was wondering about the std::map
sky
2014/11/19 03:28:17
In theory those shouldn't matter as the only possi
msw
2014/11/19 18:18:29
Acknowledged.
|
+ clone->SetBounds(view->bounds()); |
+ clone->SetSurfaceId(view->surface_id()); |
+ return clone; |
+} |
+ |
+// Creates copies of all the visible children of |parent|. Newly cloned views |
+// are |
msw
2014/11/18 23:37:42
nit: fix line break
sky
2014/11/19 00:49:39
Done.
|
+// added to |cloned_parent| and have |delegate| as their delegate. |
+void CloneAllViews(const ServerView* parent, |
msw
2014/11/18 23:37:42
nit: CloneViewTree?
sky
2014/11/19 00:49:39
Done.
|
+ ServerView* cloned_parent, |
+ ServerViewDelegate* delegate) { |
+ DCHECK(parent->visible()); |
+ for (const ServerView* to_clone : parent->GetChildren()) { |
msw
2014/11/18 23:37:42
q: will cloned views preserve the ordering of the
sky
2014/11/19 00:49:39
Yes. I added a comment indicating this.
|
+ if (to_clone->visible()) { |
+ ServerView* cloned = CloneView(to_clone, delegate); |
+ cloned_parent->Add(cloned); |
+ CloneAllViews(to_clone, cloned, delegate); |
+ } |
+ } |
+} |
+ |
+// Recurses through all the children of |view| moving any cloned views to |
+// |add_to| stacked above |stack_above|. |stack_above| is updated as views are |
+// moved. |
+void ReparentClonedViews(ServerView* add_to, |
msw
2014/11/18 23:37:41
nit: s/add_to/new_parent/?
sky
2014/11/19 00:49:39
Done.
|
+ ServerView** stack_above, |
+ ServerView* view) { |
+ if (view->id() == ClonedViewId()) { |
+ const gfx::Rect new_bounds(ConvertRectBetweenViews( |
+ view, add_to, gfx::Rect(view->bounds().size()))); |
+ add_to->Add(view); |
+ add_to->Reorder(view, *stack_above, ORDER_DIRECTION_ABOVE); |
+ view->SetBounds(new_bounds); |
+ *stack_above = view; |
+ return; |
+ } |
+ |
+ for (ServerView* child : view->GetChildren()) |
+ ReparentClonedViews(add_to, stack_above, child); |
+} |
+ |
+// Deletes |view| and all its descendants. |
+void DeleteAllViews(ServerView* view) { |
msw
2014/11/18 23:37:41
nit: DeleteViewTree?
sky
2014/11/19 00:49:39
Done.
|
+ for (ServerView* child : view->GetChildren()) |
+ DeleteAllViews(child); |
+ |
+ delete view; |
+} |
+ |
+// TODO(sky): nuke, proof of concept. |
+bool DecrementAnimatingViewsOpacity(ServerView* view) { |
+ if (view->id() == ClonedViewId()) { |
+ const float new_opacity = view->opacity() - .05f; |
+ if (new_opacity <= 0) |
+ DeleteAllViews(view); |
+ else |
+ view->SetOpacity(new_opacity); |
+ return true; |
+ } |
+ bool ret_value = false; |
+ for (ServerView* child : view->GetChildren()) { |
+ if (DecrementAnimatingViewsOpacity(child)) |
+ ret_value = true; |
+ } |
+ return ret_value; |
+} |
+ |
+} // namespace |
ConnectionManager::ScopedChange::ScopedChange( |
ViewManagerServiceImpl* connection, |
@@ -82,8 +158,8 @@ void ConnectionManager::OnConnectionError(ClientConnection* connection) { |
void ConnectionManager::EmbedAtView( |
ConnectionSpecificId creator_id, |
- const String& url, |
- Id transport_view_id, |
+ const std::string& url, |
+ const ViewId& view_id, |
InterfaceRequest<ServiceProvider> service_provider) { |
std::string creator_url; |
ConnectionMap::const_iterator it = connection_map_.find(creator_id); |
@@ -92,8 +168,7 @@ void ConnectionManager::EmbedAtView( |
ClientConnection* client_connection = |
delegate_->CreateClientConnectionForEmbedAtView( |
- this, creator_id, creator_url, url.To<std::string>(), |
- ViewIdFromTransportId(transport_view_id)); |
+ this, creator_id, creator_url, url, view_id); |
AddConnection(client_connection); |
client_connection->service()->Init(client_connection->client(), |
service_provider.Pass()); |
@@ -142,6 +217,21 @@ void ConnectionManager::SetWindowManagerClientConnection( |
InterfaceRequest<ServiceProvider>()); |
} |
+bool ConnectionManager::CloneAndAnimate(const ViewId& view_id) { |
+ ServerView* view = GetView(view_id); |
+ if (!view || !view->IsDrawn(root_.get()) || view == root_.get()) |
+ return false; |
+ if (!animation_timer_.IsRunning()) { |
+ animation_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(100), |
+ this, &ConnectionManager::DoAnimation); |
+ } |
+ ServerView* clone = CloneView(view, this); |
+ CloneAllViews(view, clone, this); |
+ view->parent()->Add(clone); |
+ view->parent()->Reorder(clone, view, ORDER_DIRECTION_ABOVE); |
+ return true; |
+} |
+ |
void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view, |
const gfx::Rect& old_bounds, |
const gfx::Rect& new_bounds) { |
@@ -199,22 +289,41 @@ void ConnectionManager::FinishChange() { |
current_change_ = NULL; |
} |
+void ConnectionManager::DoAnimation() { |
+ if (!DecrementAnimatingViewsOpacity(root())) |
+ animation_timer_.Stop(); |
+} |
+ |
void ConnectionManager::AddConnection(ClientConnection* connection) { |
DCHECK_EQ(0u, connection_map_.count(connection->service()->id())); |
connection_map_[connection->service()->id()] = connection; |
} |
+void ConnectionManager::OnWillDestroyView(ServerView* view) { |
+ if (!in_destructor_ && root_->Contains(view) && view != root_.get() && |
msw
2014/11/18 23:37:42
Add a comment here explaining why this is useful,
|
+ view->id() != ClonedViewId()) { |
+ ServerView* parent_above = view; |
+ ReparentClonedViews(view->parent(), &parent_above, view); |
msw
2014/11/18 23:37:41
Add a comment here explaining why this is useful,
msw
2014/11/18 23:37:42
I worry a bit about potential performance implicat
sky
2014/11/19 00:49:39
The bubbling at most happens for the depth of the
msw
2014/11/19 01:27:51
Acknowledged.
|
+ } |
+} |
+ |
void ConnectionManager::OnViewDestroyed(const ServerView* view) { |
if (!in_destructor_) |
ProcessViewDeleted(view->id()); |
} |
-void ConnectionManager::OnWillChangeViewHierarchy( |
- const ServerView* view, |
- const ServerView* new_parent, |
- const ServerView* old_parent) { |
- if (!in_destructor_) |
- ProcessWillChangeViewHierarchy(view, new_parent, old_parent); |
+void ConnectionManager::OnWillChangeViewHierarchy(ServerView* view, |
+ ServerView* new_parent, |
+ ServerView* old_parent) { |
+ if (view->id() == ClonedViewId() || in_destructor_) |
+ return; |
+ |
+ if (root_->Contains(view) && view != root_.get()) { |
+ ServerView* parent_above = view; |
+ ReparentClonedViews(view->parent(), &parent_above, view); |
msw
2014/11/18 23:37:42
I'm confused; does this reparent cloned views to |
sky
2014/11/19 00:49:39
Added similar comment to above, let me know if sti
msw
2014/11/19 01:27:51
I guess it makes sense, re-parenting an ancestor o
sky
2014/11/19 03:28:17
I think we'll just have to see how this pans out.
msw
2014/11/19 18:18:29
Acknowledged.
|
+ } |
+ |
+ ProcessWillChangeViewHierarchy(view, new_parent, old_parent); |
} |
void ConnectionManager::OnViewHierarchyChanged(const ServerView* view, |
@@ -263,10 +372,17 @@ void ConnectionManager::OnViewReordered(const ServerView* view, |
display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size())); |
} |
-void ConnectionManager::OnWillChangeViewVisibility(const ServerView* view) { |
+void ConnectionManager::OnWillChangeViewVisibility(ServerView* view) { |
if (in_destructor_) |
return; |
+ if (view != root_.get() && view->id() != ClonedViewId() && |
+ root_->Contains(view) && view->IsDrawn(root_.get())) { |
+ // View is going to hide. Promote any cloned views. |
+ ServerView* parent_above = view; |
+ ReparentClonedViews(view->parent(), &parent_above, view); |
+ } |
+ |
for (auto& pair : connection_map_) { |
pair.second->service()->ProcessWillChangeViewVisibility( |
view, IsChangeSource(pair.first)); |
@@ -283,9 +399,9 @@ void ConnectionManager::OnViewSharedPropertyChanged( |
} |
} |
-void ConnectionManager::SetViewportSize(SizePtr size) { |
- gfx::Size new_size = size.To<gfx::Size>(); |
- display_manager_->SetViewportSize(new_size); |
+void ConnectionManager::OnScheduleViewPaint(const ServerView* view) { |
+ if (!in_destructor_) |
+ display_manager_->SchedulePaint(view, gfx::Rect(view->bounds().size())); |
} |
void ConnectionManager::DispatchInputEventToView(Id transport_view_id, |
@@ -301,5 +417,15 @@ void ConnectionManager::DispatchInputEventToView(Id transport_view_id, |
} |
} |
+void ConnectionManager::SetViewportSize(SizePtr size) { |
+ gfx::Size new_size = size.To<gfx::Size>(); |
+ display_manager_->SetViewportSize(new_size); |
+} |
+ |
+void ConnectionManager::CloneAndAnimate(Id transport_view_id, |
+ const Callback<void(bool)>& callback) { |
+ callback.Run(CloneAndAnimate(ViewIdFromTransportId(transport_view_id))); |
msw
2014/11/18 23:37:42
Add a comment describing the expected lifetime of
msw
2014/11/18 23:37:42
optional nit: it might be more straightforward to
sky
2014/11/19 00:49:39
This code is all going to change drastically (see
msw
2014/11/19 01:27:51
Acknowledged.
|
+} |
+ |
} // namespace service |
} // namespace mojo |