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 SERVICES_UI_PUBLIC_CPP_WINDOW_TREE_CLIENT_H_ | |
6 #define SERVICES_UI_PUBLIC_CPP_WINDOW_TREE_CLIENT_H_ | |
7 | |
8 #include <stdint.h> | |
9 | |
10 #include <map> | |
11 #include <memory> | |
12 #include <set> | |
13 #include <string> | |
14 #include <vector> | |
15 | |
16 #include "base/atomicops.h" | |
17 #include "base/macros.h" | |
18 #include "base/memory/weak_ptr.h" | |
19 #include "base/observer_list.h" | |
20 #include "mojo/public/cpp/bindings/associated_binding.h" | |
21 #include "mojo/public/cpp/bindings/strong_binding.h" | |
22 #include "services/ui/common/types.h" | |
23 #include "services/ui/public/cpp/window.h" | |
24 #include "services/ui/public/cpp/window_manager_delegate.h" | |
25 #include "services/ui/public/interfaces/window_tree.mojom.h" | |
26 | |
27 namespace display { | |
28 class Display; | |
29 } | |
30 | |
31 namespace gfx { | |
32 class Insets; | |
33 } | |
34 | |
35 namespace service_manager { | |
36 class Connector; | |
37 } | |
38 | |
39 namespace ui { | |
40 class InFlightChange; | |
41 class WindowTreeClientDelegate; | |
42 class WindowTreeClientPrivate; | |
43 class WindowTreeClientObserver; | |
44 enum class ChangeType; | |
45 | |
46 // Manages the connection with mus. | |
47 // | |
48 // WindowTreeClient is owned by the creator. Generally when the delegate gets | |
49 // one of OnEmbedRootDestroyed() or OnLostConnection() it should delete the | |
50 // WindowTreeClient. | |
51 // | |
52 // When WindowTreeClient is deleted all windows are deleted (and observers | |
53 // notified). | |
54 class WindowTreeClient : public mojom::WindowTreeClient, | |
55 public mojom::WindowManager, | |
56 public WindowManagerClient { | |
57 public: | |
58 explicit WindowTreeClient( | |
59 WindowTreeClientDelegate* delegate, | |
60 WindowManagerDelegate* window_manager_delegate = nullptr, | |
61 mojom::WindowTreeClientRequest request = nullptr); | |
62 ~WindowTreeClient() override; | |
63 | |
64 // Establishes the connection by way of the WindowTreeFactory. | |
65 void ConnectViaWindowTreeFactory(service_manager::Connector* connector); | |
66 | |
67 // Establishes the connection by way of WindowManagerWindowTreeFactory. | |
68 void ConnectAsWindowManager(service_manager::Connector* connector); | |
69 | |
70 // Wait for OnEmbed(), returning when done. | |
71 void WaitForEmbed(); | |
72 | |
73 bool connected() const { return tree_ != nullptr; } | |
74 ClientSpecificId client_id() const { return client_id_; } | |
75 | |
76 // API exposed to the window implementations that pushes local changes to the | |
77 // service. | |
78 void DestroyWindow(Window* window); | |
79 | |
80 // These methods take TransportIds. For windows owned by the current client, | |
81 // the client id high word can be zero. In all cases, the TransportId 0x1 | |
82 // refers to the root window. | |
83 void AddChild(Window* parent, Id child_id); | |
84 void RemoveChild(Window* parent, Id child_id); | |
85 | |
86 void AddTransientWindow(Window* window, Id transient_window_id); | |
87 void RemoveTransientWindowFromParent(Window* window); | |
88 | |
89 void SetModal(Window* window); | |
90 | |
91 void Reorder(Window* window, | |
92 Id relative_window_id, | |
93 mojom::OrderDirection direction); | |
94 | |
95 // Returns true if the specified window was created by this client. | |
96 bool WasCreatedByThisClient(const Window* window) const; | |
97 | |
98 void SetBounds(Window* window, | |
99 const gfx::Rect& old_bounds, | |
100 const gfx::Rect& bounds); | |
101 void SetCapture(Window* window); | |
102 void ReleaseCapture(Window* window); | |
103 void SetClientArea(Id window_id, | |
104 const gfx::Insets& client_area, | |
105 const std::vector<gfx::Rect>& additional_client_areas); | |
106 void SetHitTestMask(Id window_id, const gfx::Rect& mask); | |
107 void ClearHitTestMask(Id window_id); | |
108 void SetFocus(Window* window); | |
109 void SetCanFocus(Id window_id, bool can_focus); | |
110 void SetCanAcceptDrops(Id window_id, bool can_accept_drops); | |
111 void SetCanAcceptEvents(Id window_id, bool can_accept_events); | |
112 void SetPredefinedCursor(Id window_id, ui::mojom::Cursor cursor_id); | |
113 void SetVisible(Window* window, bool visible); | |
114 void SetOpacity(Window* window, float opacity); | |
115 void SetProperty(Window* window, | |
116 const std::string& name, | |
117 const base::Optional<std::vector<uint8_t>>& data); | |
118 void SetWindowTextInputState(Id window_id, mojo::TextInputStatePtr state); | |
119 void SetImeVisibility(Id window_id, | |
120 bool visible, | |
121 mojo::TextInputStatePtr state); | |
122 | |
123 void Embed(Id window_id, | |
124 mojom::WindowTreeClientPtr client, | |
125 uint32_t flags, | |
126 const mojom::WindowTree::EmbedCallback& callback); | |
127 | |
128 void RequestClose(Window* window); | |
129 | |
130 void AttachCompositorFrameSink( | |
131 Id window_id, | |
132 cc::mojom::MojoCompositorFrameSinkRequest compositor_frame_sink, | |
133 cc::mojom::MojoCompositorFrameSinkClientPtr client); | |
134 | |
135 // Sets the input capture to |window| without notifying the server. | |
136 void LocalSetCapture(Window* window); | |
137 // Sets focus to |window| without notifying the server. | |
138 void LocalSetFocus(Window* window); | |
139 | |
140 // Start/stop tracking windows. While tracked, they can be retrieved via | |
141 // WindowTreeClient::GetWindowById. | |
142 void AddWindow(Window* window); | |
143 | |
144 bool IsRoot(Window* window) const { return roots_.count(window) > 0; } | |
145 | |
146 void OnWindowDestroying(Window* window); | |
147 | |
148 // Called after the window's observers have been notified of destruction (as | |
149 // the last step of ~Window). | |
150 void OnWindowDestroyed(Window* window); | |
151 | |
152 Window* GetWindowByServerId(Id id); | |
153 | |
154 // Returns the root of this connection. | |
155 const std::set<Window*>& GetRoots(); | |
156 | |
157 // Returns the Window with input capture; null if no window has requested | |
158 // input capture, or if another app has capture. | |
159 Window* GetCaptureWindow(); | |
160 | |
161 // Returns the focused window; null if focus is not yet known or another app | |
162 // is focused. | |
163 Window* GetFocusedWindow(); | |
164 | |
165 // Sets focus to null. This does nothing if focus is currently null. | |
166 void ClearFocus(); | |
167 | |
168 // Returns the current location of the mouse on screen. Note: this method may | |
169 // race the asynchronous initialization; but in that case we return (0, 0). | |
170 gfx::Point GetCursorScreenPoint(); | |
171 | |
172 // See description in window_tree.mojom. When an existing pointer watcher is | |
173 // updated or cleared then any future events from the server for that watcher | |
174 // will be ignored. | |
175 void StartPointerWatcher(bool want_moves); | |
176 void StopPointerWatcher(); | |
177 | |
178 void PerformDragDrop( | |
179 Window* window, | |
180 const std::map<std::string, std::vector<uint8_t>>& drag_data, | |
181 int drag_operation, | |
182 const gfx::Point& cursor_location, | |
183 const SkBitmap& bitmap, | |
184 const base::Callback<void(bool, uint32_t)>& callback); | |
185 | |
186 // Cancels a in progress drag drop. (If no drag is in progress, does | |
187 // nothing.) | |
188 void CancelDragDrop(Window* window); | |
189 | |
190 // Performs a window move. |callback| will be asynchronously called with the | |
191 // whether the move loop completed successfully. | |
192 void PerformWindowMove(Window* window, | |
193 ui::mojom::MoveLoopSource source, | |
194 const gfx::Point& cursor_location, | |
195 const base::Callback<void(bool)>& callback); | |
196 | |
197 // Cancels a in progress window move. (If no window is currently being moved, | |
198 // does nothing.) | |
199 void CancelWindowMove(Window* window); | |
200 | |
201 // Creates and returns a new Window (which is owned by the window server). | |
202 // Windows are initially hidden, use SetVisible(true) to show. | |
203 Window* NewWindow() { return NewWindow(nullptr); } | |
204 Window* NewWindow( | |
205 const std::map<std::string, std::vector<uint8_t>>* properties); | |
206 Window* NewTopLevelWindow( | |
207 const std::map<std::string, std::vector<uint8_t>>* properties); | |
208 | |
209 void AddObserver(WindowTreeClientObserver* observer); | |
210 void RemoveObserver(WindowTreeClientObserver* observer); | |
211 | |
212 #if !defined(NDEBUG) | |
213 std::string GetDebugWindowHierarchy() const; | |
214 void BuildDebugInfo(const std::string& depth, | |
215 Window* window, | |
216 std::string* result) const; | |
217 #endif | |
218 | |
219 private: | |
220 friend class WindowTreeClientPrivate; | |
221 | |
222 struct CurrentDragState; | |
223 | |
224 enum class NewWindowType { | |
225 CHILD, | |
226 TOP_LEVEL, | |
227 }; | |
228 | |
229 using IdToWindowMap = std::map<Id, Window*>; | |
230 | |
231 // TODO(sky): this assumes change_ids never wrap, which is a bad assumption. | |
232 using InFlightMap = std::map<uint32_t, std::unique_ptr<InFlightChange>>; | |
233 | |
234 // Returns the oldest InFlightChange that matches |change|. | |
235 InFlightChange* GetOldestInFlightChangeMatching(const InFlightChange& change); | |
236 | |
237 // See InFlightChange for details on how InFlightChanges are used. | |
238 uint32_t ScheduleInFlightChange(std::unique_ptr<InFlightChange> change); | |
239 | |
240 // Returns true if there is an InFlightChange that matches |change|. If there | |
241 // is an existing change SetRevertValueFrom() is invoked on it. Returns false | |
242 // if there is no InFlightChange matching |change|. | |
243 // See InFlightChange for details on how InFlightChanges are used. | |
244 bool ApplyServerChangeToExistingInFlightChange(const InFlightChange& change); | |
245 | |
246 static Id server_id(const Window* window) { return window->server_id(); } | |
247 | |
248 void BuildWindowTree(const std::vector<mojom::WindowDataPtr>& windows, | |
249 Window* initial_parent); | |
250 | |
251 Window* NewWindowImpl(NewWindowType type, | |
252 const Window::SharedProperties* properties); | |
253 | |
254 // Sets the mojom::WindowTree implementation. | |
255 void SetWindowTree(mojom::WindowTreePtr window_tree_ptr); | |
256 | |
257 // Called when the mojom::WindowTree connection is lost, deletes this. | |
258 void OnConnectionLost(); | |
259 | |
260 // OnEmbed() calls into this. Exposed as a separate function for testing. | |
261 void OnEmbedImpl(mojom::WindowTree* window_tree, | |
262 ClientSpecificId client_id, | |
263 mojom::WindowDataPtr root_data, | |
264 int64_t display_id, | |
265 Id focused_window_id, | |
266 bool drawn); | |
267 | |
268 // Called by WmNewDisplayAdded(). | |
269 void WmNewDisplayAddedImpl(const display::Display& display, | |
270 mojom::WindowDataPtr root_data, | |
271 bool parent_drawn); | |
272 | |
273 void OnReceivedCursorLocationMemory(mojo::ScopedSharedBufferHandle handle); | |
274 | |
275 // Callback passed from WmPerformMoveLoop(). | |
276 void OnWmMoveLoopCompleted(uint32_t change_id, bool completed); | |
277 | |
278 // Overridden from WindowTreeClient: | |
279 void OnEmbed(ClientSpecificId client_id, | |
280 mojom::WindowDataPtr root, | |
281 mojom::WindowTreePtr tree, | |
282 int64_t display_id, | |
283 Id focused_window_id, | |
284 bool drawn) override; | |
285 void OnEmbeddedAppDisconnected(Id window_id) override; | |
286 void OnUnembed(Id window_id) override; | |
287 void OnCaptureChanged(Id new_capture_window_id, | |
288 Id old_capture_window_id) override; | |
289 void OnTopLevelCreated(uint32_t change_id, | |
290 mojom::WindowDataPtr data, | |
291 int64_t display_id, | |
292 bool drawn) override; | |
293 void OnWindowBoundsChanged(Id window_id, | |
294 const gfx::Rect& old_bounds, | |
295 const gfx::Rect& new_bounds) override; | |
296 void OnClientAreaChanged( | |
297 uint32_t window_id, | |
298 const gfx::Insets& new_client_area, | |
299 const std::vector<gfx::Rect>& new_additional_client_areas) override; | |
300 void OnTransientWindowAdded(uint32_t window_id, | |
301 uint32_t transient_window_id) override; | |
302 void OnTransientWindowRemoved(uint32_t window_id, | |
303 uint32_t transient_window_id) override; | |
304 void OnWindowHierarchyChanged( | |
305 Id window_id, | |
306 Id old_parent_id, | |
307 Id new_parent_id, | |
308 std::vector<mojom::WindowDataPtr> windows) override; | |
309 void OnWindowReordered(Id window_id, | |
310 Id relative_window_id, | |
311 mojom::OrderDirection direction) override; | |
312 void OnWindowDeleted(Id window_id) override; | |
313 void OnWindowVisibilityChanged(Id window_id, bool visible) override; | |
314 void OnWindowOpacityChanged(Id window_id, | |
315 float old_opacity, | |
316 float new_opacity) override; | |
317 void OnWindowParentDrawnStateChanged(Id window_id, bool drawn) override; | |
318 void OnWindowSharedPropertyChanged( | |
319 Id window_id, | |
320 const std::string& name, | |
321 const base::Optional<std::vector<uint8_t>>& new_data) override; | |
322 void OnWindowInputEvent(uint32_t event_id, | |
323 Id window_id, | |
324 std::unique_ptr<ui::Event> event, | |
325 bool matches_pointer_watcher) override; | |
326 void OnPointerEventObserved(std::unique_ptr<ui::Event> event, | |
327 uint32_t window_id) override; | |
328 void OnWindowFocused(Id focused_window_id) override; | |
329 void OnWindowPredefinedCursorChanged(Id window_id, | |
330 mojom::Cursor cursor) override; | |
331 void OnWindowSurfaceChanged(Id window_id, | |
332 const cc::SurfaceInfo& surface_info) override; | |
333 void OnDragDropStart( | |
334 const std::unordered_map<std::string, std::vector<uint8_t>>& mime_data) | |
335 override; | |
336 void OnDragEnter(Id window_id, | |
337 uint32_t event_flags, | |
338 const gfx::Point& position, | |
339 uint32_t effect_bitmask, | |
340 const OnDragEnterCallback& callback) override; | |
341 void OnDragOver(Id window_id, | |
342 uint32_t event_flags, | |
343 const gfx::Point& position, | |
344 uint32_t effect_bitmask, | |
345 const OnDragOverCallback& callback) override; | |
346 void OnDragLeave(Id window_id) override; | |
347 void OnCompleteDrop(Id window_id, | |
348 uint32_t event_flags, | |
349 const gfx::Point& position, | |
350 uint32_t effect_bitmask, | |
351 const OnCompleteDropCallback& callback) override; | |
352 void OnPerformDragDropCompleted(uint32_t window, | |
353 bool success, | |
354 uint32_t action_taken) override; | |
355 void OnDragDropDone() override; | |
356 void OnChangeCompleted(uint32_t change_id, bool success) override; | |
357 void RequestClose(uint32_t window_id) override; | |
358 void GetWindowManager( | |
359 mojo::AssociatedInterfaceRequest<WindowManager> internal) override; | |
360 | |
361 // Overridden from WindowManager: | |
362 void OnConnect(ClientSpecificId client_id) override; | |
363 void WmNewDisplayAdded(const display::Display& display, | |
364 mojom::WindowDataPtr root_data, | |
365 bool parent_drawn) override; | |
366 void WmDisplayRemoved(int64_t display_id) override; | |
367 void WmDisplayModified(const display::Display& display) override; | |
368 void WmSetBounds(uint32_t change_id, | |
369 Id window_id, | |
370 const gfx::Rect& transit_bounds) override; | |
371 void WmSetProperty( | |
372 uint32_t change_id, | |
373 Id window_id, | |
374 const std::string& name, | |
375 const base::Optional<std::vector<uint8_t>>& transit_data) override; | |
376 void WmCreateTopLevelWindow( | |
377 uint32_t change_id, | |
378 ClientSpecificId requesting_client_id, | |
379 const std::unordered_map<std::string, std::vector<uint8_t>>& | |
380 transport_properties) override; | |
381 void WmClientJankinessChanged(ClientSpecificId client_id, | |
382 bool janky) override; | |
383 void WmPerformMoveLoop(uint32_t change_id, | |
384 Id window_id, | |
385 mojom::MoveLoopSource source, | |
386 const gfx::Point& cursor_location) override; | |
387 void WmCancelMoveLoop(uint32_t window_id) override; | |
388 void WmDeactivateWindow(uint32_t window_id) override; | |
389 void OnAccelerator(uint32_t ack_id, | |
390 uint32_t accelerator_id, | |
391 std::unique_ptr<ui::Event> event) override; | |
392 | |
393 // Overridden from WindowManagerClient: | |
394 void SetFrameDecorationValues( | |
395 mojom::FrameDecorationValuesPtr values) override; | |
396 void SetNonClientCursor(Window* window, ui::mojom::Cursor cursor_id) override; | |
397 void AddAccelerators(std::vector<mojom::AcceleratorPtr> accelerators, | |
398 const base::Callback<void(bool)>& callback) override; | |
399 void RemoveAccelerator(uint32_t id) override; | |
400 void AddActivationParent(Window* window) override; | |
401 void RemoveActivationParent(Window* window) override; | |
402 void ActivateNextWindow() override; | |
403 void SetUnderlaySurfaceOffsetAndExtendedHitArea( | |
404 Window* window, | |
405 const gfx::Vector2d& offset, | |
406 const gfx::Insets& hit_area) override; | |
407 | |
408 // The one int in |cursor_location_mapping_|. When we read from this | |
409 // location, we must always read from it atomically. | |
410 base::subtle::Atomic32* cursor_location_memory() { | |
411 return reinterpret_cast<base::subtle::Atomic32*>( | |
412 cursor_location_mapping_.get()); | |
413 } | |
414 | |
415 // This is set once and only once when we get OnEmbed(). It gives the unique | |
416 // id for this client. | |
417 ClientSpecificId client_id_; | |
418 | |
419 // Id assigned to the next window created. | |
420 ClientSpecificId next_window_id_; | |
421 | |
422 // Id used for the next change id supplied to the server. | |
423 uint32_t next_change_id_; | |
424 InFlightMap in_flight_map_; | |
425 | |
426 WindowTreeClientDelegate* delegate_; | |
427 | |
428 WindowManagerDelegate* window_manager_delegate_; | |
429 | |
430 std::set<Window*> roots_; | |
431 | |
432 IdToWindowMap windows_; | |
433 std::map<ClientSpecificId, std::set<Window*>> embedded_windows_; | |
434 | |
435 Window* capture_window_; | |
436 | |
437 Window* focused_window_; | |
438 | |
439 mojo::Binding<mojom::WindowTreeClient> binding_; | |
440 mojom::WindowTreePtr tree_ptr_; | |
441 // Typically this is the value contained in |tree_ptr_|, but tests may | |
442 // directly set this. | |
443 mojom::WindowTree* tree_; | |
444 | |
445 // Set to true if OnEmbed() was received. | |
446 bool is_from_embed_ = false; | |
447 | |
448 bool in_destructor_; | |
449 | |
450 // A mapping to shared memory that is one 32 bit integer long. The window | |
451 // server uses this to let us synchronously read the cursor location. | |
452 mojo::ScopedSharedBufferMapping cursor_location_mapping_; | |
453 | |
454 base::ObserverList<WindowTreeClientObserver> observers_; | |
455 | |
456 std::unique_ptr<mojo::AssociatedBinding<mojom::WindowManager>> | |
457 window_manager_internal_; | |
458 mojom::WindowManagerClientAssociatedPtr window_manager_internal_client_; | |
459 | |
460 bool has_pointer_watcher_ = false; | |
461 | |
462 // The current change id for the client. | |
463 uint32_t current_move_loop_change_ = 0u; | |
464 | |
465 // Callback executed when a move loop initiated by PerformWindowMove() is | |
466 // completed. | |
467 base::Callback<void(bool)> on_current_move_finished_; | |
468 | |
469 // The current change id for the window manager.gg | |
470 uint32_t current_wm_move_loop_change_ = 0u; | |
471 Id current_wm_move_loop_window_id_ = 0u; | |
472 | |
473 // State related to being the initiator of a drag started with | |
474 // PerformDragDrop(). | |
475 std::unique_ptr<CurrentDragState> current_drag_state_; | |
476 | |
477 // The mus server sends the mime drag data once per connection; we cache this | |
478 // and are responsible for sending it to all of our windows. | |
479 | |
480 std::map<std::string, std::vector<uint8_t>> mime_drag_data_; | |
481 | |
482 // A set of window ids for windows that we received an OnDragEnter() message | |
483 // for. We maintain this set so we know who to send OnDragFinish() messages | |
484 // at the end of the drag. | |
485 std::set<Id> drag_entered_windows_; | |
486 | |
487 base::WeakPtrFactory<WindowTreeClient> weak_factory_; | |
488 | |
489 DISALLOW_COPY_AND_ASSIGN(WindowTreeClient); | |
490 }; | |
491 | |
492 } // namespace ui | |
493 | |
494 #endif // SERVICES_UI_PUBLIC_CPP_WINDOW_TREE_CLIENT_H_ | |
OLD | NEW |