summaryrefslogtreecommitdiff
path: root/chromium/ui/aura/mus/in_flight_change.h
blob: 1d6d0f630bdf6e6e8a9a225da6b9927f20071661 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef UI_AURA_MUS_IN_FLIGHT_CHANGE_H_
#define UI_AURA_MUS_IN_FLIGHT_CHANGE_H_

#include <stdint.h>

#include <memory>
#include <string>
#include <vector>

#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "components/viz/common/surfaces/local_surface_id.h"
#include "ui/aura/window_observer.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/transform.h"

namespace ui {
namespace mojom {
enum class CursorType : int32_t;
}
}  // namespace ui

namespace aura {

class CaptureSynchronizer;
class FocusSynchronizer;
class WindowMus;
class WindowTreeClient;

enum class ChangeType {
  ADD_CHILD,
  ADD_TRANSIENT_WINDOW,
  BOUNDS,
  CAPTURE,
  CHILD_MODAL_PARENT,
  DELETE_WINDOW,
  DRAG_LOOP,
  FOCUS,
  MOVE_LOOP,
  NEW_TOP_LEVEL_WINDOW,
  NEW_WINDOW,
  OPACITY,
  CURSOR,
  PROPERTY,
  REMOVE_CHILD,
  REMOVE_TRANSIENT_WINDOW_FROM_PARENT,
  REORDER,
  SET_MODAL,
  TRANSFORM,
  VISIBLE,
};

// Print a human-readable string representation of |change_type| for logging.
std::string ChangeTypeToString(ChangeType change_type);

// InFlightChange is used to track function calls to the server and take the
// appropriate action when the call fails, or the same property changes while
// waiting for the response. When a function is called on the server an
// InFlightChange is created. The function call is complete when
// OnChangeCompleted() is received from the server. The following may occur
// while waiting for a response:
// . A new value is encountered from the server. For example, the bounds of
//   a window is locally changed and while waiting for the ack
//   OnWindowBoundsChanged() is received.
//   When this happens SetRevertValueFrom() is invoked on the InFlightChange.
//   The expectation is SetRevertValueFrom() takes the value to revert from the
//   supplied change.
// . While waiting for the ack the property is again modified locally. When
//   this happens a new InFlightChange is created. Once the ack for the first
//   call is received, and the server rejected the change ChangeFailed() is
//   invoked on the first change followed by SetRevertValueFrom() on the second
//   InFlightChange. This allows the new change to update the value to revert
//   should the second call fail.
// . If the server responds that the call failed and there is not another
//   InFlightChange for the same window outstanding, then ChangeFailed() is
//   invoked followed by Revert(). The expectation is Revert() sets the
//   appropriate value back on the Window.
//
// In general there are two classes of changes:
// 1. We are the only side allowed to make the change.
// 2. The change can also be applied by another client. For example, the
//    window manager may change the bounds as well as the local client.
//
// For (1) use CrashInFlightChange. As the name implies this change CHECKs that
// the change succeeded. Use the following pattern for this. This code goes
// where the change is sent to the server (in WindowTreeClient):
//   const uint32_t change_id =
//   ScheduleInFlightChange(base::WrapUnique(new CrashInFlightChange(
//       window, ChangeType::REORDER)));
//
// For (2) use the same pattern as (1), but in the on change callback from the
// server (e.g. OnWindowBoundsChanged()) add the following:
//   // value_from_server is the value supplied from the server. It corresponds
//   // to the value of the property at the time the server processed the
//   // change. If the local change fails, this is the value reverted to.
//   InFlightBoundsChange new_change(window, value_from_server);
//   if (ApplyServerChangeToExistingInFlightChange(new_change)) {
//     // There was an in flight change for the same property. The in flight
//     // change takes the value to revert from |new_change|.
//     return;
//   }
//
//   // else case is no flight in change and the new value can be applied
//   // immediately.
//   WindowPrivate(window).LocalSetValue(new_value_from_server);
//
class InFlightChange {
 public:
  InFlightChange(WindowMus* window, ChangeType type);
  virtual ~InFlightChange();

  // NOTE: for properties not associated with any window window is null.
  WindowMus* window() { return window_; }
  const WindowMus* window() const { return window_; }
  ChangeType change_type() const { return change_type_; }

  // Returns true if the two changes are considered the same. This is only
  // invoked if the window id and ChangeType match.
  virtual bool Matches(const InFlightChange& change) const;

  // Called in two cases:
  // . When the corresponding property on the server changes. In this case
  //   |change| corresponds to the value from the server.
  // . When |change| unsuccesfully completes.
  virtual void SetRevertValueFrom(const InFlightChange& change) = 0;

  // The change failed. Normally you need not take any action here as Revert()
  // is called as appropriate.
  virtual void ChangeFailed();

  // The change failed and there is no pending change of the same type
  // outstanding, revert the value.
  virtual void Revert() = 0;

 private:
  WindowMus* window_;
  const ChangeType change_type_;
};

class InFlightBoundsChange : public InFlightChange {
 public:
  InFlightBoundsChange(
      WindowTreeClient* window_tree_client,
      WindowMus* window,
      const gfx::Rect& revert_bounds,
      const base::Optional<viz::LocalSurfaceId>& local_surface_id);
  ~InFlightBoundsChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  WindowTreeClient* window_tree_client_;
  gfx::Rect revert_bounds_;
  base::Optional<viz::LocalSurfaceId> revert_local_surface_id_;

