mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-08 14:03:49 +00:00
Bug 710096 - Hold the monitor on the layer controller when adjusting and rendering the viewport metrics. r=Cwiiis a=java-only
This commit is contained in:
parent
f4d5eb2e45
commit
a6ee503da0
@ -162,28 +162,22 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
mGeckoViewport = new ViewportMetrics(viewportObject);
|
||||
mGeckoViewport.setSize(viewportSize);
|
||||
|
||||
mTileLayer.setOrigin(PointUtils.round(mGeckoViewport.getDisplayportOrigin()));
|
||||
mTileLayer.setResolution(mGeckoViewport.getZoomFactor());
|
||||
LayerController controller = getLayerController();
|
||||
synchronized (controller) {
|
||||
PointF displayportOrigin = mGeckoViewport.getDisplayportOrigin();
|
||||
mTileLayer.setOrigin(PointUtils.round(displayportOrigin));
|
||||
mTileLayer.setResolution(mGeckoViewport.getZoomFactor());
|
||||
|
||||
// Make sure LayerController metrics changes only happen in the
|
||||
// UI thread.
|
||||
final LayerController controller = getLayerController();
|
||||
|
||||
if (controller != null) {
|
||||
controller.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (onlyUpdatePageSize) {
|
||||
// Don't adjust page size when zooming unless zoom levels are
|
||||
// approximately equal.
|
||||
if (FloatUtils.fuzzyEquals(controller.getZoomFactor(), mGeckoViewport.getZoomFactor()))
|
||||
controller.setPageSize(mGeckoViewport.getPageSize());
|
||||
} else {
|
||||
controller.setViewportMetrics(mGeckoViewport);
|
||||
controller.notifyPanZoomControllerOfGeometryChange(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (onlyUpdatePageSize) {
|
||||
// Don't adjust page size when zooming unless zoom levels are
|
||||
// approximately equal.
|
||||
if (FloatUtils.fuzzyEquals(controller.getZoomFactor(),
|
||||
mGeckoViewport.getZoomFactor()))
|
||||
controller.setPageSize(mGeckoViewport.getPageSize());
|
||||
} else {
|
||||
controller.setViewportMetrics(mGeckoViewport);
|
||||
controller.notifyPanZoomControllerOfGeometryChange(true);
|
||||
}
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Bad viewport description: " + viewportDescription);
|
||||
|
@ -58,12 +58,13 @@ import android.view.GestureDetector;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View.OnTouchListener;
|
||||
import java.lang.Math;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
private static final String LOGTAG = "GeckoLayerController";
|
||||
@ -155,7 +156,8 @@ public class LayerController {
|
||||
}
|
||||
|
||||
/**
|
||||
* The view calls this to indicate that the viewport changed size.
|
||||
* 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
|
||||
@ -173,6 +175,7 @@ public class LayerController {
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
/** Scrolls the viewport to the given point. You must hold the monitor while calling this. */
|
||||
public void scrollTo(PointF point) {
|
||||
mViewportMetrics.setOrigin(point);
|
||||
notifyLayerClientOfGeometryChange();
|
||||
@ -181,6 +184,7 @@ public class LayerController {
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
/** Scrolls the viewport by the given offset. You must hold the monitor while calling this. */
|
||||
public void scrollBy(PointF point) {
|
||||
PointF origin = mViewportMetrics.getOrigin();
|
||||
origin.offset(point.x, point.y);
|
||||
@ -192,6 +196,7 @@ public class LayerController {
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
/** Sets the current viewport. You must hold the monitor while calling this. */
|
||||
public void setViewport(RectF viewport) {
|
||||
mViewportMetrics.setViewport(viewport);
|
||||
notifyLayerClientOfGeometryChange();
|
||||
@ -200,6 +205,7 @@ public class LayerController {
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
/** Sets the current page size. You must hold the monitor while calling this. */
|
||||
public void setPageSize(FloatSize size) {
|
||||
if (mViewportMetrics.getPageSize().fuzzyEquals(size))
|
||||
return;
|
||||
@ -215,7 +221,8 @@ public class LayerController {
|
||||
/**
|
||||
* Sets the entire viewport metrics at once. This function does not notify the layer client or
|
||||
* the pan/zoom controller, so you will need to call notifyLayerClientOfGeometryChange() or
|
||||
* notifyPanZoomControllerOfGeometryChange() after calling this.
|
||||
* notifyPanZoomControllerOfGeometryChange() after calling this. You must hold the monitor
|
||||
* while calling this.
|
||||
*/
|
||||
public void setViewportMetrics(ViewportMetrics viewport) {
|
||||
mViewportMetrics = new ViewportMetrics(viewport);
|
||||
@ -223,10 +230,15 @@ public class LayerController {
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
/** Scales the viewport. You must hold the monitor while calling this. */
|
||||
public void scaleTo(float zoomFactor) {
|
||||
scaleWithFocus(zoomFactor, new PointF(0,0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales the viewport, keeping the given focus point in the same place before and after the
|
||||
* scale operation. You must hold the monitor while calling this.
|
||||
*/
|
||||
public void scaleWithFocus(float zoomFactor, PointF focus) {
|
||||
mViewportMetrics.scaleTo(zoomFactor, focus);
|
||||
|
||||
@ -237,6 +249,10 @@ public class LayerController {
|
||||
mView.requestRender();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the viewport origin and scales in one operation. You must hold the monitor while
|
||||
* calling this.
|
||||
*/
|
||||
public void scaleWithOrigin(float zoomFactor, PointF origin) {
|
||||
mViewportMetrics.setOrigin(origin);
|
||||
scaleTo(zoomFactor);
|
||||
|
@ -132,9 +132,6 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
||||
|
||||
/**
|
||||
* Called whenever a new frame is about to be drawn.
|
||||
*
|
||||
* FIXME: This is racy. Layers and page sizes can be modified by the pan/zoom controller while
|
||||
* this is going on.
|
||||
*/
|
||||
public void onDrawFrame(GL10 gl) {
|
||||
long frameStartTime = SystemClock.uptimeMillis();
|
||||
@ -142,63 +139,68 @@ public class LayerRenderer implements GLSurfaceView.Renderer {
|
||||
TextureReaper.get().reap(gl);
|
||||
|
||||
LayerController controller = mView.getController();
|
||||
Layer rootLayer = controller.getRoot();
|
||||
RenderContext screenContext = createScreenContext(), pageContext = createPageContext();
|
||||
RenderContext screenContext = createScreenContext();
|
||||
|
||||
if (!pageContext.fuzzyEquals(mLastPageContext)) {
|
||||
// the viewport or page changed, so show the scrollbars again
|
||||
// as per UX decision
|
||||
mVertScrollLayer.unfade();
|
||||
mHorizScrollLayer.unfade();
|
||||
mFadeRunnable.scheduleStartFade(ScrollbarLayer.FADE_DELAY);
|
||||
} else if (mFadeRunnable.timeToFade()) {
|
||||
boolean stillFading = mVertScrollLayer.fade() | mHorizScrollLayer.fade();
|
||||
if (stillFading) {
|
||||
mFadeRunnable.scheduleNextFadeFrame();
|
||||
synchronized (controller) {
|
||||
Layer rootLayer = controller.getRoot();
|
||||
RenderContext pageContext = createPageContext();
|
||||
|
||||
if (!pageContext.fuzzyEquals(mLastPageContext)) {
|
||||
// the viewport or page changed, so show the scrollbars again
|
||||
// as per UX decision
|
||||
mVertScrollLayer.unfade();
|
||||
mHorizScrollLayer.unfade();
|
||||
mFadeRunnable.scheduleStartFade(ScrollbarLayer.FADE_DELAY);
|
||||
} else if (mFadeRunnable.timeToFade()) {
|
||||
boolean stillFading = mVertScrollLayer.fade() | mHorizScrollLayer.fade();
|
||||
if (stillFading) {
|
||||
mFadeRunnable.scheduleNextFadeFrame();
|
||||
}
|
||||
}
|
||||
mLastPageContext = pageContext;
|
||||
|
||||
/* Update layers. */
|
||||
if (rootLayer != null) rootLayer.update(gl);
|
||||
mShadowLayer.update(gl);
|
||||
mCheckerboardLayer.update(gl);
|
||||
mFrameRateLayer.update(gl);
|
||||
mVertScrollLayer.update(gl);
|
||||
mHorizScrollLayer.update(gl);
|
||||
|
||||
/* Draw the background. */
|
||||
gl.glClearColor(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, 1.0f);
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
/* Draw the drop shadow, if we need to. */
|
||||
Rect pageRect = getPageRect();
|
||||
RectF untransformedPageRect = new RectF(0.0f, 0.0f, pageRect.width(),
|
||||
pageRect.height());
|
||||
if (!untransformedPageRect.contains(controller.getViewport()))
|
||||
mShadowLayer.draw(pageContext);
|
||||
|
||||
/* Draw the checkerboard. */
|
||||
Rect scissorRect = transformToScissorRect(pageRect);
|
||||
gl.glEnable(GL10.GL_SCISSOR_TEST);
|
||||
gl.glScissor(scissorRect.left, scissorRect.top,
|
||||
scissorRect.width(), scissorRect.height());
|
||||
|
||||
mCheckerboardLayer.draw(screenContext);
|
||||
|
||||
/* Draw the layer the client added to us. */
|
||||
if (rootLayer != null)
|
||||
rootLayer.draw(pageContext);
|
||||
|
||||
gl.glDisable(GL10.GL_SCISSOR_TEST);
|
||||
|
||||
/* Draw the vertical scrollbar. */
|
||||
IntSize screenSize = new IntSize(controller.getViewportSize());
|
||||
if (pageRect.height() > screenSize.height)
|
||||
mVertScrollLayer.draw(pageContext);
|
||||
|
||||
/* Draw the horizontal scrollbar. */
|
||||
if (pageRect.width() > screenSize.width)
|
||||
mHorizScrollLayer.draw(pageContext);
|
||||
}
|
||||
mLastPageContext = pageContext;
|
||||
|
||||
/* Update layers. */
|
||||
if (rootLayer != null) rootLayer.update(gl);
|
||||
mShadowLayer.update(gl);
|
||||
mCheckerboardLayer.update(gl);
|
||||
mFrameRateLayer.update(gl);
|
||||
mVertScrollLayer.update(gl);
|
||||
mHorizScrollLayer.update(gl);
|
||||
|
||||
/* Draw the background. */
|
||||
gl.glClearColor(BACKGROUND_COLOR_R, BACKGROUND_COLOR_G, BACKGROUND_COLOR_B, 1.0f);
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
|
||||
|
||||
/* Draw the drop shadow, if we need to. */
|
||||
Rect pageRect = getPageRect();
|
||||
RectF untransformedPageRect = new RectF(0.0f, 0.0f, pageRect.width(), pageRect.height());
|
||||
if (!untransformedPageRect.contains(controller.getViewport()))
|
||||
mShadowLayer.draw(pageContext);
|
||||
|
||||
/* Draw the checkerboard. */
|
||||
Rect scissorRect = transformToScissorRect(pageRect);
|
||||
gl.glEnable(GL10.GL_SCISSOR_TEST);
|
||||
gl.glScissor(scissorRect.left, scissorRect.top,
|
||||
scissorRect.width(), scissorRect.height());
|
||||
|
||||
mCheckerboardLayer.draw(screenContext);
|
||||
|
||||
/* Draw the layer the client added to us. */
|
||||
if (rootLayer != null)
|
||||
rootLayer.draw(pageContext);
|
||||
|
||||
gl.glDisable(GL10.GL_SCISSOR_TEST);
|
||||
|
||||
/* Draw the vertical scrollbar. */
|
||||
IntSize screenSize = new IntSize(controller.getViewportSize());
|
||||
if (pageRect.height() > screenSize.height)
|
||||
mVertScrollLayer.draw(pageContext);
|
||||
|
||||
/* Draw the horizontal scrollbar. */
|
||||
if (pageRect.width() > screenSize.width)
|
||||
mHorizScrollLayer.draw(pageContext);
|
||||
|
||||
/* Draw the FPS. */
|
||||
if (mShowFrameRate) {
|
||||
|
@ -560,7 +560,9 @@ public class PanZoomController
|
||||
GeckoAppShell.sendEventToGecko(e);
|
||||
mOverrideScrollAck = false;
|
||||
} else {
|
||||
mController.scrollBy(new PointF(mX.displacement, mY.displacement));
|
||||
synchronized (mController) {
|
||||
mController.scrollBy(new PointF(mX.displacement, mY.displacement));
|
||||
}
|
||||
}
|
||||
|
||||
mX.displacement = mY.displacement = 0;
|
||||
@ -592,18 +594,22 @@ public class PanZoomController
|
||||
|
||||
/* Performs one frame of a bounce animation. */
|
||||
private void advanceBounce() {
|
||||
float t = EASE_OUT_ANIMATION_FRAMES[mBounceFrame];
|
||||
ViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t);
|
||||
mController.setViewportMetrics(newMetrics);
|
||||
mController.notifyLayerClientOfGeometryChange();
|
||||
mBounceFrame++;
|
||||
synchronized (mController) {
|
||||
float t = EASE_OUT_ANIMATION_FRAMES[mBounceFrame];
|
||||
ViewportMetrics newMetrics = mBounceStartMetrics.interpolate(mBounceEndMetrics, t);
|
||||
mController.setViewportMetrics(newMetrics);
|
||||
mController.notifyLayerClientOfGeometryChange();
|
||||
mBounceFrame++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Concludes a bounce animation and snaps the viewport into place. */
|
||||
private void finishBounce() {
|
||||
mController.setViewportMetrics(mBounceEndMetrics);
|
||||
mController.notifyLayerClientOfGeometryChange();
|
||||
mBounceFrame = -1;
|
||||
synchronized (mController) {
|
||||
mController.setViewportMetrics(mBounceEndMetrics);
|
||||
mController.notifyLayerClientOfGeometryChange();
|
||||
mBounceFrame = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -881,11 +887,14 @@ public class PanZoomController
|
||||
else
|
||||
spanRatio = 1.0f - (1.0f - spanRatio) * resistance;
|
||||
|
||||
float newZoomFactor = mController.getZoomFactor() * spanRatio;
|
||||
synchronized (mController) {
|
||||
float newZoomFactor = mController.getZoomFactor() * spanRatio;
|
||||
|
||||
mController.scrollBy(new PointF(mLastZoomFocus.x - detector.getFocusX(),
|
||||
mLastZoomFocus.y - detector.getFocusY()));
|
||||
mController.scaleWithFocus(newZoomFactor, new PointF(detector.getFocusX(), detector.getFocusY()));
|
||||
mController.scrollBy(new PointF(mLastZoomFocus.x - detector.getFocusX(),
|
||||
mLastZoomFocus.y - detector.getFocusY()));
|
||||
PointF focus = new PointF(detector.getFocusX(), detector.getFocusY());
|
||||
mController.scaleWithFocus(newZoomFactor, focus);
|
||||
}
|
||||
|
||||
mLastZoomFocus.set(detector.getFocusX(), detector.getFocusY());
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user