зеркало из https://github.com/mozilla/gecko-dev.git
Bug 777351 - Fold LayerController into GeckoLayerClient. r=sriram
This commit is contained in:
Родитель
f94834ff5e
Коммит
4f27b0d08c
|
@ -222,7 +222,7 @@ public class FormAssistPopup extends RelativeLayout implements GeckoEventListene
|
||||||
int popupWidth = RelativeLayout.LayoutParams.FILL_PARENT;
|
int popupWidth = RelativeLayout.LayoutParams.FILL_PARENT;
|
||||||
int popupLeft = left < 0 ? 0 : left;
|
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,
|
// For autocomplete suggestions, if the input is smaller than the screen-width,
|
||||||
// shrink the popup's width. Otherwise, keep it as FILL_PARENT.
|
// 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.db.BrowserDB;
|
||||||
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||||
import org.mozilla.gecko.gfx.Layer;
|
import org.mozilla.gecko.gfx.Layer;
|
||||||
import org.mozilla.gecko.gfx.LayerController;
|
|
||||||
import org.mozilla.gecko.gfx.LayerView;
|
import org.mozilla.gecko.gfx.LayerView;
|
||||||
import org.mozilla.gecko.gfx.PluginLayer;
|
import org.mozilla.gecko.gfx.PluginLayer;
|
||||||
import org.mozilla.gecko.gfx.PointUtils;
|
import org.mozilla.gecko.gfx.PointUtils;
|
||||||
|
@ -154,7 +153,6 @@ abstract public class GeckoApp
|
||||||
protected FormAssistPopup mFormAssistPopup;
|
protected FormAssistPopup mFormAssistPopup;
|
||||||
protected TabsPanel mTabsPanel;
|
protected TabsPanel mTabsPanel;
|
||||||
|
|
||||||
private LayerController mLayerController;
|
|
||||||
private GeckoLayerClient mLayerClient;
|
private GeckoLayerClient mLayerClient;
|
||||||
private AbsoluteLayout mPluginContainer;
|
private AbsoluteLayout mPluginContainer;
|
||||||
|
|
||||||
|
@ -856,10 +854,10 @@ abstract public class GeckoApp
|
||||||
tab.setCheckerboardColor(Color.WHITE);
|
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.
|
// currently displayed.
|
||||||
if (getLayerController() != null && Tabs.getInstance().isSelectedTab(tab)) {
|
if (getLayerClient() != null && Tabs.getInstance().isSelectedTab(tab)) {
|
||||||
getLayerController().setCheckerboardColor(tab.getCheckerboardColor());
|
getLayerClient().setCheckerboardColor(tab.getCheckerboardColor());
|
||||||
}
|
}
|
||||||
} else if (event.equals("DOMTitleChanged")) {
|
} else if (event.equals("DOMTitleChanged")) {
|
||||||
final int tabId = message.getInt("tabID");
|
final int tabId = message.getInt("tabID");
|
||||||
|
@ -1002,10 +1000,10 @@ abstract public class GeckoApp
|
||||||
if (tab == null)
|
if (tab == null)
|
||||||
return;
|
return;
|
||||||
tab.setZoomConstraints(new ZoomConstraints(message));
|
tab.setZoomConstraints(new ZoomConstraints(message));
|
||||||
// Sync up the LayerController and the tab if the tab's currently displayed.
|
// Sync up the GeckoLayerClient and the tab if the tab is currently displayed.
|
||||||
LayerController controller = getLayerController();
|
GeckoLayerClient layerClient = getLayerClient();
|
||||||
if (controller != null && Tabs.getInstance().isSelectedTab(tab)) {
|
if (layerClient != null && Tabs.getInstance().isSelectedTab(tab)) {
|
||||||
controller.setZoomConstraints(tab.getZoomConstraints());
|
layerClient.setZoomConstraints(tab.getZoomConstraints());
|
||||||
}
|
}
|
||||||
} else if (event.equals("Tab:HasTouchListener")) {
|
} else if (event.equals("Tab:HasTouchListener")) {
|
||||||
int tabId = message.getInt("tabID");
|
int tabId = message.getInt("tabID");
|
||||||
|
@ -1014,7 +1012,7 @@ abstract public class GeckoApp
|
||||||
mMainHandler.post(new Runnable() {
|
mMainHandler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
if (Tabs.getInstance().isSelectedTab(tab))
|
if (Tabs.getInstance().isSelectedTab(tab))
|
||||||
mLayerController.getView().getTouchEventHandler().setWaitForTouchListeners(true);
|
mLayerClient.getView().getTouchEventHandler().setWaitForTouchListeners(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (event.equals("Session:StatePurged")) {
|
} else if (event.equals("Session:StatePurged")) {
|
||||||
|
@ -1214,7 +1212,7 @@ abstract public class GeckoApp
|
||||||
tab.updateIdentityData(null);
|
tab.updateIdentityData(null);
|
||||||
tab.setReaderEnabled(false);
|
tab.setReaderEnabled(false);
|
||||||
if (Tabs.getInstance().isSelectedTab(tab))
|
if (Tabs.getInstance().isSelectedTab(tab))
|
||||||
getLayerController().getView().getRenderer().resetCheckerboard();
|
getLayerClient().getView().getRenderer().resetCheckerboard();
|
||||||
mMainHandler.post(new Runnable() {
|
mMainHandler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START, showProgress);
|
Tabs.getInstance().notifyListeners(tab, Tabs.TabEvents.START, showProgress);
|
||||||
|
@ -1351,14 +1349,14 @@ abstract public class GeckoApp
|
||||||
|
|
||||||
PluginLayer layer = (PluginLayer) tab.getPluginLayer(view);
|
PluginLayer layer = (PluginLayer) tab.getPluginLayer(view);
|
||||||
if (layer == null) {
|
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);
|
tab.addPluginLayer(view, layer);
|
||||||
} else {
|
} else {
|
||||||
layer.reset(rect);
|
layer.reset(rect);
|
||||||
layer.setVisible(true);
|
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
|
// a deadlock, see comment below in FullScreenHolder
|
||||||
mMainHandler.post(new Runnable() {
|
mMainHandler.post(new Runnable() {
|
||||||
public void run() {
|
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) {
|
private void hidePluginLayer(Layer layer) {
|
||||||
LayerView layerView = mLayerController.getView();
|
LayerView layerView = mLayerClient.getView();
|
||||||
layerView.removeLayer(layer);
|
layerView.removeLayer(layer);
|
||||||
layerView.requestRender();
|
layerView.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showPluginLayer(Layer layer) {
|
private void showPluginLayer(Layer layer) {
|
||||||
LayerView layerView = mLayerController.getView();
|
LayerView layerView = mLayerClient.getView();
|
||||||
layerView.addLayer(layer);
|
layerView.addLayer(layer);
|
||||||
layerView.requestRender();
|
layerView.requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestRender() {
|
public void requestRender() {
|
||||||
mLayerController.getView().requestRender();
|
mLayerClient.getView().requestRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void hidePlugins(Tab tab) {
|
public void hidePlugins(Tab tab) {
|
||||||
|
@ -1663,23 +1661,9 @@ abstract public class GeckoApp
|
||||||
cameraView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
cameraView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mLayerController == null) {
|
if (mLayerClient == null) {
|
||||||
/*
|
|
||||||
* Create a layer client, but don't hook it up to the layer controller yet.
|
|
||||||
*/
|
|
||||||
mLayerClient = new GeckoLayerClient(this);
|
mLayerClient = new GeckoLayerClient(this);
|
||||||
|
mLayerClient.setView((LayerView)findViewById(R.id.layer_view));
|
||||||
/*
|
|
||||||
* 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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mPluginContainer = (AbsoluteLayout) findViewById(R.id.plugin_container);
|
mPluginContainer = (AbsoluteLayout) findViewById(R.id.plugin_container);
|
||||||
|
@ -2096,8 +2080,6 @@ abstract public class GeckoApp
|
||||||
|
|
||||||
deleteTempFiles();
|
deleteTempFiles();
|
||||||
|
|
||||||
if (mLayerController != null)
|
|
||||||
mLayerController.destroy();
|
|
||||||
if (mLayerClient != null)
|
if (mLayerClient != null)
|
||||||
mLayerClient.destroy();
|
mLayerClient.destroy();
|
||||||
if (mDoorHangerPopup != null)
|
if (mDoorHangerPopup != null)
|
||||||
|
@ -2565,7 +2547,6 @@ abstract public class GeckoApp
|
||||||
|
|
||||||
/* This method is referenced by Robocop via reflection. */
|
/* This method is referenced by Robocop via reflection. */
|
||||||
public GeckoLayerClient getLayerClient() { return mLayerClient; }
|
public GeckoLayerClient getLayerClient() { return mLayerClient; }
|
||||||
public LayerController getLayerController() { return mLayerController; }
|
|
||||||
|
|
||||||
public AbsoluteLayout getPluginContainer() { return mPluginContainer; }
|
public AbsoluteLayout getPluginContainer() { return mPluginContainer; }
|
||||||
|
|
||||||
|
@ -2611,10 +2592,10 @@ abstract public class GeckoApp
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectGeckoLayerClient() {
|
private void connectGeckoLayerClient() {
|
||||||
LayerController layerController = getLayerController();
|
GeckoLayerClient layerClient = getLayerClient();
|
||||||
layerController.setLayerClient(mLayerClient);
|
layerClient.notifyGeckoReady();
|
||||||
|
|
||||||
layerController.getView().getTouchEventHandler().setOnTouchListener(new ContentTouchListener() {
|
layerClient.getView().getTouchEventHandler().setOnTouchListener(new ContentTouchListener() {
|
||||||
private PointF initialPoint = null;
|
private PointF initialPoint = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2699,7 +2680,7 @@ abstract public class GeckoApp
|
||||||
|
|
||||||
mMainHandler.post(new Runnable() {
|
mMainHandler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
mLayerController.getView().setVisibility(View.INVISIBLE);
|
mLayerClient.getView().setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||||
import org.mozilla.gecko.gfx.GfxInfoThread;
|
import org.mozilla.gecko.gfx.GfxInfoThread;
|
||||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||||
import org.mozilla.gecko.gfx.IntSize;
|
import org.mozilla.gecko.gfx.IntSize;
|
||||||
import org.mozilla.gecko.gfx.LayerController;
|
|
||||||
import org.mozilla.gecko.gfx.LayerView;
|
import org.mozilla.gecko.gfx.LayerView;
|
||||||
import org.mozilla.gecko.gfx.RectUtils;
|
import org.mozilla.gecko.gfx.RectUtils;
|
||||||
import org.mozilla.gecko.gfx.ScreenshotLayer;
|
import org.mozilla.gecko.gfx.ScreenshotLayer;
|
||||||
|
@ -539,11 +538,11 @@ public class GeckoAppShell
|
||||||
|
|
||||||
// Called on the UI thread after Gecko loads.
|
// Called on the UI thread after Gecko loads.
|
||||||
private static void geckoLoaded() {
|
private static void geckoLoaded() {
|
||||||
final LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
final GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
LayerView v = layerController.getView();
|
LayerView v = layerClient.getView();
|
||||||
mInputConnection = GeckoInputConnection.create(v);
|
mInputConnection = GeckoInputConnection.create(v);
|
||||||
v.setInputConnectionHandler(mInputConnection);
|
v.setInputConnectionHandler(mInputConnection);
|
||||||
layerController.setForceRedraw();
|
layerClient.setForceRedraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sendPendingEventsToGecko() {
|
static void sendPendingEventsToGecko() {
|
||||||
|
@ -1425,8 +1424,8 @@ public class GeckoAppShell
|
||||||
// Don't perform haptic feedback if a vibration is currently playing,
|
// Don't perform haptic feedback if a vibration is currently playing,
|
||||||
// because the haptic feedback will nuke the vibration.
|
// because the haptic feedback will nuke the vibration.
|
||||||
if (!sVibrationMaybePlaying || System.nanoTime() >= sVibrationEndTime) {
|
if (!sVibrationMaybePlaying || System.nanoTime() >= sVibrationEndTime) {
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
LayerView layerView = layerController.getView();
|
LayerView layerView = layerClient.getView();
|
||||||
layerView.performHapticFeedback(aIsLongPress ?
|
layerView.performHapticFeedback(aIsLongPress ?
|
||||||
HapticFeedbackConstants.LONG_PRESS :
|
HapticFeedbackConstants.LONG_PRESS :
|
||||||
HapticFeedbackConstants.VIRTUAL_KEY);
|
HapticFeedbackConstants.VIRTUAL_KEY);
|
||||||
|
@ -1434,8 +1433,8 @@ public class GeckoAppShell
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Vibrator vibrator() {
|
private static Vibrator vibrator() {
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
LayerView layerView = layerController.getView();
|
LayerView layerView = layerClient.getView();
|
||||||
|
|
||||||
return (Vibrator) layerView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
return (Vibrator) layerView.getContext().getSystemService(Context.VIBRATOR_SERVICE);
|
||||||
}
|
}
|
||||||
|
@ -1483,7 +1482,7 @@ public class GeckoAppShell
|
||||||
public static void notifyDefaultPrevented(final boolean defaultPrevented) {
|
public static void notifyDefaultPrevented(final boolean defaultPrevented) {
|
||||||
getMainHandler().post(new Runnable() {
|
getMainHandler().post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
LayerView view = GeckoApp.mAppContext.getLayerController().getView();
|
LayerView view = GeckoApp.mAppContext.getLayerClient().getView();
|
||||||
view.getTouchEventHandler().handleEventListenerAction(!defaultPrevented);
|
view.getTouchEventHandler().handleEventListenerAction(!defaultPrevented);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -2401,11 +2400,11 @@ class ScreenshotHandler implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void screenshotWholePage(int tabId) {
|
private void screenshotWholePage(int tabId) {
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
if (layerController == null) {
|
if (layerClient == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ImmutableViewportMetrics viewport = layerController.getViewportMetrics();
|
ImmutableViewportMetrics viewport = layerClient.getViewportMetrics();
|
||||||
RectF pageRect = viewport.getCssPageRect();
|
RectF pageRect = viewport.getCssPageRect();
|
||||||
|
|
||||||
if (FloatUtils.fuzzyEquals(pageRect.width(), 0) || FloatUtils.fuzzyEquals(pageRect.height(), 0)) {
|
if (FloatUtils.fuzzyEquals(pageRect.width(), 0) || FloatUtils.fuzzyEquals(pageRect.height(), 0)) {
|
||||||
|
@ -2505,14 +2504,14 @@ class ScreenshotHandler implements Runnable {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
if (layerController == null) {
|
if (layerClient == null) {
|
||||||
// we could be in the midst of an activity tear-down and re-start, so guard
|
// we could be in the midst of an activity tear-down and re-start, so guard
|
||||||
// against a null layer controller.
|
// against a null layer controller.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmutableViewportMetrics viewport = layerController.getViewportMetrics();
|
ImmutableViewportMetrics viewport = layerClient.getViewportMetrics();
|
||||||
if (RectUtils.fuzzyEquals(mPageRect, viewport.getCssPageRect())) {
|
if (RectUtils.fuzzyEquals(mPageRect, viewport.getCssPageRect())) {
|
||||||
// the page size hasn't changed, so our dirty rect is still valid and we can just
|
// the page size hasn't changed, so our dirty rect is still valid and we can just
|
||||||
// repaint that area
|
// repaint that area
|
||||||
|
@ -2592,9 +2591,9 @@ class ScreenshotHandler implements Runnable {
|
||||||
// this screenshot has all its slices done, so push it out
|
// this screenshot has all its slices done, so push it out
|
||||||
// to the layer renderer and remove it from the list
|
// to the layer renderer and remove it from the list
|
||||||
}
|
}
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
if (layerController != null) {
|
if (layerClient != null) {
|
||||||
layerController.getView().getRenderer().setCheckerboardBitmap(
|
layerClient.getView().getRenderer().setCheckerboardBitmap(
|
||||||
data, bufferWidth, bufferHeight, handler.mPageRect,
|
data, bufferWidth, bufferHeight, handler.mPageRect,
|
||||||
current.getPaintedRegion());
|
current.getPaintedRegion());
|
||||||
}
|
}
|
||||||
|
|
|
@ -227,7 +227,7 @@ public class GeckoEvent {
|
||||||
public void addMotionPoint(int index, int eventIndex, MotionEvent event) {
|
public void addMotionPoint(int index, int eventIndex, MotionEvent event) {
|
||||||
try {
|
try {
|
||||||
PointF geckoPoint = new PointF(event.getX(eventIndex), event.getY(eventIndex));
|
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));
|
mPoints[index] = new Point(Math.round(geckoPoint.x), Math.round(geckoPoint.y));
|
||||||
mPointIndicies[index] = event.getPointerId(eventIndex);
|
mPointIndicies[index] = event.getPointerId(eventIndex);
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||||
import org.mozilla.gecko.gfx.InputConnectionHandler;
|
import org.mozilla.gecko.gfx.InputConnectionHandler;
|
||||||
import org.mozilla.gecko.gfx.LayerController;
|
|
||||||
|
|
||||||
import android.R;
|
import android.R;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -294,8 +294,8 @@ class GeckoInputConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
private static View getView() {
|
private static View getView() {
|
||||||
LayerController controller = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
return (controller == null ? null : controller.getView());
|
return (layerClient == null ? null : layerClient.getView());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Span getSelection() {
|
private Span getSelection() {
|
||||||
|
|
|
@ -131,7 +131,6 @@ FENNEC_JAVA_FILES = \
|
||||||
gfx/InputConnectionHandler.java \
|
gfx/InputConnectionHandler.java \
|
||||||
gfx/IntSize.java \
|
gfx/IntSize.java \
|
||||||
gfx/Layer.java \
|
gfx/Layer.java \
|
||||||
gfx/LayerController.java \
|
|
||||||
gfx/LayerRenderer.java \
|
gfx/LayerRenderer.java \
|
||||||
gfx/LayerView.java \
|
gfx/LayerView.java \
|
||||||
gfx/PluginLayer.java \
|
gfx/PluginLayer.java \
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko;
|
||||||
|
|
||||||
import org.mozilla.gecko.gfx.LayerController;
|
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
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) {
|
public void show(String aTitle, String aText, PromptButton[] aButtons, PromptListItem[] aMenuList, boolean aMultipleSelection) {
|
||||||
final LayerController controller = GeckoApp.mAppContext.getLayerController();
|
final GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
controller.post(new Runnable() {
|
layerClient.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
// treat actions that show a dialog as if preventDefault by content to prevent panning
|
// treat actions that show a dialog as if preventDefault by content to prevent panning
|
||||||
controller.getPanZoomController().abortPanning();
|
layerClient.getPanZoomController().abortPanning();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||||
import org.mozilla.gecko.gfx.Layer;
|
import org.mozilla.gecko.gfx.Layer;
|
||||||
import org.mozilla.gecko.gfx.Layer.RenderContext;
|
import org.mozilla.gecko.gfx.Layer.RenderContext;
|
||||||
import org.mozilla.gecko.gfx.LayerController;
|
|
||||||
import org.mozilla.gecko.util.FloatUtils;
|
import org.mozilla.gecko.util.FloatUtils;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
@ -55,18 +55,18 @@ class TextSelection extends Layer implements GeckoEventListener {
|
||||||
mViewLeft = 0.0f;
|
mViewLeft = 0.0f;
|
||||||
mViewTop = 0.0f;
|
mViewTop = 0.0f;
|
||||||
mViewZoom = 0.0f;
|
mViewZoom = 0.0f;
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
if (layerController != null) {
|
if (layerClient != null) {
|
||||||
layerController.getView().addLayer(TextSelection.this);
|
layerClient.getView().addLayer(TextSelection.this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (event.equals("TextSelection:HideHandles")) {
|
} else if (event.equals("TextSelection:HideHandles")) {
|
||||||
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
if (layerController != null) {
|
if (layerClient != null) {
|
||||||
layerController.getView().removeLayer(TextSelection.this);
|
layerClient.getView().removeLayer(TextSelection.this);
|
||||||
}
|
}
|
||||||
|
|
||||||
mStartHandle.setVisibility(View.GONE);
|
mStartHandle.setVisibility(View.GONE);
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
package org.mozilla.gecko;
|
package org.mozilla.gecko;
|
||||||
|
|
||||||
|
import org.mozilla.gecko.gfx.GeckoLayerClient;
|
||||||
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
|
||||||
import org.mozilla.gecko.gfx.LayerController;
|
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
@ -83,15 +83,15 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
|
||||||
mLeft = mLeft + newX - mTouchStartX;
|
mLeft = mLeft + newX - mTouchStartX;
|
||||||
mTop = mTop + newY - mTouchStartY;
|
mTop = mTop + newY - mTouchStartY;
|
||||||
|
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
if (layerController == null) {
|
if (layerClient == null) {
|
||||||
Log.e(LOGTAG, "Can't move selection because layerController is null");
|
Log.e(LOGTAG, "Can't move selection because layerClient is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Send x coordinate on the right side of the start handle, left side of the end handle.
|
// 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);
|
float left = (float) mLeft + (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
|
||||||
PointF geckoPoint = new PointF(left, (float) mTop);
|
PointF geckoPoint = new PointF(left, (float) mTop);
|
||||||
geckoPoint = layerController.convertViewPointToLayerPoint(geckoPoint);
|
geckoPoint = layerClient.convertViewPointToLayerPoint(geckoPoint);
|
||||||
|
|
||||||
JSONObject args = new JSONObject();
|
JSONObject args = new JSONObject();
|
||||||
try {
|
try {
|
||||||
|
@ -107,14 +107,14 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
void positionFromGecko(int left, int top) {
|
void positionFromGecko(int left, int top) {
|
||||||
LayerController layerController = GeckoApp.mAppContext.getLayerController();
|
GeckoLayerClient layerClient = GeckoApp.mAppContext.getLayerClient();
|
||||||
if (layerController == null) {
|
if (layerClient == null) {
|
||||||
Log.e(LOGTAG, "Can't position handle because layerController is null");
|
Log.e(LOGTAG, "Can't position handle because layerClient is null");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mGeckoPoint = new PointF((float) left, (float) top);
|
mGeckoPoint = new PointF((float) left, (float) top);
|
||||||
ImmutableViewportMetrics metrics = layerController.getViewportMetrics();
|
ImmutableViewportMetrics metrics = layerClient.getViewportMetrics();
|
||||||
repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
|
repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,10 @@ import org.mozilla.gecko.GeckoEvent;
|
||||||
import org.mozilla.gecko.GeckoEventResponder;
|
import org.mozilla.gecko.GeckoEventResponder;
|
||||||
import org.mozilla.gecko.Tab;
|
import org.mozilla.gecko.Tab;
|
||||||
import org.mozilla.gecko.Tabs;
|
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.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
@ -17,20 +21,22 @@ import org.json.JSONObject;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.PointF;
|
import android.graphics.PointF;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.GestureDetector;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
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 static final String LOGTAG = "GeckoLayerClient";
|
||||||
|
|
||||||
private LayerController mLayerController;
|
|
||||||
private LayerRenderer mLayerRenderer;
|
private LayerRenderer mLayerRenderer;
|
||||||
private boolean mLayerRendererInitialized;
|
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. */
|
/* This is written by the compositor thread and read by the UI thread. */
|
||||||
private volatile boolean mCompositorCreated;
|
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) {
|
public GeckoLayerClient(Context context) {
|
||||||
// we can fill these in with dummy values because they are always written
|
// we can fill these in with dummy values because they are always written
|
||||||
// to before being read
|
// to before being read
|
||||||
|
@ -75,16 +108,28 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
mCurrentViewTransform = new ViewTransform(0, 0, 1);
|
mCurrentViewTransform = new ViewTransform(0, 0, 1);
|
||||||
|
|
||||||
mCompositorCreated = false;
|
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. */
|
public void setView(LayerView v) {
|
||||||
void setLayerController(LayerController layerController) {
|
mView = v;
|
||||||
LayerView view = layerController.getView();
|
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()));
|
mRootLayer = new VirtualLayer(new IntSize(mView.getWidth(), mView.getHeight()));
|
||||||
mLayerRenderer = new LayerRenderer(view);
|
mLayerRenderer = new LayerRenderer(mView);
|
||||||
|
|
||||||
GeckoAppShell.registerGeckoEventListener("Viewport:Update", this);
|
GeckoAppShell.registerGeckoEventListener("Viewport:Update", this);
|
||||||
GeckoAppShell.registerGeckoEventListener("Viewport:PageSize", this);
|
GeckoAppShell.registerGeckoEventListener("Viewport:PageSize", this);
|
||||||
|
@ -92,9 +137,8 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
GeckoAppShell.registerGeckoEventListener("Checkerboard:Toggle", this);
|
GeckoAppShell.registerGeckoEventListener("Checkerboard:Toggle", this);
|
||||||
GeckoAppShell.registerGeckoEventListener("Preferences:Data", this);
|
GeckoAppShell.registerGeckoEventListener("Preferences:Data", this);
|
||||||
|
|
||||||
view.setListener(this);
|
mView.setListener(this);
|
||||||
view.setLayerRenderer(mLayerRenderer);
|
mView.setLayerRenderer(mLayerRenderer);
|
||||||
layerController.setRoot(mRootLayer);
|
|
||||||
|
|
||||||
sendResizeEventIfNecessary(true);
|
sendResizeEventIfNecessary(true);
|
||||||
|
|
||||||
|
@ -105,6 +149,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
|
mPanZoomController.destroy();
|
||||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:Update", this);
|
GeckoAppShell.unregisterGeckoEventListener("Viewport:Update", this);
|
||||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:PageSize", this);
|
GeckoAppShell.unregisterGeckoEventListener("Viewport:PageSize", this);
|
||||||
GeckoAppShell.unregisterGeckoEventListener("Viewport:CalculateDisplayPort", this);
|
GeckoAppShell.unregisterGeckoEventListener("Viewport:CalculateDisplayPort", this);
|
||||||
|
@ -112,17 +157,76 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
GeckoAppShell.unregisterGeckoEventListener("Preferences:Data", this);
|
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. */
|
/* Informs Gecko that the screen size has changed. */
|
||||||
private void sendResizeEventIfNecessary(boolean force) {
|
private void sendResizeEventIfNecessary(boolean force) {
|
||||||
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
|
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
|
||||||
View view = mLayerController.getView();
|
|
||||||
|
|
||||||
IntSize newScreenSize = new IntSize(metrics.widthPixels, metrics.heightPixels);
|
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 screenSizeChanged = !mScreenSize.equals(newScreenSize);
|
||||||
boolean windowSizeChanged = !mWindowSize.equals(newWindowSize);
|
boolean windowSizeChanged = !mWindowSize.equals(newWindowSize);
|
||||||
|
@ -163,15 +267,37 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
GeckoAppShell.viewSizeChanged();
|
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) {
|
void adjustViewport(DisplayPortMetrics displayPort) {
|
||||||
ImmutableViewportMetrics metrics = mLayerController.getViewportMetrics();
|
ImmutableViewportMetrics metrics = getViewportMetrics();
|
||||||
|
|
||||||
ViewportMetrics clampedMetrics = new ViewportMetrics(metrics);
|
ViewportMetrics clampedMetrics = new ViewportMetrics(metrics);
|
||||||
clampedMetrics.setViewport(clampedMetrics.getClampedViewport());
|
clampedMetrics.setViewport(clampedMetrics.getClampedViewport());
|
||||||
|
|
||||||
if (displayPort == null) {
|
if (displayPort == null) {
|
||||||
displayPort = DisplayPortCalculator.calculate(metrics,
|
displayPort = DisplayPortCalculator.calculate(metrics, mPanZoomController.getVelocityVector());
|
||||||
mLayerController.getPanZoomController().getVelocityVector());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mDisplayPort = displayPort;
|
mDisplayPort = displayPort;
|
||||||
|
@ -184,6 +310,17 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
GeckoAppShell.sendEventToGecko(GeckoEvent.createViewportEvent(clampedMetrics, displayPort));
|
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
|
* The different types of Viewport messages handled. All viewport events
|
||||||
* expect a display-port to be returned, but can handle one not being
|
* 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. */
|
/** Viewport message handler. */
|
||||||
private void handleViewportMessage(JSONObject message, ViewportMessageType type) throws JSONException {
|
private void handleViewportMessage(JSONObject message, ViewportMessageType type) throws JSONException {
|
||||||
ViewportMetrics messageMetrics = new ViewportMetrics(message);
|
ViewportMetrics messageMetrics = new ViewportMetrics(message);
|
||||||
synchronized (mLayerController) {
|
synchronized (this) {
|
||||||
final ViewportMetrics newMetrics;
|
final ViewportMetrics newMetrics;
|
||||||
ImmutableViewportMetrics oldMetrics = mLayerController.getViewportMetrics();
|
ImmutableViewportMetrics oldMetrics = getViewportMetrics();
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
default:
|
default:
|
||||||
|
@ -207,7 +344,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
newMetrics = messageMetrics;
|
newMetrics = messageMetrics;
|
||||||
// Keep the old viewport size
|
// Keep the old viewport size
|
||||||
newMetrics.setSize(oldMetrics.getSize());
|
newMetrics.setSize(oldMetrics.getSize());
|
||||||
mLayerController.abortPanZoomAnimation();
|
abortPanZoomAnimation();
|
||||||
break;
|
break;
|
||||||
case PAGE_SIZE:
|
case PAGE_SIZE:
|
||||||
// adjust the page dimensions to account for differences in zoom
|
// adjust the page dimensions to account for differences in zoom
|
||||||
|
@ -219,13 +356,13 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mLayerController.post(new Runnable() {
|
post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
mGeckoViewport = newMetrics;
|
mGeckoViewport = newMetrics;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mLayerController.setViewportMetrics(newMetrics);
|
setViewportMetrics(newMetrics);
|
||||||
mDisplayPort = DisplayPortCalculator.calculate(mLayerController.getViewportMetrics(), null);
|
mDisplayPort = DisplayPortCalculator.calculate(getViewportMetrics(), null);
|
||||||
}
|
}
|
||||||
mReturnDisplayPort = mDisplayPort;
|
mReturnDisplayPort = mDisplayPort;
|
||||||
}
|
}
|
||||||
|
@ -242,7 +379,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
mReturnDisplayPort = DisplayPortCalculator.calculate(newMetrics, null);
|
mReturnDisplayPort = DisplayPortCalculator.calculate(newMetrics, null);
|
||||||
} else if ("Checkerboard:Toggle".equals(event)) {
|
} else if ("Checkerboard:Toggle".equals(event)) {
|
||||||
boolean showChecks = message.getBoolean("value");
|
boolean showChecks = message.getBoolean("value");
|
||||||
mLayerController.setCheckerboardShowChecks(showChecks);
|
setCheckerboardShowChecks(showChecks);
|
||||||
Log.i(LOGTAG, "Showing checks: " + showChecks);
|
Log.i(LOGTAG, "Showing checks: " + showChecks);
|
||||||
} else if ("Preferences:Data".equals(event)) {
|
} else if ("Preferences:Data".equals(event)) {
|
||||||
JSONArray jsonPrefs = message.getJSONArray("preferences");
|
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
|
* 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
|
* 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;
|
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.
|
/** 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
|
* 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
|
* 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,
|
public void setFirstPaintViewport(float offsetX, float offsetY, float zoom,
|
||||||
float pageLeft, float pageTop, float pageRight, float pageBottom,
|
float pageLeft, float pageTop, float pageRight, float pageBottom,
|
||||||
float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
|
float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
|
||||||
synchronized (mLayerController) {
|
synchronized (this) {
|
||||||
final ViewportMetrics currentMetrics = new ViewportMetrics(mLayerController.getViewportMetrics());
|
final ViewportMetrics currentMetrics = new ViewportMetrics(getViewportMetrics());
|
||||||
currentMetrics.setOrigin(new PointF(offsetX, offsetY));
|
currentMetrics.setOrigin(new PointF(offsetX, offsetY));
|
||||||
currentMetrics.setZoomFactor(zoom);
|
currentMetrics.setZoomFactor(zoom);
|
||||||
currentMetrics.setPageRect(new RectF(pageLeft, pageTop, pageRight, pageBottom),
|
currentMetrics.setPageRect(new RectF(pageLeft, pageTop, pageRight, pageBottom),
|
||||||
new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom));
|
new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom));
|
||||||
// Since we have switched to displaying a different document, we need to update any
|
// 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-related state we have lying around. This includes mGeckoViewport and
|
||||||
// viewport in mLayerController. Usually this information is updated via handleViewportMessage
|
// mViewportMetrics. Usually this information is updated via handleViewportMessage
|
||||||
// while we remain on the same document.
|
// while we remain on the same document.
|
||||||
mLayerController.post(new Runnable() {
|
post(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
mGeckoViewport = currentMetrics;
|
mGeckoViewport = currentMetrics;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mLayerController.setViewportMetrics(currentMetrics);
|
setViewportMetrics(currentMetrics);
|
||||||
|
|
||||||
Tab tab = Tabs.getInstance().getSelectedTab();
|
Tab tab = Tabs.getInstance().getSelectedTab();
|
||||||
mLayerController.setCheckerboardColor(tab.getCheckerboardColor());
|
setCheckerboardColor(tab.getCheckerboardColor());
|
||||||
mLayerController.setZoomConstraints(tab.getZoomConstraints());
|
setZoomConstraints(tab.getZoomConstraints());
|
||||||
|
|
||||||
// At this point, we have just switched to displaying a different document than we
|
// 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
|
// 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
|
// 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
|
// 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.
|
// be out of sync with this first-paint viewport, then we force them back in sync.
|
||||||
mLayerController.abortPanZoomAnimation();
|
abortPanZoomAnimation();
|
||||||
mLayerController.getView().setPaintState(LayerView.PAINT_BEFORE_FIRST);
|
mView.setPaintState(LayerView.PAINT_BEFORE_FIRST);
|
||||||
}
|
}
|
||||||
DisplayPortCalculator.resetPageState();
|
DisplayPortCalculator.resetPageState();
|
||||||
mDrawTimingQueue.reset();
|
mDrawTimingQueue.reset();
|
||||||
mLayerController.getView().getRenderer().resetCheckerboard();
|
mView.getRenderer().resetCheckerboard();
|
||||||
GeckoAppShell.screenshotWholePage(Tabs.getInstance().getSelectedTab());
|
GeckoAppShell.screenshotWholePage(Tabs.getInstance().getSelectedTab());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,10 +511,10 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
* function will be invoked before syncViewportInfo.
|
* function will be invoked before syncViewportInfo.
|
||||||
*/
|
*/
|
||||||
public void setPageRect(float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
|
public void setPageRect(float cssPageLeft, float cssPageTop, float cssPageRight, float cssPageBottom) {
|
||||||
synchronized (mLayerController) {
|
synchronized (this) {
|
||||||
RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
|
RectF cssPageRect = new RectF(cssPageLeft, cssPageTop, cssPageRight, cssPageBottom);
|
||||||
float ourZoom = mLayerController.getViewportMetrics().zoomFactor;
|
float ourZoom = getViewportMetrics().zoomFactor;
|
||||||
mLayerController.setPageRect(RectUtils.scale(cssPageRect, ourZoom), cssPageRect);
|
setPageRect(RectUtils.scale(cssPageRect, ourZoom), cssPageRect);
|
||||||
// Here the page size of the document has changed, but the document being displayed
|
// 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
|
// 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
|
// 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.
|
* which would avoid the copy into mCurrentViewTransform.
|
||||||
*/
|
*/
|
||||||
public ViewTransform syncViewportInfo(int x, int y, int width, int height, float resolution, boolean layersUpdated) {
|
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
|
// getViewportMetrics is thread safe so we don't need to synchronize.
|
||||||
// on mLayerController.
|
|
||||||
// We save the viewport metrics here, so we later use it later in
|
// We save the viewport metrics here, so we later use it later in
|
||||||
// createFrame (which will be called by nsWindow::DrawWindowUnderlay on
|
// 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
|
// metrics can change between here and there, as it's accessed outside
|
||||||
// of the compositor thread.
|
// of the compositor thread.
|
||||||
mFrameMetrics = mLayerController.getViewportMetrics();
|
mFrameMetrics = getViewportMetrics();
|
||||||
|
|
||||||
mCurrentViewTransform.x = mFrameMetrics.viewportRectLeft;
|
mCurrentViewTransform.x = mFrameMetrics.viewportRectLeft;
|
||||||
mCurrentViewTransform.y = mFrameMetrics.viewportRectTop;
|
mCurrentViewTransform.y = mFrameMetrics.viewportRectTop;
|
||||||
|
@ -438,6 +589,14 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
mLayerRenderer.deactivateDefaultProgram();
|
mLayerRenderer.deactivateDefaultProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void geometryChanged() {
|
||||||
|
/* Let Gecko know if the screensize has changed */
|
||||||
|
sendResizeEventIfNecessary(false);
|
||||||
|
if (getRedrawHint()) {
|
||||||
|
adjustViewport(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Implementation of LayerView.Listener */
|
/** Implementation of LayerView.Listener */
|
||||||
public void renderRequested() {
|
public void renderRequested() {
|
||||||
GeckoAppShell.scheduleComposite();
|
GeckoAppShell.scheduleComposite();
|
||||||
|
@ -472,7 +631,7 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
|
|
||||||
/** Implementation of LayerView.Listener */
|
/** Implementation of LayerView.Listener */
|
||||||
public void surfaceChanged(int width, int height) {
|
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
|
// We need to make this call even when the compositor isn't currently
|
||||||
// paused (e.g. during an orientation change), to make the compositor
|
// paused (e.g. during an orientation change), to make the compositor
|
||||||
|
@ -486,6 +645,89 @@ public class GeckoLayerClient implements GeckoEventResponder, LayerView.Listener
|
||||||
mCompositorCreated = true;
|
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. */
|
/** Used by robocop for testing purposes. Not for production use! This is called via reflection by robocop. */
|
||||||
public void setDrawListener(DrawListener listener) {
|
public void setDrawListener(DrawListener listener) {
|
||||||
mDrawListener = listener;
|
mDrawListener = listener;
|
||||||
|
|
|
@ -1,270 +0,0 @@
|
||||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
package org.mozilla.gecko.gfx;
|
|
||||||
|
|
||||||
import org.mozilla.gecko.ZoomConstraints;
|
|
||||||
import org.mozilla.gecko.ui.PanZoomController;
|
|
||||||
import org.mozilla.gecko.ui.PanZoomTarget;
|
|
||||||
import org.mozilla.gecko.ui.SimpleScaleGestureDetector;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.PointF;
|
|
||||||
import android.graphics.RectF;
|
|
||||||
import android.util.DisplayMetrics;
|
|
||||||
import android.view.GestureDetector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The layer controller manages a tile that represents the visible page. It does panning and
|
|
||||||
* zooming natively by delegating to a panning/zooming controller. Touch events can be dispatched
|
|
||||||
* to a higher-level view.
|
|
||||||
*
|
|
||||||
* Many methods require that the monitor be held, with a synchronized (controller) { ... } block.
|
|
||||||
*/
|
|
||||||
public class LayerController implements PanZoomTarget {
|
|
||||||
private static final String LOGTAG = "GeckoLayerController";
|
|
||||||
|
|
||||||
private Layer mRootLayer; /* The root layer. */
|
|
||||||
private LayerView mView; /* The main rendering view. */
|
|
||||||
private Context mContext; /* The current context. */
|
|
||||||
|
|
||||||
/* This is volatile so that we can read and write to it from different threads.
|
|
||||||
* We avoid synchronization to make getting the viewport metrics from
|
|
||||||
* the compositor as cheap as possible. The viewport is immutable so
|
|
||||||
* we don't need to worry about anyone mutating it while we're reading from it.
|
|
||||||
* Specifically:
|
|
||||||
* 1) reading mViewportMetrics from any thread is fine without synchronization
|
|
||||||
* 2) writing to mViewportMetrics requires synchronizing on the layer controller object
|
|
||||||
* 3) whenver reading multiple fields from mViewportMetrics without synchronization (i.e. in
|
|
||||||
* case 1 above) you should always frist grab a local copy of the reference, and then use
|
|
||||||
* that because mViewportMetrics might get reassigned in between reading the different
|
|
||||||
* fields. */
|
|
||||||
private volatile ImmutableViewportMetrics mViewportMetrics; /* The current viewport metrics. */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The panning and zooming controller, which interprets pan and zoom gestures for us and
|
|
||||||
* updates our visible rect appropriately.
|
|
||||||
*/
|
|
||||||
private PanZoomController mPanZoomController;
|
|
||||||
|
|
||||||
private GeckoLayerClient mLayerClient; /* The layer client. */
|
|
||||||
|
|
||||||
/* The new color for the checkerboard. */
|
|
||||||
private int mCheckerboardColor = Color.WHITE;
|
|
||||||
private boolean mCheckerboardShouldShowChecks;
|
|
||||||
|
|
||||||
private ZoomConstraints mZoomConstraints;
|
|
||||||
|
|
||||||
private boolean mForceRedraw;
|
|
||||||
|
|
||||||
public LayerController(Context context) {
|
|
||||||
mContext = context;
|
|
||||||
mForceRedraw = true;
|
|
||||||
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
|
|
||||||
mViewportMetrics = new ImmutableViewportMetrics(new ViewportMetrics(displayMetrics));
|
|
||||||
mPanZoomController = new PanZoomController(this);
|
|
||||||
mCheckerboardShouldShowChecks = true;
|
|
||||||
mZoomConstraints = new ZoomConstraints(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setView(LayerView v) {
|
|
||||||
mView = v;
|
|
||||||
mView.connect(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoot(Layer layer) { mRootLayer = layer; }
|
|
||||||
|
|
||||||
public void setLayerClient(GeckoLayerClient layerClient) {
|
|
||||||
mLayerClient = layerClient;
|
|
||||||
layerClient.setLayerController(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void destroy() {
|
|
||||||
mPanZoomController.destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setForceRedraw() {
|
|
||||||
mForceRedraw = true;
|
|
||||||
notifyLayerClientOfGeometryChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Layer getRoot() { return mRootLayer; }
|
|
||||||
public LayerView getView() { return mView; }
|
|
||||||
public Context getContext() { return mContext; }
|
|
||||||
public ImmutableViewportMetrics getViewportMetrics() { return mViewportMetrics; }
|
|
||||||
public Object getLock() { return this; }
|
|
||||||
|
|
||||||
public FloatSize getViewportSize() {
|
|
||||||
return mViewportMetrics.getSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PanZoomController getPanZoomController() { return mPanZoomController; }
|
|
||||||
public GestureDetector.OnGestureListener getGestureListener() { return mPanZoomController; }
|
|
||||||
public SimpleScaleGestureDetector.SimpleScaleGestureListener getScaleGestureListener() {
|
|
||||||
return mPanZoomController;
|
|
||||||
}
|
|
||||||
public GestureDetector.OnDoubleTapListener getDoubleTapListener() { return mPanZoomController; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The view calls this function to indicate that the viewport changed size. It must hold the
|
|
||||||
* monitor while calling it.
|
|
||||||
*
|
|
||||||
* TODO: Refactor this to use an interface. Expose that interface only to the view and not
|
|
||||||
* to the layer client. That way, the layer client won't be tempted to call this, which might
|
|
||||||
* result in an infinite loop.
|
|
||||||
*/
|
|
||||||
public void setViewportSize(FloatSize size) {
|
|
||||||
ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
|
|
||||||
viewportMetrics.setSize(size);
|
|
||||||
mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
|
|
||||||
|
|
||||||
if (mLayerClient != null) {
|
|
||||||
mLayerClient.viewportSizeChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets the current page rect. You must hold the monitor while calling this. */
|
|
||||||
public void setPageRect(RectF rect, RectF cssRect) {
|
|
||||||
// Since the "rect" is always just a multiple of "cssRect" we don't need to
|
|
||||||
// check both; this function assumes that both "rect" and "cssRect" are relative
|
|
||||||
// the zoom factor in mViewportMetrics.
|
|
||||||
if (mViewportMetrics.getCssPageRect().equals(cssRect))
|
|
||||||
return;
|
|
||||||
|
|
||||||
ViewportMetrics viewportMetrics = new ViewportMetrics(mViewportMetrics);
|
|
||||||
viewportMetrics.setPageRect(rect, cssRect);
|
|
||||||
mViewportMetrics = new ImmutableViewportMetrics(viewportMetrics);
|
|
||||||
|
|
||||||
// Page size is owned by the layer client, so no need to notify it of
|
|
||||||
// this change.
|
|
||||||
|
|
||||||
mView.post(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
mPanZoomController.pageRectUpdated();
|
|
||||||
mView.requestRender();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the entire viewport metrics at once.
|
|
||||||
* You must hold the monitor while calling this.
|
|
||||||
*/
|
|
||||||
public void setViewportMetrics(ViewportMetrics viewport) {
|
|
||||||
mViewportMetrics = new ImmutableViewportMetrics(viewport);
|
|
||||||
mView.requestRender();
|
|
||||||
notifyLayerClientOfGeometryChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnimationTarget(ViewportMetrics viewport) {
|
|
||||||
if (mLayerClient != null) {
|
|
||||||
// We know what the final viewport of the animation is going to be, so
|
|
||||||
// immediately request a draw of that area by setting the display port
|
|
||||||
// accordingly. This way we should have the content pre-rendered by the
|
|
||||||
// time the animation is done.
|
|
||||||
ImmutableViewportMetrics metrics = new ImmutableViewportMetrics(viewport);
|
|
||||||
DisplayPortMetrics displayPort = DisplayPortCalculator.calculate(metrics, null);
|
|
||||||
mLayerClient.adjustViewport(displayPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean post(Runnable action) { return mView.post(action); }
|
|
||||||
|
|
||||||
private void notifyLayerClientOfGeometryChange() {
|
|
||||||
if (mLayerClient != null)
|
|
||||||
mLayerClient.geometryChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Aborts any pan/zoom animation that is currently in progress. */
|
|
||||||
public void abortPanZoomAnimation() {
|
|
||||||
if (mPanZoomController != null) {
|
|
||||||
mView.post(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
mPanZoomController.abortAnimation();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if this controller is fine with performing a redraw operation or false if it
|
|
||||||
* would prefer that the action didn't take place.
|
|
||||||
*/
|
|
||||||
public boolean getRedrawHint() {
|
|
||||||
if (mForceRedraw) {
|
|
||||||
mForceRedraw = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mPanZoomController.getRedrawHint()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DisplayPortCalculator.aboutToCheckerboard(mViewportMetrics,
|
|
||||||
mPanZoomController.getVelocityVector(), mLayerClient.getDisplayPort());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a point from layer view coordinates to layer coordinates. In other words, given a
|
|
||||||
* point measured in pixels from the top left corner of the layer view, returns the point in
|
|
||||||
* pixels measured from the last scroll position we sent to Gecko, in CSS pixels. Assuming the
|
|
||||||
* events being sent to Gecko are processed in FIFO order, this calculation should always be
|
|
||||||
* correct.
|
|
||||||
*/
|
|
||||||
public PointF convertViewPointToLayerPoint(PointF viewPoint) {
|
|
||||||
if (mLayerClient == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImmutableViewportMetrics viewportMetrics = mViewportMetrics;
|
|
||||||
PointF origin = viewportMetrics.getOrigin();
|
|
||||||
float zoom = viewportMetrics.zoomFactor;
|
|
||||||
ViewportMetrics geckoViewport = mLayerClient.getGeckoViewportMetrics();
|
|
||||||
PointF geckoOrigin = geckoViewport.getOrigin();
|
|
||||||
float geckoZoom = geckoViewport.getZoomFactor();
|
|
||||||
|
|
||||||
// viewPoint + origin gives the coordinate in device pixels from the top-left corner of the page.
|
|
||||||
// Divided by zoom, this gives us the coordinate in CSS pixels from the top-left corner of the page.
|
|
||||||
// geckoOrigin / geckoZoom is where Gecko thinks it is (scrollTo position) in CSS pixels from
|
|
||||||
// the top-left corner of the page. Subtracting the two gives us the offset of the viewPoint from
|
|
||||||
// the current Gecko coordinate in CSS pixels.
|
|
||||||
PointF layerPoint = new PointF(
|
|
||||||
((viewPoint.x + origin.x) / zoom) - (geckoOrigin.x / geckoZoom),
|
|
||||||
((viewPoint.y + origin.y) / zoom) - (geckoOrigin.y / geckoZoom));
|
|
||||||
|
|
||||||
return layerPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieves whether we should show checkerboard checks or not. */
|
|
||||||
public boolean checkerboardShouldShowChecks() {
|
|
||||||
return mCheckerboardShouldShowChecks;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Retrieves the color that the checkerboard should be. */
|
|
||||||
public int getCheckerboardColor() {
|
|
||||||
return mCheckerboardColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets whether or not the checkerboard should show checkmarks. */
|
|
||||||
public void setCheckerboardShowChecks(boolean showChecks) {
|
|
||||||
mCheckerboardShouldShowChecks = showChecks;
|
|
||||||
mView.requestRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Sets a new color for the checkerboard. */
|
|
||||||
public void setCheckerboardColor(int newColor) {
|
|
||||||
mCheckerboardColor = newColor;
|
|
||||||
mView.requestRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setZoomConstraints(ZoomConstraints constraints) {
|
|
||||||
mZoomConstraints = constraints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ZoomConstraints getZoomConstraints() {
|
|
||||||
return mZoomConstraints;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -445,7 +445,7 @@ public class LayerRenderer {
|
||||||
|
|
||||||
mUpdated = true;
|
mUpdated = true;
|
||||||
|
|
||||||
Layer rootLayer = mView.getController().getRoot();
|
Layer rootLayer = mView.getLayerClient().getRoot();
|
||||||
|
|
||||||
if (!mPageContext.fuzzyEquals(mLastPageContext)) {
|
if (!mPageContext.fuzzyEquals(mLastPageContext)) {
|
||||||
// the viewport or page changed, so show the scrollbars again
|
// the viewport or page changed, so show the scrollbars again
|
||||||
|
@ -518,7 +518,7 @@ public class LayerRenderer {
|
||||||
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
|
GLES20.glDisable(GLES20.GL_SCISSOR_TEST);
|
||||||
|
|
||||||
/* Update background color. */
|
/* Update background color. */
|
||||||
mBackgroundColor = mView.getController().getCheckerboardColor();
|
mBackgroundColor = mView.getLayerClient().getCheckerboardColor();
|
||||||
|
|
||||||
/* Clear to the page background colour. The bits set here need to
|
/* Clear to the page background colour. The bits set here need to
|
||||||
* match up with those used in gfx/layers/opengl/LayerManagerOGL.cpp.
|
* 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
|
/* Draw the 'checkerboard'. We use gfx.show_checkerboard_pattern to
|
||||||
* determine whether to draw the screenshot layer.
|
* 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 */
|
/* 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);
|
mCheckerboardLayer.setMask(rootMask);
|
||||||
|
|
||||||
/* Scissor around the page-rect, in case the page has shrunk
|
/* 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.
|
// Draws the layer the client added to us.
|
||||||
void drawRootLayer() {
|
void drawRootLayer() {
|
||||||
Layer rootLayer = mView.getController().getRoot();
|
Layer rootLayer = mView.getLayerClient().getRoot();
|
||||||
if (rootLayer == null) {
|
if (rootLayer == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -590,7 +590,7 @@ public class LayerRenderer {
|
||||||
mHorizScrollLayer.draw(mPageContext);
|
mHorizScrollLayer.draw(mPageContext);
|
||||||
|
|
||||||
/* Measure how much of the screen is checkerboarding */
|
/* Measure how much of the screen is checkerboarding */
|
||||||
Layer rootLayer = mView.getController().getRoot();
|
Layer rootLayer = mView.getLayerClient().getRoot();
|
||||||
if ((rootLayer != null) &&
|
if ((rootLayer != null) &&
|
||||||
(mProfileRender || PanningPerfAPI.isRecordingCheckerboard())) {
|
(mProfileRender || PanningPerfAPI.isRecordingCheckerboard())) {
|
||||||
// Find out how much of the viewport area is valid
|
// Find out how much of the viewport area is valid
|
||||||
|
|
|
@ -34,15 +34,12 @@ import java.lang.reflect.Method;
|
||||||
/**
|
/**
|
||||||
* A view rendered by the layer compositor.
|
* 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.
|
* Note that LayerView is accessed by Robocop via reflection.
|
||||||
*/
|
*/
|
||||||
public class LayerView extends FrameLayout {
|
public class LayerView extends FrameLayout {
|
||||||
private static String LOGTAG = "GeckoLayerView";
|
private static String LOGTAG = "GeckoLayerView";
|
||||||
|
|
||||||
private LayerController mController;
|
private GeckoLayerClient mLayerClient;
|
||||||
private TouchEventHandler mTouchEventHandler;
|
private TouchEventHandler mTouchEventHandler;
|
||||||
private GLController mGLController;
|
private GLController mGLController;
|
||||||
private InputConnectionHandler mInputConnectionHandler;
|
private InputConnectionHandler mInputConnectionHandler;
|
||||||
|
@ -98,9 +95,9 @@ public class LayerView extends FrameLayout {
|
||||||
mGLController = new GLController(this);
|
mGLController = new GLController(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect(LayerController controller) {
|
void connect(GeckoLayerClient layerClient) {
|
||||||
mController = controller;
|
mLayerClient = layerClient;
|
||||||
mTouchEventHandler = new TouchEventHandler(getContext(), this, mController);
|
mTouchEventHandler = new TouchEventHandler(getContext(), this, layerClient);
|
||||||
mRenderer = new LayerRenderer(this);
|
mRenderer = new LayerRenderer(this);
|
||||||
mInputConnectionHandler = null;
|
mInputConnectionHandler = null;
|
||||||
|
|
||||||
|
@ -125,12 +122,12 @@ public class LayerView extends FrameLayout {
|
||||||
return mTouchEventHandler.handleEvent(event);
|
return mTouchEventHandler.handleEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LayerController getController() { return mController; }
|
public GeckoLayerClient getLayerClient() { return mLayerClient; }
|
||||||
public TouchEventHandler getTouchEventHandler() { return mTouchEventHandler; }
|
public TouchEventHandler getTouchEventHandler() { return mTouchEventHandler; }
|
||||||
|
|
||||||
/** The LayerRenderer calls this to indicate that the window has changed size. */
|
/** The LayerRenderer calls this to indicate that the window has changed size. */
|
||||||
public void setViewportSize(IntSize size) {
|
public void setViewportSize(IntSize size) {
|
||||||
mController.setViewportSize(new FloatSize(size));
|
mLayerClient.setViewportSize(new FloatSize(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInputConnectionHandler(InputConnectionHandler inputConnectionHandler) {
|
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. */
|
/** This function is invoked by Gecko (compositor thread) via JNI; be careful when modifying signature. */
|
||||||
public static GLController registerCxxCompositor() {
|
public static GLController registerCxxCompositor() {
|
||||||
try {
|
try {
|
||||||
LayerView layerView = GeckoApp.mAppContext.getLayerController().getView();
|
LayerView layerView = GeckoApp.mAppContext.getLayerClient().getView();
|
||||||
layerView.mListener.compositorCreated();
|
layerView.mListener.compositorCreated();
|
||||||
return layerView.getGLController();
|
return layerView.getGLController();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -125,17 +125,17 @@ public final class TouchEventHandler implements Tabs.OnTabsChangedListener {
|
||||||
// processed. (n is the absolute value of the balance.)
|
// processed. (n is the absolute value of the balance.)
|
||||||
private int mProcessingBalance;
|
private int mProcessingBalance;
|
||||||
|
|
||||||
TouchEventHandler(Context context, LayerView view, LayerController controller) {
|
TouchEventHandler(Context context, LayerView view, GeckoLayerClient layerClient) {
|
||||||
mView = view;
|
mView = view;
|
||||||
|
|
||||||
mEventQueue = new LinkedList<MotionEvent>();
|
mEventQueue = new LinkedList<MotionEvent>();
|
||||||
mGestureDetector = new GestureDetector(context, controller.getGestureListener());
|
mGestureDetector = new GestureDetector(context, layerClient.getGestureListener());
|
||||||
mScaleGestureDetector = new SimpleScaleGestureDetector(controller.getScaleGestureListener());
|
mScaleGestureDetector = new SimpleScaleGestureDetector(layerClient.getScaleGestureListener());
|
||||||
mPanZoomController = controller.getPanZoomController();
|
mPanZoomController = layerClient.getPanZoomController();
|
||||||
mListenerTimeoutProcessor = new ListenerTimeoutProcessor();
|
mListenerTimeoutProcessor = new ListenerTimeoutProcessor();
|
||||||
mDispatchEvents = true;
|
mDispatchEvents = true;
|
||||||
|
|
||||||
mGestureDetector.setOnDoubleTapListener(controller.getDoubleTapListener());
|
mGestureDetector.setOnDoubleTapListener(layerClient.getDoubleTapListener());
|
||||||
|
|
||||||
Tabs.registerOnTabsChangedListener(this);
|
Tabs.registerOnTabsChangedListener(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ class MotionEventReplayer {
|
||||||
// edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=21972329,
|
// edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=21972329,
|
||||||
// downTime=21972329, deviceId=6, source=0x1002 }
|
// 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
|
// onTouchEvent function on a phone running Ice Cream Sandwich. Different
|
||||||
// Android versions have different serializations of the motion event, and this
|
// Android versions have different serializations of the motion event, and this
|
||||||
// code could probably be modified to parse other serializations if needed.
|
// code could probably be modified to parse other serializations if needed.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче