OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef COMPONENTS_MUS_WS_WINDOW_TREE_H_ | |
6 #define COMPONENTS_MUS_WS_WINDOW_TREE_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include <map> | |
11 #include <memory> | |
12 #include <queue> | |
13 #include <set> | |
14 #include <string> | |
15 #include <vector> | |
16 | |
17 #include "base/callback.h" | |
18 #include "base/containers/hash_tables.h" | |
19 #include "base/macros.h" | |
20 #include "cc/ipc/surface_id.mojom.h" | |
21 #include "components/mus/public/interfaces/window_tree.mojom.h" | |
22 #include "components/mus/ws/access_policy_delegate.h" | |
23 #include "components/mus/ws/ids.h" | |
24 #include "components/mus/ws/user_id.h" | |
25 #include "components/mus/ws/window_tree_binding.h" | |
26 #include "mojo/public/cpp/bindings/associated_binding.h" | |
27 | |
28 namespace gfx { | |
29 class Insets; | |
30 class Rect; | |
31 } | |
32 | |
33 namespace ui { | |
34 class Event; | |
35 } | |
36 | |
37 namespace mus { | |
38 namespace ws { | |
39 | |
40 class AccessPolicy; | |
41 class DisplayManager; | |
42 class Display; | |
43 class EventMatcher; | |
44 class ServerWindow; | |
45 class TargetedEvent; | |
46 class WindowManagerDisplayRoot; | |
47 class WindowManagerState; | |
48 class WindowServer; | |
49 class WindowTreeTest; | |
50 | |
51 namespace test { | |
52 class WindowTreeTestApi; | |
53 } | |
54 | |
55 // WindowTree represents a view onto portions of the window tree. The parts of | |
56 // the tree exposed to the client start at the root windows. A WindowTree may | |
57 // have any number of roots (including none). A WindowTree may not have | |
58 // visibility of all the descendants of its roots. | |
59 // | |
60 // WindowTree notifies its client as changes happen to windows exposed to the | |
61 // the client. | |
62 // | |
63 // See ids.h for details on how WindowTree handles identity of windows. | |
64 class WindowTree : public mojom::WindowTree, | |
65 public AccessPolicyDelegate, | |
66 public mojom::WindowManagerClient { | |
67 public: | |
68 WindowTree(WindowServer* window_server, | |
69 const UserId& user_id, | |
70 ServerWindow* root, | |
71 std::unique_ptr<AccessPolicy> access_policy); | |
72 ~WindowTree() override; | |
73 | |
74 void Init(std::unique_ptr<WindowTreeBinding> binding, | |
75 mojom::WindowTreePtr tree); | |
76 | |
77 // Called if this WindowTree hosts a WindowManager. | |
78 void ConfigureWindowManager(); | |
79 | |
80 ClientSpecificId id() const { return id_; } | |
81 | |
82 void set_embedder_intercepts_events() { embedder_intercepts_events_ = true; } | |
83 bool embedder_intercepts_events() const { | |
84 return embedder_intercepts_events_; | |
85 } | |
86 | |
87 const UserId& user_id() const { return user_id_; } | |
88 | |
89 mojom::WindowTreeClient* client() { return binding_->client(); } | |
90 | |
91 // Returns the Window with the specified id. | |
92 ServerWindow* GetWindow(const WindowId& id) { | |
93 return const_cast<ServerWindow*>( | |
94 const_cast<const WindowTree*>(this)->GetWindow(id)); | |
95 } | |
96 const ServerWindow* GetWindow(const WindowId& id) const; | |
97 | |
98 // Returns the Window with the specified client id *only* if known to this | |
99 // client, returns null if not known. | |
100 ServerWindow* GetWindowByClientId(const ClientWindowId& id) { | |
101 return const_cast<ServerWindow*>( | |
102 const_cast<const WindowTree*>(this)->GetWindowByClientId(id)); | |
103 } | |
104 const ServerWindow* GetWindowByClientId(const ClientWindowId& id) const; | |
105 | |
106 bool IsWindowKnown(const ServerWindow* window) const { | |
107 return IsWindowKnown(window, nullptr); | |
108 } | |
109 // Returns whether |window| is known to this tree. If |window| is known and | |
110 // |client_window_id| is non-null |client_window_id| is set to the | |
111 // ClientWindowId of the window. | |
112 bool IsWindowKnown(const ServerWindow* window, | |
113 ClientWindowId* client_window_id) const; | |
114 | |
115 // Returns true if |window| is one of this trees roots. | |
116 bool HasRoot(const ServerWindow* window) const; | |
117 | |
118 std::set<const ServerWindow*> roots() { return roots_; } | |
119 | |
120 void set_name(const std::string& name) { name_ = name; } | |
121 const std::string& name() const { return name_; } | |
122 | |
123 bool janky() const { return janky_; } | |
124 | |
125 const Display* GetDisplay(const ServerWindow* window) const; | |
126 Display* GetDisplay(const ServerWindow* window) { | |
127 return const_cast<Display*>( | |
128 const_cast<const WindowTree*>(this)->GetDisplay(window)); | |
129 } | |
130 | |
131 const WindowManagerDisplayRoot* GetWindowManagerDisplayRoot( | |
132 const ServerWindow* window) const; | |
133 WindowManagerDisplayRoot* GetWindowManagerDisplayRoot( | |
134 const ServerWindow* window) { | |
135 return const_cast<WindowManagerDisplayRoot*>( | |
136 const_cast<const WindowTree*>(this)->GetWindowManagerDisplayRoot( | |
137 window)); | |
138 } | |
139 WindowManagerState* window_manager_state() { | |
140 return window_manager_state_.get(); | |
141 } | |
142 | |
143 DisplayManager* display_manager(); | |
144 const DisplayManager* display_manager() const; | |
145 | |
146 WindowServer* window_server() { return window_server_; } | |
147 const WindowServer* window_server() const { return window_server_; } | |
148 | |
149 // Adds a new root to this tree. This is only valid for window managers. | |
150 void AddRootForWindowManager(const ServerWindow* root); | |
151 | |
152 // Invoked when a tree is about to be destroyed. | |
153 void OnWindowDestroyingTreeImpl(WindowTree* tree); | |
154 | |
155 // These functions are synchronous variants of those defined in the mojom. The | |
156 // WindowTree implementations all call into these. See the mojom for details. | |
157 bool SetCapture(const ClientWindowId& client_window_id); | |
158 bool NewWindow(const ClientWindowId& client_window_id, | |
159 const std::map<std::string, std::vector<uint8_t>>& properties); | |
160 bool AddWindow(const ClientWindowId& parent_id, | |
161 const ClientWindowId& child_id); | |
162 bool AddTransientWindow(const ClientWindowId& window_id, | |
163 const ClientWindowId& transient_window_id); | |
164 bool SetModal(const ClientWindowId& window_id); | |
165 std::vector<const ServerWindow*> GetWindowTree( | |
166 const ClientWindowId& window_id) const; | |
167 bool SetWindowVisibility(const ClientWindowId& window_id, bool visible); | |
168 bool SetWindowOpacity(const ClientWindowId& window_id, float opacity); | |
169 bool SetFocus(const ClientWindowId& window_id); | |
170 bool Embed(const ClientWindowId& window_id, | |
171 mojom::WindowTreeClientPtr client, | |
172 uint32_t flags); | |
173 void DispatchInputEvent(ServerWindow* target, const ui::Event& event); | |
174 | |
175 bool IsWaitingForNewTopLevelWindow(uint32_t wm_change_id); | |
176 void OnWindowManagerCreatedTopLevelWindow(uint32_t wm_change_id, | |
177 uint32_t client_change_id, | |
178 const ServerWindow* window); | |
179 void AddActivationParent(const ClientWindowId& window_id); | |
180 | |
181 // Calls through to the client. | |
182 void OnChangeCompleted(uint32_t change_id, bool success); | |
183 void OnAccelerator(uint32_t accelerator_id, const ui::Event& event); | |
184 | |
185 // Called when |tree|'s jankiness changes (see janky_ for definition). | |
186 // Notifies the window manager client so it can update UI for the affected | |
187 // window(s). | |
188 void ClientJankinessChanged(WindowTree* tree); | |
189 | |
190 // The following methods are invoked after the corresponding change has been | |
191 // processed. They do the appropriate bookkeeping and update the client as | |
192 // necessary. | |
193 void ProcessWindowBoundsChanged(const ServerWindow* window, | |
194 const gfx::Rect& old_bounds, | |
195 const gfx::Rect& new_bounds, | |
196 bool originated_change); | |
197 void ProcessClientAreaChanged( | |
198 const ServerWindow* window, | |
199 const gfx::Insets& new_client_area, | |
200 const std::vector<gfx::Rect>& new_additional_client_areas, | |
201 bool originated_change); | |
202 void ProcessWillChangeWindowHierarchy(const ServerWindow* window, | |
203 const ServerWindow* new_parent, | |
204 const ServerWindow* old_parent, | |
205 bool originated_change); | |
206 void ProcessWindowPropertyChanged(const ServerWindow* window, | |
207 const std::string& name, | |
208 const std::vector<uint8_t>* new_data, | |
209 bool originated_change); | |
210 void ProcessWindowHierarchyChanged(const ServerWindow* window, | |
211 const ServerWindow* new_parent, | |
212 const ServerWindow* old_parent, | |
213 bool originated_change); | |
214 void ProcessWindowReorder(const ServerWindow* window, | |
215 const ServerWindow* relative_window, | |
216 mojom::OrderDirection direction, | |
217 bool originated_change); | |
218 void ProcessWindowDeleted(const ServerWindow* window, bool originated_change); | |
219 void ProcessWillChangeWindowVisibility(const ServerWindow* window, | |
220 bool originated_change); | |
221 void ProcessWindowOpacityChanged(const ServerWindow* window, | |
222 float old_opacity, | |
223 float new_opacity, | |
224 bool originated_change); | |
225 void ProcessCursorChanged(const ServerWindow* window, | |
226 int32_t cursor_id, | |
227 bool originated_change); | |
228 void ProcessFocusChanged(const ServerWindow* old_focused_window, | |
229 const ServerWindow* new_focused_window); | |
230 void ProcessLostCapture(const ServerWindow* old_lost_capture, | |
231 bool originated_change); | |
232 void ProcessTransientWindowAdded(const ServerWindow* window, | |
233 const ServerWindow* transient_window, | |
234 bool originated_change); | |
235 void ProcessTransientWindowRemoved(const ServerWindow* window, | |
236 const ServerWindow* transient_window, | |
237 bool originated_change); | |
238 | |
239 // Sends this event to the client if it matches an active event observer. | |
240 void SendToEventObserver(const ui::Event& event); | |
241 | |
242 private: | |
243 friend class test::WindowTreeTestApi; | |
244 | |
245 struct WaitingForTopLevelWindowInfo { | |
246 WaitingForTopLevelWindowInfo(const ClientWindowId& client_window_id, | |
247 uint32_t wm_change_id) | |
248 : client_window_id(client_window_id), wm_change_id(wm_change_id) {} | |
249 ~WaitingForTopLevelWindowInfo() {} | |
250 | |
251 // Id supplied from the client. | |
252 ClientWindowId client_window_id; | |
253 | |
254 // Change id we created for the window manager. | |
255 uint32_t wm_change_id; | |
256 }; | |
257 | |
258 enum class RemoveRootReason { | |
259 // The window is being removed. | |
260 DELETED, | |
261 | |
262 // Another client is being embedded in the window. | |
263 EMBED, | |
264 }; | |
265 | |
266 bool ShouldRouteToWindowManager(const ServerWindow* window) const; | |
267 | |
268 ClientWindowId ClientWindowIdForWindow(const ServerWindow* window) const; | |
269 | |
270 // Returns true if |id| is a valid WindowId for a new window. | |
271 bool IsValidIdForNewWindow(const ClientWindowId& id) const; | |
272 | |
273 WindowId GenerateNewWindowId(); | |
274 | |
275 // These functions return true if the corresponding mojom function is allowed | |
276 // for this tree. | |
277 bool CanReorderWindow(const ServerWindow* window, | |
278 const ServerWindow* relative_window, | |
279 mojom::OrderDirection direction) const; | |
280 | |
281 // Deletes a window owned by this tree. Returns true on success. |source| is | |
282 // the tree that originated the change. | |
283 bool DeleteWindowImpl(WindowTree* source, ServerWindow* window); | |
284 | |
285 // If |window| is known does nothing. Otherwise adds |window| to |windows|, | |
286 // marks |window| as known and recurses. | |
287 void GetUnknownWindowsFrom(const ServerWindow* window, | |
288 std::vector<const ServerWindow*>* windows); | |
289 | |
290 // Removes |window| from the appropriate maps. If |window| is known to this | |
291 // client true is returned. | |
292 bool RemoveFromMaps(const ServerWindow* window); | |
293 | |
294 // Removes |window| and all its descendants from the necessary maps. This | |
295 // does not recurse through windows that were created by this tree. All | |
296 // windows owned by this tree are added to |local_windows|. | |
297 void RemoveFromKnown(const ServerWindow* window, | |
298 std::vector<ServerWindow*>* local_windows); | |
299 | |
300 // Removes a root from set of roots of this tree. This does not remove | |
301 // the window from the window tree, only from the set of roots. | |
302 void RemoveRoot(const ServerWindow* window, RemoveRootReason reason); | |
303 | |
304 // Converts Window(s) to WindowData(s) for transport. This assumes all the | |
305 // windows are valid for the client. The parent of windows the client is not | |
306 // allowed to see are set to NULL (in the returned WindowData(s)). | |
307 mojo::Array<mojom::WindowDataPtr> WindowsToWindowDatas( | |
308 const std::vector<const ServerWindow*>& windows); | |
309 mojom::WindowDataPtr WindowToWindowData(const ServerWindow* window); | |
310 | |
311 // Implementation of GetWindowTree(). Adds |window| to |windows| and recurses | |
312 // if CanDescendIntoWindowForWindowTree() returns true. | |
313 void GetWindowTreeImpl(const ServerWindow* window, | |
314 std::vector<const ServerWindow*>* windows) const; | |
315 | |
316 // Notify the client if the drawn state of any of the roots changes. | |
317 // |window| is the window that is changing to the drawn state | |
318 // |new_drawn_value|. | |
319 void NotifyDrawnStateChanged(const ServerWindow* window, | |
320 bool new_drawn_value); | |
321 | |
322 // Deletes all Windows we own. | |
323 void DestroyWindows(); | |
324 | |
325 bool CanEmbed(const ClientWindowId& window_id) const; | |
326 void PrepareForEmbed(ServerWindow* window); | |
327 void RemoveChildrenAsPartOfEmbed(ServerWindow* window); | |
328 | |
329 void DispatchInputEventImpl(ServerWindow* target, const ui::Event& event); | |
330 | |
331 // Calls OnChangeCompleted() on the client. | |
332 void NotifyChangeCompleted(uint32_t change_id, | |
333 mojom::WindowManagerErrorCode error_code); | |
334 | |
335 // WindowTree: | |
336 void NewWindow(uint32_t change_id, | |
337 Id transport_window_id, | |
338 mojo::Map<mojo::String, mojo::Array<uint8_t>> | |
339 transport_properties) override; | |
340 void NewTopLevelWindow(uint32_t change_id, | |
341 Id transport_window_id, | |
342 mojo::Map<mojo::String, mojo::Array<uint8_t>> | |
343 transport_properties) override; | |
344 void DeleteWindow(uint32_t change_id, Id transport_window_id) override; | |
345 void AddWindow(uint32_t change_id, Id parent_id, Id child_id) override; | |
346 void RemoveWindowFromParent(uint32_t change_id, Id window_id) override; | |
347 void AddTransientWindow(uint32_t change_id, | |
348 Id window, | |
349 Id transient_window) override; | |
350 void RemoveTransientWindowFromParent(uint32_t change_id, | |
351 Id transient_window_id) override; | |
352 void SetModal(uint32_t change_id, Id window_id) override; | |
353 void ReorderWindow(uint32_t change_Id, | |
354 Id window_id, | |
355 Id relative_window_id, | |
356 mojom::OrderDirection direction) override; | |
357 void GetWindowTree( | |
358 Id window_id, | |
359 const base::Callback<void(mojo::Array<mojom::WindowDataPtr>)>& callback) | |
360 override; | |
361 void SetCapture(uint32_t change_id, Id window_id) override; | |
362 void ReleaseCapture(uint32_t change_id, Id window_id) override; | |
363 void SetEventObserver(mojom::EventMatcherPtr matcher, | |
364 uint32_t observer_id) override; | |
365 void SetWindowBounds(uint32_t change_id, | |
366 Id window_id, | |
367 const gfx::Rect& bounds) override; | |
368 void SetWindowVisibility(uint32_t change_id, | |
369 Id window_id, | |
370 bool visible) override; | |
371 void SetWindowProperty(uint32_t change_id, | |
372 Id transport_window_id, | |
373 const mojo::String& name, | |
374 mojo::Array<uint8_t> value) override; | |
375 void SetWindowOpacity(uint32_t change_id, | |
376 Id window_id, | |
377 float opacity) override; | |
378 void AttachSurface(Id transport_window_id, | |
379 mojom::SurfaceType type, | |
380 mojo::InterfaceRequest<mojom::Surface> surface, | |
381 mojom::SurfaceClientPtr client) override; | |
382 void Embed(Id transport_window_id, | |
383 mojom::WindowTreeClientPtr client, | |
384 uint32_t flags, | |
385 const EmbedCallback& callback) override; | |
386 void SetFocus(uint32_t change_id, Id transport_window_id) override; | |
387 void SetCanFocus(Id transport_window_id, bool can_focus) override; | |
388 void SetPredefinedCursor(uint32_t change_id, | |
389 Id transport_window_id, | |
390 mus::mojom::Cursor cursor_id) override; | |
391 void SetWindowTextInputState(Id transport_window_id, | |
392 mojo::TextInputStatePtr state) override; | |
393 void SetImeVisibility(Id transport_window_id, | |
394 bool visible, | |
395 mojo::TextInputStatePtr state) override; | |
396 void OnWindowInputEventAck(uint32_t event_id, | |
397 mojom::EventResult result) override; | |
398 void SetClientArea( | |
399 Id transport_window_id, | |
400 const gfx::Insets& insets, | |
401 mojo::Array<gfx::Rect> transport_additional_client_areas) override; | |
402 void SetHitTestMask(Id transport_window_id, const gfx::Rect& mask) override; | |
403 void GetWindowManagerClient( | |
404 mojo::AssociatedInterfaceRequest<mojom::WindowManagerClient> internal) | |
405 override; | |
406 void GetCursorLocationMemory(const GetCursorLocationMemoryCallback& callback) | |
407 override; | |
408 | |
409 // mojom::WindowManagerClient: | |
410 void AddAccelerator(uint32_t id, | |
411 mojom::EventMatcherPtr event_matcher, | |
412 const AddAcceleratorCallback& callback) override; | |
413 void RemoveAccelerator(uint32_t id) override; | |
414 void AddActivationParent(Id transport_window_id) override; | |
415 void RemoveActivationParent(Id transport_window_id) override; | |
416 void ActivateNextWindow() override; | |
417 void SetUnderlaySurfaceOffsetAndExtendedHitArea( | |
418 Id window_id, | |
419 int32_t x_offset, | |
420 int32_t y_offset, | |
421 const gfx::Insets& hit_area) override; | |
422 void WmResponse(uint32_t change_id, bool response) override; | |
423 void WmRequestClose(Id transport_window_id) override; | |
424 void WmSetFrameDecorationValues( | |
425 mojom::FrameDecorationValuesPtr values) override; | |
426 void WmSetNonClientCursor(uint32_t window_id, | |
427 mojom::Cursor cursor_id) override; | |
428 void OnWmCreatedTopLevelWindow(uint32_t change_id, | |
429 Id transport_window_id) override; | |
430 | |
431 // AccessPolicyDelegate: | |
432 bool HasRootForAccessPolicy(const ServerWindow* window) const override; | |
433 bool IsWindowKnownForAccessPolicy(const ServerWindow* window) const override; | |
434 bool IsWindowRootOfAnotherTreeForAccessPolicy( | |
435 const ServerWindow* window) const override; | |
436 | |
437 WindowServer* window_server_; | |
438 | |
439 UserId user_id_; | |
440 | |
441 // Id of this tree as assigned by WindowServer. | |
442 const ClientSpecificId id_; | |
443 std::string name_; | |
444 | |
445 ClientSpecificId next_window_id_; | |
446 | |
447 std::unique_ptr<WindowTreeBinding> binding_; | |
448 | |
449 std::unique_ptr<mus::ws::AccessPolicy> access_policy_; | |
450 | |
451 // The roots, or embed points, of this tree. A WindowTree may have any | |
452 // number of roots, including 0. | |
453 std::set<const ServerWindow*> roots_; | |
454 | |
455 // The windows created by this tree. This tree owns these objects. | |
456 base::hash_map<WindowId, ServerWindow*> created_window_map_; | |
457 | |
458 // The client is allowed to assign ids. These two maps providing the mapping | |
459 // from the ids native to the server (WindowId) to those understood by the | |
460 // client (ClientWindowId). | |
461 base::hash_map<ClientWindowId, WindowId> client_id_to_window_id_map_; | |
462 base::hash_map<WindowId, ClientWindowId> window_id_to_client_id_map_; | |
463 | |
464 uint32_t event_ack_id_; | |
465 | |
466 // A client is considered janky if it hasn't ACK'ed input events within a | |
467 // reasonable timeframe. | |
468 bool janky_ = false; | |
469 | |
470 // Set when the client is using SetEventObserver() to observe events, | |
471 // otherwise null. | |
472 std::unique_ptr<EventMatcher> event_observer_matcher_; | |
473 | |
474 // The ID supplied by the client for the current event observer. | |
475 uint32_t event_observer_id_ = 0; | |
476 | |
477 // WindowManager the current event came from. | |
478 WindowManagerState* event_source_wms_ = nullptr; | |
479 | |
480 std::queue<std::unique_ptr<TargetedEvent>> event_queue_; | |
481 | |
482 std::unique_ptr<mojo::AssociatedBinding<mojom::WindowManagerClient>> | |
483 window_manager_internal_client_binding_; | |
484 mojom::WindowManager* window_manager_internal_; | |
485 std::unique_ptr<WindowManagerState> window_manager_state_; | |
486 | |
487 std::unique_ptr<WaitingForTopLevelWindowInfo> | |
488 waiting_for_top_level_window_info_; | |
489 bool embedder_intercepts_events_ = false; | |
490 | |
491 DISALLOW_COPY_AND_ASSIGN(WindowTree); | |
492 }; | |
493 | |
494 } // namespace ws | |
495 } // namespace mus | |
496 | |
497 #endif // COMPONENTS_MUS_WS_WINDOW_TREE_H_ | |
OLD | NEW |