From c4b7bdc63dcd4c3089eae8ce650e93c280bad092 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Tue, 22 Aug 2023 18:08:16 +0200 Subject: [PATCH] ViewGroup: handle scroll events --- src/api-impl-jni/defines.h | 1 + src/api-impl-jni/util.c | 3 ++- src/api-impl-jni/util.h | 1 + src/api-impl-jni/views/android_view_View.c | 4 +++- .../views/android_view_ViewGroup.c | 20 +++++++++++++++++++ .../widgets/android_opengl_GLSurfaceView.c | 4 +++- .../android/content/res/AssetManager.java | 3 +-- .../android/content/res/Resources.java | 2 +- src/api-impl/android/graphics/Matrix.java | 3 ++- src/api-impl/android/view/MotionEvent.java | 10 ++++++++-- src/api-impl/android/view/View.java | 6 ++++++ src/api-impl/android/view/ViewParent.java | 3 +-- src/api-impl/android/widget/EdgeEffect.java | 4 ++++ 13 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/api-impl-jni/defines.h b/src/api-impl-jni/defines.h index f7757afa..709e3fda 100644 --- a/src/api-impl-jni/defines.h +++ b/src/api-impl-jni/defines.h @@ -39,6 +39,7 @@ #define MOTION_EVENT_ACTION_DOWN 0 #define MOTION_EVENT_ACTION_UP 1 #define MOTION_EVENT_ACTION_MOVE 2 +#define MOTION_EVENT_ACTION_SCROLL 8 #endif diff --git a/src/api-impl-jni/util.c b/src/api-impl-jni/util.c index c0e0ca2d..6558f4e5 100644 --- a/src/api-impl-jni/util.c +++ b/src/api-impl-jni/util.c @@ -77,7 +77,7 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.paint.getColor = _METHOD(handle_cache.paint.class, "getColor", "()I"); handle_cache.motion_event.class = _REF((*env)->FindClass(env, "android/view/MotionEvent")); - handle_cache.motion_event.constructor = _METHOD(handle_cache.motion_event.class, "", "(IFF)V"); + handle_cache.motion_event.constructor = _METHOD(handle_cache.motion_event.class, "", "(IIFF)V"); handle_cache.canvas.class = _REF((*env)->FindClass(env, "android/graphics/Canvas")); handle_cache.canvas.constructor = _METHOD(handle_cache.canvas.class, "", "(JJ)V"); @@ -115,6 +115,7 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.view.getSuggestedMinimumWidth = _METHOD(handle_cache.view.class, "getSuggestedMinimumWidth", "()I"); handle_cache.view.getSuggestedMinimumHeight = _METHOD(handle_cache.view.class, "getSuggestedMinimumHeight", "()I"); handle_cache.view.setMeasuredDimension = _METHOD(handle_cache.view.class, "setMeasuredDimension", "(II)V"); + handle_cache.view.onGenericMotionEvent = _METHOD(handle_cache.view.class, "onGenericMotionEvent", "(Landroid/view/MotionEvent;)Z"); handle_cache.asset_manager.class = _REF((*env)->FindClass(env, "android/content/res/AssetManager")); handle_cache.asset_manager.extractFromAPK = _STATIC_METHOD(handle_cache.asset_manager.class, "extractFromAPK", "(Ljava/lang/String;Ljava/lang/String;)V"); diff --git a/src/api-impl-jni/util.h b/src/api-impl-jni/util.h index 5cc0fc06..065d2e33 100644 --- a/src/api-impl-jni/util.h +++ b/src/api-impl-jni/util.h @@ -76,6 +76,7 @@ struct handle_cache { jmethodID getSuggestedMinimumWidth; jmethodID getSuggestedMinimumHeight; jmethodID setMeasuredDimension; + jmethodID onGenericMotionEvent; } view; struct { jclass class; diff --git a/src/api-impl-jni/views/android_view_View.c b/src/api-impl-jni/views/android_view_View.c index 5f42dacd..31c947fc 100644 --- a/src/api-impl-jni/views/android_view_View.c +++ b/src/api-impl-jni/views/android_view_View.c @@ -7,6 +7,8 @@ #include "../generated_headers/android_view_View.h" +#define SOURCE_TOUCHSCREEN 4098 + struct touch_callback_data { JavaVM *jvm; jobject this; jobject on_touch_listener; jclass on_touch_listener_class; }; static void call_ontouch_callback(int action, float x, float y, struct touch_callback_data *d) @@ -14,7 +16,7 @@ static void call_ontouch_callback(int action, float x, float y, struct touch_cal JNIEnv *env; (*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6); - jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, action, x, y); + jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, SOURCE_TOUCHSCREEN, action, x, y); (*env)->CallBooleanMethod(env, d->on_touch_listener, _METHOD(d->on_touch_listener_class, "onTouch", "(Landroid/view/View;Landroid/view/MotionEvent;)Z"), d->this, motion_event); diff --git a/src/api-impl-jni/views/android_view_ViewGroup.c b/src/api-impl-jni/views/android_view_ViewGroup.c index fec61320..a0511fb2 100644 --- a/src/api-impl-jni/views/android_view_ViewGroup.c +++ b/src/api-impl-jni/views/android_view_ViewGroup.c @@ -10,6 +10,8 @@ #define MEASURE_SPEC_EXACTLY (1 << 30) +#define SOURCE_CLASS_POINTER 0x2 + struct _AndroidLayout { GtkLayoutManager parent_instance; jobject view; @@ -64,6 +66,18 @@ static GtkLayoutManager *android_layout_new(jobject view) { return &layout->parent_instance; } +static gboolean scroll_cb(GtkEventControllerScroll* self, gdouble dx, gdouble dy, jobject this) +{ + JNIEnv *env = get_jni_env(); + jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, SOURCE_CLASS_POINTER, MOTION_EVENT_ACTION_SCROLL, dx, -dy); + + gboolean ret = (*env)->CallBooleanMethod(env, this, handle_cache.view.onGenericMotionEvent, motion_event); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + + return ret; +} + /** * Should be overwritten by ViewGroup subclasses. * Fall back to vertical GtkBox if subclass is not implemented yet @@ -83,6 +97,12 @@ JNIEXPORT jlong JNICALL Java_android_view_ViewGroup_native_1constructor(JNIEnv * if (measure_method != handle_cache.view.onMeasure || layout_method != handle_cache.view.onLayout) { gtk_widget_set_layout_manager(box, android_layout_new(_REF(this))); } + if (_METHOD(_CLASS(this), "onGenericMotionEvent", "(Landroid/view/MotionEvent;)Z") != handle_cache.view.onGenericMotionEvent) { + GtkEventController *controller = gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_VERTICAL); + + g_signal_connect(controller, "scroll", G_CALLBACK(scroll_cb), _REF(this)); + gtk_widget_add_controller(box, controller); + } return _INTPTR(box); } diff --git a/src/api-impl-jni/widgets/android_opengl_GLSurfaceView.c b/src/api-impl-jni/widgets/android_opengl_GLSurfaceView.c index 76451af0..2a154941 100644 --- a/src/api-impl-jni/widgets/android_opengl_GLSurfaceView.c +++ b/src/api-impl-jni/widgets/android_opengl_GLSurfaceView.c @@ -19,6 +19,8 @@ #include "../generated_headers/android_opengl_GLSurfaceView.h" +#define SOURCE_TOUCHSCREEN 4098 + // for whatever reason, some Mesa builds don't export the OES function (which we use in order to have GLESv1 support) GL_APICALL void GL_APIENTRY _glEGLImageTargetTexture2DOES_load(GLenum target, GLeglImageOES image); static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC _glEGLImageTargetTexture2DOES = &_glEGLImageTargetTexture2DOES_load; @@ -469,7 +471,7 @@ static void call_ontouch_callback(GtkEventControllerLegacy* event_controller, in // execute the Java callback function - jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, action, (float)x, (float)y); + jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, SOURCE_TOUCHSCREEN, action, (float)x, (float)y); (*env)->CallBooleanMethod(env, d->this, handle_cache.gl_surface_view.onTouchEvent, motion_event); diff --git a/src/api-impl/android/content/res/AssetManager.java b/src/api-impl/android/content/res/AssetManager.java index 12c19a53..465d9754 100644 --- a/src/api-impl/android/content/res/AssetManager.java +++ b/src/api-impl/android/content/res/AssetManager.java @@ -301,9 +301,8 @@ public final class AssetManager { return map; } - /*package*/ final boolean getThemeValue(int theme, int ident, + /*package*/ final boolean getThemeValue(Map style, int ident, TypedValue outValue, boolean resolveRefs) { - Map style = loadStyle(theme); EntryGroup entryGroup = tableBlockSearch(ident); if (entryGroup == null) return false; diff --git a/src/api-impl/android/content/res/Resources.java b/src/api-impl/android/content/res/Resources.java index 47f853bc..65671c5e 100644 --- a/src/api-impl/android/content/res/Resources.java +++ b/src/api-impl/android/content/res/Resources.java @@ -1422,7 +1422,7 @@ public class Resources { */ public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) { - boolean got = mAssets.getThemeValue(mTheme, resid, outValue, resolveRefs); + boolean got = mAssets.getThemeValue(themeMap, resid, outValue, resolveRefs); if (false) { System.out.println( "resolveAttribute #" + Integer.toHexString(resid) + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type) + ", data=0x" + Integer.toHexString(outValue.data)); diff --git a/src/api-impl/android/graphics/Matrix.java b/src/api-impl/android/graphics/Matrix.java index 0bdec467..5d3639aa 100644 --- a/src/api-impl/android/graphics/Matrix.java +++ b/src/api-impl/android/graphics/Matrix.java @@ -202,7 +202,8 @@ public class Matrix { * This maybe faster than testing if (getType() == 0) */ public boolean isIdentity() { - return native_isIdentity(native_instance); + return true; + // return native_isIdentity(native_instance); } /** * Returns true if will map a rectangle to another rectangle. This can be diff --git a/src/api-impl/android/view/MotionEvent.java b/src/api-impl/android/view/MotionEvent.java index aa0bc284..3c85c0c2 100644 --- a/src/api-impl/android/view/MotionEvent.java +++ b/src/api-impl/android/view/MotionEvent.java @@ -1363,6 +1363,7 @@ public final class MotionEvent extends InputEvent { private static native void nativeScale(int nativePtr, float scale); private static native void nativeTransform(int nativePtr, Matrix matrix); + int source; int action; float coord_x; float coord_y; @@ -1370,7 +1371,8 @@ public final class MotionEvent extends InputEvent { private MotionEvent() { } - public MotionEvent(int action, float coord_x, float coord_y) { + public MotionEvent(int source, int action, float coord_x, float coord_y) { + this.source = source; this.action = action; this.coord_x = coord_x; this.coord_y = coord_y; @@ -1694,7 +1696,7 @@ public final class MotionEvent extends InputEvent { */ @Override public final int getSource() { - return 4098 /*SOURCE_TOUCHSCREEN*/; // TODO: reflect reality + return source; // return nativeGetSource(mNativePtr); } @@ -1931,6 +1933,10 @@ public final class MotionEvent extends InputEvent { * @see #AXIS_Y */ public final float getAxisValue(int axis) { + if (axis == AXIS_HSCROLL) + return coord_x; + else if (axis == AXIS_VSCROLL) + return coord_y; return nativeGetAxisValue(mNativePtr, axis, 0, HISTORY_CURRENT); } diff --git a/src/api-impl/android/view/View.java b/src/api-impl/android/view/View.java index 69bf8802..70be3e6c 100644 --- a/src/api-impl/android/view/View.java +++ b/src/api-impl/android/view/View.java @@ -3,6 +3,7 @@ package android.view; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Handler; @@ -1195,4 +1196,9 @@ public class View extends Object { public void setTranslationY(float translationY) {} public void setAlpha(float alpha) {} + + public boolean onGenericMotionEvent(MotionEvent event) {return false;} + + protected boolean awakenScrollBars() {return false;} + public Matrix getMatrix() {return new Matrix();} } diff --git a/src/api-impl/android/view/ViewParent.java b/src/api-impl/android/view/ViewParent.java index 8b07d9d3..21c3c673 100644 --- a/src/api-impl/android/view/ViewParent.java +++ b/src/api-impl/android/view/ViewParent.java @@ -1,6 +1,5 @@ package android.view; -import android.graphics.Rect; - public interface ViewParent { + public abstract ViewParent getParent(); } diff --git a/src/api-impl/android/widget/EdgeEffect.java b/src/api-impl/android/widget/EdgeEffect.java index 4c0f9f78..79321447 100644 --- a/src/api-impl/android/widget/EdgeEffect.java +++ b/src/api-impl/android/widget/EdgeEffect.java @@ -14,4 +14,8 @@ public class EdgeEffect extends View { super(context, attributeSet); } + public void setSize(int width, int height) {} + public void onPull(float deltaDistance) {} + public boolean isFinished() {return true;} + }