diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-11-27 22:47:42 +0100 |
---|---|---|
committer | Tomaž Vajngerl <tomaz.vajngerl@collabora.com> | 2014-12-04 23:04:28 +0100 |
commit | 74eae6786334cdf3a456b52b10fd285e2a589813 (patch) | |
tree | 3e072164d6a462bf5ad631925426038e9707d0b0 | |
parent | daa20c9a7f602828927a5f8833bdaf54185f160e (diff) |
android: Fold LayerController into GeckoLayerClient
Change-Id: I6a6e702e243b389f1c487b6b5390f28a4292cc74
10 files changed, 335 insertions, 359 deletions
diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java index 4c5509a3ac4b..e9c2877e2445 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitThread.java @@ -6,8 +6,7 @@ import android.util.DisplayMetrics; import android.util.Log; import org.mozilla.gecko.gfx.GeckoLayerClient; -import org.mozilla.gecko.gfx.ImmutableViewportMetrics; -import org.mozilla.gecko.gfx.LayerController; +import org.mozilla.gecko.gfx.ImmutableViewportMetrics;; import java.util.concurrent.LinkedBlockingQueue; @@ -19,7 +18,6 @@ public class LOKitThread extends Thread { private TileProvider mTileProvider; private ImmutableViewportMetrics mViewportMetrics; private GeckoLayerClient mLayerClient; - private LayerController mController; public LOKitThread() { TileProviderFactory.initialize(); @@ -47,7 +45,7 @@ public class LOKitThread extends Thread { /** Handle the geometry change + draw. */ private void redraw() { - if (mController == null || mTileProvider == null) { + if (mLayerClient == null || mTileProvider == null) { // called too early... return; } @@ -55,16 +53,16 @@ public class LOKitThread extends Thread { draw(); RectF rect = new RectF(0, 0, mTileProvider.getPageWidth(), mTileProvider.getPageHeight()); - mController.setPageRect(rect, rect); - mController.setViewportMetrics(mController.getViewportMetrics()); - mController.setForceRedraw(); + mLayerClient.setPageRect(rect, rect); + mLayerClient.setViewportMetrics(mLayerClient.getViewportMetrics()); + mLayerClient.setForceRedraw(); } /** Invalidate everything + handle the geometry change + draw. */ private void refresh() { Bitmap bitmap = mTileProvider.thumbnail(1000); if (bitmap != null) { - mApplication.getLayerController().getView().changeCheckerboardBitmap(bitmap, mTileProvider.getPageWidth(), mTileProvider.getPageHeight()); + mApplication.getLayerClient().getView().changeCheckerboardBitmap(bitmap, mTileProvider.getPageWidth(), mTileProvider.getPageHeight()); } mLayerClient.clearAndResetlayers(); @@ -83,10 +81,9 @@ public class LOKitThread extends Thread { mApplication = LibreOfficeMainActivity.mAppContext; } - mController = mApplication.getLayerController(); mLayerClient = mApplication.getLayerClient(); - mTileProvider = TileProviderFactory.create(mController, filename); + mTileProvider = TileProviderFactory.create(mLayerClient, filename); boolean isReady = mTileProvider.isReady(); if (isReady) { mLayerClient.setTileProvider(mTileProvider); diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java index 0d404414c546..ec6d1d1237c3 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LOKitTileProvider.java @@ -8,8 +8,8 @@ import org.libreoffice.kit.LibreOfficeKit; import org.libreoffice.kit.Office; import org.mozilla.gecko.gfx.BufferedCairoImage; import org.mozilla.gecko.gfx.CairoImage; +import org.mozilla.gecko.gfx.GeckoLayerClient; import org.mozilla.gecko.gfx.IntSize; -import org.mozilla.gecko.gfx.LayerController; import java.nio.ByteBuffer; @@ -18,7 +18,7 @@ public class LOKitTileProvider implements TileProvider { private static int TILE_SIZE = 256; private Office mOffice; private Document mDocument; - private final LayerController mLayerController; + private final GeckoLayerClient mLayerClient; private final float mTileWidth; private final float mTileHeight; private final String mInputFile; @@ -30,8 +30,8 @@ public class LOKitTileProvider implements TileProvider { private long objectCreationTime = System.currentTimeMillis(); - public LOKitTileProvider(LayerController layerController, String input) { - mLayerController = layerController; + public LOKitTileProvider(GeckoLayerClient layerClient, String input) { + mLayerClient = layerClient; mDPI = (float) LOKitShell.getDpi(); mTileWidth = pixelToTwip(TILE_SIZE, mDPI); mTileHeight = pixelToTwip(TILE_SIZE, mDPI); diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java index 6ca7b4dcf778..991a1533a674 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/LibreOfficeMainActivity.java @@ -3,8 +3,6 @@ package org.libreoffice; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; -import android.content.Intent; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.support.v4.widget.DrawerLayout; @@ -15,14 +13,12 @@ import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; -import android.widget.Button; import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import org.mozilla.gecko.ZoomConstraints; import org.mozilla.gecko.gfx.GeckoLayerClient; -import org.mozilla.gecko.gfx.LayerController; import org.mozilla.gecko.gfx.LayerView; import java.util.ArrayList; @@ -35,7 +31,6 @@ public class LibreOfficeMainActivity extends Activity { public static LibreOfficeMainActivity mAppContext; - private static LayerController mLayerController; private static GeckoLayerClient mLayerClient; private static LOKitThread sLOKitThread; @@ -52,10 +47,6 @@ public class LibreOfficeMainActivity extends Activity { return mLayerClient; } - public static LayerController getLayerController() { - return mLayerController; - } - @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. @@ -130,12 +121,11 @@ public class LibreOfficeMainActivity extends Activity { sLOKitThread.clearQueue(); } - mLayerController = new LayerController(this); - mLayerController.setZoomConstraints(new ZoomConstraints(true)); mLayerClient = new GeckoLayerClient(this); + mLayerClient.setZoomConstraints(new ZoomConstraints(true)); LayerView layerView = (LayerView) findViewById(R.id.layer_view); - mLayerController.setView(layerView); - mLayerController.setLayerClient(mLayerClient); + mLayerClient.setView(layerView); + mLayerClient.notifyReady(); } @Override @@ -167,6 +157,7 @@ public class LibreOfficeMainActivity extends Activity { @Override protected void onDestroy() { Log.i(LOGTAG, "onDestroy.."); + mLayerClient.destroy(); super.onDestroy(); } diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java index eba732fea95b..8fd51b8ca8c6 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/MockTileProvider.java @@ -4,17 +4,17 @@ import android.graphics.Bitmap; import org.mozilla.gecko.gfx.BufferedCairoImage; import org.mozilla.gecko.gfx.CairoImage; +import org.mozilla.gecko.gfx.GeckoLayerClient; import org.mozilla.gecko.gfx.IntSize; -import org.mozilla.gecko.gfx.LayerController; public class MockTileProvider implements TileProvider { private static final int TILE_SIZE = 256; - private final LayerController layerController; + private final GeckoLayerClient mLayerClient; private final String inputFile; - public MockTileProvider(LayerController layerController, String inputFile) { - this.layerController = layerController; - this.inputFile = inputFile; + public MockTileProvider(GeckoLayerClient layerClient, String input) { + mLayerClient = layerClient; + this.inputFile = input; for (int i = 0; i < 5; i++) { String partName = "Part " + i; @@ -52,7 +52,7 @@ public class MockTileProvider implements TileProvider { tileNumber += 1; // 0 to 1 based numbering String imageName = "d" + tileNumber; - Bitmap bitmap = layerController.getView().getDrawable(imageName); + Bitmap bitmap = mLayerClient.getView().getDrawable(imageName); CairoImage image = new BufferedCairoImage(bitmap); @@ -61,7 +61,7 @@ public class MockTileProvider implements TileProvider { @Override public Bitmap thumbnail(int size) { - return layerController.getView().getDrawable("dummy_page"); + return mLayerClient.getView().getDrawable("dummy_page"); } @Override diff --git a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java index 3bfe0b7febf5..b79e56e9414e 100644 --- a/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java +++ b/android/experimental/LOAndroid3/src/java/org/libreoffice/TileProviderFactory.java @@ -2,7 +2,7 @@ package org.libreoffice; import org.libreoffice.kit.LibreOfficeKit; -import org.mozilla.gecko.gfx.LayerController; +import org.mozilla.gecko.gfx.GeckoLayerClient; public class TileProviderFactory { private static TileProviderID currentTileProvider = TileProviderID.LOKIT; @@ -17,11 +17,11 @@ public class TileProviderFactory { } } - public static TileProvider create(LayerController layerController, String filename) { + public static TileProvider create(GeckoLayerClient layerClient, String filename) { if (currentTileProvider == TileProviderID.LOKIT) { - return new LOKitTileProvider(layerController, filename); + return new LOKitTileProvider(layerClient, filename); } else { - return new MockTileProvider(layerController, filename); + return new MockTileProvider(layerClient, filename); } } diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java index b5bb73d1985d..508fb9f12a9c 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/GeckoLayerClient.java @@ -39,62 +39,110 @@ package org.mozilla.gecko.gfx; import android.content.Context; +import android.graphics.Color; +import android.graphics.PointF; import android.graphics.RectF; import android.util.DisplayMetrics; import android.util.Log; +import android.view.GestureDetector; import org.libreoffice.LOEvent; import org.libreoffice.LOEventFactory; import org.libreoffice.LOKitShell; -import org.libreoffice.LibreOfficeMainActivity; import org.libreoffice.TileProvider; +import org.mozilla.gecko.ZoomConstraints; +import org.mozilla.gecko.ui.PanZoomController; +import org.mozilla.gecko.ui.PanZoomTarget; +import org.mozilla.gecko.ui.SimpleScaleGestureDetector; import org.mozilla.gecko.util.FloatUtils; -public class GeckoLayerClient implements LayerView.Listener { - private static final String LOGTAG = "GeckoLayerClient"; +public class GeckoLayerClient implements PanZoomTarget, LayerView.Listener { + private static final String LOGTAG = GeckoLayerClient.class.getSimpleName(); - private LayerController mLayerController; + private LayerRenderer mLayerRenderer; + private boolean mLayerRendererInitialized; + private Context mContext; private IntSize mScreenSize; private IntSize mWindowSize; private DisplayPortMetrics mDisplayPort; + private boolean mRecordDrawTimes; private DrawTimingQueue mDrawTimingQueue; private DynamicTileLayer mRootLayer; - /* The viewport that Gecko is currently displaying. */ + /* The Gecko viewport as per the UI thread. Must be touched only on the UI thread. */ private ImmutableViewportMetrics mGeckoViewport; - /* The viewport that Gecko will display when drawing is finished */ + /* + * The viewport metrics being used to draw the current frame. This is only + * accessed by the compositor thread, and so needs no synchronisation. + */ + private ImmutableViewportMetrics mFrameMetrics; + private ImmutableViewportMetrics mNewGeckoViewport; - private Context mContext; + private boolean mPendingViewportAdjust; + /* The current viewport metrics. + * This is volatile so that we can read and write to it from different threads. + * We avoid synchronization to make getting the viewport metrics from + * the compositor as cheap as possible. The viewport is immutable so + * we don't need to worry about anyone mutating it while we're reading from it. + * Specifically: + * 1) reading mViewportMetrics from any thread is fine without synchronization + * 2) writing to mViewportMetrics requires synchronizing on the layer controller object + * 3) whenver reading multiple fields from mViewportMetrics without synchronization (i.e. in + * case 1 above) you should always frist grab a local copy of the reference, and then use + * that because mViewportMetrics might get reassigned in between reading the different + * fields. */ + private volatile ImmutableViewportMetrics mViewportMetrics; + + private ZoomConstraints mZoomConstraints; + + private boolean mGeckoIsReady; + + /* The new color for the checkerboard. */ + private int mCheckerboardColor = Color.WHITE; + private boolean mCheckerboardShouldShowChecks; + + private final PanZoomController mPanZoomController; + + private LayerView mView; + + private boolean mForceRedraw; + public GeckoLayerClient(Context context) { mContext = context; mScreenSize = new IntSize(0, 0); mWindowSize = new IntSize(0, 0); mDisplayPort = new DisplayPortMetrics(); - mRecordDrawTimes = true; + mRecordDrawTimes = false; mDrawTimingQueue = new DrawTimingQueue(); - } - /** Attaches the root layer to the layer controller so that Gecko appears. */ - public void setLayerController(LayerController layerController) { - LayerView view = layerController.getView(); + mForceRedraw = true; + DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); + mViewportMetrics = new ImmutableViewportMetrics(displayMetrics); + mZoomConstraints = new ZoomConstraints(false); + mCheckerboardShouldShowChecks = true; + + mPanZoomController = new PanZoomController(this); + } - mLayerController = layerController; + public void setView(LayerView v) { + mView = v; + mView.connect(this); + } + public void notifyReady() { + mGeckoIsReady = true; mRootLayer = new DynamicTileLayer(); - view.setListener(this); - layerController.setRoot(mRootLayer); - - if (mGeckoViewport != null) { - layerController.setViewportMetrics(mGeckoViewport); - } + mLayerRenderer = new LayerRenderer(mView); + mView.setListener(this); + mView.setLayerRenderer(mLayerRenderer); sendResizeEventIfNecessary(true); } @@ -108,7 +156,7 @@ public class GeckoLayerClient implements LayerView.Listener { } public void endDrawing(ImmutableViewportMetrics viewportMetrics) { - synchronized (mLayerController) { + synchronized (this) { try { mNewGeckoViewport = viewportMetrics; updateViewport(true); @@ -124,7 +172,7 @@ public class GeckoLayerClient implements LayerView.Listener { // JS-side viewport dimensions override the java-side ones because // java is the One True Source of this information, and allowing JS // to override can lead to race conditions where this data gets clobbered. - FloatSize viewportSize = mLayerController.getViewportSize(); + FloatSize viewportSize = getViewportSize(); mGeckoViewport = mNewGeckoViewport.setViewportSize(viewportSize.width, viewportSize.height); RectF position = mGeckoViewport.getViewport(); @@ -134,12 +182,12 @@ public class GeckoLayerClient implements LayerView.Listener { if (onlyUpdatePageSize) { // Don't adjust page size when zooming unless zoom levels are // approximately equal. - if (FloatUtils.fuzzyEquals(mLayerController.getViewportMetrics().zoomFactor, mGeckoViewport.zoomFactor)) { - mLayerController.setPageRect(mGeckoViewport.getPageRect(), mGeckoViewport.getCssPageRect()); + if (FloatUtils.fuzzyEquals(getViewportMetrics().zoomFactor, mGeckoViewport.zoomFactor)) { + setPageRect(mGeckoViewport.getPageRect(), mGeckoViewport.getCssPageRect()); } } else { - mLayerController.setViewportMetrics(mGeckoViewport); - mLayerController.abortPanZoomAnimation(); + setViewportMetrics(mGeckoViewport); + abortPanZoomAnimation(); } } @@ -171,13 +219,12 @@ public class GeckoLayerClient implements LayerView.Listener { } void adjustViewport(DisplayPortMetrics displayPort) { - ImmutableViewportMetrics metrics = mLayerController.getViewportMetrics(); + ImmutableViewportMetrics metrics = getViewportMetrics(); ImmutableViewportMetrics clampedMetrics = metrics.clamp(); if (displayPort == null) { - displayPort = DisplayPortCalculator.calculate(metrics, - mLayerController.getPanZoomController().getVelocityVector()); + displayPort = DisplayPortCalculator.calculate(metrics, getPanZoomController().getVelocityVector()); } mDisplayPort = displayPort; @@ -190,21 +237,22 @@ public class GeckoLayerClient implements LayerView.Listener { LOKitShell.sendEvent(LOEventFactory.viewport(clampedMetrics)); } - /** This function is invoked by Gecko via JNI; be careful when modifying signature. + /** + * This function is invoked by Gecko via JNI; be careful when modifying signature. * The compositor invokes this function whenever it determines that the page size * has changed (based on the information it gets from layout). If setFirstPaintViewport * is invoked on a frame, then this function will not be. For any given frame, this * function will be invoked before syncViewportInfo. */ public void setPageSize(float zoom, float pageWidth, float pageHeight, float cssPageWidth, float cssPageHeight) { - synchronized (mLayerController) { + synchronized (this) { // adjust the page dimensions to account for differences in zoom // between the rendered content (which is what the compositor tells us) // and our zoom level (which may have diverged). RectF pageRect = new RectF(0.0f, 0.0f, pageWidth, pageHeight); RectF cssPageRect = new RectF(0.0f, 0.0f, cssPageWidth, cssPageHeight); - float ourZoom = mLayerController.getViewportMetrics().zoomFactor; - mLayerController.setPageRect(RectUtils.scale(pageRect, ourZoom / zoom), cssPageRect); + float ourZoom = getViewportMetrics().zoomFactor; + setPageRect(RectUtils.scale(pageRect, ourZoom / zoom), cssPageRect); // Here the page size of the document has changed, but the document being displayed // is still the same. Therefore, we don't need to send anything to browser.js; any // changes we need to make to the display port will get sent the next time we call @@ -214,7 +262,7 @@ public class GeckoLayerClient implements LayerView.Listener { public void geometryChanged() { sendResizeEventIfNecessary(false); - if (mLayerController.getRedrawHint()) { + if (getRedrawHint()) { adjustViewport(null); } } @@ -249,17 +297,224 @@ public class GeckoLayerClient implements LayerView.Listener { } public void reevaluateTiles() { - mRootLayer.reevaluateTiles(mLayerController.getViewportMetrics()); + mRootLayer.reevaluateTiles(getViewportMetrics()); } public void clearAndResetlayers() { mRootLayer.clearAndReset(); } + public void destroy() { + mPanZoomController.destroy(); + } + + public void setForceRedraw() { + mForceRedraw = true; + notifyLayerClientOfGeometryChange(); + } + + public LayerView getView() { + return mView; + } + + public Context getContext() { + return mContext; + } + + public ImmutableViewportMetrics getViewportMetrics() { + return mViewportMetrics; + } + + /** + * Sets the entire viewport metrics at once. + * You must hold the monitor while calling this. + */ + public void setViewportMetrics(ImmutableViewportMetrics viewport) { + mViewportMetrics = viewport; + mView.requestRender(); + notifyLayerClientOfGeometryChange(); + } + + public Object getLock() { + return this; + } + + public FloatSize getViewportSize() { + return mViewportMetrics.getSize(); + } + + /** + * The view calls this function to indicate that the viewport changed size. It must hold the + * monitor while calling it. + * <p/> + * TODO: Refactor this to use an interface. Expose that interface only to the view and not + * to the layer client. That way, the layer client won't be tempted to call this, which might + * result in an infinite loop. + */ + public void setViewportSize(FloatSize size) { + mViewportMetrics = mViewportMetrics.setViewportSize(size.width, size.height); + viewportSizeChanged(); + } + + public PanZoomController getPanZoomController() { + return mPanZoomController; + } + + public GestureDetector.OnGestureListener getGestureListener() { + return mPanZoomController; + } + + public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() { + return mPanZoomController; + } + + public GestureDetector.OnDoubleTapListener getDoubleTapListener() { + return mPanZoomController; + } + + /** + * Sets the current page rect. You must hold the monitor while calling this. + */ + public void setPageRect(RectF rect, RectF cssRect) { + // Since the "rect" is always just a multiple of "cssRect" we don't need to + // check both; this function assumes that both "rect" and "cssRect" are relative + // the zoom factor in mViewportMetrics. + if (mViewportMetrics.getCssPageRect().equals(cssRect)) + return; + + mViewportMetrics = mViewportMetrics.setPageRect(rect, cssRect); + + // Page size is owned by the layer client, so no need to notify it of + // this change. + + mView.post(new Runnable() { + public void run() { + mPanZoomController.pageRectUpdated(); + mView.requestRender(); + } + }); + } + + public void setAnimationTarget(ImmutableViewportMetrics viewport) { + // We know what the final viewport of the animation is going to be, so + // immediately request a draw of that area by setting the display port + // accordingly. This way we should have the content pre-rendered by the + // time the animation is done. + DisplayPortMetrics displayPort = DisplayPortCalculator.calculate(viewport, null); + adjustViewport(displayPort); + } + + public boolean post(Runnable action) { + return mView.post(action); + } + + private void notifyLayerClientOfGeometryChange() { + geometryChanged(); + } + + /** + * Aborts any pan/zoom animation that is currently in progress. + */ + public void abortPanZoomAnimation() { + if (mPanZoomController != null) { + mView.post(new Runnable() { + public void run() { + mPanZoomController.abortAnimation(); + } + }); + } + } + + /** + * Returns true if this controller is fine with performing a redraw operation or false if it + * would prefer that the action didn't take place. + */ + public boolean getRedrawHint() { + if (mForceRedraw) { + mForceRedraw = false; + return true; + } + + if (!mPanZoomController.getRedrawHint()) { + return false; + } + + return DisplayPortCalculator.aboutToCheckerboard(mViewportMetrics, mPanZoomController.getVelocityVector(), getDisplayPort()); + } + + /** + * Converts a point from layer view coordinates to layer coordinates. In other words, given a + * point measured in pixels from the top left corner of the layer view, returns the point in + * pixels measured from the last scroll position we sent to Gecko, in CSS pixels. Assuming the + * events being sent to Gecko are processed in FIFO order, this calculation should always be + * correct. + */ + public PointF convertViewPointToLayerPoint(PointF viewPoint) { + ImmutableViewportMetrics viewportMetrics = mViewportMetrics; + PointF origin = viewportMetrics.getOrigin(); + float zoom = viewportMetrics.zoomFactor; + ImmutableViewportMetrics geckoViewport = getGeckoViewportMetrics(); + PointF geckoOrigin = geckoViewport.getOrigin(); + float geckoZoom = geckoViewport.zoomFactor; + + // viewPoint + origin gives the coordinate in device pixels from the top-left corner of the page. + // Divided by zoom, this gives us the coordinate in CSS pixels from the top-left corner of the page. + // geckoOrigin / geckoZoom is where Gecko thinks it is (scrollTo position) in CSS pixels from + // the top-left corner of the page. Subtracting the two gives us the offset of the viewPoint from + // the current Gecko coordinate in CSS pixels. + PointF layerPoint = new PointF( + ((viewPoint.x + origin.x) / zoom) - (geckoOrigin.x / geckoZoom), + ((viewPoint.y + origin.y) / zoom) - (geckoOrigin.y / geckoZoom)); + + return layerPoint; + } + + /** + * Retrieves whether we should show checkerboard checks or not. + */ + public boolean checkerboardShouldShowChecks() { + return mCheckerboardShouldShowChecks; + } + + /** + * Retrieves the color that the checkerboard should be. + */ + public int getCheckerboardColor() { + return mCheckerboardColor; + } + + /** + * Sets a new color for the checkerboard. + */ + public void setCheckerboardColor(int newColor) { + mCheckerboardColor = newColor; + mView.requestRender(); + } + + /** + * Sets whether or not the checkerboard should show checkmarks. + */ + public void setCheckerboardShowChecks(boolean showChecks) { + mCheckerboardShouldShowChecks = showChecks; + mView.requestRender(); + } + + public ZoomConstraints getZoomConstraints() { + return mZoomConstraints; + } + + public void setZoomConstraints(ZoomConstraints constraints) { + mZoomConstraints = constraints; + } + private class AdjustRunnable implements Runnable { public void run() { mPendingViewportAdjust = false; adjustViewport(null); } } + + public Layer getRoot() { + return mRootLayer; + } }
\ No newline at end of file diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java deleted file mode 100644 index c641c756eb47..000000000000 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerController.java +++ /dev/null @@ -1,265 +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.gecko.gfx; - -import android.content.Context; -import android.graphics.Color; -import android.graphics.PointF; -import android.graphics.RectF; -import android.util.DisplayMetrics; -import android.view.GestureDetector; - -import org.mozilla.gecko.ZoomConstraints; -import org.mozilla.gecko.ui.PanZoomController; -import org.mozilla.gecko.ui.PanZoomTarget; -import org.mozilla.gecko.ui.SimpleScaleGestureDetector; - -/** - * The layer controller manages a tile that represents the visible page. It does panning and - * zooming natively by delegating to a panning/zooming controller. Touch events can be dispatched - * to a higher-level view. - * - * Many methods require that the monitor be held, with a synchronized (controller) { ... } block. - */ -public class LayerController implements PanZoomTarget { - private static final String LOGTAG = "GeckoLayerController"; - - private Layer mRootLayer; /* The root layer. */ - private LayerView mView; /* The main rendering view. */ - private Context mContext; /* The current context. */ - - /* This is volatile so that we can read and write to it from different threads. - * We avoid synchronization to make getting the viewport metrics from - * the compositor as cheap as possible. The viewport is immutable so - * we don't need to worry about anyone mutating it while we're reading from it. - * Specifically: - * 1) reading mViewportMetrics from any thread is fine without synchronization - * 2) writing to mViewportMetrics requires synchronizing on the layer controller object - * 3) whenver reading multiple fields from mViewportMetrics without synchronization (i.e. in - * case 1 above) you should always frist grab a local copy of the reference, and then use - * that because mViewportMetrics might get reassigned in between reading the different - * fields. */ - private volatile ImmutableViewportMetrics mViewportMetrics; /* The current viewport metrics. */ - - /* - * The panning and zooming controller, which interprets pan and zoom gestures for us and - * updates our visible rect appropriately. - */ - private PanZoomController mPanZoomController; - - private GeckoLayerClient mLayerClient; /* The layer client. */ - - /* The new color for the checkerboard. */ - private int mCheckerboardColor = Color.WHITE; - private boolean mCheckerboardShouldShowChecks; - - private ZoomConstraints mZoomConstraints; - - private boolean mForceRedraw; - - public LayerController(Context context) { - mContext = context; - mForceRedraw = true; - DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); - mViewportMetrics = new ImmutableViewportMetrics(displayMetrics); - mPanZoomController = new PanZoomController(this); - mCheckerboardShouldShowChecks = true; - mZoomConstraints = new ZoomConstraints(false); - } - - public void setView(LayerView v) { - mView = v; - mView.connect(this); - } - - public void setRoot(Layer layer) { mRootLayer = layer; } - - public void setLayerClient(GeckoLayerClient layerClient) { - mLayerClient = layerClient; - layerClient.setLayerController(this); - } - - public void destroy() { - mPanZoomController.destroy(); - } - - public void setForceRedraw() { - mForceRedraw = true; - notifyLayerClientOfGeometryChange(); - } - - public Layer getRoot() { return mRootLayer; } - public LayerView getView() { return mView; } - public Context getContext() { return mContext; } - public ImmutableViewportMetrics getViewportMetrics() { return mViewportMetrics; } - public Object getLock() { return this; } - - public FloatSize getViewportSize() { - return mViewportMetrics.getSize(); - } - - public PanZoomController getPanZoomController() { return mPanZoomController; } - public GestureDetector.OnGestureListener getGestureListener() { return mPanZoomController; } - public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() { - return mPanZoomController; - } - public GestureDetector.OnDoubleTapListener getDoubleTapListener() { return mPanZoomController; } - - /** - * The view calls this function to indicate that the viewport changed size. It must hold the - * monitor while calling it. - * - * TODO: Refactor this to use an interface. Expose that interface only to the view and not - * to the layer client. That way, the layer client won't be tempted to call this, which might - * result in an infinite loop. - */ - public void setViewportSize(FloatSize size) { - mViewportMetrics = mViewportMetrics.setViewportSize(size.width, size.height); - - if (mLayerClient != null) { - mLayerClient.viewportSizeChanged(); - } - } - - /** Sets the current page rect. You must hold the monitor while calling this. */ - public void setPageRect(RectF rect, RectF cssRect) { - // Since the "rect" is always just a multiple of "cssRect" we don't need to - // check both; this function assumes that both "rect" and "cssRect" are relative - // the zoom factor in mViewportMetrics. - if (mViewportMetrics.getCssPageRect().equals(cssRect)) - return; - - mViewportMetrics = mViewportMetrics.setPageRect(rect, cssRect); - - // Page size is owned by the layer client, so no need to notify it of - // this change. - - mView.post(new Runnable() { - public void run() { - mPanZoomController.pageRectUpdated(); - mView.requestRender(); - } - }); - } - - /** - * Sets the entire viewport metrics at once. - * You must hold the monitor while calling this. - */ - public void setViewportMetrics(ImmutableViewportMetrics viewport) { - mViewportMetrics = viewport; - mView.requestRender(); - notifyLayerClientOfGeometryChange(); - } - - public void setAnimationTarget(ImmutableViewportMetrics viewport) { - if (mLayerClient != null) { - // We know what the final viewport of the animation is going to be, so - // immediately request a draw of that area by setting the display port - // accordingly. This way we should have the content pre-rendered by the - // time the animation is done. - DisplayPortMetrics displayPort = DisplayPortCalculator.calculate(viewport, null); - mLayerClient.adjustViewport(displayPort); - } - } - - public boolean post(Runnable action) { return mView.post(action); } - - private void notifyLayerClientOfGeometryChange() { - if (mLayerClient != null) - mLayerClient.geometryChanged(); - } - - /** Aborts any pan/zoom animation that is currently in progress. */ - public void abortPanZoomAnimation() { - if (mPanZoomController != null) { - mView.post(new Runnable() { - public void run() { - mPanZoomController.abortAnimation(); - } - }); - } - } - - /** - * Returns true if this controller is fine with performing a redraw operation or false if it - * would prefer that the action didn't take place. - */ - public boolean getRedrawHint() { - if (mForceRedraw) { - mForceRedraw = false; - return true; - } - - if (!mPanZoomController.getRedrawHint()) { - return false; - } - - return DisplayPortCalculator.aboutToCheckerboard(mViewportMetrics, - mPanZoomController.getVelocityVector(), mLayerClient.getDisplayPort()); - } - - /** - * Converts a point from layer view coordinates to layer coordinates. In other words, given a - * point measured in pixels from the top left corner of the layer view, returns the point in - * pixels measured from the last scroll position we sent to Gecko, in CSS pixels. Assuming the - * events being sent to Gecko are processed in FIFO order, this calculation should always be - * correct. - */ - public PointF convertViewPointToLayerPoint(PointF viewPoint) { - if (mLayerClient == null) { - return null; - } - - ImmutableViewportMetrics viewportMetrics = mViewportMetrics; - PointF origin = viewportMetrics.getOrigin(); - float zoom = viewportMetrics.zoomFactor; - ImmutableViewportMetrics geckoViewport = mLayerClient.getGeckoViewportMetrics(); - PointF geckoOrigin = geckoViewport.getOrigin(); - float geckoZoom = geckoViewport.zoomFactor; - - // viewPoint + origin gives the coordinate in device pixels from the top-left corner of the page. - // Divided by zoom, this gives us the coordinate in CSS pixels from the top-left corner of the page. - // geckoOrigin / geckoZoom is where Gecko thinks it is (scrollTo position) in CSS pixels from - // the top-left corner of the page. Subtracting the two gives us the offset of the viewPoint from - // the current Gecko coordinate in CSS pixels. - PointF layerPoint = new PointF( - ((viewPoint.x + origin.x) / zoom) - (geckoOrigin.x / geckoZoom), - ((viewPoint.y + origin.y) / zoom) - (geckoOrigin.y / geckoZoom)); - - return layerPoint; - } - - /** Retrieves whether we should show checkerboard checks or not. */ - public boolean checkerboardShouldShowChecks() { - return mCheckerboardShouldShowChecks; - } - - /** Retrieves the color that the checkerboard should be. */ - public int getCheckerboardColor() { - return mCheckerboardColor; - } - - /** Sets whether or not the checkerboard should show checkmarks. */ - public void setCheckerboardShowChecks(boolean showChecks) { - mCheckerboardShouldShowChecks = showChecks; - mView.requestRender(); - } - - /** Sets a new color for the checkerboard. */ - public void setCheckerboardColor(int newColor) { - mCheckerboardColor = newColor; - mView.requestRender(); - } - - public void setZoomConstraints(ZoomConstraints constraints) { - mZoomConstraints = constraints; - } - - public ZoomConstraints getZoomConstraints() { - return mZoomConstraints; - } -} diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java index 9dd3f499f4d0..feb9c09e824a 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerRenderer.java @@ -158,8 +158,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer { public LayerRenderer(LayerView view) { mView = view; - LayerController controller = view.getController(); - CairoImage backgroundImage = new BufferedCairoImage(view.getBackgroundPattern()); mBackgroundLayer = new SingleTileLayer(true, backgroundImage); @@ -283,8 +281,8 @@ public class LayerRenderer implements GLSurfaceView.Renderer { * Called whenever a new frame is about to be drawn. */ public void onDrawFrame(GL10 gl) { - Frame frame = createFrame(mView.getController().getViewportMetrics()); - synchronized (mView.getController()) { + Frame frame = createFrame(mView.getLayerClient().getViewportMetrics()); + synchronized (mView.getLayerClient()) { frame.beginDrawing(); frame.drawBackground(); frame.drawRootLayer(); @@ -498,7 +496,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer { mUpdated = true; - Layer rootLayer = mView.getController().getRoot(); + Layer rootLayer = mView.getLayerClient().getRoot(); if (!mPageContext.fuzzyEquals(mLastPageContext)) { // the viewport or page changed, so show the scrollbars again @@ -571,7 +569,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer { GLES20.glDisable(GLES20.GL_SCISSOR_TEST); /* Update background color. */ - mBackgroundColor = mView.getController().getCheckerboardColor(); + mBackgroundColor = mView.getLayerClient().getCheckerboardColor(); /* Clear to the page background colour. The bits set here need to * match up with those used in gfx/layers/opengl/LayerManagerOGL.cpp. @@ -596,9 +594,9 @@ public class LayerRenderer implements GLSurfaceView.Renderer { /* Draw the 'checkerboard'. We use gfx.show_checkerboard_pattern to * determine whether to draw the screenshot layer. */ - if (mView.getController().checkerboardShouldShowChecks()) { + if (mView.getLayerClient().checkerboardShouldShowChecks()) { /* Find the area the root layer will render into, to mask the checkerboard layer */ - Rect rootMask = getMaskForLayer(mView.getController().getRoot()); + Rect rootMask = getMaskForLayer(mView.getLayerClient().getRoot()); mScreenshotLayer.setMask(rootMask); /* Scissor around the page-rect, in case the page has shrunk @@ -611,7 +609,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer { // Draws the layer the client added to us. void drawRootLayer() { - Layer rootLayer = mView.getController().getRoot(); + Layer rootLayer = mView.getLayerClient().getRoot(); if (rootLayer == null) { return; } @@ -643,7 +641,7 @@ public class LayerRenderer implements GLSurfaceView.Renderer { mHorizScrollLayer.draw(mPageContext); /* Measure how much of the screen is checkerboarding */ - Layer rootLayer = mView.getController().getRoot(); + Layer rootLayer = mView.getLayerClient().getRoot(); if ((rootLayer != null) && (mProfileRender || PanningPerfAPI.isRecordingCheckerboard())) { // Find out how much of the viewport area is valid diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java index 863157aa252c..4d23cf42d68f 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/LayerView.java @@ -42,7 +42,7 @@ import java.nio.IntBuffer; public class LayerView extends FrameLayout { private static String LOGTAG = "GeckoLayerView"; - private LayerController mController; + private GeckoLayerClient mLayerClient; private TouchEventHandler mTouchEventHandler; private GLController mGLController; private InputConnectionHandler mInputConnectionHandler; @@ -100,9 +100,9 @@ public class LayerView extends FrameLayout { mGLController = new GLController(this); } - void connect(LayerController controller) { - mController = controller; - mTouchEventHandler = new TouchEventHandler(getContext(), this, mController); + void connect(GeckoLayerClient layerClient) { + mLayerClient = layerClient; + mTouchEventHandler = new TouchEventHandler(getContext(), this, layerClient); mRenderer = new LayerRenderer(this); mInputConnectionHandler = null; @@ -124,12 +124,12 @@ public class LayerView extends FrameLayout { return mTouchEventHandler.handleEvent(event); } - public LayerController getController() { return mController; } + public GeckoLayerClient getLayerClient() { return mLayerClient; } public TouchEventHandler getTouchEventHandler() { return mTouchEventHandler; } /** The LayerRenderer calls this to indicate that the window has changed size. */ public void setViewportSize(IntSize size) { - mController.setViewportSize(new FloatSize(size)); + mLayerClient.setViewportSize(new FloatSize(size)); } @Override @@ -307,7 +307,7 @@ public class LayerView extends FrameLayout { /** This function is invoked by Gecko (compositor thread) via JNI; be careful when modifying signature. */ public static GLController registerCxxCompositor() { try { - LayerView layerView = LibreOfficeMainActivity.mAppContext.getLayerController().getView(); + LayerView layerView = LibreOfficeMainActivity.mAppContext.getLayerClient().getView(); layerView.mListener.compositorCreated(); return layerView.getGLController(); } catch (Exception e) { diff --git a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java index b93b5f0a1ff6..f0fe21baf0c4 100644 --- a/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java +++ b/android/experimental/LOAndroid3/src/java/org/mozilla/gecko/gfx/TouchEventHandler.java @@ -123,17 +123,17 @@ public final class TouchEventHandler { // processed. (n is the absolute value of the balance.) private int mProcessingBalance; - TouchEventHandler(Context context, LayerView view, LayerController controller) { + TouchEventHandler(Context context, LayerView view, GeckoLayerClient layerClient) { mView = view; mEventQueue = new LinkedList<MotionEvent>(); - mGestureDetector = new GestureDetector(context, controller.getGestureListener()); - mScaleGestureDetector = new SimpleScaleGestureDetector(controller.getScaleGestureListener()); - mPanZoomController = controller.getPanZoomController(); + mGestureDetector = new GestureDetector(context, layerClient.getGestureListener()); + mScaleGestureDetector = new SimpleScaleGestureDetector(layerClient.getScaleGestureListener()); + mPanZoomController = layerClient.getPanZoomController(); mListenerTimeoutProcessor = new ListenerTimeoutProcessor(); mDispatchEvents = true; - mGestureDetector.setOnDoubleTapListener(controller.getDoubleTapListener()); + mGestureDetector.setOnDoubleTapListener(layerClient.getDoubleTapListener()); } /* This function MUST be called on the UI thread */ |