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

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

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

Powered by Google App Engine
This is Rietveld 408576698