Bug 1197811 - Turn the LayerView into a ScrollView that scrolls to shift the surface rather than using setTranslation. r=rbarker

On Gingerbread devices (Android API 9 or 10) the ViewHelper.setTranslationY code
doesn't work to move the SurfaceView. In order to acheive that effect I turned
LayerView into a ScrollView with a dummy element at the top, and allow it to
scroll. This allows the SurfaceView to move as desired. A few places in the code
were assuming that the LayerView and SurfaceView were always at the same screen
location (which was true before but not any more) and so those sites needed
some updating as well.

--HG--
extra : commitid : Jpr1k74MOAD
This commit is contained in:
Kartikaya Gupta 2015-08-28 17:22:17 -04:00
Родитель 587a360099
Коммит 42112ad989
7 изменённых файлов: 94 добавлений и 23 удалений

Просмотреть файл

@ -1636,7 +1636,7 @@ public class BrowserApp extends GeckoApp
if (mLayerView != null && height != mToolbarHeight) {
mToolbarHeight = height;
mLayerView.getDynamicToolbarAnimator().setMaxTranslation(height);
mLayerView.setMaxTranslation(height);
mDynamicToolbar.setVisible(true, VisibilityTransition.IMMEDIATE);
}
}

Просмотреть файл

@ -125,28 +125,24 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
}
private void move(float newX, float newY) {
LayerView layerView = GeckoAppShell.getLayerView();
// newX and newY are in screen coordinates, but mLeft/mTop are relative
// to the ancestor (which is what LayerView is relative to also). So,
// we need to adjust them newX/newY. The |ancestorOrigin| variable computed
// we need to adjust newX/newY. The |ancestorOrigin| variable computed
// below is the origin of the ancestor relative to the screen coordinates,
// so subtracting that from newY puts newY into the desired coordinate
// space. We also need to include the offset amount of the touch location
// relative to the top left of the handle (mTouchStart).
float layerViewTranslation = GeckoAppShell.getLayerView().getSurfaceTranslation();
int[] layerViewPosition = new int[2];
GeckoAppShell.getLayerView().getLocationOnScreen(layerViewPosition);
float ancestorOrigin = layerViewPosition[1] - layerViewTranslation;
layerView.getLocationOnScreen(layerViewPosition);
float ancestorOrigin = layerViewPosition[1];
mLeft = newX - mTouchStart.x;
mTop = newY - mTouchStart.y - ancestorOrigin;
LayerView layerView = GeckoAppShell.getLayerView();
if (layerView == null) {
Log.e(LOGTAG, "Can't move selection because layerView is null");
return;
}
// Send x coordinate on the right side of the start handle, left side of the end handle.
float layerViewTranslation = layerView.getSurfaceTranslation();
PointF geckoPoint = new PointF(mLeft + adjustLeftForHandle(),
mTop - layerViewTranslation);
geckoPoint = layerView.convertViewPointToLayerPoint(geckoPoint);

Просмотреть файл

@ -165,6 +165,9 @@ public class ZoomedView extends FrameLayout implements LayerView.DynamicToolbarL
layerView.dispatchTouchEvent(actionDownEvent);
actionDownEvent.recycle();
PointF convertedPosition = getUnzoomedPositionFromPointInZoomedView(event.getX(), event.getY());
// the LayerView expects the coordinates relative to the window, not the surface, so we need
// to adjust that here.
convertedPosition.y += layerView.getSurfaceTranslation();
MotionEvent e = MotionEvent.obtain(event.getDownTime(), event.getEventTime(),
MotionEvent.ACTION_UP, convertedPosition.x, convertedPosition.y,
event.getMetaState());
@ -179,6 +182,9 @@ public class ZoomedView extends FrameLayout implements LayerView.DynamicToolbarL
originRawX = event.getRawX();
originRawY = event.getRawY();
PointF convertedPosition = getUnzoomedPositionFromPointInZoomedView(event.getX(), event.getY());
// the LayerView expects the coordinates relative to the window, not the surface, so we need
// to adjust that here.
convertedPosition.y += layerView.getSurfaceTranslation();
actionDownEvent = MotionEvent.obtain(event.getDownTime(), event.getEventTime(),
MotionEvent.ACTION_DOWN, convertedPosition.x, convertedPosition.y,
event.getMetaState());

Просмотреть файл

@ -148,6 +148,10 @@ public class DynamicToolbarAnimator {
}
}
public float getMaxTranslation() {
return mMaxTranslation;
}
public float getToolbarTranslation() {
return mToolbarTranslation;
}

Просмотреть файл

