Bug 1436754 - Merge LayerSession into GeckoSession; r=snorp,jchen

Depends on D10990

Differential Revision: https://phabricator.services.mozilla.com/D10991

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Agi Sferro 2018-11-09 17:04:38 +00:00
Родитель 71ee91b62f
Коммит 32866173fc
7 изменённых файлов: 602 добавлений и 631 удалений

Просмотреть файл

@ -16,7 +16,7 @@ import java.util.ArrayList;
import java.util.List;
public final class CompositorController {
private final LayerSession.Compositor mCompositor;
private final GeckoSession.Compositor mCompositor;
public interface GetPixelsCallback {
void onPixelsResult(int width, int height, IntBuffer pixels);
@ -27,7 +27,7 @@ public final class CompositorController {
private int mDefaultClearColor = Color.WHITE;
private Runnable mFirstPaintCallback;
/* package */ CompositorController(final LayerSession session) {
/* package */ CompositorController(final GeckoSession session) {
mCompositor = session.mCompositor;
}

Просмотреть файл

@ -40,12 +40,12 @@ public final class DynamicToolbarAnimator {
private final Set<PinReason> mPinFlags = EnumSet.noneOf(PinReason.class);
private final LayerSession mTarget;
private final LayerSession.Compositor mCompositor;
private final GeckoSession mTarget;
private final GeckoSession.Compositor mCompositor;
private ToolbarChromeProxy mToolbarChromeProxy;
private int mMaxToolbarHeight;
/* package */ DynamicToolbarAnimator(final LayerSession aTarget) {
/* package */ DynamicToolbarAnimator(final GeckoSession aTarget) {
mTarget = aTarget;
mCompositor = aTarget.mCompositor;
}
@ -69,7 +69,7 @@ public final class DynamicToolbarAnimator {
}
}
// Keep this package-private because applications should use one of LayerSession's
// Keep this package-private because applications should use one of GeckoSession's
// coordinates APIs instead of dealing with the dynamic toolbar manually.
/* package */ int getCurrentToolbarHeight() {
ThreadUtils.assertOnUiThread();
@ -116,8 +116,8 @@ public final class DynamicToolbarAnimator {
if (mCompositor.isReady()) {
mCompositor.sendToolbarAnimatorMessage(
immediately ? LayerSession.REQUEST_SHOW_TOOLBAR_IMMEDIATELY
: LayerSession.REQUEST_SHOW_TOOLBAR_ANIMATED);
immediately ? GeckoSession.REQUEST_SHOW_TOOLBAR_IMMEDIATELY
: GeckoSession.REQUEST_SHOW_TOOLBAR_ANIMATED);
}
}
@ -126,8 +126,8 @@ public final class DynamicToolbarAnimator {
if (mCompositor.isReady()) {
mCompositor.sendToolbarAnimatorMessage(
immediately ? LayerSession.REQUEST_HIDE_TOOLBAR_IMMEDIATELY
: LayerSession.REQUEST_HIDE_TOOLBAR_ANIMATED);
immediately ? GeckoSession.REQUEST_HIDE_TOOLBAR_IMMEDIATELY
: GeckoSession.REQUEST_HIDE_TOOLBAR_ANIMATED);
}
}
@ -136,10 +136,10 @@ public final class DynamicToolbarAnimator {
if ((mToolbarChromeProxy != null) && mToolbarChromeProxy.isToolbarChromeVisible()) {
mCompositor.sendToolbarAnimatorMessage(
LayerSession.REQUEST_SHOW_TOOLBAR_IMMEDIATELY);
GeckoSession.REQUEST_SHOW_TOOLBAR_IMMEDIATELY);
} else {
mCompositor.sendToolbarAnimatorMessage(
LayerSession.REQUEST_HIDE_TOOLBAR_IMMEDIATELY);
GeckoSession.REQUEST_HIDE_TOOLBAR_IMMEDIATELY);
}
for (final PinReason reason : PinReason.values()) {
@ -153,12 +153,12 @@ public final class DynamicToolbarAnimator {
}
switch (message) {
case LayerSession.STATIC_TOOLBAR_NEEDS_UPDATE: {
case GeckoSession.STATIC_TOOLBAR_NEEDS_UPDATE: {
// Send updated toolbar image to compositor.
final Bitmap bm = mToolbarChromeProxy.getBitmapOfToolbarChrome();
if (bm == null) {
mCompositor.sendToolbarAnimatorMessage(
LayerSession.TOOLBAR_SNAPSHOT_FAILED);
GeckoSession.TOOLBAR_SNAPSHOT_FAILED);
break;
}
@ -172,22 +172,22 @@ public final class DynamicToolbarAnimator {
} catch (final Throwable e) {
Log.e(LOGTAG, "Cannot get toolbar pixels", e);
mCompositor.sendToolbarAnimatorMessage(
LayerSession.TOOLBAR_SNAPSHOT_FAILED);
GeckoSession.TOOLBAR_SNAPSHOT_FAILED);
}
break;
}
case LayerSession.STATIC_TOOLBAR_READY: {
case GeckoSession.STATIC_TOOLBAR_READY: {
// Hide toolbar and send TOOLBAR_HIDDEN message to compositor
mToolbarChromeProxy.toggleToolbarChrome(false);
mCompositor.sendToolbarAnimatorMessage(LayerSession.TOOLBAR_HIDDEN);
mCompositor.sendToolbarAnimatorMessage(GeckoSession.TOOLBAR_HIDDEN);
break;
}
case LayerSession.TOOLBAR_SHOW: {
case GeckoSession.TOOLBAR_SHOW: {
// Show toolbar.
mToolbarChromeProxy.toggleToolbarChrome(true);
mCompositor.sendToolbarAnimatorMessage(LayerSession.TOOLBAR_VISIBLE);
mCompositor.sendToolbarAnimatorMessage(GeckoSession.TOOLBAR_VISIBLE);
break;
}

Просмотреть файл

@ -32,6 +32,8 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.database.Cursor;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.net.Uri;
import android.os.Binder;
@ -54,8 +56,7 @@ import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
public class GeckoSession extends LayerSession
implements Parcelable {
public class GeckoSession implements Parcelable {
private static final String LOGTAG = "GeckoSession";
private static final boolean DEBUG = false;
@ -106,6 +107,161 @@ public class GeckoSession extends LayerSession
private boolean mShouldPinOnScreen;
// All fields are accessed on UI thread only.
private PanZoomController mNPZC;
private OverscrollEdgeEffect mOverscroll;
private DynamicToolbarAnimator mToolbar;
private CompositorController mController;
private boolean mAttachedCompositor;
private boolean mCompositorReady;
private Surface mSurface;
// All fields of coordinates are in screen units.
private int mLeft;
private int mTop; // Top of the surface (including toolbar);
private int mClientTop; // Top of the client area (i.e. excluding toolbar);
private int mWidth;
private int mHeight; // Height of the surface (including toolbar);
private int mClientHeight; // Height of the client area (i.e. excluding toolbar);
private float mViewportLeft;
private float mViewportTop;
private float mViewportZoom = 1.0f;
//
// NOTE: These values are also defined in
// gfx/layers/ipc/UiCompositorControllerMessageTypes.h and must be kept in sync. Any
// new AnimatorMessageType added here must also be added there.
//
// Sent from compositor when the static toolbar wants to hide.
/* package */ final static int STATIC_TOOLBAR_NEEDS_UPDATE = 0;
// Sent from compositor when the static toolbar image has been updated and is ready to
// animate.
/* package */ final static int STATIC_TOOLBAR_READY = 1;
// Sent to compositor when the real toolbar has been hidden.
/* package */ final static int TOOLBAR_HIDDEN = 2;
// Sent to compositor when the real toolbar is visible.
/* package */ final static int TOOLBAR_VISIBLE = 3;
// Sent from compositor when the static toolbar has been made visible so the real
// toolbar should be shown.
/* package */ final static int TOOLBAR_SHOW = 4;
// Sent from compositor after first paint
/* package */ final static int FIRST_PAINT = 5;
// Sent to compositor requesting toolbar be shown immediately
/* package */ final static int REQUEST_SHOW_TOOLBAR_IMMEDIATELY = 6;
// Sent to compositor requesting toolbar be shown animated
/* package */ final static int REQUEST_SHOW_TOOLBAR_ANIMATED = 7;
// Sent to compositor requesting toolbar be hidden immediately
/* package */ final static int REQUEST_HIDE_TOOLBAR_IMMEDIATELY = 8;
// Sent to compositor requesting toolbar be hidden animated
/* package */ final static int REQUEST_HIDE_TOOLBAR_ANIMATED = 9;
// Sent from compositor when a layer has been updated
/* package */ final static int LAYERS_UPDATED = 10;
// Sent to compositor when the toolbar snapshot fails.
/* package */ final static int TOOLBAR_SNAPSHOT_FAILED = 11;
// Special message sent from UiCompositorControllerChild once it is open
/* package */ final static int COMPOSITOR_CONTROLLER_OPEN = 20;
// Special message sent from controller to query if the compositor controller is open.
/* package */ final static int IS_COMPOSITOR_CONTROLLER_OPEN = 21;
protected class Compositor extends JNIObject {
public boolean isReady() {
return GeckoSession.this.isCompositorReady();
}
@WrapForJNI(calledFrom = "ui")
private void onCompositorAttached() {
GeckoSession.this.onCompositorAttached();
}
@WrapForJNI(calledFrom = "ui")
private void onCompositorDetached() {
// Clear out any pending calls on the UI thread.
GeckoSession.this.onCompositorDetached();
}
@WrapForJNI(dispatchTo = "gecko")
@Override protected native void disposeNative();
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
public native void attachNPZC(PanZoomController npzc);
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
public native void onBoundsChanged(int left, int top, int width, int height);
// Gecko thread pauses compositor; blocks UI thread.
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void syncPauseCompositor();
// UI thread resumes compositor and notifies Gecko thread; does not block UI thread.
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void syncResumeResizeCompositor(int width, int height, Object surface);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void setMaxToolbarHeight(int height);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void setPinned(boolean pinned, int reason);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void sendToolbarAnimatorMessage(int message);
@WrapForJNI(calledFrom = "ui")
private void recvToolbarAnimatorMessage(int message) {
GeckoSession.this.handleCompositorMessage(message);
}
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void setDefaultClearColor(int color);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void requestScreenPixels();
@WrapForJNI(calledFrom = "ui")
private void recvScreenPixels(int width, int height, int[] pixels) {
GeckoSession.this.recvScreenPixels(width, height, pixels);
}
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void enableLayerUpdateNotifications(boolean enable);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void sendToolbarPixelsToCompositor(final int width, final int height,
final int[] pixels);
// The compositor invokes this function just before compositing a frame where the
// document is different from the document composited on the last frame. In these
// cases, the viewport information we have in Java is no longer valid and needs to
// be replaced with the new viewport information provided.
@WrapForJNI(calledFrom = "ui")
private void updateRootFrameMetrics(float scrollX, float scrollY, float zoom) {
GeckoSession.this.onMetricsChanged(scrollX, scrollY, zoom);
}
@WrapForJNI(calledFrom = "ui")
private void updateOverscrollVelocity(final float x, final float y) {
GeckoSession.this.updateOverscrollVelocity(x, y);
}
@WrapForJNI(calledFrom = "ui")
private void updateOverscrollOffset(final float x, final float y) {
GeckoSession.this.updateOverscrollOffset(x, y);
}
@Override
protected void finalize() throws Throwable {
disposeNative();
}
}
protected final Compositor mCompositor = new Compositor();
@WrapForJNI(stubName = "GetCompositor", calledFrom = "ui")
private Object getCompositorFromNative() {
// Only used by native code.
return mCompositorReady ? mCompositor : null;
}
/* package */ static abstract class CallbackResult<T> extends GeckoResult<T>
implements EventCallback {
@Override
@ -2085,9 +2241,15 @@ public class GeckoSession extends LayerSession
}
}
@Override
protected void setShouldPinOnScreen(final boolean pinned) {
super.setShouldPinOnScreen(pinned);
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mToolbar != null) {
mToolbar.setPinned(pinned, DynamicToolbarAnimator.PinReason.CARET_DRAG);
}
mShouldPinOnScreen = pinned;
}
@ -3150,6 +3312,170 @@ public class GeckoSession extends LayerSession
public void onScrollChanged(GeckoSession session, int scrollX, int scrollY);
}
/**
* Get the PanZoomController instance for this session.
*
* @return PanZoomController instance.
*/
@UiThread
public PanZoomController getPanZoomController() {
ThreadUtils.assertOnUiThread();
if (mNPZC == null) {
mNPZC = new PanZoomController(this);
if (mAttachedCompositor) {
mCompositor.attachNPZC(mNPZC);
}
}
return mNPZC;
}
/**
* Get the OverscrollEdgeEffect instance for this session.
*
* @return OverscrollEdgeEffect instance.
*/
@UiThread
public OverscrollEdgeEffect getOverscrollEdgeEffect() {
ThreadUtils.assertOnUiThread();
if (mOverscroll == null) {
mOverscroll = new OverscrollEdgeEffect(this);
}
return mOverscroll;
}
/**
* Get the DynamicToolbarAnimator instance for this session.
*
* @return DynamicToolbarAnimator instance.
*/
@UiThread
public @NonNull DynamicToolbarAnimator getDynamicToolbarAnimator() {
ThreadUtils.assertOnUiThread();
if (mToolbar == null) {
mToolbar = new DynamicToolbarAnimator(this);
}
return mToolbar;
}
/**
* Get the CompositorController instance for this session.
*
* @return CompositorController instance.
*/
@UiThread
public @NonNull CompositorController getCompositorController() {
ThreadUtils.assertOnUiThread();
if (mController == null) {
mController = new CompositorController(this);
if (mCompositorReady) {
mController.onCompositorReady();
}
}
return mController;
}
/**
* Get a matrix for transforming from client coordinates to surface coordinates.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getClientToScreenMatrix(Matrix)
* @see #getPageToSurfaceMatrix(Matrix)
*/
@UiThread
public void getClientToSurfaceMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
matrix.setScale(mViewportZoom, mViewportZoom);
if (mClientTop != mTop) {
matrix.postTranslate(0, mClientTop - mTop);
}
}
/**
* Get a matrix for transforming from client coordinates to screen coordinates. The
* client coordinates are in CSS pixels and are relative to the viewport origin; their
* relation to screen coordinates does not depend on the current scroll position.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getClientToSurfaceMatrix(Matrix)
* @see #getPageToScreenMatrix(Matrix)
*/
@UiThread
public void getClientToScreenMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
getClientToSurfaceMatrix(matrix);
matrix.postTranslate(mLeft, mTop);
}
/**
* Get a matrix for transforming from page coordinates to screen coordinates. The page
* coordinates are in CSS pixels and are relative to the page origin; their relation
* to screen coordinates depends on the current scroll position of the outermost
* frame.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getPageToSurfaceMatrix(Matrix)
* @see #getClientToScreenMatrix(Matrix)
*/
@UiThread
public void getPageToScreenMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
getPageToSurfaceMatrix(matrix);
matrix.postTranslate(mLeft, mTop);
}
/**
* Get a matrix for transforming from page coordinates to surface coordinates.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getPageToScreenMatrix(Matrix)
* @see #getClientToSurfaceMatrix(Matrix)
*/
@UiThread
public void getPageToSurfaceMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
getClientToSurfaceMatrix(matrix);
matrix.postTranslate(-mViewportLeft, -mViewportTop);
}
/**
* Get the bounds of the client area in client coordinates. The returned top-left
* coordinates are always (0, 0). Use the matrix from {@link
* #getClientToSurfaceMatrix(Matrix)} or {@link #getClientToScreenMatrix(Matrix)} to
* map these bounds to surface or screen coordinates, respectively.
*
* @param rect RectF to be replaced by the client bounds in client coordinates.
* @see #getSurfaceBounds(Rect)
*/
@UiThread
public void getClientBounds(@NonNull final RectF rect) {
ThreadUtils.assertOnUiThread();
rect.set(0.0f, 0.0f, (float) mWidth / mViewportZoom,
(float) mClientHeight / mViewportZoom);
}
/**
* Get the bounds of the client area in surface coordinates. This is equivalent to
* mapping the bounds returned by #getClientBounds(RectF) with the matrix returned by
* #getClientToSurfaceMatrix(Matrix).
*
* @param rect Rect to be replaced by the client bounds in surface coordinates.
*/
@UiThread
public void getSurfaceBounds(@NonNull final Rect rect) {
ThreadUtils.assertOnUiThread();
rect.set(0, mClientTop - mTop, mWidth, mHeight);
}
/**
* GeckoSession applications implement this interface to handle tracking
* protection events.
@ -3598,6 +3924,237 @@ public class GeckoSession extends LayerSession
int virtualId);
}
/* package */ void onSurfaceChanged(final Surface surface, final int width,
final int height) {
ThreadUtils.assertOnUiThread();
mWidth = width;
mHeight = height;
if (mCompositorReady) {
mCompositor.syncResumeResizeCompositor(width, height, surface);
onWindowBoundsChanged();
return;
}
// We have a valid surface but we're not attached or the compositor
// is not ready; save the surface for later when we're ready.
mSurface = surface;
// Adjust bounds as the last step.
onWindowBoundsChanged();
}
/* package */ void onSurfaceDestroyed() {
ThreadUtils.assertOnUiThread();
if (mCompositorReady) {
mCompositor.syncPauseCompositor();
return;
}
// While the surface was valid, we never became attached or the
// compositor never became ready; clear the saved surface.
mSurface = null;
}
/* package */ void onScreenOriginChanged(final int left, final int top) {
ThreadUtils.assertOnUiThread();
if (mLeft == left && mTop == top) {
return;
}
mLeft = left;
mTop = top;
onWindowBoundsChanged();
}
/* package */ void onCompositorAttached() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
mAttachedCompositor = true;
if (mNPZC != null) {
mCompositor.attachNPZC(mNPZC);
}
if (mSurface != null) {
// If we have a valid surface, create the compositor now that we're attached.
// Leave mSurface alone because we'll need it later for onCompositorReady.
onSurfaceChanged(mSurface, mWidth, mHeight);
}
mCompositor.sendToolbarAnimatorMessage(IS_COMPOSITOR_CONTROLLER_OPEN);
}
/* package */ void onCompositorDetached() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mController != null) {
mController.onCompositorDetached();
}
mAttachedCompositor = false;
mCompositorReady = false;
}
/* package */ void handleCompositorMessage(final int message) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
switch (message) {
case COMPOSITOR_CONTROLLER_OPEN: {
if (isCompositorReady()) {
return;
}
// Delay calling onCompositorReady to avoid deadlock due
// to synchronous call to the compositor.
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
onCompositorReady();
}
});
break;
}
case FIRST_PAINT: {
if (mController != null) {
mController.onFirstPaint();
}
break;
}
case LAYERS_UPDATED: {
if (mController != null) {
mController.notifyDrawCallbacks();
}
break;
}
case STATIC_TOOLBAR_READY:
case TOOLBAR_SHOW: {
if (mToolbar != null) {
mToolbar.handleToolbarAnimatorMessage(message);
// Update window bounds due to toolbar visibility change.
onWindowBoundsChanged();
}
break;
}
default: {
if (mToolbar != null) {
mToolbar.handleToolbarAnimatorMessage(message);
} else {
Log.w(LOGTAG, "Unexpected message: " + message);
}
break;
}
}
}
/* package */ void recvScreenPixels(int width, int height, int[] pixels) {
if (mController != null) {
mController.recvScreenPixels(width, height, pixels);
}
}
/* package */ boolean isCompositorReady() {
return mCompositorReady;
}
/* package */ void onCompositorReady() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
mCompositorReady = true;
if (mController != null) {
mController.onCompositorReady();
}
if (mSurface != null) {
// If we have a valid surface, resume the
// compositor now that the compositor is ready.
onSurfaceChanged(mSurface, mWidth, mHeight);
mSurface = null;
}
if (mToolbar != null) {
mToolbar.onCompositorReady();
}
}
/* package */ void updateOverscrollVelocity(final float x, final float y) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mOverscroll == null) {
return;
}
// Multiply the velocity by 1000 to match what was done in JPZ.
mOverscroll.setVelocity(x * 1000.0f, OverscrollEdgeEffect.AXIS_X);
mOverscroll.setVelocity(y * 1000.0f, OverscrollEdgeEffect.AXIS_Y);
}
/* package */ void updateOverscrollOffset(final float x, final float y) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mOverscroll == null) {
return;
}
mOverscroll.setDistance(x, OverscrollEdgeEffect.AXIS_X);
mOverscroll.setDistance(y, OverscrollEdgeEffect.AXIS_Y);
}
/* package */ void onMetricsChanged(final float scrollX, final float scrollY,
final float zoom) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
mViewportLeft = scrollX;
mViewportTop = scrollY;
mViewportZoom = zoom;
}
/* protected */ void onWindowBoundsChanged() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
final int toolbarHeight;
if (mToolbar != null) {
toolbarHeight = mToolbar.getCurrentToolbarHeight();
} else {
toolbarHeight = 0;
}
mClientTop = mTop + toolbarHeight;
mClientHeight = mHeight - toolbarHeight;
if (mAttachedCompositor) {
mCompositor.onBoundsChanged(mLeft, mClientTop, mWidth, mClientHeight);
}
if (mOverscroll != null) {
mOverscroll.setSize(mWidth, mClientHeight);
}
}
/**
* GeckoSession applications implement this interface to handle media events.
*/

