mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
pinch to zoom
This commit is contained in:
parent
89ab110357
commit
296b76070c
6 changed files with 157 additions and 19 deletions
|
@ -286,6 +286,24 @@ impl ServoGlue {
|
||||||
self.process_event(event)
|
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.
|
/// Perform a click.
|
||||||
pub fn click(&mut self, x: u32, y: u32) -> Result<(), &'static str> {
|
pub fn click(&mut self, x: u32, y: u32) -> Result<(), &'static str> {
|
||||||
let mouse_event =
|
let mouse_event =
|
||||||
|
|
|
@ -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));
|
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]
|
#[no_mangle]
|
||||||
pub extern "C" fn click(x: i32, y: i32) {
|
pub extern "C" fn click(x: i32, y: i32) {
|
||||||
debug!("click");
|
debug!("click");
|
||||||
|
|
|
@ -9,7 +9,7 @@ use api::{self, EventLoopWaker, ServoGlue, SERVO, HostTrait, ReadFileTrait};
|
||||||
use gl_glue;
|
use gl_glue;
|
||||||
use jni::{JNIEnv, JavaVM};
|
use jni::{JNIEnv, JavaVM};
|
||||||
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
|
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 log::Level;
|
||||||
use std;
|
use std;
|
||||||
use std::os::raw::c_void;
|
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));
|
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]
|
#[no_mangle]
|
||||||
pub fn Java_com_mozilla_servoview_JNIServo_click(env: JNIEnv, _: JClass, x: jint, y: jint) {
|
pub fn Java_com_mozilla_servoview_JNIServo_click(env: JNIEnv, _: JClass, x: jint, y: jint) {
|
||||||
debug!("click");
|
debug!("click");
|
||||||
|
|
|
@ -49,6 +49,12 @@ public class JNIServo {
|
||||||
|
|
||||||
public native void scrollEnd(int dx, int dy, int x, int y);
|
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 native void click(int x, int y);
|
||||||
|
|
||||||
public interface Callbacks {
|
public interface Callbacks {
|
||||||
|
|
|
@ -86,6 +86,18 @@ public class Servo {
|
||||||
mRunCallback.inGLThread(() -> mJNI.scrollEnd(dx, dy, x, y));
|
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) {
|
public void click(int x, int y) {
|
||||||
mRunCallback.inGLThread(() -> mJNI.click(x, y));
|
mRunCallback.inGLThread(() -> mJNI.click(x, y));
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,11 @@ import android.net.Uri;
|
||||||
import android.opengl.GLES31;
|
import android.opengl.GLES31;
|
||||||
import android.opengl.GLSurfaceView;
|
import android.opengl.GLSurfaceView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
import android.view.GestureDetector;
|
import android.view.GestureDetector;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ScaleGestureDetector;
|
||||||
import android.widget.OverScroller;
|
import android.widget.OverScroller;
|
||||||
|
|
||||||
import com.mozilla.servoview.Servo.Client;
|
import com.mozilla.servoview.Servo.Client;
|
||||||
|
@ -26,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
|
||||||
public class ServoView extends GLSurfaceView
|
public class ServoView extends GLSurfaceView
|
||||||
implements
|
implements
|
||||||
GestureDetector.OnGestureListener,
|
GestureDetector.OnGestureListener,
|
||||||
|
ScaleGestureDetector.OnScaleGestureListener,
|
||||||
Choreographer.FrameCallback,
|
Choreographer.FrameCallback,
|
||||||
GfxCallbacks,
|
GfxCallbacks,
|
||||||
RunCallback {
|
RunCallback {
|
||||||
|
@ -39,12 +42,18 @@ public class ServoView extends GLSurfaceView
|
||||||
private boolean mAnimating;
|
private boolean mAnimating;
|
||||||
private String mServoArgs = "";
|
private String mServoArgs = "";
|
||||||
private GestureDetector mGestureDetector;
|
private GestureDetector mGestureDetector;
|
||||||
|
private ScaleGestureDetector mScaleGestureDetector;
|
||||||
|
|
||||||
private OverScroller mScroller;
|
private OverScroller mScroller;
|
||||||
private int mLastX = 0;
|
private int mLastX = 0;
|
||||||
private int mCurX = 0;
|
private int mCurX = 0;
|
||||||
private int mLastY = 0;
|
private int mLastY = 0;
|
||||||
private int mCurY = 0;
|
private int mCurY = 0;
|
||||||
private boolean mFlinging;
|
private boolean mFlinging;
|
||||||
|
private boolean mScrolling;
|
||||||
|
|
||||||
|
private boolean mZooming;
|
||||||
|
private float mZoomFactor = 1;
|
||||||
|
|
||||||
public ServoView(Context context, AttributeSet attrs) {
|
public ServoView(Context context, AttributeSet attrs) {
|
||||||
super(context, attrs);
|
super(context, attrs);
|
||||||
|
@ -138,19 +147,18 @@ public class ServoView extends GLSurfaceView
|
||||||
|
|
||||||
private void initGestures(Context context) {
|
private void initGestures(Context context) {
|
||||||
mGestureDetector = new GestureDetector(context, this);
|
mGestureDetector = new GestureDetector(context, this);
|
||||||
|
mScaleGestureDetector = new ScaleGestureDetector(context, this);
|
||||||
mScroller = new OverScroller(context);
|
mScroller = new OverScroller(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void doFrame(long frameTimeNanos) {
|
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;
|
mFlinging = false;
|
||||||
inGLThread(() -> mServo.scrollEnd(0, 0, mCurX, mCurY));
|
mScrolling = false;
|
||||||
if (!mAnimating) {
|
mServo.scrollEnd(0, 0, mCurX, mCurY);
|
||||||
// Not scrolling. Not animating. We don't need to schedule
|
|
||||||
// another frame.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mFlinging) {
|
if (mFlinging) {
|
||||||
|
@ -165,15 +173,25 @@ public class ServoView extends GLSurfaceView
|
||||||
mLastX = mCurX;
|
mLastX = mCurX;
|
||||||
mLastY = mCurY;
|
mLastY = mCurY;
|
||||||
|
|
||||||
if (dx != 0 || dy != 0) {
|
boolean scrollNecessary = mScrolling && (dx != 0 || dy != 0);
|
||||||
inGLThread(() -> mServo.scroll(dx, dy, mCurX, mCurY));
|
boolean zoomNecessary = mZooming && mZoomFactor != 1;
|
||||||
} else {
|
|
||||||
if (mAnimating) {
|
if (scrollNecessary) {
|
||||||
requestRender();
|
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) {
|
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) {
|
public boolean onTouchEvent(final MotionEvent e) {
|
||||||
mGestureDetector.onTouchEvent(e);
|
mGestureDetector.onTouchEvent(e);
|
||||||
|
mScaleGestureDetector.onTouchEvent(e);
|
||||||
|
|
||||||
int action = e.getActionMasked();
|
int action = e.getActionMasked();
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
@ -207,7 +226,8 @@ public class ServoView extends GLSurfaceView
|
||||||
mCurY = (int) e.getY();
|
mCurY = (int) e.getY();
|
||||||
mLastY = mCurY;
|
mLastY = mCurY;
|
||||||
mScroller.forceFinished(true);
|
mScroller.forceFinished(true);
|
||||||
inGLThread(() -> mServo.scrollStart(0, 0, mCurX, mCurY));
|
mServo.scrollStart(0, 0, mCurX, mCurY);
|
||||||
|
mScrolling = true;
|
||||||
Choreographer.getInstance().postFrameCallback(this);
|
Choreographer.getInstance().postFrameCallback(this);
|
||||||
return true;
|
return true;
|
||||||
case (MotionEvent.ACTION_MOVE):
|
case (MotionEvent.ACTION_MOVE):
|
||||||
|
@ -217,8 +237,8 @@ public class ServoView extends GLSurfaceView
|
||||||
case (MotionEvent.ACTION_UP):
|
case (MotionEvent.ACTION_UP):
|
||||||
case (MotionEvent.ACTION_CANCEL):
|
case (MotionEvent.ACTION_CANCEL):
|
||||||
if (!mFlinging) {
|
if (!mFlinging) {
|
||||||
inGLThread(() -> mServo.scrollEnd(0, 0, mCurX, mCurY));
|
mScrolling = false;
|
||||||
Choreographer.getInstance().removeFrameCallback(this);
|
mServo.scrollEnd(0, 0, mCurX, mCurY);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
|
@ -227,7 +247,7 @@ public class ServoView extends GLSurfaceView
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onSingleTapUp(MotionEvent e) {
|
public boolean onSingleTapUp(MotionEvent e) {
|
||||||
inGLThread(() -> mServo.click((int) e.getX(), (int) e.getY()));
|
mServo.click((int) e.getX(), (int) e.getY());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,6 +261,33 @@ public class ServoView extends GLSurfaceView
|
||||||
public void onShowPress(MotionEvent e) {
|
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
|
@Override
|
||||||
public void onPause() {
|
public void onPause() {
|
||||||
super.onPause();
|
super.onPause();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue