android_layout_measure(): refactor to respect LayoutParams

This is needed when a Java widget gets measured from GTK
This commit is contained in:
Julian Winkler
2023-10-31 22:56:22 +01:00
committed by Julian Winkler
parent 8b6de0e83a
commit 3c03223085
6 changed files with 54 additions and 0 deletions

View File

@@ -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");

View File

@@ -72,6 +72,7 @@ struct handle_cache {
jmethodID performClick;
jmethodID onTouchEvent;
jmethodID layoutInternal;
jmethodID measure;
} view;
struct {
jclass class;

View File

@@ -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;
}

View File

@@ -4,13 +4,24 @@
#include <jni.h>
#include <gtk/gtk.h>
#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

View File

@@ -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) {

View File

@@ -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);