Просмотреть файл

@ -1,586 +0,0 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.geckoview;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.mozglue.JNIObject;
import org.mozilla.gecko.util.ThreadUtils;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
import android.util.Log;
import android.view.Surface;
public class LayerSession {
private static final String LOGTAG = "GeckoLayerSession";
private static final boolean DEBUG = false;
//
// NOTE: These values are also defined in
// gfx/layers/ipc/UiCompositorControllerMessageTypes.h and must be kept in sync. Any
// new AnimatorMessageType added here must also be added there.
//
// Sent from compositor when the static toolbar wants to hide.
/* package */ final static int STATIC_TOOLBAR_NEEDS_UPDATE = 0;
// Sent from compositor when the static toolbar image has been updated and is ready to
// animate.
/* package */ final static int STATIC_TOOLBAR_READY = 1;
// Sent to compositor when the real toolbar has been hidden.
/* package */ final static int TOOLBAR_HIDDEN = 2;
// Sent to compositor when the real toolbar is visible.
/* package */ final static int TOOLBAR_VISIBLE = 3;
// Sent from compositor when the static toolbar has been made visible so the real
// toolbar should be shown.
/* package */ final static int TOOLBAR_SHOW = 4;
// Sent from compositor after first paint
/* package */ final static int FIRST_PAINT = 5;
// Sent to compositor requesting toolbar be shown immediately
/* package */ final static int REQUEST_SHOW_TOOLBAR_IMMEDIATELY = 6;
// Sent to compositor requesting toolbar be shown animated
/* package */ final static int REQUEST_SHOW_TOOLBAR_ANIMATED = 7;
// Sent to compositor requesting toolbar be hidden immediately
/* package */ final static int REQUEST_HIDE_TOOLBAR_IMMEDIATELY = 8;
// Sent to compositor requesting toolbar be hidden animated
/* package */ final static int REQUEST_HIDE_TOOLBAR_ANIMATED = 9;
// Sent from compositor when a layer has been updated
/* package */ final static int LAYERS_UPDATED = 10;
// Sent to compositor when the toolbar snapshot fails.
/* package */ final static int TOOLBAR_SNAPSHOT_FAILED = 11;
// Special message sent from UiCompositorControllerChild once it is open
/* package */ final static int COMPOSITOR_CONTROLLER_OPEN = 20;
// Special message sent from controller to query if the compositor controller is open.
/* package */ final static int IS_COMPOSITOR_CONTROLLER_OPEN = 21;
protected class Compositor extends JNIObject {
public boolean isReady() {
return LayerSession.this.isCompositorReady();
}
@WrapForJNI(calledFrom = "ui")
private void onCompositorAttached() {
LayerSession.this.onCompositorAttached();
}
@WrapForJNI(calledFrom = "ui")
private void onCompositorDetached() {
// Clear out any pending calls on the UI thread.
LayerSession.this.onCompositorDetached();
}
@WrapForJNI(dispatchTo = "gecko")
@Override protected native void disposeNative();
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
public native void attachNPZC(PanZoomController npzc);
@WrapForJNI(calledFrom = "ui", dispatchTo = "gecko")
public native void onBoundsChanged(int left, int top, int width, int height);
// Gecko thread pauses compositor; blocks UI thread.
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void syncPauseCompositor();
// UI thread resumes compositor and notifies Gecko thread; does not block UI thread.
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void syncResumeResizeCompositor(int width, int height, Object surface);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void setMaxToolbarHeight(int height);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void setPinned(boolean pinned, int reason);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void sendToolbarAnimatorMessage(int message);
@WrapForJNI(calledFrom = "ui")
private void recvToolbarAnimatorMessage(int message) {
LayerSession.this.handleCompositorMessage(message);
}
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void setDefaultClearColor(int color);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void requestScreenPixels();
@WrapForJNI(calledFrom = "ui")
private void recvScreenPixels(int width, int height, int[] pixels) {
LayerSession.this.recvScreenPixels(width, height, pixels);
}
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void enableLayerUpdateNotifications(boolean enable);
@WrapForJNI(calledFrom = "ui", dispatchTo = "current")
public native void sendToolbarPixelsToCompositor(final int width, final int height,
final int[] pixels);
// The compositor invokes this function just before compositing a frame where the
// document is different from the document composited on the last frame. In these
// cases, the viewport information we have in Java is no longer valid and needs to
// be replaced with the new viewport information provided.
@WrapForJNI(calledFrom = "ui")
private void updateRootFrameMetrics(float scrollX, float scrollY, float zoom) {
LayerSession.this.onMetricsChanged(scrollX, scrollY, zoom);
}
@WrapForJNI(calledFrom = "ui")
private void updateOverscrollVelocity(final float x, final float y) {
LayerSession.this.updateOverscrollVelocity(x, y);
}
@WrapForJNI(calledFrom = "ui")
private void updateOverscrollOffset(final float x, final float y) {
LayerSession.this.updateOverscrollOffset(x, y);
}
@Override
protected void finalize() throws Throwable {
disposeNative();
}
}
protected final Compositor mCompositor = new Compositor();
// All fields are accessed on UI thread only.
private PanZoomController mNPZC;
private OverscrollEdgeEffect mOverscroll;
private DynamicToolbarAnimator mToolbar;
private CompositorController mController;
private boolean mAttachedCompositor;
private boolean mCompositorReady;
private Surface mSurface;
// All fields of coordinates are in screen units.
private int mLeft;
private int mTop; // Top of the surface (including toolbar);
private int mClientTop; // Top of the client area (i.e. excluding toolbar);
private int mWidth;
private int mHeight; // Height of the surface (including toolbar);
private int mClientHeight; // Height of the client area (i.e. excluding toolbar);
private float mViewportLeft;
private float mViewportTop;
private float mViewportZoom = 1.0f;
/**
* Get the PanZoomController instance for this session.
*
* @return PanZoomController instance.
*/
@UiThread
public PanZoomController getPanZoomController() {
ThreadUtils.assertOnUiThread();
if (mNPZC == null) {
mNPZC = new PanZoomController(this);
if (mAttachedCompositor) {
mCompositor.attachNPZC(mNPZC);
}
}
return mNPZC;
}
/**
* Get the OverscrollEdgeEffect instance for this session.
*
* @return OverscrollEdgeEffect instance.
*/
@UiThread
public OverscrollEdgeEffect getOverscrollEdgeEffect() {
ThreadUtils.assertOnUiThread();
if (mOverscroll == null) {
mOverscroll = new OverscrollEdgeEffect(this);
}
return mOverscroll;
}
/**
* Get the DynamicToolbarAnimator instance for this session.
*
* @return DynamicToolbarAnimator instance.
*/
@UiThread
public @NonNull DynamicToolbarAnimator getDynamicToolbarAnimator() {
ThreadUtils.assertOnUiThread();
if (mToolbar == null) {
mToolbar = new DynamicToolbarAnimator(this);
}
return mToolbar;
}
/**
* Get the CompositorController instance for this session.
*
* @return CompositorController instance.
*/
@UiThread
public @NonNull CompositorController getCompositorController() {
ThreadUtils.assertOnUiThread();
if (mController == null) {
mController = new CompositorController(this);
if (mCompositorReady) {
mController.onCompositorReady();
}
}
return mController;
}
/**
* Get a matrix for transforming from client coordinates to screen coordinates. The
* client coordinates are in CSS pixels and are relative to the viewport origin; their
* relation to screen coordinates does not depend on the current scroll position.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getClientToSurfaceMatrix(Matrix)
* @see #getPageToScreenMatrix(Matrix)
*/
@UiThread
public void getClientToScreenMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
getClientToSurfaceMatrix(matrix);
matrix.postTranslate(mLeft, mTop);
}
/**
* Get a matrix for transforming from client coordinates to surface coordinates.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getClientToScreenMatrix(Matrix)
* @see #getPageToSurfaceMatrix(Matrix)
*/
@UiThread
public void getClientToSurfaceMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
matrix.setScale(mViewportZoom, mViewportZoom);
if (mClientTop != mTop) {
matrix.postTranslate(0, mClientTop - mTop);
}
}
/**
* Get a matrix for transforming from page coordinates to screen coordinates. The page
* coordinates are in CSS pixels and are relative to the page origin; their relation
* to screen coordinates depends on the current scroll position of the outermost
* frame.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getPageToSurfaceMatrix(Matrix)
* @see #getClientToScreenMatrix(Matrix)
*/
@UiThread
public void getPageToScreenMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
getPageToSurfaceMatrix(matrix);
matrix.postTranslate(mLeft, mTop);
}
/**
* Get a matrix for transforming from page coordinates to surface coordinates.
*
* @param matrix Matrix to be replaced by the transformation matrix.
* @see #getPageToScreenMatrix(Matrix)
* @see #getClientToSurfaceMatrix(Matrix)
*/
@UiThread
public void getPageToSurfaceMatrix(@NonNull final Matrix matrix) {
ThreadUtils.assertOnUiThread();
getClientToSurfaceMatrix(matrix);
matrix.postTranslate(-mViewportLeft, -mViewportTop);
}
/**
* Get the bounds of the client area in client coordinates. The returned top-left
* coordinates are always (0, 0). Use the matrix from {@link
* #getClientToSurfaceMatrix(Matrix)} or {@link #getClientToScreenMatrix(Matrix)} to
* map these bounds to surface or screen coordinates, respectively.
*
* @param rect RectF to be replaced by the client bounds in client coordinates.
* @see #getSurfaceBounds(Rect)
*/
@UiThread
public void getClientBounds(@NonNull final RectF rect) {
ThreadUtils.assertOnUiThread();
rect.set(0.0f, 0.0f, (float) mWidth / mViewportZoom,
(float) mClientHeight / mViewportZoom);
}
/**
* Get the bounds of the client area in surface coordinates. This is equivalent to
* mapping the bounds returned by #getClientBounds(RectF) with the matrix returned by
* #getClientToSurfaceMatrix(Matrix).
*
* @param rect Rect to be replaced by the client bounds in surface coordinates.
*/
@UiThread
public void getSurfaceBounds(@NonNull final Rect rect) {
ThreadUtils.assertOnUiThread();
rect.set(0, mClientTop - mTop, mWidth, mHeight);
}
@WrapForJNI(stubName = "GetCompositor", calledFrom = "ui")
private Object getCompositorFromNative() {
// Only used by native code.
return mCompositorReady ? mCompositor : null;
}
/* package */ void onCompositorAttached() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
mAttachedCompositor = true;
if (mNPZC != null) {
mCompositor.attachNPZC(mNPZC);
}
if (mSurface != null) {
// If we have a valid surface, create the compositor now that we're attached.
// Leave mSurface alone because we'll need it later for onCompositorReady.
onSurfaceChanged(mSurface, mWidth, mHeight);
}
mCompositor.sendToolbarAnimatorMessage(IS_COMPOSITOR_CONTROLLER_OPEN);
}
/* package */ void onCompositorDetached() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mController != null) {
mController.onCompositorDetached();
}
mAttachedCompositor = false;
mCompositorReady = false;
}
/* package */ void handleCompositorMessage(final int message) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
switch (message) {
case COMPOSITOR_CONTROLLER_OPEN: {
if (isCompositorReady()) {
return;
}
// Delay calling onCompositorReady to avoid deadlock due
// to synchronous call to the compositor.
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
onCompositorReady();
}
});
break;
}
case FIRST_PAINT: {
if (mController != null) {
mController.onFirstPaint();
}
break;
}
case LAYERS_UPDATED: {
if (mController != null) {
mController.notifyDrawCallbacks();
}
break;
}
case STATIC_TOOLBAR_READY:
case TOOLBAR_SHOW: {
if (mToolbar != null) {
mToolbar.handleToolbarAnimatorMessage(message);
// Update window bounds due to toolbar visibility change.
onWindowBoundsChanged();
}
break;
}
default: {
if (mToolbar != null) {
mToolbar.handleToolbarAnimatorMessage(message);
} else {
Log.w(LOGTAG, "Unexpected message: " + message);
}
break;
}
}
}
/* package */ void recvScreenPixels(int width, int height, int[] pixels) {
if (mController != null) {
mController.recvScreenPixels(width, height, pixels);
}
}
/* package */ boolean isCompositorReady() {
return mCompositorReady;
}
/* package */ void onCompositorReady() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
mCompositorReady = true;
if (mController != null) {
mController.onCompositorReady();
}
if (mSurface != null) {
// If we have a valid surface, resume the
// compositor now that the compositor is ready.
onSurfaceChanged(mSurface, mWidth, mHeight);
mSurface = null;
}
if (mToolbar != null) {
mToolbar.onCompositorReady();
}
}
/* package */ void updateOverscrollVelocity(final float x, final float y) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mOverscroll == null) {
return;
}
// Multiply the velocity by 1000 to match what was done in JPZ.
mOverscroll.setVelocity(x * 1000.0f, OverscrollEdgeEffect.AXIS_X);
mOverscroll.setVelocity(y * 1000.0f, OverscrollEdgeEffect.AXIS_Y);
}
/* package */ void updateOverscrollOffset(final float x, final float y) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mOverscroll == null) {
return;
}
mOverscroll.setDistance(x, OverscrollEdgeEffect.AXIS_X);
mOverscroll.setDistance(y, OverscrollEdgeEffect.AXIS_Y);
}
protected void setShouldPinOnScreen(final boolean pinned) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
if (mToolbar != null) {
mToolbar.setPinned(pinned, DynamicToolbarAnimator.PinReason.CARET_DRAG);
}
}
/* package */ void onMetricsChanged(final float scrollX, final float scrollY,
final float zoom) {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
mViewportLeft = scrollX;
mViewportTop = scrollY;
mViewportZoom = zoom;
}
/* protected */ void onWindowBoundsChanged() {
if (DEBUG) {
ThreadUtils.assertOnUiThread();
}
final int toolbarHeight;
if (mToolbar != null) {
toolbarHeight = mToolbar.getCurrentToolbarHeight();
} else {
toolbarHeight = 0;
}
mClientTop = mTop + toolbarHeight;
mClientHeight = mHeight - toolbarHeight;
if (mAttachedCompositor) {
mCompositor.onBoundsChanged(mLeft, mClientTop, mWidth, mClientHeight);
}
if (mOverscroll != null) {
mOverscroll.setSize(mWidth, mClientHeight);
}
}
@UiThread
public void onSurfaceChanged(final Surface surface, final int width,
final int height) {
ThreadUtils.assertOnUiThread();
mWidth = width;
mHeight = height;
if (mCompositorReady) {
mCompositor.syncResumeResizeCompositor(width, height, surface);
onWindowBoundsChanged();
return;
}
// We have a valid surface but we're not attached or the compositor
// is not ready; save the surface for later when we're ready.
mSurface = surface;
// Adjust bounds as the last step.
onWindowBoundsChanged();
}
@UiThread
public void onSurfaceDestroyed() {
ThreadUtils.assertOnUiThread();
if (mCompositorReady) {
mCompositor.syncPauseCompositor();
return;
}
// While the surface was valid, we never became attached or the
// compositor never became ready; clear the saved surface.
mSurface = null;
}
@UiThread
public void onScreenOriginChanged(final int left, final int top) {
ThreadUtils.assertOnUiThread();
if (mLeft == left && mTop == top) {
return;
}
mLeft = left;
mTop = top;
onWindowBoundsChanged();
}
}

