From 4f27b0d08c72c34cb46b7321529d429eb600204a Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 7 Aug 2012 10:39:04 -0400 Subject: [PATCH] Bug 777351 - Fold LayerController into GeckoLayerClient. r=sriram --- mobile/android/base/FormAssistPopup.java | 2 +- mobile/android/base/GeckoApp.java | 61 ++- mobile/android/base/GeckoAppShell.java | 35 +- mobile/android/base/GeckoEvent.java | 2 +- mobile/android/base/GeckoInputConnection.java | 6 +- mobile/android/base/Makefile.in | 1 - mobile/android/base/PromptService.java | 8 +- mobile/android/base/TextSelection.java | 14 +- mobile/android/base/TextSelectionHandle.java | 18 +- mobile/android/base/gfx/GeckoLayerClient.java | 346 +++++++++++++++--- mobile/android/base/gfx/LayerController.java | 270 -------------- mobile/android/base/gfx/LayerRenderer.java | 12 +- mobile/android/base/gfx/LayerView.java | 17 +- .../android/base/gfx/TouchEventHandler.java | 10 +- .../base/tests/MotionEventReplayer.java.in | 2 +- 15 files changed, 376 insertions(+), 428 deletions(-) delete mode 100644 mobile/android/base/gfx/LayerController.java diff --git a/mobile/android/base/FormAssistPopup.java b/mobile/android/base/FormAssistPopup.java index 222aad40f242..26cc76ff117e 100644 --- a/mobile/android/base/FormAssistPopup.java +++ b/mobile/android/base/FormAssistPopup.java @@ -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. diff --git a/mobile/android/base/GeckoApp.java b/mobile/android/base/GeckoApp.java index b7a32edea371..d3816ecca000 100644 --- a/mobile/android/base/GeckoApp.java +++ b/mobile/android/base/GeckoApp.java @@ -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); } }); } diff --git a/mobile/android/base/GeckoAppShell.java b/mobile/android/base/GeckoAppShell.java index 69503f167668..37da54de8587 100644 --- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -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()); } diff --git a/mobile/android/base/GeckoEvent.java b/mobile/android/base/GeckoEvent.java index d671015129ec..4e5f2ae6e659 100644 --- a/mobile/android/base/GeckoEvent.java +++ b/mobile/android/base/GeckoEvent.java @@ -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); diff --git a/mobile/android/base/GeckoInputConnection.java b/mobile/android/base/GeckoInputConnection.java index 3926de857314..1557fd91e5e6 100644 --- a/mobile/android/base/GeckoInputConnection.java +++ b/mobile/android/base/GeckoInputConnection.java @@ -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() { diff --git a/mobile/android/base/Makefile.in b/mobile/android/base/Makefile.in index ab7cab8ce86d..04389e20f562 100644 --- a/mobile/android/base/Makefile.in +++ b/mobile/android/base/Makefile.in @@ -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 \ diff --git a/mobile/android/base/PromptService.java b/mobile/android/base/PromptService.java index 2e9aa760f972..31b7a51dd8c8 100644 --- a/mobile/android/base/PromptService.java +++ b/mobile/android/base/PromptService.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(); } }); diff --git a/mobile/android/base/TextSelection.java b/mobile/android/base/TextSelection.java index 54dbfc20b0d0..6628945a1f02 100644 --- a/mobile/android/base/TextSelection.java +++ b/mobile/android/base/TextSelection.java @@ -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); diff --git a/mobile/android/base/TextSelectionHandle.java b/mobile/android/base/TextSelectionHandle.java index 764e0819400c..f66435caa085 100644 --- a/mobile/android/base/TextSelectionHandle.java +++ b/mobile/android/base/TextSelectionHandle.java @@ -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); } diff --git a/mobile/android/base/gfx/GeckoLayerClient.java b/mobile/android/base/gfx/GeckoLayerClient.java index c9b535a4474e..e4f040a02eb7 100644 --- a/mobile/android/base/gfx/GeckoLayerClient.java +++ b/mobile/android/base/gfx/GeckoLayerClient.java @@ -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; diff --git a/mobile/android/base/gfx/LayerController.java b/mobile/android/base/gfx/LayerController.java deleted file mode 100644 index 0e21898533c3..000000000000 --- a/mobile/android/base/gfx/LayerController.java +++ /dev/null @@ -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; - } -} diff --git a/mobile/android/base/gfx/LayerRenderer.java b/mobile/android/base/gfx/LayerRenderer.java index 597f8ee00ddf..b5e25965d672 100644 --- a/mobile/android/base/gfx/LayerRenderer.java +++ b/mobile/android/base/gfx/LayerRenderer.java @@ -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 diff --git a/mobile/android/base/gfx/LayerView.java b/mobile/android/base/gfx/LayerView.java index ea8c0a690423..656de9b9fba3 100644 --- a/mobile/android/base/gfx/LayerView.java +++ b/mobile/android/base/gfx/LayerView.java @@ -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) { diff --git a/mobile/android/base/gfx/TouchEventHandler.java b/mobile/android/base/gfx/TouchEventHandler.java index d06be1003bd5..77004a069ebc 100644 --- a/mobile/android/base/gfx/TouchEventHandler.java +++ b/mobile/android/base/gfx/TouchEventHandler.java @@ -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(); - 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); } diff --git a/mobile/android/base/tests/MotionEventReplayer.java.in b/mobile/android/base/tests/MotionEventReplayer.java.in index 9d6717bb554f..63651a20545e 100644 --- a/mobile/android/base/tests/MotionEventReplayer.java.in +++ b/mobile/android/base/tests/MotionEventReplayer.java.in @@ -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.