]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix file chooser hangs inside xwidget-webkit
authorPo Lu <luangruo@yahoo.com>
Sat, 13 Nov 2021 03:24:13 +0000 (11:24 +0800)
committerPo Lu <luangruo@yahoo.com>
Sat, 13 Nov 2021 03:24:13 +0000 (11:24 +0800)
* 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

index c1fbfedc7030514dab31bd7d22f5bf2a84369c71..fad07efb2947917448bc4808ccba6615b9c19b3a 100644 (file)
@@ -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,