aboutsummaryrefslogtreecommitdiffstats
path: root/src/xselect.c
diff options
context:
space:
mode:
authorKim F. Storm2004-11-05 11:30:31 +0000
committerKim F. Storm2004-11-05 11:30:31 +0000
commitdd0fe424b211c09aae652be0179b6c1658d98776 (patch)
tree3ff106073e5eee5055b475046a47f9851693cc9c /src/xselect.c
parent87d78665be8f47e32768d30d84ce421dc216c9d0 (diff)
downloademacs-dd0fe424b211c09aae652be0179b6c1658d98776.tar.gz
emacs-dd0fe424b211c09aae652be0179b6c1658d98776.zip
* 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.
Diffstat (limited to 'src/xselect.c')
-rw-r--r--src/xselect.c162
1 files changed, 130 insertions, 32 deletions
diff --git a/src/xselect.c b/src/xselect.c
index 0d327da85a2..e3698bae9a6 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
@@ -171,6 +172,86 @@ static void lisp_data_to_selection_data ();
171static Lisp_Object selection_data_to_lisp_data (); 172static Lisp_Object selection_data_to_lisp_data ();
172static Lisp_Object x_get_window_property_as_lisp_data (); 173static 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
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
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
@@ -560,13 +641,10 @@ static struct prop_location *property_change_reply_object;
560static struct prop_location *property_change_wait_list; 641static struct prop_location *property_change_wait_list;
561 642
562static Lisp_Object 643static Lisp_Object
563queue_selection_requests_unwind (frame) 644queue_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
@@ -664,10 +742,10 @@ x_reply_selection_request (event, format, data, size, type)
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 */
@@ -701,6 +779,8 @@ x_reply_selection_request (event, format, data, size, type)
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)
@@ -774,7 +854,7 @@ x_reply_selection_request (event, format, data, size, type)
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
777void 857static void
778x_handle_selection_request (event) 858x_handle_selection_request (event)
779 struct input_event *event; 859 struct input_event *event;
780{ 860{
@@ -789,6 +869,8 @@ x_handle_selection_request (event)
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;
@@ -883,7 +965,7 @@ x_handle_selection_request (event)
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
886void 968static void
887x_handle_selection_clear (event) 969x_handle_selection_clear (event)
888 struct input_event *event; 970 struct input_event *event;
889{ 971{
@@ -896,6 +978,8 @@ x_handle_selection_clear (event)
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;
898 980
981 TRACE0 ("x_handle_selection_clear");
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;
@@ -964,6 +1048,24 @@ x_handle_selection_clear (event)
964 } 1048 }
965} 1049}
966 1050
1051void
1052x_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
@@ -1094,12 +1196,14 @@ unexpect_property_change (location)
1094/* Remove the property change expectation element for IDENTIFIER. */ 1196/* Remove the property change expectation element for IDENTIFIER. */
1095 1197
1096static Lisp_Object 1198static Lisp_Object
1097wait_for_property_change_unwind (identifierval) 1199wait_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
@@ -1112,18 +1216,17 @@ wait_for_property_change (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;
1116 1219
1117 tem = Fcons (Qnil, Qnil); 1220 if (property_change_reply_object)
1118 XSETCARFASTINT (tem, (EMACS_UINT)location >> 16); 1221 abort ();
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)
@@ -1154,7 +1257,8 @@ x_handle_property_notify (event)
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)
@@ -1170,11 +1274,6 @@ x_handle_property_notify (event)
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
@@ -1300,10 +1399,10 @@ x_get_foreign_selection (selection_symbol, target_type, time_stamp)
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
@@ -1459,10 +1558,10 @@ receive_incremental_selection (display, window, property, target_type,
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);
@@ -1492,7 +1591,6 @@ receive_incremental_selection (display, window, property, target_type,
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);