api-impl-jni: make invalidate() work inside the draw callback

this lets us remove the tick callback, and only call onDraw
when it's actually necessary
This commit is contained in:
Mis012
2023-10-31 23:14:47 +01:00
parent bcd588446d
commit 065fd96308
3 changed files with 26 additions and 9 deletions

View File

@@ -267,7 +267,7 @@ JNIEXPORT jlong JNICALL Java_android_view_View_native_1constructor(JNIEnv *env,
JNIEXPORT void JNICALL Java_android_view_View_nativeInvalidate(JNIEnv *env, jclass class, jlong widget_ptr) { JNIEXPORT void JNICALL Java_android_view_View_nativeInvalidate(JNIEnv *env, jclass class, jlong widget_ptr) {
GtkWidget *widget = GTK_WIDGET(_PTR(widget_ptr)); GtkWidget *widget = GTK_WIDGET(_PTR(widget_ptr));
gtk_widget_queue_draw(gtk_widget_get_parent(widget)); wrapper_widget_queue_draw(WRAPPER_WIDGET(gtk_widget_get_parent(widget)));
} }
JNIEXPORT void JNICALL Java_android_view_View_native_1destructor(JNIEnv *env, jobject this, jlong widget_ptr) JNIEXPORT void JNICALL Java_android_view_View_native_1destructor(JNIEnv *env, jobject this, jlong widget_ptr)

View File

@@ -74,6 +74,7 @@ GtkWidget * wrapper_widget_new(void)
void wrapper_widget_set_child(WrapperWidget *parent, GtkWidget *child) // TODO: make sure there can only be one child 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); gtk_widget_insert_before(child, GTK_WIDGET(parent), NULL);
parent->child = child;
} }
#define MEASURE_SPEC_EXACTLY (1 << 30) #define MEASURE_SPEC_EXACTLY (1 << 30)
@@ -95,12 +96,23 @@ static void on_mapped(GtkWidget* self, gpointer data)
} }
} }
// FIXME: this is used in one other place as well, should probably go in util.c or gtk_util.c? static guint sk_area_queue_queue_redraw(GtkWidget *sk_area)
gboolean tick_callback(GtkWidget* widget, GdkFrameClock* frame_clock, gpointer user_data)
{ {
gtk_widget_queue_draw(widget); gtk_widget_queue_draw(sk_area);
gtk_widget_queue_draw(gtk_widget_get_parent(widget)); return G_SOURCE_REMOVE;
return G_SOURCE_CONTINUE; }
void wrapper_widget_queue_draw(WrapperWidget *wrapper)
{
if(wrapper->sk_area) {
/* schedule the call to gtk_widget_queue_draw for a future event loop pass in case we're currently inside the sk_area's snapshot */
/* GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations. */
g_idle_add_full(G_PRIORITY_HIGH_IDLE + 20, G_SOURCE_FUNC(sk_area_queue_queue_redraw), wrapper->sk_area, NULL);
}
if(wrapper->child)
gtk_widget_queue_draw(wrapper->child);
gtk_widget_queue_draw(GTK_WIDGET(wrapper));
} }
void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject jobj) void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject jobj)
@@ -114,9 +126,11 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job
wrapper->draw_method = draw_method; wrapper->draw_method = draw_method;
GtkWidget *sk_area = sk_area_new(); GtkWidget *sk_area = sk_area_new();
gtk_widget_set_sensitive(sk_area, false);
sk_area_set_draw_func(SK_AREA_WIDGET(sk_area), skia_draw_func, wrapper); 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_insert_before(sk_area, GTK_WIDGET(wrapper), NULL);
gtk_widget_add_tick_callback(sk_area, tick_callback, NULL, NULL); wrapper->sk_area = sk_area;
// gtk_widget_add_tick_callback(sk_area, tick_callback, NULL, NULL);
} }
jmethodID measure_method = _METHOD(_CLASS(jobj), "onMeasure", "(II)V"); jmethodID measure_method = _METHOD(_CLASS(jobj), "onMeasure", "(II)V");
@@ -128,7 +142,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) {
/* use gtk_widget_get_first_child since the jobject may not have the "widget" variable set yet */ /* use wrapper->child since the jobject may not have the "widget" variable set yet */
_setOnTouchListener(env, jobj, gtk_widget_get_first_child(GTK_WIDGET(wrapper)), NULL); _setOnTouchListener(env, jobj, wrapper->child, NULL);
} }
} }

View File

@@ -9,6 +9,8 @@ G_DECLARE_FINAL_TYPE (WrapperWidget, wrapper_widget, WRAPPER, WIDGET, GtkWidget)
struct _WrapperWidget struct _WrapperWidget
{ {
GtkWidget parent_instance; GtkWidget parent_instance;
GtkWidget *child;
GtkWidget *sk_area;
JavaVM *jvm; JavaVM *jvm;
jobject jobj; jobject jobj;
jobject canvas; jobject canvas;
@@ -24,6 +26,7 @@ struct _WrapperWidgetClass
GtkWidget * wrapper_widget_new(void); GtkWidget * wrapper_widget_new(void);
void wrapper_widget_set_child(WrapperWidget *parent, GtkWidget *child); void wrapper_widget_set_child(WrapperWidget *parent, GtkWidget *child);
void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject jobj); void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject jobj);
void wrapper_widget_queue_draw(WrapperWidget *wrapper);
void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject on_touch_listener); void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject on_touch_listener);