зеркало из https://github.com/mozilla/gecko-dev.git
Bug 777351 - Fold LayerController into GeckoLayerClient. r=sriram
This commit is contained in:
Родитель
81e3002e79
Коммит
aafa3dfccd
|
@ -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;
|
||||
|
@ -152,7 +151,6 @@ abstract public class GeckoApp
|
|||
protected FormAssistPopup mFormAssistPopup;
|
||||
protected TabsPanel mTabsPanel;
|
||||
|
||||
private LayerController mLayerController;
|
||||
private GeckoLayerClient mLayerClient;
|
||||
private AbsoluteLayout mPluginContainer;
|
||||
|
||||
|
@ -875,10 +873,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");
|
||||
|
@ -1023,10 +1021,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");
|
||||
|
@ -1035,7 +1033,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")) {
|
||||
|
@ -1261,7 +1259,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);
|
||||
|
@ -1398,14 +1396,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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1427,7 +1425,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);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1482,19 +1480,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) {
|
||||
|
@ -1708,23 +1706,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);
|
||||
|
@ -2145,8 +2129,6 @@ abstract public class GeckoApp
|
|||
|
||||
deleteTempFiles();
|
||||
|
||||
if (mLayerController != null)
|
||||
mLayerController.destroy();
|
||||
if (mLayerClient != null)
|
||||
mLayerClient.destroy();
|
||||
if (mFormAssistPopup != null)
|
||||
|
@ -2602,7 +2584,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; }
|
||||
|
||||
|
@ -2648,10 +2629,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
|
||||
|
@ -2736,7 +2717,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.IntSize;
|
|||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.GfxInfoThread;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.ScreenshotLayer;
|
||||
import org.mozilla.gecko.gfx.RectUtils;
|
||||
|
@ -540,10 +539,10 @@ 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 = v.setInputConnectionHandler();
|
||||
layerController.setForceRedraw();
|
||||
layerClient.setForceRedraw();
|
||||
}
|
||||
|
||||
static void sendPendingEventsToGecko() {
|
||||
|
@ -1418,8 +1417,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);
|
||||
|
@ -1427,8 +1426,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);
|
||||
}
|
||||
|
@ -1476,7 +1475,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);
|
||||
}
|
||||
});
|
||||
|
@ -2394,11 +2393,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)) {
|
||||
|
@ -2498,14 +2497,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
|
||||
|
@ -2585,9 +2584,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());
|
||||
}
|
||||
|
|
|
@ -226,7 +226,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);
|
||||
|
|
|
@ -38,7 +38,7 @@ import android.view.inputmethod.InputConnection;
|
|||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import org.mozilla.gecko.gfx.InputConnectionHandler;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
@ -294,8 +294,8 @@ public 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() {
|
||||
|
|
|
@ -124,7 +124,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 \
|
||||
|
|
|
@ -34,7 +34,7 @@ import android.widget.ArrayAdapter;
|
|||
import android.widget.ListView;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
|
||||
public class PromptService implements OnClickListener, OnCancelListener, OnItemClickListener, GeckoEventResponder {
|
||||
private static final String LOGTAG = "GeckoPromptService";
|
||||
|
@ -178,11 +178,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();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import android.util.Log;
|
|||
import android.view.View;
|
||||
import org.mozilla.gecko.gfx.Layer;
|
||||
import org.mozilla.gecko.gfx.Layer.RenderContext;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.json.JSONObject;
|
||||
|
||||
class TextSelection extends Layer implements GeckoEventListener {
|
||||
|
@ -52,18 +52,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);
|
||||
|
|
|
@ -13,8 +13,8 @@ import android.view.MotionEvent;
|
|||
import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.ImageView;
|
||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||
import org.mozilla.gecko.gfx.LayerController;
|
||||
import org.json.JSONObject;
|
||||
|
||||
class TextSelectionHandle extends ImageView implements View.OnTouchListener {
|
||||
|
@ -81,15 +81,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 {
|
||||
|
@ -105,14 +105,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,25 +10,30 @@ 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;
|
||||
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.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -61,6 +66,33 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
/* 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
|
||||
|
@ -73,16 +105,27 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
mCurrentViewTransform = new ViewTransform(0, 0, 1);
|
||||
|
||||
mCompositorCreated = false;
|
||||
|
||||
mForceRedraw = true;
|
||||
mViewportMetrics = new ImmutableViewportMetrics(new ViewportMetrics());
|
||||
mZoomConstraints = new ZoomConstraints();
|
||||
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);
|
||||
|
@ -90,9 +133,8 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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);
|
||||
|
||||
|
@ -103,6 +145,7 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
}
|
||||
|
||||
public void destroy() {
|
||||
mPanZoomController.destroy();
|
||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:Update", this);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:PageSize", this);
|
||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:CalculateDisplayPort", this);
|
||||
|
@ -110,17 +153,76 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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);
|
||||
|
@ -161,15 +263,37 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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;
|
||||
|
@ -182,6 +306,17 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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
|
||||
|
@ -195,9 +330,9 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
/** 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:
|
||||
|
@ -205,7 +340,7 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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
|
||||
|
@ -217,13 +352,13 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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;
|
||||
}
|
||||
|
@ -240,7 +375,7 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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");
|
||||
|
@ -284,13 +419,6 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -303,6 +431,28 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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
|
||||
|
@ -313,26 +463,26 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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
|
||||
|
@ -341,12 +491,12 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
// 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());
|
||||
}
|
||||
|
||||
|
@ -357,10 +507,10 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
* 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
|
||||
|
@ -378,14 +528,13 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
* 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;
|
||||
|
@ -436,6 +585,14 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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();
|
||||
|
@ -470,7 +627,7 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
|
||||
/** 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
|
||||
|
@ -484,6 +641,89 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
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;
|
||||
|
@ -494,4 +734,3 @@ public class GeckoLayerClient implements GeckoEventResponder,
|
|||
public void drawFinished();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,268 +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.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;
|
||||
mViewportMetrics = new ImmutableViewportMetrics(new ViewportMetrics());
|
||||
mPanZoomController = new PanZoomController(this);
|
||||
mCheckerboardShouldShowChecks = true;
|
||||
mZoomConstraints = new ZoomConstraints();
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -32,15 +32,12 @@ import java.nio.IntBuffer;
|
|||
/**
|
||||
* 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;
|
||||
|
@ -79,9 +76,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;
|
||||
|
||||
|
@ -106,12 +103,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 GeckoInputConnection setInputConnectionHandler() {
|
||||
|
@ -266,7 +263,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) {
|
||||
|
|
|
@ -124,17 +124,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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче