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
prevent reference cycles between Java and native objects
This commit is contained in:
@@ -45,7 +45,6 @@ JNIEXPORT jlong JNICALL Java_android_graphics_Bitmap_native_1bitmap_1from_1path(
|
|||||||
|
|
||||||
attach_sk_image(pixbuf);
|
attach_sk_image(pixbuf);
|
||||||
|
|
||||||
g_object_ref(pixbuf);
|
|
||||||
return _INTPTR(pixbuf);
|
return _INTPTR(pixbuf);
|
||||||
}
|
}
|
||||||
/* new empty bitmap */
|
/* new empty bitmap */
|
||||||
|
|||||||
@@ -115,3 +115,9 @@ JNIEXPORT void JNICALL Java_android_graphics_Canvas_native_1drawPath(JNIEnv *env
|
|||||||
|
|
||||||
sk_canvas_draw_path(canvas, path, paint);
|
sk_canvas_draw_path(canvas, path, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JNIEXPORT void JNICALL Java_android_graphics_Canvas_native_1destroy_1canvas(JNIEnv *env, jclass class, jlong skia_canvas)
|
||||||
|
{
|
||||||
|
sk_canvas_t *canvas = (sk_canvas_t *)_PTR(skia_canvas);
|
||||||
|
sk_canvas_destroy(canvas);
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#define _INTPTR(ptr)((jlong)(intptr_t)(ptr))
|
#define _INTPTR(ptr)((jlong)(intptr_t)(ptr))
|
||||||
#define _REF(obj)((*env)->NewGlobalRef(env, obj))
|
#define _REF(obj)((*env)->NewGlobalRef(env, obj))
|
||||||
#define _UNREF(obj)((*env)->DeleteGlobalRef(env, obj))
|
#define _UNREF(obj)((*env)->DeleteGlobalRef(env, obj))
|
||||||
|
#define _WEAK_REF(obj)((*env)->NewWeakGlobalRef(env, obj))
|
||||||
|
#define _WEAK_UNREF(obj)((*env)->DeleteWeakGlobalRef(env, obj))
|
||||||
#define _CLASS(object) ((*env)->GetObjectClass(env, object))
|
#define _CLASS(object) ((*env)->GetObjectClass(env, object))
|
||||||
#define _SUPER(object) ((*env)->GetSuperclass(env, object))
|
#define _SUPER(object) ((*env)->GetSuperclass(env, object))
|
||||||
#define _METHOD(class, method, attrs) ((*env)->GetMethodID(env, class, method, attrs))
|
#define _METHOD(class, method, attrs) ((*env)->GetMethodID(env, class, method, attrs))
|
||||||
|
|||||||
@@ -89,6 +89,14 @@ JNIEXPORT void JNICALL Java_android_graphics_Canvas_native_1rotate_1and_1transla
|
|||||||
JNIEXPORT void JNICALL Java_android_graphics_Canvas_native_1drawPath
|
JNIEXPORT void JNICALL Java_android_graphics_Canvas_native_1drawPath
|
||||||
(JNIEnv *, jclass, jlong, jlong, jlong);
|
(JNIEnv *, jclass, jlong, jlong, jlong);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: android_graphics_Canvas
|
||||||
|
* Method: native_destroy_canvas
|
||||||
|
* Signature: (J)V
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_android_graphics_Canvas_native_1destroy_1canvas
|
||||||
|
(JNIEnv *, jclass, jlong);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -201,19 +201,19 @@ extern "C" {
|
|||||||
#define android_view_View_TEXT_DIRECTION_RTL 4L
|
#define android_view_View_TEXT_DIRECTION_RTL 4L
|
||||||
/*
|
/*
|
||||||
* Class: android_view_View
|
* Class: android_view_View
|
||||||
* Method: setOnTouchListener
|
* Method: nativeSetOnTouchListener
|
||||||
* Signature: (Landroid/view/View/OnTouchListener;)V
|
* Signature: (J)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_android_view_View_setOnTouchListener
|
JNIEXPORT void JNICALL Java_android_view_View_nativeSetOnTouchListener
|
||||||
(JNIEnv *, jobject, jobject);
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: android_view_View
|
* Class: android_view_View
|
||||||
* Method: setOnClickListener
|
* Method: nativeSetOnClickListener
|
||||||
* Signature: (Landroid/view/View/OnClickListener;)V
|
* Signature: (J)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_android_view_View_setOnClickListener
|
JNIEXPORT void JNICALL Java_android_view_View_nativeSetOnClickListener
|
||||||
(JNIEnv *, jobject, jobject);
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: android_view_View
|
* Class: android_view_View
|
||||||
@@ -337,11 +337,11 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1setVisibility
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: android_view_View
|
* Class: android_view_View
|
||||||
* Method: setOnLongClickListener
|
* Method: nativeSetOnLongClickListener
|
||||||
* Signature: (Landroid/view/View/OnLongClickListener;)V
|
* Signature: (J)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_android_view_View_setOnLongClickListener
|
JNIEXPORT void JNICALL Java_android_view_View_nativeSetOnLongClickListener
|
||||||
(JNIEnv *, jobject, jobject);
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: android_view_View
|
* Class: android_view_View
|
||||||
|
|||||||
@@ -217,11 +217,11 @@ JNIEXPORT void JNICALL Java_android_widget_Button_native_1setText
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: android_widget_Button
|
* Class: android_widget_Button
|
||||||
* Method: native_setOnClickListener
|
* Method: nativeSetOnClickListener
|
||||||
* Signature: (JLandroid/view/View/OnClickListener;)V
|
* Signature: (J)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_android_widget_Button_native_1setOnClickListener
|
JNIEXPORT void JNICALL Java_android_widget_Button_nativeSetOnClickListener
|
||||||
(JNIEnv *, jobject, jlong, jobject);
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -225,11 +225,11 @@ JNIEXPORT void JNICALL Java_android_widget_ImageButton_native_1setDrawable
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: android_widget_ImageButton
|
* Class: android_widget_ImageButton
|
||||||
* Method: native_setOnClickListener
|
* Method: nativeSetOnClickListener
|
||||||
* Signature: (JLandroid/view/View/OnClickListener;)V
|
* Signature: (J)V
|
||||||
*/
|
*/
|
||||||
JNIEXPORT void JNICALL Java_android_widget_ImageButton_native_1setOnClickListener
|
JNIEXPORT void JNICALL Java_android_widget_ImageButton_nativeSetOnClickListener
|
||||||
(JNIEnv *, jobject, jlong, jobject);
|
(JNIEnv *, jobject, jlong);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ JNIEXPORT jlong JNICALL Java_android_graphics_drawable_Drawable_native_1construc
|
|||||||
JavaPaintable *paintable = NULL;
|
JavaPaintable *paintable = NULL;
|
||||||
if (handle_cache.drawable.draw != _METHOD(_CLASS(this), "draw", "(Landroid/graphics/Canvas;)V")) {
|
if (handle_cache.drawable.draw != _METHOD(_CLASS(this), "draw", "(Landroid/graphics/Canvas;)V")) {
|
||||||
paintable = g_object_new(java_paintable_get_type(), NULL);
|
paintable = g_object_new(java_paintable_get_type(), NULL);
|
||||||
paintable->drawable = _REF(this);
|
paintable->drawable = _WEAK_REF(this);
|
||||||
}
|
}
|
||||||
return _INTPTR(paintable);
|
return _INTPTR(paintable);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ void set_up_handle_cache(JNIEnv *env)
|
|||||||
handle_cache.view.onInterceptTouchEvent = _METHOD(handle_cache.view.class, "onInterceptTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
handle_cache.view.onInterceptTouchEvent = _METHOD(handle_cache.view.class, "onInterceptTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||||
handle_cache.view.layoutInternal = _METHOD(handle_cache.view.class, "layoutInternal", "(II)V");
|
handle_cache.view.layoutInternal = _METHOD(handle_cache.view.class, "layoutInternal", "(II)V");
|
||||||
handle_cache.view.measure = _METHOD(handle_cache.view.class, "measure", "(II)V");
|
handle_cache.view.measure = _METHOD(handle_cache.view.class, "measure", "(II)V");
|
||||||
|
handle_cache.view.performLongClick = _METHOD(handle_cache.view.class, "performLongClick", "(FF)Z");
|
||||||
|
|
||||||
handle_cache.asset_manager.class = _REF((*env)->FindClass(env, "android/content/res/AssetManager"));
|
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");
|
handle_cache.asset_manager.extractFromAPK = _STATIC_METHOD(handle_cache.asset_manager.class, "extractFromAPK", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ struct handle_cache {
|
|||||||
jmethodID onInterceptTouchEvent;
|
jmethodID onInterceptTouchEvent;
|
||||||
jmethodID layoutInternal;
|
jmethodID layoutInternal;
|
||||||
jmethodID measure;
|
jmethodID measure;
|
||||||
|
jmethodID performLongClick;
|
||||||
} view;
|
} view;
|
||||||
struct {
|
struct {
|
||||||
jclass class;
|
jclass class;
|
||||||
|
|||||||
@@ -87,11 +87,20 @@ static GtkSizeRequestMode android_layout_get_request_mode(GtkLayoutManager *layo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void android_layout_dispose(GObject *layout_manager)
|
||||||
|
{
|
||||||
|
AndroidLayout *layout = ATL_ANDROID_LAYOUT(layout_manager);
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
_WEAK_UNREF(layout->view);
|
||||||
|
}
|
||||||
|
|
||||||
static void android_layout_class_init(AndroidLayoutClass *klass)
|
static void android_layout_class_init(AndroidLayoutClass *klass)
|
||||||
{
|
{
|
||||||
klass->parent_class.measure = android_layout_measure;
|
klass->parent_class.measure = android_layout_measure;
|
||||||
klass->parent_class.allocate = android_layout_allocate;
|
klass->parent_class.allocate = android_layout_allocate;
|
||||||
klass->parent_class.get_request_mode = android_layout_get_request_mode;
|
klass->parent_class.get_request_mode = android_layout_get_request_mode;
|
||||||
|
|
||||||
|
klass->parent_class.parent_class.dispose = android_layout_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void android_layout_init(AndroidLayout *self) {}
|
static void android_layout_init(AndroidLayout *self) {}
|
||||||
@@ -101,7 +110,8 @@ G_DEFINE_TYPE(AndroidLayout, android_layout, GTK_TYPE_LAYOUT_MANAGER)
|
|||||||
GtkLayoutManager *android_layout_new(jobject view)
|
GtkLayoutManager *android_layout_new(jobject view)
|
||||||
{
|
{
|
||||||
AndroidLayout *layout = g_object_new(android_layout_get_type(), NULL);
|
AndroidLayout *layout = g_object_new(android_layout_get_type(), NULL);
|
||||||
layout->view = view;
|
JNIEnv *env = get_jni_env();
|
||||||
|
layout->view = _WEAK_REF(view);
|
||||||
layout->width = MATCH_PARENT;
|
layout->width = MATCH_PARENT;
|
||||||
layout->height = MATCH_PARENT;
|
layout->height = MATCH_PARENT;
|
||||||
return &layout->parent_instance;
|
return &layout->parent_instance;
|
||||||
|
|||||||
@@ -13,34 +13,31 @@
|
|||||||
|
|
||||||
#define SOURCE_TOUCHSCREEN 0x1002
|
#define SOURCE_TOUCHSCREEN 0x1002
|
||||||
|
|
||||||
struct touch_callback_data { JavaVM *jvm; jobject this; jobject on_touch_listener; jclass on_touch_listener_class; bool intercepted; };
|
|
||||||
|
|
||||||
static GdkEvent *canceled_event = NULL;
|
static GdkEvent *canceled_event = NULL;
|
||||||
static struct touch_callback_data *cancel_triggerer = NULL;
|
static WrapperWidget *cancel_triggerer = NULL;
|
||||||
|
|
||||||
static bool call_ontouch_callback(int action, double x, double y, struct touch_callback_data *d, GtkPropagationPhase phase, guint32 timestamp, GdkEvent *event)
|
static bool call_ontouch_callback(WrapperWidget *wrapper, int action, double x, double y, GtkPropagationPhase phase, guint32 timestamp, GdkEvent *event)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
double raw_x;
|
double raw_x;
|
||||||
double raw_y;
|
double raw_y;
|
||||||
JNIEnv *env;
|
JNIEnv *env = get_jni_env();
|
||||||
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
|
jobject this = wrapper->jobj;
|
||||||
|
|
||||||
gdk_event_get_position(event, &raw_x, &raw_y);
|
gdk_event_get_position(event, &raw_x, &raw_y);
|
||||||
jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, SOURCE_TOUCHSCREEN, action, (float)x, (float)y, (long)timestamp, (float)raw_x, (float)raw_y);
|
jobject motion_event = (*env)->NewObject(env, handle_cache.motion_event.class, handle_cache.motion_event.constructor, SOURCE_TOUCHSCREEN, action, (float)x, (float)y, (long)timestamp, (float)raw_x, (float)raw_y);
|
||||||
|
|
||||||
if (phase == GTK_PHASE_CAPTURE && !d->intercepted) {
|
if (phase == GTK_PHASE_CAPTURE && !wrapper->intercepting_touch) {
|
||||||
d->intercepted = (*env)->CallBooleanMethod(env, d->this, handle_cache.view.onInterceptTouchEvent, motion_event);
|
wrapper->intercepting_touch = (*env)->CallBooleanMethod(env, this, handle_cache.view.onInterceptTouchEvent, motion_event);
|
||||||
if (d->intercepted) {
|
if (wrapper->intercepting_touch) {
|
||||||
// store the event that was canceled and let it propagate to the child widgets
|
// store the event that was canceled and let it propagate to the child widgets
|
||||||
canceled_event = event;
|
canceled_event = event;
|
||||||
cancel_triggerer = d;
|
cancel_triggerer = wrapper;
|
||||||
}
|
}
|
||||||
ret = false;
|
ret = false;
|
||||||
} else if(d->on_touch_listener) /* NULL listener means the callback was registered for onTouchEvent */
|
} else {
|
||||||
ret = (*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);
|
ret = (*env)->CallBooleanMethod(env, this, handle_cache.view.onTouchEvent, motion_event);
|
||||||
else
|
}
|
||||||
ret = (*env)->CallBooleanMethod(env, d->this, _METHOD(d->on_touch_listener_class, "onTouchEvent", "(Landroid/view/MotionEvent;)Z"), motion_event);
|
|
||||||
|
|
||||||
if((*env)->ExceptionCheck(env))
|
if((*env)->ExceptionCheck(env))
|
||||||
(*env)->ExceptionDescribe(env);
|
(*env)->ExceptionDescribe(env);
|
||||||
@@ -48,7 +45,7 @@ static bool call_ontouch_callback(int action, double x, double y, struct touch_c
|
|||||||
(*env)->DeleteLocalRef(env, motion_event);
|
(*env)->DeleteLocalRef(env, motion_event);
|
||||||
|
|
||||||
if (action == MOTION_EVENT_ACTION_UP)
|
if (action == MOTION_EVENT_ACTION_UP)
|
||||||
d->intercepted = false;
|
wrapper->intercepting_touch = false;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static void gdk_event_get_widget_relative_position(GdkEvent *event, GtkWidget *widget, double *x, double *y)
|
static void gdk_event_get_widget_relative_position(GdkEvent *event, GtkWidget *widget, double *x, double *y)
|
||||||
@@ -70,41 +67,42 @@ static void gdk_event_get_widget_relative_position(GdkEvent *event, GtkWidget *w
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: find a way to reconcile this with libandroid/input.c?
|
// TODO: find a way to reconcile this with libandroid/input.c?
|
||||||
static gboolean on_event(GtkEventControllerLegacy *event_controller, GdkEvent *event, struct touch_callback_data *d)
|
static gboolean on_event(GtkEventControllerLegacy *event_controller, GdkEvent *event, gpointer user_data)
|
||||||
{
|
{
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
|
|
||||||
GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(event_controller));
|
GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(event_controller));
|
||||||
|
WrapperWidget *wrapper = WRAPPER_WIDGET(widget);
|
||||||
GtkPropagationPhase phase = gtk_event_controller_get_propagation_phase(GTK_EVENT_CONTROLLER(event_controller));
|
GtkPropagationPhase phase = gtk_event_controller_get_propagation_phase(GTK_EVENT_CONTROLLER(event_controller));
|
||||||
guint32 timestamp = gdk_event_get_time(event);
|
guint32 timestamp = gdk_event_get_time(event);
|
||||||
|
|
||||||
// TODO: this doesn't work for multitouch
|
// TODO: this doesn't work for multitouch
|
||||||
if (cancel_triggerer == d) { // cancel done
|
if (cancel_triggerer == wrapper) { // cancel done
|
||||||
canceled_event = NULL;
|
canceled_event = NULL;
|
||||||
cancel_triggerer = NULL;
|
cancel_triggerer = NULL;
|
||||||
} else if (event == canceled_event) {
|
} else if (event == canceled_event) {
|
||||||
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
||||||
call_ontouch_callback(MOTION_EVENT_ACTION_CANCEL, x, y, d, phase, timestamp, event);
|
call_ontouch_callback(wrapper, MOTION_EVENT_ACTION_CANCEL, x, y, phase, timestamp, event);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch(gdk_event_get_event_type(event)) {
|
switch(gdk_event_get_event_type(event)) {
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
case GDK_TOUCH_BEGIN:
|
case GDK_TOUCH_BEGIN:
|
||||||
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
||||||
return call_ontouch_callback(MOTION_EVENT_ACTION_DOWN, x, y, d, phase, timestamp, event);
|
return call_ontouch_callback(wrapper, MOTION_EVENT_ACTION_DOWN, x, y, phase, timestamp, event);
|
||||||
break;
|
break;
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
case GDK_TOUCH_END:
|
case GDK_TOUCH_END:
|
||||||
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
||||||
return call_ontouch_callback(MOTION_EVENT_ACTION_UP, x, y, d, phase, timestamp, event);
|
return call_ontouch_callback(wrapper, MOTION_EVENT_ACTION_UP, x, y, phase, timestamp, event);
|
||||||
break;
|
break;
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
if (!(gdk_event_get_modifier_state(event) & GDK_BUTTON1_MASK))
|
if (!(gdk_event_get_modifier_state(event) & GDK_BUTTON1_MASK))
|
||||||
break;
|
break;
|
||||||
case GDK_TOUCH_UPDATE:
|
case GDK_TOUCH_UPDATE:
|
||||||
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
gdk_event_get_widget_relative_position(event, widget, &x, &y);
|
||||||
return call_ontouch_callback(MOTION_EVENT_ACTION_MOVE, x, y, d, phase, timestamp, event);
|
return call_ontouch_callback(wrapper, MOTION_EVENT_ACTION_MOVE, x, y, phase, timestamp, event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -113,12 +111,13 @@ static gboolean on_event(GtkEventControllerLegacy *event_controller, GdkEvent *e
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_click(GtkGestureClick *gesture, int n_press, double x, double y, struct touch_callback_data *d)
|
static void on_click(GtkGestureClick *gesture, int n_press, double x, double y, gpointer user_data)
|
||||||
{
|
{
|
||||||
JNIEnv *env;
|
JNIEnv *env = get_jni_env();
|
||||||
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
|
GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
|
||||||
|
WrapperWidget *wrapper = WRAPPER_WIDGET(gtk_widget_get_parent(widget));
|
||||||
|
|
||||||
(*env)->CallVoidMethod(env, d->on_touch_listener, _METHOD(d->on_touch_listener_class, "onClick", "(Landroid/view/View;)V"), d->this);
|
(*env)->CallBooleanMethod(env, wrapper->jobj, handle_cache.view.performClick);
|
||||||
|
|
||||||
if((*env)->ExceptionCheck(env))
|
if((*env)->ExceptionCheck(env))
|
||||||
(*env)->ExceptionDescribe(env);
|
(*env)->ExceptionDescribe(env);
|
||||||
@@ -146,25 +145,16 @@ static gboolean scroll_cb(GtkEventControllerScroll* self, gdouble dx, gdouble dy
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject on_touch_listener)
|
void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget)
|
||||||
{
|
{
|
||||||
JavaVM *jvm;
|
|
||||||
(*env)->GetJavaVM(env, &jvm);
|
|
||||||
|
|
||||||
struct touch_callback_data *callback_data = malloc(sizeof(struct touch_callback_data));
|
|
||||||
callback_data->jvm = jvm;
|
|
||||||
callback_data->this = _REF(this);
|
|
||||||
callback_data->on_touch_listener = on_touch_listener ? _REF(on_touch_listener) : NULL;
|
|
||||||
callback_data->on_touch_listener_class = on_touch_listener ? _REF(_CLASS(callback_data->on_touch_listener)) : _REF(_CLASS(callback_data->this));
|
|
||||||
|
|
||||||
GtkEventController *old_controller = g_object_get_data(G_OBJECT(widget), "on_touch_listener");
|
GtkEventController *old_controller = g_object_get_data(G_OBJECT(widget), "on_touch_listener");
|
||||||
if(old_controller)
|
if(old_controller)
|
||||||
gtk_widget_remove_controller(widget, old_controller);
|
return;
|
||||||
|
|
||||||
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_event_controller_legacy_new());
|
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_event_controller_legacy_new());
|
||||||
gtk_event_controller_set_propagation_phase(controller, GTK_PHASE_BUBBLE);
|
gtk_event_controller_set_propagation_phase(controller, GTK_PHASE_BUBBLE);
|
||||||
|
|
||||||
g_signal_connect(controller, "event", G_CALLBACK(on_event), callback_data);
|
g_signal_connect(controller, "event", G_CALLBACK(on_event), NULL);
|
||||||
gtk_widget_add_controller(widget, controller);
|
gtk_widget_add_controller(widget, controller);
|
||||||
g_object_set_data(G_OBJECT(widget), "on_touch_listener", controller);
|
g_object_set_data(G_OBJECT(widget), "on_touch_listener", controller);
|
||||||
|
|
||||||
@@ -177,7 +167,7 @@ void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject o
|
|||||||
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_event_controller_legacy_new());
|
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_event_controller_legacy_new());
|
||||||
gtk_event_controller_set_propagation_phase(controller, GTK_PHASE_CAPTURE);
|
gtk_event_controller_set_propagation_phase(controller, GTK_PHASE_CAPTURE);
|
||||||
|
|
||||||
g_signal_connect(controller, "event", G_CALLBACK(on_event), callback_data);
|
g_signal_connect(controller, "event", G_CALLBACK(on_event), NULL);
|
||||||
gtk_widget_add_controller(widget, controller);
|
gtk_widget_add_controller(widget, controller);
|
||||||
g_object_set_data(G_OBJECT(widget), "on_intercept_touch_listener", controller);
|
g_object_set_data(G_OBJECT(widget), "on_intercept_touch_listener", controller);
|
||||||
}
|
}
|
||||||
@@ -188,35 +178,24 @@ void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject o
|
|||||||
gtk_widget_set_overflow(GTK_WIDGET(wrapper), GTK_OVERFLOW_HIDDEN);
|
gtk_widget_set_overflow(GTK_WIDGET(wrapper), GTK_OVERFLOW_HIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_android_view_View_setOnTouchListener(JNIEnv *env, jobject this, jobject on_touch_listener)
|
JNIEXPORT void JNICALL Java_android_view_View_nativeSetOnTouchListener(JNIEnv *env, jobject this, jlong widget_ptr)
|
||||||
{
|
{
|
||||||
GtkWidget *widget = gtk_widget_get_parent(GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "widget"))));
|
GtkWidget *widget = gtk_widget_get_parent(GTK_WIDGET(_PTR(widget_ptr)));
|
||||||
|
|
||||||
_setOnTouchListener(env, this, widget, on_touch_listener);
|
_setOnTouchListener(env, this, widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_android_view_View_setOnClickListener(JNIEnv *env, jobject this, jobject on_click_listener)
|
JNIEXPORT void JNICALL Java_android_view_View_nativeSetOnClickListener(JNIEnv *env, jobject this, jlong widget_ptr)
|
||||||
{
|
{
|
||||||
GtkWidget *widget = GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "widget")));
|
GtkWidget *widget = GTK_WIDGET(_PTR(widget_ptr));
|
||||||
if (!on_click_listener)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JavaVM *jvm;
|
|
||||||
(*env)->GetJavaVM(env, &jvm);
|
|
||||||
|
|
||||||
struct touch_callback_data *callback_data = malloc(sizeof(struct touch_callback_data));
|
|
||||||
callback_data->jvm = jvm;
|
|
||||||
callback_data->this = _REF(this);
|
|
||||||
callback_data->on_touch_listener = _REF(on_click_listener);
|
|
||||||
callback_data->on_touch_listener_class = _REF(_CLASS(callback_data->on_touch_listener));
|
|
||||||
|
|
||||||
GtkEventController *old_controller = g_object_get_data(G_OBJECT(widget), "on_click_listener");
|
GtkEventController *old_controller = g_object_get_data(G_OBJECT(widget), "on_click_listener");
|
||||||
if(old_controller)
|
if(old_controller)
|
||||||
gtk_widget_remove_controller(widget, old_controller);
|
return;
|
||||||
|
|
||||||
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
|
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
|
||||||
|
|
||||||
g_signal_connect(controller, "released", G_CALLBACK(on_click), callback_data); // the release completes the click, I guess?
|
g_signal_connect(controller, "released", G_CALLBACK(on_click), NULL); // the release completes the click, I guess?
|
||||||
gtk_widget_add_controller(widget, controller);
|
gtk_widget_add_controller(widget, controller);
|
||||||
g_object_set_data(G_OBJECT(widget), "on_click_listener", controller);
|
g_object_set_data(G_OBJECT(widget), "on_click_listener", controller);
|
||||||
widget_set_needs_allocation(widget);
|
widget_set_needs_allocation(widget);
|
||||||
@@ -351,15 +330,27 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1setVisibility(JNIEnv *env,
|
|||||||
*/
|
*/
|
||||||
struct _JavaWidget {GtkWidget parent_instance;};
|
struct _JavaWidget {GtkWidget parent_instance;};
|
||||||
G_DECLARE_FINAL_TYPE(JavaWidget, java_widget, JAVA, WIDGET, GtkWidget)
|
G_DECLARE_FINAL_TYPE(JavaWidget, java_widget, JAVA, WIDGET, GtkWidget)
|
||||||
|
static void java_widget_dispose(GObject *java_widget)
|
||||||
|
{
|
||||||
|
GtkWidget *widget = GTK_WIDGET(java_widget);
|
||||||
|
GtkWidget *child = gtk_widget_get_first_child(widget);
|
||||||
|
while (child) {
|
||||||
|
GtkWidget *_child = gtk_widget_get_next_sibling(child);
|
||||||
|
gtk_widget_unparent(child);
|
||||||
|
child = _child;
|
||||||
|
}
|
||||||
|
}
|
||||||
static void java_widget_init(JavaWidget *java_widget) {}
|
static void java_widget_init(JavaWidget *java_widget) {}
|
||||||
static void java_widget_class_init(JavaWidgetClass *class) {}
|
static void java_widget_class_init(JavaWidgetClass *class) {
|
||||||
|
G_OBJECT_CLASS(class)->dispose = java_widget_dispose;
|
||||||
|
}
|
||||||
G_DEFINE_TYPE(JavaWidget, java_widget, GTK_TYPE_WIDGET)
|
G_DEFINE_TYPE(JavaWidget, java_widget, GTK_TYPE_WIDGET)
|
||||||
|
|
||||||
JNIEXPORT jlong JNICALL Java_android_view_View_native_1constructor(JNIEnv *env, jobject this, jobject context, jobject attrs)
|
JNIEXPORT jlong JNICALL Java_android_view_View_native_1constructor(JNIEnv *env, jobject this, jobject context, jobject attrs)
|
||||||
{
|
{
|
||||||
GtkWidget *wrapper = g_object_ref(wrapper_widget_new());
|
WrapperWidget *wrapper = g_object_ref(WRAPPER_WIDGET(wrapper_widget_new()));
|
||||||
GtkWidget *widget = g_object_new(java_widget_get_type(), NULL);
|
GtkWidget *widget = g_object_new(java_widget_get_type(), NULL);
|
||||||
gtk_widget_set_layout_manager(widget, android_layout_new(_REF(this)));
|
gtk_widget_set_layout_manager(widget, android_layout_new(this));
|
||||||
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), widget);
|
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), widget);
|
||||||
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
|
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
|
||||||
|
|
||||||
@@ -373,7 +364,7 @@ JNIEXPORT jlong JNICALL Java_android_view_View_native_1constructor(JNIEnv *env,
|
|||||||
if (_METHOD(_CLASS(this), "onGenericMotionEvent", "(Landroid/view/MotionEvent;)Z") != handle_cache.view.onGenericMotionEvent) {
|
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);
|
GtkEventController *controller = gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_VERTICAL);
|
||||||
|
|
||||||
g_signal_connect(controller, "scroll", G_CALLBACK(scroll_cb), _REF(this));
|
g_signal_connect(controller, "scroll", G_CALLBACK(scroll_cb), wrapper->jobj);
|
||||||
gtk_widget_add_controller(widget, controller);
|
gtk_widget_add_controller(widget, controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,12 +513,13 @@ JNIEXPORT jboolean JNICALL Java_android_view_View_native_1getGlobalVisibleRect(J
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_long_click(GtkGestureLongPress *gesture, double x, double y, struct touch_callback_data *d)
|
static void on_long_click(GtkGestureLongPress *gesture, double x, double y, gpointer user_data)
|
||||||
{
|
{
|
||||||
JNIEnv *env;
|
JNIEnv *env = get_jni_env();
|
||||||
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
|
GtkWidget *widget = gtk_event_controller_get_widget(GTK_EVENT_CONTROLLER(gesture));
|
||||||
|
WrapperWidget *wrapper = WRAPPER_WIDGET(gtk_widget_get_parent(widget));
|
||||||
|
|
||||||
bool ret =(*env)->CallBooleanMethod(env, d->on_touch_listener, _METHOD(d->on_touch_listener_class, "onLongClick", "(Landroid/view/View;)Z"), d->this);
|
bool ret =(*env)->CallBooleanMethod(env, wrapper->jobj, handle_cache.view.performLongClick, x, y);
|
||||||
|
|
||||||
if((*env)->ExceptionCheck(env))
|
if((*env)->ExceptionCheck(env))
|
||||||
(*env)->ExceptionDescribe(env);
|
(*env)->ExceptionDescribe(env);
|
||||||
@@ -536,7 +528,7 @@ static void on_long_click(GtkGestureLongPress *gesture, double x, double y, stru
|
|||||||
gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
gtk_gesture_set_state(GTK_GESTURE(gesture), GTK_EVENT_SEQUENCE_CLAIMED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_long_click_update(GtkGesture *gesture, GdkEventSequence* sequence, struct touch_callback_data *d)
|
static void on_long_click_update(GtkGesture *gesture, GdkEventSequence* sequence, gpointer user_data)
|
||||||
{
|
{
|
||||||
GdkEvent *event = gtk_gesture_get_last_event(gesture, sequence);
|
GdkEvent *event = gtk_gesture_get_last_event(gesture, sequence);
|
||||||
if (event == canceled_event) {
|
if (event == canceled_event) {
|
||||||
@@ -544,29 +536,17 @@ static void on_long_click_update(GtkGesture *gesture, GdkEventSequence* sequence
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_android_view_View_setOnLongClickListener(JNIEnv *env, jobject this, jobject on_long_click_listener)
|
JNIEXPORT void JNICALL Java_android_view_View_nativeSetOnLongClickListener(JNIEnv *env, jobject this, jlong widget_ptr)
|
||||||
{
|
{
|
||||||
GtkWidget *widget = GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "widget")));
|
GtkWidget *widget = GTK_WIDGET(_PTR(widget_ptr));
|
||||||
if (!on_long_click_listener)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JavaVM *jvm;
|
|
||||||
(*env)->GetJavaVM(env, &jvm);
|
|
||||||
|
|
||||||
struct touch_callback_data *callback_data = malloc(sizeof(struct touch_callback_data));
|
|
||||||
callback_data->jvm = jvm;
|
|
||||||
callback_data->this = _REF(this);
|
|
||||||
callback_data->on_touch_listener = _REF(on_long_click_listener);
|
|
||||||
callback_data->on_touch_listener_class = _REF(_CLASS(callback_data->on_touch_listener));
|
|
||||||
|
|
||||||
GtkEventController *old_controller = g_object_get_data(G_OBJECT(widget), "on_long_click_listener");
|
GtkEventController *old_controller = g_object_get_data(G_OBJECT(widget), "on_long_click_listener");
|
||||||
if(old_controller)
|
if(old_controller)
|
||||||
gtk_widget_remove_controller(widget, old_controller);
|
return;
|
||||||
|
|
||||||
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_gesture_long_press_new());
|
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_gesture_long_press_new());
|
||||||
|
|
||||||
g_signal_connect(controller, "pressed", G_CALLBACK(on_long_click), callback_data);
|
g_signal_connect(controller, "pressed", G_CALLBACK(on_long_click), NULL);
|
||||||
g_signal_connect(controller, "update", G_CALLBACK(on_long_click_update), callback_data);
|
g_signal_connect(controller, "update", G_CALLBACK(on_long_click_update), NULL);
|
||||||
gtk_widget_add_controller(widget, controller);
|
gtk_widget_add_controller(widget, controller);
|
||||||
g_object_set_data(G_OBJECT(widget), "on_long_click_listener", controller);
|
g_object_set_data(G_OBJECT(widget), "on_long_click_listener", controller);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,13 +17,19 @@ static void wrapper_widget_init (WrapperWidget *wrapper_widget)
|
|||||||
|
|
||||||
static void wrapper_widget_dispose(GObject *wrapper_widget)
|
static void wrapper_widget_dispose(GObject *wrapper_widget)
|
||||||
{
|
{
|
||||||
gtk_widget_unparent(gtk_widget_get_first_child(GTK_WIDGET(wrapper_widget)));
|
GtkWidget *widget = GTK_WIDGET(wrapper_widget);
|
||||||
|
GtkWidget *child = gtk_widget_get_first_child(widget);
|
||||||
|
while (child) {
|
||||||
|
GtkWidget *_child = gtk_widget_get_next_sibling(child);
|
||||||
|
gtk_widget_unparent(child);
|
||||||
|
child = _child;
|
||||||
|
}
|
||||||
WrapperWidget *wrapper = WRAPPER_WIDGET(wrapper_widget);
|
WrapperWidget *wrapper = WRAPPER_WIDGET(wrapper_widget);
|
||||||
if (wrapper->jvm) {
|
if (wrapper->jvm) {
|
||||||
JNIEnv *env;
|
JNIEnv *env;
|
||||||
(*wrapper->jvm)->GetEnv(wrapper->jvm, (void**)&env, JNI_VERSION_1_6);
|
(*wrapper->jvm)->GetEnv(wrapper->jvm, (void**)&env, JNI_VERSION_1_6);
|
||||||
if (wrapper->jobj)
|
if (wrapper->jobj)
|
||||||
_UNREF(wrapper->jobj);
|
_WEAK_UNREF(wrapper->jobj);
|
||||||
if (wrapper->canvas)
|
if (wrapper->canvas)
|
||||||
_UNREF(wrapper->canvas);
|
_UNREF(wrapper->canvas);
|
||||||
}
|
}
|
||||||
@@ -179,7 +185,7 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job
|
|||||||
JavaVM *jvm;
|
JavaVM *jvm;
|
||||||
(*env)->GetJavaVM(env, &jvm);
|
(*env)->GetJavaVM(env, &jvm);
|
||||||
wrapper->jvm = jvm;
|
wrapper->jvm = jvm;
|
||||||
wrapper->jobj = _REF(jobj);
|
wrapper->jobj = _WEAK_REF(jobj);
|
||||||
jmethodID on_draw_method = _METHOD(_CLASS(jobj), "onDraw", "(Landroid/graphics/Canvas;)V");
|
jmethodID on_draw_method = _METHOD(_CLASS(jobj), "onDraw", "(Landroid/graphics/Canvas;)V");
|
||||||
jmethodID draw_method = _METHOD(_CLASS(jobj), "draw", "(Landroid/graphics/Canvas;)V");
|
jmethodID draw_method = _METHOD(_CLASS(jobj), "draw", "(Landroid/graphics/Canvas;)V");
|
||||||
if (on_draw_method != handle_cache.view.onDraw || draw_method != handle_cache.view.draw) {
|
if (on_draw_method != handle_cache.view.onDraw || draw_method != handle_cache.view.draw) {
|
||||||
@@ -192,7 +198,7 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job
|
|||||||
|
|
||||||
jmethodID ontouchevent_method = _METHOD(_CLASS(jobj), "onTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
jmethodID ontouchevent_method = _METHOD(_CLASS(jobj), "onTouchEvent", "(Landroid/view/MotionEvent;)Z");
|
||||||
if (ontouchevent_method != handle_cache.view.onTouchEvent) {
|
if (ontouchevent_method != handle_cache.view.onTouchEvent) {
|
||||||
_setOnTouchListener(env, jobj, GTK_WIDGET(wrapper), NULL);
|
_setOnTouchListener(env, jobj, GTK_WIDGET(wrapper));
|
||||||
}
|
}
|
||||||
|
|
||||||
jmethodID computeScroll_method = _METHOD(_CLASS(jobj), "computeScroll", "()V");
|
jmethodID computeScroll_method = _METHOD(_CLASS(jobj), "computeScroll", "()V");
|
||||||
@@ -204,7 +210,7 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job
|
|||||||
if (performClick_method != handle_cache.view.performClick) {
|
if (performClick_method != handle_cache.view.performClick) {
|
||||||
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
|
GtkEventController *controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
|
||||||
|
|
||||||
g_signal_connect(controller, "released", G_CALLBACK(on_click), _REF(jobj));
|
g_signal_connect(controller, "released", G_CALLBACK(on_click), wrapper->jobj);
|
||||||
gtk_widget_add_controller(wrapper->child, controller);
|
gtk_widget_add_controller(wrapper->child, controller);
|
||||||
widget_set_needs_allocation(wrapper->child);
|
widget_set_needs_allocation(wrapper->child);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ struct _WrapperWidget
|
|||||||
int real_width;
|
int real_width;
|
||||||
int real_height;
|
int real_height;
|
||||||
gboolean needs_allocation;
|
gboolean needs_allocation;
|
||||||
|
gboolean intercepting_touch;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _WrapperWidgetClass
|
struct _WrapperWidgetClass
|
||||||
@@ -37,6 +38,6 @@ void wrapper_widget_set_layout_params(WrapperWidget *wrapper, int width, int hei
|
|||||||
void wrapper_widget_set_background(WrapperWidget *wrapper, GdkPaintable *paintable);
|
void wrapper_widget_set_background(WrapperWidget *wrapper, GdkPaintable *paintable);
|
||||||
void wrapper_widget_consume_touch_events(WrapperWidget *wrapper);
|
void wrapper_widget_consume_touch_events(WrapperWidget *wrapper);
|
||||||
|
|
||||||
void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject on_touch_listener);
|
void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ JNIEXPORT jlong JNICALL Java_android_widget_AbsListView_native_1constructor(JNIE
|
|||||||
RangeListModel *model = g_object_new(range_list_model_get_type(), NULL);
|
RangeListModel *model = g_object_new(range_list_model_get_type(), NULL);
|
||||||
GtkWidget *list_view = gtk_list_view_new(GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(model))), factory);
|
GtkWidget *list_view = gtk_list_view_new(GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(model))), factory);
|
||||||
model->list_view = list_view;
|
model->list_view = list_view;
|
||||||
model->jobject = _REF(this);
|
model->jobject = _WEAK_REF(this);
|
||||||
GtkWidget *scrolled_window = gtk_scrolled_window_new();
|
GtkWidget *scrolled_window = gtk_scrolled_window_new();
|
||||||
gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(scrolled_window), TRUE);
|
gtk_scrolled_window_set_propagate_natural_height(GTK_SCROLLED_WINDOW(scrolled_window), TRUE);
|
||||||
gtk_scrolled_window_set_propagate_natural_width(GTK_SCROLLED_WINDOW(scrolled_window), TRUE);
|
gtk_scrolled_window_set_propagate_natural_width(GTK_SCROLLED_WINDOW(scrolled_window), TRUE);
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ JNIEXPORT jlong JNICALL Java_android_widget_AbsSpinner_native_1constructor(JNIEn
|
|||||||
GtkWidget *dropdown = gtk_drop_down_new(G_LIST_MODEL(model), NULL);
|
GtkWidget *dropdown = gtk_drop_down_new(G_LIST_MODEL(model), NULL);
|
||||||
gtk_drop_down_set_factory(GTK_DROP_DOWN(dropdown), factory);
|
gtk_drop_down_set_factory(GTK_DROP_DOWN(dropdown), factory);
|
||||||
model->list_view = dropdown;
|
model->list_view = dropdown;
|
||||||
model->jobject = _REF(this);
|
model->jobject = _WEAK_REF(this);
|
||||||
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), dropdown);
|
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), dropdown);
|
||||||
gtk_widget_set_name(dropdown, "Spinner");
|
gtk_widget_set_name(dropdown, "Spinner");
|
||||||
return _INTPTR(dropdown);
|
return _INTPTR(dropdown);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ JNIEXPORT jlong JNICALL Java_android_widget_Button_native_1constructor(JNIEnv *e
|
|||||||
GtkWidget *label = gtk_button_new_with_label(text);
|
GtkWidget *label = gtk_button_new_with_label(text);
|
||||||
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), label);
|
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), label);
|
||||||
wrapper_widget_consume_touch_events(WRAPPER_WIDGET(wrapper)); // Android button consumes touch events
|
wrapper_widget_consume_touch_events(WRAPPER_WIDGET(wrapper)); // Android button consumes touch events
|
||||||
|
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
|
||||||
return _INTPTR(label);
|
return _INTPTR(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,38 +28,20 @@ JNIEXPORT void JNICALL Java_android_widget_Button_native_1setText(JNIEnv *env, j
|
|||||||
((*env)->ReleaseStringUTFChars(env, text, nativeText));
|
((*env)->ReleaseStringUTFChars(env, text, nativeText));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct touch_callback_data {
|
static void clicked_cb(GtkWidget *button, gpointer user_data) {
|
||||||
JavaVM *jvm;
|
JNIEnv *env = get_jni_env();
|
||||||
jobject this;
|
WrapperWidget *wrapper = WRAPPER_WIDGET(gtk_widget_get_parent(button));
|
||||||
jobject listener;
|
|
||||||
jmethodID listener_method;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void clicked_cb(GtkWidget *button, struct touch_callback_data *d) {
|
(*env)->CallBooleanMethod(env, wrapper->jobj, handle_cache.view.performClick);
|
||||||
JNIEnv *env;
|
|
||||||
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
|
|
||||||
|
|
||||||
(*env)->CallVoidMethod(env, d->listener, d->listener_method, d->this);
|
|
||||||
|
|
||||||
if((*env)->ExceptionCheck(env))
|
if((*env)->ExceptionCheck(env))
|
||||||
(*env)->ExceptionDescribe(env);
|
(*env)->ExceptionDescribe(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_android_widget_Button_native_1setOnClickListener(JNIEnv *env, jobject this, jlong widget_ptr, jobject on_click_listener)
|
JNIEXPORT void JNICALL Java_android_widget_Button_nativeSetOnClickListener(JNIEnv *env, jobject this, jlong widget_ptr)
|
||||||
{
|
{
|
||||||
GtkWidget *button = GTK_WIDGET(_PTR(widget_ptr));
|
GtkWidget *button = GTK_WIDGET(_PTR(widget_ptr));
|
||||||
g_signal_handlers_disconnect_matched(button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, clicked_cb, NULL);
|
g_signal_handlers_disconnect_matched(button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, clicked_cb, NULL);
|
||||||
if (!on_click_listener)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JavaVM *jvm;
|
g_signal_connect(button, "clicked", G_CALLBACK(clicked_cb), NULL);
|
||||||
(*env)->GetJavaVM(env, &jvm);
|
|
||||||
|
|
||||||
struct touch_callback_data *callback_data = malloc(sizeof(struct touch_callback_data));
|
|
||||||
callback_data->jvm = jvm;
|
|
||||||
callback_data->this = _REF(this);
|
|
||||||
callback_data->listener = _REF(on_click_listener);
|
|
||||||
callback_data->listener_method = _METHOD(_CLASS(on_click_listener), "onClick", "(Landroid/view/View;)V");
|
|
||||||
|
|
||||||
g_signal_connect(button, "clicked", G_CALLBACK(clicked_cb), callback_data);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ JNIEXPORT void JNICALL Java_android_widget_EditText_native_1setOnEditorActionLis
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
struct changed_callback_data *callback_data = malloc(sizeof(struct changed_callback_data));
|
struct changed_callback_data *callback_data = malloc(sizeof(struct changed_callback_data));
|
||||||
callback_data->this = _REF(this);
|
callback_data->this = _WEAK_REF(this);
|
||||||
callback_data->listener = _REF(listener);
|
callback_data->listener = _REF(listener);
|
||||||
callback_data->listener_method = _METHOD(_CLASS(listener), "onEditorAction", "(Landroid/widget/TextView;ILandroid/view/KeyEvent;)Z");
|
callback_data->listener_method = _METHOD(_CLASS(listener), "onEditorAction", "(Landroid/widget/TextView;ILandroid/view/KeyEvent;)Z");
|
||||||
|
|
||||||
|
|||||||
@@ -26,41 +26,23 @@ JNIEXPORT void JNICALL Java_android_widget_ImageButton_native_1setPixbuf(JNIEnv
|
|||||||
Java_android_widget_ImageButton_native_1setDrawable(env, this, widget_ptr, _INTPTR(paintable));
|
Java_android_widget_ImageButton_native_1setDrawable(env, this, widget_ptr, _INTPTR(paintable));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct touch_callback_data {
|
static void clicked_cb(GtkWidget *button, gpointer user_data) {
|
||||||
JavaVM *jvm;
|
|
||||||
jobject this;
|
|
||||||
jobject listener;
|
|
||||||
jmethodID listener_method;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void clicked_cb(GtkWidget *button, struct touch_callback_data *d) {
|
|
||||||
printf("clicked_cb\n");
|
printf("clicked_cb\n");
|
||||||
JNIEnv *env;
|
JNIEnv *env = get_jni_env();
|
||||||
(*d->jvm)->GetEnv(d->jvm, (void**)&env, JNI_VERSION_1_6);
|
WrapperWidget *wrapper = WRAPPER_WIDGET(gtk_widget_get_parent(button));
|
||||||
|
|
||||||
(*env)->CallVoidMethod(env, d->listener, d->listener_method, d->this);
|
(*env)->CallBooleanMethod(env, wrapper->jobj, handle_cache.view.performClick);
|
||||||
|
|
||||||
if((*env)->ExceptionCheck(env))
|
if((*env)->ExceptionCheck(env))
|
||||||
(*env)->ExceptionDescribe(env);
|
(*env)->ExceptionDescribe(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_android_widget_ImageButton_native_1setOnClickListener(JNIEnv *env, jobject this, jlong widget_ptr, jobject on_click_listener)
|
JNIEXPORT void JNICALL Java_android_widget_ImageButton_nativeSetOnClickListener(JNIEnv *env, jobject this, jlong widget_ptr)
|
||||||
{
|
{
|
||||||
GtkWidget *button = GTK_WIDGET(_PTR(widget_ptr));
|
GtkWidget *button = GTK_WIDGET(_PTR(widget_ptr));
|
||||||
g_signal_handlers_disconnect_matched(button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, clicked_cb, NULL);
|
g_signal_handlers_disconnect_matched(button, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, clicked_cb, NULL);
|
||||||
if (!on_click_listener)
|
|
||||||
return;
|
|
||||||
|
|
||||||
JavaVM *jvm;
|
g_signal_connect(button, "clicked", G_CALLBACK(clicked_cb), NULL);
|
||||||
(*env)->GetJavaVM(env, &jvm);
|
|
||||||
|
|
||||||
struct touch_callback_data *callback_data = malloc(sizeof(struct touch_callback_data));
|
|
||||||
callback_data->jvm = jvm;
|
|
||||||
callback_data->this = _REF(this);
|
|
||||||
callback_data->listener = _REF(on_click_listener);
|
|
||||||
callback_data->listener_method = _METHOD(_CLASS(on_click_listener), "onClick", "(Landroid/view/View;)V");
|
|
||||||
|
|
||||||
g_signal_connect(button, "clicked", G_CALLBACK(clicked_cb), callback_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_android_widget_ImageButton_native_1setDrawable(JNIEnv *env, jobject this, jlong widget_ptr, jlong paintable_ptr)
|
JNIEXPORT void JNICALL Java_android_widget_ImageButton_native_1setDrawable(JNIEnv *env, jobject this, jlong widget_ptr, jlong paintable_ptr)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ JNIEXPORT jlong JNICALL Java_android_widget_TextView_native_1constructor(JNIEnv
|
|||||||
gtk_widget_set_hexpand(label, TRUE);
|
gtk_widget_set_hexpand(label, TRUE);
|
||||||
gtk_box_append(GTK_BOX(box), label);
|
gtk_box_append(GTK_BOX(box), label);
|
||||||
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), box);
|
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), box);
|
||||||
|
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
|
||||||
|
|
||||||
PangoAttrList* pango_attrs = pango_attr_list_new();
|
PangoAttrList* pango_attrs = pango_attr_list_new();
|
||||||
pango_attr_list_insert(pango_attrs, pango_attr_font_features_new("tnum"));
|
pango_attr_list_insert(pango_attrs, pango_attr_font_features_new("tnum"));
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user