diff --git a/meson.build b/meson.build index 5f51d79f..ad051c6d 100644 --- a/meson.build +++ b/meson.build @@ -169,7 +169,8 @@ libtranslationlayer_so = shared_library('translation_layer_main', [ executable('android-translation-layer', [ 'src/main-executable/main.c', - 'src/main-executable/r_debug.c' + 'src/main-executable/r_debug.c', + 'src/main-executable/back_button.c' ], install: true, dependencies: [ diff --git a/src/api-impl-jni/app/android_app_Activity.c b/src/api-impl-jni/app/android_app_Activity.c index e66084fc..771e869c 100644 --- a/src/api-impl-jni/app/android_app_Activity.c +++ b/src/api-impl-jni/app/android_app_Activity.c @@ -6,6 +6,7 @@ #include "../defines.h" #include "../util.h" +#include "../main-executable/back_button.h" #include "android_app_Activity.h" #include "../generated_headers/android_app_Activity.h" @@ -75,6 +76,19 @@ static void activity_update_current(JNIEnv *env) activity_current = activity_new; } + + if(activity_current != NULL){ + jclass current_activity_class = (*env)->GetObjectClass(env, activity_current); + jmethodID current_activity_on_back_pressed_method_id = (*env) ->GetMethodID(env, current_activity_class, "onBackPressed", "()V"); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + + if(g_list_length(activity_backlog) > 1 || handle_cache.activity.onBackPressed != current_activity_on_back_pressed_method_id){ + back_button_set_sensitive(true); + } else { + back_button_set_sensitive(false); + } + } } void activity_window_ready(void) @@ -88,6 +102,24 @@ void activity_window_ready(void) } } +void current_activity_back_pressed(void){ + JNIEnv *env = get_jni_env(); + + jclass current_activity_class = (*env)->GetObjectClass(env, activity_current); + jmethodID current_activity_on_back_pressed_method_id = (*env) ->GetMethodID(env, current_activity_class, "onBackPressed", "()V"); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + + // Either a new activity was added to the backlog or the current activity's onBackPressed method was changed + if(g_list_length(activity_backlog) > 1 || handle_cache.activity.onBackPressed != current_activity_on_back_pressed_method_id){ + (*env)->CallVoidMethod(env, activity_current, handle_cache.activity.onBackPressed); + if((*env)->ExceptionCheck(env)) + (*env)->ExceptionDescribe(env); + } else { + back_button_set_sensitive(false); + } +} + void activity_close_all(void) { GList *activities, *l; diff --git a/src/api-impl-jni/app/android_app_Activity.h b/src/api-impl-jni/app/android_app_Activity.h index dea8f0fa..fc12333f 100644 --- a/src/api-impl-jni/app/android_app_Activity.h +++ b/src/api-impl-jni/app/android_app_Activity.h @@ -3,3 +3,4 @@ void activity_start(JNIEnv *env, jobject activity_object); void activity_window_ready(void); void activity_close_all(void); +void current_activity_back_pressed(void); diff --git a/src/api-impl-jni/util.c b/src/api-impl-jni/util.c index 80fea7fb..44ff49a7 100644 --- a/src/api-impl-jni/util.c +++ b/src/api-impl-jni/util.c @@ -75,6 +75,7 @@ void set_up_handle_cache(JNIEnv *env) handle_cache.activity.onDestroy = _METHOD(handle_cache.activity.class, "onDestroy", "()V"); handle_cache.activity.onStop = _METHOD(handle_cache.activity.class, "onStop", "()V"); handle_cache.activity.onPause = _METHOD(handle_cache.activity.class, "onPause", "()V"); + handle_cache.activity.onBackPressed = _METHOD(handle_cache.activity.class, "onBackPressed", "()V"); handle_cache.attribute_set.class = _REF((*env)->FindClass(env, "android/util/AttributeSet")); if((*env)->ExceptionCheck(env)) diff --git a/src/api-impl-jni/util.h b/src/api-impl-jni/util.h index 1cc1a8aa..2b5e15e7 100644 --- a/src/api-impl-jni/util.h +++ b/src/api-impl-jni/util.h @@ -17,6 +17,7 @@ struct handle_cache { jmethodID onDestroy; jmethodID onStop; jmethodID onPause; + jmethodID onBackPressed; } activity; struct { jclass class; diff --git a/src/api-impl/android/app/Activity.java b/src/api-impl/android/app/Activity.java index 45437a3b..2d44cfaf 100644 --- a/src/api-impl/android/app/Activity.java +++ b/src/api-impl/android/app/Activity.java @@ -482,6 +482,7 @@ public class Activity extends ContextThemeWrapper implements Window.Callback { } public void onBackPressed() { + System.out.println("onBackPressed() called"); finish(); } diff --git a/src/main-executable/back_button.c b/src/main-executable/back_button.c new file mode 100644 index 00000000..5c327f28 --- /dev/null +++ b/src/main-executable/back_button.c @@ -0,0 +1,18 @@ +#include "back_button.h" + +#include "../api-impl-jni/app/android_app_Activity.h" + +GtkWidget *back_button; + +GtkWidget* back_button_new() { + back_button = gtk_button_new_from_icon_name("go-previous"); + + g_signal_connect(back_button, "clicked", G_CALLBACK(current_activity_back_pressed), NULL); + + back_button_set_sensitive(false); + return back_button; +} + +void back_button_set_sensitive(bool sensitive) { + gtk_widget_set_sensitive(GTK_WIDGET(back_button), sensitive); +} diff --git a/src/main-executable/back_button.h b/src/main-executable/back_button.h new file mode 100644 index 00000000..1a124ac0 --- /dev/null +++ b/src/main-executable/back_button.h @@ -0,0 +1,4 @@ +#include + +GtkWidget* back_button_new(); +void back_button_set_sensitive(bool sensitive); \ No newline at end of file diff --git a/src/main-executable/main.c b/src/main-executable/main.c index 7cad57fe..1f1d2573 100644 --- a/src/main-executable/main.c +++ b/src/main-executable/main.c @@ -10,6 +10,8 @@ #include "../api-impl-jni/util.h" #include "../api-impl-jni/app/android_app_Activity.h" +#include "back_button.h" + #include #include #include @@ -547,6 +549,11 @@ static void open(GtkApplication *app, GFile **files, gint nfiles, const gchar *h gtk_window_set_default_size(GTK_WINDOW(window), d->window_width, d->window_height); g_signal_connect(window, "close-request", G_CALLBACK(app_exit), env); + GtkWidget *header_bar = gtk_header_bar_new(); + GtkWidget *back_button = back_button_new(); + + gtk_header_bar_pack_start(GTK_HEADER_BAR(header_bar), back_button); + gtk_window_set_titlebar(GTK_WINDOW(window), header_bar); gtk_window_present(GTK_WINDOW(window)); // set package name as application id for window icon on Wayland. Needs a {package_name}.desktop file defining the icon