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
handle drag-and-drop events as ACTION_SEND Intents
This commit is contained in:
@@ -99,6 +99,7 @@ void set_up_handle_cache(JNIEnv *env)
|
|||||||
(*env)->ExceptionDescribe(env);
|
(*env)->ExceptionDescribe(env);
|
||||||
handle_cache.context.sendBroadcast = _METHOD(handle_cache.context.class, "sendBroadcast", "(Landroid/content/Intent;)V");
|
handle_cache.context.sendBroadcast = _METHOD(handle_cache.context.class, "sendBroadcast", "(Landroid/content/Intent;)V");
|
||||||
handle_cache.context.startActivity = _METHOD(handle_cache.context.class, "startActivity", "(Landroid/content/Intent;)V");
|
handle_cache.context.startActivity = _METHOD(handle_cache.context.class, "startActivity", "(Landroid/content/Intent;)V");
|
||||||
|
handle_cache.context.resolveActivityInternal = _STATIC_METHOD(handle_cache.context.class, "resolveActivityInternal", "(Landroid/content/Intent;)Landroid/app/Activity;");
|
||||||
handle_cache.context.startService = _METHOD(handle_cache.context.class, "startService", "(Landroid/content/Intent;)Landroid/content/ComponentName;");
|
handle_cache.context.startService = _METHOD(handle_cache.context.class, "startService", "(Landroid/content/Intent;)Landroid/content/ComponentName;");
|
||||||
|
|
||||||
handle_cache.application.class = _REF((*env)->FindClass(env, "android/app/Application"));
|
handle_cache.application.class = _REF((*env)->FindClass(env, "android/app/Application"));
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ struct handle_cache {
|
|||||||
jmethodID get_package_name;
|
jmethodID get_package_name;
|
||||||
jmethodID sendBroadcast;
|
jmethodID sendBroadcast;
|
||||||
jmethodID startActivity;
|
jmethodID startActivity;
|
||||||
|
jmethodID resolveActivityInternal;
|
||||||
jmethodID startService;
|
jmethodID startService;
|
||||||
} context;
|
} context;
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
@@ -158,6 +158,8 @@ static gboolean on_event(GtkEventControllerLegacy *event_controller, GdkEvent *e
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t id = (uintptr_t)gdk_event_get_event_sequence(event);
|
uintptr_t id = (uintptr_t)gdk_event_get_event_sequence(event);
|
||||||
|
if (id > MAX_POINTERS-1) // sequence id is a real pointer for drag and drop events
|
||||||
|
return false;
|
||||||
|
|
||||||
/* FIXME: this will clash with touchscreen */
|
/* FIXME: this will clash with touchscreen */
|
||||||
if(id == 0)
|
if(id == 0)
|
||||||
|
|||||||
@@ -547,6 +547,30 @@ public class Context extends Object {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For use from native code */
|
||||||
|
static Activity resolveActivityInternal(Intent intent) throws ReflectiveOperationException {
|
||||||
|
String className = null;
|
||||||
|
if (intent.getComponent() != null) {
|
||||||
|
className = intent.getComponent().getClassName();
|
||||||
|
} else {
|
||||||
|
int best_score = -5;
|
||||||
|
for (PackageParser.Activity activity: pkg.activities) {
|
||||||
|
for (PackageParser.IntentInfo intentInfo: activity.intents) {
|
||||||
|
int score = intentInfo.match(intent.getAction(), intent.getType(), intent.getScheme(), intent.getData(), intent.getCategories(), "Context");
|
||||||
|
if (score > best_score && score > 0) {
|
||||||
|
className = activity.className;
|
||||||
|
best_score = score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (className != null) {
|
||||||
|
return Activity.internalCreateActivity(className, this_application.native_window, intent);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void startActivity(Intent intent) {
|
public void startActivity(Intent intent) {
|
||||||
Slog.i(TAG, "startActivity(" + intent + ") called");
|
Slog.i(TAG, "startActivity(" + intent + ") called");
|
||||||
if (intent.getAction() != null && intent.getAction().equals("android.intent.action.CHOOSER")) {
|
if (intent.getAction() != null && intent.getAction().equals("android.intent.action.CHOOSER")) {
|
||||||
|
|||||||
@@ -236,6 +236,31 @@ static void parse_string_extras(JNIEnv *env, char **extra_string_keys, jobject i
|
|||||||
g_regex_unref(regex);
|
g_regex_unref(regex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Drag and drop callback to simulate ACTION_SEND intents */
|
||||||
|
static gboolean on_drop(GtkDropTarget *target, const GValue *value, double x, double y, gpointer user_data)
|
||||||
|
{
|
||||||
|
const char *data = g_value_get_string(value);
|
||||||
|
if (!data || !*data) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNIEnv *env = get_jni_env();
|
||||||
|
jobject intent = (*env)->NewObject(env, handle_cache.intent.class, handle_cache.intent.constructor);
|
||||||
|
_SET_OBJ_FIELD(intent, "action", "Ljava/lang/String;", _JSTRING("android.intent.action.SEND"));
|
||||||
|
_SET_OBJ_FIELD(intent, "data", "Landroid/net/Uri;", (*env)->CallStaticObjectMethod(env, handle_cache.uri.class, handle_cache.uri.parse, _JSTRING(data)));
|
||||||
|
|
||||||
|
jobject activity = (*env)->CallStaticObjectMethod(env, handle_cache.context.class, handle_cache.context.resolveActivityInternal, intent);
|
||||||
|
if ((*env)->ExceptionCheck(env)) {
|
||||||
|
(*env)->ExceptionDescribe(env);
|
||||||
|
}
|
||||||
|
if (!activity) {
|
||||||
|
printf("failed to resolve activity to handle URI: %s\n", data);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
activity_start(env, activity);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void open(GtkApplication *app, GFile **files, gint nfiles, const gchar *hint, struct jni_callback_data *d)
|
static void open(GtkApplication *app, GFile **files, gint nfiles, const gchar *hint, struct jni_callback_data *d)
|
||||||
{
|
{
|
||||||
// TODO: pass all files to classpath
|
// TODO: pass all files to classpath
|
||||||
@@ -668,6 +693,9 @@ static void open(GtkApplication *app, GFile **files, gint nfiles, const gchar *h
|
|||||||
|
|
||||||
gtk_header_bar_pack_start(GTK_HEADER_BAR(header_bar), back_button);
|
gtk_header_bar_pack_start(GTK_HEADER_BAR(header_bar), back_button);
|
||||||
gtk_window_set_titlebar(GTK_WINDOW(window), header_bar);
|
gtk_window_set_titlebar(GTK_WINDOW(window), header_bar);
|
||||||
|
GtkDropTarget *drop_target = gtk_drop_target_new(G_TYPE_STRING, GDK_ACTION_COPY);
|
||||||
|
g_signal_connect(drop_target, "drop", G_CALLBACK(on_drop), NULL);
|
||||||
|
gtk_widget_add_controller(window, GTK_EVENT_CONTROLLER(drop_target));
|
||||||
gtk_window_present(GTK_WINDOW(window));
|
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
|
// set package name as application id for window icon on Wayland. Needs a {package_name}.desktop file defining the icon
|
||||||
|
|||||||
Reference in New Issue
Block a user