From: Po Lu Date: Sat, 28 May 2022 02:09:19 +0000 (+0800) Subject: Improve safety of various DND callbacks X-Git-Tag: emacs-29.0.90~1910^2~376 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=73237458ba305506d42293beb88d26054f8a353c;p=emacs.git Improve safety of various DND callbacks * src/xterm.c (x_dnd_begin_drag_and_drop): Restore selection events if DND is no longer in progress and don't call x-dnd-movement-function. --- diff --git a/src/xterm.c b/src/xterm.c index 94c996a11dc..5c591134692 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10646,7 +10646,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, /* FIXME: how come this can end up with movement frames from other displays on GTK builds? */ && (FRAME_X_DISPLAY (x_dnd_movement_frame) - == FRAME_X_DISPLAY (f))) + == FRAME_X_DISPLAY (f)) + /* If both those variables are false, then F is no + longer protected from deletion by Lisp code. This + can only happen during the final iteration of the DND + event loop. */ + && (x_dnd_in_progress || x_dnd_waiting_for_finish)) { XSETFRAME (frame_object, x_dnd_movement_frame); XSETINT (x, x_dnd_movement_x); @@ -10677,14 +10682,24 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, { if (hold_quit.kind == SELECTION_REQUEST_EVENT) { - x_dnd_old_window_attrs = root_window_attrs; - x_dnd_unwind_flag = true; + /* It's not safe to run Lisp inside this function if + x_dnd_in_progress and x_dnd_waiting_for_finish + are unset, so push it back into the event queue. */ + + if (!x_dnd_in_progress && !x_dnd_waiting_for_finish) + kbd_buffer_store_event (&hold_quit); + else + { + x_dnd_old_window_attrs = root_window_attrs; + x_dnd_unwind_flag = true; + + ref = SPECPDL_INDEX (); + record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f); + x_handle_selection_event ((struct selection_input_event *) &hold_quit); + x_dnd_unwind_flag = false; + unbind_to (ref, Qnil); + } - ref = SPECPDL_INDEX (); - record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f); - x_handle_selection_event ((struct selection_input_event *) &hold_quit); - x_dnd_unwind_flag = false; - unbind_to (ref, Qnil); continue; }