[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 6011d39b6a: Fix drag-and-drop of files with multibyte filenames
From: |
Po Lu |
Subject: |
master 6011d39b6a: Fix drag-and-drop of files with multibyte filenames |
Date: |
Sun, 5 Jun 2022 03:38:34 -0400 (EDT) |
branch: master
commit 6011d39b6a4bc659da364255bcae22c4e6ef3a3f
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Fix drag-and-drop of files with multibyte filenames
* lisp/dired.el (dired-mouse-drag): Fix re-signalling of errors.
* lisp/select.el (xselect-convert-to-filename):
(xselect-convert-to-text-uri-list):
(xselect-convert-to-dt-netfile): Encode in raw-text-unix.
* src/xgselect.c (suppress_xg_select, release_xg_select): New
functions.
(xg_select): Respect xg_select suppression by delegating to
pselect.
* src/xgselect.h: Update prototypes.
* src/xterm.c (x_dnd_begin_drag_and_drop): Suppress xg_select
during the nested event loop.
(handle_one_xevent): Handle cases where hold_quit is nil inside
a selection event handler during DND.
---
lisp/dired.el | 6 +++---
lisp/select.el | 22 ++++++++++++----------
src/xgselect.c | 23 +++++++++++++++++++++++
src/xgselect.h | 7 ++++---
src/xterm.c | 19 +++++++++++++++++++
5 files changed, 61 insertions(+), 16 deletions(-)
diff --git a/lisp/dired.el b/lisp/dired.el
index 7df50a7b2a..55e150e9e0 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1787,12 +1787,12 @@ other marked file as well. Otherwise, unmark all
files."
nil action t))))
(error (when (eq (event-basic-type new-event) 'mouse-1)
(push new-event unread-command-events))
- ;; Errors from `dnd-begin-drag-file' should be
+ ;; Errors from `dnd-begin-drag-files' should be
;; treated as user errors, since they should
;; only occur when the user performs an invalid
;; action, such as trying to create a link to
- ;; an invalid file.
- (user-error error))))))))))
+ ;; a remote file.
+ (user-error (cadr error)))))))))))
(defvar dired-mouse-drag-files-map (let ((keymap (make-sparse-keymap)))
(define-key keymap [down-mouse-1]
#'dired-mouse-drag)
diff --git a/lisp/select.el b/lisp/select.el
index df1d402655..c5412f2a73 100644
--- a/lisp/select.el
+++ b/lisp/select.el
@@ -630,20 +630,20 @@ two markers or an overlay. Otherwise, it is nil."
(xselect--encode-string 'TEXT (buffer-file-name (nth 2 value))))
(if (and (stringp value)
(file-exists-p value))
- (xselect--encode-string 'TEXT (expand-file-name value)
- nil t)
+ ;; Motif expects this to be STRING, but it treats the data as
+ ;; a sequence of bytes instead of a Latin-1 string.
+ (cons 'STRING (encode-coding-string (expand-file-name value)
+ 'raw-text-unix))
(when (vectorp value)
(with-temp-buffer
(cl-loop for file across value
- do (progn (insert (encode-coding-string
- (expand-file-name file)
- file-name-coding-system))
- (insert "\0")))
+ do (insert (expand-file-name file) "\0"))
;; Get rid of the last NULL byte.
(when (> (point) 1)
(delete-char -1))
;; Motif wants STRING.
- (cons 'STRING (buffer-string)))))))
+ (cons 'STRING (encode-coding-string (buffer-string)
+ 'raw-text-unix)))))))
(defun xselect-convert-to-charpos (_selection _type value)
(when (setq value (xselect--selection-bounds value))
@@ -710,14 +710,15 @@ This function returns the string \"emacs\"."
(defun xselect-convert-to-text-uri-list (_selection _type value)
(if (stringp value)
- (concat (url-encode-url value) "\n")
+ (xselect--encode-string 'TEXT
+ (concat (url-encode-url value) "\n"))
(when (vectorp value)
(with-temp-buffer
(cl-loop for tem across value
do (progn
(insert (url-encode-url tem))
(insert "\n")))
- (buffer-string)))))
+ (xselect--encode-string 'TEXT (buffer-string))))))
(defun xselect-convert-to-xm-file (selection _type value)
(when (and (stringp value)
@@ -770,7 +771,8 @@ VALUE should be SELECTION's local value."
(stringp value)
(file-exists-p value)
(not (file-remote-p value)))
- (xselect-tt-net-file value)))
+ (encode-coding-string (xselect-tt-net-file value)
+ 'raw-text-unix t)))
(setq selection-converter-alist
'((TEXT . xselect-convert-to-string)
diff --git a/src/xgselect.c b/src/xgselect.c
index 7252210c68..6e09a15fa8 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -33,6 +33,9 @@ along with GNU Emacs. If not, see
<https://www.gnu.org/licenses/>. */
static ptrdiff_t threads_holding_glib_lock;
static GMainContext *glib_main_context;
+/* The depth of xg_select suppression. */
+static int xg_select_suppress_count;
+
void
release_select_lock (void)
{
@@ -69,6 +72,23 @@ acquire_select_lock (GMainContext *context)
#endif
}
+/* Call this to not use xg_select when using it would be a bad idea,
+ i.e. during drag-and-drop. */
+void
+suppress_xg_select (void)
+{
+ ++xg_select_suppress_count;
+}
+
+void
+release_xg_select (void)
+{
+ if (!xg_select_suppress_count)
+ emacs_abort ();
+
+ --xg_select_suppress_count;
+}
+
/* `xg_select' is a `pselect' replacement. Why do we need a separate function?
1. Timeouts. Glib and Gtk rely on timer events. If we did pselect
with a greater timeout then the one scheduled by Glib, we would
@@ -100,6 +120,9 @@ xg_select (int fds_lim, fd_set *rfds, fd_set *wfds, fd_set
*efds,
bool already_has_events;
#endif
+ if (xg_select_suppress_count)
+ return pselect (fds_lim, rfds, wfds, efds, timeout, sigmask);
+
context = g_main_context_default ();
acquire_select_lock (context);
diff --git a/src/xgselect.h b/src/xgselect.h
index 15482cbf92..156d4bde59 100644
--- a/src/xgselect.h
+++ b/src/xgselect.h
@@ -25,9 +25,10 @@ along with GNU Emacs. If not, see
<https://www.gnu.org/licenses/>. */
struct timespec;
-extern int xg_select (int max_fds,
- fd_set *rfds, fd_set *wfds, fd_set *efds,
- struct timespec *timeout, sigset_t *sigmask);
+extern int xg_select (int, fd_set *, fd_set *, fd_set *,
+ struct timespec *, sigset_t *);
+extern void suppress_xg_select (void);
+extern void release_xg_select (void);
extern void release_select_lock (void);
diff --git a/src/xterm.c b/src/xterm.c
index a6ef2bfd15..4d8d7e80eb 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -700,6 +700,10 @@ along with GNU Emacs. If not, see
<https://www.gnu.org/licenses/>. */
#endif
#endif
+#ifdef USE_GTK
+#include <xgselect.h>
+#endif
+
#include "bitmaps/gray.xbm"
#ifdef HAVE_XKB
@@ -10760,6 +10764,13 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
if (x_dnd_toplevels)
x_dnd_free_toplevels (true);
+#ifdef USE_GTK
+ /* Prevent GTK+ timeouts from being run, since they can call
+ handle_one_xevent behind our back. */
+ suppress_xg_select ();
+ record_unwind_protect_void (release_xg_select);
+#endif
+
x_dnd_in_progress = true;
x_dnd_frame = f;
x_dnd_last_seen_window = None;
@@ -15818,7 +15829,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
|| (x_dnd_waiting_for_finish
&& dpyinfo->display == x_dnd_finish_display))
{
+#ifndef USE_GTK
eassume (hold_quit);
+#else
+ /* If the debugger runs inside a selection converter, then
+ xg_select can call handle_one_xevent with no
+ hold_quit. */
+ if (!hold_quit)
+ goto done;
+#endif
*hold_quit = inev.ie;
EVENT_INIT (inev.ie);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 6011d39b6a: Fix drag-and-drop of files with multibyte filenames,
Po Lu <=