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

Side by Side Diff: services/ui/public/cpp/window_tree_client.cc

Issue 2651593002: mus: Remove the old client lib. (Closed)
Patch Set: restore test Created 3 years, 11 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 "services/ui/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 "base/strings/stringprintf.h"
16 #include "mojo/public/cpp/bindings/map.h"
17 #include "services/service_manager/public/cpp/connector.h"
18 #include "services/ui/common/util.h"
19 #include "services/ui/public/cpp/in_flight_change.h"
20 #include "services/ui/public/cpp/input_event_handler.h"
21 #include "services/ui/public/cpp/window_drop_target.h"
22 #include "services/ui/public/cpp/window_manager_delegate.h"
23 #include "services/ui/public/cpp/window_observer.h"
24 #include "services/ui/public/cpp/window_private.h"
25 #include "services/ui/public/cpp/window_tracker.h"
26 #include "services/ui/public/cpp/window_tree_client_delegate.h"
27 #include "services/ui/public/cpp/window_tree_client_observer.h"
28 #include "services/ui/public/interfaces/constants.mojom.h"
29 #include "services/ui/public/interfaces/window_manager_window_tree_factory.mojom .h"
30 #include "ui/display/screen.h"
31 #include "ui/events/event.h"
32 #include "ui/gfx/geometry/dip_util.h"
33 #include "ui/gfx/geometry/insets.h"
34 #include "ui/gfx/geometry/size.h"
35
36 namespace ui {
37
38 Id MakeTransportId(ClientSpecificId client_id, ClientSpecificId local_id) {
39 return (client_id << 16) | local_id;
40 }
41
42 // Helper function to get the device_scale_factor() of the display::Display
43 // with |display_id|.
44 float ScaleFactorForDisplay(int64_t display_id) {
45 // TODO(jonross): Remove this once aura-mus is complete. Currently the screen
46 // is not being set properly for mus-in-renderer. (http://crbug.com/659155)
47 if (!display::Screen::GetScreen())
48 return 1.f;
49
50 // TODO(riajiang): Change to use display::GetDisplayWithDisplayId() after
51 // https://codereview.chromium.org/2361283002/ is landed.
52 std::vector<display::Display> displays =
53 display::Screen::GetScreen()->GetAllDisplays();
54 auto iter = std::find_if(displays.begin(), displays.end(),
55 [display_id](const display::Display& display) {
56 return display.id() == display_id;
57 });
58 if (iter != displays.end())
59 return iter->device_scale_factor();
60 return 1.f;
61 }
62
63 // Helper called to construct a local window object from transport data.
64 Window* AddWindowToClient(WindowTreeClient* client,
65 Window* parent,
66 const mojom::WindowDataPtr& window_data) {
67 // We don't use the ctor that takes a WindowTreeClient here, since it will
68 // call back to the service and attempt to create a new window.
69 Window* window = WindowPrivate::LocalCreate();
70 WindowPrivate private_window(window);
71 private_window.set_client(client);
72 private_window.set_server_id(window_data->window_id);
73 private_window.set_visible(window_data->visible);
74 private_window.set_properties(
75 mojo::UnorderedMapToMap(window_data->properties));
76 client->AddWindow(window);
77 private_window.LocalSetBounds(
78 gfx::Rect(),
79 gfx::ConvertRectToDIP(ScaleFactorForDisplay(window->display_id()),
80 window_data->bounds));
81 if (parent)
82 WindowPrivate(parent).LocalAddChild(window);
83 return window;
84 }
85
86 struct WindowTreeClient::CurrentDragState {
87 // The current change id of the current drag an drop ipc.
88 uint32_t change_id;
89
90 // The effect to return when we send our finish signal.
91 uint32_t completed_action;
92
93 // Callback executed when a drag initiated by PerformDragDrop() is completed.
94 base::Callback<void(bool, uint32_t)> on_finished;
95 };
96
97 WindowTreeClient::WindowTreeClient(
98 WindowTreeClientDelegate* delegate,
99 WindowManagerDelegate* window_manager_delegate,
100 mojo::InterfaceRequest<mojom::WindowTreeClient> request)
101 : client_id_(0),
102 next_window_id_(1),
103 next_change_id_(1),
104 delegate_(delegate),
105 window_manager_delegate_(window_manager_delegate),
106 capture_window_(nullptr),
107 focused_window_(nullptr),
108 binding_(this),
109 tree_(nullptr),
110 in_destructor_(false),
111 weak_factory_(this) {
112 // Allow for a null request in tests.
113 if (request.is_pending())
114 binding_.Bind(std::move(request));
115 if (window_manager_delegate)
116 window_manager_delegate->SetWindowManagerClient(this);
117 }
118
119 WindowTreeClient::~WindowTreeClient() {
120 in_destructor_ = true;
121
122 for (auto& observer : observers_)
123 observer.OnWillDestroyClient(this);
124
125 std::vector<Window*> non_owned;
126 WindowTracker tracker;
127 while (!windows_.empty()) {
128 IdToWindowMap::iterator it = windows_.begin();
129 if (it->second->WasCreatedByThisClient()) {
130 it->second->Destroy();
131 } else {
132 tracker.Add(it->second);
133 windows_.erase(it);
134 }
135 }
136
137 // Delete the non-owned windows last. In the typical case these are roots. The
138 // exception is the window manager and embed roots, which may know about
139 // other random windows that it doesn't own.
140 // NOTE: we manually delete as we're a friend.
141 while (!tracker.windows().empty())
142 delete tracker.windows().front();
143
144 for (auto& observer : observers_)
145 observer.OnDidDestroyClient(this);
146 }
147
148 void WindowTreeClient::ConnectViaWindowTreeFactory(
149 service_manager::Connector* connector) {
150 // The client id doesn't really matter, we use 101 purely for debugging.
151 client_id_ = 101;
152
153 mojom::WindowTreeFactoryPtr factory;
154 connector->BindInterface(ui::mojom::kServiceName, &factory);
155 mojom::WindowTreePtr window_tree;
156 factory->CreateWindowTree(MakeRequest(&window_tree),
157 binding_.CreateInterfacePtrAndBind());
158 SetWindowTree(std::move(window_tree));
159 }
160
161 void WindowTreeClient::ConnectAsWindowManager(
162 service_manager::Connector* connector) {
163 DCHECK(window_manager_delegate_);
164
165 mojom::WindowManagerWindowTreeFactoryPtr factory;
166 connector->BindInterface(ui::mojom::kServiceName, &factory);
167 mojom::WindowTreePtr window_tree;
168 factory->CreateWindowTree(MakeRequest(&window_tree),
169 binding_.CreateInterfacePtrAndBind());
170 SetWindowTree(std::move(window_tree));
171 }
172
173 void WindowTreeClient::WaitForEmbed() {
174 DCHECK(roots_.empty());
175 // OnEmbed() is the first function called.
176 binding_.WaitForIncomingMethodCall();
177 // TODO(sky): deal with pipe being closed before we get OnEmbed().
178 }
179
180 void WindowTreeClient::DestroyWindow(Window* window) {
181 DCHECK(tree_);
182 const uint32_t change_id = ScheduleInFlightChange(
183 base::MakeUnique<CrashInFlightChange>(window, ChangeType::DELETE_WINDOW));
184 tree_->DeleteWindow(change_id, server_id(window));
185 }
186
187 void WindowTreeClient::AddChild(Window* parent, Id child_id) {
188 DCHECK(tree_);
189 const uint32_t change_id = ScheduleInFlightChange(
190 base::MakeUnique<CrashInFlightChange>(parent, ChangeType::ADD_CHILD));
191 tree_->AddWindow(change_id, parent->server_id(), child_id);
192 }
193
194 void WindowTreeClient::RemoveChild(Window* parent, Id child_id) {
195 DCHECK(tree_);
196 const uint32_t change_id = ScheduleInFlightChange(
197 base::MakeUnique<CrashInFlightChange>(parent, ChangeType::REMOVE_CHILD));
198 tree_->RemoveWindowFromParent(change_id, child_id);
199 }
200
201 void WindowTreeClient::AddTransientWindow(Window* window,
202 Id transient_window_id) {
203 DCHECK(tree_);
204 const uint32_t change_id =
205 ScheduleInFlightChange(base::MakeUnique<CrashInFlightChange>(
206 window, ChangeType::ADD_TRANSIENT_WINDOW));
207 tree_->AddTransientWindow(change_id, server_id(window), transient_window_id);
208 }
209
210 void WindowTreeClient::RemoveTransientWindowFromParent(Window* window) {
211 DCHECK(tree_);
212 const uint32_t change_id =
213 ScheduleInFlightChange(base::MakeUnique<CrashInFlightChange>(
214 window, ChangeType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT));
215 tree_->RemoveTransientWindowFromParent(change_id, server_id(window));
216 }
217
218 void WindowTreeClient::SetModal(Window* window) {
219 DCHECK(tree_);
220 const uint32_t change_id =
221 ScheduleInFlightChange(base::MakeUnique<InFlightSetModalChange>(window));
222 tree_->SetModal(change_id, server_id(window));
223 }
224
225 void WindowTreeClient::Reorder(Window* window,
226 Id relative_window_id,
227 mojom::OrderDirection direction) {
228 DCHECK(tree_);
229 const uint32_t change_id = ScheduleInFlightChange(
230 base::MakeUnique<CrashInFlightChange>(window, ChangeType::REORDER));
231 tree_->ReorderWindow(change_id, server_id(window), relative_window_id,
232 direction);
233 }
234
235 bool WindowTreeClient::WasCreatedByThisClient(const Window* window) const {
236 // Windows created via CreateTopLevelWindow() are not owned by us, but have
237 // our client id. const_cast is required by set.
238 return HiWord(server_id(window)) == client_id_ &&
239 roots_.count(const_cast<Window*>(window)) == 0;
240 }
241
242 void WindowTreeClient::SetBounds(Window* window,
243 const gfx::Rect& old_bounds,
244 const gfx::Rect& bounds) {
245 DCHECK(tree_);
246 const uint32_t change_id = ScheduleInFlightChange(
247 base::MakeUnique<InFlightBoundsChange>(window, old_bounds));
248 tree_->SetWindowBounds(
249 change_id, server_id(window),
250 gfx::ConvertRectToPixel(ScaleFactorForDisplay(window->display_id()),
251 bounds));
252 }
253
254 void WindowTreeClient::SetCapture(Window* window) {
255 // In order for us to get here we had to have exposed a window, which implies
256 // we got a client.
257 DCHECK(tree_);
258 if (capture_window_ == window)
259 return;
260 const uint32_t change_id = ScheduleInFlightChange(
261 base::MakeUnique<InFlightCaptureChange>(this, capture_window_));
262 tree_->SetCapture(change_id, server_id(window));
263 LocalSetCapture(window);
264 }
265
266 void WindowTreeClient::ReleaseCapture(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::MakeUnique<InFlightCaptureChange>(this, window));
274 tree_->ReleaseCapture(change_id, server_id(window));
275 LocalSetCapture(nullptr);
276 }
277
278 void WindowTreeClient::SetClientArea(
279 Id window_id,
280 const gfx::Insets& client_area,
281 const std::vector<gfx::Rect>& additional_client_areas) {
282 DCHECK(tree_);
283 float device_scale_factor =
284 ScaleFactorForDisplay(GetWindowByServerId(window_id)->display_id());
285 std::vector<gfx::Rect> additional_client_areas_in_pixel;
286 for (const gfx::Rect& area : additional_client_areas) {
287 additional_client_areas_in_pixel.push_back(
288 gfx::ConvertRectToPixel(device_scale_factor, area));
289 }
290 tree_->SetClientArea(
291 window_id, gfx::ConvertInsetsToPixel(device_scale_factor, client_area),
292 additional_client_areas_in_pixel);
293 }
294
295 void WindowTreeClient::SetHitTestMask(Id window_id, const gfx::Rect& mask) {
296 DCHECK(tree_);
297 tree_->SetHitTestMask(
298 window_id,
299 gfx::ConvertRectToPixel(
300 ScaleFactorForDisplay(GetWindowByServerId(window_id)->display_id()),
301 mask));
302 }
303
304 void WindowTreeClient::ClearHitTestMask(Id window_id) {
305 DCHECK(tree_);
306 tree_->SetHitTestMask(window_id, base::nullopt);
307 }
308
309 void WindowTreeClient::SetFocus(Window* window) {
310 // In order for us to get here we had to have exposed a window, which implies
311 // we got a client.
312 DCHECK(tree_);
313 const uint32_t change_id = ScheduleInFlightChange(
314 base::MakeUnique<InFlightFocusChange>(this, focused_window_));
315 tree_->SetFocus(change_id, window ? server_id(window) : 0);
316 LocalSetFocus(window);
317 }
318
319 void WindowTreeClient::SetCanFocus(Id window_id, bool can_focus) {
320 DCHECK(tree_);
321 tree_->SetCanFocus(window_id, can_focus);
322 }
323
324 void WindowTreeClient::SetPredefinedCursor(Id window_id,
325 ui::mojom::Cursor cursor_id) {
326 DCHECK(tree_);
327
328 Window* window = GetWindowByServerId(window_id);
329 if (!window)
330 return;
331
332 // We make an inflight change thing here.
333 const uint32_t change_id =
334 ScheduleInFlightChange(base::MakeUnique<InFlightPredefinedCursorChange>(
335 window, window->predefined_cursor()));
336 tree_->SetPredefinedCursor(change_id, window_id, cursor_id);
337 }
338
339 void WindowTreeClient::SetVisible(Window* window, bool visible) {
340 DCHECK(tree_);
341 const uint32_t change_id = ScheduleInFlightChange(
342 base::MakeUnique<InFlightVisibleChange>(window, !visible));
343 tree_->SetWindowVisibility(change_id, server_id(window), visible);
344 }
345
346 void WindowTreeClient::SetOpacity(Window* window, float opacity) {
347 DCHECK(tree_);
348 const uint32_t change_id = ScheduleInFlightChange(
349 base::MakeUnique<InFlightOpacityChange>(window, window->opacity()));
350 tree_->SetWindowOpacity(change_id, server_id(window), opacity);
351 }
352
353 void WindowTreeClient::SetProperty(
354 Window* window,
355 const std::string& name,
356 const base::Optional<std::vector<uint8_t>>& data) {
357 DCHECK(tree_);
358
359 base::Optional<std::vector<uint8_t>> old_value;
360 if (window->HasSharedProperty(name))
361 old_value.emplace(window->properties_[name]);
362
363 const uint32_t change_id =
364 ScheduleInFlightChange(base::MakeUnique<InFlightPropertyChange>(
365 window, name, std::move(old_value)));
366 tree_->SetWindowProperty(change_id, server_id(window), name, data);
367 }
368
369 void WindowTreeClient::SetWindowTextInputState(
370 Id window_id,
371 mojo::TextInputStatePtr state) {
372 DCHECK(tree_);
373 tree_->SetWindowTextInputState(window_id, std::move(state));
374 }
375
376 void WindowTreeClient::SetImeVisibility(Id window_id,
377 bool visible,
378 mojo::TextInputStatePtr state) {
379 DCHECK(tree_);
380 tree_->SetImeVisibility(window_id, visible, std::move(state));
381 }
382
383 void WindowTreeClient::Embed(Id window_id,
384 mojom::WindowTreeClientPtr client,
385 uint32_t flags,
386 const mojom::WindowTree::EmbedCallback& callback) {
387 DCHECK(tree_);
388 tree_->Embed(window_id, std::move(client), flags, callback);
389 }
390
391 void WindowTreeClient::RequestClose(Window* window) {
392 if (window_manager_internal_client_)
393 window_manager_internal_client_->WmRequestClose(server_id(window));
394 }
395
396 void WindowTreeClient::AttachCompositorFrameSink(
397 Id window_id,
398 cc::mojom::MojoCompositorFrameSinkRequest compositor_frame_sink,
399 cc::mojom::MojoCompositorFrameSinkClientPtr client) {
400 DCHECK(tree_);
401 tree_->AttachCompositorFrameSink(window_id, std::move(compositor_frame_sink),
402 std::move(client));
403 }
404
405 void WindowTreeClient::LocalSetCapture(Window* window) {
406 if (capture_window_ == window)
407 return;
408 Window* lost_capture = capture_window_;
409 capture_window_ = window;
410 if (lost_capture) {
411 for (auto& observer : *WindowPrivate(lost_capture).observers())
412 observer.OnWindowLostCapture(lost_capture);
413 }
414 for (auto& observer : observers_)
415 observer.OnWindowTreeCaptureChanged(window, lost_capture);
416 }
417
418 void WindowTreeClient::LocalSetFocus(Window* focused) {
419 Window* blurred = focused_window_;
420 // Update |focused_window_| before calling any of the observers, so that the
421 // observers get the correct result from calling |Window::HasFocus()|,
422 // |WindowTreeClient::GetFocusedWindow()| etc.
423 focused_window_ = focused;
424 if (blurred) {
425 for (auto& observer : *WindowPrivate(blurred).observers())
426 observer.OnWindowFocusChanged(focused, blurred);
427 }
428 if (focused) {
429 for (auto& observer : *WindowPrivate(focused).observers())
430 observer.OnWindowFocusChanged(focused, blurred);
431 }
432 for (auto& observer : observers_)
433 observer.OnWindowTreeFocusChanged(focused, blurred);
434 }
435
436 void WindowTreeClient::AddWindow(Window* window) {
437 DCHECK(windows_.find(server_id(window)) == windows_.end());
438 windows_[server_id(window)] = window;
439 }
440
441 void WindowTreeClient::OnWindowDestroying(Window* window) {
442 if (window == capture_window_) {
443 // Normally the queue updates itself upon window destruction. However since
444 // |window| is being destroyed, it will not be possible to notify its
445 // observers of the lost capture. Update local state now.
446 LocalSetCapture(nullptr);
447 }
448 // For |focused_window_| window destruction clears the entire focus state.
449 }
450
451 void WindowTreeClient::OnWindowDestroyed(Window* window) {
452 windows_.erase(server_id(window));
453
454 for (auto& entry : embedded_windows_) {
455 auto it = entry.second.find(window);
456 if (it != entry.second.end()) {
457 entry.second.erase(it);
458 break;
459 }
460 }
461
462 // Remove any InFlightChanges associated with the window.
463 std::set<uint32_t> in_flight_change_ids_to_remove;
464 for (const auto& pair : in_flight_map_) {
465 if (pair.second->window() == window)
466 in_flight_change_ids_to_remove.insert(pair.first);
467 }
468 for (auto change_id : in_flight_change_ids_to_remove)
469 in_flight_map_.erase(change_id);
470
471 const bool was_root = roots_.erase(window) > 0;
472 if (!in_destructor_ && was_root && roots_.empty() && is_from_embed_)
473 delegate_->OnEmbedRootDestroyed(window);
474 }
475
476 Window* WindowTreeClient::GetWindowByServerId(Id id) {
477 IdToWindowMap::const_iterator it = windows_.find(id);
478 return it != windows_.end() ? it->second : NULL;
479 }
480
481 InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching(
482 const InFlightChange& change) {
483 for (const auto& pair : in_flight_map_) {
484 if (pair.second->window() == change.window() &&
485 pair.second->change_type() == change.change_type() &&
486 pair.second->Matches(change)) {
487 return pair.second.get();
488 }
489 }
490 return nullptr;
491 }
492
493 uint32_t WindowTreeClient::ScheduleInFlightChange(
494 std::unique_ptr<InFlightChange> change) {
495 DCHECK(!change->window() ||
496 windows_.count(change->window()->server_id()) > 0);
497 const uint32_t change_id = next_change_id_++;
498 in_flight_map_[change_id] = std::move(change);
499 return change_id;
500 }
501
502 bool WindowTreeClient::ApplyServerChangeToExistingInFlightChange(
503 const InFlightChange& change) {
504 InFlightChange* existing_change = GetOldestInFlightChangeMatching(change);
505 if (!existing_change)
506 return false;
507
508 existing_change->SetRevertValueFrom(change);
509 return true;
510 }
511
512 void WindowTreeClient::BuildWindowTree(
513 const std::vector<mojom::WindowDataPtr>& windows,
514 Window* initial_parent) {
515 for (const auto& window_data : windows) {
516 Window* parent = window_data->parent_id == 0
517 ? nullptr
518 : GetWindowByServerId(window_data->parent_id);
519 Window* existing_window = GetWindowByServerId(window_data->window_id);
520 if (!existing_window)
521 AddWindowToClient(this, parent, window_data);
522 else if (parent)
523 WindowPrivate(parent).LocalAddChild(existing_window);
524 }
525 }
526
527 Window* WindowTreeClient::NewWindowImpl(
528 NewWindowType type,
529 const Window::SharedProperties* properties) {
530 DCHECK(tree_);
531 Window* window =
532 new Window(this, MakeTransportId(client_id_, next_window_id_++));
533 if (properties)
534 window->properties_ = *properties;
535 AddWindow(window);
536
537 const uint32_t change_id =
538 ScheduleInFlightChange(base::MakeUnique<CrashInFlightChange>(
539 window, type == NewWindowType::CHILD
540 ? ChangeType::NEW_WINDOW
541 : ChangeType::NEW_TOP_LEVEL_WINDOW));
542 std::unordered_map<std::string, std::vector<uint8_t>> transport_properties;
543 if (properties)
544 transport_properties = mojo::MapToUnorderedMap(*properties);
545
546 if (type == NewWindowType::CHILD) {
547 tree_->NewWindow(change_id, server_id(window),
548 std::move(transport_properties));
549 } else {
550 roots_.insert(window);
551 tree_->NewTopLevelWindow(change_id, server_id(window),
552 transport_properties);
553 }
554 return window;
555 }
556
557 void WindowTreeClient::SetWindowTree(mojom::WindowTreePtr window_tree_ptr) {
558 tree_ptr_ = std::move(window_tree_ptr);
559 tree_ = tree_ptr_.get();
560
561 tree_ptr_->GetCursorLocationMemory(
562 base::Bind(&WindowTreeClient::OnReceivedCursorLocationMemory,
563 weak_factory_.GetWeakPtr()));
564
565 tree_ptr_.set_connection_error_handler(base::Bind(
566 &WindowTreeClient::OnConnectionLost, weak_factory_.GetWeakPtr()));
567
568 if (window_manager_delegate_) {
569 tree_ptr_->GetWindowManagerClient(MakeRequest(
570 &window_manager_internal_client_, tree_ptr_.associated_group()));
571 }
572 }
573
574 void WindowTreeClient::OnConnectionLost() {
575 delegate_->OnLostConnection(this);
576 }
577
578 void WindowTreeClient::OnEmbedImpl(mojom::WindowTree* window_tree,
579 ClientSpecificId client_id,
580 mojom::WindowDataPtr root_data,
581 int64_t display_id,
582 Id focused_window_id,
583 bool drawn) {
584 // WARNING: this is only called if WindowTreeClient was created as the
585 // result of an embedding.
586 tree_ = window_tree;
587 client_id_ = client_id;
588
589 DCHECK(roots_.empty());
590 Window* root = AddWindowToClient(this, nullptr, root_data);
591 WindowPrivate(root).LocalSetDisplay(display_id);
592 roots_.insert(root);
593
594 focused_window_ = GetWindowByServerId(focused_window_id);
595
596 WindowPrivate(root).LocalSetParentDrawn(drawn);
597
598 delegate_->OnEmbed(root);
599
600 if (focused_window_) {
601 for (auto& observer : observers_)
602 observer.OnWindowTreeFocusChanged(focused_window_, nullptr);
603 }
604 }
605
606 void WindowTreeClient::WmNewDisplayAddedImpl(const display::Display& display,
607 mojom::WindowDataPtr root_data,
608 bool parent_drawn) {
609 DCHECK(window_manager_delegate_);
610
611 Window* root = AddWindowToClient(this, nullptr, root_data);
612 WindowPrivate(root).LocalSetDisplay(display.id());
613 WindowPrivate(root).LocalSetParentDrawn(parent_drawn);
614 roots_.insert(root);
615
616 window_manager_delegate_->OnWmNewDisplay(root, display);
617 }
618
619 void WindowTreeClient::OnReceivedCursorLocationMemory(
620 mojo::ScopedSharedBufferHandle handle) {
621 cursor_location_mapping_ = handle->Map(sizeof(base::subtle::Atomic32));
622 DCHECK(cursor_location_mapping_);
623 }
624
625 void WindowTreeClient::OnWmMoveLoopCompleted(uint32_t change_id,
626 bool completed) {
627 if (window_manager_internal_client_)
628 window_manager_internal_client_->WmResponse(change_id, completed);
629
630 if (change_id == current_wm_move_loop_change_) {
631 current_wm_move_loop_change_ = 0;
632 current_wm_move_loop_window_id_ = 0;
633 }
634 }
635
636 ////////////////////////////////////////////////////////////////////////////////
637 // WindowTreeClient, WindowTreeClient implementation:
638
639 const std::set<Window*>& WindowTreeClient::GetRoots() {
640 return roots_;
641 }
642
643 Window* WindowTreeClient::GetFocusedWindow() {
644 return focused_window_;
645 }
646
647 void WindowTreeClient::ClearFocus() {
648 if (!focused_window_)
649 return;
650
651 SetFocus(nullptr);
652 }
653
654 gfx::Point WindowTreeClient::GetCursorScreenPoint() {
655 // We raced initialization. Return (0, 0).
656 if (!cursor_location_memory())
657 return gfx::Point();
658
659 base::subtle::Atomic32 location =
660 base::subtle::NoBarrier_Load(cursor_location_memory());
661 return gfx::Point(static_cast<int16_t>(location >> 16),
662 static_cast<int16_t>(location & 0xFFFF));
663 }
664
665 void WindowTreeClient::StartPointerWatcher(bool want_moves) {
666 if (has_pointer_watcher_)
667 StopPointerWatcher();
668 has_pointer_watcher_ = true;
669 tree_->StartPointerWatcher(want_moves);
670 }
671
672 void WindowTreeClient::StopPointerWatcher() {
673 DCHECK(has_pointer_watcher_);
674 tree_->StopPointerWatcher();
675 has_pointer_watcher_ = false;
676 }
677
678 void WindowTreeClient::PerformDragDrop(
679 Window* window,
680 const std::map<std::string, std::vector<uint8_t>>& drag_data,
681 int drag_operation,
682 const gfx::Point& cursor_location,
683 const SkBitmap& bitmap,
684 const base::Callback<void(bool, uint32_t)>& callback) {
685 DCHECK(!current_drag_state_);
686
687 // TODO(erg): Pass |cursor_location| and |bitmap| in PerformDragDrop() when
688 // we start showing an image representation of the drag under the cursor.
689
690 auto unordered_drag_data = mojo::MapToUnorderedMap(drag_data);
691
692 if (window->drop_target()) {
693 // To minimize the number of round trips, copy the drag drop data to our
694 // handler here, instead of forcing mus to send this same data back.
695 OnDragDropStart(unordered_drag_data);
696 }
697
698 uint32_t current_drag_change = ScheduleInFlightChange(
699 base::MakeUnique<InFlightDragChange>(window, ChangeType::DRAG_LOOP));
700 current_drag_state_.reset(new CurrentDragState{
701 current_drag_change, ui::mojom::kDropEffectNone, callback});
702
703 tree_->PerformDragDrop(current_drag_change, window->server_id(),
704 unordered_drag_data, drag_operation);
705 }
706
707 void WindowTreeClient::CancelDragDrop(Window* window) {
708 // Server will clean up drag and fail the in-flight change.
709 tree_->CancelDragDrop(window->server_id());
710 }
711
712 void WindowTreeClient::PerformWindowMove(
713 Window* window,
714 ui::mojom::MoveLoopSource source,
715 const gfx::Point& cursor_location,
716 const base::Callback<void(bool)>& callback) {
717 DCHECK(on_current_move_finished_.is_null());
718 on_current_move_finished_ = callback;
719
720 current_move_loop_change_ = ScheduleInFlightChange(
721 base::MakeUnique<InFlightDragChange>(window, ChangeType::MOVE_LOOP));
722 // Tell the window manager to take over moving us.
723 tree_->PerformWindowMove(current_move_loop_change_, window->server_id(),
724 source, cursor_location);
725 }
726
727 void WindowTreeClient::CancelWindowMove(Window* window) {
728 tree_->CancelWindowMove(window->server_id());
729 }
730
731 Window* WindowTreeClient::NewWindow(
732 const Window::SharedProperties* properties) {
733 return NewWindowImpl(NewWindowType::CHILD, properties);
734 }
735
736 Window* WindowTreeClient::NewTopLevelWindow(
737 const Window::SharedProperties* properties) {
738 Window* window = NewWindowImpl(NewWindowType::TOP_LEVEL, properties);
739 // Assume newly created top level windows are drawn by default, otherwise
740 // requests to focus will fail. We will get the real value in
741 // OnTopLevelCreated().
742 window->LocalSetParentDrawn(true);
743 return window;
744 }
745
746 #if !defined(NDEBUG)
747 std::string WindowTreeClient::GetDebugWindowHierarchy() const {
748 std::string result;
749 for (Window* root : roots_)
750 BuildDebugInfo(std::string(), root, &result);
751 return result;
752 }
753
754 void WindowTreeClient::BuildDebugInfo(const std::string& depth,
755 Window* window,
756 std::string* result) const {
757 std::string name = window->GetName();
758 *result += base::StringPrintf(
759 "%sid=%d visible=%s bounds=%d,%d %dx%d %s\n", depth.c_str(),
760 window->server_id(), window->visible() ? "true" : "false",
761 window->bounds().x(), window->bounds().y(), window->bounds().width(),
762 window->bounds().height(), !name.empty() ? name.c_str() : "(no name)");
763 for (Window* child : window->children())
764 BuildDebugInfo(depth + " ", child, result);
765 }
766 #endif // !defined(NDEBUG)
767
768 ////////////////////////////////////////////////////////////////////////////////
769 // WindowTreeClient, WindowTreeClient implementation:
770
771 void WindowTreeClient::AddObserver(WindowTreeClientObserver* observer) {
772 observers_.AddObserver(observer);
773 }
774
775 void WindowTreeClient::RemoveObserver(WindowTreeClientObserver* observer) {
776 observers_.RemoveObserver(observer);
777 }
778
779 void WindowTreeClient::SetCanAcceptDrops(Id window_id, bool can_accept_drops) {
780 DCHECK(tree_);
781 tree_->SetCanAcceptDrops(window_id, can_accept_drops);
782 }
783
784 void WindowTreeClient::SetCanAcceptEvents(Id window_id,
785 bool can_accept_events) {
786 DCHECK(tree_);
787 tree_->SetCanAcceptEvents(window_id, can_accept_events);
788 }
789
790 void WindowTreeClient::OnEmbed(ClientSpecificId client_id,
791 mojom::WindowDataPtr root_data,
792 mojom::WindowTreePtr tree,
793 int64_t display_id,
794 Id focused_window_id,
795 bool drawn) {
796 DCHECK(!tree_ptr_);
797 tree_ptr_ = std::move(tree);
798
799 is_from_embed_ = true;
800
801 if (window_manager_delegate_) {
802 tree_ptr_->GetWindowManagerClient(MakeRequest(
803 &window_manager_internal_client_, tree_ptr_.associated_group()));
804 }
805
806 OnEmbedImpl(tree_ptr_.get(), client_id, std::move(root_data), display_id,
807 focused_window_id, drawn);
808 }
809
810 void WindowTreeClient::OnEmbeddedAppDisconnected(Id window_id) {
811 Window* window = GetWindowByServerId(window_id);
812 if (window) {
813 for (auto& observer : *WindowPrivate(window).observers())
814 observer.OnWindowEmbeddedAppDisconnected(window);
815 }
816 }
817
818 void WindowTreeClient::OnUnembed(Id window_id) {
819 Window* window = GetWindowByServerId(window_id);
820 if (!window)
821 return;
822
823 delegate_->OnUnembed(window);
824 WindowPrivate(window).LocalDestroy();
825 }
826
827 void WindowTreeClient::OnCaptureChanged(Id new_capture_window_id,
828 Id old_capture_window_id) {
829 Window* new_capture_window = GetWindowByServerId(new_capture_window_id);
830 Window* lost_capture_window = GetWindowByServerId(old_capture_window_id);
831 if (!new_capture_window && !lost_capture_window)
832 return;
833
834 InFlightCaptureChange change(this, new_capture_window);
835 if (ApplyServerChangeToExistingInFlightChange(change))
836 return;
837
838 LocalSetCapture(new_capture_window);
839 }
840
841 void WindowTreeClient::OnTopLevelCreated(uint32_t change_id,
842 mojom::WindowDataPtr data,
843 int64_t display_id,
844 bool drawn) {
845 // The server ack'd the top level window we created and supplied the state
846 // of the window at the time the server created it. For properties we do not
847 // have changes in flight for we can update them immediately. For properties
848 // with changes in flight we set the revert value from the server.
849
850 if (!in_flight_map_.count(change_id)) {
851 // The window may have been destroyed locally before the server could finish
852 // creating the window, and before the server received the notification that
853 // the window has been destroyed.
854 return;
855 }
856 std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
857 in_flight_map_.erase(change_id);
858
859 Window* window = change->window();
860 WindowPrivate window_private(window);
861
862 // Drawn state and display-id always come from the server (they can't be
863 // modified locally).
864 window_private.LocalSetParentDrawn(drawn);
865 window_private.LocalSetDisplay(display_id);
866
867 // The default visibilty is false, we only need update visibility if it
868 // differs from that.
869 if (data->visible) {
870 InFlightVisibleChange visible_change(window, data->visible);
871 InFlightChange* current_change =
872 GetOldestInFlightChangeMatching(visible_change);
873 if (current_change)
874 current_change->SetRevertValueFrom(visible_change);
875 else
876 window_private.LocalSetVisible(true);
877 }
878
879 const gfx::Rect bounds(data->bounds);
880 {
881 InFlightBoundsChange bounds_change(window, bounds);
882 InFlightChange* current_change =
883 GetOldestInFlightChangeMatching(bounds_change);
884 if (current_change)
885 current_change->SetRevertValueFrom(bounds_change);
886 else if (window->bounds() != bounds)
887 window_private.LocalSetBounds(window->bounds(), bounds);
888 }
889
890 // There is currently no API to bulk set properties, so we iterate over each
891 // property individually.
892 Window::SharedProperties properties =
893 mojo::UnorderedMapToMap(data->properties);
894 for (const auto& pair : properties) {
895 InFlightPropertyChange property_change(window, pair.first, pair.second);
896 InFlightChange* current_change =
897 GetOldestInFlightChangeMatching(property_change);
898 if (current_change)
899 current_change->SetRevertValueFrom(property_change);
900 else
901 window_private.LocalSetSharedProperty(pair.first, &(pair.second));
902 }
903
904 // Top level windows should not have a parent.
905 DCHECK_EQ(0u, data->parent_id);
906 }
907
908 void WindowTreeClient::OnWindowBoundsChanged(Id window_id,
909 const gfx::Rect& old_bounds,
910 const gfx::Rect& new_bounds) {
911 Window* window = GetWindowByServerId(window_id);
912 if (!window)
913 return;
914
915 float device_scale_factor = ScaleFactorForDisplay(window->display_id());
916 gfx::Rect old_bounds_in_dip =
917 gfx::ConvertRectToDIP(device_scale_factor, old_bounds);
918 gfx::Rect new_bounds_in_dip =
919 gfx::ConvertRectToDIP(device_scale_factor, new_bounds);
920
921 InFlightBoundsChange new_change(window, new_bounds_in_dip);
922 if (ApplyServerChangeToExistingInFlightChange(new_change))
923 return;
924 WindowPrivate(window).LocalSetBounds(old_bounds_in_dip, new_bounds_in_dip);
925 }
926
927 void WindowTreeClient::OnClientAreaChanged(
928 uint32_t window_id,
929 const gfx::Insets& new_client_area,
930 const std::vector<gfx::Rect>& new_additional_client_areas) {
931 Window* window = GetWindowByServerId(window_id);
932 if (window) {
933 float device_scale_factor = ScaleFactorForDisplay(window->display_id());
934 std::vector<gfx::Rect> new_additional_client_areas_in_dip;
935 for (const gfx::Rect& area : new_additional_client_areas) {
936 new_additional_client_areas_in_dip.push_back(
937 gfx::ConvertRectToDIP(device_scale_factor, area));
938 }
939 WindowPrivate(window).LocalSetClientArea(
940 gfx::ConvertInsetsToDIP(device_scale_factor, new_client_area),
941 new_additional_client_areas_in_dip);
942 }
943 }
944
945 void WindowTreeClient::OnTransientWindowAdded(
946 uint32_t window_id,
947 uint32_t transient_window_id) {
948 Window* window = GetWindowByServerId(window_id);
949 Window* transient_window = GetWindowByServerId(transient_window_id);
950 // window or transient_window or both may be null if a local delete occurs
951 // with an in flight add from the server.
952 if (window && transient_window)
953 WindowPrivate(window).LocalAddTransientWindow(transient_window);
954 }
955
956 void WindowTreeClient::OnTransientWindowRemoved(
957 uint32_t window_id,
958 uint32_t transient_window_id) {
959 Window* window = GetWindowByServerId(window_id);
960 Window* transient_window = GetWindowByServerId(transient_window_id);
961 // window or transient_window or both may be null if a local delete occurs
962 // with an in flight delete from the server.
963 if (window && transient_window)
964 WindowPrivate(window).LocalRemoveTransientWindow(transient_window);
965 }
966
967 void WindowTreeClient::OnWindowHierarchyChanged(
968 Id window_id,
969 Id old_parent_id,
970 Id new_parent_id,
971 std::vector<mojom::WindowDataPtr> windows) {
972 Window* initial_parent =
973 windows.size() ? GetWindowByServerId(windows[0]->parent_id) : NULL;
974
975 const bool was_window_known = GetWindowByServerId(window_id) != nullptr;
976
977 BuildWindowTree(windows, initial_parent);
978
979 // If the window was not known, then BuildWindowTree() will have created it
980 // and parented the window.
981 if (!was_window_known)
982 return;
983
984 Window* new_parent = GetWindowByServerId(new_parent_id);
985 Window* old_parent = GetWindowByServerId(old_parent_id);
986 Window* window = GetWindowByServerId(window_id);
987 if (new_parent)
988 WindowPrivate(new_parent).LocalAddChild(window);
989 else
990 WindowPrivate(old_parent).LocalRemoveChild(window);
991 }
992
993 void WindowTreeClient::OnWindowReordered(Id window_id,
994 Id relative_window_id,
995 mojom::OrderDirection direction) {
996 Window* window = GetWindowByServerId(window_id);
997 Window* relative_window = GetWindowByServerId(relative_window_id);
998 if (window && relative_window)
999 WindowPrivate(window).LocalReorder(relative_window, direction);
1000 }
1001
1002 void WindowTreeClient::OnWindowDeleted(Id window_id) {
1003 Window* window = GetWindowByServerId(window_id);
1004 if (window)
1005 WindowPrivate(window).LocalDestroy();
1006 }
1007
1008 Window* WindowTreeClient::GetCaptureWindow() {
1009 return capture_window_;
1010 }
1011
1012 void WindowTreeClient::OnWindowVisibilityChanged(Id window_id,
1013 bool visible) {
1014 Window* window = GetWindowByServerId(window_id);
1015 if (!window)
1016 return;
1017
1018 InFlightVisibleChange new_change(window, visible);
1019 if (ApplyServerChangeToExistingInFlightChange(new_change))
1020 return;
1021
1022 WindowPrivate(window).LocalSetVisible(visible);
1023 }
1024
1025 void WindowTreeClient::OnWindowOpacityChanged(Id window_id,
1026 float old_opacity,
1027 float new_opacity) {
1028 Window* window = GetWindowByServerId(window_id);
1029 if (!window)
1030 return;
1031
1032 InFlightOpacityChange new_change(window, new_opacity);
1033 if (ApplyServerChangeToExistingInFlightChange(new_change))
1034 return;
1035
1036 WindowPrivate(window).LocalSetOpacity(new_opacity);
1037 }
1038
1039 void WindowTreeClient::OnWindowParentDrawnStateChanged(Id window_id,
1040 bool drawn) {
1041 Window* window = GetWindowByServerId(window_id);
1042 if (window)
1043 WindowPrivate(window).LocalSetParentDrawn(drawn);
1044 }
1045
1046 void WindowTreeClient::OnWindowSharedPropertyChanged(
1047 Id window_id,
1048 const std::string& name,
1049 const base::Optional<std::vector<uint8_t>>& new_data) {
1050 Window* window = GetWindowByServerId(window_id);
1051 if (!window)
1052 return;
1053
1054 InFlightPropertyChange new_change(window, name, new_data);
1055 if (ApplyServerChangeToExistingInFlightChange(new_change))
1056 return;
1057
1058 WindowPrivate(window).LocalSetSharedProperty(
1059 name, new_data ? &new_data.value() : nullptr);
1060 }
1061
1062 void WindowTreeClient::OnWindowInputEvent(uint32_t event_id,
1063 Id window_id,
1064 std::unique_ptr<ui::Event> event,
1065 bool matches_pointer_watcher) {
1066 DCHECK(event);
1067 Window* window = GetWindowByServerId(window_id); // May be null.
1068
1069 if (matches_pointer_watcher && has_pointer_watcher_) {
1070 DCHECK(event->IsPointerEvent());
1071 delegate_->OnPointerEventObserved(*event->AsPointerEvent(), window);
1072 }
1073
1074 if (!window || !window->input_event_handler_) {
1075 tree_->OnWindowInputEventAck(event_id, mojom::EventResult::UNHANDLED);
1076 return;
1077 }
1078
1079 std::unique_ptr<base::Callback<void(mojom::EventResult)>> ack_callback(
1080 new base::Callback<void(mojom::EventResult)>(
1081 base::Bind(&mojom::WindowTree::OnWindowInputEventAck,
1082 base::Unretained(tree_), event_id)));
1083
1084 // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or
1085 // ui::TouchEvent once we have proper support for pointer events.
1086 if (event->IsMousePointerEvent()) {
1087 if (event->type() == ui::ET_POINTER_WHEEL_CHANGED) {
1088 window->input_event_handler_->OnWindowInputEvent(
1089 window, ui::MouseWheelEvent(*event->AsPointerEvent()), &ack_callback);
1090 } else {
1091 window->input_event_handler_->OnWindowInputEvent(
1092 window, ui::MouseEvent(*event->AsPointerEvent()), &ack_callback);
1093 }
1094 } else if (event->IsTouchPointerEvent()) {
1095 window->input_event_handler_->OnWindowInputEvent(
1096 window, ui::TouchEvent(*event->AsPointerEvent()), &ack_callback);
1097 } else {
1098 window->input_event_handler_->OnWindowInputEvent(window, *event.get(),
1099 &ack_callback);
1100 }
1101
1102 // The handler did not take ownership of the callback, so we send the ack,
1103 // marking the event as not consumed.
1104 if (ack_callback)
1105 ack_callback->Run(mojom::EventResult::UNHANDLED);
1106 }
1107
1108 void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event,
1109 uint32_t window_id) {
1110 DCHECK(event);
1111 DCHECK(event->IsPointerEvent());
1112 if (has_pointer_watcher_) {
1113 Window* target_window = GetWindowByServerId(window_id);
1114 delegate_->OnPointerEventObserved(*event->AsPointerEvent(), target_window);
1115 }
1116 }
1117
1118 void WindowTreeClient::OnWindowFocused(Id focused_window_id) {
1119 Window* focused_window = GetWindowByServerId(focused_window_id);
1120 InFlightFocusChange new_change(this, focused_window);
1121 if (ApplyServerChangeToExistingInFlightChange(new_change))
1122 return;
1123
1124 LocalSetFocus(focused_window);
1125 }
1126
1127 void WindowTreeClient::OnWindowPredefinedCursorChanged(
1128 Id window_id,
1129 mojom::Cursor cursor) {
1130 Window* window = GetWindowByServerId(window_id);
1131 if (!window)
1132 return;
1133
1134 InFlightPredefinedCursorChange new_change(window, cursor);
1135 if (ApplyServerChangeToExistingInFlightChange(new_change))
1136 return;
1137
1138 WindowPrivate(window).LocalSetPredefinedCursor(cursor);
1139 }
1140
1141 void WindowTreeClient::OnWindowSurfaceChanged(
1142 Id window_id,
1143 const cc::SurfaceInfo& surface_info) {
1144 Window* window = GetWindowByServerId(window_id);
1145 if (!window)
1146 return;
1147 WindowPrivate(window).LocalSetSurfaceInfo(surface_info);
1148 }
1149
1150 void WindowTreeClient::OnDragDropStart(
1151 const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) {
1152 mime_drag_data_ = mojo::UnorderedMapToMap(mime_data);
1153 }
1154
1155 void WindowTreeClient::OnDragEnter(Id window_id,
1156 uint32_t key_state,
1157 const gfx::Point& position,
1158 uint32_t effect_bitmask,
1159 const OnDragEnterCallback& callback) {
1160 Window* window = GetWindowByServerId(window_id);
1161 if (!window || !window->drop_target()) {
1162 callback.Run(mojom::kDropEffectNone);
1163 return;
1164 }
1165
1166 if (!base::ContainsKey(drag_entered_windows_, window_id)) {
1167 window->drop_target()->OnDragDropStart(mime_drag_data_);
1168 drag_entered_windows_.insert(window_id);
1169 }
1170
1171 uint32_t ret =
1172 window->drop_target()->OnDragEnter(key_state, position, effect_bitmask);
1173 callback.Run(ret);
1174 }
1175
1176 void WindowTreeClient::OnDragOver(Id window_id,
1177 uint32_t key_state,
1178 const gfx::Point& position,
1179 uint32_t effect_bitmask,
1180 const OnDragOverCallback& callback) {
1181 Window* window = GetWindowByServerId(window_id);
1182 if (!window || !window->drop_target()) {
1183 callback.Run(mojom::kDropEffectNone);
1184 return;
1185 }
1186
1187 uint32_t ret =
1188 window->drop_target()->OnDragOver(key_state, position, effect_bitmask);
1189 callback.Run(ret);
1190 }
1191
1192 void WindowTreeClient::OnDragLeave(Id window_id) {
1193 Window* window = GetWindowByServerId(window_id);
1194 if (!window || !window->drop_target())
1195 return;
1196
1197 window->drop_target()->OnDragLeave();
1198 }
1199
1200 void WindowTreeClient::OnDragDropDone() {
1201 for (Id id : drag_entered_windows_) {
1202 Window* window = GetWindowByServerId(id);
1203 if (!window || !window->drop_target())
1204 continue;
1205 window->drop_target()->OnDragDropDone();
1206 }
1207 drag_entered_windows_.clear();
1208 }
1209
1210 void WindowTreeClient::OnCompleteDrop(Id window_id,
1211 uint32_t key_state,
1212 const gfx::Point& position,
1213 uint32_t effect_bitmask,
1214 const OnCompleteDropCallback& callback) {
1215 Window* window = GetWindowByServerId(window_id);
1216 if (!window || !window->drop_target()) {
1217 callback.Run(mojom::kDropEffectNone);
1218 return;
1219 }
1220
1221 uint32_t ret = window->drop_target()->OnCompleteDrop(key_state, position,
1222 effect_bitmask);
1223 callback.Run(ret);
1224 }
1225
1226 void WindowTreeClient::OnPerformDragDropCompleted(uint32_t change_id,
1227 bool success,
1228 uint32_t action_taken) {
1229 if (current_drag_state_ && change_id == current_drag_state_->change_id) {
1230 current_drag_state_->completed_action = action_taken;
1231 OnChangeCompleted(change_id, success);
1232 }
1233 }
1234
1235 void WindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) {
1236 std::unique_ptr<InFlightChange> change(std::move(in_flight_map_[change_id]));
1237 in_flight_map_.erase(change_id);
1238 if (!change)
1239 return;
1240
1241 if (!success)
1242 change->ChangeFailed();
1243
1244 InFlightChange* next_change = GetOldestInFlightChangeMatching(*change);
1245 if (next_change) {
1246 if (!success)
1247 next_change->SetRevertValueFrom(*change);
1248 } else if (!success) {
1249 change->Revert();
1250 }
1251
1252 if (change_id == current_move_loop_change_) {
1253 current_move_loop_change_ = 0;
1254 on_current_move_finished_.Run(success);
1255 on_current_move_finished_.Reset();
1256 }
1257
1258 if (current_drag_state_ && change_id == current_drag_state_->change_id) {
1259 OnDragDropDone();
1260
1261 current_drag_state_->on_finished.Run(success,
1262 current_drag_state_->completed_action);
1263 current_drag_state_.reset();
1264 }
1265 }
1266
1267 void WindowTreeClient::GetWindowManager(
1268 mojo::AssociatedInterfaceRequest<WindowManager> internal) {
1269 window_manager_internal_.reset(
1270 new mojo::AssociatedBinding<mojom::WindowManager>(this,
1271 std::move(internal)));
1272 }
1273
1274 void WindowTreeClient::RequestClose(uint32_t window_id) {
1275 Window* window = GetWindowByServerId(window_id);
1276 if (!window || !IsRoot(window))
1277 return;
1278
1279 for (auto& observer : *WindowPrivate(window).observers())
1280 observer.OnRequestClose(window);
1281 }
1282
1283 void WindowTreeClient::OnConnect(ClientSpecificId client_id) {
1284 client_id_ = client_id;
1285 }
1286
1287 void WindowTreeClient::WmNewDisplayAdded(const display::Display& display,
1288 mojom::WindowDataPtr root_data,
1289 bool parent_drawn) {
1290 WmNewDisplayAddedImpl(display, std::move(root_data), parent_drawn);
1291 }
1292
1293 void WindowTreeClient::WmDisplayRemoved(int64_t display_id) {
1294 DCHECK(window_manager_delegate_);
1295
1296 for (Window* root : roots_) {
1297 if (root->display_id() == display_id) {
1298 window_manager_delegate_->OnWmDisplayRemoved(root);
1299 return;
1300 }
1301 }
1302 }
1303
1304 void WindowTreeClient::WmDisplayModified(const display::Display& display) {
1305 DCHECK(window_manager_delegate_);
1306 window_manager_delegate_->OnWmDisplayModified(display);
1307 }
1308
1309 void WindowTreeClient::WmSetBounds(uint32_t change_id,
1310 Id window_id,
1311 const gfx::Rect& transit_bounds) {
1312 Window* window = GetWindowByServerId(window_id);
1313 bool result = false;
1314 if (window) {
1315 DCHECK(window_manager_delegate_);
1316 gfx::Rect transit_bounds_in_dip = gfx::ConvertRectToDIP(
1317 ScaleFactorForDisplay(window->display_id()), transit_bounds);
1318 gfx::Rect bounds = transit_bounds_in_dip;
1319 result = window_manager_delegate_->OnWmSetBounds(window, &bounds);
1320 if (result) {
1321 // If the resulting bounds differ return false. Returning false ensures
1322 // the client applies the bounds we set below.
1323 result = bounds == transit_bounds_in_dip;
1324 window->SetBounds(bounds);
1325 }
1326 }
1327 if (window_manager_internal_client_)
1328 window_manager_internal_client_->WmResponse(change_id, result);
1329 }
1330
1331 void WindowTreeClient::WmSetProperty(
1332 uint32_t change_id,
1333 Id window_id,
1334 const std::string& name,
1335 const base::Optional<std::vector<uint8_t>>& transit_data) {
1336 Window* window = GetWindowByServerId(window_id);
1337 bool result = false;
1338 if (window) {
1339 DCHECK(window_manager_delegate_);
1340 std::unique_ptr<std::vector<uint8_t>> data;
1341 if (transit_data.has_value())
1342 data.reset(new std::vector<uint8_t>(transit_data.value()));
1343
1344 result = window_manager_delegate_->OnWmSetProperty(window, name, &data);
1345 if (result) {
1346 // If the resulting bounds differ return false. Returning false ensures
1347 // the client applies the bounds we set below.
1348 window->SetSharedPropertyInternal(name, data.get());
1349 }
1350 }
1351 if (window_manager_internal_client_)
1352 window_manager_internal_client_->WmResponse(change_id, result);
1353 }
1354
1355 void WindowTreeClient::WmCreateTopLevelWindow(
1356 uint32_t change_id,
1357 ClientSpecificId requesting_client_id,
1358 const std::unordered_map<std::string, std::vector<uint8_t>>&
1359 transport_properties) {
1360 std::map<std::string, std::vector<uint8_t>> properties =
1361 mojo::UnorderedMapToMap(transport_properties);
1362 Window* window =
1363 window_manager_delegate_->OnWmCreateTopLevelWindow(&properties);
1364 embedded_windows_[requesting_client_id].insert(window);
1365 if (window_manager_internal_client_) {
1366 window_manager_internal_client_->OnWmCreatedTopLevelWindow(
1367 change_id, server_id(window));
1368 }
1369 }
1370
1371 void WindowTreeClient::WmClientJankinessChanged(ClientSpecificId client_id,
1372 bool janky) {
1373 if (window_manager_delegate_) {
1374 auto it = embedded_windows_.find(client_id);
1375 CHECK(it != embedded_windows_.end());
1376 window_manager_delegate_->OnWmClientJankinessChanged(
1377 embedded_windows_[client_id], janky);
1378 }
1379 }
1380
1381 void WindowTreeClient::WmPerformMoveLoop(uint32_t change_id,
1382 Id window_id,
1383 mojom::MoveLoopSource source,
1384 const gfx::Point& cursor_location) {
1385 if (!window_manager_delegate_ || current_wm_move_loop_change_ != 0) {
1386 OnWmMoveLoopCompleted(change_id, false);
1387 return;
1388 }
1389
1390 current_wm_move_loop_change_ = change_id;
1391 current_wm_move_loop_window_id_ = window_id;
1392 Window* window = GetWindowByServerId(window_id);
1393 if (window) {
1394 window_manager_delegate_->OnWmPerformMoveLoop(
1395 window, source, cursor_location,
1396 base::Bind(&WindowTreeClient::OnWmMoveLoopCompleted,
1397 weak_factory_.GetWeakPtr(), change_id));
1398 } else {
1399 OnWmMoveLoopCompleted(change_id, false);
1400 }
1401 }
1402
1403 void WindowTreeClient::WmCancelMoveLoop(uint32_t change_id) {
1404 if (!window_manager_delegate_ || change_id != current_wm_move_loop_change_)
1405 return;
1406
1407 Window* window = GetWindowByServerId(current_wm_move_loop_window_id_);
1408 if (window)
1409 window_manager_delegate_->OnWmCancelMoveLoop(window);
1410 }
1411
1412 void WindowTreeClient::WmDeactivateWindow(uint32_t window_id) {}
1413
1414 void WindowTreeClient::OnAccelerator(uint32_t ack_id,
1415 uint32_t accelerator_id,
1416 std::unique_ptr<ui::Event> event) {
1417 DCHECK(event);
1418 const mojom::EventResult result =
1419 window_manager_delegate_->OnAccelerator(accelerator_id, *event.get());
1420 if (ack_id && window_manager_internal_client_)
1421 window_manager_internal_client_->OnAcceleratorAck(ack_id, result);
1422 }
1423
1424 void WindowTreeClient::SetFrameDecorationValues(
1425 mojom::FrameDecorationValuesPtr values) {
1426 if (window_manager_internal_client_) {
1427 window_manager_internal_client_->WmSetFrameDecorationValues(
1428 std::move(values));
1429 }
1430 }
1431
1432 void WindowTreeClient::SetNonClientCursor(Window* window,
1433 ui::mojom::Cursor cursor_id) {
1434 window_manager_internal_client_->WmSetNonClientCursor(server_id(window),
1435 cursor_id);
1436 }
1437
1438 void WindowTreeClient::AddAccelerators(
1439 std::vector<mojom::AcceleratorPtr> accelerators,
1440 const base::Callback<void(bool)>& callback) {
1441 if (window_manager_internal_client_) {
1442 window_manager_internal_client_->AddAccelerators(std::move(accelerators),
1443 callback);
1444 }
1445 }
1446
1447 void WindowTreeClient::RemoveAccelerator(uint32_t id) {
1448 if (window_manager_internal_client_) {
1449 window_manager_internal_client_->RemoveAccelerator(id);
1450 }
1451 }
1452
1453 void WindowTreeClient::AddActivationParent(Window* window) {
1454 if (window_manager_internal_client_)
1455 window_manager_internal_client_->AddActivationParent(server_id(window));
1456 }
1457
1458 void WindowTreeClient::RemoveActivationParent(Window* window) {
1459 if (window_manager_internal_client_)
1460 window_manager_internal_client_->RemoveActivationParent(server_id(window));
1461 }
1462
1463 void WindowTreeClient::ActivateNextWindow() {
1464 if (window_manager_internal_client_)
1465 window_manager_internal_client_->ActivateNextWindow();
1466 }
1467
1468 void WindowTreeClient::SetUnderlaySurfaceOffsetAndExtendedHitArea(
1469 Window* window,
1470 const gfx::Vector2d& offset,
1471 const gfx::Insets& hit_area) {
1472 if (window_manager_internal_client_) {
1473 // TODO(riajiang): Figure out if |offset| needs to be converted.
1474 // (http://crbugs.com/646932)
1475 window_manager_internal_client_->SetUnderlaySurfaceOffsetAndExtendedHitArea(
1476 server_id(window), offset.x(), offset.y(),
1477 gfx::ConvertInsetsToDIP(ScaleFactorForDisplay(window->display_id()),
1478 hit_area));
1479 }
1480 }
1481
1482 } // namespace ui
OLDNEW
« no previous file with comments | « services/ui/public/cpp/window_tree_client.h ('k') | services/ui/public/cpp/window_tree_client_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698