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

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

Issue 2651593002: mus: Remove the old client lib. (Closed)
Patch Set: restore test Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « services/ui/public/cpp/window.h ('k') | services/ui/public/cpp/window_drop_target.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 "services/ui/public/cpp/window.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <set>
11 #include <string>
12
13 #include "base/bind.h"
14 #include "base/macros.h"
15 #include "services/ui/common/transient_window_utils.h"
16 #include "services/ui/public/cpp/property_type_converters.h"
17 #include "services/ui/public/cpp/window_compositor_frame_sink.h"
18 #include "services/ui/public/cpp/window_observer.h"
19 #include "services/ui/public/cpp/window_private.h"
20 #include "services/ui/public/cpp/window_property.h"
21 #include "services/ui/public/cpp/window_tracker.h"
22 #include "services/ui/public/cpp/window_tree_client.h"
23 #include "services/ui/public/interfaces/window_manager.mojom.h"
24 #include "ui/display/display.h"
25 #include "ui/display/types/display_constants.h"
26 #include "ui/gfx/geometry/rect.h"
27 #include "ui/gfx/geometry/size.h"
28
29 namespace ui {
30
31 namespace {
32
33 void NotifyWindowTreeChangeAtReceiver(
34 Window* receiver,
35 const WindowObserver::TreeChangeParams& params,
36 bool change_applied) {
37 WindowObserver::TreeChangeParams local_params = params;
38 local_params.receiver = receiver;
39 if (change_applied) {
40 for (auto& observer : *WindowPrivate(receiver).observers())
41 observer.OnTreeChanged(local_params);
42 } else {
43 for (auto& observer : *WindowPrivate(receiver).observers())
44 observer.OnTreeChanging(local_params);
45 }
46 }
47
48 void NotifyWindowTreeChangeUp(Window* start_at,
49 const WindowObserver::TreeChangeParams& params,
50 bool change_applied) {
51 for (Window* current = start_at; current; current = current->parent())
52 NotifyWindowTreeChangeAtReceiver(current, params, change_applied);
53 }
54
55 void NotifyWindowTreeChangeDown(Window* start_at,
56 const WindowObserver::TreeChangeParams& params,
57 bool change_applied) {
58 NotifyWindowTreeChangeAtReceiver(start_at, params, change_applied);
59 Window::Children::const_iterator it = start_at->children().begin();
60 for (; it != start_at->children().end(); ++it)
61 NotifyWindowTreeChangeDown(*it, params, change_applied);
62 }
63
64 void NotifyWindowTreeChange(const WindowObserver::TreeChangeParams& params,
65 bool change_applied) {
66 NotifyWindowTreeChangeDown(params.target, params, change_applied);
67 if (params.old_parent)
68 NotifyWindowTreeChangeUp(params.old_parent, params, change_applied);
69 if (params.new_parent)
70 NotifyWindowTreeChangeUp(params.new_parent, params, change_applied);
71 }
72
73 class ScopedTreeNotifier {
74 public:
75 ScopedTreeNotifier(Window* target, Window* old_parent, Window* new_parent) {
76 params_.target = target;
77 params_.old_parent = old_parent;
78 params_.new_parent = new_parent;
79 NotifyWindowTreeChange(params_, false);
80 }
81 ~ScopedTreeNotifier() { NotifyWindowTreeChange(params_, true); }
82
83 private:
84 WindowObserver::TreeChangeParams params_;
85
86 DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier);
87 };
88
89 void RemoveChildImpl(Window* child, Window::Children* children) {
90 Window::Children::iterator it =
91 std::find(children->begin(), children->end(), child);
92 if (it != children->end()) {
93 children->erase(it);
94 WindowPrivate(child).ClearParent();
95 }
96 }
97
98 class OrderChangedNotifier {
99 public:
100 OrderChangedNotifier(Window* window,
101 Window* relative_window,
102 mojom::OrderDirection direction)
103 : window_(window),
104 relative_window_(relative_window),
105 direction_(direction) {}
106
107 ~OrderChangedNotifier() {}
108
109 void NotifyWindowReordering() {
110 for (auto& observer : *WindowPrivate(window_).observers())
111 observer.OnWindowReordering(window_, relative_window_, direction_);
112 }
113
114 void NotifyWindowReordered() {
115 for (auto& observer : *WindowPrivate(window_).observers())
116 observer.OnWindowReordered(window_, relative_window_, direction_);
117 }
118
119 private:
120 Window* window_;
121 Window* relative_window_;
122 mojom::OrderDirection direction_;
123
124 DISALLOW_COPY_AND_ASSIGN(OrderChangedNotifier);
125 };
126
127 class ScopedSetBoundsNotifier {
128 public:
129 ScopedSetBoundsNotifier(Window* window,
130 const gfx::Rect& old_bounds,
131 const gfx::Rect& new_bounds)
132 : window_(window), old_bounds_(old_bounds), new_bounds_(new_bounds) {
133 for (auto& observer : *WindowPrivate(window_).observers())
134 observer.OnWindowBoundsChanging(window_, old_bounds_, new_bounds_);
135 }
136 ~ScopedSetBoundsNotifier() {
137 for (auto& observer : *WindowPrivate(window_).observers())
138 observer.OnWindowBoundsChanged(window_, old_bounds_, new_bounds_);
139 }
140
141 private:
142 Window* window_;
143 const gfx::Rect old_bounds_;
144 const gfx::Rect new_bounds_;
145
146 DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier);
147 };
148
149 bool IsClientRoot(Window* window) {
150 return window->window_tree() &&
151 window->window_tree()->GetRoots().count(window) > 0;
152 }
153
154 bool WasCreatedByThisClientOrIsRoot(Window* window) {
155 return window->WasCreatedByThisClient() || IsClientRoot(window);
156 }
157
158 void EmptyEmbedCallback(bool result) {}
159
160 } // namespace
161
162 ////////////////////////////////////////////////////////////////////////////////
163 // Window, public:
164
165 void Window::Destroy() {
166 if (!WasCreatedByThisClientOrIsRoot(this))
167 return;
168
169 if (client_)
170 client_->DestroyWindow(this);
171 while (!children_.empty()) {
172 Window* child = children_.front();
173 if (!child->WasCreatedByThisClient()) {
174 WindowPrivate(child).ClearParent();
175 children_.erase(children_.begin());
176 } else {
177 child->Destroy();
178 DCHECK(std::find(children_.begin(), children_.end(), child) ==
179 children_.end());
180 }
181 }
182 LocalDestroy();
183 }
184
185 bool Window::WasCreatedByThisClient() const {
186 return !client_ || client_->WasCreatedByThisClient(this);
187 }
188
189 void Window::SetBounds(const gfx::Rect& bounds) {
190 if (!WasCreatedByThisClientOrIsRoot(this))
191 return;
192 if (bounds_ == bounds)
193 return;
194 if (client_)
195 client_->SetBounds(this, bounds_, bounds);
196 LocalSetBounds(bounds_, bounds);
197 }
198
199 gfx::Rect Window::GetBoundsInRoot() const {
200 gfx::Vector2d offset;
201 for (const Window* w = parent(); w != nullptr; w = w->parent())
202 offset += w->bounds().OffsetFromOrigin();
203 return bounds() + offset;
204 }
205
206 void Window::SetClientArea(
207 const gfx::Insets& client_area,
208 const std::vector<gfx::Rect>& additional_client_areas) {
209 if (!WasCreatedByThisClientOrIsRoot(this))
210 return;
211
212 if (client_)
213 client_->SetClientArea(server_id_, client_area,
214 additional_client_areas);
215 LocalSetClientArea(client_area, additional_client_areas);
216 }
217
218 void Window::SetHitTestMask(const gfx::Rect& mask) {
219 if (!WasCreatedByThisClientOrIsRoot(this))
220 return;
221
222 if (hit_test_mask_ && *hit_test_mask_ == mask)
223 return;
224
225 if (client_)
226 client_->SetHitTestMask(server_id_, mask);
227 hit_test_mask_.reset(new gfx::Rect(mask));
228 }
229
230 void Window::ClearHitTestMask() {
231 if (!WasCreatedByThisClientOrIsRoot(this))
232 return;
233
234 if (!hit_test_mask_)
235 return;
236
237 if (client_)
238 client_->ClearHitTestMask(server_id_);
239 hit_test_mask_.reset();
240 }
241
242 void Window::SetVisible(bool value) {
243 if (visible_ == value)
244 return;
245
246 if (client_)
247 client_->SetVisible(this, value);
248 LocalSetVisible(value);
249 }
250
251 void Window::SetOpacity(float opacity) {
252 if (client_)
253 client_->SetOpacity(this, opacity);
254 LocalSetOpacity(opacity);
255 }
256
257 void Window::SetPredefinedCursor(ui::mojom::Cursor cursor_id) {
258 if (cursor_id_ == cursor_id)
259 return;
260
261 if (client_)
262 client_->SetPredefinedCursor(server_id_, cursor_id);
263 LocalSetPredefinedCursor(cursor_id);
264 }
265
266 bool Window::IsDrawn() const {
267 if (!visible_)
268 return false;
269 return parent_ ? parent_->IsDrawn() : parent_drawn_;
270 }
271
272 std::unique_ptr<WindowCompositorFrameSink> Window::RequestCompositorFrameSink(
273 scoped_refptr<cc::ContextProvider> context_provider,
274 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) {
275 std::unique_ptr<WindowCompositorFrameSinkBinding>
276 compositor_frame_sink_binding;
277 std::unique_ptr<WindowCompositorFrameSink> compositor_frame_sink =
278 WindowCompositorFrameSink::Create(
279 cc::FrameSinkId(server_id(), 0), std::move(context_provider),
280 gpu_memory_buffer_manager, &compositor_frame_sink_binding);
281 AttachCompositorFrameSink(std::move(compositor_frame_sink_binding));
282 return compositor_frame_sink;
283 }
284
285 void Window::AttachCompositorFrameSink(
286 std::unique_ptr<WindowCompositorFrameSinkBinding>
287 compositor_frame_sink_binding) {
288 window_tree()->AttachCompositorFrameSink(
289 server_id_,
290 std::move(compositor_frame_sink_binding->compositor_frame_sink_request_),
291 mojo::MakeProxy(std::move(
292 compositor_frame_sink_binding->compositor_frame_sink_client_)));
293 }
294
295 void Window::ClearSharedProperty(const std::string& name) {
296 SetSharedPropertyInternal(name, nullptr);
297 }
298
299 bool Window::HasSharedProperty(const std::string& name) const {
300 return properties_.count(name) > 0;
301 }
302
303 void Window::AddObserver(WindowObserver* observer) {
304 observers_.AddObserver(observer);
305 }
306
307 void Window::RemoveObserver(WindowObserver* observer) {
308 observers_.RemoveObserver(observer);
309 }
310
311 const Window* Window::GetRoot() const {
312 const Window* root = this;
313 for (const Window* parent = this; parent; parent = parent->parent())
314 root = parent;
315 return root;
316 }
317
318 void Window::AddChild(Window* child) {
319 // TODO(beng): not necessarily valid to all clients, but possibly to the
320 // embeddee in an embedder-embeddee relationship.
321 if (client_)
322 CHECK_EQ(child->client_, client_);
323 // Roots can not be added as children of other windows.
324 if (window_tree() && window_tree()->IsRoot(child))
325 return;
326 LocalAddChild(child);
327 if (client_)
328 client_->AddChild(this, child->server_id());
329 }
330
331 void Window::RemoveChild(Window* child) {
332 // TODO(beng): not necessarily valid to all clients, but possibly to the
333 // embeddee in an embedder-embeddee relationship.
334 if (client_)
335 CHECK_EQ(child->client_, client_);
336 LocalRemoveChild(child);
337 if (client_)
338 client_->RemoveChild(this, child->server_id());
339 }
340
341 void Window::Reorder(Window* relative, mojom::OrderDirection direction) {
342 if (!LocalReorder(relative, direction))
343 return;
344 if (client_)
345 client_->Reorder(this, relative->server_id(), direction);
346 }
347
348 void Window::MoveToFront() {
349 if (!parent_ || parent_->children_.back() == this)
350 return;
351 Reorder(parent_->children_.back(), mojom::OrderDirection::ABOVE);
352 }
353
354 void Window::MoveToBack() {
355 if (!parent_ || parent_->children_.front() == this)
356 return;
357 Reorder(parent_->children_.front(), mojom::OrderDirection::BELOW);
358 }
359
360 bool Window::Contains(const Window* child) const {
361 if (!child)
362 return false;
363 if (child == this)
364 return true;
365 if (client_)
366 CHECK_EQ(child->client_, client_);
367 for (const Window* p = child->parent(); p; p = p->parent()) {
368 if (p == this)
369 return true;
370 }
371 return false;
372 }
373
374 void Window::AddTransientWindow(Window* transient_window) {
375 // A system modal window cannot become a transient child.
376 DCHECK(!transient_window->is_modal() || transient_window->transient_parent());
377
378 if (client_)
379 CHECK_EQ(transient_window->client_, client_);
380 LocalAddTransientWindow(transient_window);
381 if (client_)
382 client_->AddTransientWindow(this, transient_window->server_id());
383 }
384
385 void Window::RemoveTransientWindow(Window* transient_window) {
386 if (client_)
387 CHECK_EQ(transient_window->window_tree(), client_);
388 LocalRemoveTransientWindow(transient_window);
389 if (client_)
390 client_->RemoveTransientWindowFromParent(transient_window);
391 }
392
393 void Window::SetModal() {
394 if (is_modal_)
395 return;
396
397 LocalSetModal();
398 if (client_)
399 client_->SetModal(this);
400 }
401
402 Window* Window::GetChildByLocalId(int id) {
403 if (id == local_id_)
404 return this;
405 // TODO(beng): this could be improved depending on how we decide to own
406 // windows.
407 for (Window* child : children_) {
408 Window* matching_child = child->GetChildByLocalId(id);
409 if (matching_child)
410 return matching_child;
411 }
412 return nullptr;
413 }
414
415 void Window::SetTextInputState(mojo::TextInputStatePtr state) {
416 if (client_)
417 client_->SetWindowTextInputState(server_id_, std::move(state));
418 }
419
420 void Window::SetImeVisibility(bool visible, mojo::TextInputStatePtr state) {
421 // SetImeVisibility() shouldn't be used if the window is not editable.
422 DCHECK(state.is_null() || state->type != mojo::TextInputType::NONE);
423 if (client_)
424 client_->SetImeVisibility(server_id_, visible, std::move(state));
425 }
426
427 bool Window::HasCapture() const {
428 return client_ && client_->GetCaptureWindow() == this;
429 }
430
431 void Window::SetCapture() {
432 if (client_)
433 client_->SetCapture(this);
434 }
435
436 void Window::ReleaseCapture() {
437 if (client_)
438 client_->ReleaseCapture(this);
439 }
440
441 void Window::SetFocus() {
442 if (client_ && IsDrawn())
443 client_->SetFocus(this);
444 }
445
446 bool Window::HasFocus() const {
447 return client_ && client_->GetFocusedWindow() == this;
448 }
449
450 void Window::SetCanFocus(bool can_focus) {
451 if (client_)
452 client_->SetCanFocus(server_id_, can_focus);
453 }
454
455 void Window::SetCanAcceptDrops(WindowDropTarget* drop_target) {
456 if (drop_target_ == drop_target)
457 return;
458 drop_target_ = drop_target;
459 if (client_)
460 client_->SetCanAcceptDrops(server_id_, !!drop_target_);
461 }
462
463 void Window::SetCanAcceptEvents(bool can_accept_events) {
464 if (can_accept_events_ == can_accept_events)
465 return;
466 can_accept_events_ = can_accept_events;
467 if (client_)
468 client_->SetCanAcceptEvents(server_id_, can_accept_events_);
469 }
470
471 void Window::Embed(ui::mojom::WindowTreeClientPtr client, uint32_t flags) {
472 Embed(std::move(client), base::Bind(&EmptyEmbedCallback), flags);
473 }
474
475 void Window::Embed(ui::mojom::WindowTreeClientPtr client,
476 const EmbedCallback& callback,
477 uint32_t flags) {
478 if (PrepareForEmbed())
479 client_->Embed(server_id_, std::move(client), flags, callback);
480 else
481 callback.Run(false);
482 }
483
484 void Window::RequestClose() {
485 if (client_)
486 client_->RequestClose(this);
487 }
488
489 void Window::PerformDragDrop(
490 const std::map<std::string, std::vector<uint8_t>>& drag_data,
491 int drag_operation,
492 const gfx::Point& cursor_location,
493 const SkBitmap& bitmap,
494 const base::Callback<void(bool, uint32_t)>& callback) {
495 client_->PerformDragDrop(this, drag_data, drag_operation, cursor_location,
496 bitmap, callback);
497 }
498
499 void Window::CancelDragDrop() {
500 client_->CancelDragDrop(this);
501 }
502
503 void Window::PerformWindowMove(mojom::MoveLoopSource source,
504 const gfx::Point& cursor_location,
505 const base::Callback<void(bool)>& callback) {
506 client_->PerformWindowMove(this, source, cursor_location, callback);
507 }
508
509 void Window::CancelWindowMove() {
510 client_->CancelWindowMove(this);
511 }
512
513 std::string Window::GetName() const {
514 if (HasSharedProperty(mojom::WindowManager::kName_Property))
515 return GetSharedProperty<std::string>(mojom::WindowManager::kName_Property);
516
517 return std::string();
518 }
519
520 ////////////////////////////////////////////////////////////////////////////////
521 // Window, protected:
522
523 Window::Window() : Window(nullptr, static_cast<Id>(-1)) {}
524
525 Window::~Window() {
526 for (auto& observer : observers_)
527 observer.OnWindowDestroying(this);
528 if (client_)
529 client_->OnWindowDestroying(this);
530
531 if (HasFocus()) {
532 // The focused window is being removed. When this happens the server
533 // advances focus. We don't want to randomly pick a Window to get focus, so
534 // we update local state only, and wait for the next focus change from the
535 // server.
536 client_->LocalSetFocus(nullptr);
537 }
538
539 // Remove from transient parent.
540 if (transient_parent_)
541 transient_parent_->LocalRemoveTransientWindow(this);
542
543 // Return the surface reference if there is one.
544 if (surface_info_.id().is_valid())
545 LocalSetSurfaceInfo(cc::SurfaceInfo());
546
547 // Remove transient children.
548 while (!transient_children_.empty()) {
549 Window* transient_child = transient_children_.front();
550 LocalRemoveTransientWindow(transient_child);
551 transient_child->LocalDestroy();
552 DCHECK(transient_children_.empty() ||
553 transient_children_.front() != transient_child);
554 }
555
556 if (parent_)
557 parent_->LocalRemoveChild(this);
558
559 // We may still have children. This can happen if the embedder destroys the
560 // root while we're still alive.
561 while (!children_.empty()) {
562 Window* child = children_.front();
563 LocalRemoveChild(child);
564 DCHECK(children_.empty() || children_.front() != child);
565 }
566
567 // Notify observers before clearing properties (order matches aura::Window).
568 for (auto& observer : observers_)
569 observer.OnWindowDestroyed(this);
570
571 // Clear properties.
572 for (auto& pair : prop_map_) {
573 if (pair.second.deallocator)
574 (*pair.second.deallocator)(pair.second.value);
575 }
576 prop_map_.clear();
577
578 // Invoke after observers so that can clean up any internal state observers
579 // may have changed.
580 if (window_tree())
581 window_tree()->OnWindowDestroyed(this);
582 }
583
584 ////////////////////////////////////////////////////////////////////////////////
585 // Window, private:
586
587 Window::Window(WindowTreeClient* client, Id id)
588 : client_(client),
589 server_id_(id),
590 parent_(nullptr),
591 stacking_target_(nullptr),
592 transient_parent_(nullptr),
593 is_modal_(false),
594 // Matches aura, see aura::Window for details.
595 observers_(base::ObserverList<WindowObserver>::NOTIFY_EXISTING_ONLY),
596 input_event_handler_(nullptr),
597 visible_(false),
598 opacity_(1.0f),
599 display_id_(display::kInvalidDisplayId),
600 cursor_id_(mojom::Cursor::CURSOR_NULL),
601 parent_drawn_(false) {}
602
603 void Window::SetSharedPropertyInternal(const std::string& name,
604 const std::vector<uint8_t>* value) {
605 if (!WasCreatedByThisClientOrIsRoot(this))
606 return;
607
608 if (client_) {
609 base::Optional<std::vector<uint8_t>> transport_value;
610 if (value) {
611 transport_value.emplace(value->size());
612 if (value->size())
613 memcpy(&transport_value.value().front(), &(value->front()),
614 value->size());
615 }
616 // TODO: add test coverage of this (450303).
617 client_->SetProperty(this, name, std::move(transport_value));
618 }
619 LocalSetSharedProperty(name, value);
620 }
621
622 int64_t Window::SetLocalPropertyInternal(const void* key,
623 const char* name,
624 PropertyDeallocator deallocator,
625 int64_t value,
626 int64_t default_value) {
627 int64_t old = GetLocalPropertyInternal(key, default_value);
628 if (value == default_value) {
629 prop_map_.erase(key);
630 } else {
631 Value prop_value;
632 prop_value.name = name;
633 prop_value.value = value;
634 prop_value.deallocator = deallocator;
635 prop_map_[key] = prop_value;
636 }
637 for (auto& observer : observers_)
638 observer.OnWindowLocalPropertyChanged(this, key, old);
639 return old;
640 }
641
642 int64_t Window::GetLocalPropertyInternal(const void* key,
643 int64_t default_value) const {
644 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
645 if (iter == prop_map_.end())
646 return default_value;
647 return iter->second.value;
648 }
649
650 void Window::LocalDestroy() {
651 delete this;
652 }
653
654 void Window::LocalAddChild(Window* child) {
655 ScopedTreeNotifier notifier(child, child->parent(), this);
656 if (child->parent())
657 RemoveChildImpl(child, &child->parent_->children_);
658 children_.push_back(child);
659 child->parent_ = this;
660 child->display_id_ = display_id_;
661 }
662
663 void Window::LocalRemoveChild(Window* child) {
664 DCHECK_EQ(this, child->parent());
665 ScopedTreeNotifier notifier(child, this, nullptr);
666 RemoveChildImpl(child, &children_);
667 }
668
669 void Window::LocalAddTransientWindow(Window* transient_window) {
670 if (transient_window->transient_parent())
671 RemoveTransientWindowImpl(transient_window);
672 transient_children_.push_back(transient_window);
673 transient_window->transient_parent_ = this;
674
675 // Restack |transient_window| properly above its transient parent, if they
676 // share the same parent.
677 if (transient_window->parent() == parent())
678 RestackTransientDescendants(this, &GetStackingTarget,
679 &ReorderWithoutNotification);
680
681 for (auto& observer : observers_)
682 observer.OnTransientChildAdded(this, transient_window);
683 }
684
685 void Window::LocalRemoveTransientWindow(Window* transient_window) {
686 DCHECK_EQ(this, transient_window->transient_parent());
687 RemoveTransientWindowImpl(transient_window);
688 for (auto& observer : observers_)
689 observer.OnTransientChildRemoved(this, transient_window);
690 }
691
692 void Window::LocalSetModal() {
693 is_modal_ = true;
694 }
695
696 bool Window::LocalReorder(Window* relative, mojom::OrderDirection direction) {
697 OrderChangedNotifier notifier(this, relative, direction);
698 return ReorderImpl(this, relative, direction, &notifier);
699 }
700
701 void Window::LocalSetBounds(const gfx::Rect& old_bounds,
702 const gfx::Rect& new_bounds) {
703 // If this client owns the window, then it should be the only one to change
704 // the bounds.
705 DCHECK(!WasCreatedByThisClient() || old_bounds == bounds_);
706 ScopedSetBoundsNotifier notifier(this, old_bounds, new_bounds);
707 bounds_ = new_bounds;
708 }
709
710 void Window::LocalSetClientArea(
711 const gfx::Insets& new_client_area,
712 const std::vector<gfx::Rect>& additional_client_areas) {
713 const std::vector<gfx::Rect> old_additional_client_areas =
714 additional_client_areas_;
715 const gfx::Insets old_client_area = client_area_;
716 client_area_ = new_client_area;
717 additional_client_areas_ = additional_client_areas;
718 for (auto& observer : observers_) {
719 observer.OnWindowClientAreaChanged(this, old_client_area,
720 old_additional_client_areas);
721 }
722 }
723
724 void Window::LocalSetDisplay(int64_t display_id) {
725 display_id_ = display_id;
726 // TODO(sad): Notify observers (of this window, and of the descendant windows)
727 // when a window moves from one display into another. https://crbug.com/614887
728 }
729
730 void Window::LocalSetParentDrawn(bool value) {
731 if (parent_drawn_ == value)
732 return;
733
734 // As IsDrawn() is derived from |visible_| and |parent_drawn_|, only send
735 // drawn notification is the value of IsDrawn() is really changing.
736 if (IsDrawn() == value) {
737 parent_drawn_ = value;
738 return;
739 }
740 for (auto& observer : observers_)
741 observer.OnWindowDrawnChanging(this);
742 parent_drawn_ = value;
743 for (auto& observer : observers_)
744 observer.OnWindowDrawnChanged(this);
745 }
746
747 void Window::LocalSetVisible(bool visible) {
748 if (visible_ == visible)
749 return;
750
751 for (auto& observer : observers_)
752 observer.OnWindowVisibilityChanging(this, visible);
753 visible_ = visible;
754 if (parent_) {
755 for (auto& observer : parent_->observers_)
756 observer.OnChildWindowVisibilityChanged(this, visible);
757 }
758
759 NotifyWindowVisibilityChanged(this, visible);
760 }
761
762 void Window::LocalSetOpacity(float opacity) {
763 if (opacity_ == opacity)
764 return;
765
766 float old_opacity = opacity_;
767 opacity_ = opacity;
768 for (auto& observer : observers_)
769 observer.OnWindowOpacityChanged(this, old_opacity, opacity_);
770 }
771
772 void Window::LocalSetPredefinedCursor(mojom::Cursor cursor_id) {
773 if (cursor_id_ == cursor_id)
774 return;
775
776 cursor_id_ = cursor_id;
777 for (auto& observer : observers_)
778 observer.OnWindowPredefinedCursorChanged(this, cursor_id);
779 }
780
781 void Window::LocalSetSharedProperty(const std::string& name,
782 const std::vector<uint8_t>* value) {
783 std::vector<uint8_t> old_value;
784 std::vector<uint8_t>* old_value_ptr = nullptr;
785 auto it = properties_.find(name);
786 if (it != properties_.end()) {
787 old_value = it->second;
788 old_value_ptr = &old_value;
789
790 if (value && old_value == *value)
791 return;
792 } else if (!value) {
793 // This property isn't set in |properties_| and |value| is nullptr, so
794 // there's no change.
795 return;
796 }
797
798 if (value) {
799 properties_[name] = *value;
800 } else if (it != properties_.end()) {
801 properties_.erase(it);
802 }
803
804 for (auto& observer : observers_)
805 observer.OnWindowSharedPropertyChanged(this, name, old_value_ptr, value);
806 }
807
808 void Window::LocalSetSurfaceInfo(const cc::SurfaceInfo& surface_info) {
809 if (surface_info_.id().is_valid()) {
810 const cc::SurfaceId& existing_surface_id = surface_info_.id();
811 const cc::SurfaceId& new_surface_id = surface_info.id();
812 if (existing_surface_id.is_valid() &&
813 existing_surface_id != new_surface_id) {
814 // TODO(kylechar): Start return reference here?
815 }
816 }
817 surface_info_ = surface_info;
818 }
819
820 void Window::NotifyWindowStackingChanged() {
821 if (stacking_target_) {
822 Children::const_iterator window_i = std::find(
823 parent()->children().begin(), parent()->children().end(), this);
824 DCHECK(window_i != parent()->children().end());
825 if (window_i != parent()->children().begin() &&
826 (*(window_i - 1) == stacking_target_))
827 return;
828 }
829 RestackTransientDescendants(this, &GetStackingTarget,
830 &ReorderWithoutNotification);
831 }
832
833 void Window::NotifyWindowVisibilityChanged(Window* target, bool visible) {
834 if (!NotifyWindowVisibilityChangedDown(target, visible))
835 return; // |this| has been deleted.
836
837 NotifyWindowVisibilityChangedUp(target, visible);
838 }
839
840 bool Window::NotifyWindowVisibilityChangedAtReceiver(Window* target,
841 bool visible) {
842 // |this| may be deleted during a call to OnWindowVisibilityChanged() on one
843 // of the observers. We create an local observer for that. In that case we
844 // exit without further access to any members.
845 WindowTracker tracker;
846 tracker.Add(this);
847 for (auto& observer : observers_)
848 observer.OnWindowVisibilityChanged(target, visible);
849 return tracker.Contains(this);
850 }
851
852 bool Window::NotifyWindowVisibilityChangedDown(Window* target, bool visible) {
853 if (!NotifyWindowVisibilityChangedAtReceiver(target, visible))
854 return false; // |this| was deleted.
855 std::set<const Window*> child_already_processed;
856 bool child_destroyed = false;
857 do {
858 child_destroyed = false;
859 for (Window::Children::const_iterator it = children_.begin();
860 it != children_.end(); ++it) {
861 if (!child_already_processed.insert(*it).second)
862 continue;
863 if (!(*it)->NotifyWindowVisibilityChangedDown(target, visible)) {
864 // |*it| was deleted, |it| is invalid and |children_| has changed. We
865 // exit the current for-loop and enter a new one.
866 child_destroyed = true;
867 break;
868 }
869 }
870 } while (child_destroyed);
871 return true;
872 }
873
874 void Window::NotifyWindowVisibilityChangedUp(Window* target, bool visible) {
875 // Start with the parent as we already notified |this|
876 // in NotifyWindowVisibilityChangedDown.
877 for (Window* window = parent(); window; window = window->parent()) {
878 bool ret = window->NotifyWindowVisibilityChangedAtReceiver(target, visible);
879 DCHECK(ret);
880 }
881 }
882
883 bool Window::PrepareForEmbed() {
884 if (!WasCreatedByThisClient())
885 return false;
886
887 while (!children_.empty())
888 RemoveChild(children_[0]);
889 return true;
890 }
891
892 void Window::RemoveTransientWindowImpl(Window* transient_window) {
893 Window::Children::iterator it = std::find(
894 transient_children_.begin(), transient_children_.end(), transient_window);
895 if (it != transient_children_.end()) {
896 transient_children_.erase(it);
897 transient_window->transient_parent_ = nullptr;
898 }
899 // If |transient_window| and its former transient parent share the same
900 // parent, |transient_window| should be restacked properly so it is not among
901 // transient children of its former parent, anymore.
902 if (parent() == transient_window->parent())
903 RestackTransientDescendants(this, &GetStackingTarget,
904 &ReorderWithoutNotification);
905
906 // TOOD(fsamuel): We might want to notify observers here.
907 }
908
909 // static
910 void Window::ReorderWithoutNotification(Window* window,
911 Window* relative,
912 mojom::OrderDirection direction) {
913 ReorderImpl(window, relative, direction, nullptr);
914 }
915
916 // static
917 bool Window::ReorderImpl(Window* window,
918 Window* relative,
919 mojom::OrderDirection direction,
920 OrderChangedNotifier* notifier) {
921 DCHECK(relative);
922 DCHECK_NE(window, relative);
923 DCHECK_EQ(window->parent(), relative->parent());
924 DCHECK(window->parent());
925
926 if (!AdjustStackingForTransientWindows(&window, &relative, &direction,
927 window->stacking_target_))
928 return false;
929
930 const size_t child_i = std::find(window->parent_->children_.begin(),
931 window->parent_->children_.end(), window) -
932 window->parent_->children_.begin();
933 const size_t target_i =
934 std::find(window->parent_->children_.begin(),
935 window->parent_->children_.end(), relative) -
936 window->parent_->children_.begin();
937 if ((direction == mojom::OrderDirection::ABOVE && child_i == target_i + 1) ||
938 (direction == mojom::OrderDirection::BELOW && child_i + 1 == target_i)) {
939 return false;
940 }
941
942 if (notifier)
943 notifier->NotifyWindowReordering();
944
945 const size_t dest_i = direction == mojom::OrderDirection::ABOVE
946 ? (child_i < target_i ? target_i : target_i + 1)
947 : (child_i < target_i ? target_i - 1 : target_i);
948 window->parent_->children_.erase(window->parent_->children_.begin() +
949 child_i);
950 window->parent_->children_.insert(window->parent_->children_.begin() + dest_i,
951 window);
952
953 window->NotifyWindowStackingChanged();
954
955 if (notifier)
956 notifier->NotifyWindowReordered();
957
958 return true;
959 }
960
961 // static
962 Window** Window::GetStackingTarget(Window* window) {
963 return &window->stacking_target_;
964 }
965 } // namespace ui
OLDNEW
« no previous file with comments | « services/ui/public/cpp/window.h ('k') | services/ui/public/cpp/window_drop_target.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698