From 7a9f8ed6fba0d6728cbf185696bdc1a95b1acfea Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 7 Jul 2022 18:36:56 +0800 Subject: [PATCH] Fix quitting out of selection converters during drag and drop * src/xterm.c (x_dnd_process_quit): New function. (x_dnd_begin_drag_and_drop): Use it instead. Also quit if quit-flag is true immediately after a selection converter is run. --- src/xterm.c | 110 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 45 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index a21daa2dfc0..98a5beed178 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -11362,6 +11362,57 @@ x_dnd_lose_ownership (Lisp_Object timestamp_and_frame) XCDR (timestamp_and_frame)); } +/* Clean up an existing drag-and-drop operation in preparation for its + sudden termination. */ + +static void +x_dnd_process_quit (struct frame *f, Time timestamp) +{ + xm_drop_start_message dmsg; + + if (x_dnd_in_progress) + { + if (x_dnd_last_seen_window != None + && x_dnd_last_protocol_version != -1) + x_dnd_send_leave (f, x_dnd_last_seen_window); + else if (x_dnd_last_seen_window != None + && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) + && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE + && x_dnd_motif_setup_p) + { + dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, + XM_DRAG_REASON_DROP_START); + dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; + dmsg.timestamp = timestamp; + dmsg.side_effects + = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), + x_dnd_wanted_action), + XM_DROP_SITE_VALID, x_dnd_motif_operations, + XM_DROP_ACTION_DROP_CANCEL); + dmsg.x = 0; + dmsg.y = 0; + dmsg.index_atom = x_dnd_motif_atom; + dmsg.source_window = FRAME_X_WINDOW (f); + + x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, + x_dnd_last_seen_window, + timestamp); + xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), + x_dnd_last_seen_window, &dmsg); + } + + x_dnd_end_window = x_dnd_last_seen_window; + x_dnd_last_seen_window = None; + x_dnd_last_seen_toplevel = None; + x_dnd_in_progress = false; + x_dnd_frame = NULL; + } + + x_dnd_waiting_for_finish = false; + x_dnd_return_frame_object = NULL; + x_dnd_movement_frame = NULL; +} + /* This function is defined far away from the rest of the XDND code so it can utilize `x_any_window_to_frame'. */ @@ -11398,7 +11449,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, specpdl_ref ref, count, base; ptrdiff_t i, end, fill; XTextProperty prop; - xm_drop_start_message dmsg; Lisp_Object frame_object, x, y, frame, local_value; bool signals_were_pending, need_sync; #ifdef HAVE_XKB @@ -11750,50 +11800,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, if (hold_quit.kind != NO_EVENT) { - if (x_dnd_in_progress) - { - if (x_dnd_last_seen_window != None - && x_dnd_last_protocol_version != -1) - x_dnd_send_leave (f, x_dnd_last_seen_window); - else if (x_dnd_last_seen_window != None - && !XM_DRAG_STYLE_IS_DROP_ONLY (x_dnd_last_motif_style) - && x_dnd_last_motif_style != XM_DRAG_STYLE_NONE - && x_dnd_motif_setup_p) - { - dmsg.reason = XM_DRAG_REASON (XM_DRAG_ORIGINATOR_INITIATOR, - XM_DRAG_REASON_DROP_START); - dmsg.byte_order = XM_BYTE_ORDER_CUR_FIRST; - dmsg.timestamp = hold_quit.timestamp; - dmsg.side_effects - = XM_DRAG_SIDE_EFFECT (xm_side_effect_from_action (FRAME_DISPLAY_INFO (f), - x_dnd_wanted_action), - XM_DROP_SITE_VALID, x_dnd_motif_operations, - XM_DROP_ACTION_DROP_CANCEL); - dmsg.x = 0; - dmsg.y = 0; - dmsg.index_atom = x_dnd_motif_atom; - dmsg.source_window = FRAME_X_WINDOW (f); - - x_dnd_send_xm_leave_for_drop (FRAME_DISPLAY_INFO (f), f, - x_dnd_last_seen_window, - hold_quit.timestamp); - xm_send_drop_message (FRAME_DISPLAY_INFO (f), FRAME_X_WINDOW (f), - x_dnd_last_seen_window, &dmsg); - } - - x_dnd_end_window = x_dnd_last_seen_window; - x_dnd_last_seen_window = None; - x_dnd_last_seen_toplevel = None; - x_dnd_in_progress = false; - x_dnd_frame = NULL; - } - - x_dnd_waiting_for_finish = false; - x_dnd_return_frame_object = NULL; - x_dnd_movement_frame = NULL; - - /* Don't clear dpyinfo->grabbed if we're quitting. */ - + x_dnd_process_quit (f, hold_quit.timestamp); #ifdef USE_GTK current_hold_quit = NULL; #endif @@ -11821,6 +11828,19 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, unbind_to (ref, Qnil); } + /* Sometimes C-g can be pressed inside a selection + converter, where quitting is inhibited. We want + to quit after the converter exits. */ + if (!NILP (Vquit_flag) && !NILP (Vinhibit_quit)) + { + x_dnd_process_quit (f, FRAME_DISPLAY_INFO (f)->last_user_time); +#ifdef USE_GTK + current_hold_quit = NULL; +#endif + x_restore_events_after_dnd (f, &root_window_attrs); + quit (); + } + if (x_dnd_run_unsupported_drop_function && x_dnd_waiting_for_finish) { -- 2.39.5