Mercurial > emacs
comparison src/xselect.c @ 57952:a6f82b95d10b
* xselect.c (struct selection_event_queue, selection_queue)
(x_queue_selection_requests, x_queue_event)
(x_start_queuing_selection_requests)
(x_stop_queuing_selection_requests): Add new queue for selection
input events to replace previous XEvent queue in xterm.c.
(queue_selection_requests_unwind): Adapt to new queue.
(x_reply_selection_request): Adapt to new queue. Unexpect
wait_object in case of x errors (memory leak).
(x_handle_selection_request, x_handle_selection_clear): Make static.
(x_handle_selection_event): New function. May queue selection events.
(wait_for_property_change_unwind): Use save_value instead of cons.
Clear property_change_reply_object.
(wait_for_property_change): Abort if already waiting.
Use save_value instead of cons for unwind data.
(x_handle_property_notify): Skip events already arrived, but don't
free them, as "arrived" field is checked by wait_for_property_change,
and it will be freed by unwind or explicit unexpect_property_change.
(x_get_foreign_selection): Add to new queue.
(receive_incremental_selection): Don't unexpect wait_object when done
as it has already been freed by previous wait_for_property_change.
author | Kim F. Storm <storm@cua.dk> |
---|---|
date | Fri, 05 Nov 2004 11:30:31 +0000 |
parents | 481911368712 |
children | b32fa5b7492d 7a0245dd1848 |
comparison
equal
deleted
inserted
replaced
57951:fbbae2d9a2f4 | 57952:a6f82b95d10b |
---|---|
30 #include "frame.h" /* Need this to get the X window of selected_frame */ | 30 #include "frame.h" /* Need this to get the X window of selected_frame */ |
31 #include "blockinput.h" | 31 #include "blockinput.h" |
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 |
38 struct prop_location; | 39 struct prop_location; |
39 | 40 |
169 | 170 |
170 static void lisp_data_to_selection_data (); | 171 static void lisp_data_to_selection_data (); |
171 static Lisp_Object selection_data_to_lisp_data (); | 172 static Lisp_Object selection_data_to_lisp_data (); |
172 static Lisp_Object x_get_window_property_as_lisp_data (); | 173 static Lisp_Object x_get_window_property_as_lisp_data (); |
173 | 174 |
175 | |
176 | |
177 /* Define a queue to save up SelectionRequest events for later handling. */ | |
178 | |
179 struct selection_event_queue | |
180 { | |
181 struct input_event event; | |
182 struct selection_event_queue *next; | |
183 }; | |
184 | |
185 static struct selection_event_queue *selection_queue; | |
186 | |
187 /* Nonzero means queue up certain events--don't process them yet. */ | |
188 | |
189 static int x_queue_selection_requests; | |
190 | |
191 /* Queue up an X event *EVENT, to be processed later. */ | |
192 | |
193 static void | |
194 x_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 | |
223 static void | |
224 x_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 | |
235 static void | |
236 x_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 | |
174 /* 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 |
175 roundtrip whenever possible. */ | 256 roundtrip whenever possible. */ |
176 | 257 |
177 static Atom | 258 static Atom |
178 symbol_to_x_atom (dpyinfo, display, sym) | 259 symbol_to_x_atom (dpyinfo, display, sym) |
558 static struct prop_location *property_change_reply_object; | 639 static struct prop_location *property_change_reply_object; |
559 | 640 |
560 static struct prop_location *property_change_wait_list; | 641 static struct prop_location *property_change_wait_list; |
561 | 642 |
562 static Lisp_Object | 643 static Lisp_Object |
563 queue_selection_requests_unwind (frame) | 644 queue_selection_requests_unwind (tem) |
564 Lisp_Object frame; | 645 Lisp_Object tem; |
565 { | 646 { |
566 FRAME_PTR f = XFRAME (frame); | 647 x_stop_queuing_selection_requests (); |
567 | |
568 if (! NILP (frame)) | |
569 x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f)); | |
570 return Qnil; | 648 return Qnil; |
571 } | 649 } |
572 | 650 |
573 /* Return some frame whose display info is DPYINFO. | 651 /* Return some frame whose display info is DPYINFO. |
574 Return nil if there is none. */ | 652 Return nil if there is none. */ |
662 /* If the display no longer has frames, we can't expect | 740 /* If the display no longer has frames, we can't expect |
663 to get many more selection requests from it, so don't | 741 to get many more selection requests from it, so don't |
664 bother trying to queue them. */ | 742 bother trying to queue them. */ |
665 if (!NILP (frame)) | 743 if (!NILP (frame)) |
666 { | 744 { |
667 x_start_queuing_selection_requests (display); | 745 x_start_queuing_selection_requests (); |
668 | 746 |
669 record_unwind_protect (queue_selection_requests_unwind, | 747 record_unwind_protect (queue_selection_requests_unwind, |
670 frame); | 748 Qnil); |
671 } | 749 } |
672 | 750 |
673 if (x_window_to_frame (dpyinfo, window)) /* #### debug */ | 751 if (x_window_to_frame (dpyinfo, window)) /* #### debug */ |
674 error ("Attempt to transfer an INCR to ourself!"); | 752 error ("Attempt to transfer an INCR to ourself!"); |
675 | 753 |
699 { | 777 { |
700 TRACE1 ("Waiting for ACK (deletion of %s)", | 778 TRACE1 ("Waiting for ACK (deletion of %s)", |
701 XGetAtomName (display, reply.property)); | 779 XGetAtomName (display, reply.property)); |
702 wait_for_property_change (wait_object); | 780 wait_for_property_change (wait_object); |
703 } | 781 } |
782 else | |
783 unexpect_property_change (wait_object); | |
704 | 784 |
705 TRACE0 ("Got ACK"); | 785 TRACE0 ("Got ACK"); |
706 while (bytes_remaining) | 786 while (bytes_remaining) |
707 { | 787 { |
708 int i = ((bytes_remaining < max_bytes) | 788 int i = ((bytes_remaining < max_bytes) |
772 } | 852 } |
773 | 853 |
774 /* Handle a SelectionRequest event EVENT. | 854 /* Handle a SelectionRequest event EVENT. |
775 This is called from keyboard.c when such an event is found in the queue. */ | 855 This is called from keyboard.c when such an event is found in the queue. */ |
776 | 856 |
777 void | 857 static void |
778 x_handle_selection_request (event) | 858 x_handle_selection_request (event) |
779 struct input_event *event; | 859 struct input_event *event; |
780 { | 860 { |
781 struct gcpro gcpro1, gcpro2, gcpro3; | 861 struct gcpro gcpro1, gcpro2, gcpro3; |
782 Lisp_Object local_selection_data; | 862 Lisp_Object local_selection_data; |
787 Lisp_Object successful_p; | 867 Lisp_Object successful_p; |
788 int count; | 868 int count; |
789 struct x_display_info *dpyinfo | 869 struct x_display_info *dpyinfo |
790 = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event)); | 870 = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event)); |
791 | 871 |
872 TRACE0 ("x_handle_selection_request"); | |
873 | |
792 local_selection_data = Qnil; | 874 local_selection_data = Qnil; |
793 target_symbol = Qnil; | 875 target_symbol = Qnil; |
794 converted_selection = Qnil; | 876 converted_selection = Qnil; |
795 successful_p = Qnil; | 877 successful_p = Qnil; |
796 | 878 |
881 | 963 |
882 /* Handle a SelectionClear event EVENT, which indicates that some | 964 /* Handle a SelectionClear event EVENT, which indicates that some |
883 client cleared out our previously asserted selection. | 965 client cleared out our previously asserted selection. |
884 This is called from keyboard.c when such an event is found in the queue. */ | 966 This is called from keyboard.c when such an event is found in the queue. */ |
885 | 967 |
886 void | 968 static void |
887 x_handle_selection_clear (event) | 969 x_handle_selection_clear (event) |
888 struct input_event *event; | 970 struct input_event *event; |
889 { | 971 { |
890 Display *display = SELECTION_EVENT_DISPLAY (event); | 972 Display *display = SELECTION_EVENT_DISPLAY (event); |
891 Atom selection = SELECTION_EVENT_SELECTION (event); | 973 Atom selection = SELECTION_EVENT_SELECTION (event); |
893 | 975 |
894 Lisp_Object selection_symbol, local_selection_data; | 976 Lisp_Object selection_symbol, local_selection_data; |
895 Time local_selection_time; | 977 Time local_selection_time; |
896 struct x_display_info *dpyinfo = x_display_info_for_display (display); | 978 struct x_display_info *dpyinfo = x_display_info_for_display (display); |
897 struct x_display_info *t_dpyinfo; | 979 struct x_display_info *t_dpyinfo; |
980 | |
981 TRACE0 ("x_handle_selection_clear"); | |
898 | 982 |
899 /* If the new selection owner is also Emacs, | 983 /* If the new selection owner is also Emacs, |
900 don't clear the new selection. */ | 984 don't clear the new selection. */ |
901 BLOCK_INPUT; | 985 BLOCK_INPUT; |
902 /* Check each display on the same terminal, | 986 /* Check each display on the same terminal, |
962 redisplay_preserve_echo_area (20); | 1046 redisplay_preserve_echo_area (20); |
963 } | 1047 } |
964 } | 1048 } |
965 } | 1049 } |
966 | 1050 |
1051 void | |
1052 x_handle_selection_event (event) | |
1053 struct input_event *event; | |
1054 { | |
1055 TRACE0 ("x_handle_selection_event"); | |
1056 | |
1057 if (event->kind == SELECTION_REQUEST_EVENT) | |
1058 { | |
1059 if (x_queue_selection_requests) | |
1060 x_queue_event (event); | |
1061 else | |
1062 x_handle_selection_request (event); | |
1063 } | |
1064 else | |
1065 x_handle_selection_clear (event); | |
1066 } | |
1067 | |
1068 | |
967 /* Clear all selections that were made from frame F. | 1069 /* Clear all selections that were made from frame F. |
968 We do this when about to delete a frame. */ | 1070 We do this when about to delete a frame. */ |
969 | 1071 |
970 void | 1072 void |
971 x_clear_frame_selections (f) | 1073 x_clear_frame_selections (f) |
1092 } | 1194 } |
1093 | 1195 |
1094 /* Remove the property change expectation element for IDENTIFIER. */ | 1196 /* Remove the property change expectation element for IDENTIFIER. */ |
1095 | 1197 |
1096 static Lisp_Object | 1198 static Lisp_Object |
1097 wait_for_property_change_unwind (identifierval) | 1199 wait_for_property_change_unwind (loc) |
1098 Lisp_Object identifierval; | 1200 Lisp_Object loc; |
1099 { | 1201 { |
1100 unexpect_property_change ((struct prop_location *) | 1202 struct prop_location *location = XSAVE_VALUE (loc)->pointer; |
1101 (XFASTINT (XCAR (identifierval)) << 16 | 1203 |
1102 | XFASTINT (XCDR (identifierval)))); | 1204 unexpect_property_change (location); |
1205 if (location == property_change_reply_object) | |
1206 property_change_reply_object = 0; | |
1103 return Qnil; | 1207 return Qnil; |
1104 } | 1208 } |
1105 | 1209 |
1106 /* Actually wait for a property change. | 1210 /* Actually wait for a property change. |
1107 IDENTIFIER should be the value that expect_property_change returned. */ | 1211 IDENTIFIER should be the value that expect_property_change returned. */ |
1110 wait_for_property_change (location) | 1214 wait_for_property_change (location) |
1111 struct prop_location *location; | 1215 struct prop_location *location; |
1112 { | 1216 { |
1113 int secs, usecs; | 1217 int secs, usecs; |
1114 int count = SPECPDL_INDEX (); | 1218 int count = SPECPDL_INDEX (); |
1115 Lisp_Object tem; | 1219 |
1116 | 1220 if (property_change_reply_object) |
1117 tem = Fcons (Qnil, Qnil); | 1221 abort (); |
1118 XSETCARFASTINT (tem, (EMACS_UINT)location >> 16); | |
1119 XSETCDRFASTINT (tem, (EMACS_UINT)location & 0xffff); | |
1120 | 1222 |
1121 /* Make sure to do unexpect_property_change if we quit or err. */ | 1223 /* Make sure to do unexpect_property_change if we quit or err. */ |
1122 record_unwind_protect (wait_for_property_change_unwind, tem); | 1224 record_unwind_protect (wait_for_property_change_unwind, |
1225 make_save_value (location, 0)); | |
1123 | 1226 |
1124 XSETCAR (property_change_reply, Qnil); | 1227 XSETCAR (property_change_reply, Qnil); |
1125 | |
1126 property_change_reply_object = location; | 1228 property_change_reply_object = location; |
1229 | |
1127 /* If the event we are waiting for arrives beyond here, it will set | 1230 /* If the event we are waiting for arrives beyond here, it will set |
1128 property_change_reply, because property_change_reply_object says so. */ | 1231 property_change_reply, because property_change_reply_object says so. */ |
1129 if (! location->arrived) | 1232 if (! location->arrived) |
1130 { | 1233 { |
1131 secs = x_selection_timeout / 1000; | 1234 secs = x_selection_timeout / 1000; |
1152 { | 1255 { |
1153 struct prop_location *prev = 0, *rest = property_change_wait_list; | 1256 struct prop_location *prev = 0, *rest = property_change_wait_list; |
1154 | 1257 |
1155 while (rest) | 1258 while (rest) |
1156 { | 1259 { |
1157 if (rest->property == event->atom | 1260 if (!rest->arrived |
1261 && rest->property == event->atom | |
1158 && rest->window == event->window | 1262 && rest->window == event->window |
1159 && rest->display == event->display | 1263 && rest->display == event->display |
1160 && rest->desired_state == event->state) | 1264 && rest->desired_state == event->state) |
1161 { | 1265 { |
1162 TRACE2 ("Expected %s of property %s", | 1266 TRACE2 ("Expected %s of property %s", |
1168 /* If this is the one wait_for_property_change is waiting for, | 1272 /* If this is the one wait_for_property_change is waiting for, |
1169 tell it to wake up. */ | 1273 tell it to wake up. */ |
1170 if (rest == property_change_reply_object) | 1274 if (rest == property_change_reply_object) |
1171 XSETCAR (property_change_reply, Qt); | 1275 XSETCAR (property_change_reply, Qt); |
1172 | 1276 |
1173 if (prev) | |
1174 prev->next = rest->next; | |
1175 else | |
1176 property_change_wait_list = rest->next; | |
1177 xfree (rest); | |
1178 return; | 1277 return; |
1179 } | 1278 } |
1180 | 1279 |
1181 prev = rest; | 1280 prev = rest; |
1182 rest = rest->next; | 1281 rest = rest->next; |
1298 /* If the display no longer has frames, we can't expect | 1397 /* If the display no longer has frames, we can't expect |
1299 to get many more selection requests from it, so don't | 1398 to get many more selection requests from it, so don't |
1300 bother trying to queue them. */ | 1399 bother trying to queue them. */ |
1301 if (!NILP (frame)) | 1400 if (!NILP (frame)) |
1302 { | 1401 { |
1303 x_start_queuing_selection_requests (display); | 1402 x_start_queuing_selection_requests (); |
1304 | 1403 |
1305 record_unwind_protect (queue_selection_requests_unwind, | 1404 record_unwind_protect (queue_selection_requests_unwind, |
1306 frame); | 1405 Qnil); |
1307 } | 1406 } |
1308 UNBLOCK_INPUT; | 1407 UNBLOCK_INPUT; |
1309 | 1408 |
1310 /* This allows quits. Also, don't wait forever. */ | 1409 /* This allows quits. Also, don't wait forever. */ |
1311 secs = x_selection_timeout / 1000; | 1410 secs = x_selection_timeout / 1000; |
1457 We are done when the sender places a property of length 0. | 1556 We are done when the sender places a property of length 0. |
1458 */ | 1557 */ |
1459 BLOCK_INPUT; | 1558 BLOCK_INPUT; |
1460 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); | 1559 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); |
1461 TRACE1 (" Delete property %s", | 1560 TRACE1 (" Delete property %s", |
1462 SDATA (XSYMBOL (x_atom_to_symbol (display, property))->xname)); | 1561 SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property)))); |
1463 XDeleteProperty (display, window, property); | 1562 XDeleteProperty (display, window, property); |
1464 TRACE1 (" Expect new value of property %s", | 1563 TRACE1 (" Expect new value of property %s", |
1465 SDATA (XSYMBOL (x_atom_to_symbol (display, property))->xname)); | 1564 SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property)))); |
1466 wait_object = expect_property_change (display, window, property, | 1565 wait_object = expect_property_change (display, window, property, |
1467 PropertyNewValue); | 1566 PropertyNewValue); |
1468 XFlush (display); | 1567 XFlush (display); |
1469 UNBLOCK_INPUT; | 1568 UNBLOCK_INPUT; |
1470 | 1569 |
1490 { | 1589 { |
1491 TRACE0 ("Done reading incrementally"); | 1590 TRACE0 ("Done reading incrementally"); |
1492 | 1591 |
1493 if (! waiting_for_other_props_on_window (display, window)) | 1592 if (! waiting_for_other_props_on_window (display, window)) |
1494 XSelectInput (display, window, STANDARD_EVENT_SET); | 1593 XSelectInput (display, window, STANDARD_EVENT_SET); |
1495 unexpect_property_change (wait_object); | |
1496 /* Use xfree, not XFree, because x_get_window_property | 1594 /* Use xfree, not XFree, because x_get_window_property |
1497 calls xmalloc itself. */ | 1595 calls xmalloc itself. */ |
1498 if (tmp_data) xfree (tmp_data); | 1596 if (tmp_data) xfree (tmp_data); |
1499 break; | 1597 break; |
1500 } | 1598 } |