Bug 775722 - Reposition the text selection handles during pan/zoom operations. r=blassey

This commit is contained in:
Kartikaya Gupta 2012-07-26 10:13:48 -04:00
Родитель fa70604fdd
Коммит 2abce8dc66
4 изменённых файлов: 63 добавлений и 34 удалений

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

@ -6,14 +6,21 @@ package org.mozilla.gecko;
import android.util.Log;
import android.view.View;
import org.mozilla.gecko.gfx.Layer;
import org.mozilla.gecko.gfx.Layer.RenderContext;
import org.mozilla.gecko.gfx.LayerController;
import org.json.JSONObject;
class TextSelection implements GeckoEventListener {
class TextSelection extends Layer implements GeckoEventListener {
private static final String LOGTAG = "GeckoTextSelection";
private final TextSelectionHandle mStartHandle;
private final TextSelectionHandle mEndHandle;
private float mViewLeft;
private float mViewTop;
private float mViewZoom;
TextSelection(TextSelectionHandle startHandle, TextSelectionHandle endHandle) {
mStartHandle = startHandle;
mEndHandle = endHandle;
@ -41,11 +48,24 @@ class TextSelection implements GeckoEventListener {
public void run() {
mStartHandle.setVisibility(View.VISIBLE);
mEndHandle.setVisibility(View.VISIBLE);
mViewLeft = 0.0f;
mViewTop = 0.0f;
mViewZoom = 0.0f;
LayerController layerController = GeckoApp.mAppContext.getLayerController();
if (layerController != null) {
layerController.getView().addLayer(TextSelection.this);
}
}
});
} else if (event.equals("TextSelection:HideHandles")) {
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
public void run() {
LayerController layerController = GeckoApp.mAppContext.getLayerController();
if (layerController != null) {
layerController.getView().removeLayer(TextSelection.this);
}
mStartHandle.setVisibility(View.GONE);
mEndHandle.setVisibility(View.GONE);
}
@ -67,4 +87,26 @@ class TextSelection implements GeckoEventListener {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
}
}
@Override
public void draw(final RenderContext context) {
// cache the relevant values from the context and bail out if they are the same. we do this
// because this draw function gets called a lot (once per compositor frame) and we want to
// avoid doing a lot of extra work in cases where it's not needed.
if (FloatUtils.fuzzyEquals(mViewLeft, context.viewport.left)
&& FloatUtils.fuzzyEquals(mViewTop, context.viewport.top)
&& FloatUtils.fuzzyEquals(mViewZoom, context.zoomFactor)) {
return;
}
mViewLeft = context.viewport.left;
mViewTop = context.viewport.top;
mViewZoom = context.zoomFactor;
GeckoApp.mAppContext.mMainHandler.post(new Runnable() {
public void run() {
mStartHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
mEndHandle.repositionWithViewport(context.viewport.left, context.viewport.top, context.zoomFactor);
}
});
}
}

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

@ -13,6 +13,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.ImageView;
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
import org.mozilla.gecko.gfx.LayerController;
import org.json.JSONObject;
@ -28,6 +29,7 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
private int mLeft;
private int mTop;
private PointF mGeckoPoint;
private int mTouchStartX;
private int mTouchStartY;
@ -108,11 +110,18 @@ class TextSelectionHandle extends ImageView implements View.OnTouchListener {
Log.e(LOGTAG, "Can't position handle because layerController is null");
return;
}
PointF geckoPoint = new PointF((float) left, (float) top);
geckoPoint = layerController.convertLayerPointToViewPoint(geckoPoint);
mLeft = Math.round(geckoPoint.x) - (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
mTop = Math.round(geckoPoint.y);
mGeckoPoint = new PointF((float) left, (float) top);
ImmutableViewportMetrics metrics = layerController.getViewportMetrics();
repositionWithViewport(metrics.viewportRectLeft, metrics.viewportRectTop, metrics.zoomFactor);
}
void repositionWithViewport(float x, float y, float zoom) {
PointF viewPoint = new PointF((mGeckoPoint.x * zoom) - x,
(mGeckoPoint.y * zoom) - y);
mLeft = Math.round(viewPoint.x) - (mHandleType.equals(HandleType.START) ? mWidth - mShadow : mShadow);
mTop = Math.round(viewPoint.y);
setLayoutPosition();
}

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

@ -300,28 +300,6 @@ public class LayerController {
return layerPoint;
}
/**
* Does the opposite of convertViewPointToLayerPoint.
*/
public PointF convertLayerPointToViewPoint(PointF layerPoint) {
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();
PointF viewPoint = new PointF(
((layerPoint.x + (geckoOrigin.x / geckoZoom)) * zoom - origin.x),
((layerPoint.y + (geckoOrigin.y / geckoZoom)) * zoom - origin.y));
return viewPoint;
}
/** Retrieves whether we should show checkerboard checks or not. */
public boolean checkerboardShouldShowChecks() {
return mCheckerboardShouldShowChecks;

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

@ -1565,10 +1565,8 @@ var SelectionHandler = {
break;
}
case "after-viewport-change": {
// Update the cache and reposition the handles after the viewport
// changes (e.g. panning, zooming).
// Update the cache after the viewport changes (e.g. panning, zooming).
this.updateCacheForSelection();
this.positionHandles();
break;
}
case "TextSelection:Move": {
@ -1871,13 +1869,15 @@ var SelectionHandler = {
// Translate coordinates to account for selections in sub-frames. We can't cache
// this because the top-level page may have scrolled since selection started.
let offset = this._getViewOffset();
let scrollX = {}, scrollY = {};
this._view.top.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils).getScrollXY(false, scrollX, scrollY);
sendMessageToJava({
gecko: {
type: "TextSelection:PositionHandles",
startLeft: this.cache.start.x + offset.x,
startTop: this.cache.start.y + offset.y,
endLeft: this.cache.end.x + offset.x,
endTop: this.cache.end.y + offset.y
startLeft: this.cache.start.x + offset.x + scrollX.value,
startTop: this.cache.start.y + offset.y + scrollY.value,
endLeft: this.cache.end.x + offset.x + scrollX.value,
endTop: this.cache.end.y + offset.y + scrollY.value
}
});
},