api-impl{-jni}: make view.onTouchEvent work, misc stuff to make input work for Unity games

onTouchEvent was previously incorrectly handled in GLSurfaceView; move it
to View so that it works properly with any of it's descendants.

This is done by reusing the existing setOnTouchListener implementation
and changing it to use GtkEventControllerLegacy which provides motion
events.

Technically some of the code is in WrapperWidget.c since every widget
calls wrapper_widget_set_jobject and we already have related code
there.
This commit is contained in:
Mis012
2023-10-17 21:33:59 +02:00
parent 58fa4b5590
commit 4a0755c6e0
14 changed files with 154 additions and 127 deletions

View File

@@ -5,6 +5,8 @@
#include "../sk_area/sk_area.h"
#include "../generated_headers/android_view_View.h"
#include "WrapperWidget.h"
G_DEFINE_TYPE(WrapperWidget, wrapper_widget, GTK_TYPE_WIDGET)
@@ -122,4 +124,10 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job
// add a callback for when the widget is mapped, which will call onMeasure to figure out what size the widget wants to be
g_signal_connect(wrapper, "map", G_CALLBACK(on_mapped), NULL);
}
jmethodID ontouchevent_method = _METHOD(_CLASS(jobj), "onTouchEvent", "(Landroid/view/MotionEvent;)Z");
if (ontouchevent_method != handle_cache.view.onTouchEvent) {
/* use gtk_widget_get_first_child since the jobject may not have the "widget" variable set yet */
_setOnTouchListener(env, jobj, gtk_widget_get_first_child(wrapper), NULL);
}
}

View File

@@ -62,6 +62,7 @@ JNIEXPORT jlong JNICALL Java_android_opengl_GLSurfaceView_native_1constructor(JN
gtk_widget_set_vexpand(wrapper, TRUE);
GtkWidget *gl_area = gtk_gl_area_new();
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), gl_area);
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
return _INTPTR(gl_area);
}
@@ -460,54 +461,9 @@ check_gl_error();
return TRUE;
}
struct jni_callback_data { JavaVM *jvm; jobject this; jclass this_class; };
static void call_ontouch_callback(GtkEventControllerLegacy* event_controller, int action, double x, double y, struct jni_callback_data *d)
{
JNIEnv *env;
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
// execute the Java callback function
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);
if((*env)->ExceptionCheck(env))
(*env)->ExceptionDescribe(env);
(*env)->DeleteLocalRef(env, motion_event);
}
// TODO: find a way to reconcile this with libandroid/input.c
static gboolean on_event(GtkEventControllerLegacy* self, GdkEvent* event, struct jni_callback_data *d)
{
double x;
double y;
// TODO: this doesn't work for multitouch
switch(gdk_event_get_event_type(event)) {
case GDK_BUTTON_PRESS:
case GDK_TOUCH_BEGIN:
gdk_event_get_position(event, &x, &y);
call_ontouch_callback(self, MOTION_EVENT_ACTION_DOWN, x, y, d);
break;
case GDK_BUTTON_RELEASE:
case GDK_TOUCH_END:
gdk_event_get_position(event, &x, &y);
call_ontouch_callback(self, MOTION_EVENT_ACTION_UP, x, y, d);
break;
case GDK_MOTION_NOTIFY:
case GDK_TOUCH_UPDATE:
gdk_event_get_position(event, &x, &y);
call_ontouch_callback(self, MOTION_EVENT_ACTION_MOVE, x, y, d);
break;
}
}
extern gboolean tick_callback(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer user_data);
JNIEXPORT void JNICALL Java_android_opengl_GLSurfaceView_native_1set_1renderer(JNIEnv *env, jobject this, jobject renderer, jboolean implements_onTouchEvent)
JNIEXPORT void JNICALL Java_android_opengl_GLSurfaceView_native_1set_1renderer(JNIEnv *env, jobject this, jobject renderer)
{
GtkWidget *gl_area = GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "widget")));
@@ -535,21 +491,6 @@ JNIEXPORT void JNICALL Java_android_opengl_GLSurfaceView_native_1set_1renderer(J
g_signal_connect(gl_area, "render", G_CALLBACK(render), gl_callback_data);
g_signal_connect(gl_area, "realize", G_CALLBACK(on_realize), gl_callback_data);
if(implements_onTouchEvent) {
struct jni_callback_data *callback_data = malloc(sizeof(struct jni_callback_data));
callback_data->jvm = jvm;
callback_data->this = _REF(this);
callback_data->this_class = _REF(_CLASS(this));
printf("callback_data->jvm: %p\n", callback_data->jvm);
GtkEventController *controller = gtk_event_controller_legacy_new();
gtk_widget_add_controller(gl_area, controller);
g_signal_connect(controller, "event", G_CALLBACK(on_event), callback_data);
printf("GREP FOR MEEEE -- //FIXME\n");
}
gtk_widget_add_tick_callback(gl_area, tick_callback, NULL, NULL);
//FIXME

View File

@@ -78,6 +78,7 @@ JNIEXPORT jlong JNICALL Java_android_widget_FrameLayout_native_1constructor(JNIE
GtkWidget *wrapper = g_object_ref(wrapper_widget_new());
GtkWidget *frame_layout = frame_layout_widget_new();
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), frame_layout);
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
gtk_widget_set_name(GTK_WIDGET(frame_layout), "FrameLayout");
return _INTPTR(frame_layout);
}