aboutsummaryrefslogtreecommitdiffstats
path: root/src/xselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xselect.c')
-rw-r--r--src/xselect.c176
1 files changed, 144 insertions, 32 deletions
diff --git a/src/xselect.c b/src/xselect.c
index 65cb584410e..06f4bfbd2a1 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -32,6 +32,7 @@ Boston, MA 02111-1307, USA. */
32#include "buffer.h" 32#include "buffer.h"
33#include "process.h" 33#include "process.h"
34#include "termhooks.h" 34#include "termhooks.h"
35#include "keyboard.h"
35 36
36#include <X11/Xproto.h> 37#include <X11/Xproto.h>
37 38
@@ -85,10 +86,13 @@ static void initialize_cut_buffers P_ ((Display *, Window));
85 fprintf (stderr, "%d: " fmt "\n", getpid (), a0) 86 fprintf (stderr, "%d: " fmt "\n", getpid (), a0)
86#define TRACE2(fmt, a0, a1) \ 87#define TRACE2(fmt, a0, a1) \
87 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1) 88 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1)
89#define TRACE3(fmt, a0, a1, a2) \
90 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1, a2)
88#else 91#else
89#define TRACE0(fmt) (void) 0 92#define TRACE0(fmt) (void) 0
90#define TRACE1(fmt, a0) (void) 0 93#define TRACE1(fmt, a0) (void) 0
91#define TRACE2(fmt, a0, a1) (void) 0 94#define TRACE2(fmt, a0, a1) (void) 0
95#define TRACE3(fmt, a0, a1) (void) 0
92#endif 96#endif
93 97
94 98
@@ -168,6 +172,86 @@ static void lisp_data_to_selection_data ();
168static Lisp_Object selection_data_to_lisp_data (); 172static Lisp_Object selection_data_to_lisp_data ();
169static Lisp_Object x_get_window_property_as_lisp_data (); 173static Lisp_Object x_get_window_property_as_lisp_data ();
170 174
175
176
177/* Define a queue to save up SelectionRequest events for later handling. */
178
179struct selection_event_queue
180 {
181 struct input_event event;
182 struct selection_event_queue *next;
183 };
184
185static struct selection_event_queue *selection_queue;
186
187/* Nonzero means queue up certain events--don't process them yet. */
188
189static int x_queue_selection_requests;
190
191/* Queue up an X event *EVENT, to be processed later. */
192
193static void
194x_queue_event (event)
195 struct input_event *event;
196{
197 struct selection_event_queue *queue_tmp;
198
199 /* Don't queue repeated requests */
200 for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next)
201 {
202 if (!bcmp (&queue_tmp->event, event, sizeof (*event)))
203 {
204 TRACE1 ("IGNORE DUP SELECTION EVENT %08x", (unsigned long)queue_tmp);
205 return;
206 }
207 }
208
209 queue_tmp
210 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
211
212 if (queue_tmp != NULL)
213 {
214 TRACE1 ("QUEUE SELECTION EVENT %08x", (unsigned long)queue_tmp);
215 queue_tmp->event = *event;
216 queue_tmp->next = selection_queue;
217 selection_queue = queue_tmp;
218 }
219}
220
221/* Start queuing SelectionRequest events. */
222
223static void
224x_start_queuing_selection_requests ()
225{
226 if (x_queue_selection_requests)
227 abort ();
228
229 x_queue_selection_requests++;
230 TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests);
231}
232
233/* Stop queuing SelectionRequest events. */
234
235static void
236x_stop_queuing_selection_requests ()
237{
238 TRACE1 ("x_stop_queuing_selection_requests %d", x_queue_selection_requests);
239 --x_queue_selection_requests;
240
241 /* Take all the queued events and put them back
242 so that they get processed afresh. */
243
244 while (selection_queue != NULL)
245 {
246 struct selection_event_queue *queue_tmp = selection_queue;
247 TRACE1 ("RESTORE SELECTION EVENT %08x", (unsigned long)queue_tmp);
248 kbd_buffer_unget_event (&queue_tmp->event);
249 selection_queue = queue_tmp->next;
250 xfree ((char *)queue_tmp);
251 }
252}
253
254
171/* This converts a Lisp symbol to a server Atom, avoiding a server 255/* This converts a Lisp symbol to a server Atom, avoiding a server
172 roundtrip whenever possible. */ 256 roundtrip whenever possible. */
173 257
@@ -564,13 +648,10 @@ static struct prop_location *property_change_reply_object;
564static struct prop_location *property_change_wait_list; 648static struct prop_location *property_change_wait_list;
565 649
566static Lisp_Object 650static Lisp_Object
567queue_selection_requests_unwind (frame) 651queue_selection_requests_unwind (tem)
568 Lisp_Object frame; 652 Lisp_Object tem;
569{ 653{
570 FRAME_PTR f = XFRAME (frame); 654 x_stop_queuing_selection_requests ();
571
572 if (! NILP (frame))
573 x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f));
574 return Qnil; 655 return Qnil;
575} 656}
576 657
@@ -631,6 +712,17 @@ x_reply_selection_request (event, format, data, size, type)
631 BLOCK_INPUT; 712 BLOCK_INPUT;
632 count = x_catch_errors (display); 713 count = x_catch_errors (display);
633 714
715#ifdef TRACE_SELECTION
716 {
717 static int cnt;
718 char *sel = XGetAtomName (display, reply.selection);
719 char *tgt = XGetAtomName (display, reply.target);
720 TRACE3 ("%s, target %s (%d)", sel, tgt, ++cnt);
721 if (sel) XFree (sel);
722 if (tgt) XFree (tgt);
723 }
724#endif /* TRACE_SELECTION */
725
634 /* Store the data on the requested property. 726 /* Store the data on the requested property.
635 If the selection is large, only store the first N bytes of it. 727 If the selection is large, only store the first N bytes of it.
636 */ 728 */
@@ -658,10 +750,10 @@ x_reply_selection_request (event, format, data, size, type)
658 bother trying to queue them. */ 750 bother trying to queue them. */
659 if (!NILP (frame)) 751 if (!NILP (frame))
660 { 752 {
661 x_start_queuing_selection_requests (display); 753 x_start_queuing_selection_requests ();
662 754
663 record_unwind_protect (queue_selection_requests_unwind, 755 record_unwind_protect (queue_selection_requests_unwind,
664 frame); 756 Qnil);
665 } 757 }
666 758
667 if (x_window_to_frame (dpyinfo, window)) /* #### debug */ 759 if (x_window_to_frame (dpyinfo, window)) /* #### debug */
@@ -695,6 +787,8 @@ x_reply_selection_request (event, format, data, size, type)
695 XGetAtomName (display, reply.property)); 787 XGetAtomName (display, reply.property));
696 wait_for_property_change (wait_object); 788 wait_for_property_change (wait_object);
697 } 789 }
790 else
791 unexpect_property_change (wait_object);
698 792
699 TRACE0 ("Got ACK"); 793 TRACE0 ("Got ACK");
700 while (bytes_remaining) 794 while (bytes_remaining)
@@ -768,7 +862,7 @@ x_reply_selection_request (event, format, data, size, type)
768/* Handle a SelectionRequest event EVENT. 862/* Handle a SelectionRequest event EVENT.
769 This is called from keyboard.c when such an event is found in the queue. */ 863 This is called from keyboard.c when such an event is found in the queue. */
770 864
771void 865static void
772x_handle_selection_request (event) 866x_handle_selection_request (event)
773 struct input_event *event; 867 struct input_event *event;
774{ 868{
@@ -783,6 +877,8 @@ x_handle_selection_request (event)
783 struct x_display_info *dpyinfo 877 struct x_display_info *dpyinfo
784 = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event)); 878 = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event));
785 879
880 TRACE0 ("x_handle_selection_request");
881
786 local_selection_data = Qnil; 882 local_selection_data = Qnil;
787 target_symbol = Qnil; 883 target_symbol = Qnil;
788 converted_selection = Qnil; 884 converted_selection = Qnil;
@@ -877,7 +973,7 @@ x_handle_selection_request (event)
877 client cleared out our previously asserted selection. 973 client cleared out our previously asserted selection.
878 This is called from keyboard.c when such an event is found in the queue. */ 974 This is called from keyboard.c when such an event is found in the queue. */
879 975
880void 976static void
881x_handle_selection_clear (event) 977x_handle_selection_clear (event)
882 struct input_event *event; 978 struct input_event *event;
883{ 979{
@@ -890,6 +986,8 @@ x_handle_selection_clear (event)
890 struct x_display_info *dpyinfo = x_display_info_for_display (display); 986 struct x_display_info *dpyinfo = x_display_info_for_display (display);
891 struct x_display_info *t_dpyinfo; 987 struct x_display_info *t_dpyinfo;
892 988
989 TRACE0 ("x_handle_selection_clear");
990
893 /* If the new selection owner is also Emacs, 991 /* If the new selection owner is also Emacs,
894 don't clear the new selection. */ 992 don't clear the new selection. */
895 BLOCK_INPUT; 993 BLOCK_INPUT;
@@ -958,6 +1056,24 @@ x_handle_selection_clear (event)
958 } 1056 }
959} 1057}
960 1058
1059void
1060x_handle_selection_event (event)
1061 struct input_event *event;
1062{
1063 TRACE0 ("x_handle_selection_event");
1064
1065 if (event->kind == SELECTION_REQUEST_EVENT)
1066 {
1067 if (x_queue_selection_requests)
1068 x_queue_event (event);
1069 else
1070 x_handle_selection_request (event);
1071 }
1072 else
1073 x_handle_selection_clear (event);
1074}
1075
1076
961/* Clear all selections that were made from frame F. 1077/* Clear all selections that were made from frame F.
962 We do this when about to delete a frame. */ 1078 We do this when about to delete a frame. */
963 1079
@@ -1088,12 +1204,14 @@ unexpect_property_change (location)
1088/* Remove the property change expectation element for IDENTIFIER. */ 1204/* Remove the property change expectation element for IDENTIFIER. */
1089 1205
1090static Lisp_Object 1206static Lisp_Object
1091wait_for_property_change_unwind (identifierval) 1207wait_for_property_change_unwind (loc)
1092 Lisp_Object identifierval; 1208 Lisp_Object loc;
1093{ 1209{
1094 unexpect_property_change ((struct prop_location *) 1210 struct prop_location *location = XSAVE_VALUE (loc)->pointer;
1095 (XFASTINT (XCAR (identifierval)) << 16 1211
1096 | XFASTINT (XCDR (identifierval)))); 1212 unexpect_property_change (location);
1213 if (location == property_change_reply_object)
1214 property_change_reply_object = 0;
1097 return Qnil; 1215 return Qnil;
1098} 1216}
1099 1217
@@ -1106,18 +1224,17 @@ wait_for_property_change (location)
1106{ 1224{
1107 int secs, usecs; 1225 int secs, usecs;
1108 int count = SPECPDL_INDEX (); 1226 int count = SPECPDL_INDEX ();
1109 Lisp_Object tem;
1110 1227
1111 tem = Fcons (Qnil, Qnil); 1228 if (property_change_reply_object)
1112 XSETCARFASTINT (tem, (EMACS_UINT)location >> 16); 1229 abort ();
1113 XSETCDRFASTINT (tem, (EMACS_UINT)location & 0xffff);
1114 1230
1115 /* Make sure to do unexpect_property_change if we quit or err. */ 1231 /* Make sure to do unexpect_property_change if we quit or err. */
1116 record_unwind_protect (wait_for_property_change_unwind, tem); 1232 record_unwind_protect (wait_for_property_change_unwind,
1233 make_save_value (location, 0));
1117 1234
1118 XSETCAR (property_change_reply, Qnil); 1235 XSETCAR (property_change_reply, Qnil);
1119
1120 property_change_reply_object = location; 1236 property_change_reply_object = location;
1237
1121 /* If the event we are waiting for arrives beyond here, it will set 1238 /* If the event we are waiting for arrives beyond here, it will set
1122 property_change_reply, because property_change_reply_object says so. */ 1239 property_change_reply, because property_change_reply_object says so. */
1123 if (! location->arrived) 1240 if (! location->arrived)
@@ -1148,7 +1265,8 @@ x_handle_property_notify (event)
1148 1265
1149 while (rest) 1266 while (rest)
1150 { 1267 {
1151 if (rest->property == event->atom 1268 if (!rest->arrived
1269 && rest->property == event->atom
1152 && rest->window == event->window 1270 && rest->window == event->window
1153 && rest->display == event->display 1271 && rest->display == event->display
1154 && rest->desired_state == event->state) 1272 && rest->desired_state == event->state)
@@ -1164,11 +1282,6 @@ x_handle_property_notify (event)
1164 if (rest == property_change_reply_object) 1282 if (rest == property_change_reply_object)
1165 XSETCAR (property_change_reply, Qt); 1283 XSETCAR (property_change_reply, Qt);
1166 1284
1167 if (prev)
1168 prev->next = rest->next;
1169 else
1170 property_change_wait_list = rest->next;
1171 xfree (rest);
1172 return; 1285 return;
1173 } 1286 }
1174 1287
@@ -1303,10 +1416,10 @@ x_get_foreign_selection (selection_symbol, target_type, time_stamp)
1303 bother trying to queue them. */ 1416 bother trying to queue them. */
1304 if (!NILP (frame)) 1417 if (!NILP (frame))
1305 { 1418 {
1306 x_start_queuing_selection_requests (display); 1419 x_start_queuing_selection_requests ();
1307 1420
1308 record_unwind_protect (queue_selection_requests_unwind, 1421 record_unwind_protect (queue_selection_requests_unwind,
1309 frame); 1422 Qnil);
1310 } 1423 }
1311 UNBLOCK_INPUT; 1424 UNBLOCK_INPUT;
1312 1425
@@ -1462,10 +1575,10 @@ receive_incremental_selection (display, window, property, target_type,
1462 BLOCK_INPUT; 1575 BLOCK_INPUT;
1463 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); 1576 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
1464 TRACE1 (" Delete property %s", 1577 TRACE1 (" Delete property %s",
1465 XSYMBOL (x_atom_to_symbol (display, property))->name->data); 1578 SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
1466 XDeleteProperty (display, window, property); 1579 XDeleteProperty (display, window, property);
1467 TRACE1 (" Expect new value of property %s", 1580 TRACE1 (" Expect new value of property %s",
1468 XSYMBOL (x_atom_to_symbol (display, property))->name->data); 1581 SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
1469 wait_object = expect_property_change (display, window, property, 1582 wait_object = expect_property_change (display, window, property,
1470 PropertyNewValue); 1583 PropertyNewValue);
1471 XFlush (display); 1584 XFlush (display);
@@ -1495,7 +1608,6 @@ receive_incremental_selection (display, window, property, target_type,
1495 1608
1496 if (! waiting_for_other_props_on_window (display, window)) 1609 if (! waiting_for_other_props_on_window (display, window))
1497 XSelectInput (display, window, STANDARD_EVENT_SET); 1610 XSelectInput (display, window, STANDARD_EVENT_SET);
1498 unexpect_property_change (wait_object);
1499 /* Use xfree, not XFree, because x_get_window_property 1611 /* Use xfree, not XFree, because x_get_window_property
1500 calls xmalloc itself. */ 1612 calls xmalloc itself. */
1501 if (tmp_data) xfree (tmp_data); 1613 if (tmp_data) xfree (tmp_data);