Source code

Revision control

Other Tools

1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef mozilla_layers_AndroidDynamicToolbarAnimator_h_
8
#define mozilla_layers_AndroidDynamicToolbarAnimator_h_
9
10
#include "InputData.h"
11
#include "mozilla/Atomics.h"
12
#include "mozilla/EventForwards.h"
13
#include "mozilla/ipc/Shmem.h"
14
#include "mozilla/layers/Effects.h"
15
#include "mozilla/layers/TextureHost.h"
16
#include "mozilla/LinkedList.h"
17
#include "mozilla/Maybe.h"
18
#include "mozilla/TimeStamp.h"
19
#include "nsISupports.h"
20
21
namespace mozilla {
22
namespace layers {
23
24
struct FrameMetrics;
25
class APZCTreeManager;
26
class CompositorOGL;
27
28
/*
29
* The AndroidDynamicToolbarAnimator is responsible for calculating the position
30
* and drawing the static snapshot of the toolbar. The animator lives in both
31
* compositor thread and controller thread. It intercepts input events in the
32
* controller thread and determines if the intercepted touch events will cause
33
* the toolbar to move or be animated. Once the proper conditions have been met,
34
* the animator requests that the UI thread send a static snapshot of the
35
* current state of the toolbar. Once the animator has received the snapshot and
36
* converted it into an OGL texture, the animator notifies the UI thread it is
37
* ready. The UI thread will then hide the real toolbar and notify the animator
38
* that it is unlocked and may begin translating the snapshot. The
39
* animator is responsible for rendering the snapshot until it receives a
40
* message to show the toolbar or touch events cause the snapshot to be
41
* completely visible. When the snapshot is made completely visible the animator
42
* locks the static toolbar and sends a message to the UI thread to show the
43
* real toolbar and the whole process may start again. The toolbar height is in
44
* screen pixels. The toolbar height will be at max height when completely
45
* visible and at 0 when completely hidden. The toolbar is only locked when it
46
* is completely visible. The animator must ask for an update of the toolbar
47
* snapshot and that the real toolbar be hidden in order to unlock the static
48
* snapshot and begin translating it.
49
*
50
* See Bug 1335895 for more details.
51
*/
52
53
class AndroidDynamicToolbarAnimator final {
54
public:
55
// Whether to use the dynamic toolbar animator. Fennec is no longer in the
56
// tree, and Fenix doesn't yet have a dynamic toolbar, so for now this always
57
// returns false.
58
static bool IsEnabled() { return false; }
59
60
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AndroidDynamicToolbarAnimator);
61
explicit AndroidDynamicToolbarAnimator(APZCTreeManager* aApz);
62
void Initialize(LayersId aRootLayerTreeId);
63
void ClearTreeManager();
64
// Used to intercept events to determine if the event affects the toolbar.
65
// May apply translation to touch events if the toolbar is visible.
66
// Returns nsEventStatus_eIgnore when the event is not consumed and
67
// nsEventStatus_eConsumeNoDefault when the event was used to translate the
68
// toolbar.
69
nsEventStatus ReceiveInputEvent(const RefPtr<APZCTreeManager>& aApz,
70
InputData& aEvent,
71
const ScreenPoint& aScrollOffset);
72
void SetMaxToolbarHeight(ScreenIntCoord aHeight);
73
// When a pinned reason is set to true, the animator will prevent
74
// touch events from altering the height of the toolbar. All pinned
75
// reasons must be cleared before touch events will affect the toolbar.
76
// Animation requests from the UI thread are still honored even if any
77
// pin reason is set. This allows the UI thread to pin the toolbar for
78
// full screen and then request the animator hide the toolbar.
79
void SetPinned(bool aPinned, int32_t aReason);
80
// returns maximum number of Y device pixels the toolbar will cover when fully
81
// visible.
82
ScreenIntCoord GetMaxToolbarHeight() const;
83
// returns the current number of Y screen pixels the toolbar is currently
84
// showing.
85
ScreenIntCoord GetCurrentToolbarHeight() const;
86
// returns the current number of Y screen pixels the content should be offset
87
// from the top of the surface.
88
ScreenIntCoord GetCurrentContentOffset() const;
89
// returns the height in device pixels of the current Android surface used to
90
// display content and the toolbar. This will only change when the surface
91
// provided by the system actually changes size such as when the device is
92
// rotated or the virtual keyboard is made visible.
93
ScreenIntCoord GetCurrentSurfaceHeight() const;
94
// This is the height in device pixels of the root document's content. While
95
// the toolbar is being hidden or shown, the content may extend beyond the
96
// bottom of the surface until the toolbar is completely visible or hidden.
97
ScreenIntCoord GetCompositionHeight() const;
98
// Called to signal that root content is being scrolled. This prevents sub
99
// scroll frames from affecting the toolbar when being scrolled up. The idea
100
// is a scrolling down will always show the toolbar while scrolling up will
101
// only hide the toolbar if it is the root content being scrolled.
102
void SetScrollingRootContent();
103
void ToolbarAnimatorMessageFromUI(int32_t aMessage);
104
// Returns true if the animation will continue and false if it has completed.
105
bool UpdateAnimation(const TimeStamp& aCurrentFrame);
106
// Called to signify the first paint has occurred.
107
void FirstPaint();
108
// Called whenever the root document's FrameMetrics have reached a steady
109
// state.
110
void UpdateRootFrameMetrics(const FrameMetrics& aMetrics);
111
// Only update the frame metrics if the root composition size has changed
112
void MaybeUpdateCompositionSizeAndRootFrameMetrics(
113
const FrameMetrics& aMetrics);
114
// Adopts the Shmem containing the toolbar snapshot sent from the UI thread.
115
// The AndroidDynamicToolbarAnimator is responsible for deallocating the Shmem
116
// when it is done being used.
117
void AdoptToolbarPixels(mozilla::ipc::Shmem&& aMem,
118
const ScreenIntSize& aSize);
119
// Updates the toolbar snapshot texture and notifies the UI thread that the
120
// static toolbar is now ready to be displayed.
121
void UpdateToolbarSnapshotTexture(CompositorOGL* gl);
122
// Returns the Effect object used by the compositor to render the toolbar
123
// snapshot.
124
Effect* GetToolbarEffect();
125
void Shutdown();
126
127
protected:
128
enum StaticToolbarState {
129
eToolbarVisible,
130
eToolbarUpdated,
131
eToolbarUnlocked,
132
eToolbarAnimating
133
};
134
enum ControllerThreadState {
135
eNothingPending,
136
eShowPending,
137
eUnlockPending,
138
eAnimationStartPending,
139
eAnimationStopPending
140
};
141
enum AnimationStyle { eImmediate, eAnimate };
142
143
~AndroidDynamicToolbarAnimator() {}
144
nsEventStatus ProcessTouchDelta(const RefPtr<APZCTreeManager>& aApz,
145
StaticToolbarState aCurrentToolbarState,
146
ScreenIntCoord aDelta, uint32_t aTimeStamp);
147
// Called when a touch ends
148
void HandleTouchEnd(StaticToolbarState aCurrentToolbarState,
149
ScreenIntCoord aCurrentTouch);
150
// Sends a message to the UI thread. May be called from any thread
151
void PostMessage(int32_t aMessage);
152
void UpdateCompositorToolbarHeight(ScreenIntCoord aHeight);
153
void UpdateControllerToolbarHeight(ScreenIntCoord aHeight,
154
ScreenIntCoord aMaxHeight = -1);
155
void UpdateControllerSurfaceHeight(ScreenIntCoord aHeight);
156
void UpdateControllerCompositionHeight(ScreenIntCoord aHeight);
157
void UpdateFixedLayerMargins();
158
void NotifyControllerPendingAnimation(int32_t aDirection,
159
AnimationStyle aStyle);
160
void StartCompositorAnimation(int32_t aDirection, AnimationStyle aStyle,
161
ScreenIntCoord aHeight,
162
bool aWaitForPageResize);
163
void NotifyControllerAnimationStarted();
164
void StopCompositorAnimation();
165
void NotifyControllerAnimationStopped(ScreenIntCoord aHeight);
166
void RequestComposite();
167
void PostToolbarReady();
168
void UpdateFrameMetrics(ScreenPoint aScrollOffset, CSSToScreenScale aScale,
169
CSSRect aCssPageRect);
170
// Returns true if the page is too small to animate the toolbar
171
// Also ensures the toolbar is visible.
172
bool PageTooSmallEnsureToolbarVisible();
173
void ShowToolbarIfNotVisible(StaticToolbarState aCurrentToolbarState);
174
void TranslateTouchEvent(MultiTouchInput& aTouchEvent);
175
ScreenIntCoord GetFixedLayerMarginsBottom();
176
void NotifyControllerSnapshotFailed();
177
void CheckForResetOnNextMove(ScreenIntCoord aCurrentTouch);
178
// Returns true if the page scroll offset is near the bottom.
179
bool ScrollOffsetNearBottom() const;
180
// Returns true if toolbar is not completely visible nor completely hidden.
181
bool ToolbarInTransition();
182
void QueueMessage(int32_t aMessage);
183
184
// Read only Compositor and Controller threads after Initialize()
185
LayersId mRootLayerTreeId;
186
MOZ_NON_OWNING_REF APZCTreeManager* mApz;
187
188
// Read/Write Compositor Thread, Read only Controller thread
189
Atomic<StaticToolbarState> mToolbarState; // Current toolbar state.
190
Atomic<uint32_t> mPinnedFlags; // The toolbar should not be moved or animated
191
// unless no flags are set
192
193
// Controller thread only
194
bool mControllerScrollingRootContent; // Set to true when the root content is
195
// being scrolled
196
bool mControllerDragThresholdReached; // Set to true when the drag threshold
197
// has been passed in a single drag
198
bool mControllerCancelTouchTracking; // Set to true when the UI thread
199
// requests the toolbar be made visible
200
bool mControllerDragChangedDirection; // Set to true if the drag ever goes in
201
// more than one direction
202
bool mControllerResetOnNextMove; // Set to true if transitioning from
203
// multiple touches to a single touch source
204
// Causes mControllerStartTouch,
205
// mControllerPreviousTouch,
206
// mControllerTotalDistance,
207
// mControllerDragThresholdReached, and
208
// mControllerLastDragDirection to be reset
209
// on next move
210
ScreenIntCoord
211
mControllerStartTouch; // The Y position where the touch started
212
ScreenIntCoord
213
mControllerPreviousTouch; // The previous Y position of the touch
214
ScreenIntCoord mControllerTotalDistance; // Total distance travel during the
215
// current touch
216
ScreenIntCoord mControllerMaxToolbarHeight; // Max height of the toolbar
217
ScreenIntCoord mControllerToolbarHeight; // Current height of the toolbar
218
ScreenIntCoord
219
mControllerSurfaceHeight; // Current height of the render surface
220
ScreenIntCoord
221
mControllerCompositionHeight; // Current height of the visible page
222
ScreenCoord mControllerRootScrollY; // Current scroll Y value of the root
223
// scroll frame
224
int32_t mControllerLastDragDirection; // Direction of movement of the
225
// previous touch move event
226
int32_t mControllerTouchCount; // Counts the number of current touches.
227
uint32_t mControllerLastEventTimeStamp; // Time stamp for the previous touch
228
// event received
229
ControllerThreadState mControllerState; // Contains the expected pending
230
// state of the mToolbarState
231
232
// Contains the values from the last steady state root content FrameMetrics
233
struct FrameMetricsState {
234
ScreenPoint mScrollOffset;
235
CSSToScreenScale mScale;
236
CSSRect mCssPageRect;
237
ScreenRect mPageRect;
238
239
// Returns true if any of the values have changed.
240
bool Update(const ScreenPoint& aScrollOffset,
241
const CSSToScreenScale& aScale, const CSSRect& aCssPageRect);
242
};
243
244
// Controller thread only
245
FrameMetricsState mControllerFrameMetrics; // Updated when frame metrics are
246
// in a steady state.
247
248
class QueuedMessage : public LinkedListElement<QueuedMessage> {
249
public:
250
explicit QueuedMessage(int32_t aMessage) : mMessage(aMessage) {}
251
int32_t mMessage;
252
253
private:
254
QueuedMessage() = delete;
255
QueuedMessage(const QueuedMessage&) = delete;
256
QueuedMessage& operator=(const QueuedMessage&) = delete;
257
};
258
259
// Compositor thread only
260
bool
261
mCompositorShutdown; // Set to true when the compositor has been shutdown
262
bool mCompositorAnimationDeferred; // An animation has been deferred until
263
// the toolbar is unlocked
264
bool mCompositorAnimationStarted; // Set to true when the compositor has
265
// actually started animating the static
266
// snapshot.
267
bool mCompositorReceivedFirstPaint; // Set to true when a first paint occurs.
268
// Used by toolbar animator to detect a
269
// new page load.
270
bool mCompositorWaitForPageResize; // Set to true if the bottom of the page
271
// has been reached and the toolbar
272
// animator should wait for the page to
273
// resize before ending animation.
274
bool mCompositorToolbarShowRequested; // Set to true if the animator has
275
// already requested the real toolbar
276
// chrome be shown
277
bool mCompositorSendResponseForSnapshotUpdate; // Set to true when a message
278
// should be sent after a
279
// static toolbar snapshot
280
// update
281
AnimationStyle mCompositorAnimationStyle; // Set to true when the snapshot
282
// should be immediately hidden or
283
// shown in the animation update
284
ScreenIntCoord mCompositorMaxToolbarHeight; // Should contain the same value
285
// as mControllerMaxToolbarHeight
286
ScreenIntCoord mCompositorToolbarHeight; // This value is only updated by the
287
// compositor thread when the
288
// mToolbarState == ToolbarAnimating
289
ScreenIntCoord
290
mCompositorSurfaceHeight; // Current height of the render surface
291
ScreenIntSize mCompositorCompositionSize; // Current size of the visible page
292
int32_t mCompositorAnimationDirection; // Direction the snapshot should be
293
// animated
294
ScreenIntCoord
295
mCompositorAnimationStartHeight; // The height of the snapshot at the
296
// start of an animation
297
ScreenIntSize
298
mCompositorToolbarPixelsSize; // Size of the received toolbar pixels
299
Maybe<mozilla::ipc::Shmem>
300
mCompositorToolbarPixels; // Shared memory contain the updated snapshot
301
// pixels used to create the OGL texture
302
RefPtr<DataTextureSource>
303
mCompositorToolbarTexture; // The OGL texture used to render the snapshot
304
// in the compositor
305
RefPtr<EffectRGB> mCompositorToolbarEffect; // Effect used to render the
306
// snapshot in the compositor
307
TimeStamp mCompositorAnimationStartTimeStamp; // Time stamp when the current
308
// animation started
309
AutoCleanLinkedList<QueuedMessage>
310
mCompositorQueuedMessages; // Queue to contain messages sent before
311
// Initialize() called
312
};
313
314
} // namespace layers
315
} // namespace mozilla
316
#endif // mozilla_layers_AndroidDynamicToolbarAnimator_h_