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

Side by Side Diff: components/mus/ws/window_tree.cc

Issue 2119963002: Move mus to //services/ui (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/mus/ws/window_tree.h ('k') | components/mus/ws/window_tree_binding.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/mus/ws/window_tree.h"
6
7 #include <stddef.h>
8
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/macros.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/stl_util.h"
15 #include "components/mus/ws/default_access_policy.h"
16 #include "components/mus/ws/display.h"
17 #include "components/mus/ws/display_manager.h"
18 #include "components/mus/ws/event_matcher.h"
19 #include "components/mus/ws/focus_controller.h"
20 #include "components/mus/ws/operation.h"
21 #include "components/mus/ws/platform_display.h"
22 #include "components/mus/ws/server_window.h"
23 #include "components/mus/ws/server_window_observer.h"
24 #include "components/mus/ws/user_display_manager.h"
25 #include "components/mus/ws/window_manager_display_root.h"
26 #include "components/mus/ws/window_manager_state.h"
27 #include "components/mus/ws/window_server.h"
28 #include "components/mus/ws/window_tree_binding.h"
29 #include "ui/display/display.h"
30 #include "ui/platform_window/mojo/ime_type_converters.h"
31 #include "ui/platform_window/text_input_state.h"
32
33 using mojo::Array;
34 using mojo::InterfaceRequest;
35 using mojo::String;
36
37 namespace mus {
38 namespace ws {
39
40 class TargetedEvent : public ServerWindowObserver {
41 public:
42 TargetedEvent(ServerWindow* target, const ui::Event& event)
43 : target_(target), event_(ui::Event::Clone(event)) {
44 target_->AddObserver(this);
45 }
46 ~TargetedEvent() override {
47 if (target_)
48 target_->RemoveObserver(this);
49 }
50
51 ServerWindow* target() { return target_; }
52 std::unique_ptr<ui::Event> TakeEvent() { return std::move(event_); }
53
54 private:
55 // ServerWindowObserver:
56 void OnWindowDestroyed(ServerWindow* window) override {
57 DCHECK_EQ(target_, window);
58 target_->RemoveObserver(this);
59 target_ = nullptr;
60 }
61
62 ServerWindow* target_;
63 std::unique_ptr<ui::Event> event_;
64
65 DISALLOW_COPY_AND_ASSIGN(TargetedEvent);
66 };
67
68 WindowTree::WindowTree(WindowServer* window_server,
69 const UserId& user_id,
70 ServerWindow* root,
71 std::unique_ptr<AccessPolicy> access_policy)
72 : window_server_(window_server),
73 user_id_(user_id),
74 id_(window_server_->GetAndAdvanceNextClientId()),
75 next_window_id_(1),
76 access_policy_(std::move(access_policy)),
77 event_ack_id_(0),
78 window_manager_internal_(nullptr) {
79 if (root)
80 roots_.insert(root);
81 access_policy_->Init(id_, this);
82 }
83
84 WindowTree::~WindowTree() {
85 DestroyWindows();
86 }
87
88 void WindowTree::Init(std::unique_ptr<WindowTreeBinding> binding,
89 mojom::WindowTreePtr tree) {
90 DCHECK(!binding_);
91 binding_ = std::move(binding);
92
93 if (roots_.empty())
94 return;
95
96 std::vector<const ServerWindow*> to_send;
97 CHECK_EQ(1u, roots_.size());
98 const ServerWindow* root = *roots_.begin();
99 GetUnknownWindowsFrom(root, &to_send);
100
101 Display* display = GetDisplay(root);
102 int64_t display_id =
103 display ? display->id() : display::Display::kInvalidDisplayID;
104 const ServerWindow* focused_window =
105 display ? display->GetFocusedWindow() : nullptr;
106 if (focused_window)
107 focused_window = access_policy_->GetWindowForFocusChange(focused_window);
108 ClientWindowId focused_window_id;
109 if (focused_window)
110 IsWindowKnown(focused_window, &focused_window_id);
111
112 const bool drawn = root->parent() && root->parent()->IsDrawn();
113 client()->OnEmbed(id_, WindowToWindowData(to_send.front()), std::move(tree),
114 display_id, focused_window_id.id, drawn);
115 }
116
117 void WindowTree::ConfigureWindowManager() {
118 DCHECK(!window_manager_internal_);
119 window_manager_internal_ = binding_->GetWindowManager();
120 window_manager_internal_->OnConnect(id_);
121 window_manager_state_.reset(new WindowManagerState(this));
122 }
123
124 const ServerWindow* WindowTree::GetWindow(const WindowId& id) const {
125 if (id_ == id.client_id) {
126 auto iter = created_window_map_.find(id);
127 return iter == created_window_map_.end() ? nullptr : iter->second;
128 }
129 return window_server_->GetWindow(id);
130 }
131
132 bool WindowTree::IsWindowKnown(const ServerWindow* window,
133 ClientWindowId* id) const {
134 if (!window)
135 return false;
136 auto iter = window_id_to_client_id_map_.find(window->id());
137 if (iter == window_id_to_client_id_map_.end())
138 return false;
139 if (id)
140 *id = iter->second;
141 return true;
142 }
143
144 bool WindowTree::HasRoot(const ServerWindow* window) const {
145 return roots_.count(window) > 0;
146 }
147
148 const ServerWindow* WindowTree::GetWindowByClientId(
149 const ClientWindowId& id) const {
150 auto iter = client_id_to_window_id_map_.find(id);
151 return iter == client_id_to_window_id_map_.end() ? nullptr
152 : GetWindow(iter->second);
153 }
154
155 const Display* WindowTree::GetDisplay(const ServerWindow* window) const {
156 return window ? display_manager()->GetDisplayContaining(window) : nullptr;
157 }
158
159 const WindowManagerDisplayRoot* WindowTree::GetWindowManagerDisplayRoot(
160 const ServerWindow* window) const {
161 return window ? display_manager()->GetWindowManagerDisplayRoot(window)
162 : nullptr;
163 }
164
165 DisplayManager* WindowTree::display_manager() {
166 return window_server_->display_manager();
167 }
168
169 const DisplayManager* WindowTree::display_manager() const {
170 return window_server_->display_manager();
171 }
172
173 void WindowTree::AddRootForWindowManager(const ServerWindow* root) {
174 DCHECK(window_manager_internal_);
175 const ClientWindowId client_window_id(WindowIdToTransportId(root->id()));
176 DCHECK_EQ(0u, client_id_to_window_id_map_.count(client_window_id));
177 client_id_to_window_id_map_[client_window_id] = root->id();
178 window_id_to_client_id_map_[root->id()] = client_window_id;
179 roots_.insert(root);
180
181 Display* display = GetDisplay(root);
182 DCHECK(display);
183
184 window_manager_internal_->WmNewDisplayAdded(display->ToMojomDisplay(),
185 WindowToWindowData(root),
186 root->parent()->IsDrawn());
187 }
188
189 void WindowTree::OnWindowDestroyingTreeImpl(WindowTree* tree) {
190 if (window_manager_state_)
191 window_manager_state_->OnWillDestroyTree(tree);
192
193 if (event_source_wms_ && event_source_wms_->window_tree() == tree)
194 event_source_wms_ = nullptr;
195
196 // Notify our client if |tree| was embedded in any of our views.
197 for (const auto* tree_root : tree->roots_) {
198 const bool owns_tree_root = tree_root->id().client_id == id_;
199 if (owns_tree_root) {
200 client()->OnEmbeddedAppDisconnected(
201 ClientWindowIdForWindow(tree_root).id);
202 }
203 }
204 }
205
206 void WindowTree::NotifyChangeCompleted(
207 uint32_t change_id,
208 mojom::WindowManagerErrorCode error_code) {
209 client()->OnChangeCompleted(
210 change_id, error_code == mojom::WindowManagerErrorCode::SUCCESS);
211 }
212
213 bool WindowTree::SetCapture(const ClientWindowId& client_window_id) {
214 ServerWindow* window = GetWindowByClientId(client_window_id);
215 WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window);
216 ServerWindow* current_capture_window =
217 display_root ? display_root->window_manager_state()->capture_window()
218 : nullptr;
219 if (window && window->IsDrawn() && display_root &&
220 display_root->window_manager_state()->IsActive() &&
221 access_policy_->CanSetCapture(window) &&
222 (!current_capture_window ||
223 access_policy_->CanSetCapture(current_capture_window))) {
224 return display_root->window_manager_state()->SetCapture(window, id_);
225 }
226 return false;
227 }
228
229 bool WindowTree::NewWindow(
230 const ClientWindowId& client_window_id,
231 const std::map<std::string, std::vector<uint8_t>>& properties) {
232 if (!IsValidIdForNewWindow(client_window_id))
233 return false;
234 const WindowId window_id = GenerateNewWindowId();
235 DCHECK(!GetWindow(window_id));
236 ServerWindow* window =
237 window_server_->CreateServerWindow(window_id, properties);
238 created_window_map_[window_id] = window;
239 client_id_to_window_id_map_[client_window_id] = window_id;
240 window_id_to_client_id_map_[window_id] = client_window_id;
241 return true;
242 }
243
244 bool WindowTree::AddWindow(const ClientWindowId& parent_id,
245 const ClientWindowId& child_id) {
246 ServerWindow* parent = GetWindowByClientId(parent_id);
247 ServerWindow* child = GetWindowByClientId(child_id);
248 if (parent && child && child->parent() != parent &&
249 !child->Contains(parent) && access_policy_->CanAddWindow(parent, child)) {
250 Operation op(this, window_server_, OperationType::ADD_WINDOW);
251 parent->Add(child);
252 return true;
253 }
254 return false;
255 }
256
257 bool WindowTree::AddTransientWindow(const ClientWindowId& window_id,
258 const ClientWindowId& transient_window_id) {
259 ServerWindow* window = GetWindowByClientId(window_id);
260 ServerWindow* transient_window = GetWindowByClientId(transient_window_id);
261 if (window && transient_window && !transient_window->Contains(window) &&
262 access_policy_->CanAddTransientWindow(window, transient_window)) {
263 Operation op(this, window_server_, OperationType::ADD_TRANSIENT_WINDOW);
264 return window->AddTransientWindow(transient_window);
265 }
266 return false;
267 }
268
269 bool WindowTree::SetModal(const ClientWindowId& window_id) {
270 ServerWindow* window = GetWindowByClientId(window_id);
271 if (window && access_policy_->CanSetModal(window)) {
272 WindowManagerDisplayRoot* display_root =
273 GetWindowManagerDisplayRoot(window);
274 if (window->transient_parent()) {
275 window->SetModal();
276 } else if (user_id_ != InvalidUserId()) {
277 if (display_root)
278 display_root->window_manager_state()->AddSystemModalWindow(window);
279 } else {
280 return false;
281 }
282 if (display_root)
283 display_root->window_manager_state()->ReleaseCaptureBlockedByModalWindow(
284 window);
285 return true;
286 }
287 return false;
288 }
289
290 std::vector<const ServerWindow*> WindowTree::GetWindowTree(
291 const ClientWindowId& window_id) const {
292 const ServerWindow* window = GetWindowByClientId(window_id);
293 std::vector<const ServerWindow*> windows;
294 if (window)
295 GetWindowTreeImpl(window, &windows);
296 return windows;
297 }
298
299 bool WindowTree::SetWindowVisibility(const ClientWindowId& window_id,
300 bool visible) {
301 ServerWindow* window = GetWindowByClientId(window_id);
302 if (!window || !access_policy_->CanChangeWindowVisibility(window))
303 return false;
304 if (window->visible() == visible)
305 return true;
306 Operation op(this, window_server_, OperationType::SET_WINDOW_VISIBILITY);
307 window->SetVisible(visible);
308 return true;
309 }
310
311 bool WindowTree::SetWindowOpacity(const ClientWindowId& window_id,
312 float opacity) {
313 ServerWindow* window = GetWindowByClientId(window_id);
314 if (!window || !access_policy_->CanChangeWindowOpacity(window))
315 return false;
316 if (window->opacity() == opacity)
317 return true;
318 Operation op(this, window_server_, OperationType::SET_WINDOW_OPACITY);
319 window->SetOpacity(opacity);
320 return true;
321 }
322
323 bool WindowTree::SetFocus(const ClientWindowId& window_id) {
324 ServerWindow* window = GetWindowByClientId(window_id);
325 ServerWindow* currently_focused = window_server_->GetFocusedWindow();
326 if (!currently_focused && !window) {
327 DVLOG(1) << "SetFocus failure, no focused window to clear.";
328 return false;
329 }
330
331 Display* display = GetDisplay(window);
332 if (window && (!display || !window->can_focus() || !window->IsDrawn())) {
333 DVLOG(1) << "SetFocus failure, window cannot be focused.";
334 return false;
335 }
336
337 if (!access_policy_->CanSetFocus(window)) {
338 DVLOG(1) << "SetFocus failure, blocked by access policy.";
339 return false;
340 }
341
342 Operation op(this, window_server_, OperationType::SET_FOCUS);
343 bool success = window_server_->SetFocusedWindow(window);
344 if (!success) {
345 DVLOG(1) << "SetFocus failure, could not SetFocusedWindow.";
346 }
347 return success;
348 }
349
350 bool WindowTree::Embed(const ClientWindowId& window_id,
351 mojom::WindowTreeClientPtr client,
352 uint32_t flags) {
353 if (!client || !CanEmbed(window_id))
354 return false;
355 ServerWindow* window = GetWindowByClientId(window_id);
356 PrepareForEmbed(window);
357 // When embedding we don't know the user id of where the TreeClient came
358 // from. Use an invalid id, which limits what the client is able to do.
359 window_server_->EmbedAtWindow(window, InvalidUserId(), std::move(client),
360 flags,
361 base::WrapUnique(new DefaultAccessPolicy));
362 return true;
363 }
364
365 void WindowTree::DispatchInputEvent(ServerWindow* target,
366 const ui::Event& event) {
367 if (event_ack_id_) {
368 // This is currently waiting for an event ack. Add it to the queue.
369 event_queue_.push(base::WrapUnique(new TargetedEvent(target, event)));
370 // TODO(sad): If the |event_queue_| grows too large, then this should notify
371 // Display, so that it can stop sending events.
372 return;
373 }
374
375 // If there are events in the queue, then store this new event in the queue,
376 // and dispatch the latest event from the queue instead that still has a live
377 // target.
378 if (!event_queue_.empty()) {
379 event_queue_.push(base::WrapUnique(new TargetedEvent(target, event)));
380 return;
381 }
382
383 DispatchInputEventImpl(target, event);
384 }
385
386 bool WindowTree::IsWaitingForNewTopLevelWindow(uint32_t wm_change_id) {
387 return waiting_for_top_level_window_info_ &&
388 waiting_for_top_level_window_info_->wm_change_id == wm_change_id;
389 }
390
391 void WindowTree::OnWindowManagerCreatedTopLevelWindow(
392 uint32_t wm_change_id,
393 uint32_t client_change_id,
394 const ServerWindow* window) {
395 DCHECK(IsWaitingForNewTopLevelWindow(wm_change_id));
396 std::unique_ptr<WaitingForTopLevelWindowInfo>
397 waiting_for_top_level_window_info(
398 std::move(waiting_for_top_level_window_info_));
399 binding_->SetIncomingMethodCallProcessingPaused(false);
400 // We were paused, so the id should still be valid.
401 DCHECK(IsValidIdForNewWindow(
402 waiting_for_top_level_window_info->client_window_id));
403 client_id_to_window_id_map_[waiting_for_top_level_window_info
404 ->client_window_id] = window->id();
405 window_id_to_client_id_map_[window->id()] =
406 waiting_for_top_level_window_info->client_window_id;
407 roots_.insert(window);
408 Display* display = GetDisplay(window);
409 int64_t display_id =
410 display ? display->id() : display::Display::kInvalidDisplayID;
411 const bool drawn = window->parent() && window->parent()->IsDrawn();
412 client()->OnTopLevelCreated(client_change_id, WindowToWindowData(window),
413 display_id, drawn);
414 }
415
416 void WindowTree::AddActivationParent(const ClientWindowId& window_id) {
417 ServerWindow* window = GetWindowByClientId(window_id);
418 if (window) {
419 Display* display = GetDisplay(window);
420 if (display)
421 display->AddActivationParent(window);
422 else
423 DVLOG(1) << "AddActivationParent window not associated with display";
424 } else {
425 DVLOG(1) << "AddActivationParent supplied invalid window id";
426 }
427 }
428
429 void WindowTree::OnChangeCompleted(uint32_t change_id, bool success) {
430 client()->OnChangeCompleted(change_id, success);
431 }
432
433 void WindowTree::OnAccelerator(uint32_t accelerator_id,
434 const ui::Event& event) {
435 DCHECK(window_manager_internal_);
436 // TODO(moshayedi): crbug.com/617167. Don't clone even once we map
437 // mojom::Event directly to ui::Event.
438 window_manager_internal_->OnAccelerator(accelerator_id,
439 ui::Event::Clone(event));
440 }
441
442 void WindowTree::ClientJankinessChanged(WindowTree* tree) {
443 tree->janky_ = !tree->janky_;
444 if (window_manager_internal_) {
445 window_manager_internal_->WmClientJankinessChanged(
446 tree->id(), tree->janky());
447 }
448 }
449
450 void WindowTree::ProcessWindowBoundsChanged(const ServerWindow* window,
451 const gfx::Rect& old_bounds,
452 const gfx::Rect& new_bounds,
453 bool originated_change) {
454 ClientWindowId client_window_id;
455 if (originated_change || !IsWindowKnown(window, &client_window_id))
456 return;
457 client()->OnWindowBoundsChanged(client_window_id.id, old_bounds, new_bounds);
458 }
459
460 void WindowTree::ProcessClientAreaChanged(
461 const ServerWindow* window,
462 const gfx::Insets& new_client_area,
463 const std::vector<gfx::Rect>& new_additional_client_areas,
464 bool originated_change) {
465 ClientWindowId client_window_id;
466 if (originated_change || !IsWindowKnown(window, &client_window_id))
467 return;
468 client()->OnClientAreaChanged(
469 client_window_id.id, new_client_area,
470 std::vector<gfx::Rect>(new_additional_client_areas));
471 }
472
473 void WindowTree::ProcessWillChangeWindowHierarchy(
474 const ServerWindow* window,
475 const ServerWindow* new_parent,
476 const ServerWindow* old_parent,
477 bool originated_change) {
478 if (originated_change)
479 return;
480
481 const bool old_drawn = window->IsDrawn();
482 const bool new_drawn =
483 window->visible() && new_parent && new_parent->IsDrawn();
484 if (old_drawn == new_drawn)
485 return;
486
487 NotifyDrawnStateChanged(window, new_drawn);
488 }
489
490 void WindowTree::ProcessWindowPropertyChanged(
491 const ServerWindow* window,
492 const std::string& name,
493 const std::vector<uint8_t>* new_data,
494 bool originated_change) {
495 if (originated_change)
496 return;
497
498 ClientWindowId client_window_id;
499 if (!IsWindowKnown(window, &client_window_id))
500 return;
501
502 Array<uint8_t> data(nullptr);
503 if (new_data)
504 data = Array<uint8_t>::From(*new_data);
505
506 client()->OnWindowSharedPropertyChanged(client_window_id.id, String(name),
507 std::move(data));
508 }
509
510 void WindowTree::ProcessWindowHierarchyChanged(const ServerWindow* window,
511 const ServerWindow* new_parent,
512 const ServerWindow* old_parent,
513 bool originated_change) {
514 const bool knows_new = new_parent && IsWindowKnown(new_parent);
515 if (originated_change && !IsWindowKnown(window) && knows_new) {
516 std::vector<const ServerWindow*> unused;
517 GetUnknownWindowsFrom(window, &unused);
518 }
519 if (originated_change || (window_server_->current_operation_type() ==
520 OperationType::DELETE_WINDOW) ||
521 (window_server_->current_operation_type() == OperationType::EMBED) ||
522 window_server_->DidTreeMessageClient(id_)) {
523 return;
524 }
525
526 if (!access_policy_->ShouldNotifyOnHierarchyChange(window, &new_parent,
527 &old_parent)) {
528 return;
529 }
530 // Inform the client of any new windows and update the set of windows we know
531 // about.
532 std::vector<const ServerWindow*> to_send;
533 if (!IsWindowKnown(window))
534 GetUnknownWindowsFrom(window, &to_send);
535 const bool knows_old = old_parent && IsWindowKnown(old_parent);
536 if (!knows_old && !knows_new)
537 return;
538
539 const ClientWindowId new_parent_client_window_id =
540 knows_new ? ClientWindowIdForWindow(new_parent) : ClientWindowId();
541 const ClientWindowId old_parent_client_window_id =
542 knows_old ? ClientWindowIdForWindow(old_parent) : ClientWindowId();
543 const ClientWindowId client_window_id =
544 window ? ClientWindowIdForWindow(window) : ClientWindowId();
545 client()->OnWindowHierarchyChanged(
546 client_window_id.id, old_parent_client_window_id.id,
547 new_parent_client_window_id.id, WindowsToWindowDatas(to_send));
548 window_server_->OnTreeMessagedClient(id_);
549 }
550
551 void WindowTree::ProcessWindowReorder(const ServerWindow* window,
552 const ServerWindow* relative_window,
553 mojom::OrderDirection direction,
554 bool originated_change) {
555 DCHECK_EQ(window->parent(), relative_window->parent());
556 ClientWindowId client_window_id, relative_client_window_id;
557 if (originated_change || !IsWindowKnown(window, &client_window_id) ||
558 !IsWindowKnown(relative_window, &relative_client_window_id) ||
559 window_server_->DidTreeMessageClient(id_))
560 return;
561
562 // Do not notify ordering changes of the root windows, since the client
563 // doesn't know about the ancestors of the roots, and so can't do anything
564 // about this ordering change of the root.
565 if (HasRoot(window) || HasRoot(relative_window))
566 return;
567
568 client()->OnWindowReordered(client_window_id.id, relative_client_window_id.id,
569 direction);
570 window_server_->OnTreeMessagedClient(id_);
571 }
572
573 void WindowTree::ProcessWindowDeleted(const ServerWindow* window,
574 bool originated_change) {
575 if (window->id().client_id == id_)
576 created_window_map_.erase(window->id());
577
578 ClientWindowId client_window_id;
579 if (!IsWindowKnown(window, &client_window_id))
580 return;
581
582 if (HasRoot(window))
583 RemoveRoot(window, RemoveRootReason::DELETED);
584 else
585 RemoveFromMaps(window);
586
587 if (originated_change)
588 return;
589
590 client()->OnWindowDeleted(client_window_id.id);
591 window_server_->OnTreeMessagedClient(id_);
592 }
593
594 void WindowTree::ProcessWillChangeWindowVisibility(const ServerWindow* window,
595 bool originated_change) {
596 if (originated_change)
597 return;
598
599 ClientWindowId client_window_id;
600 if (IsWindowKnown(window, &client_window_id)) {
601 client()->OnWindowVisibilityChanged(client_window_id.id,
602 !window->visible());
603 return;
604 }
605
606 bool window_target_drawn_state;
607 if (window->visible()) {
608 // Window is being hidden, won't be drawn.
609 window_target_drawn_state = false;
610 } else {
611 // Window is being shown. Window will be drawn if its parent is drawn.
612 window_target_drawn_state = window->parent() && window->parent()->IsDrawn();
613 }
614
615 NotifyDrawnStateChanged(window, window_target_drawn_state);
616 }
617
618 void WindowTree::ProcessWindowOpacityChanged(const ServerWindow* window,
619 float old_opacity,
620 float new_opacity,
621 bool originated_change) {
622 if (originated_change)
623 return;
624
625 ClientWindowId client_window_id;
626 if (IsWindowKnown(window, &client_window_id)) {
627 client()->OnWindowOpacityChanged(client_window_id.id, old_opacity,
628 new_opacity);
629 }
630 }
631
632 void WindowTree::ProcessCursorChanged(const ServerWindow* window,
633 int32_t cursor_id,
634 bool originated_change) {
635 if (originated_change)
636 return;
637 ClientWindowId client_window_id;
638 if (!IsWindowKnown(window, &client_window_id))
639 return;
640
641 client()->OnWindowPredefinedCursorChanged(client_window_id.id,
642 mojom::Cursor(cursor_id));
643 }
644
645 void WindowTree::ProcessFocusChanged(const ServerWindow* old_focused_window,
646 const ServerWindow* new_focused_window) {
647 if (window_server_->current_operation_type() == OperationType::SET_FOCUS &&
648 window_server_->IsOperationSource(id_)) {
649 return;
650 }
651 const ServerWindow* window =
652 new_focused_window
653 ? access_policy_->GetWindowForFocusChange(new_focused_window)
654 : nullptr;
655 ClientWindowId client_window_id;
656 // If the window isn't known we'll supply null, which is ok.
657 IsWindowKnown(window, &client_window_id);
658 client()->OnWindowFocused(client_window_id.id);
659 }
660
661 void WindowTree::ProcessTransientWindowAdded(
662 const ServerWindow* window,
663 const ServerWindow* transient_window,
664 bool originated_change) {
665 if (originated_change)
666 return;
667
668 ClientWindowId client_window_id, transient_client_window_id;
669 if (!IsWindowKnown(window, &client_window_id) ||
670 !IsWindowKnown(transient_window, &transient_client_window_id)) {
671 return;
672 }
673 client()->OnTransientWindowAdded(client_window_id.id,
674 transient_client_window_id.id);
675 }
676
677 void WindowTree::ProcessTransientWindowRemoved(
678 const ServerWindow* window,
679 const ServerWindow* transient_window,
680 bool originated_change) {
681 if (originated_change)
682 return;
683 ClientWindowId client_window_id, transient_client_window_id;
684 if (!IsWindowKnown(window, &client_window_id) ||
685 !IsWindowKnown(transient_window, &transient_client_window_id)) {
686 return;
687 }
688 client()->OnTransientWindowRemoved(client_window_id.id,
689 transient_client_window_id.id);
690 }
691
692 bool WindowTree::ShouldRouteToWindowManager(const ServerWindow* window) const {
693 if (window_manager_state_)
694 return false; // We are the window manager, don't route to ourself.
695
696 // If the client created this window, then do not route it through the WM.
697 if (window->id().client_id == id_)
698 return false;
699
700 // If the client did not create the window, then it must be the root of the
701 // client. If not, that means the client should not know about this window,
702 // and so do not route the request to the WM.
703 if (roots_.count(window) == 0)
704 return false;
705
706 // The WindowManager is attached to the root of the Display, if there isn't a
707 // WindowManager attached no need to route to it.
708 const WindowManagerDisplayRoot* display_root =
709 GetWindowManagerDisplayRoot(window);
710 if (!display_root)
711 return false;
712
713 // Route to the windowmanager if the windowmanager created the window.
714 return display_root->window_manager_state()->window_tree()->id() ==
715 window->id().client_id;
716 }
717
718 void WindowTree::ProcessLostCapture(const ServerWindow* old_capture_window,
719 bool originated_change) {
720 if ((originated_change &&
721 window_server_->current_operation_type() ==
722 OperationType::RELEASE_CAPTURE) ||
723 !IsWindowKnown(old_capture_window)) {
724 return;
725 }
726 client()->OnLostCapture(WindowIdToTransportId(old_capture_window->id()));
727 }
728
729 ClientWindowId WindowTree::ClientWindowIdForWindow(
730 const ServerWindow* window) const {
731 auto iter = window_id_to_client_id_map_.find(window->id());
732 DCHECK(iter != window_id_to_client_id_map_.end());
733 return iter->second;
734 }
735
736 bool WindowTree::IsValidIdForNewWindow(const ClientWindowId& id) const {
737 // Reserve 0 to indicate a null window.
738 return client_id_to_window_id_map_.count(id) == 0u &&
739 access_policy_->IsValidIdForNewWindow(id) && id != ClientWindowId();
740 }
741
742 WindowId WindowTree::GenerateNewWindowId() {
743 // TODO(sky): deal with wrapping and uniqueness.
744 return WindowId(id_, next_window_id_++);
745 }
746
747 bool WindowTree::CanReorderWindow(const ServerWindow* window,
748 const ServerWindow* relative_window,
749 mojom::OrderDirection direction) const {
750 if (!window || !relative_window)
751 return false;
752
753 if (!window->parent() || window->parent() != relative_window->parent())
754 return false;
755
756 if (!access_policy_->CanReorderWindow(window, relative_window, direction))
757 return false;
758
759 std::vector<const ServerWindow*> children = window->parent()->GetChildren();
760 const size_t child_i =
761 std::find(children.begin(), children.end(), window) - children.begin();
762 const size_t target_i =
763 std::find(children.begin(), children.end(), relative_window) -
764 children.begin();
765 if ((direction == mojom::OrderDirection::ABOVE && child_i == target_i + 1) ||
766 (direction == mojom::OrderDirection::BELOW && child_i + 1 == target_i)) {
767 return false;
768 }
769
770 return true;
771 }
772
773 bool WindowTree::DeleteWindowImpl(WindowTree* source, ServerWindow* window) {
774 DCHECK(window);
775 DCHECK_EQ(window->id().client_id, id_);
776 Operation op(source, window_server_, OperationType::DELETE_WINDOW);
777 delete window;
778 return true;
779 }
780
781 void WindowTree::GetUnknownWindowsFrom(
782 const ServerWindow* window,
783 std::vector<const ServerWindow*>* windows) {
784 if (IsWindowKnown(window) || !access_policy_->CanGetWindowTree(window))
785 return;
786 windows->push_back(window);
787 // There are two cases where this gets hit:
788 // . During init, in which case using the window id as the client id is
789 // fine.
790 // . When a window is moved to a parent of a window we know about. This is
791 // only encountered for the WM or embed roots. We assume such clients want
792 // to see the real id of the window and are only created ClientWindowIds
793 // with the client_id.
794 const ClientWindowId client_window_id(WindowIdToTransportId(window->id()));
795 DCHECK_EQ(0u, client_id_to_window_id_map_.count(client_window_id));
796 client_id_to_window_id_map_[client_window_id] = window->id();
797 window_id_to_client_id_map_[window->id()] = client_window_id;
798 if (!access_policy_->CanDescendIntoWindowForWindowTree(window))
799 return;
800 std::vector<const ServerWindow*> children(window->GetChildren());
801 for (size_t i = 0; i < children.size(); ++i)
802 GetUnknownWindowsFrom(children[i], windows);
803 }
804
805 bool WindowTree::RemoveFromMaps(const ServerWindow* window) {
806 auto iter = window_id_to_client_id_map_.find(window->id());
807 if (iter == window_id_to_client_id_map_.end())
808 return false;
809
810 client_id_to_window_id_map_.erase(iter->second);
811 window_id_to_client_id_map_.erase(iter);
812 return true;
813 }
814
815 void WindowTree::RemoveFromKnown(const ServerWindow* window,
816 std::vector<ServerWindow*>* local_windows) {
817 if (window->id().client_id == id_) {
818 if (local_windows)
819 local_windows->push_back(GetWindow(window->id()));
820 return;
821 }
822
823 RemoveFromMaps(window);
824
825 std::vector<const ServerWindow*> children = window->GetChildren();
826 for (size_t i = 0; i < children.size(); ++i)
827 RemoveFromKnown(children[i], local_windows);
828 }
829
830 void WindowTree::RemoveRoot(const ServerWindow* window,
831 RemoveRootReason reason) {
832 DCHECK(roots_.count(window) > 0);
833 roots_.erase(window);
834
835 const ClientWindowId client_window_id(ClientWindowIdForWindow(window));
836
837 // No need to do anything if we created the window.
838 if (window->id().client_id == id_)
839 return;
840
841 if (reason == RemoveRootReason::EMBED) {
842 client()->OnUnembed(client_window_id.id);
843 client()->OnWindowDeleted(client_window_id.id);
844 window_server_->OnTreeMessagedClient(id_);
845 }
846
847 // This client no longer knows about the window. Unparent any windows that
848 // were parented to windows in the root.
849 std::vector<ServerWindow*> local_windows;
850 RemoveFromKnown(window, &local_windows);
851 for (size_t i = 0; i < local_windows.size(); ++i)
852 local_windows[i]->parent()->Remove(local_windows[i]);
853 }
854
855 Array<mojom::WindowDataPtr> WindowTree::WindowsToWindowDatas(
856 const std::vector<const ServerWindow*>& windows) {
857 Array<mojom::WindowDataPtr> array(windows.size());
858 for (size_t i = 0; i < windows.size(); ++i)
859 array[i] = WindowToWindowData(windows[i]);
860 return array;
861 }
862
863 mojom::WindowDataPtr WindowTree::WindowToWindowData(
864 const ServerWindow* window) {
865 DCHECK(IsWindowKnown(window));
866 const ServerWindow* parent = window->parent();
867 // If the parent isn't known, it means the parent is not visible to us (not
868 // in roots), and should not be sent over.
869 if (parent && !IsWindowKnown(parent))
870 parent = nullptr;
871 mojom::WindowDataPtr window_data(mojom::WindowData::New());
872 window_data->parent_id =
873 parent ? ClientWindowIdForWindow(parent).id : ClientWindowId().id;
874 window_data->window_id =
875 window ? ClientWindowIdForWindow(window).id : ClientWindowId().id;
876 window_data->bounds = window->bounds();
877 window_data->properties =
878 mojo::Map<String, Array<uint8_t>>::From(window->properties());
879 window_data->visible = window->visible();
880 return window_data;
881 }
882
883 void WindowTree::GetWindowTreeImpl(
884 const ServerWindow* window,
885 std::vector<const ServerWindow*>* windows) const {
886 DCHECK(window);
887
888 if (!access_policy_->CanGetWindowTree(window))
889 return;
890
891 windows->push_back(window);
892
893 if (!access_policy_->CanDescendIntoWindowForWindowTree(window))
894 return;
895
896 std::vector<const ServerWindow*> children(window->GetChildren());
897 for (size_t i = 0; i < children.size(); ++i)
898 GetWindowTreeImpl(children[i], windows);
899 }
900
901 void WindowTree::NotifyDrawnStateChanged(const ServerWindow* window,
902 bool new_drawn_value) {
903 // Even though we don't know about window, it may be an ancestor of our root,
904 // in which case the change may effect our roots drawn state.
905 if (roots_.empty())
906 return;
907
908 for (auto* root : roots_) {
909 if (window->Contains(root) && (new_drawn_value != root->IsDrawn())) {
910 client()->OnWindowParentDrawnStateChanged(
911 ClientWindowIdForWindow(root).id, new_drawn_value);
912 }
913 }
914 }
915
916 void WindowTree::DestroyWindows() {
917 if (created_window_map_.empty())
918 return;
919
920 Operation op(this, window_server_, OperationType::DELETE_WINDOW);
921 // If we get here from the destructor we're not going to get
922 // ProcessWindowDeleted(). Copy the map and delete from the copy so that we
923 // don't have to worry about whether |created_window_map_| changes or not.
924 base::hash_map<WindowId, ServerWindow*> created_window_map_copy;
925 created_window_map_.swap(created_window_map_copy);
926 // A sibling can be a transient parent of another window so we detach windows
927 // from their transient parents to avoid double deletes.
928 for (auto& pair : created_window_map_copy) {
929 ServerWindow* transient_parent = pair.second->transient_parent();
930 if (transient_parent)
931 transient_parent->RemoveTransientWindow(pair.second);
932 }
933 STLDeleteValues(&created_window_map_copy);
934 }
935
936 bool WindowTree::CanEmbed(const ClientWindowId& window_id) const {
937 const ServerWindow* window = GetWindowByClientId(window_id);
938 return window && access_policy_->CanEmbed(window);
939 }
940
941 void WindowTree::PrepareForEmbed(ServerWindow* window) {
942 DCHECK(window);
943
944 // Only allow a node to be the root for one client.
945 WindowTree* existing_owner = window_server_->GetTreeWithRoot(window);
946
947 Operation op(this, window_server_, OperationType::EMBED);
948 RemoveChildrenAsPartOfEmbed(window);
949 if (existing_owner) {
950 // Never message the originating client.
951 window_server_->OnTreeMessagedClient(id_);
952 existing_owner->RemoveRoot(window, RemoveRootReason::EMBED);
953 }
954 }
955
956 void WindowTree::RemoveChildrenAsPartOfEmbed(ServerWindow* window) {
957 CHECK(window);
958 std::vector<ServerWindow*> children = window->GetChildren();
959 for (size_t i = 0; i < children.size(); ++i)
960 window->Remove(children[i]);
961 }
962
963 void WindowTree::DispatchInputEventImpl(ServerWindow* target,
964 const ui::Event& event) {
965 DCHECK(!event_ack_id_);
966 // We do not want to create a sequential id for each event, because that can
967 // leak some information to the client. So instead, manufacture the id
968 // randomly.
969 // TODO(moshayedi): Find a faster way to generate ids.
970 event_ack_id_ = 0x1000000 | (rand() & 0xffffff);
971 WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(target);
972 DCHECK(display_root);
973 event_source_wms_ = display_root->window_manager_state();
974 // Should only get events from windows attached to a host.
975 DCHECK(event_source_wms_);
976 bool matched_observer =
977 event_observer_matcher_ && event_observer_matcher_->MatchesEvent(event);
978 client()->OnWindowInputEvent(
979 event_ack_id_, ClientWindowIdForWindow(target).id,
980 ui::Event::Clone(event), matched_observer ? event_observer_id_ : 0);
981 }
982
983 void WindowTree::SendToEventObserver(const ui::Event& event) {
984 if (event_observer_matcher_ && event_observer_matcher_->MatchesEvent(event))
985 client()->OnEventObserved(ui::Event::Clone(event), event_observer_id_);
986 }
987
988 void WindowTree::NewWindow(
989 uint32_t change_id,
990 Id transport_window_id,
991 mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) {
992 std::map<std::string, std::vector<uint8_t>> properties;
993 if (!transport_properties.is_null()) {
994 properties =
995 transport_properties.To<std::map<std::string, std::vector<uint8_t>>>();
996 }
997 client()->OnChangeCompleted(
998 change_id, NewWindow(ClientWindowId(transport_window_id), properties));
999 }
1000
1001 void WindowTree::NewTopLevelWindow(
1002 uint32_t change_id,
1003 Id transport_window_id,
1004 mojo::Map<mojo::String, mojo::Array<uint8_t>> transport_properties) {
1005 DCHECK(!waiting_for_top_level_window_info_);
1006 const ClientWindowId client_window_id(transport_window_id);
1007 // TODO(sky): need a way for client to provide context to figure out display.
1008 Display* display = display_manager()->displays().empty()
1009 ? nullptr
1010 : *(display_manager()->displays().begin());
1011 // TODO(sky): move checks to accesspolicy.
1012 WindowManagerDisplayRoot* display_root =
1013 display && user_id_ != InvalidUserId()
1014 ? display->GetWindowManagerDisplayRootForUser(user_id_)
1015 : nullptr;
1016 if (!display_root ||
1017 display_root->window_manager_state()->window_tree() == this ||
1018 !IsValidIdForNewWindow(client_window_id)) {
1019 client()->OnChangeCompleted(change_id, false);
1020 return;
1021 }
1022
1023 // The server creates the real window. Any further messages from the client
1024 // may try to alter the window. Pause incoming messages so that we know we
1025 // can't get a message for a window before the window is created. Once the
1026 // window is created we'll resume processing.
1027 binding_->SetIncomingMethodCallProcessingPaused(true);
1028
1029 const uint32_t wm_change_id =
1030 window_server_->GenerateWindowManagerChangeId(this, change_id);
1031
1032 waiting_for_top_level_window_info_.reset(
1033 new WaitingForTopLevelWindowInfo(client_window_id, wm_change_id));
1034
1035 display_root->window_manager_state()
1036 ->window_tree()
1037 ->window_manager_internal_->WmCreateTopLevelWindow(
1038 wm_change_id, id_, std::move(transport_properties));
1039 }
1040
1041 void WindowTree::DeleteWindow(uint32_t change_id, Id transport_window_id) {
1042 ServerWindow* window =
1043 GetWindowByClientId(ClientWindowId(transport_window_id));
1044 bool success = false;
1045 bool should_close = window && (access_policy_->CanDeleteWindow(window) ||
1046 ShouldRouteToWindowManager(window));
1047 if (should_close) {
1048 WindowTree* tree =
1049 window_server_->GetTreeWithId(window->id().client_id);
1050 success = tree && tree->DeleteWindowImpl(this, window);
1051 }
1052 client()->OnChangeCompleted(change_id, success);
1053 }
1054
1055 void WindowTree::AddWindow(uint32_t change_id, Id parent_id, Id child_id) {
1056 client()->OnChangeCompleted(change_id, AddWindow(ClientWindowId(parent_id),
1057 ClientWindowId(child_id)));
1058 }
1059
1060 void WindowTree::RemoveWindowFromParent(uint32_t change_id, Id window_id) {
1061 bool success = false;
1062 ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id));
1063 if (window && window->parent() &&
1064 access_policy_->CanRemoveWindowFromParent(window)) {
1065 success = true;
1066 Operation op(this, window_server_,
1067 OperationType::REMOVE_WINDOW_FROM_PARENT);
1068 window->parent()->Remove(window);
1069 }
1070 client()->OnChangeCompleted(change_id, success);
1071 }
1072
1073 void WindowTree::AddTransientWindow(uint32_t change_id,
1074 Id window,
1075 Id transient_window) {
1076 client()->OnChangeCompleted(
1077 change_id, AddTransientWindow(ClientWindowId(window),
1078 ClientWindowId(transient_window)));
1079 }
1080
1081 void WindowTree::RemoveTransientWindowFromParent(uint32_t change_id,
1082 Id transient_window_id) {
1083 bool success = false;
1084 ServerWindow* transient_window =
1085 GetWindowByClientId(ClientWindowId(transient_window_id));
1086 if (transient_window && transient_window->transient_parent() &&
1087 access_policy_->CanRemoveTransientWindowFromParent(transient_window)) {
1088 success = true;
1089 Operation op(this, window_server_,
1090 OperationType::REMOVE_TRANSIENT_WINDOW_FROM_PARENT);
1091 transient_window->transient_parent()->RemoveTransientWindow(
1092 transient_window);
1093 }
1094 client()->OnChangeCompleted(change_id, success);
1095 }
1096
1097 void WindowTree::SetModal(uint32_t change_id, Id window_id) {
1098 client()->OnChangeCompleted(change_id, SetModal(ClientWindowId(window_id)));
1099 }
1100
1101 void WindowTree::ReorderWindow(uint32_t change_id,
1102 Id window_id,
1103 Id relative_window_id,
1104 mojom::OrderDirection direction) {
1105 bool success = false;
1106 ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id));
1107 ServerWindow* relative_window =
1108 GetWindowByClientId(ClientWindowId(relative_window_id));
1109 if (CanReorderWindow(window, relative_window, direction)) {
1110 success = true;
1111 Operation op(this, window_server_, OperationType::REORDER_WINDOW);
1112 window->Reorder(relative_window, direction);
1113 window_server_->ProcessWindowReorder(window, relative_window, direction);
1114 }
1115 client()->OnChangeCompleted(change_id, success);
1116 }
1117
1118 void WindowTree::GetWindowTree(
1119 Id window_id,
1120 const base::Callback<void(Array<mojom::WindowDataPtr>)>& callback) {
1121 std::vector<const ServerWindow*> windows(
1122 GetWindowTree(ClientWindowId(window_id)));
1123 callback.Run(WindowsToWindowDatas(windows));
1124 }
1125
1126 void WindowTree::SetCapture(uint32_t change_id, Id window_id) {
1127 client()->OnChangeCompleted(change_id, SetCapture(ClientWindowId(window_id)));
1128 }
1129
1130 void WindowTree::ReleaseCapture(uint32_t change_id, Id window_id) {
1131 ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id));
1132 WindowManagerDisplayRoot* display_root = GetWindowManagerDisplayRoot(window);
1133 ServerWindow* current_capture_window =
1134 display_root ? display_root->window_manager_state()->capture_window()
1135 : nullptr;
1136 bool success = window && display_root &&
1137 display_root->window_manager_state()->IsActive() &&
1138 (!current_capture_window ||
1139 access_policy_->CanSetCapture(current_capture_window)) &&
1140 window == current_capture_window;
1141 if (success) {
1142 Operation op(this, window_server_, OperationType::RELEASE_CAPTURE);
1143 success = display_root->window_manager_state()->SetCapture(
1144 nullptr, kInvalidClientId);
1145 }
1146 client()->OnChangeCompleted(change_id, success);
1147 }
1148
1149 void WindowTree::SetEventObserver(mojom::EventMatcherPtr matcher,
1150 uint32_t observer_id) {
1151 if (matcher.is_null() || observer_id == 0) {
1152 // Clear any existing event observer.
1153 event_observer_matcher_.reset();
1154 event_observer_id_ = 0;
1155 return;
1156 }
1157
1158 // Do not allow key events to be observed, as a compromised app could register
1159 // itself as an event observer and spy on keystrokes to another app.
1160 if (!matcher->type_matcher) {
1161 DVLOG(1) << "SetEventObserver must specify an event type.";
1162 return;
1163 }
1164 const ui::mojom::EventType event_type_whitelist[] = {
1165 ui::mojom::EventType::POINTER_CANCEL, ui::mojom::EventType::POINTER_DOWN,
1166 ui::mojom::EventType::POINTER_MOVE, ui::mojom::EventType::POINTER_UP,
1167 ui::mojom::EventType::MOUSE_EXIT, ui::mojom::EventType::WHEEL,
1168 };
1169 bool allowed = false;
1170 for (ui::mojom::EventType event_type : event_type_whitelist) {
1171 if (matcher->type_matcher->type == event_type) {
1172 allowed = true;
1173 break;
1174 }
1175 }
1176 if (!allowed) {
1177 DVLOG(1) << "SetEventObserver event type not allowed";
1178 return;
1179 }
1180
1181 event_observer_matcher_.reset(new EventMatcher(*matcher));
1182 event_observer_id_ = observer_id;
1183 }
1184
1185 void WindowTree::SetWindowBounds(uint32_t change_id,
1186 Id window_id,
1187 const gfx::Rect& bounds) {
1188 ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id));
1189 if (window && ShouldRouteToWindowManager(window)) {
1190 const uint32_t wm_change_id =
1191 window_server_->GenerateWindowManagerChangeId(this, change_id);
1192 // |window_id| may be a client id, use the id from the window to ensure
1193 // the windowmanager doesn't get an id it doesn't know about.
1194 WindowManagerDisplayRoot* display_root =
1195 GetWindowManagerDisplayRoot(window);
1196 WindowTree* wm_tree = display_root->window_manager_state()->window_tree();
1197 wm_tree->window_manager_internal_->WmSetBounds(
1198 wm_change_id, wm_tree->ClientWindowIdForWindow(window).id,
1199 std::move(bounds));
1200 return;
1201 }
1202
1203 // Only the owner of the window can change the bounds.
1204 bool success = window && access_policy_->CanSetWindowBounds(window);
1205 if (success) {
1206 Operation op(this, window_server_, OperationType::SET_WINDOW_BOUNDS);
1207 window->SetBounds(bounds);
1208 }
1209 client()->OnChangeCompleted(change_id, success);
1210 }
1211
1212 void WindowTree::SetWindowVisibility(uint32_t change_id,
1213 Id transport_window_id,
1214 bool visible) {
1215 client()->OnChangeCompleted(
1216 change_id,
1217 SetWindowVisibility(ClientWindowId(transport_window_id), visible));
1218 }
1219
1220 void WindowTree::SetWindowProperty(uint32_t change_id,
1221 Id transport_window_id,
1222 const mojo::String& name,
1223 mojo::Array<uint8_t> value) {
1224 ServerWindow* window =
1225 GetWindowByClientId(ClientWindowId(transport_window_id));
1226 if (window && ShouldRouteToWindowManager(window)) {
1227 const uint32_t wm_change_id =
1228 window_server_->GenerateWindowManagerChangeId(this, change_id);
1229 WindowManagerDisplayRoot* display_root =
1230 GetWindowManagerDisplayRoot(window);
1231 WindowTree* wm_tree = display_root->window_manager_state()->window_tree();
1232 wm_tree->window_manager_internal_->WmSetProperty(
1233 wm_change_id, wm_tree->ClientWindowIdForWindow(window).id, name,
1234 std::move(value));
1235 return;
1236 }
1237 const bool success = window && access_policy_->CanSetWindowProperties(window);
1238 if (success) {
1239 Operation op(this, window_server_, OperationType::SET_WINDOW_PROPERTY);
1240 if (value.is_null()) {
1241 window->SetProperty(name, nullptr);
1242 } else {
1243 std::vector<uint8_t> data = value.To<std::vector<uint8_t>>();
1244 window->SetProperty(name, &data);
1245 }
1246 }
1247 client()->OnChangeCompleted(change_id, success);
1248 }
1249
1250 void WindowTree::SetWindowOpacity(uint32_t change_id,
1251 Id window_id,
1252 float opacity) {
1253 client()->OnChangeCompleted(
1254 change_id, SetWindowOpacity(ClientWindowId(window_id), opacity));
1255 }
1256
1257 void WindowTree::AttachSurface(Id transport_window_id,
1258 mojom::SurfaceType type,
1259 mojo::InterfaceRequest<mojom::Surface> surface,
1260 mojom::SurfaceClientPtr client) {
1261 ServerWindow* window =
1262 GetWindowByClientId(ClientWindowId(transport_window_id));
1263 const bool success =
1264 window && access_policy_->CanSetWindowSurface(window, type);
1265 if (!success)
1266 return;
1267 window->CreateSurface(type, std::move(surface), std::move(client));
1268 }
1269
1270 void WindowTree::SetWindowTextInputState(Id transport_window_id,
1271 mojo::TextInputStatePtr state) {
1272 ServerWindow* window =
1273 GetWindowByClientId(ClientWindowId(transport_window_id));
1274 bool success = window && access_policy_->CanSetWindowTextInputState(window);
1275 if (success)
1276 window->SetTextInputState(state.To<ui::TextInputState>());
1277 }
1278
1279 void WindowTree::SetImeVisibility(Id transport_window_id,
1280 bool visible,
1281 mojo::TextInputStatePtr state) {
1282 ServerWindow* window =
1283 GetWindowByClientId(ClientWindowId(transport_window_id));
1284 bool success = window && access_policy_->CanSetWindowTextInputState(window);
1285 if (success) {
1286 if (!state.is_null())
1287 window->SetTextInputState(state.To<ui::TextInputState>());
1288
1289 Display* display = GetDisplay(window);
1290 if (display)
1291 display->SetImeVisibility(window, visible);
1292 }
1293 }
1294
1295 void WindowTree::OnWindowInputEventAck(uint32_t event_id,
1296 mojom::EventResult result) {
1297 if (event_ack_id_ == 0 || event_id != event_ack_id_) {
1298 // TODO(sad): Something bad happened. Kill the client?
1299 NOTIMPLEMENTED() << "Wrong event acked.";
1300 }
1301 event_ack_id_ = 0;
1302
1303 if (janky_)
1304 event_source_wms_->window_tree()->ClientJankinessChanged(this);
1305
1306 WindowManagerState* event_source_wms = event_source_wms_;
1307 event_source_wms_ = nullptr;
1308 if (event_source_wms)
1309 event_source_wms->OnEventAck(this, result);
1310
1311 if (!event_queue_.empty()) {
1312 DCHECK(!event_ack_id_);
1313 ServerWindow* target = nullptr;
1314 std::unique_ptr<ui::Event> event;
1315 do {
1316 std::unique_ptr<TargetedEvent> targeted_event =
1317 std::move(event_queue_.front());
1318 event_queue_.pop();
1319 target = targeted_event->target();
1320 event = targeted_event->TakeEvent();
1321 } while (!event_queue_.empty() && !GetDisplay(target));
1322 if (target)
1323 DispatchInputEventImpl(target, *event);
1324 }
1325 }
1326
1327 void WindowTree::SetClientArea(
1328 Id transport_window_id,
1329 const gfx::Insets& insets,
1330 mojo::Array<gfx::Rect> transport_additional_client_areas) {
1331 ServerWindow* window =
1332 GetWindowByClientId(ClientWindowId(transport_window_id));
1333 if (!window || !access_policy_->CanSetClientArea(window))
1334 return;
1335
1336 std::vector<gfx::Rect> additional_client_areas =
1337 transport_additional_client_areas.To<std::vector<gfx::Rect>>();
1338 window->SetClientArea(insets, additional_client_areas);
1339 }
1340
1341 void WindowTree::SetHitTestMask(Id transport_window_id, const gfx::Rect& mask) {
1342 ServerWindow* window =
1343 GetWindowByClientId(ClientWindowId(transport_window_id));
1344 if (!window || !access_policy_->CanSetHitTestMask(window)) {
1345 DVLOG(1) << "SetHitTestMask failed";
1346 return;
1347 }
1348
1349 if (!mask.IsEmpty())
1350 window->SetHitTestMask(mask);
1351 else
1352 window->ClearHitTestMask();
1353 }
1354
1355 void WindowTree::Embed(Id transport_window_id,
1356 mojom::WindowTreeClientPtr client,
1357 uint32_t flags,
1358 const EmbedCallback& callback) {
1359 callback.Run(
1360 Embed(ClientWindowId(transport_window_id), std::move(client), flags));
1361 }
1362
1363 void WindowTree::SetFocus(uint32_t change_id, Id transport_window_id) {
1364 client()->OnChangeCompleted(change_id,
1365 SetFocus(ClientWindowId(transport_window_id)));
1366 }
1367
1368 void WindowTree::SetCanFocus(Id transport_window_id, bool can_focus) {
1369 ServerWindow* window =
1370 GetWindowByClientId(ClientWindowId(transport_window_id));
1371 // TODO(sky): there should be an else case (it shouldn't route to wm and
1372 // policy allows, then set_can_focus).
1373 if (window && ShouldRouteToWindowManager(window))
1374 window->set_can_focus(can_focus);
1375 }
1376
1377 void WindowTree::SetPredefinedCursor(uint32_t change_id,
1378 Id transport_window_id,
1379 mus::mojom::Cursor cursor_id) {
1380 ServerWindow* window =
1381 GetWindowByClientId(ClientWindowId(transport_window_id));
1382
1383 // Only the owner of the window can change the bounds.
1384 bool success = window && access_policy_->CanSetCursorProperties(window);
1385 if (success) {
1386 Operation op(this, window_server_,
1387 OperationType::SET_WINDOW_PREDEFINED_CURSOR);
1388 window->SetPredefinedCursor(cursor_id);
1389 }
1390 client()->OnChangeCompleted(change_id, success);
1391 }
1392
1393 void WindowTree::GetWindowManagerClient(
1394 mojo::AssociatedInterfaceRequest<mojom::WindowManagerClient> internal) {
1395 if (!access_policy_->CanSetWindowManager() || !window_manager_internal_ ||
1396 window_manager_internal_client_binding_) {
1397 return;
1398 }
1399 window_manager_internal_client_binding_.reset(
1400 new mojo::AssociatedBinding<mojom::WindowManagerClient>(
1401 this, std::move(internal)));
1402 }
1403
1404 void WindowTree::GetCursorLocationMemory(
1405 const GetCursorLocationMemoryCallback& callback) {
1406 callback.Run(
1407 window_server_->display_manager()->GetUserDisplayManager(user_id_)->
1408 GetCursorLocationMemory());
1409 }
1410
1411 void WindowTree::AddAccelerator(uint32_t id,
1412 mojom::EventMatcherPtr event_matcher,
1413 const AddAcceleratorCallback& callback) {
1414 DCHECK(window_manager_state_);
1415 const bool success =
1416 window_manager_state_->event_dispatcher()->AddAccelerator(
1417 id, std::move(event_matcher));
1418 callback.Run(success);
1419 }
1420
1421 void WindowTree::RemoveAccelerator(uint32_t id) {
1422 window_manager_state_->event_dispatcher()->RemoveAccelerator(id);
1423 }
1424
1425 void WindowTree::AddActivationParent(Id transport_window_id) {
1426 AddActivationParent(ClientWindowId(transport_window_id));
1427 }
1428
1429 void WindowTree::RemoveActivationParent(Id transport_window_id) {
1430 ServerWindow* window =
1431 GetWindowByClientId(ClientWindowId(transport_window_id));
1432 if (window) {
1433 Display* display = GetDisplay(window);
1434 if (display)
1435 display->RemoveActivationParent(window);
1436 else
1437 DVLOG(1) << "RemoveActivationParent window not associated with display";
1438 } else {
1439 DVLOG(1) << "RemoveActivationParent supplied invalid window id";
1440 }
1441 }
1442
1443 void WindowTree::ActivateNextWindow() {
1444 DCHECK(window_manager_state_);
1445 if (window_server_->user_id_tracker()->active_id() != user_id_)
1446 return;
1447
1448 ServerWindow* focused_window = window_server_->GetFocusedWindow();
1449 if (focused_window) {
1450 WindowManagerDisplayRoot* display_root =
1451 GetWindowManagerDisplayRoot(focused_window);
1452 if (display_root->window_manager_state() != window_manager_state_.get()) {
1453 // We aren't active.
1454 return;
1455 }
1456 display_root->display()->ActivateNextWindow();
1457 return;
1458 }
1459 // Use the first display.
1460 std::set<Display*> displays = window_server_->display_manager()->displays();
1461 if (displays.empty())
1462 return;
1463
1464 (*displays.begin())->ActivateNextWindow();
1465 }
1466
1467 void WindowTree::SetUnderlaySurfaceOffsetAndExtendedHitArea(
1468 Id window_id,
1469 int32_t x_offset,
1470 int32_t y_offset,
1471 const gfx::Insets& hit_area) {
1472 ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id));
1473 if (!window)
1474 return;
1475
1476 window->SetUnderlayOffset(gfx::Vector2d(x_offset, y_offset));
1477 window->set_extended_hit_test_region(hit_area);
1478 }
1479
1480 void WindowTree::WmResponse(uint32_t change_id, bool response) {
1481 window_server_->WindowManagerChangeCompleted(change_id, response);
1482 }
1483
1484 void WindowTree::WmRequestClose(Id transport_window_id) {
1485 ServerWindow* window =
1486 GetWindowByClientId(ClientWindowId(transport_window_id));
1487 WindowTree* tree = window_server_->GetTreeWithRoot(window);
1488 if (tree && tree != this) {
1489 tree->client()->RequestClose(tree->ClientWindowIdForWindow(window).id);
1490 }
1491 // TODO(sky): think about what else case means.
1492 }
1493
1494 void WindowTree::WmSetFrameDecorationValues(
1495 mojom::FrameDecorationValuesPtr values) {
1496 DCHECK(window_manager_state_);
1497 window_manager_state_->SetFrameDecorationValues(std::move(values));
1498 }
1499
1500 void WindowTree::WmSetNonClientCursor(uint32_t window_id,
1501 mojom::Cursor cursor_id) {
1502 DCHECK(window_manager_state_);
1503 ServerWindow* window = GetWindowByClientId(ClientWindowId(window_id));
1504 if (window) {
1505 window->SetNonClientCursor(cursor_id);
1506 } else {
1507 DVLOG(1) << "trying to update non-client cursor of invalid window";
1508 }
1509 }
1510
1511 void WindowTree::OnWmCreatedTopLevelWindow(uint32_t change_id,
1512 Id transport_window_id) {
1513 ServerWindow* window =
1514 GetWindowByClientId(ClientWindowId(transport_window_id));
1515 if (window && window->id().client_id != id_) {
1516 DVLOG(1) << "OnWmCreatedTopLevelWindow supplied invalid window id";
1517 window_server_->WindowManagerSentBogusMessage();
1518 window = nullptr;
1519 }
1520 window_server_->WindowManagerCreatedTopLevelWindow(this, change_id, window);
1521 }
1522
1523 bool WindowTree::HasRootForAccessPolicy(const ServerWindow* window) const {
1524 return HasRoot(window);
1525 }
1526
1527 bool WindowTree::IsWindowKnownForAccessPolicy(
1528 const ServerWindow* window) const {
1529 return IsWindowKnown(window);
1530 }
1531
1532 bool WindowTree::IsWindowRootOfAnotherTreeForAccessPolicy(
1533 const ServerWindow* window) const {
1534 WindowTree* tree = window_server_->GetTreeWithRoot(window);
1535 return tree && tree != this;
1536 }
1537
1538 } // namespace ws
1539 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/window_tree.h ('k') | components/mus/ws/window_tree_binding.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698