pinch to zoom

This commit is contained in:
Paul Rouget 2018-08-16 13:35:21 +02:00
parent 89ab110357
commit 296b76070c
6 changed files with 157 additions and 19 deletions

View file

@ -286,6 +286,24 @@ impl ServoGlue {
self.process_event(event)
}
/// Start pinchzoom.
/// x/y are pinch origin coordinates.
pub fn pinchzoom_start(&mut self, factor: f32, _x: u32, _y: u32) -> Result<(), &'static str> {
self.process_event(WindowEvent::PinchZoom(factor))
}
/// Pinchzoom.
/// x/y are pinch origin coordinates.
pub fn pinchzoom(&mut self, factor: f32, _x: u32, _y: u32) -> Result<(), &'static str> {
self.process_event(WindowEvent::PinchZoom(factor))
}
/// End pinchzoom.
/// x/y are pinch origin coordinates.
pub fn pinchzoom_end(&mut self, factor: f32, _x: u32, _y: u32) -> Result<(), &'static str> {
self.process_event(WindowEvent::PinchZoom(factor))
}
/// Perform a click.
pub fn click(&mut self, x: u32, y: u32) -> Result<(), &'static str> {
let mouse_event =

View file

@ -180,6 +180,24 @@ pub extern "C" fn scroll(dx: i32, dy: i32, x: i32, y: i32) {
call(|s| s.scroll(dx as i32, dy as i32, x as u32, y as u32));
}
#[no_mangle]
pub extern "C" fn pinchzoom_start(factor: f32, x: i32, y: i32) {
debug!("pinchzoom_start");
call(|s| s.pinchzoom_start(factor, x as u32, y as u32));
}
#[no_mangle]
pub extern "C" fn pinchzoom(factor: f32, x: i32, y: i32) {
debug!("pinchzoom");
call(|s| s.pinchzoom(factor, x as u32, y as u32));
}
#[no_mangle]
pub extern "C" fn pinchzoom_end(factor: f32, x: i32, y: i32) {
debug!("pinchzoom_end");
call(|s| s.pinchzoom_end(factor, x as u32, y as u32));
}
#[no_mangle]
pub extern "C" fn click(x: i32, y: i32) {
debug!("click");

View file

@ -9,7 +9,7 @@ use api::{self, EventLoopWaker, ServoGlue, SERVO, HostTrait, ReadFileTrait};
use gl_glue;
use jni::{JNIEnv, JavaVM};
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
use jni::sys::{jboolean, jint, jstring, JNI_TRUE};
use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE};
use log::Level;
use std;
use std::os::raw::c_void;
@ -207,6 +207,43 @@ pub fn Java_com_mozilla_servoview_JNIServo_scroll(
call(env, |s| s.scroll(dx as i32, dy as i32, x as u32, y as u32));
}
#[no_mangle]
pub fn Java_com_mozilla_servoview_JNIServo_pinchZoomStart(
env: JNIEnv,
_: JClass,
factor: jfloat,
x: jint,
y: jint,
) {
debug!("pinchZoomStart");
call(env, |s| s.pinchzoom_start(factor as f32, x as u32, y as u32));
}
#[no_mangle]
pub fn Java_com_mozilla_servoview_JNIServo_pinchZoom(
env: JNIEnv,
_: JClass,
factor: jfloat,
x: jint,
y: jint,
) {
debug!("pinchZoom");
call(env, |s| s.pinchzoom(factor as f32, x as u32, y as u32));
}
#[no_mangle]
pub fn Java_com_mozilla_servoview_JNIServo_pinchZoomEnd(
env: JNIEnv,
_: JClass,
factor: jfloat,
x: jint,
y: jint,
) {
debug!("pinchZoomEnd");
call(env, |s| s.pinchzoom_end(factor as f32, x as u32, y as u32));
}
#[no_mangle]
pub fn Java_com_mozilla_servoview_JNIServo_click(env: JNIEnv, _: JClass, x: jint, y: jint) {
debug!("click");

View file

@ -49,6 +49,12 @@ public class JNIServo {
public native void scrollEnd(int dx, int dy, int x, int y);
public native void pinchZoomStart(float factor, int x, int y);
public native void pinchZoom(float factor, int x, int y);
public native void pinchZoomEnd(float factor, int x, int y);
public native void click(int x, int y);
public interface Callbacks {

View file

@ -86,6 +86,18 @@ public class Servo {
mRunCallback.inGLThread(() -> mJNI.scrollEnd(dx, dy, x, y));
}
public void pinchZoomStart(float factor, int x, int y) {
mRunCallback.inGLThread(() -> mJNI.pinchZoomStart(factor, x, y));
}
public void pinchZoom(float factor, int x, int y) {
mRunCallback.inGLThread(() -> mJNI.pinchZoom(factor, x, y));
}
public void pinchZoomEnd(float factor, int x, int y) {
mRunCallback.inGLThread(() -> mJNI.pinchZoomEnd(factor, x, y));
}
public void click(int x, int y) {
mRunCallback.inGLThread(() -> mJNI.click(x, y));
}

View file

@ -11,9 +11,11 @@ import android.net.Uri;
import android.opengl.GLES31;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Choreographer;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.widget.OverScroller;
import com.mozilla.servoview.Servo.Client;
@ -26,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
public class ServoView extends GLSurfaceView
implements
GestureDetector.OnGestureListener,
ScaleGestureDetector.OnScaleGestureListener,
Choreographer.FrameCallback,
GfxCallbacks,
RunCallback {
@ -39,12 +42,18 @@ public class ServoView extends GLSurfaceView
private boolean mAnimating;
private String mServoArgs = "";
private GestureDetector mGestureDetector;
private ScaleGestureDetector mScaleGestureDetector;
private OverScroller mScroller;
private int mLastX = 0;
private int mCurX = 0;
private int mLastY = 0;
private int mCurY = 0;
private boolean mFlinging;
private boolean mScrolling;
private boolean mZooming;
private float mZoomFactor = 1;
public ServoView(Context context, AttributeSet attrs) {
super(context, attrs);
@ -138,19 +147,18 @@ public class ServoView extends GLSurfaceView
private void initGestures(Context context) {
mGestureDetector = new GestureDetector(context, this);
mScaleGestureDetector = new ScaleGestureDetector(context, this);
mScroller = new OverScroller(context);
}
public void doFrame(long frameTimeNanos) {
if (mScroller.isFinished() && mFlinging) {
// 3 reasons to be here: animating or scrolling/flinging or pinching
if (mFlinging && mScroller.isFinished()) {
mFlinging = false;
inGLThread(() -> mServo.scrollEnd(0, 0, mCurX, mCurY));
if (!mAnimating) {
// Not scrolling. Not animating. We don't need to schedule
// another frame.
return;
}
mScrolling = false;
mServo.scrollEnd(0, 0, mCurX, mCurY);
}
if (mFlinging) {
@ -165,15 +173,25 @@ public class ServoView extends GLSurfaceView
mLastX = mCurX;
mLastY = mCurY;
if (dx != 0 || dy != 0) {
inGLThread(() -> mServo.scroll(dx, dy, mCurX, mCurY));
} else {
if (mAnimating) {
requestRender();
}
boolean scrollNecessary = mScrolling && (dx != 0 || dy != 0);
boolean zoomNecessary = mZooming && mZoomFactor != 1;
if (scrollNecessary) {
mServo.scroll(dx, dy, mCurX, mCurY);
}
Choreographer.getInstance().postFrameCallback(this);
if (zoomNecessary) {
mServo.pinchZoom(mZoomFactor, 0, 0);
mZoomFactor = 1;
}
if (!zoomNecessary && !scrollNecessary && mAnimating) {
requestRender();
}
if (mZooming || mScrolling || mAnimating) {
Choreographer.getInstance().postFrameCallback(this);
}
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
@ -198,6 +216,7 @@ public class ServoView extends GLSurfaceView
public boolean onTouchEvent(final MotionEvent e) {
mGestureDetector.onTouchEvent(e);
mScaleGestureDetector.onTouchEvent(e);
int action = e.getActionMasked();
switch (action) {
@ -207,7 +226,8 @@ public class ServoView extends GLSurfaceView
mCurY = (int) e.getY();
mLastY = mCurY;
mScroller.forceFinished(true);
inGLThread(() -> mServo.scrollStart(0, 0, mCurX, mCurY));
mServo.scrollStart(0, 0, mCurX, mCurY);
mScrolling = true;
Choreographer.getInstance().postFrameCallback(this);
return true;
case (MotionEvent.ACTION_MOVE):
@ -217,8 +237,8 @@ public class ServoView extends GLSurfaceView
case (MotionEvent.ACTION_UP):
case (MotionEvent.ACTION_CANCEL):
if (!mFlinging) {
inGLThread(() -> mServo.scrollEnd(0, 0, mCurX, mCurY));
Choreographer.getInstance().removeFrameCallback(this);
mScrolling = false;
mServo.scrollEnd(0, 0, mCurX, mCurY);
}
return true;
default:
@ -227,7 +247,7 @@ public class ServoView extends GLSurfaceView
}
public boolean onSingleTapUp(MotionEvent e) {
inGLThread(() -> mServo.click((int) e.getX(), (int) e.getY()));
mServo.click((int) e.getX(), (int) e.getY());
return false;
}
@ -241,6 +261,33 @@ public class ServoView extends GLSurfaceView
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
if (mScroller.isFinished()) {
mZoomFactor = detector.getScaleFactor();
mZooming = true;
mServo.pinchZoomStart(mZoomFactor, 0, 0);
Choreographer.getInstance().postFrameCallback(this);
return true;
} else {
return false;
}
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
mZoomFactor *= detector.getScaleFactor();
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
mZoomFactor = detector.getScaleFactor();
mZooming = false;
mServo.pinchZoomEnd(mZoomFactor, 0, 0);
}
@Override
public void onPause() {
super.onPause();