Просмотреть файл

@ -32,12 +32,12 @@ public final class OverscrollEdgeEffect {
// All four edges of the screen
private final EdgeEffect[] mEdges = new EdgeEffect[4];
private final LayerSession mSession;
private final GeckoSession mSession;
private Runnable mInvalidationCallback;
private int mWidth;
private int mHeight;
/* package */ OverscrollEdgeEffect(final LayerSession session) {
/* package */ OverscrollEdgeEffect(final GeckoSession session) {
mSession = session;
}

Просмотреть файл

@ -24,7 +24,7 @@ public class PanZoomController extends JNIObject {
private static final int EVENT_SOURCE_MOTION = 1;
private static final int EVENT_SOURCE_MOUSE = 2;
private final LayerSession mSession;
private final GeckoSession mSession;
private final Rect mTempRect = new Rect();
private boolean mAttached;
private float mPointerScrollFactor = 64.0f;
@ -149,7 +149,7 @@ public class PanZoomController extends JNIObject {
event.getMetaState(), x, y, event.getButtonState());
}
protected PanZoomController(final LayerSession session) {
protected PanZoomController(final GeckoSession session) {
mSession = session;
enableEventQueue();
}

Просмотреть файл

@ -839,12 +839,12 @@ nsWindow::AndroidView::GetInitData(JSContext* aCx, JS::MutableHandleValue aOut)
* separate from GeckoViewSupport.
*/
class nsWindow::LayerViewSupport final
: public LayerSession::Compositor::Natives<LayerViewSupport>
: public GeckoSession::Compositor::Natives<LayerViewSupport>
{
using LockedWindowPtr = WindowPtr<LayerViewSupport>::Locked;
WindowPtr<LayerViewSupport> mWindow;
LayerSession::Compositor::WeakRef mCompositor;
GeckoSession::Compositor::WeakRef mCompositor;
Atomic<bool, ReleaseAcquire> mCompositorPaused;
jni::Object::GlobalRef mSurface;
@ -882,16 +882,16 @@ class nsWindow::LayerViewSupport final
};
public:
typedef LayerSession::Compositor::Natives<LayerViewSupport> Base;
typedef GeckoSession::Compositor::Natives<LayerViewSupport> Base;
static LayerViewSupport*
FromNative(const LayerSession::Compositor::LocalRef& instance)
FromNative(const GeckoSession::Compositor::LocalRef& instance)
{
return GetNative(instance);
}
LayerViewSupport(NativePtr<LayerViewSupport>* aPtr, nsWindow* aWindow,
const LayerSession::Compositor::LocalRef& aInstance)
const GeckoSession::Compositor::LocalRef& aInstance)
: mWindow(aPtr, aWindow)
, mCompositor(aInstance)
, mCompositorPaused(true)
@ -908,7 +908,7 @@ public:
void OnDetach(already_AddRefed<Runnable> aDisposer)
{
if (RefPtr<nsThread> uiThread = GetAndroidUiThread()) {
LayerSession::Compositor::GlobalRef compositor(mCompositor);
GeckoSession::Compositor::GlobalRef compositor(mCompositor);
if (!compositor) {
return;
}
@ -923,7 +923,7 @@ public:
}
}
const LayerSession::Compositor::Ref& GetJavaCompositor() const
const GeckoSession::Compositor::Ref& GetJavaCompositor() const
{
return mCompositor;
}
@ -1004,7 +1004,7 @@ public:
}
}
void SyncResumeResizeCompositor(const LayerSession::Compositor::LocalRef& aObj,
void SyncResumeResizeCompositor(const GeckoSession::Compositor::LocalRef& aObj,
int32_t aWidth, int32_t aHeight,
jni::Object::Param aSurface)
{
@ -1020,10 +1020,10 @@ public:
class OnResumedEvent : public nsAppShell::Event
{
LayerSession::Compositor::GlobalRef mCompositor;
GeckoSession::Compositor::GlobalRef mCompositor;
public:
explicit OnResumedEvent(LayerSession::Compositor::GlobalRef&& aCompositor)
explicit OnResumedEvent(GeckoSession::Compositor::GlobalRef&& aCompositor)
: mCompositor(std::move(aCompositor))
{}
@ -1033,7 +1033,7 @@ public:
JNIEnv* const env = jni::GetGeckoThreadEnv();
LayerViewSupport* const lvs = GetNative(
LayerSession::Compositor::LocalRef(env, mCompositor));
GeckoSession::Compositor::LocalRef(env, mCompositor));
if (!lvs || !lvs->mWindow) {
env->ExceptionClear();
@ -1128,7 +1128,7 @@ public:
void RecvToolbarAnimatorMessage(int32_t aMessage)
{
auto compositor = LayerSession::Compositor::LocalRef(mCompositor);
auto compositor = GeckoSession::Compositor::LocalRef(mCompositor);
if (compositor) {
compositor->RecvToolbarAnimatorMessage(aMessage);
}
@ -1155,7 +1155,7 @@ public:
MOZ_ASSERT(AndroidBridge::IsJavaUiThread());
auto pixels = mozilla::jni::IntArray::New(aMem.get<int>(), aMem.Size<int>());
auto compositor = LayerSession::Compositor::LocalRef(mCompositor);
auto compositor = GeckoSession::Compositor::LocalRef(mCompositor);
if (compositor) {
compositor->RecvScreenPixels(aSize.width, aSize.height, pixels);
}
@ -1320,8 +1320,8 @@ nsWindow::GeckoViewSupport::Transfer(const GeckoSession::Window::LocalRef& inst,
window.mNPZCSupport.Detach(window.mNPZCSupport->GetJavaNPZC());
}
auto compositor = LayerSession::Compositor::LocalRef(
inst.Env(), LayerSession::Compositor::Ref::From(aCompositor));
auto compositor = GeckoSession::Compositor::LocalRef(
inst.Env(), GeckoSession::Compositor::Ref::From(aCompositor));
if (window.mLayerViewSupport &&
window.mLayerViewSupport->GetJavaCompositor() != compositor) {
window.mLayerViewSupport.Detach(
@ -1354,7 +1354,7 @@ nsWindow::GeckoViewSupport::Transfer(const GeckoSession::Window::LocalRef& inst,
DispatchToUiThread(
"GeckoViewSupport::Transfer",
[compositor = LayerSession::Compositor::GlobalRef(compositor)] {
[compositor = GeckoSession::Compositor::GlobalRef(compositor)] {
compositor->OnCompositorAttached();
});
}
@ -2028,7 +2028,7 @@ nsWindow::UpdateOverscrollVelocity(const float aX, const float aY)
DispatchToUiThread(
"nsWindow::UpdateOverscrollVelocity",
[compositor = LayerSession::Compositor::GlobalRef(compositor),
[compositor = GeckoSession::Compositor::GlobalRef(compositor),
aX, aY] {
compositor->UpdateOverscrollVelocity(aX, aY);
});
@ -2047,7 +2047,7 @@ nsWindow::UpdateOverscrollOffset(const float aX, const float aY)
DispatchToUiThread(
"nsWindow::UpdateOverscrollOffset",
[compositor = LayerSession::Compositor::GlobalRef(compositor),
[compositor = GeckoSession::Compositor::GlobalRef(compositor),
aX, aY] {
compositor->UpdateOverscrollOffset(aX, aY);
});