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

Side by Side Diff: components/mus/ws/server_window.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/server_window.h ('k') | components/mus/ws/server_window_delegate.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/server_window.h"
6
7 #include <inttypes.h>
8 #include <stddef.h>
9
10 #include "base/strings/stringprintf.h"
11 #include "components/mus/common/transient_window_utils.h"
12 #include "components/mus/public/interfaces/window_manager.mojom.h"
13 #include "components/mus/ws/server_window_delegate.h"
14 #include "components/mus/ws/server_window_observer.h"
15 #include "components/mus/ws/server_window_surface_manager.h"
16
17 namespace mus {
18
19 namespace ws {
20
21 ServerWindow::ServerWindow(ServerWindowDelegate* delegate, const WindowId& id)
22 : ServerWindow(delegate, id, Properties()) {}
23
24 ServerWindow::ServerWindow(ServerWindowDelegate* delegate,
25 const WindowId& id,
26 const Properties& properties)
27 : delegate_(delegate),
28 id_(id),
29 parent_(nullptr),
30 stacking_target_(nullptr),
31 transient_parent_(nullptr),
32 is_modal_(false),
33 visible_(false),
34 cursor_id_(mojom::Cursor::CURSOR_NULL),
35 non_client_cursor_id_(mojom::Cursor::CURSOR_NULL),
36 opacity_(1),
37 can_focus_(true),
38 properties_(properties),
39 // Don't notify newly added observers during notification. This causes
40 // problems for code that adds an observer as part of an observer
41 // notification (such as ServerWindowDrawTracker).
42 observers_(
43 base::ObserverList<ServerWindowObserver>::NOTIFY_EXISTING_ONLY) {
44 DCHECK(delegate); // Must provide a delegate.
45 }
46
47 ServerWindow::~ServerWindow() {
48 FOR_EACH_OBSERVER(ServerWindowObserver, observers_, OnWindowDestroying(this));
49
50 if (transient_parent_)
51 transient_parent_->RemoveTransientWindow(this);
52
53 // Destroy transient children, only after we've removed ourselves from our
54 // parent, as destroying an active transient child may otherwise attempt to
55 // refocus us.
56 Windows transient_children(transient_children_);
57 STLDeleteElements(&transient_children);
58 DCHECK(transient_children_.empty());
59
60 while (!children_.empty())
61 children_.front()->parent()->Remove(children_.front());
62
63 if (parent_)
64 parent_->Remove(this);
65
66 FOR_EACH_OBSERVER(ServerWindowObserver, observers_, OnWindowDestroyed(this));
67 }
68
69 void ServerWindow::AddObserver(ServerWindowObserver* observer) {
70 observers_.AddObserver(observer);
71 }
72
73 void ServerWindow::RemoveObserver(ServerWindowObserver* observer) {
74 DCHECK(observers_.HasObserver(observer));
75 observers_.RemoveObserver(observer);
76 }
77
78 void ServerWindow::CreateSurface(mojom::SurfaceType surface_type,
79 mojo::InterfaceRequest<mojom::Surface> request,
80 mojom::SurfaceClientPtr client) {
81 GetOrCreateSurfaceManager()->CreateSurface(surface_type, std::move(request),
82 std::move(client));
83 }
84
85 void ServerWindow::Add(ServerWindow* child) {
86 // We assume validation checks happened already.
87 DCHECK(child);
88 DCHECK(child != this);
89 DCHECK(!child->Contains(this));
90 if (child->parent() == this) {
91 if (children_.size() == 1)
92 return; // Already in the right position.
93 child->Reorder(children_.back(), mojom::OrderDirection::ABOVE);
94 return;
95 }
96
97 ServerWindow* old_parent = child->parent();
98 FOR_EACH_OBSERVER(ServerWindowObserver, child->observers_,
99 OnWillChangeWindowHierarchy(child, this, old_parent));
100
101 if (child->parent())
102 child->parent()->RemoveImpl(child);
103
104 child->parent_ = this;
105 children_.push_back(child);
106
107 // Stack the child properly if it is a transient child of a sibling.
108 if (child->transient_parent_ && child->transient_parent_->parent() == this)
109 RestackTransientDescendants(child->transient_parent_, &GetStackingTarget,
110 &ReorderImpl);
111
112 FOR_EACH_OBSERVER(ServerWindowObserver, child->observers_,
113 OnWindowHierarchyChanged(child, this, old_parent));
114 }
115
116 void ServerWindow::Remove(ServerWindow* child) {
117 // We assume validation checks happened else where.
118 DCHECK(child);
119 DCHECK(child != this);
120 DCHECK(child->parent() == this);
121
122 FOR_EACH_OBSERVER(ServerWindowObserver, child->observers_,
123 OnWillChangeWindowHierarchy(child, nullptr, this));
124 RemoveImpl(child);
125
126 // Stack the child properly if it is a transient child of a sibling.
127 if (child->transient_parent_ && child->transient_parent_->parent() == this)
128 RestackTransientDescendants(child->transient_parent_, &GetStackingTarget,
129 &ReorderImpl);
130
131 FOR_EACH_OBSERVER(ServerWindowObserver, child->observers_,
132 OnWindowHierarchyChanged(child, nullptr, this));
133 }
134
135 void ServerWindow::Reorder(ServerWindow* relative,
136 mojom::OrderDirection direction) {
137 ReorderImpl(this, relative, direction);
138 }
139
140 void ServerWindow::StackChildAtBottom(ServerWindow* child) {
141 // There's nothing to do if the child is already at the bottom.
142 if (children_.size() <= 1 || child == children_.front())
143 return;
144 child->Reorder(children_.front(), mojom::OrderDirection::BELOW);
145 }
146
147 void ServerWindow::StackChildAtTop(ServerWindow* child) {
148 // There's nothing to do if the child is already at the top.
149 if (children_.size() <= 1 || child == children_.back())
150 return;
151 child->Reorder(children_.back(), mojom::OrderDirection::ABOVE);
152 }
153
154 void ServerWindow::SetBounds(const gfx::Rect& bounds) {
155 if (bounds_ == bounds)
156 return;
157
158 // TODO(fsamuel): figure out how will this work with CompositorFrames.
159
160 const gfx::Rect old_bounds = bounds_;
161 bounds_ = bounds;
162 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
163 OnWindowBoundsChanged(this, old_bounds, bounds));
164 }
165
166 void ServerWindow::SetClientArea(
167 const gfx::Insets& insets,
168 const std::vector<gfx::Rect>& additional_client_areas) {
169 if (client_area_ == insets &&
170 additional_client_areas == additional_client_areas_) {
171 return;
172 }
173
174 additional_client_areas_ = additional_client_areas;
175 client_area_ = insets;
176 FOR_EACH_OBSERVER(
177 ServerWindowObserver, observers_,
178 OnWindowClientAreaChanged(this, insets, additional_client_areas));
179 }
180
181 void ServerWindow::SetHitTestMask(const gfx::Rect& mask) {
182 hit_test_mask_.reset(new gfx::Rect(mask));
183 }
184
185 void ServerWindow::ClearHitTestMask() {
186 hit_test_mask_.reset();
187 }
188
189 const ServerWindow* ServerWindow::GetRoot() const {
190 return delegate_->GetRootWindow(this);
191 }
192
193 std::vector<const ServerWindow*> ServerWindow::GetChildren() const {
194 std::vector<const ServerWindow*> children;
195 children.reserve(children_.size());
196 for (size_t i = 0; i < children_.size(); ++i)
197 children.push_back(children_[i]);
198 return children;
199 }
200
201 std::vector<ServerWindow*> ServerWindow::GetChildren() {
202 // TODO(sky): rename to children() and fix return type.
203 return children_;
204 }
205
206 ServerWindow* ServerWindow::GetChildWindow(const WindowId& window_id) {
207 if (id_ == window_id)
208 return this;
209
210 for (ServerWindow* child : children_) {
211 ServerWindow* window = child->GetChildWindow(window_id);
212 if (window)
213 return window;
214 }
215
216 return nullptr;
217 }
218
219 bool ServerWindow::AddTransientWindow(ServerWindow* child) {
220 // A system modal window cannot become a transient child.
221 if (child->is_modal() && !child->transient_parent())
222 return false;
223
224 if (child->transient_parent())
225 child->transient_parent()->RemoveTransientWindow(child);
226
227 DCHECK(std::find(transient_children_.begin(), transient_children_.end(),
228 child) == transient_children_.end());
229 transient_children_.push_back(child);
230 child->transient_parent_ = this;
231
232 // Restack |child| properly above its transient parent, if they share the same
233 // parent.
234 if (child->parent() == parent())
235 RestackTransientDescendants(this, &GetStackingTarget, &ReorderImpl);
236
237 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
238 OnTransientWindowAdded(this, child));
239 return true;
240 }
241
242 void ServerWindow::RemoveTransientWindow(ServerWindow* child) {
243 Windows::iterator i =
244 std::find(transient_children_.begin(), transient_children_.end(), child);
245 DCHECK(i != transient_children_.end());
246 transient_children_.erase(i);
247 DCHECK_EQ(this, child->transient_parent());
248 child->transient_parent_ = nullptr;
249
250 // If |child| and its former transient parent share the same parent, |child|
251 // should be restacked properly so it is not among transient children of its
252 // former parent, anymore.
253 if (parent() == child->parent())
254 RestackTransientDescendants(this, &GetStackingTarget, &ReorderImpl);
255
256 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
257 OnTransientWindowRemoved(this, child));
258 }
259
260 void ServerWindow::SetModal() {
261 is_modal_ = true;
262 }
263
264 bool ServerWindow::Contains(const ServerWindow* window) const {
265 for (const ServerWindow* parent = window; parent; parent = parent->parent_) {
266 if (parent == this)
267 return true;
268 }
269 return false;
270 }
271
272 void ServerWindow::SetVisible(bool value) {
273 if (visible_ == value)
274 return;
275
276 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
277 OnWillChangeWindowVisibility(this));
278 visible_ = value;
279 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
280 OnWindowVisibilityChanged(this));
281 }
282
283 void ServerWindow::SetOpacity(float value) {
284 if (value == opacity_)
285 return;
286 float old_opacity = opacity_;
287 opacity_ = value;
288 delegate_->OnScheduleWindowPaint(this);
289 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
290 OnWindowOpacityChanged(this, old_opacity, opacity_));
291 }
292
293 void ServerWindow::SetPredefinedCursor(mus::mojom::Cursor value) {
294 if (value == cursor_id_)
295 return;
296 cursor_id_ = value;
297 FOR_EACH_OBSERVER(
298 ServerWindowObserver, observers_,
299 OnWindowPredefinedCursorChanged(this, static_cast<int32_t>(value)));
300 }
301
302 void ServerWindow::SetNonClientCursor(mus::mojom::Cursor value) {
303 if (value == non_client_cursor_id_)
304 return;
305 non_client_cursor_id_ = value;
306 FOR_EACH_OBSERVER(
307 ServerWindowObserver, observers_,
308 OnWindowNonClientCursorChanged(this, static_cast<int32_t>(value)));
309 }
310
311 void ServerWindow::SetTransform(const gfx::Transform& transform) {
312 if (transform_ == transform)
313 return;
314
315 transform_ = transform;
316 delegate_->OnScheduleWindowPaint(this);
317 }
318
319 void ServerWindow::SetProperty(const std::string& name,
320 const std::vector<uint8_t>* value) {
321 auto it = properties_.find(name);
322 if (it != properties_.end()) {
323 if (value && it->second == *value)
324 return;
325 } else if (!value) {
326 // This property isn't set in |properties_| and |value| is nullptr, so
327 // there's
328 // no change.
329 return;
330 }
331
332 if (value) {
333 properties_[name] = *value;
334 } else if (it != properties_.end()) {
335 properties_.erase(it);
336 }
337
338 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
339 OnWindowSharedPropertyChanged(this, name, value));
340 }
341
342 std::string ServerWindow::GetName() const {
343 auto it = properties_.find(mojom::WindowManager::kName_Property);
344 if (it == properties_.end())
345 return std::string();
346 return std::string(it->second.begin(), it->second.end());
347 }
348
349 void ServerWindow::SetTextInputState(const ui::TextInputState& state) {
350 const bool changed = !(text_input_state_ == state);
351 if (changed) {
352 text_input_state_ = state;
353 // keyboard even if the state is not changed. So we have to notify
354 // |observers_|.
355 FOR_EACH_OBSERVER(ServerWindowObserver, observers_,
356 OnWindowTextInputStateChanged(this, state));
357 }
358 }
359
360 bool ServerWindow::IsDrawn() const {
361 const ServerWindow* root = delegate_->GetRootWindow(this);
362 if (!root || !root->visible())
363 return false;
364 const ServerWindow* window = this;
365 while (window && window != root && window->visible())
366 window = window->parent();
367 return root == window;
368 }
369
370 void ServerWindow::DestroySurfacesScheduledForDestruction() {
371 if (!surface_manager_)
372 return;
373 ServerWindowSurface* surface = surface_manager_->GetDefaultSurface();
374 if (surface)
375 surface->DestroySurfacesScheduledForDestruction();
376
377 surface = surface_manager_->GetUnderlaySurface();
378 if (surface)
379 surface->DestroySurfacesScheduledForDestruction();
380 }
381
382 ServerWindowSurfaceManager* ServerWindow::GetOrCreateSurfaceManager() {
383 if (!surface_manager_.get())
384 surface_manager_.reset(new ServerWindowSurfaceManager(this));
385 return surface_manager_.get();
386 }
387
388 void ServerWindow::SetUnderlayOffset(const gfx::Vector2d& offset) {
389 if (offset == underlay_offset_)
390 return;
391
392 underlay_offset_ = offset;
393 delegate_->OnScheduleWindowPaint(this);
394 }
395
396 #if !defined(NDEBUG)
397 std::string ServerWindow::GetDebugWindowHierarchy() const {
398 std::string result;
399 BuildDebugInfo(std::string(), &result);
400 return result;
401 }
402
403 void ServerWindow::BuildDebugInfo(const std::string& depth,
404 std::string* result) const {
405 std::string name = GetName();
406 *result += base::StringPrintf(
407 "%sid=%d,%d visible=%s bounds=%d,%d %dx%d %s\n", depth.c_str(),
408 static_cast<int>(id_.client_id), static_cast<int>(id_.window_id),
409 visible_ ? "true" : "false", bounds_.x(), bounds_.y(), bounds_.width(),
410 bounds_.height(), !name.empty() ? name.c_str() : "(no name)");
411 for (const ServerWindow* child : children_)
412 child->BuildDebugInfo(depth + " ", result);
413 }
414 #endif
415
416 void ServerWindow::RemoveImpl(ServerWindow* window) {
417 window->parent_ = nullptr;
418 children_.erase(std::find(children_.begin(), children_.end(), window));
419 }
420
421 void ServerWindow::OnStackingChanged() {
422 if (stacking_target_) {
423 Windows::const_iterator window_i = std::find(
424 parent()->children().begin(), parent()->children().end(), this);
425 DCHECK(window_i != parent()->children().end());
426 if (window_i != parent()->children().begin() &&
427 (*(window_i - 1) == stacking_target_)) {
428 return;
429 }
430 }
431 RestackTransientDescendants(this, &GetStackingTarget, &ReorderImpl);
432 }
433
434 // static
435 void ServerWindow::ReorderImpl(ServerWindow* window,
436 ServerWindow* relative,
437 mojom::OrderDirection direction) {
438 DCHECK(relative);
439 DCHECK_NE(window, relative);
440 DCHECK_EQ(window->parent(), relative->parent());
441
442 if (!AdjustStackingForTransientWindows(&window, &relative, &direction,
443 window->stacking_target_))
444 return;
445
446 window->parent_->children_.erase(std::find(window->parent_->children_.begin(),
447 window->parent_->children_.end(),
448 window));
449 Windows::iterator i = std::find(window->parent_->children_.begin(),
450 window->parent_->children_.end(), relative);
451 if (direction == mojom::OrderDirection::ABOVE) {
452 DCHECK(i != window->parent_->children_.end());
453 window->parent_->children_.insert(++i, window);
454 } else if (direction == mojom::OrderDirection::BELOW) {
455 DCHECK(i != window->parent_->children_.end());
456 window->parent_->children_.insert(i, window);
457 }
458 FOR_EACH_OBSERVER(ServerWindowObserver, window->observers_,
459 OnWindowReordered(window, relative, direction));
460 window->OnStackingChanged();
461 }
462
463 // static
464 ServerWindow** ServerWindow::GetStackingTarget(ServerWindow* window) {
465 return &window->stacking_target_;
466 }
467
468 } // namespace ws
469
470 } // namespace mus
OLDNEW
« no previous file with comments | « components/mus/ws/server_window.h ('k') | components/mus/ws/server_window_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698