зеркало из https://github.com/mozilla/gecko-dev.git
Bug 777351 - Fold LayerController into GeckoLayerClient. r=sriram
This commit is contained in:
Родитель
f94834ff5e
Коммит
4f27b0d08c
|
@ -222,7 +222,7 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
|||
int popupWidth = RelativeLayout.LayoutParams.FILL_PARENT;
|
||||
int popupLeft = left < 0 ? 0 : left;
|
||||
|
||||
FloatSize viewport = GeckoApp.mAppContext.getLayerController().getViewportSize();
|
||||
FloatSize viewport = GeckoApp.mAppContext.getLayerClient().getViewportSize();
|
||||
|
||||
// For autocomplete suggestions, if the input is smaller than the screen-width,
|
||||
// shrink the popup's width. Otherwise, keep it as FILL_PARENT.
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.mozilla.gecko;
|
|||
import org.mozilla.gecko.db.BrowserDB;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.Layer;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PluginLayer;
|
||||
import org.mozilla.gecko.gfx.PointUtils;
|
||||
|
@ -154,7 +153,6 @@ abstract public class GeckoApp
|
|||
protected FormAssistPopup mFormAssistPopup;
|
||||
protected TabsPanel mTabsPanel;
|
||||
|
||||
private LayerController mLayerController;
|
||||
private GeckoLayerClient mLayerClient;
|
||||
private AbsoluteLayout mPluginContainer;
|
||||
|
||||
|
@ -856,10 +854,10 @@ abstract public class GeckoApp
|
|||
tab.setCheckerboardColor(Color.WHITE);
|
||||
}
|
||||
|
||||
// Sync up the LayerController and the tab if the tab's
|
||||
// Sync up the GeckoLayerClient and the tab if the tab's
|
||||
// currently displayed.
|
||||
if (getLayerController() != null && Tabs.getInstance().isSelectedTab(tab)) {
|
||||
getLayerController().setCheckerboardColor(tab.getCheckerboardColor());
|
||||
if (getLayerClient() != null && Tabs.getInstance().isSelectedTab(tab)) {
|
||||
getLayerClient().setCheckerboardColor(tab.getCheckerboardColor());
|
||||
}
|
||||
} else if (event.equals("DOMTitleChanged")) {
|
||||
final int tabId = message.getInt("tabID");
|
||||
|
@ -1002,10 +1000,10 @@ abstract public class GeckoApp
|
|||
if (tab == null)
|
||||
return;
|
||||
tab.setZoomConstraints(new ZoomConstraints(message));
|
||||
// Sync up the LayerController and the tab if the tab's currently displayed.
|
||||
LayerController controller = getLayerController();
|
||||
if (controller != null && Tabs.getInstance().isSelectedTab(tab)) {
|
||||
controller.setZoomConstraints(tab.getZoomConstraints());
|
||||
// Sync up the GeckoLayerClient and the tab if the tab is currently displayed.
|
||||
GeckoLayerClient layerClient = getLayerClient();
|
||||
if (layerClient != null && Tabs.getInstance().isSelectedTab(tab)) {
|
||||
layerClient.setZoomConstraints(tab.getZoomConstraints());
|
||||
}
|
||||
} else if (event.equals("Tab:HasTouchListener")) {
|
||||
int tabId = message.getInt("tabID");
|
||||
|
@ -1014,7 +1012,7 @@ abstract public class GeckoApp
|
|||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
mLayerController.getView().getTouchEventHandler().setWaitForTouchListeners(true);
|
||||
mLayerClient.getView().getTouchEventHandler().setWaitForTouchListeners(true);
|
||||
}
|
||||
});
|
||||
} else if (event.equals("Session:StatePurged")) {
|
||||
|
@ -1214,7 +1212,7 @@ abstract public class GeckoApp
|
|||
tab.updateIdentityData(null);
|
||||
tab.setReaderEnabled(false);
|
||||
if (Tabs.getInstance().isSelectedTab(tab))
|
||||
getLayerController().getView().getRenderer().resetCheckerboard();
|
||||
getLayerClient().getView().getRenderer().resetCheckerboard();
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START, showProgress);
|
||||
|
@ -1351,14 +1349,14 @@ abstract public class GeckoApp
|
|||
|
||||
PluginLayer layer = (PluginLayer) tab.getPluginLayer(view);
|
||||
if (layer == null) {
|
||||
layer = new PluginLayer(view, rect, mLayerController.getView().getRenderer().getMaxTextureSize());
|
||||
layer = new PluginLayer(view, rect, mLayerClient.getView().getRenderer().getMaxTextureSize());
|
||||
tab.addPluginLayer(view, layer);
|
||||
} else {
|
||||
layer.reset(rect);
|
||||
layer.setVisible(true);
|
||||
}
|
||||
|
||||
mLayerController.getView().addLayer(layer);
|
||||
mLayerClient.getView().addLayer(layer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1380,7 +1378,7 @@ abstract public class GeckoApp
|
|||
// a deadlock, see comment below in FullScreenHolder
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mLayerController.getView().setVisibility(View.VISIBLE);
|
||||
mLayerClient.getView().setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1435,19 +1433,19 @@ abstract public class GeckoApp
|
|||
}
|
||||
|
||||
private void hidePluginLayer(Layer layer) {
|
||||
LayerView layerView = mLayerController.getView();
|
||||
LayerView layerView = mLayerClient.getView();
|
||||
layerView.removeLayer(layer);
|
||||
layerView.requestRender();
|
||||
}
|
||||
|
||||
private void showPluginLayer(Layer layer) {
|
||||
LayerView layerView = mLayerController.getView();
|
||||
LayerView layerView = mLayerClient.getView();
|
||||
layerView.addLayer(layer);
|
||||
layerView.requestRender();
|
||||
}
|
||||
|
||||
public void requestRender() {
|
||||
mLayerController.getView().requestRender();
|
||||
mLayerClient.getView().requestRender();
|
||||
}
|
||||
|
||||
public void hidePlugins(Tab tab) {
|
||||
|
@ -1663,23 +1661,9 @@ abstract public class GeckoApp
|
|||
cameraView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||
}
|
||||
|
||||
if (mLayerController == null) {
|
||||
/*
|
||||
* Create a layer client, but don't hook it up to the layer controller yet.
|
||||
*/
|
||||
if (mLayerClient == null) {
|
||||
mLayerClient = new GeckoLayerClient(this);
|
||||
|
||||
/*
|
||||
* Hook a placeholder layer client up to the layer controller so that the user can pan
|
||||
* and zoom a cached screenshot of the previous page. This call will return null if
|
||||
* there is no cached screenshot; in that case, we have no choice but to display a
|
||||
* checkerboard.
|
||||
*
|
||||
* TODO: Fall back to a built-in screenshot of the Fennec Start page for a nice first-
|
||||
* run experience, perhaps?
|
||||
*/
|
||||
mLayerController = new LayerController(this);
|
||||
mLayerController.setView((LayerView)findViewById(R.id.layer_view));
|
||||
mLayerClient.setView((LayerView)findViewById(R.id.layer_view));
|
||||
}
|
||||
|
||||
mPluginContainer = (AbsoluteLayout) findViewById(R.id.plugin_container);
|
||||
|
@ -2096,8 +2080,6 @@ abstract public class GeckoApp
|
|||
|
||||
deleteTempFiles();
|
||||
|
||||
if (mLayerController != null)
|
||||
mLayerController.destroy();
|
||||
if (mLayerClient != null)
|
||||
mLayerClient.destroy();
|
||||
if (mDoorHangerPopup != null)
|
||||
|
@ -2565,7 +2547,6 @@ abstract public class GeckoApp
|
|||
|
||||
/* This method is referenced by Robocop via reflection. */
|
||||
public GeckoLayerClient getLayerClient() { return mLayerClient; }
|
||||
public LayerController getLayerController() { return mLayerController; }
|
||||
|
||||
public AbsoluteLayout getPluginContainer() { return mPluginContainer; }
|
||||
|
||||
|
@ -2611,10 +2592,10 @@ abstract public class GeckoApp
|
|||
}
|
||||
|
||||
private void connectGeckoLayerClient() {
|
||||
LayerController layerController = getLayerController();
|
||||
layerController.setLayerClient(mLayerClient);
|
||||
GeckoLayerClient layerClient = getLayerClient();
|
||||
layerClient.notifyGeckoReady();
|
||||
|
||||
layerController.getView().getTouchEventHandler().setOnTouchListener(new ContentTouchListener() {
|
||||
layerClient.getView().getTouchEventHandler().setOnTouchListener(new ContentTouchListener() {
|
||||
private PointF initialPoint = null;
|
||||
|
||||
@Override
|
||||
|
@ -2699,7 +2680,7 @@ abstract public class GeckoApp
|
|||
|
||||
mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mLayerController.getView().setVisibility(View.INVISIBLE);
|
||||
mLayerClient.getView().setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import org.mozilla.gecko.gfx.GeckoLayerClient;
|
|||
import org.mozilla.gecko.gfx.GfxInfoThread;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
import org.mozilla.gecko.gfx.IntSize;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.RectUtils;
|
||||
import org.mozilla.gecko.gfx.ScreenshotLayer;
|
||||
|
@ -539,11 +538,11 @@ public class GeckoAppShell
|
|||
|
||||
// Called on the UI thread after Gecko loads.
|
||||
private static void geckoLoaded() {
|
||||
final LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
LayerView v = layerController.getView();
|
||||
final GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
LayerView v = layerClient.getView();
|
||||
mInputConnection = GeckoInputConnection.create(v);
|
||||
v.setInputConnectionHandler(mInputConnection);
|
||||
layerController.setForceRedraw();
|
||||
layerClient.setForceRedraw();
|
||||
}
|
||||
|
||||
static void sendPendingEventsToGecko() {
|
||||
|
@ -1425,8 +1424,8 @@ public class GeckoAppShell
|
|||
// Don't perform haptic feedback if a vibration is currently playing,
|
||||
// because the haptic feedback will nuke the vibration.
|
||||
if (!sVibrationMaybePlaying || System.nanoTime() >= sVibrationEndTime) {
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
LayerView layerView = layerController.getView();
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
LayerView layerView = layerClient.getView();
|
||||
layerView.performHapticFeedback(aIsLongPress ?
|
||||
HapticFeedbackConstants.LONG_PRESS :
|
||||
HapticFeedbackConstants.VIRTUAL_KEY);
|
||||
|
@ -1434,8 +1433,8 @@ public class GeckoAppShell
|
|||
}
|
||||
|
||||
private static Vibrator vibrator() {
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
LayerView layerView = layerController.getView();
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
LayerView layerView = layerClient.getView();
|
||||
|
||||
return (Vibrator) layerView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||
}
|
||||
|
@ -1483,7 +1482,7 @@ public class GeckoAppShell
|
|||
public static void notifyDefaultPrevented(final boolean defaultPrevented) {
|
||||
getMainHandler().post(new Runnable() {
|
||||
public void run() {
|
||||
LayerView view = GeckoApp.mAppContext.getLayerController().getView();
|
||||
LayerView view = GeckoApp.mAppContext.getLayerClient().getView();
|
||||
view.getTouchEventHandler().handleEventListenerAction(!defaultPrevented);
|
||||
}
|
||||
});
|
||||
|
@ -2401,11 +2400,11 @@ class ScreenshotHandler implements Runnable {
|
|||
}
|
||||
|
||||
private void screenshotWholePage(int tabId) {
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
if (layerController == null) {
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
if (layerClient == null) {
|
||||
return;
|
||||
}
|
||||
ImmutableViewportMetrics viewport = layerController.getViewportMetrics();
|
||||
ImmutableViewportMetrics viewport = layerClient.getViewportMetrics();
|
||||
RectF pageRect = viewport.getCssPageRect();
|
||||
|
||||
if (FloatUtils.fuzzyEquals(pageRect.width(), 0) || FloatUtils.fuzzyEquals(pageRect.height(), 0)) {
|
||||
|
@ -2505,14 +2504,14 @@ class ScreenshotHandler implements Runnable {
|
|||
return;
|
||||
}
|
||||
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
if (layerController == null) {
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
if (layerClient == null) {
|
||||
// we could be in the midst of an activity tear-down and re-start, so guard
|
||||
// against a null layer controller.
|
||||
return;
|
||||
}
|
||||
|
||||
ImmutableViewportMetrics viewport = layerController.getViewportMetrics();
|
||||
ImmutableViewportMetrics viewport = layerClient.getViewportMetrics();
|
||||
if (RectUtils.fuzzyEquals(mPageRect, viewport.getCssPageRect())) {
|
||||
// the page size hasn't changed, so our dirty rect is still valid and we can just
|
||||
// repaint that area
|
||||
|
@ -2592,9 +2591,9 @@ class ScreenshotHandler implements Runnable {
|
|||
// this screenshot has all its slices done, so push it out
|
||||
// to the layer renderer and remove it from the list
|
||||
}
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
if (layerController != null) {
|
||||
layerController.getView().getRenderer().setCheckerboardBitmap(
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
if (layerClient != null) {
|
||||
layerClient.getView().getRenderer().setCheckerboardBitmap(
|
||||
data, bufferWidth, bufferHeight, handler.mPageRect,
|
||||
current.getPaintedRegion());
|
||||
}
|
||||
|
|
|
@ -227,7 +227,7 @@ public class GeckoEvent {
|
|||
public void addMotionPoint(int index, int eventIndex, MotionEvent event) {
|
||||
try {
|
||||
PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex));
|
||||
geckoPoint = GeckoApp.mAppContext.getLayerController().convertViewPointToLayerPoint(geckoPoint);
|
||||
geckoPoint = GeckoApp.mAppContext.getLayerClient().convertViewPointToLayerPoint(geckoPoint);
|
||||
|
||||
mPoints[index] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y));
|
||||
mPointIndicies[index] = event.getPointerId(eventIndex);
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.InputConnectionHandler;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
|
||||
import android.R;
|
||||
import android.content.Context;
|
||||
|
@ -294,8 +294,8 @@ class GeckoInputConnection
|
|||
}
|
||||
|
||||
private static View getView() {
|
||||
LayerController controller = GeckoApp.mAppContext.getLayerController();
|
||||
return (controller == null ? null : controller.getView());
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
return (layerClient == null ? null : layerClient.getView());
|
||||
}
|
||||
|
||||
private Span getSelection() {
|
||||
|
|
|
@ -131,7 +131,6 @@ FENNEC_JAVA_FILES = \
|
|||
gfx/InputConnectionHandler.java \
|
||||
gfx/IntSize.java \
|
||||
gfx/Layer.java \
|
||||
gfx/LayerController.java \
|
||||
gfx/LayerRenderer.java \
|
||||
gfx/LayerView.java \
|
||||
gfx/PluginLayer.java \
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
@ -181,11 +181,11 @@ public class PromptService implements OnClickListener, OnCancelListener, OnItemC
|
|||
}
|
||||
|
||||
public void show(String aTitle, String aText, PromptButton[] aButtons, PromptListItem[] aMenuList, boolean aMultipleSelection) {
|
||||
final LayerController controller = GeckoApp.mAppContext.getLayerController();
|
||||
controller.post(new Runnable() {
|
||||
final GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
layerClient.post(new Runnable() {
|
||||
public void run() {
|
||||
// treat actions that show a dialog as if preventDefault by content to prevent panning
|
||||
controller.getPanZoomController().abortPanning();
|
||||
layerClient.getPanZoomController().abortPanning();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.Layer;
|
||||
import org.mozilla.gecko.gfx.Layer.RenderContext;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.util.FloatUtils;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
@ -55,18 +55,18 @@ class TextSelection extends Layer implements GeckoEventListener {
|
|||
mViewLeft = 0.0f;
|
||||
mViewTop = 0.0f;
|
||||
mViewZoom = 0.0f;
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
if (layerController != null) {
|
||||
layerController.getView().addLayer(TextSelection.this);
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
if (layerClient != null) {
|
||||
layerClient.getView().addLayer(TextSelection.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (event.equals("TextSelection:HideHandles")) {
|
||||
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
if (layerController != null) {
|
||||
layerController.getView().removeLayer(TextSelection.this);
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
if (layerClient != null) {
|
||||
layerClient.getView().removeLayer(TextSelection.this);
|
||||
}
|
||||
|
||||
mStartHandle.setVisibility(View.GONE);
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
package org.mozilla.gecko;
|
||||
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
@ -83,15 +83,15 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
|
|||
mLeft = mLeft + newX - mTouchStartX;
|
||||
mTop = mTop + newY - mTouchStartY;
|
||||
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
if (layerController == null) {
|
||||
Log.e(LOGTAG, "Can't move selection because layerController is null");
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
if (layerClient == null) {
|
||||
Log.e(LOGTAG, "Can't move selection because layerClient is null");
|
||||
return;
|
||||
}
|
||||
// Send x coordinate on the right side of the start handle, left side of the end handle.
|
||||
float left = (float) mLeft + (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
|
||||
PointF geckoPoint = new PointF(left, (float) mTop);
|
||||
geckoPoint = layerController.convertViewPointToLayerPoint(geckoPoint);
|
||||
geckoPoint = layerClient.convertViewPointToLayerPoint(geckoPoint);
|
||||
|
||||
JSONObject args = new JSONObject();
|
||||
try {
|
||||
|
@ -107,14 +107,14 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
|
|||
}
|
||||
|
||||
void positionFromGecko(int left, int top) {
|
||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
||||
if (layerController == null) {
|
||||
Log.e(LOGTAG, "Can't position handle because layerController is null");
|
||||
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||
if (layerClient == null) {
|
||||
Log.e(LOGTAG, "Can't position handle because layerClient is null");
|
||||
return;
|
||||
}
|
||||
|
||||
mGeckoPoint = new PointF((float) left, (float) top);
|
||||
ImmutableViewportMetrics metrics = layerController.getViewportMetrics();
|
||||
ImmutableViewportMetrics metrics = layerClient.getViewportMetrics();
|
||||
repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,10 @@ import org.mozilla.gecko.GeckoEvent;
|
|||
import org.mozilla.gecko.GeckoEventResponder;
|
||||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.Tabs;
|
||||
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.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
@ -17,20 +21,22 @@ import org.json.JSONObject;
|
|||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.SystemClock;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.GestureDetector;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener {
|
||||
public class GeckoLayerClient
|
||||
implements GeckoEventResponder, LayerView.Listener, PanZoomTarget
|
||||
{
|
||||
private static final String LOGTAG = "GeckoLayerClient";
|
||||
|
||||
private LayerController mLayerController;
|
||||
private LayerRenderer mLayerRenderer;
|
||||
private boolean mLayerRendererInitialized;
|
||||
|
||||
|
@ -63,6 +69,33 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
/* This is written by the compositor thread and read by the UI thread. */
|
||||
private volatile boolean mCompositorCreated;
|
||||
|
||||
private boolean mForceRedraw;
|
||||
|
||||
/* 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;
|
||||
private boolean mCheckerboardShouldShowChecks;
|
||||
|
||||
private final PanZoomController mPanZoomController;
|
||||
private LayerView mView;
|
||||
|
||||
public GeckoLayerClient(Context context) {
|
||||
// we can fill these in with dummy values because they are always written
|
||||
// to before being read
|
||||
|
@ -75,16 +108,28 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
mCurrentViewTransform = new ViewTransform(0, 0, 1);
|
||||
|
||||
mCompositorCreated = false;
|
||||
|
||||
mForceRedraw = true;
|
||||
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
|
||||
mViewportMetrics = new ImmutableViewportMetrics(new ViewportMetrics(displayMetrics));
|
||||
mZoomConstraints = new ZoomConstraints(false);
|
||||
mCheckerboardColor = Color.WHITE;
|
||||
mCheckerboardShouldShowChecks = true;
|
||||
|
||||
mPanZoomController = new PanZoomController(this);
|
||||
}
|
||||
|
||||
/** Attaches the root layer to the layer controller so that Gecko appears. */
|
||||
void setLayerController(LayerController layerController) {
|
||||
LayerView view = layerController.getView();
|
||||
public void setView(LayerView v) {
|
||||
mView = v;
|
||||
mView.connect(this);
|
||||
}
|
||||
|
||||
mLayerController = layerController;
|
||||
/** Attaches to root layer so that Gecko appears. */
|
||||
public void notifyGeckoReady() {
|
||||
mGeckoIsReady = true;
|
||||
|
||||
mRootLayer = new VirtualLayer(new IntSize(view.getWidth(), view.getHeight()));
|
||||
mLayerRenderer = new LayerRenderer(view);
|
||||
mRootLayer = new VirtualLayer(new IntSize(mView.getWidth(), mView.getHeight()));
|
||||
mLayerRenderer = new LayerRenderer(mView);
|
||||
|
||||
GeckoAppShell.registerGeckoEventListener("Viewport:Update", this);
|
||||
GeckoAppShell.registerGeckoEventListener("Viewport:PageSize", this);
|
||||
|
@ -92,9 +137,8 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
GeckoAppShell.registerGeckoEventListener("Checkerboard:Toggle", this);
|
||||
GeckoAppShell.registerGeckoEventListener("Preferences:Data", this);
|
||||
|
||||
view.setListener(this);
|
||||
view.setLayerRenderer(mLayerRenderer);
|
||||
layerController.setRoot(mRootLayer);
|
||||
mView.setListener(this);
|
||||
mView.setLayerRenderer(mLayerRenderer);
|
||||
|
||||
sendResizeEventIfNecessary(true);
|
||||
|
||||
|
@ -105,6 +149,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
}
|
||||
|
||||
public void destroy() {
|
||||
mPanZoomController.destroy();
|
||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:Update", this);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:PageSize", this);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:CalculateDisplayPort", this);
|
||||
|
@ -112,17 +157,76 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
GeckoAppShell.unregisterGeckoEventListener("Preferences:Data", this);
|
||||
}
|
||||
|
||||
DisplayPortMetrics getDisplayPort() {
|
||||
return mDisplayPort;
|
||||
/**
|
||||
* Returns true if this client 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(), mDisplayPort);
|
||||
}
|
||||
|
||||
public Layer getRoot() {
|
||||
return mGeckoIsReady ? mRootLayer : null;
|
||||
}
|
||||
|
||||
public LayerView getView() {
|
||||
return mView;
|
||||
}
|
||||
|
||||
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.
|
||||
*
|
||||
* 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) {
|
||||
ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
|
||||
viewportMetrics.setSize(size);
|
||||
mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
|
||||
|
||||
if (mGeckoIsReady) {
|
||||
viewportSizeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public PanZoomController getPanZoomController() {
|
||||
return mPanZoomController;
|
||||
}
|
||||
|
||||
public GestureDetector.OnGestureListener getGestureListener() {
|
||||
return mPanZoomController;
|
||||
}
|
||||
|
||||
public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() {
|
||||
return mPanZoomController;
|
||||
}
|
||||
|
||||
public GestureDetector.OnDoubleTapListener getDoubleTapListener() {
|
||||
return mPanZoomController;
|
||||
}
|
||||
|
||||
/* Informs Gecko that the screen size has changed. */
|
||||
private void sendResizeEventIfNecessary(boolean force) {
|
||||
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
|
||||
View view = mLayerController.getView();
|
||||
|
||||
IntSize newScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
|
||||
IntSize newWindowSize = new IntSize(view.getWidth(), view.getHeight());
|
||||
IntSize newWindowSize = new IntSize(mView.getWidth(), mView.getHeight());
|
||||
|
||||
boolean screenSizeChanged = !mScreenSize.equals(newScreenSize);
|
||||
boolean windowSizeChanged = !mWindowSize.equals(newWindowSize);
|
||||
|
@ -163,15 +267,37 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
GeckoAppShell.viewSizeChanged();
|
||||
}
|
||||
|
||||
/** Sets the current page rect. You must hold the monitor while calling this. */
|
||||
private 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;
|
||||
|
||||
ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
|
||||
viewportMetrics.setPageRect(rect, cssRect);
|
||||
mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
|
||||
|
||||
// Page size is owned by the layer client, so no need to notify it of
|
||||
// this change.
|
||||
|
||||
post(new Runnable() {
|
||||
public void run() {
|
||||
mPanZoomController.pageRectUpdated();
|
||||
mView.requestRender();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void adjustViewport(DisplayPortMetrics displayPort) {
|
||||
ImmutableViewportMetrics metrics = mLayerController.getViewportMetrics();
|
||||
ImmutableViewportMetrics metrics = getViewportMetrics();
|
||||
|
||||
ViewportMetrics clampedMetrics = new ViewportMetrics(metrics);
|
||||
clampedMetrics.setViewport(clampedMetrics.getClampedViewport());
|
||||
|
||||
if (displayPort == null) {
|
||||
displayPort = DisplayPortCalculator.calculate(metrics,
|
||||
mLayerController.getPanZoomController().getVelocityVector());
|
||||
displayPort = DisplayPortCalculator.calculate(metrics, mPanZoomController.getVelocityVector());
|
||||
}
|
||||
|
||||
mDisplayPort = displayPort;
|
||||
|
@ -184,6 +310,17 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
GeckoAppShell.sendEventToGecko(GeckoEvent.createViewportEvent(clampedMetrics, displayPort));
|
||||
}
|
||||
|
||||
/** Aborts any pan/zoom animation that is currently in progress. */
|
||||
private void abortPanZoomAnimation() {
|
||||
if (mPanZoomController != null) {
|
||||
post(new Runnable() {
|
||||
public void run() {
|
||||
mPanZoomController.abortAnimation();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The different types of Viewport messages handled. All viewport events
|
||||
* expect a display-port to be returned, but can handle one not being
|
||||
|
@ -197,9 +334,9 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
/** Viewport message handler. */
|
||||
private void handleViewportMessage(JSONObject message, ViewportMessageType type) throws JSONException {
|
||||
ViewportMetrics messageMetrics = new ViewportMetrics(message);
|
||||
synchronized (mLayerController) {
|
||||
synchronized (this) {
|
||||
final ViewportMetrics newMetrics;
|
||||
ImmutableViewportMetrics oldMetrics = mLayerController.getViewportMetrics();
|
||||
ImmutableViewportMetrics oldMetrics = getViewportMetrics();
|
||||
|
||||
switch (type) {
|
||||
default:
|
||||
|
@ -207,7 +344,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
newMetrics = messageMetrics;
|
||||
// Keep the old viewport size
|
||||
newMetrics.setSize(oldMetrics.getSize());
|
||||
mLayerController.abortPanZoomAnimation();
|
||||
abortPanZoomAnimation();
|
||||
break;
|
||||
case PAGE_SIZE:
|
||||
// adjust the page dimensions to account for differences in zoom
|
||||
|
@ -219,13 +356,13 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
break;
|
||||
}
|
||||
|
||||
mLayerController.post(new Runnable() {
|
||||
post(new Runnable() {
|
||||
public void run() {
|
||||
mGeckoViewport = newMetrics;
|
||||
}
|
||||
});
|
||||
mLayerController.setViewportMetrics(newMetrics);
|
||||
mDisplayPort = DisplayPortCalculator.calculate(mLayerController.getViewportMetrics(), null);
|
||||
setViewportMetrics(newMetrics);
|
||||
mDisplayPort = DisplayPortCalculator.calculate(getViewportMetrics(), null);
|
||||
}
|
||||
mReturnDisplayPort = mDisplayPort;
|
||||
}
|
||||
|
@ -242,7 +379,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
mReturnDisplayPort = DisplayPortCalculator.calculate(newMetrics, null);
|
||||
} else if ("Checkerboard:Toggle".equals(event)) {
|
||||
boolean showChecks = message.getBoolean("value");
|
||||
mLayerController.setCheckerboardShowChecks(showChecks);
|
||||
setCheckerboardShowChecks(showChecks);
|
||||
Log.i(LOGTAG, "Showing checks: " + showChecks);
|
||||
} else if ("Preferences:Data".equals(event)) {
|
||||
JSONArray jsonPrefs = message.getJSONArray("preferences");
|
||||
|
@ -286,13 +423,6 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
}
|
||||
}
|
||||
|
||||
void geometryChanged() {
|
||||
/* Let Gecko know if the screensize has changed */
|
||||
sendResizeEventIfNecessary(false);
|
||||
if (mLayerController.getRedrawHint())
|
||||
adjustViewport(null);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns the last viewport that we sent to Gecko. If any additional events are
|
||||
* being sent to Gecko that are relative on the Gecko viewport position, they must (a) be relative
|
||||
|
@ -305,6 +435,28 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
return mGeckoViewport;
|
||||
}
|
||||
|
||||
public boolean checkerboardShouldShowChecks() {
|
||||
return mCheckerboardShouldShowChecks;
|
||||
}
|
||||
|
||||
public int getCheckerboardColor() {
|
||||
return mCheckerboardColor;
|
||||
}
|
||||
|
||||
public void setCheckerboardShowChecks(boolean showChecks) {
|
||||
mCheckerboardShouldShowChecks = showChecks;
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
public void setCheckerboardColor(int newColor) {
|
||||
mCheckerboardColor = newColor;
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
public void setZoomConstraints(ZoomConstraints constraints) {
|
||||
mZoomConstraints = constraints;
|
||||
}
|
||||
|
||||
/** This function is invoked by Gecko via JNI; be careful when modifying signature.
|
||||
* 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
|
||||
|
@ -315,26 +467,26 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
public void setFirstPaintViewport(float offsetX, float offsetY, float zoom,
|
||||
float pageLeft, float pageTop, float pageRight, float pageBottom,
|
||||
float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
|
||||
synchronized (mLayerController) {
|
||||
final ViewportMetrics currentMetrics = new ViewportMetrics(mLayerController.getViewportMetrics());
|
||||
synchronized (this) {
|
||||
final ViewportMetrics currentMetrics = new ViewportMetrics(getViewportMetrics());
|
||||
currentMetrics.setOrigin(new PointF(offsetX, offsetY));
|
||||
currentMetrics.setZoomFactor(zoom);
|
||||
currentMetrics.setPageRect(new RectF(pageLeft, pageTop, pageRight, pageBottom),
|
||||
new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom));
|
||||
// Since we have switched to displaying a different document, we need to update any
|
||||
// viewport-related state we have lying around. This includes mGeckoViewport and the
|
||||
// viewport in mLayerController. Usually this information is updated via handleViewportMessage
|
||||
// viewport-related state we have lying around. This includes mGeckoViewport and
|
||||
// mViewportMetrics. Usually this information is updated via handleViewportMessage
|
||||
// while we remain on the same document.
|
||||
mLayerController.post(new Runnable() {
|
||||
post(new Runnable() {
|
||||
public void run() {
|
||||
mGeckoViewport = currentMetrics;
|
||||
}
|
||||
});
|
||||
mLayerController.setViewportMetrics(currentMetrics);
|
||||
setViewportMetrics(currentMetrics);
|
||||
|
||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||
mLayerController.setCheckerboardColor(tab.getCheckerboardColor());
|
||||
mLayerController.setZoomConstraints(tab.getZoomConstraints());
|
||||
setCheckerboardColor(tab.getCheckerboardColor());
|
||||
setZoomConstraints(tab.getZoomConstraints());
|
||||
|
||||
// At this point, we have just switched to displaying a different document than we
|
||||
// we previously displaying. This means we need to abort any panning/zooming animations
|
||||
|
@ -343,12 +495,12 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
// sends the request after aborting the animation. The display port request is actually
|
||||
// a full viewport update, which is fine because if browser.js has somehow moved to
|
||||
// be out of sync with this first-paint viewport, then we force them back in sync.
|
||||
mLayerController.abortPanZoomAnimation();
|
||||
mLayerController.getView().setPaintState(LayerView.PAINT_BEFORE_FIRST);
|
||||
abortPanZoomAnimation();
|
||||
mView.setPaintState(LayerView.PAINT_BEFORE_FIRST);
|
||||
}
|
||||
DisplayPortCalculator.resetPageState();
|
||||
mDrawTimingQueue.reset();
|
||||
mLayerController.getView().getRenderer().resetCheckerboard();
|
||||
mView.getRenderer().resetCheckerboard();
|
||||
GeckoAppShell.screenshotWholePage(Tabs.getInstance().getSelectedTab());
|
||||
}
|
||||
|
||||
|
@ -359,10 +511,10 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
* function will be invoked before syncViewportInfo.
|
||||
*/
|
||||
public void setPageRect(float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
|
||||
synchronized (mLayerController) {
|
||||
synchronized (this) {
|
||||
RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
|
||||
float ourZoom = mLayerController.getViewportMetrics().zoomFactor;
|
||||
mLayerController.setPageRect(RectUtils.scale(cssPageRect, ourZoom), cssPageRect);
|
||||
float ourZoom = getViewportMetrics().zoomFactor;
|
||||
setPageRect(RectUtils.scale(cssPageRect, ourZoom), 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
|
||||
|
@ -380,14 +532,13 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
* which would avoid the copy into mCurrentViewTransform.
|
||||
*/
|
||||
public ViewTransform syncViewportInfo(int x, int y, int width, int height, float resolution, boolean layersUpdated) {
|
||||
// getViewportMetrics is thread safe so we don't need to synchronize
|
||||
// on mLayerController.
|
||||
// getViewportMetrics is thread safe so we don't need to synchronize.
|
||||
// We save the viewport metrics here, so we later use it later in
|
||||
// createFrame (which will be called by nsWindow::DrawWindowUnderlay on
|
||||
// the native side, by the compositor). The LayerController's viewport
|
||||
// the native side, by the compositor). The viewport
|
||||
// metrics can change between here and there, as it's accessed outside
|
||||
// of the compositor thread.
|
||||
mFrameMetrics = mLayerController.getViewportMetrics();
|
||||
mFrameMetrics = getViewportMetrics();
|
||||
|
||||
mCurrentViewTransform.x = mFrameMetrics.viewportRectLeft;
|
||||
mCurrentViewTransform.y = mFrameMetrics.viewportRectTop;
|
||||
|
@ -438,6 +589,14 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
mLayerRenderer.deactivateDefaultProgram();
|
||||
}
|
||||
|
||||
void geometryChanged() {
|
||||
/* Let Gecko know if the screensize has changed */
|
||||
sendResizeEventIfNecessary(false);
|
||||
if (getRedrawHint()) {
|
||||
adjustViewport(null);
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of LayerView.Listener */
|
||||
public void renderRequested() {
|
||||
GeckoAppShell.scheduleComposite();
|
||||
|
@ -472,7 +631,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
|
||||
/** Implementation of LayerView.Listener */
|
||||
public void surfaceChanged(int width, int height) {
|
||||
mLayerController.setViewportSize(new FloatSize(width, height));
|
||||
setViewportSize(new FloatSize(width, height));
|
||||
|
||||
// We need to make this call even when the compositor isn't currently
|
||||
// paused (e.g. during an orientation change), to make the compositor
|
||||
|
@ -486,6 +645,89 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
|||
mCompositorCreated = true;
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget */
|
||||
public ImmutableViewportMetrics getViewportMetrics() {
|
||||
return mViewportMetrics;
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget */
|
||||
public ZoomConstraints getZoomConstraints() {
|
||||
return mZoomConstraints;
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget */
|
||||
public void setAnimationTarget(ViewportMetrics viewport) {
|
||||
if (mGeckoIsReady) {
|
||||
// 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.
|
||||
ImmutableViewportMetrics metrics = new ImmutableViewportMetrics(viewport);
|
||||
DisplayPortMetrics displayPort = DisplayPortCalculator.calculate(metrics, null);
|
||||
adjustViewport(displayPort);
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget
|
||||
* You must hold the monitor while calling this.
|
||||
*/
|
||||
public void setViewportMetrics(ViewportMetrics viewport) {
|
||||
mViewportMetrics = new ImmutableViewportMetrics(viewport);
|
||||
mView.requestRender();
|
||||
if (mGeckoIsReady) {
|
||||
geometryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget */
|
||||
public void setForceRedraw() {
|
||||
mForceRedraw = true;
|
||||
if (mGeckoIsReady) {
|
||||
geometryChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget */
|
||||
public boolean post(Runnable action) {
|
||||
return mView.post(action);
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget */
|
||||
public Object getLock() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Implementation of PanZoomTarget
|
||||
* 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 (!mGeckoIsReady) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ImmutableViewportMetrics viewportMetrics = mViewportMetrics;
|
||||
PointF origin = viewportMetrics.getOrigin();
|
||||
float zoom = viewportMetrics.zoomFactor;
|
||||
ViewportMetrics geckoViewport = getGeckoViewportMetrics();
|
||||
PointF geckoOrigin = geckoViewport.getOrigin();
|
||||
float geckoZoom = geckoViewport.getZoomFactor();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/** Used by robocop for testing purposes. Not for production use! This is called via reflection by robocop. */
|
||||
public void setDrawListener(DrawListener listener) {
|
||||
mDrawListener = listener;
|
||||
|
|
|
@ -1,270 +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 org.mozilla.gecko.ZoomConstraints;
|
||||
import org.mozilla.gecko.ui.PanZoomController;
|
||||
import org.mozilla.gecko.ui.PanZoomTarget;
|
||||
import org.mozilla.gecko.ui.SimpleScaleGestureDetector;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.GestureDetector;
|
||||
|
||||
/**
|
||||
* 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(new ViewportMetrics(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) {
|
||||
ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
|
||||
viewportMetrics.setSize(size);
|
||||
mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
|
||||
|
||||
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;
|
||||
|
||||
ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
|
||||
viewportMetrics.setPageRect(rect, cssRect);
|
||||
mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
|
||||
|
||||
// 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(ViewportMetrics viewport) {
|
||||
mViewportMetrics = new ImmutableViewportMetrics(viewport);
|
||||
mView.requestRender();
|
||||
notifyLayerClientOfGeometryChange();
|
||||
}
|
||||
|
||||
public void setAnimationTarget(ViewportMetrics 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.
|
||||
ImmutableViewportMetrics metrics = new ImmutableViewportMetrics(viewport);
|
||||
DisplayPortMetrics displayPort = DisplayPortCalculator.calculate(metrics, 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;
|
||||
ViewportMetrics geckoViewport = mLayerClient.getGeckoViewportMetrics();
|
||||
PointF geckoOrigin = geckoViewport.getOrigin();
|
||||
float geckoZoom = geckoViewport.getZoomFactor();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
|
@ -445,7 +445,7 @@ public class LayerRenderer {
|
|||
|
||||
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
|
||||
|
@ -518,7 +518,7 @@ public class LayerRenderer {
|
|||
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.
|
||||
|
@ -543,9 +543,9 @@ public class LayerRenderer {
|
|||
/* 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());
|
||||
mCheckerboardLayer.setMask(rootMask);
|
||||
|
||||
/* Scissor around the page-rect, in case the page has shrunk
|
||||
|
@ -558,7 +558,7 @@ public class LayerRenderer {
|
|||
|
||||
// Draws the layer the client added to us.
|
||||
void drawRootLayer() {
|
||||
Layer rootLayer = mView.getController().getRoot();
|
||||
Layer rootLayer = mView.getLayerClient().getRoot();
|
||||
if (rootLayer == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -590,7 +590,7 @@ public class LayerRenderer {
|
|||
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
|
||||
|
|
|
@ -34,15 +34,12 @@ import java.lang.reflect.Method;
|
|||
/**
|
||||
* A view rendered by the layer compositor.
|
||||
*
|
||||
* This view delegates to LayerRenderer to actually do the drawing. Its role is largely that of a
|
||||
* mediator between the LayerRenderer and the LayerController.
|
||||
*
|
||||
* Note that LayerView is accessed by Robocop via reflection.
|
||||
*/
|
||||
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;
|
||||
|
@ -98,9 +95,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;
|
||||
|
||||
|
@ -125,12 +122,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));
|
||||
}
|
||||
|
||||
public void setInputConnectionHandler(InputConnectionHandler inputConnectionHandler) {
|
||||
|
@ -280,7 +277,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 = GeckoApp.mAppContext.getLayerController().getView();
|
||||
LayerView layerView = GeckoApp.mAppContext.getLayerClient().getView();
|
||||
layerView.mListener.compositorCreated();
|
||||
return layerView.getGLController();
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -125,17 +125,17 @@ public final class TouchEventHandler implements Tabs.OnTabsChangedListener {
|
|||
// 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());
|
||||
|
||||
Tabs.registerOnTabsChangedListener(this);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ class MotionEventReplayer {
|
|||
// edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=21972329,
|
||||
// downTime=21972329, deviceId=6, source=0x1002 }
|
||||
//
|
||||
// These can be generated by printing out event.toString() in LayerController's
|
||||
// These can be generated by printing out event.toString() in LayerView's
|
||||
// onTouchEvent function on a phone running Ice Cream Sandwich. Different
|
||||
// Android versions have different serializations of the motion event, and this
|
||||
// code could probably be modified to parse other serializations if needed.
|
||||
|
|
Загрузка…
Ссылка в новой задаче