cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / components / view_manager / view_tree_host_impl.cc
blob70093b0eadb31e18bf2e6321a0a433c78285c7fe
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/view_manager/view_tree_host_impl.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "components/view_manager/connection_manager.h"
9 #include "components/view_manager/display_manager.h"
10 #include "components/view_manager/focus_controller.h"
11 #include "components/view_manager/public/cpp/types.h"
12 #include "components/view_manager/view_tree_host_delegate.h"
13 #include "components/view_manager/view_tree_impl.h"
14 #include "mojo/common/common_type_converters.h"
15 #include "mojo/converters/geometry/geometry_type_converters.h"
17 namespace view_manager {
19 ViewTreeHostImpl::ViewTreeHostImpl(
20 mojo::ViewTreeHostClientPtr client,
21 ConnectionManager* connection_manager,
22 bool is_headless,
23 mojo::ApplicationImpl* app_impl,
24 const scoped_refptr<gles2::GpuState>& gpu_state,
25 const scoped_refptr<surfaces::SurfacesState>& surfaces_state)
26 : delegate_(nullptr),
27 connection_manager_(connection_manager),
28 client_(client.Pass()),
29 event_dispatcher_(this),
30 display_manager_(
31 DisplayManager::Create(is_headless,
32 app_impl,
33 gpu_state,
34 surfaces_state)),
35 focus_controller_(new FocusController(this)) {
36 display_manager_->Init(this);
37 if (client_) {
38 client_.set_connection_error_handler(
39 base::Bind(&ViewTreeHostImpl::OnClientClosed,
40 base::Unretained(this)));
44 ViewTreeHostImpl::~ViewTreeHostImpl() {
47 void ViewTreeHostImpl::Init(ViewTreeHostDelegate* delegate) {
48 delegate_ = delegate;
49 if (delegate_ && root_)
50 delegate_->OnDisplayInitialized();
53 ViewTreeImpl* ViewTreeHostImpl::GetViewTree() {
54 return delegate_ ? delegate_->GetViewTree() : nullptr;
57 bool ViewTreeHostImpl::IsViewAttachedToRoot(const ServerView* view) const {
58 return root_->Contains(view) && view != root_.get();
61 bool ViewTreeHostImpl::SchedulePaintIfInViewport(const ServerView* view,
62 const gfx::Rect& bounds) {
63 if (root_->Contains(view)) {
64 display_manager_->SchedulePaint(view, bounds);
65 return true;
67 return false;
70 const mojo::ViewportMetrics& ViewTreeHostImpl::GetViewportMetrics() const {
71 return display_manager_->GetViewportMetrics();
74 void ViewTreeHostImpl::SetFocusedView(ServerView* new_focused_view) {
75 ServerView* old_focused_view = focus_controller_->GetFocusedView();
76 if (old_focused_view == new_focused_view)
77 return;
78 DCHECK(root_view()->Contains(new_focused_view));
79 focus_controller_->SetFocusedView(new_focused_view);
80 // TODO(beng): have the FocusController notify us via FocusControllerDelegate.
81 OnFocusChanged(old_focused_view, new_focused_view);
84 ServerView* ViewTreeHostImpl::GetFocusedView() {
85 return focus_controller_->GetFocusedView();
88 void ViewTreeHostImpl::DestroyFocusController() {
89 focus_controller_.reset();
92 void ViewTreeHostImpl::UpdateTextInputState(ServerView* view,
93 const ui::TextInputState& state) {
94 // Do not need to update text input for unfocused views.
95 if (!display_manager_ || focus_controller_->GetFocusedView() != view)
96 return;
97 display_manager_->UpdateTextInputState(state);
100 void ViewTreeHostImpl::SetImeVisibility(ServerView* view, bool visible) {
101 // Do not need to show or hide IME for unfocused view.
102 if (focus_controller_->GetFocusedView() != view)
103 return;
104 display_manager_->SetImeVisibility(visible);
107 void ViewTreeHostImpl::OnAccelerator(uint32_t accelerator_id,
108 mojo::EventPtr event) {
109 client()->OnAccelerator(accelerator_id, event.Pass());
112 void ViewTreeHostImpl::DispatchInputEventToView(const ServerView* target,
113 mojo::EventPtr event) {
114 // If the view is an embed root, forward to the embedded view, not the owner.
115 ViewTreeImpl* connection =
116 connection_manager_->GetConnectionWithRoot(target->id());
117 if (!connection)
118 connection = connection_manager_->GetConnection(target->id().connection_id);
119 DCHECK_EQ(this, connection->GetHost());
120 connection->client()->OnViewInputEvent(ViewIdToTransportId(target->id()),
121 event.Pass(),
122 base::Bind(&base::DoNothing));
125 void ViewTreeHostImpl::SetSize(mojo::SizePtr size) {
126 display_manager_->SetViewportSize(size.To<gfx::Size>());
129 void ViewTreeHostImpl::SetTitle(const mojo::String& title) {
130 display_manager_->SetTitle(title.To<base::string16>());
133 void ViewTreeHostImpl::AddAccelerator(uint32_t id,
134 mojo::KeyboardCode keyboard_code,
135 mojo::EventFlags flags) {
136 event_dispatcher_.AddAccelerator(id, keyboard_code, flags);
139 void ViewTreeHostImpl::RemoveAccelerator(uint32_t id) {
140 event_dispatcher_.RemoveAccelerator(id);
143 void ViewTreeHostImpl::OnClientClosed() {
144 // |display_manager_.reset()| destroys the display-manager first, and then
145 // sets |display_manager_| to nullptr. However, destroying |display_manager_|
146 // can destroy the corresponding ViewTreeHostConnection, and |this|. So
147 // setting it to nullptr afterwards in reset() ends up writing on free'd
148 // memory. So transfer over to a local scoped_ptr<> before destroying it.
149 scoped_ptr<DisplayManager> temp = display_manager_.Pass();
152 ServerView* ViewTreeHostImpl::GetRootView() {
153 return root_.get();
156 void ViewTreeHostImpl::OnEvent(mojo::EventPtr event) {
157 event_dispatcher_.OnEvent(event.Pass());
160 void ViewTreeHostImpl::OnDisplayClosed() {
161 if (delegate_)
162 delegate_->OnDisplayClosed();
165 void ViewTreeHostImpl::OnViewportMetricsChanged(
166 const mojo::ViewportMetrics& old_metrics,
167 const mojo::ViewportMetrics& new_metrics) {
168 if (!root_) {
169 root_.reset(connection_manager_->CreateServerView(
170 RootViewId(connection_manager_->GetAndAdvanceNextHostId())));
171 root_->SetBounds(gfx::Rect(new_metrics.size_in_pixels.To<gfx::Size>()));
172 root_->SetVisible(true);
173 if (delegate_)
174 delegate_->OnDisplayInitialized();
175 } else {
176 root_->SetBounds(gfx::Rect(new_metrics.size_in_pixels.To<gfx::Size>()));
178 // TODO(fsamuel): We shouldn't broadcast this to all connections but only
179 // those within a window root.
180 connection_manager_->ProcessViewportMetricsChanged(old_metrics, new_metrics);
183 void ViewTreeHostImpl::OnFocusChanged(ServerView* old_focused_view,
184 ServerView* new_focused_view) {
185 // There are up to four connections that need to be notified:
186 // . the connection containing |old_focused_view|.
187 // . the connection with |old_focused_view| as its root.
188 // . the connection containing |new_focused_view|.
189 // . the connection with |new_focused_view| as its root.
190 // Some of these connections may be the same. The following takes care to
191 // notify each only once.
192 ViewTreeImpl* owning_connection_old = nullptr;
193 ViewTreeImpl* embedded_connection_old = nullptr;
195 if (old_focused_view) {
196 owning_connection_old = connection_manager_->GetConnection(
197 old_focused_view->id().connection_id);
198 if (owning_connection_old) {
199 owning_connection_old->ProcessFocusChanged(old_focused_view,
200 new_focused_view);
202 embedded_connection_old =
203 connection_manager_->GetConnectionWithRoot(old_focused_view->id());
204 if (embedded_connection_old) {
205 DCHECK_NE(owning_connection_old, embedded_connection_old);
206 embedded_connection_old->ProcessFocusChanged(old_focused_view,
207 new_focused_view);
210 ViewTreeImpl* owning_connection_new = nullptr;
211 ViewTreeImpl* embedded_connection_new = nullptr;
212 if (new_focused_view) {
213 owning_connection_new = connection_manager_->GetConnection(
214 new_focused_view->id().connection_id);
215 if (owning_connection_new &&
216 owning_connection_new != owning_connection_old &&
217 owning_connection_new != embedded_connection_old) {
218 owning_connection_new->ProcessFocusChanged(old_focused_view,
219 new_focused_view);
221 embedded_connection_new =
222 connection_manager_->GetConnectionWithRoot(new_focused_view->id());
223 if (embedded_connection_new &&
224 embedded_connection_new != owning_connection_old &&
225 embedded_connection_new != embedded_connection_old) {
226 DCHECK_NE(owning_connection_new, embedded_connection_new);
227 embedded_connection_new->ProcessFocusChanged(old_focused_view,
228 new_focused_view);
232 // Ensure that we always notify the root connection of a focus change.
233 ViewTreeImpl* root_tree = GetViewTree();
234 if (root_tree != owning_connection_old &&
235 root_tree != embedded_connection_old &&
236 root_tree != owning_connection_new &&
237 root_tree != embedded_connection_new) {
238 root_tree->ProcessFocusChanged(old_focused_view, new_focused_view);
241 UpdateTextInputState(new_focused_view, new_focused_view->text_input_state());
244 } // namespace view_manager