From eb4567e5be17e30583baebced562cb83595643e3 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sat, 13 Nov 2021 11:24:13 +0800 Subject: [PATCH] Fix file chooser hangs inside xwidget-webkit * src/xwidget.c (run_file_chooser_cb): New function that runs a nested event loop instead of acting asynchronously. (Fmake_xwidget): Attach file chooser signal. --- src/xwidget.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/xwidget.c b/src/xwidget.c index c1fbfedc703..fad07efb294 100644 --- a/src/xwidget.c +++ b/src/xwidget.c @@ -91,6 +91,9 @@ webkit_decide_policy_cb (WebKitWebView *, WebKitPolicyDecisionType, gpointer); static GtkWidget *find_widget_at_pos (GtkWidget *, int, int, int *, int *); +static gboolean run_file_chooser_cb (WebKitWebView *, + WebKitFileChooserRequest *, + gpointer); struct widget_search_data { @@ -261,6 +264,10 @@ fails. */) "script-dialog", G_CALLBACK (webkit_script_dialog_cb), NULL); + g_signal_connect (G_OBJECT (xw->widget_osr), + "run-file-chooser", + G_CALLBACK (run_file_chooser_cb), + NULL); } g_signal_connect (G_OBJECT (xw->widgetwindow_osr), "damage-event", @@ -778,6 +785,70 @@ mouse_target_changed (WebKitWebView *webview, define_cursors (xw, hitresult); } +static gboolean +run_file_chooser_cb (WebKitWebView *webview, + WebKitFileChooserRequest *request, + gpointer user_data) +{ + struct frame *f = SELECTED_FRAME (); + GtkWidget *chooser; + GtkFileFilter *filter; + bool select_multiple_p; + guint response; + GSList *filenames; + GSList *tem; + int i, len; + gchar **files; + + /* Return TRUE to prevent WebKit from showing the default script + dialog in the offscreen window, which runs a nested main loop + Emacs can't respond to, and as such can't pass X events to. */ + if (!FRAME_WINDOW_P (f)) + return TRUE; + + chooser = gtk_file_chooser_dialog_new ("Select file", + GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), + GTK_FILE_CHOOSER_ACTION_OPEN, + "Cancel", + GTK_RESPONSE_CANCEL, + "Select", + GTK_RESPONSE_ACCEPT, + NULL); + filter = webkit_file_chooser_request_get_mime_types_filter (request); + select_multiple_p = webkit_file_chooser_request_get_select_multiple (request); + + gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), + select_multiple_p); + gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter); + response = gtk_dialog_run (GTK_DIALOG (chooser)); + + if (response == GTK_RESPONSE_CANCEL) + { + gtk_widget_destroy (chooser); + webkit_file_chooser_request_cancel (request); + + return TRUE; + } + + filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser)); + len = g_slist_length (filenames); + files = alloca (sizeof *files * (len + 1)); + + for (tem = filenames, i = 0; tem; tem = tem->next, ++i) + files[i] = tem->data; + files[len] = NULL; + + g_slist_free (filenames); + webkit_file_chooser_request_select_files (request, (const gchar **) files); + + for (i = 0; i < len; ++i) + g_free (files[i]); + + gtk_widget_destroy (chooser); + + return TRUE; +} + static void xwidget_button_1 (struct xwidget_view *view, -- 2.39.2