OLD | NEW |
| (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 | |
OLD | NEW |