Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1635)

Unified Diff: mojo/services/view_manager/cpp/lib/view_manager_client_impl.cc

Issue 1536713004: Revert "Delete the ViewManager and WindowManager services." (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: mojo/services/view_manager/cpp/lib/view_manager_client_impl.cc
diff --git a/mojo/services/view_manager/cpp/lib/view_manager_client_impl.cc b/mojo/services/view_manager/cpp/lib/view_manager_client_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6852f660dcd1bb6cbff39c935f7905061b4053d1
--- /dev/null
+++ b/mojo/services/view_manager/cpp/lib/view_manager_client_impl.cc
@@ -0,0 +1,494 @@
+// 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.
+
+#include "view_manager/cpp/lib/view_manager_client_impl.h"
+
+#include "mojo/public/cpp/application/application_impl.h"
+#include "mojo/public/cpp/application/connect.h"
+#include "mojo/public/cpp/application/service_provider_impl.h"
+#include "mojo/public/interfaces/application/service_provider.mojom.h"
+#include "mojo/public/interfaces/application/shell.mojom.h"
+#include "view_manager/cpp/lib/view_private.h"
+#include "view_manager/cpp/util.h"
+#include "view_manager/cpp/view_manager_delegate.h"
+#include "view_manager/cpp/view_observer.h"
+
+namespace mojo {
+
+Id MakeTransportId(ConnectionSpecificId connection_id,
+ ConnectionSpecificId local_id) {
+ return (connection_id << 16) | local_id;
+}
+
+// Helper called to construct a local view object from transport data.
+View* AddViewToViewManager(ViewManagerClientImpl* client,
+ View* parent,
+ const ViewDataPtr& view_data) {
+ // We don't use the ctor that takes a ViewManager here, since it will call
+ // back to the service and attempt to create a new view.
+ View* view = ViewPrivate::LocalCreate();
+ ViewPrivate private_view(view);
+ private_view.set_view_manager(client);
+ private_view.set_id(view_data->view_id);
+ private_view.set_visible(view_data->visible);
+ private_view.set_drawn(view_data->drawn);
+ private_view.LocalSetViewportMetrics(ViewportMetrics(),
+ *view_data->viewport_metrics);
+ private_view.set_properties(
+ view_data->properties.To<std::map<std::string, std::vector<uint8_t>>>());
+ client->AddView(view);
+ private_view.LocalSetBounds(Rect(), *view_data->bounds);
+ if (parent)
+ ViewPrivate(parent).LocalAddChild(view);
+ return view;
+}
+
+View* BuildViewTree(ViewManagerClientImpl* client,
+ const Array<ViewDataPtr>& views,
+ View* initial_parent) {
+ std::vector<View*> parents;
+ View* root = NULL;
+ View* last_view = NULL;
+ if (initial_parent)
+ parents.push_back(initial_parent);
+ for (size_t i = 0; i < views.size(); ++i) {
+ if (last_view && views[i]->parent_id == last_view->id()) {
+ parents.push_back(last_view);
+ } else if (!parents.empty()) {
+ while (parents.back()->id() != views[i]->parent_id)
+ parents.pop_back();
+ }
+ View* view = AddViewToViewManager(
+ client, !parents.empty() ? parents.back() : NULL, views[i]);
+ if (!last_view)
+ root = view;
+ last_view = view;
+ }
+ return root;
+}
+
+// Responsible for removing a root from the ViewManager when that view is
+// destroyed.
+class RootObserver : public ViewObserver {
+ public:
+ explicit RootObserver(View* root) : root_(root) {}
+ ~RootObserver() override {}
+
+ private:
+ // Overridden from ViewObserver:
+ void OnViewDestroyed(View* view) override {
+ DCHECK_EQ(view, root_);
+ static_cast<ViewManagerClientImpl*>(root_->view_manager())
+ ->RootDestroyed(root_);
+ view->RemoveObserver(this);
+ delete this;
+ }
+
+ View* root_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(RootObserver);
+};
+
+ViewManagerClientImpl::ViewManagerClientImpl(
+ ViewManagerDelegate* delegate,
+ Shell* shell,
+ InterfaceRequest<ViewManagerClient> request,
+ bool delete_on_error)
+ : connection_id_(0),
+ next_id_(1),
+ delegate_(delegate),
+ root_(nullptr),
+ capture_view_(nullptr),
+ focused_view_(nullptr),
+ activated_view_(nullptr),
+ wm_observer_binding_(this),
+ binding_(this, request.Pass()) {
+ if (delete_on_error)
+ binding_.set_connection_error_handler([this]() { delete this; });
+}
+
+ViewManagerClientImpl::~ViewManagerClientImpl() {
+ std::vector<View*> non_owned;
+ while (!views_.empty()) {
+ IdToViewMap::iterator it = views_.begin();
+ if (OwnsView(it->second->id())) {
+ it->second->Destroy();
+ } else {
+ non_owned.push_back(it->second);
+ views_.erase(it);
+ }
+ }
+ // Delete the non-owned views last. In the typical case these are roots. The
+ // exception is the window manager, which may know aboutother random views
+ // that it doesn't own.
+ // NOTE: we manually delete as we're a friend.
+ for (size_t i = 0; i < non_owned.size(); ++i)
+ delete non_owned[i];
+
+ delegate_->OnViewManagerDisconnected(this);
+}
+
+void ViewManagerClientImpl::DestroyView(Id view_id) {
+ DCHECK(service_);
+ service_->DeleteView(view_id, ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) {
+ DCHECK(service_);
+ service_->AddView(parent_id, child_id, ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) {
+ DCHECK(service_);
+ service_->RemoveViewFromParent(child_id, ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::Reorder(Id view_id,
+ Id relative_view_id,
+ OrderDirection direction) {
+ DCHECK(service_);
+ service_->ReorderView(view_id, relative_view_id, direction,
+ ActionCompletedCallback());
+}
+
+bool ViewManagerClientImpl::OwnsView(Id id) const {
+ return HiWord(id) == connection_id_;
+}
+
+void ViewManagerClientImpl::SetBounds(Id view_id, const Rect& bounds) {
+ DCHECK(service_);
+ service_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) {
+ DCHECK(service_);
+ if (surface_id.is_null())
+ return;
+ service_->SetViewSurfaceId(view_id, surface_id.Pass(),
+ ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::SetFocus(Id view_id) {
+ // In order for us to get here we had to have exposed a view, which implies we
+ // got a connection.
+ DCHECK(service_);
+ service_->PerformAction(view_id, "focus", ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) {
+ DCHECK(service_);
+ service_->SetViewVisibility(view_id, visible, ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::SetProperty(Id view_id,
+ const std::string& name,
+ const std::vector<uint8_t>& data) {
+ DCHECK(service_);
+ service_->SetViewProperty(view_id, String(name), Array<uint8_t>::From(data),
+ ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::Embed(const String& url, Id view_id) {
+ Embed(url, view_id, nullptr, nullptr);
+}
+
+void ViewManagerClientImpl::Embed(const String& url,
+ Id view_id,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services) {
+ DCHECK(service_);
+ service_->EmbedUrl(url, view_id, services.Pass(), exposed_services.Pass(),
+ ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::Embed(Id view_id, ViewManagerClientPtr client) {
+ DCHECK(service_);
+ service_->Embed(view_id, client.Pass(), ActionCompletedCallback());
+}
+
+void ViewManagerClientImpl::AddView(View* view) {
+ DCHECK(views_.find(view->id()) == views_.end());
+ views_[view->id()] = view;
+}
+
+void ViewManagerClientImpl::RemoveView(Id view_id) {
+ if (focused_view_ && focused_view_->id() == view_id)
+ OnFocusChanged(0);
+ if (capture_view_ && capture_view_->id() == view_id)
+ OnCaptureChanged(0);
+ if (activated_view_ && activated_view_->id() == view_id)
+ OnActiveWindowChanged(0);
+
+ IdToViewMap::iterator it = views_.find(view_id);
+ if (it != views_.end())
+ views_.erase(it);
+}
+
+void ViewManagerClientImpl::SetViewManagerService(
+ ViewManagerServicePtr service) {
+ DCHECK(!service_);
+ DCHECK(service);
+ service_ = service.Pass();
+}
+////////////////////////////////////////////////////////////////////////////////
+// ViewManagerClientImpl, ViewManager implementation:
+
+Id ViewManagerClientImpl::CreateViewOnServer() {
+ DCHECK(service_);
+ const Id view_id = MakeTransportId(connection_id_, ++next_id_);
+ service_->CreateView(view_id, [this](ErrorCode code) {
+ OnActionCompleted(code == ErrorCode::NONE);
+ });
+ return view_id;
+}
+
+const std::string& ViewManagerClientImpl::GetEmbedderURL() const {
+ return creator_url_;
+}
+
+View* ViewManagerClientImpl::GetRoot() {
+ return root_;
+}
+
+View* ViewManagerClientImpl::GetViewById(Id id) {
+ IdToViewMap::const_iterator it = views_.find(id);
+ return it != views_.end() ? it->second : NULL;
+}
+
+View* ViewManagerClientImpl::GetFocusedView() {
+ return focused_view_;
+}
+
+View* ViewManagerClientImpl::CreateView() {
+ View* view = new View(this, CreateViewOnServer());
+ AddView(view);
+ return view;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewManagerClientImpl, ViewManagerClient implementation:
+
+void ViewManagerClientImpl::OnEmbed(
+ ConnectionSpecificId connection_id,
+ const String& creator_url,
+ ViewDataPtr root_data,
+ ViewManagerServicePtr view_manager_service,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services,
+ ScopedMessagePipeHandle window_manager_pipe) {
+ if (view_manager_service) {
+ DCHECK(!service_);
+ service_ = view_manager_service.Pass();
+ }
+ connection_id_ = connection_id;
+ creator_url_ = String::From(creator_url);
+
+ DCHECK(!root_);
+ root_ = AddViewToViewManager(this, nullptr, root_data);
+ root_->AddObserver(new RootObserver(root_));
+
+ window_manager_.Bind(
+ InterfacePtrInfo<WindowManager>(window_manager_pipe.Pass(), 0u));
+ WindowManagerObserverPtr observer;
+ wm_observer_binding_.Bind(GetProxy(&observer));
+ // binding to |this| is safe here as |window_manager_| is bound to our
+ // lifetime.
+ window_manager_->GetFocusedAndActiveViews(
+ observer.Pass(),
+ [this](uint32_t capture_view_id, uint32_t focused_view_id,
+ uint32_t active_view_id) {
+ if (GetViewById(capture_view_id) != capture_view_)
+ OnCaptureChanged(capture_view_id);
+ if (GetViewById(focused_view_id) != focused_view_)
+ OnFocusChanged(focused_view_id);
+ if (GetViewById(active_view_id) != activated_view_)
+ OnActiveWindowChanged(active_view_id);
+ });
+
+ delegate_->OnEmbed(root_, services.Pass(), exposed_services.Pass());
+}
+
+void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) {
+ View* view = GetViewById(view_id);
+ if (view) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(),
+ OnViewEmbeddedAppDisconnected(view));
+ }
+}
+
+void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id,
+ RectPtr old_bounds,
+ RectPtr new_bounds) {
+ View* view = GetViewById(view_id);
+ ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds);
+}
+
+namespace {
+
+void SetViewportMetricsOnDecendants(View* root,
+ const ViewportMetrics& old_metrics,
+ const ViewportMetrics& new_metrics) {
+ ViewPrivate(root).LocalSetViewportMetrics(old_metrics, new_metrics);
+ const View::Children& children = root->children();
+ for (size_t i = 0; i < children.size(); ++i)
+ SetViewportMetricsOnDecendants(children[i], old_metrics, new_metrics);
+}
+}
+
+void ViewManagerClientImpl::OnViewViewportMetricsChanged(
+ ViewportMetricsPtr old_metrics,
+ ViewportMetricsPtr new_metrics) {
+ View* view = GetRoot();
+ if (view)
+ SetViewportMetricsOnDecendants(view, *old_metrics, *new_metrics);
+}
+
+void ViewManagerClientImpl::OnViewHierarchyChanged(
+ Id view_id,
+ Id new_parent_id,
+ Id old_parent_id,
+ mojo::Array<ViewDataPtr> views) {
+ View* initial_parent = views.size() ? GetViewById(views[0]->parent_id) : NULL;
+
+ BuildViewTree(this, views, initial_parent);
+
+ View* new_parent = GetViewById(new_parent_id);
+ View* old_parent = GetViewById(old_parent_id);
+ View* view = GetViewById(view_id);
+ if (new_parent)
+ ViewPrivate(new_parent).LocalAddChild(view);
+ else
+ ViewPrivate(old_parent).LocalRemoveChild(view);
+}
+
+void ViewManagerClientImpl::OnViewReordered(Id view_id,
+ Id relative_view_id,
+ OrderDirection direction) {
+ View* view = GetViewById(view_id);
+ View* relative_view = GetViewById(relative_view_id);
+ if (view && relative_view)
+ ViewPrivate(view).LocalReorder(relative_view, direction);
+}
+
+void ViewManagerClientImpl::OnViewDeleted(Id view_id) {
+ View* view = GetViewById(view_id);
+ if (view)
+ ViewPrivate(view).LocalDestroy();
+}
+
+void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) {
+ // TODO(sky): there is a race condition here. If this client and another
+ // client change the visibility at the same time the wrong value may be set.
+ // Deal with this some how.
+ View* view = GetViewById(view_id);
+ if (view)
+ ViewPrivate(view).LocalSetVisible(visible);
+}
+
+void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) {
+ View* view = GetViewById(view_id);
+ if (view)
+ ViewPrivate(view).LocalSetDrawn(drawn);
+}
+
+void ViewManagerClientImpl::OnViewSharedPropertyChanged(
+ Id view_id,
+ const String& name,
+ Array<uint8_t> new_data) {
+ View* view = GetViewById(view_id);
+ if (view) {
+ std::vector<uint8_t> data;
+ std::vector<uint8_t>* data_ptr = NULL;
+ if (!new_data.is_null()) {
+ data = new_data.To<std::vector<uint8_t>>();
+ data_ptr = &data;
+ }
+
+ view->SetSharedProperty(name, data_ptr);
+ }
+}
+
+void ViewManagerClientImpl::OnViewInputEvent(
+ Id view_id,
+ EventPtr event,
+ const Callback<void()>& ack_callback) {
+ View* view = GetViewById(view_id);
+ if (view) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(),
+ OnViewInputEvent(view, event));
+ }
+ ack_callback.Run();
+}
+
+void ViewManagerClientImpl::OnPerformAction(
+ Id view_id,
+ const String& name,
+ const Callback<void(bool)>& callback) {
+ View* view = GetViewById(view_id);
+ callback.Run(delegate_->OnPerformAction(view, name));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewManagerClientImpl, WindowManagerObserver implementation:
+
+void ViewManagerClientImpl::OnCaptureChanged(Id capture_view_id) {
+ View* gained_capture = GetViewById(capture_view_id);
+ View* lost_capture = capture_view_;
+ if (lost_capture) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(lost_capture).observers(),
+ OnViewFocusChanged(gained_capture, lost_capture));
+ }
+ capture_view_ = gained_capture;
+ if (gained_capture) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(gained_capture).observers(),
+ OnViewFocusChanged(gained_capture, lost_capture));
+ }
+}
+
+void ViewManagerClientImpl::OnFocusChanged(Id focused_view_id) {
+ View* focused = GetViewById(focused_view_id);
+ View* blurred = focused_view_;
+ if (blurred) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(blurred).observers(),
+ OnViewFocusChanged(focused, blurred));
+ }
+ focused_view_ = focused;
+ if (focused) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(focused).observers(),
+ OnViewFocusChanged(focused, blurred));
+ }
+}
+
+void ViewManagerClientImpl::OnActiveWindowChanged(Id active_view_id) {
+ View* activated = GetViewById(active_view_id);
+ View* deactivated = activated_view_;
+ if (deactivated) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(deactivated).observers(),
+ OnViewActivationChanged(activated, deactivated));
+ }
+ activated_view_ = activated;
+ if (activated) {
+ FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(activated).observers(),
+ OnViewActivationChanged(activated, deactivated));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// ViewManagerClientImpl, private:
+
+void ViewManagerClientImpl::RootDestroyed(View* root) {
+ DCHECK_EQ(root, root_);
+ root_ = nullptr;
+}
+
+void ViewManagerClientImpl::OnActionCompleted(bool success) {
+ if (!change_acked_callback_.is_null())
+ change_acked_callback_.Run();
+}
+
+Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() {
+ return [this](bool success) { OnActionCompleted(success); };
+}
+
+} // namespace mojo

Powered by Google App Engine
This is Rietveld 408576698