diff --git a/src/api-impl-jni/views/AndroidLayout.c b/src/api-impl-jni/views/AndroidLayout.c index c54e7f36..2100230a 100644 --- a/src/api-impl-jni/views/AndroidLayout.c +++ b/src/api-impl-jni/views/AndroidLayout.c @@ -64,6 +64,10 @@ static void android_layout_allocate(GtkLayoutManager *layout_manager, GtkWidget { AndroidLayout *layout = ATL_ANDROID_LAYOUT(layout_manager); JNIEnv *env = get_jni_env(); + if (!width && !height) { + width = layout->real_width; + height = layout->real_height; + } (*env)->CallVoidMethod(env, layout->view, handle_cache.view.layoutInternal, width, height); if((*env)->ExceptionCheck(env)) @@ -108,3 +112,12 @@ void android_layout_set_params(AndroidLayout *layout, int width, int height) layout->width = width; layout->height = height; } + +void widget_set_needs_allocation(GtkWidget *widget) { + if (ATL_IS_ANDROID_LAYOUT(gtk_widget_get_layout_manager(widget))) { + AndroidLayout *layout = ATL_ANDROID_LAYOUT(gtk_widget_get_layout_manager(widget)); + if (!layout->needs_allocation && (layout->real_width || layout->real_height)) + gtk_widget_size_allocate(widget, &(GtkAllocation){.x = 0, .y = 0, .width = layout->real_width, .height = layout->real_height}, 0); + layout->needs_allocation = true; + } +} diff --git a/src/api-impl-jni/views/AndroidLayout.h b/src/api-impl-jni/views/AndroidLayout.h index 9f90cb74..7fc1461e 100644 --- a/src/api-impl-jni/views/AndroidLayout.h +++ b/src/api-impl-jni/views/AndroidLayout.h @@ -19,9 +19,14 @@ struct _AndroidLayout { jobject view; int width; int height; + int real_width; + int real_height; + gboolean needs_allocation; }; GtkLayoutManager *android_layout_new(jobject view); void android_layout_set_params(AndroidLayout *layout, int width, int height); +void widget_set_needs_allocation(GtkWidget *widget); + #endif // ANDROID_LAYOUT_H \ No newline at end of file diff --git a/src/api-impl-jni/views/android_view_View.c b/src/api-impl-jni/views/android_view_View.c index ca4b48b4..412ea602 100644 --- a/src/api-impl-jni/views/android_view_View.c +++ b/src/api-impl-jni/views/android_view_View.c @@ -181,6 +181,10 @@ void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget, jobject o gtk_widget_add_controller(widget, controller); g_object_set_data(G_OBJECT(widget), "on_intercept_touch_listener", controller); } + WrapperWidget *wrapper = WRAPPER_WIDGET(widget); + if (!wrapper->needs_allocation && (wrapper->layout_width || wrapper->layout_height)) + gtk_widget_size_allocate(GTK_WIDGET(wrapper), &(GtkAllocation){.x = 0, .y = 0, .width = wrapper->layout_width, .height = wrapper->layout_height}, 0); + wrapper->needs_allocation = true; } JNIEXPORT void JNICALL Java_android_view_View_setOnTouchListener(JNIEnv *env, jobject this, jobject on_touch_listener) @@ -214,6 +218,7 @@ JNIEXPORT void JNICALL Java_android_view_View_setOnClickListener(JNIEnv *env, jo g_signal_connect(controller, "released", G_CALLBACK(on_click), callback_data); // the release completes the click, I guess? gtk_widget_add_controller(widget, controller); g_object_set_data(G_OBJECT(widget), "on_click_listener", controller); + widget_set_needs_allocation(widget); } JNIEXPORT jint JNICALL Java_android_view_View_getWidth(JNIEnv *env, jobject this) @@ -225,6 +230,10 @@ JNIEXPORT jint JNICALL Java_android_view_View_getWidth(JNIEnv *env, jobject this gtk_widget_get_allocation(widget, &alloc); printf("widget size is currently %dx%d\n", alloc.width, alloc.height); */ + if (ATL_IS_ANDROID_LAYOUT(gtk_widget_get_layout_manager(widget))) { + AndroidLayout *layout = ATL_ANDROID_LAYOUT(gtk_widget_get_layout_manager(widget)); + return layout->real_width; + } return gtk_widget_get_width(widget); } @@ -232,6 +241,10 @@ JNIEXPORT jint JNICALL Java_android_view_View_getHeight(JNIEnv *env, jobject thi { GtkWidget *widget = GTK_WIDGET(_PTR(_GET_LONG_FIELD(this, "widget"))); + if (ATL_IS_ANDROID_LAYOUT(gtk_widget_get_layout_manager(widget))) { + AndroidLayout *layout = ATL_ANDROID_LAYOUT(gtk_widget_get_layout_manager(widget)); + return layout->real_height; + } return gtk_widget_get_height(widget); } @@ -358,7 +371,7 @@ JNIEXPORT jlong JNICALL Java_android_view_View_native_1constructor(JNIEnv *env, (*env)->ReleaseStringUTFChars(env, nameObj, name); /* this should better match default android behavior */ - gtk_widget_set_overflow(wrapper, GTK_OVERFLOW_HIDDEN); + gtk_widget_set_overflow(wrapper, GTK_OVERFLOW_VISIBLE); jmethodID measure_method = _METHOD(class, "onMeasure", "(II)V"); jmethodID layout_method = _METHOD(class, "onLayout", "(ZIIII)V"); @@ -437,9 +450,20 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1layout(JNIEnv *env, jobjec GtkAllocation allocation = { .x=l, .y=t, - .width=r-l, - .height=b-t, }; + int width = r-l; + int height = b-t; + WrapperWidget *wrapper = WRAPPER_WIDGET(widget); + if (wrapper->real_width != width || wrapper->real_height != height) { + wrapper->real_width = width; + wrapper->real_height = height; + if (!wrapper->needs_allocation) + gtk_widget_queue_allocate(widget); + } + if (wrapper->needs_allocation) { + allocation.width = width; + allocation.height = height; + } gtk_widget_size_allocate(widget, &allocation, -1); } @@ -474,6 +498,7 @@ JNIEXPORT void JNICALL Java_android_view_View_setBackgroundColor(JNIEnv *env, jo gtk_style_context_add_provider(style_context, GTK_STYLE_PROVIDER(css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); g_object_set_data(G_OBJECT(widget), "background_color_style_provider", css_provider); + widget_set_needs_allocation(widget); } #pragma GCC diagnostic pop diff --git a/src/api-impl-jni/widgets/WrapperWidget.c b/src/api-impl-jni/widgets/WrapperWidget.c index ff15888c..5526d93b 100644 --- a/src/api-impl-jni/widgets/WrapperWidget.c +++ b/src/api-impl-jni/widgets/WrapperWidget.c @@ -8,6 +8,7 @@ #include "../generated_headers/android_view_View.h" #include "WrapperWidget.h" +#include "src/api-impl-jni/views/AndroidLayout.h" G_DEFINE_TYPE(WrapperWidget, wrapper_widget, GTK_TYPE_WIDGET) @@ -68,6 +69,10 @@ void wrapper_widget_measure(GtkWidget *widget, GtkOrientation orientation, int f void wrapper_widget_allocate(GtkWidget *widget, int width, int height, int baseline) { WrapperWidget *wrapper = WRAPPER_WIDGET(widget); + if (!width && !height) { + width = wrapper->real_width; + height = wrapper->real_height; + } GtkAllocation allocation = { .x = 0, .y = 0, @@ -89,7 +94,21 @@ void wrapper_widget_allocate(GtkWidget *widget, int width, int height, int basel allocation.y = -(*env)->CallIntMethod(env, wrapper->jobj, handle_cache.view.getScrollY); } - gtk_widget_size_allocate(wrapper->child, &allocation, baseline); + if (ATL_IS_ANDROID_LAYOUT(gtk_widget_get_layout_manager(wrapper->child))) { + AndroidLayout *layout = ATL_ANDROID_LAYOUT(gtk_widget_get_layout_manager(wrapper->child)); + if (layout->real_width != width || layout->real_height != height) { + layout->real_width = width; + layout->real_height = height; + if (!layout->needs_allocation) + gtk_widget_queue_allocate(wrapper->child); + } + if (layout->needs_allocation) + gtk_widget_size_allocate(wrapper->child, &allocation, baseline); + else + gtk_widget_size_allocate(wrapper->child, &(GtkAllocation){.x = allocation.x, .y = allocation.y}, baseline); + } else { + gtk_widget_size_allocate(wrapper->child, &allocation, baseline); + } if (wrapper->sk_area) gtk_widget_size_allocate(wrapper->sk_area, &allocation, baseline); if (wrapper->background) @@ -184,6 +203,7 @@ void wrapper_widget_set_jobject(WrapperWidget *wrapper, JNIEnv *env, jobject job g_signal_connect(controller, "released", G_CALLBACK(on_click), _REF(jobj)); gtk_widget_add_controller(wrapper->child, controller); + widget_set_needs_allocation(wrapper->child); } } diff --git a/src/api-impl-jni/widgets/WrapperWidget.h b/src/api-impl-jni/widgets/WrapperWidget.h index 01fceb90..ce22153f 100644 --- a/src/api-impl-jni/widgets/WrapperWidget.h +++ b/src/api-impl-jni/widgets/WrapperWidget.h @@ -20,6 +20,9 @@ struct _WrapperWidget jmethodID computeScroll_method; int layout_width; int layout_height; + int real_width; + int real_height; + gboolean needs_allocation; }; struct _WrapperWidgetClass