diff --git a/src/api-impl-jni/util.c b/src/api-impl-jni/util.c index c674e716..c8d9cfa7 100644 --- a/src/api-impl-jni/util.c +++ b/src/api-impl-jni/util.c @@ -118,6 +118,7 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.view.performClick = _METHOD(handle_cache.view.class, "performClick", "()Z"); handle_cache.view.onTouchEvent = _METHOD(handle_cache.view.class, "onTouchEvent", "(Landroid/view/MotionEvent;)Z"); 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.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"); diff --git a/src/api-impl-jni/util.h b/src/api-impl-jni/util.h index 8d7b83ea..ab867cff 100644 --- a/src/api-impl-jni/util.h +++ b/src/api-impl-jni/util.h @@ -72,6 +72,7 @@ struct handle_cache { jmethodID performClick; jmethodID onTouchEvent; jmethodID layoutInternal; + jmethodID measure; } view; struct { jclass class; diff --git a/src/api-impl-jni/views/AndroidLayout.c b/src/api-impl-jni/views/AndroidLayout.c index 5d06b172..ecaaccd3 100644 --- a/src/api-impl-jni/views/AndroidLayout.c +++ b/src/api-impl-jni/views/AndroidLayout.c @@ -3,11 +3,36 @@ #include "../util.h" #include "AndroidLayout.h" +static int make_measure_spec(int layout_size, int for_size) +{ + if (layout_size >= 0) + return layout_size | MEASURE_SPEC_EXACTLY; + else if (for_size >= 0 && layout_size == MATCH_PARENT) + return for_size | MEASURE_SPEC_EXACTLY; + else if (for_size >= 0 && layout_size == WRAP_CONTENT) + return for_size | MEASURE_SPEC_AT_MOST; + else if (layout_size == WRAP_CONTENT) + return MEASURE_SPEC_UNSPECIFIED; + else + return -1; +} + static void android_layout_measure(GtkLayoutManager *layout_manager, GtkWidget *widget, GtkOrientation orientation, int for_size, int *minimum, int *natural, int *minimum_baseline, int *natural_baseline) { AndroidLayout *layout = ATL_ANDROID_LAYOUT(layout_manager); JNIEnv *env = get_jni_env(); + if (layout->width || layout->height) { + int widthMeasureSpec = make_measure_spec(layout->width, orientation == GTK_ORIENTATION_VERTICAL ? for_size : -1); + int heightMeasureSpec = make_measure_spec(layout->height, orientation == GTK_ORIENTATION_HORIZONTAL ? for_size : -1); + + if (widthMeasureSpec != -1 && heightMeasureSpec != -1) { + (*env)->CallVoidMethod(env, layout->view, handle_cache.view.measure, widthMeasureSpec, heightMeasureSpec); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + } + } + if (orientation == GTK_ORIENTATION_HORIZONTAL) { *minimum = (*env)->CallIntMethod(env, layout->view, handle_cache.view.getSuggestedMinimumWidth); *natural = (*env)->CallIntMethod(env, layout->view, handle_cache.view.getMeasuredWidth); @@ -49,3 +74,9 @@ GtkLayoutManager *android_layout_new(jobject view) layout->view = view; return &layout->parent_instance; } + +void android_layout_set_params(AndroidLayout *layout, int width, int height) +{ + layout->width = width; + layout->height = height; +} diff --git a/src/api-impl-jni/views/AndroidLayout.h b/src/api-impl-jni/views/AndroidLayout.h index 8be2dd96..9f90cb74 100644 --- a/src/api-impl-jni/views/AndroidLayout.h +++ b/src/api-impl-jni/views/AndroidLayout.h @@ -4,13 +4,24 @@ #include #include +#define MEASURE_SPEC_UNSPECIFIED (0 << 30) +#define MEASURE_SPEC_EXACTLY (1 << 30) +#define MEASURE_SPEC_AT_MOST (2 << 30) +#define MEASURE_SPEC_MASK (0x3 << 30) + +#define MATCH_PARENT (-1) +#define WRAP_CONTENT (-2) + G_DECLARE_FINAL_TYPE(AndroidLayout, android_layout, ATL, ANDROID_LAYOUT, GtkLayoutManager); struct _AndroidLayout { GtkLayoutManager parent_instance; jobject view; + int width; + int height; }; GtkLayoutManager *android_layout_new(jobject view); +void android_layout_set_params(AndroidLayout *layout, int width, int height); #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 7f675c0d..03903a2a 100644 --- a/src/api-impl-jni/views/android_view_View.c +++ b/src/api-impl-jni/views/android_view_View.c @@ -4,6 +4,7 @@ #include "../util.h" #include "../widgets/WrapperWidget.h" +#include "../views/AndroidLayout.h" #include "../generated_headers/android_view_View.h" @@ -236,6 +237,10 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1setLayoutParams(JNIEnv *en g_object_set(G_OBJECT(widget), "width-request", width, NULL); if(height > 0) g_object_set(G_OBJECT(widget), "height-request", height, NULL); + + GtkLayoutManager *layout_manager = gtk_widget_get_layout_manager(WRAPPER_WIDGET(widget)->child); + if (ATL_IS_ANDROID_LAYOUT(layout_manager)) + android_layout_set_params(ATL_ANDROID_LAYOUT(layout_manager), width, height); } JNIEXPORT void JNICALL Java_android_view_View_setVisibility(JNIEnv *env, jobject this, jint visibility) { diff --git a/src/api-impl/android/widget/FrameLayout.java b/src/api-impl/android/widget/FrameLayout.java index 958b08f9..e2789e5a 100644 --- a/src/api-impl/android/widget/FrameLayout.java +++ b/src/api-impl/android/widget/FrameLayout.java @@ -26,6 +26,11 @@ public class FrameLayout extends ViewGroup { return new LayoutParams(getContext(), attrs); } + @Override + protected LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); + } + public static class LayoutParams extends ViewGroup.MarginLayoutParams { public LayoutParams (Context c, AttributeSet attrs) { super(c, attrs);