aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-06-06 11:08:19 +0800
committerPo Lu2022-06-06 11:08:19 +0800
commitb90d2a6a63f1b7f73d2cb7e976148e8195fc5502 (patch)
tree965057d58b783e920711e05138ad56184ceec6c4
parent0a36671f415bd681ddca0bad8612aca031fd407d (diff)
downloademacs-b90d2a6a63f1b7f73d2cb7e976148e8195fc5502.tar.gz
emacs-b90d2a6a63f1b7f73d2cb7e976148e8195fc5502.zip
Rework X selections to make it safe to run the debugger inside converters
* src/keyboard.c (prev_kbd_event): Delete function. (readable_events): Return 1 if x_detect_pending_selection_requests returns true. (kbd_buffer_unget_event): Also delete function, since nested selection requests are really handled correctly. (kbd_buffer_get_event): Handle events from the special X deferred selection queue as well. * src/keyboard.h: Update prototypes. * src/xselect.c (struct selection_event_queue) (selection_input_event_equal, x_queue_event) (x_start_queuing_selection_requests) (x_stop_queuing_selection_requests): Delete structs, since they are no longer required. (x_handle_selection_request, x_handle_selection_event): Allow nested selection events. * src/xterm.c (struct x_selection_request_event): New struct. (x_handle_pending_selection_requests_1) (x_handle_pending_selection_requests): Handle all events in the new selection event queue. (x_push_selection_request, x_detect_pending_selection_requests): New functions. (x_dnd_begin_drag_and_drop): Drain the selection queue here as well. (handle_one_xevent): When inside a nested event loop, just push selections to that queue. (XTread_socket): Allow reading X events if x_dnd_unwind_flag is true, even though DND is in progress. (x_delete_display): Delete pending selection events for the display that is going away. * src/xterm.h: Update prototypes.
-rw-r--r--src/keyboard.c64
-rw-r--r--src/keyboard.h3
-rw-r--r--src/xselect.c93
-rw-r--r--src/xterm.c163
-rw-r--r--src/xterm.h2
5 files changed, 163 insertions, 162 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 274c7b3fa84..55d710ed627 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -389,14 +389,6 @@ next_kbd_event (union buffered_input_event *ptr)
389 return ptr == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : ptr + 1; 389 return ptr == kbd_buffer + KBD_BUFFER_SIZE - 1 ? kbd_buffer : ptr + 1;
390} 390}
391 391
392#ifdef HAVE_X11
393static union buffered_input_event *
394prev_kbd_event (union buffered_input_event *ptr)
395{
396 return ptr == kbd_buffer ? kbd_buffer + KBD_BUFFER_SIZE - 1 : ptr - 1;
397}
398#endif
399
400/* Like EVENT_START, but assume EVENT is an event. 392/* Like EVENT_START, but assume EVENT is an event.
401 This pacifies gcc -Wnull-dereference, which might otherwise 393 This pacifies gcc -Wnull-dereference, which might otherwise
402 complain about earlier checks that EVENT is indeed an event. */ 394 complain about earlier checks that EVENT is indeed an event. */
@@ -3528,6 +3520,11 @@ readable_events (int flags)
3528 return 1; 3520 return 1;
3529 } 3521 }
3530 3522
3523#ifdef HAVE_X_WINDOWS
3524 if (x_detect_pending_selection_requests ())
3525 return 1;
3526#endif
3527
3531 if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && some_mouse_moved ()) 3528 if (!(flags & READABLE_EVENTS_IGNORE_SQUEEZABLES) && some_mouse_moved ())
3532 return 1; 3529 return 1;
3533 if (single_kboard) 3530 if (single_kboard)
@@ -3699,25 +3696,6 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
3699 Vquit_flag = Vthrow_on_input; 3696 Vquit_flag = Vthrow_on_input;
3700} 3697}
3701 3698
3702
3703#ifdef HAVE_X11
3704
3705/* Put a selection input event back in the head of the event queue. */
3706
3707void
3708kbd_buffer_unget_event (struct selection_input_event *event)
3709{
3710 /* Don't let the very last slot in the buffer become full, */
3711 union buffered_input_event *kp = prev_kbd_event (kbd_fetch_ptr);
3712 if (kp != kbd_store_ptr)
3713 {
3714 kp->sie = *event;
3715 kbd_fetch_ptr = kp;
3716 }
3717}
3718
3719#endif
3720
3721/* Limit help event positions to this range, to avoid overflow problems. */ 3699/* Limit help event positions to this range, to avoid overflow problems. */
3722#define INPUT_EVENT_POS_MAX \ 3700#define INPUT_EVENT_POS_MAX \
3723 ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \ 3701 ((ptrdiff_t) min (PTRDIFF_MAX, min (TYPE_MAXIMUM (Time) / 2, \
@@ -3874,6 +3852,11 @@ kbd_buffer_get_event (KBOARD **kbp,
3874 struct timespec *end_time) 3852 struct timespec *end_time)
3875{ 3853{
3876 Lisp_Object obj, str; 3854 Lisp_Object obj, str;
3855#ifdef HAVE_X_WINDOWS
3856 bool had_pending_selection_requests;
3857
3858 had_pending_selection_requests = false;
3859#endif
3877 3860
3878#ifdef subprocesses 3861#ifdef subprocesses
3879 if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4) 3862 if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4)
@@ -3926,10 +3909,18 @@ kbd_buffer_get_event (KBOARD **kbp,
3926#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL) 3909#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
3927 gobble_input (); 3910 gobble_input ();
3928#endif 3911#endif
3912
3929 if (kbd_fetch_ptr != kbd_store_ptr) 3913 if (kbd_fetch_ptr != kbd_store_ptr)
3930 break; 3914 break;
3931 if (some_mouse_moved ()) 3915 if (some_mouse_moved ())
3932 break; 3916 break;
3917#ifdef HAVE_X_WINDOWS
3918 if (x_detect_pending_selection_requests ())
3919 {
3920 had_pending_selection_requests = true;
3921 break;
3922 }
3923#endif
3933 if (end_time) 3924 if (end_time)
3934 { 3925 {
3935 struct timespec now = current_timespec (); 3926 struct timespec now = current_timespec ();
@@ -3966,6 +3957,16 @@ kbd_buffer_get_event (KBOARD **kbp,
3966 gobble_input (); 3957 gobble_input ();
3967 } 3958 }
3968 3959
3960#ifdef HAVE_X_WINDOWS
3961 /* Handle pending selection requests. This can happen if Emacs
3962 enters a recursive edit inside a nested event loop (probably
3963 because the debugger opened) or someone called
3964 `read-char'. */
3965
3966 if (had_pending_selection_requests)
3967 x_handle_pending_selection_requests ();
3968#endif
3969
3969 if (CONSP (Vunread_command_events)) 3970 if (CONSP (Vunread_command_events))
3970 { 3971 {
3971 Lisp_Object first; 3972 Lisp_Object first;
@@ -4345,6 +4346,10 @@ kbd_buffer_get_event (KBOARD **kbp,
4345 ? movement_frame->last_mouse_device 4346 ? movement_frame->last_mouse_device
4346 : virtual_core_pointer_name); 4347 : virtual_core_pointer_name);
4347 } 4348 }
4349#ifdef HAVE_X_WINDOWS
4350 else if (had_pending_selection_requests)
4351 obj = Qnil;
4352#endif
4348 else 4353 else
4349 /* We were promised by the above while loop that there was 4354 /* We were promised by the above while loop that there was
4350 something for us to read! */ 4355 something for us to read! */
@@ -7241,7 +7246,10 @@ lucid_event_type_list_p (Lisp_Object object)
7241 If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal 7246 If READABLE_EVENTS_FILTER_EVENTS is set in FLAGS, ignore internal
7242 events (FOCUS_IN_EVENT). 7247 events (FOCUS_IN_EVENT).
7243 If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse 7248 If READABLE_EVENTS_IGNORE_SQUEEZABLES is set in FLAGS, ignore mouse
7244 movements and toolkit scroll bar thumb drags. */ 7249 movements and toolkit scroll bar thumb drags.
7250
7251 On X, this also returns if the selection event chain is full, since
7252 that's also "keyboard input". */
7245 7253
7246static bool 7254static bool
7247get_input_pending (int flags) 7255get_input_pending (int flags)
diff --git a/src/keyboard.h b/src/keyboard.h
index a0b7204fa2b..6ae2dc9c4c6 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -481,9 +481,6 @@ kbd_buffer_store_event_hold (struct input_event *event,
481 kbd_buffer_store_buffered_event ((union buffered_input_event *) event, 481 kbd_buffer_store_buffered_event ((union buffered_input_event *) event,
482 hold_quit); 482 hold_quit);
483} 483}
484#ifdef HAVE_X11
485extern void kbd_buffer_unget_event (struct selection_input_event *);
486#endif
487extern void poll_for_input_1 (void); 484extern void poll_for_input_1 (void);
488extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object, 485extern void show_help_echo (Lisp_Object, Lisp_Object, Lisp_Object,
489 Lisp_Object); 486 Lisp_Object);
diff --git a/src/xselect.c b/src/xselect.c
index 5f2a0cf56de..6e693c25884 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -116,92 +116,6 @@ selection_quantum (Display *display)
116 assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist) 116 assq_no_quit (selection_symbol, dpyinfo->terminal->Vselection_alist)
117 117
118 118
119/* Define a queue to save up SELECTION_REQUEST_EVENT events for later
120 handling. */
121
122struct selection_event_queue
123 {
124 struct selection_input_event event;
125 struct selection_event_queue *next;
126 };
127
128static struct selection_event_queue *selection_queue;
129
130/* Nonzero means queue up SELECTION_REQUEST_EVENT events. */
131
132static int x_queue_selection_requests;
133
134/* True if the input events are duplicates. */
135
136static bool
137selection_input_event_equal (struct selection_input_event *a,
138 struct selection_input_event *b)
139{
140 return (a->kind == b->kind && a->dpyinfo == b->dpyinfo
141 && a->requestor == b->requestor && a->selection == b->selection
142 && a->target == b->target && a->property == b->property
143 && a->time == b->time);
144}
145
146/* Queue up an SELECTION_REQUEST_EVENT *EVENT, to be processed later. */
147
148static void
149x_queue_event (struct selection_input_event *event)
150{
151 struct selection_event_queue *queue_tmp;
152
153 /* Don't queue repeated requests.
154 This only happens for large requests which uses the incremental protocol. */
155 for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next)
156 {
157 if (selection_input_event_equal (event, &queue_tmp->event))
158 {
159 TRACE1 ("DECLINE DUP SELECTION EVENT %p", queue_tmp);
160 x_decline_selection_request (event);
161 return;
162 }
163 }
164
165 queue_tmp = xmalloc (sizeof *queue_tmp);
166 TRACE1 ("QUEUE SELECTION EVENT %p", queue_tmp);
167 queue_tmp->event = *event;
168 queue_tmp->next = selection_queue;
169 selection_queue = queue_tmp;
170}
171
172/* Start queuing SELECTION_REQUEST_EVENT events. */
173
174static void
175x_start_queuing_selection_requests (void)
176{
177 if (x_queue_selection_requests)
178 emacs_abort ();
179
180 x_queue_selection_requests++;
181 TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests);
182}
183
184/* Stop queuing SELECTION_REQUEST_EVENT events. */
185
186static void
187x_stop_queuing_selection_requests (void)
188{
189 TRACE1 ("x_stop_queuing_selection_requests %d", x_queue_selection_requests);
190 --x_queue_selection_requests;
191
192 /* Take all the queued events and put them back
193 so that they get processed afresh. */
194
195 while (selection_queue != NULL)
196 {
197 struct selection_event_queue *queue_tmp = selection_queue;
198 TRACE1 ("RESTORE SELECTION EVENT %p", queue_tmp);
199 kbd_buffer_unget_event (&queue_tmp->event);
200 selection_queue = queue_tmp->next;
201 xfree (queue_tmp);
202 }
203}
204
205 119
206/* This converts a Lisp symbol to a server Atom, avoiding a server 120/* This converts a Lisp symbol to a server Atom, avoiding a server
207 roundtrip whenever possible. */ 121 roundtrip whenever possible. */
@@ -839,11 +753,6 @@ x_handle_selection_request (struct selection_input_event *event)
839 selection_request_dpyinfo = dpyinfo; 753 selection_request_dpyinfo = dpyinfo;
840 record_unwind_protect_void (x_selection_request_lisp_error); 754 record_unwind_protect_void (x_selection_request_lisp_error);
841 755
842 /* We might be able to handle nested x_handle_selection_requests,
843 but this is difficult to test, and seems unimportant. */
844 x_start_queuing_selection_requests ();
845 record_unwind_protect_void (x_stop_queuing_selection_requests);
846
847 TRACE2 ("x_handle_selection_request: selection=%s, target=%s", 756 TRACE2 ("x_handle_selection_request: selection=%s, target=%s",
848 SDATA (SYMBOL_NAME (selection_symbol)), 757 SDATA (SYMBOL_NAME (selection_symbol)),
849 SDATA (SYMBOL_NAME (target_symbol))); 758 SDATA (SYMBOL_NAME (target_symbol)));
@@ -1028,8 +937,6 @@ x_handle_selection_event (struct selection_input_event *event)
1028 TRACE0 ("x_handle_selection_event"); 937 TRACE0 ("x_handle_selection_event");
1029 if (event->kind != SELECTION_REQUEST_EVENT) 938 if (event->kind != SELECTION_REQUEST_EVENT)
1030 x_handle_selection_clear (event); 939 x_handle_selection_clear (event);
1031 else if (x_queue_selection_requests)
1032 x_queue_event (event);
1033 else 940 else
1034 x_handle_selection_request (event); 941 x_handle_selection_request (event);
1035} 942}
diff --git a/src/xterm.c b/src/xterm.c
index 4d8d7e80eb5..ffbd09d27f0 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -789,6 +789,21 @@ static int current_finish;
789static struct input_event *current_hold_quit; 789static struct input_event *current_hold_quit;
790#endif 790#endif
791 791
792struct x_selection_request_event
793{
794 /* The selection request event. */
795 struct selection_input_event se;
796
797 /* The next unprocessed selection request event. */
798 struct x_selection_request_event *next;
799};
800
801/* Chain of unprocessed selection request events. Used to handle
802 selection requests inside long-lasting modal event loops, such as
803 the drag-and-drop loop. */
804
805struct x_selection_request_event *pending_selection_requests;
806
792/* Compare two request serials A and B with OP, handling 807/* Compare two request serials A and B with OP, handling
793 wraparound. */ 808 wraparound. */
794#define X_COMPARE_SERIALS(a, op ,b) \ 809#define X_COMPARE_SERIALS(a, op ,b) \
@@ -1169,6 +1184,10 @@ static unsigned int x_dnd_keyboard_state;
1169 terminating DND as part of the display disconnect handler. */ 1184 terminating DND as part of the display disconnect handler. */
1170static sigjmp_buf x_dnd_disconnect_handler; 1185static sigjmp_buf x_dnd_disconnect_handler;
1171 1186
1187/* Whether or not the current invocation of handle_one_xevent
1188 happened inside the drag_and_drop event loop. */
1189static bool x_dnd_inside_handle_one_xevent;
1190
1172/* Structure describing a single window that can be the target of 1191/* Structure describing a single window that can be the target of
1173 drag-and-drop operations. */ 1192 drag-and-drop operations. */
1174struct x_client_list_window 1193struct x_client_list_window
@@ -10546,6 +10565,53 @@ x_next_event_from_any_display (XEvent *event)
10546 10565
10547#endif /* USE_X_TOOLKIT || USE_GTK */ 10566#endif /* USE_X_TOOLKIT || USE_GTK */
10548 10567
10568static void
10569x_handle_pending_selection_requests_1 (struct x_selection_request_event *tem)
10570{
10571 specpdl_ref count;
10572 struct selection_input_event se;
10573
10574 count = SPECPDL_INDEX ();
10575 se = tem->se;
10576
10577 record_unwind_protect_ptr (xfree, tem);
10578 x_handle_selection_event (&se);
10579 unbind_to (count, Qnil);
10580}
10581
10582/* Handle all pending selection request events from modal event
10583 loops. */
10584void
10585x_handle_pending_selection_requests (void)
10586{
10587 struct x_selection_request_event *tem;
10588
10589 while (pending_selection_requests)
10590 {
10591 tem = pending_selection_requests;
10592 pending_selection_requests = tem->next;
10593
10594 x_handle_pending_selection_requests_1 (tem);
10595 }
10596}
10597
10598static void
10599x_push_selection_request (struct selection_input_event *se)
10600{
10601 struct x_selection_request_event *tem;
10602
10603 tem = xmalloc (sizeof *tem);
10604 tem->next = pending_selection_requests;
10605 tem->se = *se;
10606 pending_selection_requests = tem;
10607}
10608
10609bool
10610x_detect_pending_selection_requests (void)
10611{
10612 return pending_selection_requests;
10613}
10614
10549/* This function is defined far away from the rest of the XDND code so 10615/* This function is defined far away from the rest of the XDND code so
10550 it can utilize `x_any_window_to_frame'. */ 10616 it can utilize `x_any_window_to_frame'. */
10551 10617
@@ -10841,6 +10907,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
10841 while (x_dnd_in_progress || x_dnd_waiting_for_finish) 10907 while (x_dnd_in_progress || x_dnd_waiting_for_finish)
10842 { 10908 {
10843 EVENT_INIT (hold_quit); 10909 EVENT_INIT (hold_quit);
10910
10844#ifdef USE_GTK 10911#ifdef USE_GTK
10845 current_finish = X_EVENT_NORMAL; 10912 current_finish = X_EVENT_NORMAL;
10846 current_hold_quit = &hold_quit; 10913 current_hold_quit = &hold_quit;
@@ -10849,6 +10916,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
10849#endif 10916#endif
10850 10917
10851 block_input (); 10918 block_input ();
10919 x_dnd_inside_handle_one_xevent = true;
10852#ifdef USE_GTK 10920#ifdef USE_GTK
10853 gtk_main_iteration (); 10921 gtk_main_iteration ();
10854#elif defined USE_X_TOOLKIT 10922#elif defined USE_X_TOOLKIT
@@ -10890,6 +10958,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
10890 current_count = -1; 10958 current_count = -1;
10891 current_hold_quit = NULL; 10959 current_hold_quit = NULL;
10892#endif 10960#endif
10961 x_dnd_inside_handle_one_xevent = false;
10893 10962
10894 /* The unblock_input below might try to read input, but 10963 /* The unblock_input below might try to read input, but
10895 XTread_socket does nothing inside a drag-and-drop event 10964 XTread_socket does nothing inside a drag-and-drop event
@@ -10942,29 +11011,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
10942 11011
10943 if (hold_quit.kind != NO_EVENT) 11012 if (hold_quit.kind != NO_EVENT)
10944 { 11013 {
10945 if (hold_quit.kind == SELECTION_REQUEST_EVENT)
10946 {
10947 /* It's not safe to run Lisp inside this function if
10948 x_dnd_in_progress and x_dnd_waiting_for_finish
10949 are unset, so push it back into the event queue. */
10950
10951 if (!x_dnd_in_progress && !x_dnd_waiting_for_finish)
10952 kbd_buffer_store_event (&hold_quit);
10953 else
10954 {
10955 x_dnd_old_window_attrs = root_window_attrs;
10956 x_dnd_unwind_flag = true;
10957
10958 ref = SPECPDL_INDEX ();
10959 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
10960 x_handle_selection_event ((struct selection_input_event *) &hold_quit);
10961 x_dnd_unwind_flag = false;
10962 unbind_to (ref, Qnil);
10963 }
10964
10965 continue;
10966 }
10967
10968 if (x_dnd_in_progress) 11014 if (x_dnd_in_progress)
10969 { 11015 {
10970 if (x_dnd_last_seen_window != None 11016 if (x_dnd_last_seen_window != None
@@ -11031,6 +11077,19 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
11031 quit (); 11077 quit ();
11032 } 11078 }
11033 11079
11080 if (pending_selection_requests
11081 && (x_dnd_in_progress || x_dnd_waiting_for_finish))
11082 {
11083 x_dnd_old_window_attrs = root_window_attrs;
11084 x_dnd_unwind_flag = true;
11085
11086 ref = SPECPDL_INDEX ();
11087 record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
11088 x_handle_pending_selection_requests ();
11089 x_dnd_unwind_flag = false;
11090 unbind_to (ref, Qnil);
11091 }
11092
11034#ifdef USE_GTK 11093#ifdef USE_GTK
11035 if (xg_pending_quit_event.kind != NO_EVENT) 11094 if (xg_pending_quit_event.kind != NO_EVENT)
11036 { 11095 {
@@ -15801,6 +15860,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
15801 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo; 15860 SELECTION_EVENT_DPYINFO (&inev.sie) = dpyinfo;
15802 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection; 15861 SELECTION_EVENT_SELECTION (&inev.sie) = eventp->selection;
15803 SELECTION_EVENT_TIME (&inev.sie) = eventp->time; 15862 SELECTION_EVENT_TIME (&inev.sie) = eventp->time;
15863
15864 if ((x_dnd_in_progress
15865 && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame))
15866 || (x_dnd_waiting_for_finish
15867 && dpyinfo->display == x_dnd_finish_display))
15868 {
15869 x_push_selection_request (&inev.sie);
15870 EVENT_INIT (inev.ie);
15871 }
15804 } 15872 }
15805 break; 15873 break;
15806 15874
@@ -15829,17 +15897,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
15829 || (x_dnd_waiting_for_finish 15897 || (x_dnd_waiting_for_finish
15830 && dpyinfo->display == x_dnd_finish_display)) 15898 && dpyinfo->display == x_dnd_finish_display))
15831 { 15899 {
15832#ifndef USE_GTK 15900 x_push_selection_request (&inev.sie);
15833 eassume (hold_quit);
15834#else
15835 /* If the debugger runs inside a selection converter, then
15836 xg_select can call handle_one_xevent with no
15837 hold_quit. */
15838 if (!hold_quit)
15839 goto done;
15840#endif
15841
15842 *hold_quit = inev.ie;
15843 EVENT_INIT (inev.ie); 15901 EVENT_INIT (inev.ie);
15844 } 15902 }
15845 15903
@@ -21120,12 +21178,16 @@ XTread_socket (struct terminal *terminal, struct input_event *hold_quit)
21120 read X events while the drag-and-drop event loop is in progress, 21178 read X events while the drag-and-drop event loop is in progress,
21121 things can go wrong very quick. 21179 things can go wrong very quick.
21122 21180
21181 When x_dnd_unwind_flag is true, the above doesn't apply, since
21182 the surrounding code takes special precautions to keep it safe.
21183
21123 That doesn't matter for events from displays other than the 21184 That doesn't matter for events from displays other than the
21124 display of the drag-and-drop operation, though. */ 21185 display of the drag-and-drop operation, though. */
21125 if ((x_dnd_in_progress 21186 if (!x_dnd_unwind_flag
21126 && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame)) 21187 && ((x_dnd_in_progress
21127 || (x_dnd_waiting_for_finish 21188 && dpyinfo->display == FRAME_X_DISPLAY (x_dnd_frame))
21128 && dpyinfo->display == x_dnd_finish_display)) 21189 || (x_dnd_waiting_for_finish
21190 && dpyinfo->display == x_dnd_finish_display)))
21129 return 0; 21191 return 0;
21130 21192
21131 block_input (); 21193 block_input ();
@@ -25840,6 +25902,7 @@ x_delete_display (struct x_display_info *dpyinfo)
25840 struct terminal *t; 25902 struct terminal *t;
25841 struct color_name_cache_entry *color_entry, *next_color_entry; 25903 struct color_name_cache_entry *color_entry, *next_color_entry;
25842 int i; 25904 int i;
25905 struct x_selection_request_event *ie, *last, *temp;
25843 25906
25844 /* Close all frames and delete the generic struct terminal for this 25907 /* Close all frames and delete the generic struct terminal for this
25845 X display. */ 25908 X display. */
@@ -25855,6 +25918,30 @@ x_delete_display (struct x_display_info *dpyinfo)
25855 break; 25918 break;
25856 } 25919 }
25857 25920
25921 /* Find any pending selection requests for this display and unchain
25922 them. */
25923
25924 last = NULL;
25925
25926 for (ie = pending_selection_requests; ie; ie = ie->next)
25927 {
25928 again:
25929
25930 if (SELECTION_EVENT_DPYINFO (&ie->se) == dpyinfo)
25931 {
25932 if (last)
25933 last->next = ie->next;
25934
25935 temp = ie;
25936 ie = ie->next;
25937 xfree (temp);
25938
25939 goto again;
25940 }
25941
25942 last = ie;
25943 }
25944
25858 if (next_noop_dpyinfo == dpyinfo) 25945 if (next_noop_dpyinfo == dpyinfo)
25859 next_noop_dpyinfo = dpyinfo->next; 25946 next_noop_dpyinfo = dpyinfo->next;
25860 25947
diff --git a/src/xterm.h b/src/xterm.h
index 878cb5fd87b..22c6b551766 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1455,6 +1455,8 @@ extern void x_xr_reset_ext_clip (struct frame *f);
1455extern void x_scroll_bar_configure (GdkEvent *); 1455extern void x_scroll_bar_configure (GdkEvent *);
1456#endif 1456#endif
1457 1457
1458extern void x_handle_pending_selection_requests (void);
1459extern bool x_detect_pending_selection_requests (void);
1458extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, 1460extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,
1459 Lisp_Object, Atom *, const char **, 1461 Lisp_Object, Atom *, const char **,
1460 size_t, bool, Atom *, int); 1462 size_t, bool, Atom *, int);