From 708afaf4d374ef4f86bd9a267f06da7f90add3a7 Mon Sep 17 00:00:00 2001 From: Julia Johannesen Date: Tue, 31 Mar 2026 22:33:29 -0400 Subject: [PATCH] Copy alt to clipboard when running natively --- main.js | 19 +++++++++++++++-- native/src/ls-web-view.c | 46 ++++++++++++++++++++++++++++++++++------ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/main.js b/main.js index 7cdcf6c..4054288 100644 --- a/main.js +++ b/main.js @@ -14,6 +14,8 @@ let schedule = { const offlineTitle = 'OFFLINE'; const offlineSubtitle = 'takin a nap'; + +let altText; let copyClipboard; let saveImage; @@ -91,7 +93,7 @@ function loadSchedule() { schedule = JSON.parse(atob(saved)); } -function altText() { +function generateAltText() { let altText = "ari melody LIVE schedule: "; const activeDays = Object.keys(schedule.days) @@ -113,9 +115,11 @@ function altText() { altText += `, `; } - alert(altText); + return altText; } +altText = () => alert(generateAltText()); + if ('webkit' in window && 'messageHandlers' in window.webkit) { let _promiseId = 0; let _promises = new Map(); @@ -136,6 +140,17 @@ if ('webkit' in window && 'messageHandlers' in window.webkit) { reject(); }); + altText = () => new Promise((resolve, reject) => { + const thisPromiseId = ++_promiseId; + + _promises.set(thisPromiseId, [resolve, reject]); + + window.webkit.messageHandlers.altText.postMessage([ + thisPromiseId, + generateAltText(), + ]); + }); + copyClipboard = () => new Promise((resolve, reject) => { const thisPromiseId = ++_promiseId; diff --git a/native/src/ls-web-view.c b/native/src/ls-web-view.c index cbafdac..bed5332 100644 --- a/native/src/ls-web-view.c +++ b/native/src/ls-web-view.c @@ -20,9 +20,12 @@ static void ls_web_view_init(LSWebView *self) {} static void ls_web_view_on_resource_request(WebKitURISchemeRequest *request, gpointer user_data); -static void ls_web_view_on_snapshot_message_received(WebKitUserContentManager *manager, +static void ls_web_view_on_alt_text_message_received(WebKitUserContentManager *manager, JSCValue *value, gpointer user_data); +static void ls_web_view_on_copy_snapshot_message_received(WebKitUserContentManager *manager, + JSCValue *value, + gpointer user_data); static void ls_web_view_constructed(GObject *object) { G_OBJECT_CLASS(ls_web_view_parent_class)->constructed(object); @@ -38,10 +41,14 @@ static void ls_web_view_constructed(GObject *object) { webkit_settings_set_enable_developer_extras(settings, TRUE); WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager(web_view); + + webkit_user_content_manager_register_script_message_handler(manager, "altText", NULL); + g_signal_connect(manager, "script-message-received::altText", + G_CALLBACK(ls_web_view_on_alt_text_message_received), object); + webkit_user_content_manager_register_script_message_handler(manager, "copySnapshot", NULL); g_signal_connect(manager, "script-message-received::copySnapshot", - G_CALLBACK(ls_web_view_on_snapshot_message_received), - g_object_ref(object)); + G_CALLBACK(ls_web_view_on_copy_snapshot_message_received), object); webkit_web_view_load_uri(web_view, "gresource:///space/arimelody/LiveSchedule/webview/index.html"); } @@ -203,17 +210,41 @@ static void ls_web_view_copy_snapshot_to_file(void *user_data) { ls_web_view_copy_snapshot_to_file_after_save_dialog, user_data); } -static void ls_web_view_on_snapshot_message_received(WebKitUserContentManager *manager, +static void ls_web_view_on_alt_text_message_received(WebKitUserContentManager *manager, JSCValue *value, gpointer user_data) { - JSCValue *id_val = jsc_value_object_get_property_at_index(value, 0); + JSCValue *callback_id_val = jsc_value_object_get_property_at_index(value, 0); + JSCValue *alt_text_val = jsc_value_object_get_property_at_index(value, 1); + int callback_id = jsc_value_to_int32(callback_id_val); + char *alt_text = jsc_value_to_string(alt_text_val); + + GdkClipboard *clipboard = gdk_display_get_clipboard(gdk_display_get_default()); + gdk_clipboard_set_text(clipboard, alt_text); + + LSWebView *self = LS_WEB_VIEW(user_data); + + WebKitUserMessage *message = + webkit_user_message_new("_nativePromiseResolve", g_variant_new("(i)", callback_id)); + + webkit_web_view_send_message_to_page(WEBKIT_WEB_VIEW(self), message, NULL, NULL, NULL); + + g_object_unref(callback_id_val); + g_object_unref(alt_text_val); + g_free(alt_text); +} + +static void ls_web_view_on_copy_snapshot_message_received(WebKitUserContentManager *manager, + JSCValue *value, + gpointer user_data) +{ + JSCValue *callback_id_val = jsc_value_object_get_property_at_index(value, 0); JSCValue *kind_val = jsc_value_object_get_property_at_index(value, 1); JSCValue *xoffset_val = jsc_value_object_get_property_at_index(value, 2); JSCValue *yoffset_val = jsc_value_object_get_property_at_index(value, 3); JSCValue *width_val = jsc_value_object_get_property_at_index(value, 4); JSCValue *height_val = jsc_value_object_get_property_at_index(value, 5); - int callback_id = jsc_value_to_int32(id_val); + int callback_id = jsc_value_to_int32(callback_id_val); char *kind = jsc_value_to_string(kind_val); float xoffset = (float)jsc_value_to_double(xoffset_val); float yoffset = (float)jsc_value_to_double(yoffset_val); @@ -232,6 +263,7 @@ static void ls_web_view_on_snapshot_message_received(WebKitUserContentManager *m (struct _LSWebViewCopySnapshotUserData *)g_malloc(sizeof(struct _LSWebViewCopySnapshotUserData)); task_user_data->self = g_object_ref(self); task_user_data->cancellable = g_object_ref(self->cancellable); + task_user_data->callback_id = callback_id; task_user_data->xoffset = xoffset; task_user_data->yoffset = yoffset; task_user_data->width = width; @@ -243,7 +275,7 @@ static void ls_web_view_on_snapshot_message_received(WebKitUserContentManager *m g_idle_add_once(ls_web_view_copy_snapshot_to_file, task_user_data); } - g_object_unref(id_val); + g_object_unref(callback_id_val); g_object_unref(kind_val); g_object_unref(xoffset_val); g_object_unref(yoffset_val);