diff options
| author | Po Lu | 2021-11-13 11:24:13 +0800 |
|---|---|---|
| committer | Po Lu | 2021-11-13 11:24:13 +0800 |
| commit | eb4567e5be17e30583baebced562cb83595643e3 (patch) | |
| tree | 90cf5547cd30ee5c9552674867515b7e59386a7b /src | |
| parent | 59a58328bc086bdda1d8be816778f2a74379b02f (diff) | |
| download | emacs-eb4567e5be17e30583baebced562cb83595643e3.tar.gz emacs-eb4567e5be17e30583baebced562cb83595643e3.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xwidget.c | 71 |
1 files changed, 71 insertions, 0 deletions
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 *, | |||
| 91 | WebKitPolicyDecisionType, | 91 | WebKitPolicyDecisionType, |
| 92 | gpointer); | 92 | gpointer); |
| 93 | static GtkWidget *find_widget_at_pos (GtkWidget *, int, int, int *, int *); | 93 | static GtkWidget *find_widget_at_pos (GtkWidget *, int, int, int *, int *); |
| 94 | static gboolean run_file_chooser_cb (WebKitWebView *, | ||
| 95 | WebKitFileChooserRequest *, | ||
| 96 | gpointer); | ||
| 94 | 97 | ||
| 95 | struct widget_search_data | 98 | struct widget_search_data |
| 96 | { | 99 | { |
| @@ -261,6 +264,10 @@ fails. */) | |||
| 261 | "script-dialog", | 264 | "script-dialog", |
| 262 | G_CALLBACK (webkit_script_dialog_cb), | 265 | G_CALLBACK (webkit_script_dialog_cb), |
| 263 | NULL); | 266 | NULL); |
| 267 | g_signal_connect (G_OBJECT (xw->widget_osr), | ||
| 268 | "run-file-chooser", | ||
| 269 | G_CALLBACK (run_file_chooser_cb), | ||
| 270 | NULL); | ||
| 264 | } | 271 | } |
| 265 | 272 | ||
| 266 | g_signal_connect (G_OBJECT (xw->widgetwindow_osr), "damage-event", | 273 | g_signal_connect (G_OBJECT (xw->widgetwindow_osr), "damage-event", |
| @@ -778,6 +785,70 @@ mouse_target_changed (WebKitWebView *webview, | |||
| 778 | define_cursors (xw, hitresult); | 785 | define_cursors (xw, hitresult); |
| 779 | } | 786 | } |
| 780 | 787 | ||
| 788 | static gboolean | ||
| 789 | run_file_chooser_cb (WebKitWebView *webview, | ||
| 790 | WebKitFileChooserRequest *request, | ||
| 791 | gpointer user_data) | ||
| 792 | { | ||
| 793 | struct frame *f = SELECTED_FRAME (); | ||
| 794 | GtkWidget *chooser; | ||
| 795 | GtkFileFilter *filter; | ||
| 796 | bool select_multiple_p; | ||
| 797 | guint response; | ||
| 798 | GSList *filenames; | ||
| 799 | GSList *tem; | ||
| 800 | int i, len; | ||
| 801 | gchar **files; | ||
| 802 | |||
| 803 | /* Return TRUE to prevent WebKit from showing the default script | ||
| 804 | dialog in the offscreen window, which runs a nested main loop | ||
| 805 | Emacs can't respond to, and as such can't pass X events to. */ | ||
| 806 | if (!FRAME_WINDOW_P (f)) | ||
| 807 | return TRUE; | ||
| 808 | |||
| 809 | chooser = gtk_file_chooser_dialog_new ("Select file", | ||
| 810 | GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)), | ||
| 811 | GTK_FILE_CHOOSER_ACTION_OPEN, | ||
| 812 | "Cancel", | ||
| 813 | GTK_RESPONSE_CANCEL, | ||
| 814 | "Select", | ||
| 815 | GTK_RESPONSE_ACCEPT, | ||
| 816 | NULL); | ||
| 817 | filter = webkit_file_chooser_request_get_mime_types_filter (request); | ||
| 818 | select_multiple_p = webkit_file_chooser_request_get_select_multiple (request); | ||
| 819 | |||
| 820 | gtk_file_chooser_set_select_multiple (GTK_FILE_CHOOSER (chooser), | ||
| 821 | select_multiple_p); | ||
| 822 | gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (chooser), filter); | ||
| 823 | response = gtk_dialog_run (GTK_DIALOG (chooser)); | ||
| 824 | |||
| 825 | if (response == GTK_RESPONSE_CANCEL) | ||
| 826 | { | ||
| 827 | gtk_widget_destroy (chooser); | ||
| 828 | webkit_file_chooser_request_cancel (request); | ||
| 829 | |||
| 830 | return TRUE; | ||
| 831 | } | ||
| 832 | |||
| 833 | filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER (chooser)); | ||
| 834 | len = g_slist_length (filenames); | ||
| 835 | files = alloca (sizeof *files * (len + 1)); | ||
| 836 | |||
| 837 | for (tem = filenames, i = 0; tem; tem = tem->next, ++i) | ||
| 838 | files[i] = tem->data; | ||
| 839 | files[len] = NULL; | ||
| 840 | |||
| 841 | g_slist_free (filenames); | ||
| 842 | webkit_file_chooser_request_select_files (request, (const gchar **) files); | ||
| 843 | |||
| 844 | for (i = 0; i < len; ++i) | ||
| 845 | g_free (files[i]); | ||
| 846 | |||
| 847 | gtk_widget_destroy (chooser); | ||
| 848 | |||
| 849 | return TRUE; | ||
| 850 | } | ||
| 851 | |||
| 781 | 852 | ||
| 782 | static void | 853 | static void |
| 783 | xwidget_button_1 (struct xwidget_view *view, | 854 | xwidget_button_1 (struct xwidget_view *view, |