2023-08-11 18:09:17 +02:00
|
|
|
#include <gtk/gtk.h>
|
2023-09-01 16:03:31 +02:00
|
|
|
#include <libportal/portal.h>
|
2023-08-11 18:09:17 +02:00
|
|
|
|
|
|
|
|
#include <jni.h>
|
|
|
|
|
|
|
|
|
|
#include "../defines.h"
|
|
|
|
|
#include "../util.h"
|
|
|
|
|
#include "android_app_Activity.h"
|
|
|
|
|
#include "../generated_headers/android_app_Activity.h"
|
|
|
|
|
|
|
|
|
|
static GList *activity_backlog = NULL;
|
|
|
|
|
static jobject activity_current = NULL;
|
|
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
static void activity_close(JNIEnv *env, jobject activity)
|
|
|
|
|
{
|
2023-08-11 18:09:17 +02:00
|
|
|
// in case some exception was left unhandled in native code, print it here so we don't confuse it with an exception thrown by onDestroy
|
|
|
|
|
if((*env)->ExceptionCheck(env)) {
|
|
|
|
|
fprintf(stderr, "app_exit: seems there was a pending exception... :");
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* -- run the main activity's onDestroy -- */
|
2023-09-25 19:53:20 +02:00
|
|
|
(*env)->CallVoidMethod(env, activity, handle_cache.activity.onDestroy, NULL);
|
2023-08-11 18:09:17 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
static void activity_update_current(JNIEnv *env)
|
|
|
|
|
{
|
2023-08-11 18:09:17 +02:00
|
|
|
jobject activity_new = activity_backlog ? g_list_first(activity_backlog)->data : NULL;
|
|
|
|
|
|
|
|
|
|
if (activity_current != activity_new) {
|
|
|
|
|
if (activity_current) {
|
2023-09-25 19:53:20 +02:00
|
|
|
(*env)->CallVoidMethod(env, activity_current, handle_cache.activity.onPause);
|
2023-08-11 18:09:17 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
|
2023-09-25 19:53:20 +02:00
|
|
|
(*env)->CallVoidMethod(env, activity_current, handle_cache.activity.onStop);
|
2023-08-11 18:09:17 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
2023-09-25 19:53:20 +02:00
|
|
|
|
2023-10-08 13:58:04 +02:00
|
|
|
(*env)->CallVoidMethod(env, activity_current, handle_cache.activity.onWindowFocusChanged, false);
|
2023-09-25 19:53:20 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
|
2023-08-11 18:09:17 +02:00
|
|
|
}
|
|
|
|
|
if (activity_new) {
|
2023-09-25 19:53:20 +02:00
|
|
|
(*env)->CallVoidMethod(env, activity_new, handle_cache.activity.onStart);
|
|
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
|
|
|
|
|
(*env)->CallVoidMethod(env, activity_new, handle_cache.activity.onResume);
|
2023-08-11 18:09:17 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
|
2023-09-25 19:53:20 +02:00
|
|
|
(*env)->CallVoidMethod(env, activity_new, handle_cache.activity.onWindowFocusChanged, true);
|
2023-08-11 18:09:17 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
}
|
|
|
|
|
activity_current = activity_new;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
void activity_window_ready(void)
|
|
|
|
|
{
|
2023-08-11 18:09:17 +02:00
|
|
|
JNIEnv *env = get_jni_env();
|
|
|
|
|
|
|
|
|
|
for (GList *l = activity_backlog; l != NULL; l = l->next) {
|
2023-09-25 19:53:20 +02:00
|
|
|
(*env)->CallVoidMethod(env, l->data, handle_cache.activity.onWindowFocusChanged, true);
|
2023-08-11 18:09:17 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
void activity_close_all(void)
|
|
|
|
|
{
|
2023-08-11 18:09:17 +02:00
|
|
|
GList *activities, *l;
|
|
|
|
|
JNIEnv *env = get_jni_env();
|
|
|
|
|
// local backup of the backlog
|
|
|
|
|
activities = activity_backlog;
|
|
|
|
|
// deactivate all activities
|
|
|
|
|
activity_backlog = NULL;
|
|
|
|
|
activity_update_current(env);
|
|
|
|
|
// destroy all activities
|
|
|
|
|
for (l = activities; l != NULL; l = l->next) {
|
|
|
|
|
activity_close(env, l->data);
|
|
|
|
|
_UNREF(l->data);
|
|
|
|
|
}
|
|
|
|
|
g_list_free(activities);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
void activity_start(JNIEnv *env, jobject activity_object)
|
|
|
|
|
{
|
2023-08-11 18:09:17 +02:00
|
|
|
/* -- run the activity's onCreate -- */
|
2023-09-25 19:53:20 +02:00
|
|
|
(*env)->CallVoidMethod(env, activity_object, handle_cache.activity.onCreate, NULL);
|
2023-08-11 18:09:17 +02:00
|
|
|
if((*env)->ExceptionCheck(env))
|
|
|
|
|
(*env)->ExceptionDescribe(env);
|
|
|
|
|
|
|
|
|
|
activity_backlog = g_list_prepend(activity_backlog, _REF(activity_object));
|
|
|
|
|
activity_update_current(env);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
JNIEXPORT void JNICALL Java_android_app_Activity_nativeFinish(JNIEnv *env, jobject this, jlong window)
|
|
|
|
|
{
|
2023-08-22 13:20:04 +02:00
|
|
|
GList *l;
|
|
|
|
|
jobject removed_activity = NULL;
|
|
|
|
|
for (l = activity_backlog; l != NULL; l = l->next) {
|
|
|
|
|
if ((*env)->IsSameObject(env, this, l->data)) {
|
|
|
|
|
removed_activity = l->data;
|
|
|
|
|
activity_backlog = g_list_delete_link(activity_backlog, l);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-11 18:09:17 +02:00
|
|
|
activity_update_current(env);
|
|
|
|
|
activity_close(env, this);
|
2023-08-22 13:20:04 +02:00
|
|
|
if (removed_activity)
|
|
|
|
|
_UNREF(removed_activity);
|
2023-08-11 18:09:17 +02:00
|
|
|
if (activity_backlog == NULL)
|
|
|
|
|
gtk_window_close(GTK_WINDOW(_PTR(window)));
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
JNIEXPORT void JNICALL Java_android_app_Activity_nativeStartActivity(JNIEnv *env, jclass class, jobject activity)
|
|
|
|
|
{
|
2023-08-11 18:09:17 +02:00
|
|
|
activity_start(env, activity);
|
|
|
|
|
}
|
2023-09-01 16:03:31 +02:00
|
|
|
|
2024-02-10 20:37:28 +01:00
|
|
|
JNIEXPORT void JNICALL Java_android_app_Activity_nativeOpenURI(JNIEnv *env, jclass class, jstring uriString)
|
|
|
|
|
{
|
|
|
|
|
static XdpPortal *portal = NULL;
|
2023-09-01 16:03:31 +02:00
|
|
|
if (!portal) {
|
|
|
|
|
portal = xdp_portal_new();
|
|
|
|
|
}
|
2024-02-10 20:37:28 +01:00
|
|
|
|
|
|
|
|
const char *uri = (*env)->GetStringUTFChars(env, uriString, NULL);
|
2023-09-01 16:03:31 +02:00
|
|
|
xdp_portal_open_uri(portal, NULL, uri, XDP_OPEN_URI_FLAG_NONE, NULL, NULL, NULL);
|
|
|
|
|
(*env)->ReleaseStringUTFChars(env, uriString, uri);
|
|
|
|
|
}
|
2024-02-10 20:37:28 +01:00
|
|
|
|
|
|
|
|
extern GtkWindow *window; // TODO: get this in a better way
|
|
|
|
|
|
|
|
|
|
JNIEXPORT void JNICALL Java_android_app_Activity_nativeShare(JNIEnv *env, jclass class, jstring text_jstring)
|
|
|
|
|
{
|
|
|
|
|
const char *text = (*env)->GetStringUTFChars(env, text_jstring, NULL);
|
|
|
|
|
GdkClipboard *clipboard = gdk_display_get_clipboard(gtk_root_get_display(GTK_ROOT(window)));
|
|
|
|
|
gdk_clipboard_set_text(clipboard, text);
|
|
|
|
|
(*env)->ReleaseStringUTFChars(env, text_jstring, text);
|
|
|
|
|
}
|