  DISALLOW_COPY_AND_ASSIGN(InFlightBoundsChange);
};

class InFlightDragChange : public InFlightChange {
 public:
  InFlightDragChange(WindowMus* window, ChangeType type);

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  DISALLOW_COPY_AND_ASSIGN(InFlightDragChange);
};

class InFlightTransformChange : public InFlightChange {
 public:
  InFlightTransformChange(WindowTreeClient* window_tree_client,
                          WindowMus* window,
                          const gfx::Transform& revert_transform);
  ~InFlightTransformChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  WindowTreeClient* window_tree_client_;
  gfx::Transform revert_transform_;

  DISALLOW_COPY_AND_ASSIGN(InFlightTransformChange);
};

// Inflight change that crashes on failure. This is useful for changes that are
// expected to always complete.
class CrashInFlightChange : public InFlightChange {
 public:
  CrashInFlightChange(WindowMus* window, ChangeType type);
  ~CrashInFlightChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void ChangeFailed() override;
  void Revert() override;

 private:
  DISALLOW_COPY_AND_ASSIGN(CrashInFlightChange);
};

// Use this class for properties that are specific to the client, and not a
// particular window. For example, only a single window can have focus, so focus
// is specific to the client.
//
// This does not implement InFlightChange::Revert, subclasses must implement
// that to update the WindowTreeClient.
class InFlightWindowTreeClientChange : public InFlightChange,
                                       public WindowObserver {
 public:
  InFlightWindowTreeClientChange(WindowTreeClient* client,
                                 WindowMus* revert_value,
                                 ChangeType type);
  ~InFlightWindowTreeClientChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;

 protected:
  WindowTreeClient* client() { return client_; }
  WindowMus* revert_window() { return revert_window_; }

 private:
  void SetRevertWindow(WindowMus* window);

  // WindowObserver:
  void OnWindowDestroyed(Window* window) override;

  WindowTreeClient* client_;
  WindowMus* revert_window_;

  DISALLOW_COPY_AND_ASSIGN(InFlightWindowTreeClientChange);
};

class InFlightCaptureChange : public InFlightWindowTreeClientChange {
 public:
  InFlightCaptureChange(WindowTreeClient* client,
                        CaptureSynchronizer* capture_synchronizer,
                        WindowMus* revert_value);
  ~InFlightCaptureChange() override;

  // InFlightChange:
  void Revert() override;

 private:
  CaptureSynchronizer* capture_synchronizer_;
  DISALLOW_COPY_AND_ASSIGN(InFlightCaptureChange);
};

class InFlightFocusChange : public InFlightWindowTreeClientChange {
 public:
  InFlightFocusChange(WindowTreeClient* client,
                      FocusSynchronizer* focus_synchronizer,
                      WindowMus* revert_value);
  ~InFlightFocusChange() override;

  // InFlightChange:
  void Revert() override;

 private:
  FocusSynchronizer* focus_synchronizer_;

  DISALLOW_COPY_AND_ASSIGN(InFlightFocusChange);
};

class InFlightPropertyChange : public InFlightChange {
 public:
  InFlightPropertyChange(WindowMus* window,
                         const std::string& property_name,
                         std::unique_ptr<std::vector<uint8_t>> revert_value);
  ~InFlightPropertyChange() override;

  // InFlightChange:
  bool Matches(const InFlightChange& change) const override;
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  const std::string property_name_;
  std::unique_ptr<std::vector<uint8_t>> revert_value_;

  DISALLOW_COPY_AND_ASSIGN(InFlightPropertyChange);
};

class InFlightCursorChange : public InFlightChange {
 public:
  InFlightCursorChange(WindowMus* window, const ui::Cursor& revert_value);
  ~InFlightCursorChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  ui::Cursor revert_cursor_;

  DISALLOW_COPY_AND_ASSIGN(InFlightCursorChange);
};

class InFlightVisibleChange : public InFlightChange {
 public:
  InFlightVisibleChange(WindowTreeClient* client,
                        WindowMus* window,
                        const bool revert_value);
  ~InFlightVisibleChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  WindowTreeClient* window_tree_client_;
  bool revert_visible_;

  DISALLOW_COPY_AND_ASSIGN(InFlightVisibleChange);
};

class InFlightOpacityChange : public InFlightChange {
 public:
  InFlightOpacityChange(WindowMus* window, float revert_value);
  ~InFlightOpacityChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  float revert_opacity_;

  DISALLOW_COPY_AND_ASSIGN(InFlightOpacityChange);
};

class InFlightSetModalTypeChange : public InFlightChange {
 public:
  InFlightSetModalTypeChange(WindowMus* window, ui::ModalType revert_value);
  ~InFlightSetModalTypeChange() override;

  // InFlightChange:
  void SetRevertValueFrom(const InFlightChange& change) override;
  void Revert() override;

 private:
  ui::ModalType revert_modal_type_;

  DISALLOW_COPY_AND_ASSIGN(InFlightSetModalTypeChange);
};

}  // namespace aura

#endif  // UI_AURA_MUS_IN_FLIGHT_CHANGE_H_