aboutsummaryrefslogtreecommitdiffstats
path: root/src/xselect.c
diff options
context:
space:
mode:
authorMiles Bader2004-11-12 02:53:04 +0000
committerMiles Bader2004-11-12 02:53:04 +0000
commit8b7e837d9c3266e775142a4865845b3d2a8b60aa (patch)
treed1468612ab319b665728b9ebf94dbc0c0d4c20fc /src/xselect.c
parentd1a3e560ff62e047d9fa8e8b3b1bc1e56e104c26 (diff)
parente22c7647c7ff33c846132f3d2877ac436b8b47e6 (diff)
downloademacs-8b7e837d9c3266e775142a4865845b3d2a8b60aa.tar.gz
emacs-8b7e837d9c3266e775142a4865845b3d2a8b60aa.zip
Revision: miles@gnu.org--gnu-2004/emacs--unicode--0--patch-70
Merge from emacs--cvs-trunk--0 Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-669 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-678 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-679 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-680 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-688 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-689 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-690 - miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-691 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-69 Merge from emacs--cvs-trunk--0 * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-70 - miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-71 Update from CVS
Diffstat (limited to 'src/xselect.c')
-rw-r--r--src/xselect.c189
1 files changed, 157 insertions, 32 deletions
diff --git a/src/xselect.c b/src/xselect.c
index 35f4586b754..c89347be2cd 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -24,6 +24,14 @@ Boston, MA 02111-1307, USA. */
24 24
25#include <config.h> 25#include <config.h>
26#include <stdio.h> /* termhooks.h needs this */ 26#include <stdio.h> /* termhooks.h needs this */
27
28#ifdef HAVE_SYS_TYPES_H
29#include <sys/types.h>
30#endif
31#ifdef HAVE_UNISTD_H
32#include <unistd.h>
33#endif
34
27#include "lisp.h" 35#include "lisp.h"
28#include "xterm.h" /* for all of the X includes */ 36#include "xterm.h" /* for all of the X includes */
29#include "dispextern.h" /* frame.h seems to want this */ 37#include "dispextern.h" /* frame.h seems to want this */
@@ -32,6 +40,7 @@ Boston, MA 02111-1307, USA. */
32#include "buffer.h" 40#include "buffer.h"
33#include "process.h" 41#include "process.h"
34#include "termhooks.h" 42#include "termhooks.h"
43#include "keyboard.h"
35 44
36#include <X11/Xproto.h> 45#include <X11/Xproto.h>
37 46
@@ -85,10 +94,13 @@ static void initialize_cut_buffers P_ ((Display *, Window));
85 fprintf (stderr, "%d: " fmt "\n", getpid (), a0) 94 fprintf (stderr, "%d: " fmt "\n", getpid (), a0)
86#define TRACE2(fmt, a0, a1) \ 95#define TRACE2(fmt, a0, a1) \
87 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1) 96 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1)
97#define TRACE3(fmt, a0, a1, a2) \
98 fprintf (stderr, "%d: " fmt "\n", getpid (), a0, a1, a2)
88#else 99#else
89#define TRACE0(fmt) (void) 0 100#define TRACE0(fmt) (void) 0
90#define TRACE1(fmt, a0) (void) 0 101#define TRACE1(fmt, a0) (void) 0
91#define TRACE2(fmt, a0, a1) (void) 0 102#define TRACE2(fmt, a0, a1) (void) 0
103#define TRACE3(fmt, a0, a1) (void) 0
92#endif 104#endif
93 105
94 106
@@ -168,6 +180,89 @@ static void lisp_data_to_selection_data ();
168static Lisp_Object selection_data_to_lisp_data (); 180static Lisp_Object selection_data_to_lisp_data ();
169static Lisp_Object x_get_window_property_as_lisp_data (); 181static Lisp_Object x_get_window_property_as_lisp_data ();
170 182
183
184
185/* Define a queue to save up SELECTION_REQUEST_EVENT events for later
186 handling. */
187
188struct selection_event_queue
189 {
190 struct input_event event;
191 struct selection_event_queue *next;
192 };
193
194static struct selection_event_queue *selection_queue;
195
196/* Nonzero means queue up SELECTION_REQUEST_EVENT events. */
197
198static int x_queue_selection_requests;
199
200/* Queue up an SELECTION_REQUEST_EVENT *EVENT, to be processed later. */
201
202static void
203x_queue_event (event)
204 struct input_event *event;
205{
206 struct selection_event_queue *queue_tmp;
207
208 /* Don't queue repeated requests.
209 This only happens for large requests which uses the incremental protocol. */
210 for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next)
211 {
212 if (!bcmp (&queue_tmp->event, event, sizeof (*event)))
213 {
214 TRACE1 ("DECLINE DUP SELECTION EVENT %08lx", (unsigned long)queue_tmp);
215 x_decline_selection_request (event);
216 return;
217 }
218 }
219
220 queue_tmp
221 = (struct selection_event_queue *) xmalloc (sizeof (struct selection_event_queue));
222
223 if (queue_tmp != NULL)
224 {
225 TRACE1 ("QUEUE SELECTION EVENT %08lx", (unsigned long)queue_tmp);
226 queue_tmp->event = *event;
227 queue_tmp->next = selection_queue;
228 selection_queue = queue_tmp;
229 }
230}
231
232/* Start queuing SELECTION_REQUEST_EVENT events. */
233
234static void
235x_start_queuing_selection_requests ()
236{
237 if (x_queue_selection_requests)
238 abort ();
239
240 x_queue_selection_requests++;
241 TRACE1 ("x_start_queuing_selection_requests %d", x_queue_selection_requests);
242}
243
244/* Stop queuing SELECTION_REQUEST_EVENT events. */
245
246static void
247x_stop_queuing_selection_requests ()
248{
249 TRACE1 ("x_stop_queuing_selection_requests %d", x_queue_selection_requests);
250 --x_queue_selection_requests;
251
252 /* Take all the queued events and put them back
253 so that they get processed afresh. */
254
255 while (selection_queue != NULL)
256 {
257 struct selection_event_queue *queue_tmp = selection_queue;
258 TRACE1 ("RESTORE SELECTION EVENT %08lx", (unsigned long)queue_tmp);
259 kbd_buffer_unget_event (&queue_tmp->event);
260 selection_queue = queue_tmp->next;
261 xfree ((char *)queue_tmp);
262 }
263}
264
265
171/* This converts a Lisp symbol to a server Atom, avoiding a server 266/* This converts a Lisp symbol to a server Atom, avoiding a server
172 roundtrip whenever possible. */ 267 roundtrip whenever possible. */
173 268
@@ -557,13 +652,10 @@ static struct prop_location *property_change_reply_object;
557static struct prop_location *property_change_wait_list; 652static struct prop_location *property_change_wait_list;
558 653
559static Lisp_Object 654static Lisp_Object
560queue_selection_requests_unwind (frame) 655queue_selection_requests_unwind (tem)
561 Lisp_Object frame; 656 Lisp_Object tem;
562{ 657{
563 FRAME_PTR f = XFRAME (frame); 658 x_stop_queuing_selection_requests ();
564
565 if (! NILP (frame))
566 x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f));
567 return Qnil; 659 return Qnil;
568} 660}
569 661
@@ -623,6 +715,17 @@ x_reply_selection_request (event, format, data, size, type)
623 BLOCK_INPUT; 715 BLOCK_INPUT;
624 count = x_catch_errors (display); 716 count = x_catch_errors (display);
625 717
718#ifdef TRACE_SELECTION
719 {
720 static int cnt;
721 char *sel = XGetAtomName (display, reply.selection);
722 char *tgt = XGetAtomName (display, reply.target);
723 TRACE3 ("%s, target %s (%d)", sel, tgt, ++cnt);
724 if (sel) XFree (sel);
725 if (tgt) XFree (tgt);
726 }
727#endif /* TRACE_SELECTION */
728
626 /* Store the data on the requested property. 729 /* Store the data on the requested property.
627 If the selection is large, only store the first N bytes of it. 730 If the selection is large, only store the first N bytes of it.
628 */ 731 */
@@ -650,10 +753,10 @@ x_reply_selection_request (event, format, data, size, type)
650 bother trying to queue them. */ 753 bother trying to queue them. */
651 if (!NILP (frame)) 754 if (!NILP (frame))
652 { 755 {
653 x_start_queuing_selection_requests (display); 756 x_start_queuing_selection_requests ();
654 757
655 record_unwind_protect (queue_selection_requests_unwind, 758 record_unwind_protect (queue_selection_requests_unwind,
656 frame); 759 Qnil);
657 } 760 }
658 761
659 if (x_window_to_frame (dpyinfo, window)) /* #### debug */ 762 if (x_window_to_frame (dpyinfo, window)) /* #### debug */
@@ -687,6 +790,8 @@ x_reply_selection_request (event, format, data, size, type)
687 XGetAtomName (display, reply.property)); 790 XGetAtomName (display, reply.property));
688 wait_for_property_change (wait_object); 791 wait_for_property_change (wait_object);
689 } 792 }
793 else
794 unexpect_property_change (wait_object);
690 795
691 TRACE0 ("Got ACK"); 796 TRACE0 ("Got ACK");
692 while (bytes_remaining) 797 while (bytes_remaining)
@@ -760,7 +865,7 @@ x_reply_selection_request (event, format, data, size, type)
760/* Handle a SelectionRequest event EVENT. 865/* Handle a SelectionRequest event EVENT.
761 This is called from keyboard.c when such an event is found in the queue. */ 866 This is called from keyboard.c when such an event is found in the queue. */
762 867
763void 868static void
764x_handle_selection_request (event) 869x_handle_selection_request (event)
765 struct input_event *event; 870 struct input_event *event;
766{ 871{
@@ -775,6 +880,10 @@ x_handle_selection_request (event)
775 struct x_display_info *dpyinfo 880 struct x_display_info *dpyinfo
776 = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event)); 881 = x_display_info_for_display (SELECTION_EVENT_DISPLAY (event));
777 882
883 TRACE2 ("x_handle_selection_request, from=0x%08lx time=%lu",
884 (unsigned long) SELECTION_EVENT_REQUESTOR (event),
885 (unsigned long) SELECTION_EVENT_TIME (event));
886
778 local_selection_data = Qnil; 887 local_selection_data = Qnil;
779 target_symbol = Qnil; 888 target_symbol = Qnil;
780 converted_selection = Qnil; 889 converted_selection = Qnil;
@@ -869,7 +978,7 @@ x_handle_selection_request (event)
869 client cleared out our previously asserted selection. 978 client cleared out our previously asserted selection.
870 This is called from keyboard.c when such an event is found in the queue. */ 979 This is called from keyboard.c when such an event is found in the queue. */
871 980
872void 981static void
873x_handle_selection_clear (event) 982x_handle_selection_clear (event)
874 struct input_event *event; 983 struct input_event *event;
875{ 984{
@@ -882,6 +991,8 @@ x_handle_selection_clear (event)
882 struct x_display_info *dpyinfo = x_display_info_for_display (display); 991 struct x_display_info *dpyinfo = x_display_info_for_display (display);
883 struct x_display_info *t_dpyinfo; 992 struct x_display_info *t_dpyinfo;
884 993
994 TRACE0 ("x_handle_selection_clear");
995
885 /* If the new selection owner is also Emacs, 996 /* If the new selection owner is also Emacs,
886 don't clear the new selection. */ 997 don't clear the new selection. */
887 BLOCK_INPUT; 998 BLOCK_INPUT;
@@ -950,6 +1061,24 @@ x_handle_selection_clear (event)
950 } 1061 }
951} 1062}
952 1063
1064void
1065x_handle_selection_event (event)
1066 struct input_event *event;
1067{
1068 TRACE0 ("x_handle_selection_event");
1069
1070 if (event->kind == SELECTION_REQUEST_EVENT)
1071 {
1072 if (x_queue_selection_requests)
1073 x_queue_event (event);
1074 else
1075 x_handle_selection_request (event);
1076 }
1077 else
1078 x_handle_selection_clear (event);
1079}
1080
1081
953/* Clear all selections that were made from frame F. 1082/* Clear all selections that were made from frame F.
954 We do this when about to delete a frame. */ 1083 We do this when about to delete a frame. */
955 1084
@@ -1080,12 +1209,14 @@ unexpect_property_change (location)
1080/* Remove the property change expectation element for IDENTIFIER. */ 1209/* Remove the property change expectation element for IDENTIFIER. */
1081 1210
1082static Lisp_Object 1211static Lisp_Object
1083wait_for_property_change_unwind (identifierval) 1212wait_for_property_change_unwind (loc)
1084 Lisp_Object identifierval; 1213 Lisp_Object loc;
1085{ 1214{
1086 unexpect_property_change ((struct prop_location *) 1215 struct prop_location *location = XSAVE_VALUE (loc)->pointer;
1087 (XFASTINT (XCAR (identifierval)) << 16 1216
1088 | XFASTINT (XCDR (identifierval)))); 1217 unexpect_property_change (location);
1218 if (location == property_change_reply_object)
1219 property_change_reply_object = 0;
1089 return Qnil; 1220 return Qnil;
1090} 1221}
1091 1222
@@ -1098,18 +1229,17 @@ wait_for_property_change (location)
1098{ 1229{
1099 int secs, usecs; 1230 int secs, usecs;
1100 int count = SPECPDL_INDEX (); 1231 int count = SPECPDL_INDEX ();
1101 Lisp_Object tem;
1102 1232
1103 tem = Fcons (Qnil, Qnil); 1233 if (property_change_reply_object)
1104 XSETCARFASTINT (tem, (EMACS_UINT)location >> 16); 1234 abort ();
1105 XSETCDRFASTINT (tem, (EMACS_UINT)location & 0xffff);
1106 1235
1107 /* Make sure to do unexpect_property_change if we quit or err. */ 1236 /* Make sure to do unexpect_property_change if we quit or err. */
1108 record_unwind_protect (wait_for_property_change_unwind, tem); 1237 record_unwind_protect (wait_for_property_change_unwind,
1238 make_save_value (location, 0));
1109 1239
1110 XSETCAR (property_change_reply, Qnil); 1240 XSETCAR (property_change_reply, Qnil);
1111
1112 property_change_reply_object = location; 1241 property_change_reply_object = location;
1242
1113 /* If the event we are waiting for arrives beyond here, it will set 1243 /* If the event we are waiting for arrives beyond here, it will set
1114 property_change_reply, because property_change_reply_object says so. */ 1244 property_change_reply, because property_change_reply_object says so. */
1115 if (! location->arrived) 1245 if (! location->arrived)
@@ -1140,7 +1270,8 @@ x_handle_property_notify (event)
1140 1270
1141 while (rest) 1271 while (rest)
1142 { 1272 {
1143 if (rest->property == event->atom 1273 if (!rest->arrived
1274 && rest->property == event->atom
1144 && rest->window == event->window 1275 && rest->window == event->window
1145 && rest->display == event->display 1276 && rest->display == event->display
1146 && rest->desired_state == event->state) 1277 && rest->desired_state == event->state)
@@ -1156,11 +1287,6 @@ x_handle_property_notify (event)
1156 if (rest == property_change_reply_object) 1287 if (rest == property_change_reply_object)
1157 XSETCAR (property_change_reply, Qt); 1288 XSETCAR (property_change_reply, Qt);
1158 1289
1159 if (prev)
1160 prev->next = rest->next;
1161 else
1162 property_change_wait_list = rest->next;
1163 xfree (rest);
1164 return; 1290 return;
1165 } 1291 }
1166 1292
@@ -1286,10 +1412,10 @@ x_get_foreign_selection (selection_symbol, target_type, time_stamp)
1286 bother trying to queue them. */ 1412 bother trying to queue them. */
1287 if (!NILP (frame)) 1413 if (!NILP (frame))
1288 { 1414 {
1289 x_start_queuing_selection_requests (display); 1415 x_start_queuing_selection_requests ();
1290 1416
1291 record_unwind_protect (queue_selection_requests_unwind, 1417 record_unwind_protect (queue_selection_requests_unwind,
1292 frame); 1418 Qnil);
1293 } 1419 }
1294 UNBLOCK_INPUT; 1420 UNBLOCK_INPUT;
1295 1421
@@ -1445,10 +1571,10 @@ receive_incremental_selection (display, window, property, target_type,
1445 BLOCK_INPUT; 1571 BLOCK_INPUT;
1446 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); 1572 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
1447 TRACE1 (" Delete property %s", 1573 TRACE1 (" Delete property %s",
1448 XSYMBOL (x_atom_to_symbol (display, property))->name->data); 1574 SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
1449 XDeleteProperty (display, window, property); 1575 XDeleteProperty (display, window, property);
1450 TRACE1 (" Expect new value of property %s", 1576 TRACE1 (" Expect new value of property %s",
1451 XSYMBOL (x_atom_to_symbol (display, property))->name->data); 1577 SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property))));
1452 wait_object = expect_property_change (display, window, property, 1578 wait_object = expect_property_change (display, window, property,
1453 PropertyNewValue); 1579 PropertyNewValue);
1454 XFlush (display); 1580 XFlush (display);
@@ -1478,7 +1604,6 @@ receive_incremental_selection (display, window, property, target_type,
1478 1604
1479 if (! waiting_for_other_props_on_window (display, window)) 1605 if (! waiting_for_other_props_on_window (display, window))
1480 XSelectInput (display, window, STANDARD_EVENT_SET); 1606 XSelectInput (display, window, STANDARD_EVENT_SET);
1481 unexpect_property_change (wait_object);
1482 /* Use xfree, not XFree, because x_get_window_property 1607 /* Use xfree, not XFree, because x_get_window_property
1483 calls xmalloc itself. */ 1608 calls xmalloc itself. */
1484 if (tmp_data) xfree (tmp_data); 1609 if (tmp_data) xfree (tmp_data);