You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
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.
134 lines
4.5 KiB
C
134 lines
4.5 KiB
C
#include <gtk/gtk.h>
|
|
|
|
#include "../defines.h"
|
|
#include "../util.h"
|
|
|
|
#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)
|
|
|
|
static void wrapper_widget_init (WrapperWidget *wrapper_widget)
|
|
{
|
|
|
|
}
|
|
|
|
static void wrapper_widget_dispose(GObject *wrapper_widget)
|
|
{
|
|
gtk_widget_unparent(gtk_widget_get_first_child(GTK_WIDGET(wrapper_widget)));
|
|
WrapperWidget *wrapper = WRAPPER_WIDGET(wrapper_widget);
|
|
if (wrapper->jvm) {
|
|
JNIEnv *env;
|
|
(*wrapper->jvm)->GetEnv(wrapper->jvm, (void**)&env, JNI_VERSION_1_6);
|
|
if (wrapper->jobj)
|
|
_UNREF(wrapper->jobj);
|
|
if (wrapper->canvas)
|
|
_UNREF(wrapper->canvas);
|
|
}
|
|
G_OBJECT_CLASS (wrapper_widget_parent_class)->dispose (wrapper_widget);
|
|
}
|
|
|
|
void skia_draw_func(SKArea *sk_area, sk_canvas_t *canvas, WrapperWidget *wrapper_widget)
|
|
{
|
|
JNIEnv *env;
|
|
(*wrapper_widget->jvm)->GetEnv(wrapper_widget->jvm, (void**)&env, JNI_VERSION_1_6);
|
|
if(wrapper_widget->canvas == NULL) {
|
|
wrapper_widget->canvas = _REF((*env)->NewObject(env, handle_cache.canvas.class, handle_cache.canvas.constructor, _INTPTR(canvas), 0));
|
|
} else {
|
|
_SET_LONG_FIELD(wrapper_widget->canvas, "skia_canvas", _INTPTR(canvas));
|
|
}
|
|
|
|
(*env)->CallVoidMethod(env, wrapper_widget->jobj, wrapper_widget->draw_method, wrapper_widget->canvas);
|
|
|
|
if((*env)->ExceptionCheck(env))
|
|
(*env)->ExceptionDescribe(env);
|
|
}
|
|
|
|
/*void wrapper_snapshot(GtkWidget* widget, GtkSnapshot* snapshot)
|
|
{
|
|
gtk_widget_snapshot_child(widget, gtk_widget_get_first_child(widget), snapshot);
|
|
}*/
|
|
|
|
|
|
static void wrapper_widget_class_init(WrapperWidgetClass *class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
|
|
|
|
object_class->dispose = wrapper_widget_dispose;
|
|
|
|
// widget_class->snapshot = wrapper_snapshot;
|
|
|
|
gtk_widget_class_set_layout_manager_type(widget_class, GTK_TYPE_BIN_LAYOUT);
|
|
}
|
|
|
|
GtkWidget * wrapper_widget_new(void)
|
|
{
|
|
return g_object_new (wrapper_widget_get_type(), NULL);
|
|
}
|
|
|
|
void wrapper_widget_set_child(WrapperWidget *parent, GtkWidget *child) // TODO: make sure there can only be one child
|
|
{
|
|
gtk_widget_insert_before(child, GTK_WIDGET(parent), NULL);
|
|
}
|
|
|
|
#define MEASURE_SPEC_EXACTLY (1 << 30)
|
|
|
|
static void on_mapped(GtkWidget* self, gpointer data)
|
|
{
|
|
WrapperWidget *wrapper = WRAPPER_WIDGET(self);
|
|
if (wrapper->jvm) {
|
|
JNIEnv *env;
|
|
(*wrapper->jvm)->GetEnv(wrapper->jvm, (void**)&env, JNI_VERSION_1_6);
|
|
|
|
(*env)->CallVoidMethod(env, wrapper->jobj, wrapper->measure_method, MEASURE_SPEC_EXACTLY | gtk_widget_get_width(self), MEASURE_SPEC_EXACTLY | gtk_widget_get_height(self));
|
|
int width = (*env)->CallIntMethod(env, wrapper->jobj, handle_cache.view.getMeasuredWidth);
|
|
if (width > 0)
|
|
g_object_set(G_OBJECT(self), "width-request", width, NULL);
|
|
int height = (*env)->CallIntMethod(env, wrapper->jobj, handle_cache.view.getMeasuredHeight);
|
|
if (height > 0)
|
|
g_object_set(G_OBJECT(self), "height-request", height, NULL);
|
|
}
|
|
}
|
|
|
|
// FIXME: this is used in one other place as well, should probably go in util.c or gtk_util.c?
|
|
gboolean tick_callback(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer user_data)
|
|
{
|
|
gtk_widget_queue_draw(widget);
|
|
gtk_widget_queue_draw(gtk_widget_get_parent(widget));
|
|
return G_SOURCE_CONTINUE;
|
|
}
|
|
|
|
void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject jobj)
|
|
{
|
|
JavaVM *jvm;
|
|
(*env)->GetJavaVM(env, &jvm);
|
|
wrapper->jvm = jvm;
|
|
wrapper->jobj = _REF(jobj);
|
|
jmethodID draw_method = _METHOD(_CLASS(jobj), "onDraw", "(Landroid/graphics/Canvas;)V");
|
|
if (draw_method != handle_cache.view.onDraw) {
|
|
wrapper->draw_method = draw_method;
|
|
|
|
GtkWidget *sk_area = sk_area_new();
|
|
sk_area_set_draw_func(SK_AREA_WIDGET(sk_area), skia_draw_func, wrapper);
|
|
gtk_widget_insert_before(sk_area, GTK_WIDGET(wrapper), NULL);
|
|
gtk_widget_add_tick_callback(sk_area, tick_callback, NULL, NULL);
|
|
}
|
|
|
|
jmethodID measure_method = _METHOD(_CLASS(jobj), "onMeasure", "(II)V");
|
|
if (measure_method != handle_cache.view.onMeasure) {
|
|
wrapper->measure_method = measure_method;
|
|
// 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);
|
|
}
|
|
}
|