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

Side by Side Diff: components/mus/public/cpp/lib/window_tree_client_impl.cc

Issue 2018823002: Eliminate WindowTreeConnection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@connection
Patch Set: . Created 4 years, 6 months 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2014 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.
4
5 #include "components/mus/public/cpp/lib/window_tree_client_impl.h"
6
7 #include <stddef.h>
8
9 #include <string>
10 #include <utility>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/memory/ptr_util.h"
15 #include "components/mus/common/util.h"
16 #include "components/mus/public/cpp/input_event_handler.h"
17 #include "components/mus/public/cpp/lib/in_flight_change.h"
18 #include "components/mus/public/cpp/lib/window_private.h"
19 #include "components/mus/public/cpp/window_manager_delegate.h"
20 #include "components/mus/public/cpp/window_observer.h"
21 #include "components/mus/public/cpp/window_tracker.h"
22 #include "components/mus/public/cpp/window_tree_connection.h"
23 #include "components/mus/public/cpp/window_tree_connection_observer.h"
24 #include "components/mus/public/cpp/window_tree_delegate.h"
25 #include "services/shell/public/cpp/connector.h"
26 #include "ui/events/event.h"
27 #include "ui/events/mojo/input_events_type_converters.h"
28 #include "ui/gfx/geometry/insets.h"
29 #include "ui/gfx/geometry/mojo/geometry_type_converters.h"
30 #include "ui/gfx/geometry/size.h"
31
32 namespace mus {
33
34 Id MakeTransportId(ClientSpecificId client_id, ClientSpecificId local_id) {
35 return (client_id << 16) | local_id;
36 }
37
38 Id server_id(Window* window) {
39 return WindowPrivate(window).server_id();
40 }
41
42 // Helper called to construct a local window object from transport data.
43 Window* AddWindowToClient(WindowTreeClientImpl* client,
44 Window* parent,
45 const mojom::WindowDataPtr& window_data) {
46 // We don't use the ctor that takes a WindowTreeConnection here, since it
47 // will call back to the service and attempt to create a new window.
48 Window* window = WindowPrivate::LocalCreate();
49 WindowPrivate private_window(window);
50 private_window.set_connection(client);
51 private_window.set_server_id(window_data->window_id);
52 private_window.set_visible(window_data->visible);
53 private_window.LocalSetDisplay(window_data->display_id);
54 private_window.set_properties(
55 window_data->properties
56 .To<std::map<std::string, std::vector<uint8_t>>>());
57 client->AddWindow(window);
58 private_window.LocalSetBounds(gfx::Rect(),
59 window_data->bounds.To<gfx::Rect>());
60 if (parent)
61 WindowPrivate(parent).LocalAddChild(window);
62 return window;
63 }
64
65 Window* BuildWindowTree(WindowTreeClientImpl* client,
66 const mojo::Array<mojom::WindowDataPtr>& windows,
67 Window* initial_parent) {
68 std::vector<Window*> parents;
69 Window* root = NULL;
70 Window* last_window = NULL;
71 if (initial_parent)
72 parents.push_back(initial_parent);
73 for (size_t i = 0; i < windows.size(); ++i) {
74 if (last_window && windows[i]->parent_id == server_id(last_window)) {
75 parents.push_back(last_window);
76 } else if (!parents.empty()) {
77 while (server_id(parents.back()) != windows[i]->parent_id)
78 parents.pop_back();
79 }
80 Window* window = AddWindowToClient(
81 client, !parents.empty() ? parents.back() : NULL, windows[i]);
82 if (!last_window)
83 root = window;
84 last_window = window;
85 }
86 return root;
87 }
88
89 WindowTreeConnection* WindowTreeConnection::Create(
90 WindowTreeDelegate* delegate,
91 shell::Connector* connector) {
92 WindowTreeClientImpl* client =
93 new WindowTreeClientImpl(delegate, nullptr, nullptr);
94 client->ConnectViaWindowTreeFactory(connector);
95 return client;
96 }
97
98 WindowTreeConnection* WindowTreeConnection::Create(
99 WindowTreeDelegate* delegate,
100 mojo::InterfaceRequest<mojom::WindowTreeClient> request,
101 CreateType create_type) {
102 WindowTreeClientImpl* client =
103 new WindowTreeClientImpl(delegate, nullptr, std::move(request));
104 if (create_type == CreateType::WAIT_FOR_EMBED)
105 client->WaitForEmbed();
106 return client;
107 }
108
109 WindowTreeConnection* WindowTreeConnection::CreateForWindowManager(
110 WindowTreeDelegate* delegate,
111 mojo::InterfaceRequest<mojom::WindowTreeClient> request,
112 CreateType create_type,
113 WindowManagerDelegate* window_manager_delegate) {
114 WindowTreeClientImpl* client = new WindowTreeClientImpl(
115 delegate, window_manager_delegate, std::move(request));
116 if (create_type == CreateType::WAIT_FOR_EMBED)
117 client->WaitForEmbed();
118 return client;
119 }
120
121 WindowTreeClientImpl::WindowTreeClientImpl(
122 WindowTreeDelegate* delegate,
123 WindowManagerDelegate* window_manager_delegate,
124 mojo::InterfaceRequest<mojom::WindowTreeClient> request)
125 : client_id_(0),
126 next_window_id_(1),
127 next_change_id_(1),
128 delegate_(delegate),
129 window_manager_delegate_(window_manager_delegate),
130 capture_window_(nullptr),
131 focused_window_(nullptr),
132 binding_(this),
133 tree_(nullptr),
134 delete_on_no_roots_(true),
135 in_destructor_(false),
136 cursor_location_memory_(nullptr),
137 weak_factory_(this) {
138 // Allow for a null request in tests.
139 if (request.is_pending())
140 binding_.Bind(std::move(request));
141 if (window_manager_delegate)
142 window_manager_delegate->SetWindowManagerClient(this);
143 }
144
145 WindowTreeClientImpl::~WindowTreeClientImpl() {
146 in_destructor_ = true;
147
148 std::vector<Window*> non_owned;
149 WindowTracker tracker;
150 while (!windows_.empty()) {
151 IdToWindowMap::iterator it = windows_.begin();
152 if (OwnsWindow(it->second)) {
153 it->second->Destroy();
154 } else {
155 tracker.Add(it->second);
156 windows_.erase(it);
157 }
158 }
159
160 // Delete the non-owned windows last. In the typical case these are roots. The
161 // exception is the window manager and embed roots, which may know about
162 // other random windows that it doesn't own.
163 // NOTE: we manually delete as we're a friend.
164 while (!tracker.windows().empty())
165 delete tracker.windows().front();
166
167 FOR_EACH_OBSERVER(WindowTreeConnectionObserver, observers_,
168 OnWillDestroyConnection(this));
169
170 delegate_->OnConnectionLost(this);
171 }
172
173 void WindowTreeClientImpl::ConnectViaWindowTreeFactory(
174 shell::Connector* connector) {
175 // Clients created with no root shouldn't delete automatically.
176 delete_on_no_roots_ = false;
177
178 // The client id doesn't really matter, we use 101 purely for debugging.
179 client_id_ = 101;
180
181 mojom::WindowTreeFactoryPtr factory;
182 connector->ConnectToInterface("mojo:mus", &factory);
183 factory->CreateWindowTree(GetProxy(&tree_ptr_),
184 binding_.CreateInterfacePtrAndBind());
185 tree_ = tree_ptr_.get();
186
187 tree_ptr_->GetCursorLocationMemory(
188 base::Bind(&WindowTreeClientImpl::OnReceivedCursorLocationMemory,
189 weak_factory_.GetWeakPtr()));
190 }
191
192 void WindowTreeClientImpl::WaitForEmbed() {
193 DCHECK(roots_.empty());
194 // OnEmbed() is the first function called.
195 binding_.WaitForIncomingMethodCall();
196 // TODO(sky): deal with pipe being closed before we get OnEmbed().
197 }
198
199 void WindowTreeClientImpl::DestroyWindow(Window* window) {
200 DCHECK(tree_);
201 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique(
202 new CrashInFlightChange(window, ChangeType::DELETE_WINDOW)));
203 tree_->DeleteWindow(change_id, server_id(window));
204 }
205
206 void WindowTreeClientImpl::AddChild(Window* parent, Id child_id) {
207 DCHECK(tree_);
208 const uint32_t change_id = ScheduleInFlightChange(
209 base::WrapUnique(new CrashInFlightChange(parent, ChangeType::ADD_CHILD)));
210 tree_->AddWindow(change_id, parent->server_id(), child_id);
211 }
212
213 void WindowTreeClientImpl::RemoveChild(Window* parent, Id child_id) {
214 DCHECK(tree_);
215 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique(
216 new CrashInFlightChange(parent, ChangeType::REMOVE_CHILD)));
217 tree_->RemoveWindowFromParent(change_id, child_id);
218 }
219
220 void WindowTreeClientImpl::AddTransientWindow(Window* window,
221 Id transient_window_id) {
222 DCHECK(tree_);
223 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique(
224 new CrashInFlightChange(window, ChangeType::ADD_TRANSIENT_WINDOW)));
225 tree_->AddTransientWindow(change_id, server_id(window), transient_window_id);
226 }
227
228 void WindowTreeClientImpl::RemoveTransientWindowFromParent(Window* window) {
229 DCHECK(tree_);
230 const uint32_t change_id =
231 ScheduleInFlightChange(base::WrapUnique(new CrashInFlightChange(
232 window, ChangeType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT)));
233 tree_->RemoveTransientWindowFromParent(change_id, server_id(window));
234 }
235
236 void WindowTreeClientImpl::SetModal(Window* window) {
237 DCHECK(tree_);
238 const uint32_t change_id = ScheduleInFlightChange(
239 base::WrapUnique(new InFlightSetModalChange(window)));
240 tree_->SetModal(change_id, server_id(window));
241 }
242
243 void WindowTreeClientImpl::Reorder(Window* window,
244 Id relative_window_id,
245 mojom::OrderDirection direction) {
246 DCHECK(tree_);
247 const uint32_t change_id = ScheduleInFlightChange(
248 base::WrapUnique(new CrashInFlightChange(window, ChangeType::REORDER)));
249 tree_->ReorderWindow(change_id, server_id(window), relative_window_id,
250 direction);
251 }
252
253 bool WindowTreeClientImpl::OwnsWindow(Window* window) const {
254 // Windows created via CreateTopLevelWindow() are not owned by us, but have
255 // our client id.
256 return HiWord(server_id(window)) == client_id_ &&
257 roots_.count(window) == 0;
258 }
259
260 void WindowTreeClientImpl::SetBounds(Window* window,
261 const gfx::Rect& old_bounds,
262 const gfx::Rect& bounds) {
263 DCHECK(tree_);
264 const uint32_t change_id = ScheduleInFlightChange(
265 base::WrapUnique(new InFlightBoundsChange(window, old_bounds)));
266 tree_->SetWindowBounds(change_id, server_id(window),
267 mojo::Rect::From(bounds));
268 }
269
270 void WindowTreeClientImpl::SetCapture(Window* window) {
271 // In order for us to get here we had to have exposed a window, which implies
272 // we got a client.
273 DCHECK(tree_);
274 if (capture_window_ == window)
275 return;
276 const uint32_t change_id = ScheduleInFlightChange(
277 base::WrapUnique(new InFlightCaptureChange(this, capture_window_)));
278 tree_->SetCapture(change_id, server_id(window));
279 LocalSetCapture(window);
280 }
281
282 void WindowTreeClientImpl::ReleaseCapture(Window* window) {
283 // In order for us to get here we had to have exposed a window, which implies
284 // we got a client.
285 DCHECK(tree_);
286 if (capture_window_ != window)
287 return;
288 const uint32_t change_id = ScheduleInFlightChange(
289 base::WrapUnique(new InFlightCaptureChange(this, window)));
290 tree_->ReleaseCapture(change_id, server_id(window));
291 LocalSetCapture(nullptr);
292 }
293
294 void WindowTreeClientImpl::SetClientArea(
295 Id window_id,
296 const gfx::Insets& client_area,
297 const std::vector<gfx::Rect>& additional_client_areas) {
298 DCHECK(tree_);
299 tree_->SetClientArea(
300 window_id, mojo::Insets::From(client_area),
301 mojo::Array<mojo::RectPtr>::From(additional_client_areas));
302 }
303
304 void WindowTreeClientImpl::SetHitTestMask(Id window_id, const gfx::Rect& mask) {
305 DCHECK(tree_);
306 tree_->SetHitTestMask(window_id, mojo::Rect::From(mask));
307 }
308
309 void WindowTreeClientImpl::ClearHitTestMask(Id window_id) {
310 DCHECK(tree_);
311 tree_->SetHitTestMask(window_id, nullptr);
312 }
313
314 void WindowTreeClientImpl::SetFocus(Window* window) {
315 // In order for us to get here we had to have exposed a window, which implies
316 // we got a client.
317 DCHECK(tree_);
318 const uint32_t change_id = ScheduleInFlightChange(
319 base::WrapUnique(new InFlightFocusChange(this, focused_window_)));
320 tree_->SetFocus(change_id, window ? server_id(window) : 0);
321 LocalSetFocus(window);
322 }
323
324 void WindowTreeClientImpl::SetCanFocus(Id window_id, bool can_focus) {
325 DCHECK(tree_);
326 tree_->SetCanFocus(window_id, can_focus);
327 }
328
329 void WindowTreeClientImpl::SetPredefinedCursor(Id window_id,
330 mus::mojom::Cursor cursor_id) {
331 DCHECK(tree_);
332
333 Window* window = GetWindowByServerId(window_id);
334 if (!window)
335 return;
336
337 // We make an inflight change thing here.
338 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique(
339 new InFlightPredefinedCursorChange(window, window->predefined_cursor())));
340 tree_->SetPredefinedCursor(change_id, window_id, cursor_id);
341 }
342
343 void WindowTreeClientImpl::SetVisible(Window* window, bool visible) {
344 DCHECK(tree_);
345 const uint32_t change_id = ScheduleInFlightChange(
346 base::WrapUnique(new InFlightVisibleChange(window, !visible)));
347 tree_->SetWindowVisibility(change_id, server_id(window), visible);
348 }
349
350 void WindowTreeClientImpl::SetOpacity(Window* window, float opacity) {
351 DCHECK(tree_);
352 const uint32_t change_id = ScheduleInFlightChange(
353 base::WrapUnique(new InFlightOpacityChange(window, window->opacity())));
354 tree_->SetWindowOpacity(change_id, server_id(window), opacity);
355 }
356
357 void WindowTreeClientImpl::SetProperty(Window* window,
358 const std::string& name,
359 mojo::Array<uint8_t> data) {
360 DCHECK(tree_);
361
362 mojo::Array<uint8_t> old_value(nullptr);
363 if (window->HasSharedProperty(name))
364 old_value = mojo::Array<uint8_t>::From(window->properties_[name]);
365
366 const uint32_t change_id = ScheduleInFlightChange(
367 base::WrapUnique(new InFlightPropertyChange(window, name, old_value)));
368 tree_->SetWindowProperty(change_id, server_id(window), mojo::String(name),
369 std::move(data));
370 }
371
372 void WindowTreeClientImpl::SetWindowTextInputState(
373 Id window_id,
374 mojo::TextInputStatePtr state) {
375 DCHECK(tree_);
376 tree_->SetWindowTextInputState(window_id, std::move(state));
377 }
378
379 void WindowTreeClientImpl::SetImeVisibility(Id window_id,
380 bool visible,
381 mojo::TextInputStatePtr state) {
382 DCHECK(tree_);
383 tree_->SetImeVisibility(window_id, visible, std::move(state));
384 }
385
386 void WindowTreeClientImpl::Embed(
387 Id window_id,
388 mojom::WindowTreeClientPtr client,
389 const mojom::WindowTree::EmbedCallback& callback) {
390 DCHECK(tree_);
391 tree_->Embed(window_id, std::move(client), callback);
392 }
393
394 void WindowTreeClientImpl::RequestClose(Window* window) {
395 if (window_manager_internal_client_)
396 window_manager_internal_client_->WmRequestClose(server_id(window));
397 }
398
399 void WindowTreeClientImpl::AttachSurface(
400 Id window_id,
401 mojom::SurfaceType type,
402 mojo::InterfaceRequest<mojom::Surface> surface,
403 mojom::SurfaceClientPtr client) {
404 DCHECK(tree_);
405 tree_->AttachSurface(window_id, type, std::move(surface), std::move(client));
406 }
407
408 void WindowTreeClientImpl::LocalSetCapture(Window* window) {
409 if (capture_window_ == window)
410 return;
411 Window* lost_capture = capture_window_;
412 capture_window_ = window;
413 if (lost_capture) {
414 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(lost_capture).observers(),
415 OnWindowLostCapture(lost_capture));
416 }
417 }
418
419 void WindowTreeClientImpl::LocalSetFocus(Window* focused) {
420 Window* blurred = focused_window_;
421 // Update |focused_window_| before calling any of the observers, so that the
422 // observers get the correct result from calling |Window::HasFocus()|,
423 // |WindowTreeConnection::GetFocusedWindow()| etc.
424 focused_window_ = focused;
425 if (blurred) {
426 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(blurred).observers(),
427 OnWindowFocusChanged(focused, blurred));
428 }
429 if (focused) {
430 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(focused).observers(),
431 OnWindowFocusChanged(focused, blurred));
432 }
433 FOR_EACH_OBSERVER(WindowTreeConnectionObserver, observers_,
434 OnWindowTreeFocusChanged(focused, blurred));
435 }
436
437 void WindowTreeClientImpl::AddWindow(Window* window) {
438 DCHECK(windows_.find(server_id(window)) == windows_.end());
439 windows_[server_id(window)] = window;
440 }
441
442 void WindowTreeClientImpl::OnWindowDestroying(Window* window) {
443 // TODO(jonross): Also clear the focused window (crbug.com/611983)
444 if (window == capture_window_) {
445 InFlightCaptureChange reset_change(this, nullptr);
446 ApplyServerChangeToExistingInFlightChange(reset_change);
447 // Normally just updating the queued changes is sufficient. However since
448 // |window| is being destroyed, it will not be possible to notify its
449 // observers of the lost capture. Update local state now.
450 LocalSetCapture(nullptr);
451 }
452 }
453
454 void WindowTreeClientImpl::OnWindowDestroyed(Window* window) {
455 windows_.erase(server_id(window));
456
457 for (auto& entry : embedded_windows_) {
458 auto it = entry.second.find(window);
459 if (it != entry.second.end()) {
460 entry.second.erase(it);
461 break;
462 }
463 }
464
465 // Remove any InFlightChanges associated with the window.
466 std::set<uint32_t> in_flight_change_ids_to_remove;
467 for (const auto& pair : in_flight_map_) {
468 if (pair.second->window() == window)
469 in_flight_change_ids_to_remove.insert(pair.first);
470 }
471 for (auto change_id : in_flight_change_ids_to_remove)
472 in_flight_map_.erase(change_id);
473
474 if (roots_.erase(window) > 0 && roots_.empty() && delete_on_no_roots_ &&
475 !in_destructor_) {
476 delete this;
477 }
478 }
479
480 Window* WindowTreeClientImpl::GetWindowByServerId(Id id) {
481 IdToWindowMap::const_iterator it = windows_.find(id);
482 return it != windows_.end() ? it->second : NULL;
483 }
484
485 InFlightChange* WindowTreeClientImpl::GetOldestInFlightChangeMatching(
486 const InFlightChange& change) {
487 for (const auto& pair : in_flight_map_) {
488 if (pair.second->window() == change.window() &&
489 pair.second->change_type() == change.change_type() &&
490 pair.second->Matches(change)) {
491 return pair.second.get();
492 }
493 }
494 return nullptr;
495 }
496
497 uint32_t WindowTreeClientImpl::ScheduleInFlightChange(
498 std::unique_ptr<InFlightChange> change) {
499 DCHECK(!change->window() ||
500 windows_.count(change->window()->server_id()) > 0);
501 const uint32_t change_id = next_change_id_++;
502 in_flight_map_[change_id] = std::move(change);
503 return change_id;
504 }
505
506 bool WindowTreeClientImpl::ApplyServerChangeToExistingInFlightChange(
507 const InFlightChange& change) {
508 InFlightChange* existing_change = GetOldestInFlightChangeMatching(change);
509 if (!existing_change)
510 return false;
511
512 existing_change->SetRevertValueFrom(change);
513 return true;
514 }
515
516 Window* WindowTreeClientImpl::NewWindowImpl(
517 NewWindowType type,
518 const Window::SharedProperties* properties) {
519 DCHECK(tree_);
520 Window* window =
521 new Window(this, MakeTransportId(client_id_, next_window_id_++));
522 if (properties)
523 window->properties_ = *properties;
524 AddWindow(window);
525
526 const uint32_t change_id = ScheduleInFlightChange(base::WrapUnique(
527 new CrashInFlightChange(window, type == NewWindowType::CHILD
528 ? ChangeType::NEW_WINDOW
529 : ChangeType::NEW_TOP_LEVEL_WINDOW)));
530 mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties;
531 if (properties) {
532 transport_properties =
533 mojo::Map<mojo::String, mojo::Array<uint8_t>>::From(*properties);
534 }
535 if (type == NewWindowType::CHILD) {
536 tree_->NewWindow(change_id, server_id(window),
537 std::move(transport_properties));
538 } else {
539 roots_.insert(window);
540 tree_->NewTopLevelWindow(change_id, server_id(window),
541 std::move(transport_properties));
542 }
543 return window;
544 }
545
546 void WindowTreeClientImpl::OnEmbedImpl(mojom::WindowTree* window_tree,
547 ClientSpecificId client_id,
548 mojom::WindowDataPtr root_data,
549 Id focused_window_id,
550 bool drawn) {
551 // WARNING: this is only called if WindowTreeClientImpl was created as the
552 // result of an embedding.
553 tree_ = window_tree;
554 client_id_ = client_id;
555
556 DCHECK(roots_.empty());
557 Window* root = AddWindowToClient(this, nullptr, root_data);
558 roots_.insert(root);
559
560 focused_window_ = GetWindowByServerId(focused_window_id);
561
562 WindowPrivate(root).LocalSetParentDrawn(drawn);
563
564 delegate_->OnEmbed(root);
565
566 if (focused_window_) {
567 FOR_EACH_OBSERVER(WindowTreeConnectionObserver, observers_,
568 OnWindowTreeFocusChanged(focused_window_, nullptr));
569 }
570 }
571
572 void WindowTreeClientImpl::OnReceivedCursorLocationMemory(
573 mojo::ScopedSharedBufferHandle handle) {
574 cursor_location_handle_ = std::move(handle);
575 MojoResult result = mojo::MapBuffer(
576 cursor_location_handle_.get(), 0,
577 sizeof(base::subtle::Atomic32),
578 reinterpret_cast<void**>(&cursor_location_memory_),
579 MOJO_MAP_BUFFER_FLAG_NONE);
580 if (result != MOJO_RESULT_OK) {
581 NOTREACHED();
582 return;
583 }
584 DCHECK(cursor_location_memory_);
585 }
586
587 ////////////////////////////////////////////////////////////////////////////////
588 // WindowTreeClientImpl, WindowTreeConnection implementation:
589
590 void WindowTreeClientImpl::SetDeleteOnNoRoots(bool value) {
591 delete_on_no_roots_ = value;
592 }
593
594 const std::set<Window*>& WindowTreeClientImpl::GetRoots() {
595 return roots_;
596 }
597
598 Window* WindowTreeClientImpl::GetFocusedWindow() {
599 return focused_window_;
600 }
601
602 void WindowTreeClientImpl::ClearFocus() {
603 if (!focused_window_)
604 return;
605
606 SetFocus(nullptr);
607 }
608
609 gfx::Point WindowTreeClientImpl::GetCursorScreenPoint() {
610 // We raced initialization. Return (0, 0).
611 if (!cursor_location_memory_)
612 return gfx::Point();
613
614 base::subtle::Atomic32 location =
615 base::subtle::NoBarrier_Load(cursor_location_memory_);
616 return gfx::Point(static_cast<int16_t>(location >> 16),
617 static_cast<int16_t>(location & 0xFFFF));
618 }
619
620 void WindowTreeClientImpl::SetEventObserver(mojom::EventMatcherPtr matcher) {
621 if (matcher.is_null()) {
622 has_event_observer_ = false;
623 tree_->SetEventObserver(nullptr, 0u);
624 } else {
625 has_event_observer_ = true;
626 event_observer_id_++;
627 tree_->SetEventObserver(std::move(matcher), event_observer_id_);
628 }
629 }
630
631 Window* WindowTreeClientImpl::NewWindow(
632 const Window::SharedProperties* properties) {
633 return NewWindowImpl(NewWindowType::CHILD, properties);
634 }
635
636 Window* WindowTreeClientImpl::NewTopLevelWindow(
637 const Window::SharedProperties* properties) {
638 Window* window = NewWindowImpl(NewWindowType::TOP_LEVEL, properties);
639 // Assume newly created top level windows are drawn by default, otherwise
640 // requests to focus will fail. We will get the real value in
641 // OnTopLevelCreated().
642 window->LocalSetParentDrawn(true);
643 return window;
644 }
645
646 ////////////////////////////////////////////////////////////////////////////////
647 // WindowTreeClientImpl, WindowTreeClient implementation:
648
649 void WindowTreeClientImpl::AddObserver(WindowTreeConnectionObserver* observer) {
650 observers_.AddObserver(observer);
651 }
652
653 void WindowTreeClientImpl::RemoveObserver(
654 WindowTreeConnectionObserver* observer) {
655 observers_.RemoveObserver(observer);
656 }
657
658 void WindowTreeClientImpl::OnEmbed(ClientSpecificId client_id,
659 mojom::WindowDataPtr root_data,
660 mojom::WindowTreePtr tree,
661 Id focused_window_id,
662 bool drawn) {
663 DCHECK(!tree_ptr_);
664 tree_ptr_ = std::move(tree);
665 tree_ptr_.set_connection_error_handler([this]() { delete this; });
666
667 if (window_manager_delegate_) {
668 tree_ptr_->GetWindowManagerClient(GetProxy(&window_manager_internal_client_,
669 tree_ptr_.associated_group()));
670 }
671
672 OnEmbedImpl(tree_ptr_.get(), client_id, std::move(root_data),
673 focused_window_id, drawn);
674 }
675
676 void WindowTreeClientImpl::OnEmbeddedAppDisconnected(Id window_id) {
677 Window* window = GetWindowByServerId(window_id);
678 if (window) {
679 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(window).observers(),
680 OnWindowEmbeddedAppDisconnected(window));
681 }
682 }
683
684 void WindowTreeClientImpl::OnUnembed(Id window_id) {
685 Window* window = GetWindowByServerId(window_id);
686 if (!window)
687 return;
688
689 delegate_->OnUnembed(window);
690 WindowPrivate(window).LocalDestroy();
691 }
692
693 void WindowTreeClientImpl::OnLostCapture(Id window_id) {
694 Window* window = GetWindowByServerId(window_id);
695 if (!window)
696 return;
697
698 InFlightCaptureChange reset_change(this, nullptr);
699 if (ApplyServerChangeToExistingInFlightChange(reset_change))
700 return;
701
702 LocalSetCapture(nullptr);
703 }
704
705 void WindowTreeClientImpl::OnTopLevelCreated(uint32_t change_id,
706 mojom::WindowDataPtr data,
707 bool drawn) {
708 // The server ack'd the top level window we created and supplied the state
709 // of the window at the time the server created it. For properties we do not
710 // have changes in flight for we can update them immediately. For properties
711 // with changes in flight we set the revert value from the server.
712
713 if (!in_flight_map_.count(change_id)) {
714 // The window may have been destroyed locally before the server could finish
715 // creating the window, and before the server received the notification that
716 // the window has been destroyed.
717 return;
718 }
719 std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
720 in_flight_map_.erase(change_id);
721
722 Window* window = change->window();
723 WindowPrivate window_private(window);
724
725 // Drawn state and display-id always come from the server (they can't be
726 // modified locally).
727 window_private.LocalSetParentDrawn(drawn);
728 window_private.LocalSetDisplay(data->display_id);
729
730 // The default visibilty is false, we only need update visibility if it
731 // differs from that.
732 if (data->visible) {
733 InFlightVisibleChange visible_change(window, data->visible);
734 InFlightChange* current_change =
735 GetOldestInFlightChangeMatching(visible_change);
736 if (current_change)
737 current_change->SetRevertValueFrom(visible_change);
738 else
739 window_private.LocalSetVisible(true);
740 }
741
742 const gfx::Rect bounds(data->bounds.To<gfx::Rect>());
743 {
744 InFlightBoundsChange bounds_change(window, bounds);
745 InFlightChange* current_change =
746 GetOldestInFlightChangeMatching(bounds_change);
747 if (current_change)
748 current_change->SetRevertValueFrom(bounds_change);
749 else if (window->bounds() != bounds)
750 window_private.LocalSetBounds(window->bounds(), bounds);
751 }
752
753 // There is currently no API to bulk set properties, so we iterate over each
754 // property individually.
755 Window::SharedProperties properties =
756 data->properties.To<std::map<std::string, std::vector<uint8_t>>>();
757 for (const auto& pair : properties) {
758 InFlightPropertyChange property_change(
759 window, pair.first, mojo::Array<uint8_t>::From(pair.second));
760 InFlightChange* current_change =
761 GetOldestInFlightChangeMatching(property_change);
762 if (current_change)
763 current_change->SetRevertValueFrom(property_change);
764 else
765 window_private.LocalSetSharedProperty(pair.first, &(pair.second));
766 }
767
768 // Top level windows should not have a parent.
769 DCHECK_EQ(0u, data->parent_id);
770 }
771
772 void WindowTreeClientImpl::OnWindowBoundsChanged(Id window_id,
773 mojo::RectPtr old_bounds,
774 mojo::RectPtr new_bounds) {
775 Window* window = GetWindowByServerId(window_id);
776 if (!window)
777 return;
778
779 InFlightBoundsChange new_change(window, new_bounds.To<gfx::Rect>());
780 if (ApplyServerChangeToExistingInFlightChange(new_change))
781 return;
782
783 WindowPrivate(window)
784 .LocalSetBounds(old_bounds.To<gfx::Rect>(), new_bounds.To<gfx::Rect>());
785 }
786
787 void WindowTreeClientImpl::OnClientAreaChanged(
788 uint32_t window_id,
789 mojo::InsetsPtr new_client_area,
790 mojo::Array<mojo::RectPtr> new_additional_client_areas) {
791 Window* window = GetWindowByServerId(window_id);
792 if (window) {
793 WindowPrivate(window).LocalSetClientArea(
794 new_client_area.To<gfx::Insets>(),
795 new_additional_client_areas.To<std::vector<gfx::Rect>>());
796 }
797 }
798
799 void WindowTreeClientImpl::OnTransientWindowAdded(
800 uint32_t window_id,
801 uint32_t transient_window_id) {
802 Window* window = GetWindowByServerId(window_id);
803 Window* transient_window = GetWindowByServerId(transient_window_id);
804 // window or transient_window or both may be null if a local delete occurs
805 // with an in flight add from the server.
806 if (window && transient_window)
807 WindowPrivate(window).LocalAddTransientWindow(transient_window);
808 }
809
810 void WindowTreeClientImpl::OnTransientWindowRemoved(
811 uint32_t window_id,
812 uint32_t transient_window_id) {
813 Window* window = GetWindowByServerId(window_id);
814 Window* transient_window = GetWindowByServerId(transient_window_id);
815 // window or transient_window or both may be null if a local delete occurs
816 // with an in flight delete from the server.
817 if (window && transient_window)
818 WindowPrivate(window).LocalRemoveTransientWindow(transient_window);
819 }
820
821 void WindowTreeClientImpl::OnWindowHierarchyChanged(
822 Id window_id,
823 Id old_parent_id,
824 Id new_parent_id,
825 mojo::Array<mojom::WindowDataPtr> windows) {
826 Window* initial_parent =
827 windows.size() ? GetWindowByServerId(windows[0]->parent_id) : NULL;
828
829 const bool was_window_known = GetWindowByServerId(window_id) != nullptr;
830
831 BuildWindowTree(this, windows, initial_parent);
832
833 // If the window was not known, then BuildWindowTree() will have created it
834 // and parented the window.
835 if (!was_window_known)
836 return;
837
838 Window* new_parent = GetWindowByServerId(new_parent_id);
839 Window* old_parent = GetWindowByServerId(old_parent_id);
840 Window* window = GetWindowByServerId(window_id);
841 if (new_parent)
842 WindowPrivate(new_parent).LocalAddChild(window);
843 else
844 WindowPrivate(old_parent).LocalRemoveChild(window);
845 }
846
847 void WindowTreeClientImpl::OnWindowReordered(Id window_id,
848 Id relative_window_id,
849 mojom::OrderDirection direction) {
850 Window* window = GetWindowByServerId(window_id);
851 Window* relative_window = GetWindowByServerId(relative_window_id);
852 if (window && relative_window)
853 WindowPrivate(window).LocalReorder(relative_window, direction);
854 }
855
856 void WindowTreeClientImpl::OnWindowDeleted(Id window_id) {
857 Window* window = GetWindowByServerId(window_id);
858 if (window)
859 WindowPrivate(window).LocalDestroy();
860 }
861
862 Window* WindowTreeClientImpl::GetCaptureWindow() {
863 return capture_window_;
864 }
865
866 void WindowTreeClientImpl::OnWindowVisibilityChanged(Id window_id,
867 bool visible) {
868 Window* window = GetWindowByServerId(window_id);
869 if (!window)
870 return;
871
872 InFlightVisibleChange new_change(window, visible);
873 if (ApplyServerChangeToExistingInFlightChange(new_change))
874 return;
875
876 WindowPrivate(window).LocalSetVisible(visible);
877 }
878
879 void WindowTreeClientImpl::OnWindowOpacityChanged(Id window_id,
880 float old_opacity,
881 float new_opacity) {
882 Window* window = GetWindowByServerId(window_id);
883 if (!window)
884 return;
885
886 InFlightOpacityChange new_change(window, new_opacity);
887 if (ApplyServerChangeToExistingInFlightChange(new_change))
888 return;
889
890 WindowPrivate(window).LocalSetOpacity(new_opacity);
891 }
892
893 void WindowTreeClientImpl::OnWindowParentDrawnStateChanged(Id window_id,
894 bool drawn) {
895 Window* window = GetWindowByServerId(window_id);
896 if (window)
897 WindowPrivate(window).LocalSetParentDrawn(drawn);
898 }
899
900 void WindowTreeClientImpl::OnWindowSharedPropertyChanged(
901 Id window_id,
902 const mojo::String& name,
903 mojo::Array<uint8_t> new_data) {
904 Window* window = GetWindowByServerId(window_id);
905 if (!window)
906 return;
907
908 InFlightPropertyChange new_change(window, name, new_data);
909 if (ApplyServerChangeToExistingInFlightChange(new_change))
910 return;
911
912 WindowPrivate(window).LocalSetSharedProperty(name, std::move(new_data));
913 }
914
915 void WindowTreeClientImpl::OnWindowInputEvent(uint32_t event_id,
916 Id window_id,
917 mojom::EventPtr event,
918 uint32_t event_observer_id) {
919 std::unique_ptr<ui::Event> ui_event = event.To<std::unique_ptr<ui::Event>>();
920 Window* window = GetWindowByServerId(window_id); // May be null.
921
922 // Non-zero event_observer_id means it matched an event observer on the
923 // server.
924 if (event_observer_id != 0 && has_event_observer_ &&
925 event_observer_id == event_observer_id_)
926 delegate_->OnEventObserved(*ui_event, window);
927
928 if (!window || !window->input_event_handler_) {
929 tree_->OnWindowInputEventAck(event_id, mojom::EventResult::UNHANDLED);
930 return;
931 }
932
933 std::unique_ptr<base::Callback<void(mojom::EventResult)>> ack_callback(
934 new base::Callback<void(mojom::EventResult)>(
935 base::Bind(&mojom::WindowTree::OnWindowInputEventAck,
936 base::Unretained(tree_), event_id)));
937 window->input_event_handler_->OnWindowInputEvent(
938 window, *event.To<std::unique_ptr<ui::Event>>().get(), &ack_callback);
939
940 // The handler did not take ownership of the callback, so we send the ack,
941 // marking the event as not consumed.
942 if (ack_callback)
943 ack_callback->Run(mojom::EventResult::UNHANDLED);
944 }
945
946 void WindowTreeClientImpl::OnEventObserved(mojom::EventPtr event,
947 uint32_t event_observer_id) {
948 if (has_event_observer_ && event_observer_id == event_observer_id_) {
949 std::unique_ptr<ui::Event> ui_event =
950 event.To<std::unique_ptr<ui::Event>>();
951 delegate_->OnEventObserved(*ui_event, nullptr /* target */);
952 }
953 }
954
955 void WindowTreeClientImpl::OnWindowFocused(Id focused_window_id) {
956 Window* focused_window = GetWindowByServerId(focused_window_id);
957 InFlightFocusChange new_change(this, focused_window);
958 if (ApplyServerChangeToExistingInFlightChange(new_change))
959 return;
960
961 LocalSetFocus(focused_window);
962 }
963
964 void WindowTreeClientImpl::OnWindowPredefinedCursorChanged(
965 Id window_id,
966 mojom::Cursor cursor) {
967 Window* window = GetWindowByServerId(window_id);
968 if (!window)
969 return;
970
971 InFlightPredefinedCursorChange new_change(window, cursor);
972 if (ApplyServerChangeToExistingInFlightChange(new_change))
973 return;
974
975 WindowPrivate(window).LocalSetPredefinedCursor(cursor);
976 }
977
978 void WindowTreeClientImpl::OnChangeCompleted(uint32_t change_id, bool success) {
979 std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
980 in_flight_map_.erase(change_id);
981 if (!change)
982 return;
983
984 if (!success)
985 change->ChangeFailed();
986
987 InFlightChange* next_change = GetOldestInFlightChangeMatching(*change);
988 if (next_change) {
989 if (!success)
990 next_change->SetRevertValueFrom(*change);
991 } else if (!success) {
992 change->Revert();
993 }
994 }
995
996 void WindowTreeClientImpl::GetWindowManager(
997 mojo::AssociatedInterfaceRequest<WindowManager> internal) {
998 window_manager_internal_.reset(
999 new mojo::AssociatedBinding<mojom::WindowManager>(this,
1000 std::move(internal)));
1001 }
1002
1003 void WindowTreeClientImpl::RequestClose(uint32_t window_id) {
1004 Window* window = GetWindowByServerId(window_id);
1005 if (!window || !IsRoot(window))
1006 return;
1007
1008 FOR_EACH_OBSERVER(WindowObserver, *WindowPrivate(window).observers(),
1009 OnRequestClose(window));
1010 }
1011
1012 void WindowTreeClientImpl::WmSetBounds(uint32_t change_id,
1013 Id window_id,
1014 mojo::RectPtr transit_bounds) {
1015 Window* window = GetWindowByServerId(window_id);
1016 bool result = false;
1017 if (window) {
1018 DCHECK(window_manager_delegate_);
1019 gfx::Rect bounds = transit_bounds.To<gfx::Rect>();
1020 result = window_manager_delegate_->OnWmSetBounds(window, &bounds);
1021 if (result) {
1022 // If the resulting bounds differ return false. Returning false ensures
1023 // the client applies the bounds we set below.
1024 result = bounds == transit_bounds.To<gfx::Rect>();
1025 window->SetBounds(bounds);
1026 }
1027 }
1028 if (window_manager_internal_client_)
1029 window_manager_internal_client_->WmResponse(change_id, result);
1030 }
1031
1032 void WindowTreeClientImpl::WmSetProperty(uint32_t change_id,
1033 Id window_id,
1034 const mojo::String& name,
1035 mojo::Array<uint8_t> transit_data) {
1036 Window* window = GetWindowByServerId(window_id);
1037 bool result = false;
1038 if (window) {
1039 DCHECK(window_manager_delegate_);
1040 std::unique_ptr<std::vector<uint8_t>> data;
1041 if (!transit_data.is_null()) {
1042 data.reset(
1043 new std::vector<uint8_t>(transit_data.To<std::vector<uint8_t>>()));
1044 }
1045 result = window_manager_delegate_->OnWmSetProperty(window, name, &data);
1046 if (result) {
1047 // If the resulting bounds differ return false. Returning false ensures
1048 // the client applies the bounds we set below.
1049 window->SetSharedPropertyInternal(name, data.get());
1050 }
1051 }
1052 if (window_manager_internal_client_)
1053 window_manager_internal_client_->WmResponse(change_id, result);
1054 }
1055
1056 void WindowTreeClientImpl::WmCreateTopLevelWindow(
1057 uint32_t change_id,
1058 ClientSpecificId requesting_client_id,
1059 mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) {
1060 std::map<std::string, std::vector<uint8_t>> properties =
1061 transport_properties.To<std::map<std::string, std::vector<uint8_t>>>();
1062 Window* window =
1063 window_manager_delegate_->OnWmCreateTopLevelWindow(&properties);
1064 embedded_windows_[requesting_client_id].insert(window);
1065 if (window_manager_internal_client_) {
1066 window_manager_internal_client_->OnWmCreatedTopLevelWindow(
1067 change_id, server_id(window));
1068 }
1069 }
1070
1071 void WindowTreeClientImpl::WmClientJankinessChanged(ClientSpecificId client_id,
1072 bool janky) {
1073 if (window_manager_delegate_) {
1074 auto it = embedded_windows_.find(client_id);
1075 CHECK(it != embedded_windows_.end());
1076 window_manager_delegate_->OnWmClientJankinessChanged(
1077 embedded_windows_[client_id], janky);
1078 }
1079 }
1080
1081 void WindowTreeClientImpl::OnAccelerator(uint32_t id, mojom::EventPtr event) {
1082 window_manager_delegate_->OnAccelerator(
1083 id, *event.To<std::unique_ptr<ui::Event>>().get());
1084 }
1085
1086 void WindowTreeClientImpl::SetFrameDecorationValues(
1087 mojom::FrameDecorationValuesPtr values) {
1088 if (window_manager_internal_client_) {
1089 window_manager_internal_client_->WmSetFrameDecorationValues(
1090 std::move(values));
1091 }
1092 }
1093
1094 void WindowTreeClientImpl::SetNonClientCursor(Window* window,
1095 mus::mojom::Cursor cursor_id) {
1096 window_manager_internal_client_->WmSetNonClientCursor(server_id(window),
1097 cursor_id);
1098 }
1099
1100 void WindowTreeClientImpl::AddAccelerator(
1101 uint32_t id,
1102 mojom::EventMatcherPtr event_matcher,
1103 const base::Callback<void(bool)>& callback) {
1104 if (window_manager_internal_client_) {
1105 window_manager_internal_client_->AddAccelerator(
1106 id, std::move(event_matcher), callback);
1107 }
1108 }
1109
1110 void WindowTreeClientImpl::RemoveAccelerator(uint32_t id) {
1111 if (window_manager_internal_client_) {
1112 window_manager_internal_client_->RemoveAccelerator(id);
1113 }
1114 }
1115
1116 void WindowTreeClientImpl::AddActivationParent(Window* window) {
1117 if (window_manager_internal_client_)
1118 window_manager_internal_client_->AddActivationParent(server_id(window));
1119 }
1120
1121 void WindowTreeClientImpl::RemoveActivationParent(Window* window) {
1122 if (window_manager_internal_client_)
1123 window_manager_internal_client_->RemoveActivationParent(server_id(window));
1124 }
1125
1126 void WindowTreeClientImpl::ActivateNextWindow() {
1127 if (window_manager_internal_client_)
1128 window_manager_internal_client_->ActivateNextWindow();
1129 }
1130
1131 void WindowTreeClientImpl::SetUnderlaySurfaceOffsetAndExtendedHitArea(
1132 Window* window,
1133 const gfx::Vector2d& offset,
1134 const gfx::Insets& hit_area) {
1135 if (window_manager_internal_client_) {
1136 window_manager_internal_client_->SetUnderlaySurfaceOffsetAndExtendedHitArea(
1137 server_id(window), offset.x(), offset.y(),
1138 mojo::Insets::From(hit_area));
1139 }
1140 }
1141
1142 } // namespace mus
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698