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

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

Powered by Google App Engine
This is Rietveld 408576698