@ -10,7 +10,6 @@ import java.nio.IntBuffer;
import java.util.ArrayList;
import org.mozilla.gecko.AndroidGamepadManager;
import org.mozilla.gecko.animation.ViewHelper;
import org.mozilla.gecko.annotation.RobocopTarget;
import org.mozilla.gecko.annotation.WrapForJNI;
import org.mozilla.gecko.AppConstants.Versions;
@ -45,12 +44,13 @@ import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.view.InputDevice;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ScrollView;
/**
* A view rendered by the layer compositor.
*/
public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener {
public class LayerView extends ScrollView implements Tabs.OnTabsChangedListener {
private static final String LOGTAG = "GeckoLayerView";
private GeckoLayerClient mLayerClient;
@ -66,12 +66,15 @@ public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener
private SurfaceView mSurfaceView;
private TextureView mTextureView;
private View mFillerView;
private Listener mListener;
private PointF mInitialTouchPoint;
private boolean mGeckoIsReady;
private float mSurfaceTranslation;
/* This should only be modified on the Java UI thread. */
private final Overscroll mOverscroll;
@ -233,6 +236,7 @@ public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
requestFocus();
}
event.offsetLocation(0, -mSurfaceTranslation);
if (mToolbarAnimator != null && mToolbarAnimator.onInterceptTouchEvent(event)) {
return true;
@ -289,7 +293,25 @@ public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener
mSurfaceView = new LayerSurfaceView(getContext(), this);
mSurfaceView.setBackgroundColor(Color.WHITE);
addView(mSurfaceView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
// The "filler" view sits behind the URL bar and should never be
// visible. It exists solely to make this LayerView actually
// scrollable so that we can shift the surface around on the screen.
// Once we drop support for pre-Honeycomb Android versions this
// should not be needed; we can just turn LayerView back into a
// FrameLayout that holds mSurfaceView and nothing else.
mFillerView = new View(getContext()) {
@Override protected void onMeasure(int aWidthSpec, int aHeightSpec) {
setMeasuredDimension(0, Math.round(mToolbarAnimator.getMaxTranslation()));
}
};
mFillerView.setBackgroundColor(Color.RED);
LinearLayout container = new LinearLayout(getContext());
container.setOrientation(LinearLayout.VERTICAL);
container.addView(mFillerView);
container.addView(mSurfaceView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
addView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
SurfaceHolder holder = mSurfaceView.getHolder();
holder.addCallback(new SurfaceListener());
@ -570,19 +592,48 @@ public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener
}
}
@Override
protected void onMeasure(int aWidthSpec, int aHeightSpec) {
super.onMeasure(aWidthSpec, aHeightSpec);
if (mSurfaceView != null) {
// Because of the crazy setup where this LayerView is a ScrollView
// and the SurfaceView is inside a LinearLayout, the SurfaceView
// doesn't get the right information to size itself the way we want.
// We always want it to be the same size as this LayerView, so we
// use a hack to make sure it sizes itself that way.
((LayerSurfaceView)mSurfaceView).overrideSize(getMeasuredWidth(), getMeasuredHeight());
}
}
/* A subclass of SurfaceView to listen to layout changes, as
* View.OnLayoutChangeListener requires API level 11.
*/
private class LayerSurfaceView extends SurfaceView {
LayerView mParent;
private LayerView mParent;
private int mForcedWidth;
private int mForcedHeight;
public LayerSurfaceView(Context aContext, LayerView aParent) {
super(aContext);
mParent = aParent;
}
void overrideSize(int aWidth, int aHeight) {
if (mForcedWidth != aWidth || mForcedHeight != aHeight) {
mForcedWidth = aWidth;
mForcedHeight = aHeight;
requestLayout();
}
}
@Override
protected void onMeasure(int aWidthSpec, int aHeightSpec) {
setMeasuredDimension(mForcedWidth, mForcedHeight);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
mParent.surfaceChanged(right - left, bottom - top);
}
@ -664,12 +715,24 @@ public class LayerView extends FrameLayout implements Tabs.OnTabsChangedListener
return mFullScreenState;
}
public void setMaxTranslation(float aMaxTranslation) {
mToolbarAnimator.setMaxTranslation(aMaxTranslation);
if (mFillerView != null) {
mFillerView.requestLayout();
}
}
public void setSurfaceTranslation(float translation) {
ViewHelper.setTranslationY(this, translation);
// Once we drop support for pre-Honeycomb Android versions, we can
// revert bug 1197811 and just use ViewHelper here.
if (mSurfaceTranslation != translation) {
mSurfaceTranslation = translation;
scrollTo(0, Math.round(mToolbarAnimator.getMaxTranslation() - translation));
}
}
public float getSurfaceTranslation() {
return ViewHelper.getTranslationY(this);
return mSurfaceTranslation;
}
@Override

Просмотреть файл

@ -124,24 +124,25 @@ public class OverscrollEdgeEffect implements Overscroll {
return;
}
float fillerSize = mView.getDynamicToolbarAnimator().getMaxTranslation();
PointF visibleEnd = mView.getDynamicToolbarAnimator().getVisibleEndOfLayerView();
// If we're pulling an edge, or fading it out, draw!
boolean invalidate = false;
if (!mEdges[TOP].isFinished()) {
invalidate |= draw(mEdges[TOP], canvas, 0, 0, 0);
invalidate |= draw(mEdges[TOP], canvas, 0, fillerSize, 0);
}
if (!mEdges[BOTTOM].isFinished()) {
invalidate |= draw(mEdges[BOTTOM], canvas, visibleEnd.x, visibleEnd.y, 180);
invalidate |= draw(mEdges[BOTTOM], canvas, visibleEnd.x, fillerSize + visibleEnd.y, 180);
}
if (!mEdges[LEFT].isFinished()) {
invalidate |= draw(mEdges[LEFT], canvas, 0, visibleEnd.y, 270);
invalidate |= draw(mEdges[LEFT], canvas, 0, fillerSize + visibleEnd.y, 270);
}
if (!mEdges[RIGHT].isFinished()) {
invalidate |= draw(mEdges[RIGHT], canvas, visibleEnd.x, 0, 90);
invalidate |= draw(mEdges[RIGHT], canvas, visibleEnd.x, fillerSize, 90);
}
// If the edge effect is animating off screen, invalidate.

Просмотреть файл

@ -12,7 +12,8 @@
<org.mozilla.gecko.GeckoView android:id="@+id/layer_view"
gecko:doinit="false"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
android:layout_height="match_parent"
android:scrollbars="none"/>
<AbsoluteLayout android:id="@+id/plugin_container"
android:background="@android:color/transparent"