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
WIP
This commit is contained in:
1
.gdb_history
Normal file
1
.gdb_history
Normal file
@@ -0,0 +1 @@
|
||||
r
|
||||
@@ -1,4 +1,4 @@
|
||||
project('android_translation_layer', ['c', 'java'], default_options: ['b_lundef=false'])
|
||||
project('android_translation_layer', ['c', 'java'], default_options: ['c_std=gnu23', 'b_lundef=false'])
|
||||
|
||||
gnome = import('gnome')
|
||||
fs = import('fs')
|
||||
@@ -145,6 +145,7 @@ libtranslationlayer_so = shared_library('translation_layer_main', [
|
||||
'src/api-impl-jni/views/AndroidLayout.c',
|
||||
'src/api-impl-jni/views/android_view_View.c',
|
||||
'src/api-impl-jni/views/android_view_ViewGroup.c',
|
||||
'src/api-impl-jni/views/android_view_ViewTreeObserver.c',
|
||||
'src/api-impl-jni/views/android_view_WindowManagerImpl.c',
|
||||
'src/api-impl-jni/widgets/WrapperWidget.c',
|
||||
'src/api-impl-jni/widgets/android_view_SurfaceView.c',
|
||||
@@ -197,6 +198,7 @@ executable('android-translation-layer', [
|
||||
'src/main-executable/actions.c',
|
||||
'src/main-executable/back_button.c',
|
||||
'src/main-executable/bionic_compat.c',
|
||||
'src/main-executable/inspector_page.c',
|
||||
'src/main-executable/libc_bio_path_overrides.c',
|
||||
resources
|
||||
],
|
||||
|
||||
@@ -53,3 +53,8 @@ JNIEXPORT void JNICALL Java_android_view_Window_set_1layout(JNIEnv *env, jobject
|
||||
if (width > 0 && height > 0)
|
||||
gtk_window_set_default_size(gtk_window, width, height);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_view_Window_set_1jobject(JNIEnv *env, jclass this, jlong window, jobject window_jobj)
|
||||
{
|
||||
g_object_set_data(G_OBJECT(window), "jobject", _WEAK_REF(window_jobj));
|
||||
}
|
||||
|
||||
@@ -359,6 +359,14 @@ JNIEXPORT void JNICALL Java_android_view_View_nativeRequestFocus
|
||||
JNIEXPORT void JNICALL Java_android_view_View_nativeSetFullscreen
|
||||
(JNIEnv *, jobject, jlong, jboolean);
|
||||
|
||||
/*
|
||||
* Class: android_view_View
|
||||
* Method: native_get_window
|
||||
* Signature: (J)Landroid/view/Window;
|
||||
*/
|
||||
JNIEXPORT jobject JNICALL Java_android_view_View_native_1get_1window
|
||||
(JNIEnv *, jobject, jlong);
|
||||
|
||||
/*
|
||||
* Class: android_view_View
|
||||
* Method: nativeInvalidate
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/* DO NOT EDIT THIS FILE - it is machine generated */
|
||||
#include <jni.h>
|
||||
/* Header for class android_view_ViewTreeObserver */
|
||||
|
||||
#ifndef _Included_android_view_ViewTreeObserver
|
||||
#define _Included_android_view_ViewTreeObserver
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*
|
||||
* Class: android_view_ViewTreeObserver
|
||||
* Method: native_set_have_global_layout_listeners
|
||||
* Signature: (Z)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_view_ViewTreeObserver_native_1set_1have_1global_1layout_1listeners
|
||||
(JNIEnv *, jobject, jboolean);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -43,6 +43,14 @@ JNIEXPORT void JNICALL Java_android_view_Window_take_1input_1queue
|
||||
JNIEXPORT void JNICALL Java_android_view_Window_set_1layout
|
||||
(JNIEnv *, jobject, jlong, jint, jint);
|
||||
|
||||
/*
|
||||
* Class: android_view_Window
|
||||
* Method: set_jobject
|
||||
* Signature: (JLandroid/view/Window;)V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_android_view_Window_set_1jobject
|
||||
(JNIEnv *, jclass, jlong, jobject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -135,4 +135,7 @@ void set_up_handle_cache(JNIEnv *env)
|
||||
|
||||
handle_cache.uri.class = _REF((*env)->FindClass(env, "android/net/Uri"));
|
||||
handle_cache.uri.parse = _STATIC_METHOD(handle_cache.uri.class, "parse", "(Ljava/lang/String;)Landroid/net/Uri;");
|
||||
|
||||
handle_cache.view_tree_observer.class = _REF((*env)->FindClass(env, "android/view/ViewTreeObserver"));
|
||||
handle_cache.view_tree_observer.dispatchOnGlobalLayout = _METHOD(handle_cache.view_tree_observer.class, "dispatchOnGlobalLayout", "()V");
|
||||
}
|
||||
|
||||
@@ -145,6 +145,10 @@ struct handle_cache {
|
||||
jclass class;
|
||||
jmethodID parse;
|
||||
} uri;
|
||||
struct {
|
||||
jclass class;
|
||||
jmethodID dispatchOnGlobalLayout;
|
||||
} view_tree_observer;
|
||||
};
|
||||
|
||||
extern struct handle_cache handle_cache;
|
||||
|
||||
@@ -19,6 +19,7 @@ static void location_updated (
|
||||
JNIEnv *env;
|
||||
(*jvm)->GetEnv(jvm, (void**)&env, JNI_VERSION_1_6);
|
||||
jclass class = (*env)->FindClass(env, "android/location/LocationManager");
|
||||
printf("XXLOCXX: latitude, longitude, heading: %lf %lf %lf\n", latitude, longitude, heading);
|
||||
jlong timestamp = timestamp_s * 1000 + timestamp_ms;
|
||||
(*env)->CallStaticVoidMethod(env, class, _STATIC_METHOD(class, "locationUpdated", "(DDDDDDJ)V"), latitude, longitude, altitude, accuracy, speed, heading, timestamp);
|
||||
}
|
||||
@@ -38,5 +39,6 @@ JNIEXPORT void JNICALL Java_android_location_LocationManager_nativeGetLocation(J
|
||||
g_signal_connect(portal, "location-updated", G_CALLBACK(location_updated), jvm);
|
||||
}
|
||||
|
||||
printf("XXLOCXX: Java_android_location_LocationManager_nativeGetLocation\n");
|
||||
xdp_portal_location_monitor_start (portal, NULL, 0, 0, XDP_LOCATION_ACCURACY_EXACT, XDP_LOCATION_MONITOR_FLAG_NONE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ static int make_measure_spec(int layout_size, int for_size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern int snapshot_in_progress;
|
||||
|
||||
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)
|
||||
{
|
||||
int widthMeasureSpec = 0;
|
||||
@@ -25,12 +27,16 @@ static void android_layout_measure(GtkLayoutManager *layout_manager, GtkWidget *
|
||||
AndroidLayout *layout = ATL_ANDROID_LAYOUT(layout_manager);
|
||||
JNIEnv *env = get_jni_env();
|
||||
|
||||
/* if we're inside a shanpshot, this must be getting called purely to make Gtk call gtk_widget_clear_resize_queued */
|
||||
if(snapshot_in_progress)
|
||||
return;
|
||||
|
||||
// If the parent widget is also an AndroidLayout, the measurement will already have happened in Java
|
||||
if ((layout->width || layout->height) && !ATL_IS_ANDROID_LAYOUT(gtk_widget_get_layout_manager(gtk_widget_get_parent(gtk_widget_get_parent(widget))))) {
|
||||
widthMeasureSpec = make_measure_spec(layout->width, orientation == GTK_ORIENTATION_VERTICAL ? for_size : -1);
|
||||
heightMeasureSpec = make_measure_spec(layout->height, orientation == GTK_ORIENTATION_HORIZONTAL ? for_size : -1);
|
||||
|
||||
// if layout params say match_parent, but GTK doesnt specify the dimension, fallback to old specification if available
|
||||
// if layout params say match_parent, but GTK doesn't specify the dimension, fall back to old specification if available
|
||||
if (widthMeasureSpec == -1)
|
||||
widthMeasureSpec = _GET_INT_FIELD(layout->view, "oldWidthMeasureSpec");
|
||||
if (heightMeasureSpec == -1)
|
||||
|
||||
@@ -307,8 +307,14 @@ void _setOnTouchListener(JNIEnv *env, jobject this, GtkWidget *widget)
|
||||
gtk_widget_add_controller(widget, controller);
|
||||
g_object_set_data(G_OBJECT(widget), "on_intercept_touch_listener", controller);
|
||||
}
|
||||
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);
|
||||
|
||||
|
||||
if(!wrapper->needs_allocation && wrapper->layout_width == -1 && wrapper->layout_height == -1)
|
||||
printf("[%p] in _setOnTouchListener: [%d, %d]\n", wrapper->child, wrapper->real_width, wrapper->real_height);
|
||||
|
||||
if (!wrapper->needs_allocation && (wrapper->real_width || wrapper->real_height))
|
||||
gtk_widget_size_allocate(GTK_WIDGET(wrapper), &(GtkAllocation){.x = 0, .y = 0, .width = wrapper->real_width, .height = wrapper->real_height}, 0);
|
||||
|
||||
wrapper->needs_allocation = true;
|
||||
gtk_widget_set_overflow(GTK_WIDGET(wrapper), GTK_OVERFLOW_HIDDEN);
|
||||
}
|
||||
@@ -409,8 +415,6 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1setLayoutParams(JNIEnv *en
|
||||
}
|
||||
|
||||
if (weight > 0.f) {
|
||||
printf(":::-: setting weight: %f\n", weight);
|
||||
|
||||
hexpand = TRUE;
|
||||
vexpand = TRUE;
|
||||
}
|
||||
@@ -582,9 +586,10 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1measure(JNIEnv *env, jobje
|
||||
width = width_spec_size;
|
||||
}
|
||||
|
||||
printf("[%p] in Java_android_view_View_native_1measure, calling setMeasuredDimension with [%d,%d]\n", _PTR(widget_ptr), width, height);
|
||||
(*env)->CallVoidMethod(env, this, handle_cache.view.setMeasuredDimension, width, height);
|
||||
}
|
||||
|
||||
void _gdb_force_java_stack_trace(void);
|
||||
JNIEXPORT void JNICALL Java_android_view_View_native_1layout(JNIEnv *env, jobject this, jlong widget_ptr, jint l, jint t, jint r, jint b) {
|
||||
GtkWidget *widget = gtk_widget_get_parent(GTK_WIDGET(_PTR(widget_ptr)));
|
||||
|
||||
@@ -605,6 +610,10 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1layout(JNIEnv *env, jobjec
|
||||
allocation.width = width;
|
||||
allocation.height = height;
|
||||
}
|
||||
if(width == 540 && height == 0) {
|
||||
printf("[%p] in Java_android_view_View_native_1layout, calling gtk_widget_size_allocate with [%d,%d]\n", _PTR(widget_ptr), width, height);
|
||||
//_gdb_force_java_stack_trace();
|
||||
}
|
||||
gtk_widget_size_allocate(widget, &allocation, -1);
|
||||
}
|
||||
|
||||
@@ -841,3 +850,9 @@ JNIEXPORT void JNICALL Java_android_view_View_native_1keep_1screen_1on(JNIEnv *e
|
||||
g_object_set_data(G_OBJECT(widget), "keep-screen-on-cookie", GINT_TO_POINTER(cookie));
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jobject JNICALL Java_android_view_View_native_1get_1window(JNIEnv *env, jobject this, jlong widget_ptr)
|
||||
{
|
||||
GtkWidget *widget = GTK_WIDGET(_PTR(widget_ptr));
|
||||
return g_object_get_data(G_OBJECT(gtk_widget_get_root(widget)), "jobject");
|
||||
}
|
||||
|
||||
38
src/api-impl-jni/views/android_view_ViewTreeObserver.c
Normal file
38
src/api-impl-jni/views/android_view_ViewTreeObserver.c
Normal file
@@ -0,0 +1,38 @@
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "../defines.h"
|
||||
#include "../util.h"
|
||||
#include "../generated_headers/android_view_ViewTreeObserver.h"
|
||||
|
||||
static void on_global_layout_callback(GdkFrameClock *clock, jobject view_tree_observer)
|
||||
{
|
||||
JNIEnv *env = get_jni_env();
|
||||
(*env)->CallVoidMethod(env, view_tree_observer, handle_cache.view_tree_observer.dispatchOnGlobalLayout);
|
||||
if((*env)->ExceptionCheck(env)) {
|
||||
(*env)->ExceptionDescribe(env);
|
||||
(*env)->ExceptionClear(env);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_android_view_ViewTreeObserver_native_1set_1have_1global_1layout_1listeners(JNIEnv *env, jobject this, jboolean have_listeners)
|
||||
{
|
||||
GtkWidget *window =_PTR(_GET_LONG_FIELD(this, "window"));
|
||||
|
||||
if(!window) {
|
||||
/* FIXME: calling this on unrooted widgets may be valid */
|
||||
fprintf(stderr, "in Java_android_view_ViewTreeObserver_native_1set_1have_1global_1layout_1listeners: no window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GdkFrameClock *clock = gtk_widget_get_frame_clock(window);
|
||||
|
||||
if(have_listeners) {
|
||||
/* this adds our callback before the existing handler, which means we effectively execute before the paint phase (after layout) */
|
||||
gulong signal_handle = g_signal_connect(G_OBJECT(clock), "paint", G_CALLBACK(on_global_layout_callback), _REF(this)); // FIXME: cleanup callback for _UNREF
|
||||
_SET_LONG_FIELD(this, "onGlobalLayout_signal_handle", signal_handle);
|
||||
} else {
|
||||
gulong signal_handle = _GET_LONG_FIELD(this, "onGlobalLayout_signal_handle");
|
||||
if (signal_handle)
|
||||
g_signal_handler_disconnect(G_OBJECT(clock), signal_handle);
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
G_DEFINE_TYPE(WrapperWidget, wrapper_widget, GTK_TYPE_WIDGET)
|
||||
|
||||
typedef enum { ATL_ID = 1, ATL_ID_NAME, ATL_CLASS_NAME, ATL_SUPER_CLASS_NAMES, N_PROPERTIES } WrapperWidgetProperty;
|
||||
typedef enum { ATL_ID = 1, ATL_ID_NAME, ATL_CLASS_NAME, ATL_SUPER_CLASS_NAMES, ATL_REAL_WIDTH, ATL_REAL_HEIGHT, ATL_HAS_CUSTOM_DRAW, N_PROPERTIES } WrapperWidgetProperty;
|
||||
static GParamSpec *wrapper_widget_properties[N_PROPERTIES] = { NULL, };
|
||||
|
||||
static void wrapper_widget_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
|
||||
@@ -30,6 +30,10 @@ static void wrapper_widget_get_property(GObject *object, guint property_id, GVal
|
||||
JNIEnv *env = get_jni_env();
|
||||
|
||||
jobject jobj = self->jobj;
|
||||
if(!jobj) { /* FIXME */
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
return;
|
||||
}
|
||||
jclass class = _CLASS(jobj);
|
||||
|
||||
switch ((WrapperWidgetProperty) property_id)
|
||||
@@ -85,6 +89,24 @@ static void wrapper_widget_get_property(GObject *object, guint property_id, GVal
|
||||
}
|
||||
|
||||
|
||||
case ATL_REAL_WIDTH:
|
||||
{
|
||||
g_value_set_int(value, self->real_width);
|
||||
break;
|
||||
}
|
||||
|
||||
case ATL_REAL_HEIGHT:
|
||||
{
|
||||
g_value_set_int(value, self->real_height);
|
||||
break;
|
||||
}
|
||||
|
||||
case ATL_HAS_CUSTOM_DRAW:
|
||||
{
|
||||
g_value_set_boolean(value, self->draw_method != NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||
break;
|
||||
@@ -232,6 +254,9 @@ static void wrapper_widget_class_init(WrapperWidgetClass *class)
|
||||
wrapper_widget_properties[ATL_ID_NAME] = g_param_spec_string("ATL-id-name", "ATL: ID name", "Name of the ID of the component", "", G_PARAM_READABLE);
|
||||
wrapper_widget_properties[ATL_CLASS_NAME] = g_param_spec_string("ATL-class-name", "ATL: Class name", "Name of the class of the component", "", G_PARAM_READABLE);
|
||||
wrapper_widget_properties[ATL_SUPER_CLASS_NAMES] = g_param_spec_string("ATL-superclasses-names", "ATL: Super classes names", "Names of all the superclasses of the component class", "", G_PARAM_READABLE);
|
||||
wrapper_widget_properties[ATL_REAL_WIDTH] = g_param_spec_int("ATL-real-width", "ATL: real width", "Real width of the widget", 0, INT32_MAX, 0, G_PARAM_READABLE);
|
||||
wrapper_widget_properties[ATL_REAL_HEIGHT] = g_param_spec_int("ATL-real-height", "ATL: real height", "Real height of the widget", 0, INT32_MAX, 0, G_PARAM_READABLE);
|
||||
wrapper_widget_properties[ATL_HAS_CUSTOM_DRAW] = g_param_spec_boolean("ATL-has-custom-draw", "ATL: has custom draw", "Indicates if the widget implements it's own drawing", FALSE, G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPERTIES, wrapper_widget_properties);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public class Activity extends ContextThemeWrapper implements Window.Callback, La
|
||||
Class<? extends Activity> cls = Class.forName(className).asSubclass(Activity.class);
|
||||
Constructor<? extends Activity> constructor = cls.getConstructor();
|
||||
Activity activity = constructor.newInstance();
|
||||
activity.window.native_window = native_window;
|
||||
activity.window.set_native_window(native_window);
|
||||
activity.intent = intent;
|
||||
activity.attachBaseContext(new Context());
|
||||
activity.setTheme(themeResId);
|
||||
|
||||
@@ -31,7 +31,7 @@ public class Dialog implements Window.Callback, DialogInterface {
|
||||
this.context = context;
|
||||
nativePtr = nativeInit();
|
||||
window = new Window(context, this);
|
||||
window.native_window = nativePtr;
|
||||
window.set_native_window(nativePtr);
|
||||
}
|
||||
|
||||
public Dialog(Context context) {
|
||||
|
||||
@@ -139,7 +139,7 @@ public class Instrumentation {
|
||||
Intent intent, ActivityInfo info, CharSequence title, Activity parent,
|
||||
String id, Object lastNonConfigurationInstance) throws InstantiationException, IllegalAccessException {
|
||||
Activity activity = (Activity)clazz.newInstance();
|
||||
activity.getWindow().native_window = Context.this_application.native_window;
|
||||
activity.getWindow().set_native_window(Context.this_application.native_window);
|
||||
Slog.i(TAG, "activity.getWindow().native_window >"+activity.getWindow().native_window+"<");
|
||||
return activity;
|
||||
}
|
||||
@@ -168,7 +168,7 @@ public class Instrumentation {
|
||||
Constructor<? extends Activity> constructor = cls.getConstructor();
|
||||
final Activity activity = constructor.newInstance();
|
||||
activity.intent = intent;
|
||||
activity.getWindow().native_window = Context.this_application.native_window;
|
||||
activity.getWindow().set_native_window(Context.this_application.native_window);
|
||||
runOnMainSync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -828,15 +828,18 @@ public class View implements Drawable.Callback {
|
||||
private Context context;
|
||||
private Map<Integer,Object> tags = new HashMap<>();
|
||||
private Object tag;
|
||||
int gravity = -1; // fallback gravity for layout childs
|
||||
int gravity = -1; // fallback gravity for layout children
|
||||
|
||||
int measuredWidth = 0;
|
||||
int measuredHeight = 0;
|
||||
|
||||
private int left;
|
||||
private int top;
|
||||
private int right;
|
||||
private int bottom;
|
||||
private int left = 0;
|
||||
private int top = 0;
|
||||
private int right = 0;
|
||||
private int bottom = 0;
|
||||
|
||||
private float translationX = 0;
|
||||
private float translationY = 0;
|
||||
|
||||
private int scrollX = 0;
|
||||
private int scrollY = 0;
|
||||
@@ -1067,13 +1070,23 @@ public class View implements Drawable.Callback {
|
||||
native_setLayoutParams(widget, params.width, params.height, gravity, params.weight, leftMargin, topMargin, rightMargin, bottomMargin);
|
||||
|
||||
layout_params = params;
|
||||
|
||||
System.out.printf("[0x%x] [%s] in setLayoutParams [%d, %d]\n", this.widget, getIdName(), params.width, params.height);
|
||||
if(params.width == -1 && params.height == 0)
|
||||
try {throw new Exception("stack trace");} catch(Exception e) {e.printStackTrace();}
|
||||
|
||||
}
|
||||
|
||||
public ViewGroup.LayoutParams getLayoutParams() {
|
||||
if(layout_params != null)
|
||||
System.out.printf("[0x%x] [%s] in getLayoutParams [%d, %d]\n", this.widget, getIdName(), layout_params.width, layout_params.height);
|
||||
return layout_params;
|
||||
}
|
||||
|
||||
protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
|
||||
if("net.osmand.plus:id/list".equals(getIdName()))
|
||||
try { throw new Exception("stack trace"); } catch (Exception e) { e.printStackTrace(); }
|
||||
System.out.printf("[0x%x] [%s] in setMeasuredDimension [%d, %d]\n", this.widget, getIdName(), measuredWidth, measuredHeight);
|
||||
this.measuredWidth = measuredWidth;
|
||||
this.measuredHeight = measuredHeight;
|
||||
}
|
||||
@@ -1199,8 +1212,17 @@ public class View implements Drawable.Callback {
|
||||
|
||||
public void setSelected(boolean selected) {}
|
||||
|
||||
public native Window native_get_window(long widget);
|
||||
public ViewTreeObserver getViewTreeObserver() {
|
||||
return new ViewTreeObserver();
|
||||
Window window = native_get_window(widget);
|
||||
if (window != null) {
|
||||
if (window.view_tree_observer == null)
|
||||
window.view_tree_observer = new ViewTreeObserver(window);
|
||||
return window.view_tree_observer;
|
||||
} else {
|
||||
/* FIXME: better handling of unrooted widgets? */
|
||||
return new ViewTreeObserver(null);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onFinishInflate() {}
|
||||
@@ -1464,10 +1486,12 @@ public class View implements Drawable.Callback {
|
||||
}
|
||||
|
||||
public final int getMeasuredWidth() {
|
||||
System.out.printf("[0x%x] [%s] in getMeasuredWidth width: %d\n", this.widget, getIdName(), this.measuredWidth);
|
||||
return this.measuredWidth & MEASURED_SIZE_MASK;
|
||||
}
|
||||
|
||||
public final int getMeasuredHeight() {
|
||||
System.out.printf("[0x%x] [%s] in getMeasuredHeight height: %d\n", this.widget, getIdName(), this.measuredHeight);
|
||||
return this.measuredHeight & MEASURED_SIZE_MASK;
|
||||
}
|
||||
|
||||
@@ -1659,13 +1683,31 @@ public class View implements Drawable.Callback {
|
||||
return viewPropertyAnimator;
|
||||
}
|
||||
|
||||
public float getTranslationX() {return 0.f;}
|
||||
public float getTranslationY() {return 0.f;}
|
||||
public void setTranslationX(float translationX) {}
|
||||
public float getTranslationX() {
|
||||
return translationX;
|
||||
}
|
||||
|
||||
public float getTranslationY() {
|
||||
return translationY;
|
||||
}
|
||||
|
||||
/* this is probably slower than on AOSP, becuse it's supposed to bypass the layout phase
|
||||
* and just schedule redraw (which we technically could do, but it wouldn't change the hitbox,
|
||||
* which it's supposed to) */
|
||||
public void setTranslationX(float translationX) {
|
||||
this.translationX = translationX;
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)getLayoutParams();
|
||||
lp.leftMargin += translationX;
|
||||
setLayoutParams(lp);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public void setTranslationY(float translationY) {
|
||||
// CoordinatorLayout abuses this method to trigger a layout pass
|
||||
if (getClass().getName().equals("androidx.coordinatorlayout.widget.CoordinatorLayout"))
|
||||
native_queueAllocate(widget);
|
||||
this.translationY = translationY;
|
||||
ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams)getLayoutParams();
|
||||
lp.topMargin += translationY;
|
||||
setLayoutParams(lp);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public void setX(float x) {
|
||||
@@ -1972,6 +2014,9 @@ public class View implements Drawable.Callback {
|
||||
}
|
||||
|
||||
public void forceLayout() {
|
||||
if(Looper.myLooper() == Looper.getMainLooper()) {
|
||||
requestLayout();
|
||||
} else {
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@@ -1979,6 +2024,7 @@ public class View implements Drawable.Callback {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private OnAttachStateChangeListener onAttachStateChangeListener;
|
||||
public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
|
||||
@@ -2103,8 +2149,6 @@ public class View implements Drawable.Callback {
|
||||
|
||||
public int getTextAlignment() {return 0;}
|
||||
|
||||
public float getY() {return 0.f;}
|
||||
|
||||
public View findViewWithTag(Object tag) {
|
||||
if (Objects.equals(tag, this.tag))
|
||||
return this;
|
||||
@@ -2198,7 +2242,12 @@ public class View implements Drawable.Callback {
|
||||
|
||||
public boolean isDirty() { return false; }
|
||||
|
||||
public float getX() { return getLeft(); }
|
||||
public float getX() {
|
||||
return getLeft();
|
||||
}
|
||||
public float getY() {
|
||||
return getTop();
|
||||
}
|
||||
|
||||
public boolean getGlobalVisibleRect(Rect visibleRect, Point globalOffset) {
|
||||
boolean result = native_getGlobalVisibleRect(widget, visibleRect);
|
||||
|
||||
@@ -247,6 +247,7 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
|
||||
}
|
||||
|
||||
public static int getChildMeasureSpec(int spec, int padding, int childDimension) {
|
||||
System.out.printf("[static] in getChildMeasureSpec(%d, %d, %d)\n", spec, padding, childDimension);
|
||||
int specMode = MeasureSpec.getMode(spec);
|
||||
int specSize = MeasureSpec.getSize(spec);
|
||||
int size = Math.max(0, specSize - padding);
|
||||
@@ -307,6 +308,7 @@ public class ViewGroup extends View implements ViewParent, ViewManager {
|
||||
break;
|
||||
}
|
||||
// noinspection ResourceType
|
||||
System.out.printf("[static] in getChildMeasureSpec, calling MeasureSpec.makeMeasureSpec(%d, %d)\n", resultSize, resultMode);
|
||||
return MeasureSpec.makeMeasureSpec(resultSize, resultMode);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,11 @@ public final class ViewTreeObserver {
|
||||
|
||||
private boolean mAlive = true;
|
||||
|
||||
// accessed from native code
|
||||
private long onGlobalLayout_signal_handle;
|
||||
|
||||
private long window;
|
||||
|
||||
/**
|
||||
* Interface definition for a callback to be invoked when the view hierarchy is
|
||||
* attached to and detached from its window.
|
||||
@@ -297,10 +302,9 @@ public final class ViewTreeObserver {
|
||||
public void onComputeInternalInsets(InternalInsetsInfo inoutInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ViewTreeObserver. This constructor should not be called
|
||||
*/
|
||||
ViewTreeObserver() {
|
||||
ViewTreeObserver(Window window) {
|
||||
if(window != null)
|
||||
this.window = window.native_window;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -493,18 +497,19 @@ public final class ViewTreeObserver {
|
||||
|
||||
if (mOnGlobalLayoutListeners == null) {
|
||||
mOnGlobalLayoutListeners = new CopyOnWriteArray<OnGlobalLayoutListener>();
|
||||
native_set_have_global_layout_listeners(true);
|
||||
}
|
||||
|
||||
mOnGlobalLayoutListeners.add(listener);
|
||||
|
||||
// hack: many Applications wait for the global layout before doing anything
|
||||
// so we dispatch the event immediately
|
||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
/*new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onGlobalLayout();
|
||||
}
|
||||
});
|
||||
});*/
|
||||
|
||||
}
|
||||
|
||||
@@ -539,6 +544,9 @@ public final class ViewTreeObserver {
|
||||
return;
|
||||
}
|
||||
mOnGlobalLayoutListeners.remove(victim);
|
||||
|
||||
if(mOnGlobalLayoutListeners.size() == 0)
|
||||
native_set_have_global_layout_listeners(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1038,4 +1046,6 @@ public final class ViewTreeObserver {
|
||||
getArray().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private native void native_set_have_global_layout_listeners(boolean have_listeners);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ public class Window {
|
||||
public static final int FEATURE_OPTIONS_PANEL = 0;
|
||||
public static final int FEATURE_NO_TITLE = 1;
|
||||
|
||||
public ViewTreeObserver view_tree_observer = null;
|
||||
|
||||
public static interface Callback {
|
||||
public void onContentChanged();
|
||||
|
||||
@@ -42,6 +44,11 @@ public class Window {
|
||||
decorView.onAttachedToWindow();
|
||||
}
|
||||
|
||||
public void set_native_window(long native_window) {
|
||||
this.native_window = native_window;
|
||||
set_jobject(native_window, this);
|
||||
}
|
||||
|
||||
public void addFlags(int flags) {}
|
||||
public void setFlags(int flags, int mask) {}
|
||||
public void clearFlags(int flags) {}
|
||||
@@ -65,12 +72,6 @@ public class Window {
|
||||
return decorView;
|
||||
}
|
||||
|
||||
public native void set_widget_as_root(long native_window, long widget);
|
||||
private native void set_title(long native_window, String title);
|
||||
|
||||
public native void take_input_queue(long native_window, InputQueue.Callback callback, InputQueue queue);
|
||||
public native void set_layout(long native_window, int width, int height);
|
||||
|
||||
public void takeInputQueue(InputQueue.Callback callback) {
|
||||
take_input_queue(native_window, callback, new InputQueue());
|
||||
}
|
||||
@@ -160,4 +161,10 @@ public class Window {
|
||||
public void setReturnTransition(Transition transition) {}
|
||||
|
||||
public void setEnterTransition(Transition transition) {}
|
||||
|
||||
public native void set_widget_as_root(long native_window, long widget);
|
||||
private native void set_title(long native_window, String title);
|
||||
public native void take_input_queue(long native_window, InputQueue.Callback callback, InputQueue queue);
|
||||
public native void set_layout(long native_window, int width, int height);
|
||||
private static native void set_jobject(long ptr, Window obj);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user