Copy alt to clipboard when running natively

This commit is contained in:
Julia Johannesen 2026-03-31 22:33:29 -04:00
parent f37337f088
commit 708afaf4d3
Signed by: julia
GPG key ID: 4A1377AF3E7FBC46
2 changed files with 56 additions and 9 deletions

19
main.js
View file

@ -14,6 +14,8 @@ let schedule = {
const offlineTitle = 'OFFLINE'; const offlineTitle = 'OFFLINE';
const offlineSubtitle = 'takin a nap'; const offlineSubtitle = 'takin a nap';
let altText;
let copyClipboard; let copyClipboard;
let saveImage; let saveImage;
@ -91,7 +93,7 @@ function loadSchedule() {
schedule = JSON.parse(atob(saved)); schedule = JSON.parse(atob(saved));
} }
function altText() { function generateAltText() {
let altText = "ari melody LIVE schedule: "; let altText = "ari melody LIVE schedule: ";
const activeDays = Object.keys(schedule.days) const activeDays = Object.keys(schedule.days)
@ -113,9 +115,11 @@ function altText() {
altText += `, `; altText += `, `;
} }
alert(altText); return altText;
} }
altText = () => alert(generateAltText());
if ('webkit' in window && 'messageHandlers' in window.webkit) { if ('webkit' in window && 'messageHandlers' in window.webkit) {
let _promiseId = 0; let _promiseId = 0;
let _promises = new Map(); let _promises = new Map();
@ -136,6 +140,17 @@ if ('webkit' in window && 'messageHandlers' in window.webkit) {
reject(); 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) => { copyClipboard = () => new Promise((resolve, reject) => {
const thisPromiseId = ++_promiseId; const thisPromiseId = ++_promiseId;

View file

@ -20,9 +20,12 @@ static void ls_web_view_init(LSWebView *self) {}
static void ls_web_view_on_resource_request(WebKitURISchemeRequest *request, static void ls_web_view_on_resource_request(WebKitURISchemeRequest *request,
gpointer user_data); 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, JSCValue *value,
gpointer user_data); 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) { static void ls_web_view_constructed(GObject *object) {
G_OBJECT_CLASS(ls_web_view_parent_class)->constructed(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); webkit_settings_set_enable_developer_extras(settings, TRUE);
WebKitUserContentManager *manager = webkit_web_view_get_user_content_manager(web_view); 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); webkit_user_content_manager_register_script_message_handler(manager, "copySnapshot", NULL);
g_signal_connect(manager, "script-message-received::copySnapshot", g_signal_connect(manager, "script-message-received::copySnapshot",
G_CALLBACK(ls_web_view_on_snapshot_message_received), G_CALLBACK(ls_web_view_on_copy_snapshot_message_received), object);
g_object_ref(object));
webkit_web_view_load_uri(web_view, "gresource:///space/arimelody/LiveSchedule/webview/index.html"); 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); 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, JSCValue *value,
gpointer user_data) 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 *kind_val = jsc_value_object_get_property_at_index(value, 1);
JSCValue *xoffset_val = jsc_value_object_get_property_at_index(value, 2); 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 *yoffset_val = jsc_value_object_get_property_at_index(value, 3);
JSCValue *width_val = jsc_value_object_get_property_at_index(value, 4); JSCValue *width_val = jsc_value_object_get_property_at_index(value, 4);
JSCValue *height_val = jsc_value_object_get_property_at_index(value, 5); 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); char *kind = jsc_value_to_string(kind_val);
float xoffset = (float)jsc_value_to_double(xoffset_val); float xoffset = (float)jsc_value_to_double(xoffset_val);
float yoffset = (float)jsc_value_to_double(yoffset_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)); (struct _LSWebViewCopySnapshotUserData *)g_malloc(sizeof(struct _LSWebViewCopySnapshotUserData));
task_user_data->self = g_object_ref(self); task_user_data->self = g_object_ref(self);
task_user_data->cancellable = g_object_ref(self->cancellable); task_user_data->cancellable = g_object_ref(self->cancellable);
task_user_data->callback_id = callback_id;
task_user_data->xoffset = xoffset; task_user_data->xoffset = xoffset;
task_user_data->yoffset = yoffset; task_user_data->yoffset = yoffset;
task_user_data->width = width; 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_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(kind_val);
g_object_unref(xoffset_val); g_object_unref(xoffset_val);
g_object_unref(yoffset_val); g_object_unref(yoffset_val);