aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1993-08-14 23:02:58 +0000
committerRichard M. Stallman1993-08-14 23:02:58 +0000
commitd1f21a66c48c44b9ad01f419cfc59f022aabd4c2 (patch)
tree454838a88a699491eeb8dabee94d33b9a5cb1d6a /src
parentb90d9e804346d2202de60678656b361f331d1c40 (diff)
downloademacs-d1f21a66c48c44b9ad01f419cfc59f022aabd4c2.tar.gz
emacs-d1f21a66c48c44b9ad01f419cfc59f022aabd4c2.zip
(struct property_change): New field `arrived'.
(expect_property_change): Return struct property_change *. Clear `arrived'. (unexpect_property_change): Take one as argument. (wait_for_property_change): Take one as argument. If `arrived' is set, don't wait. (wait_for_property_change_unwind): Corresponding changes. (receive_incremental_selection): Corresponding changes. (x_reply_selection_request): Corresponding changes. (property_deleted_p): Function deleted. (x_handle_selection_clear): Redisplay.
Diffstat (limited to 'src')
-rw-r--r--src/xselect.c153
1 files changed, 79 insertions, 74 deletions
diff --git a/src/xselect.c b/src/xselect.c
index 9f083b8b1a7..7b6a1164e3c 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -106,11 +106,6 @@ static void lisp_data_to_selection_data ();
106static Lisp_Object selection_data_to_lisp_data (); 106static Lisp_Object selection_data_to_lisp_data ();
107static Lisp_Object x_get_window_property_as_lisp_data (); 107static Lisp_Object x_get_window_property_as_lisp_data ();
108 108
109static int expect_property_change ();
110static void wait_for_property_change ();
111static void unexpect_property_change ();
112static int waiting_for_other_props_on_window ();
113
114/* This converts a Lisp symbol to a server Atom, avoiding a server 109/* This converts a Lisp symbol to a server Atom, avoiding a server
115 roundtrip whenever possible. */ 110 roundtrip whenever possible. */
116 111
@@ -437,6 +432,37 @@ x_selection_request_lisp_error (ignore)
437 return Qnil; 432 return Qnil;
438} 433}
439 434
435
436/* This stuff is so that INCR selections are reentrant (that is, so we can
437 be servicing multiple INCR selection requests simultaneously.) I haven't
438 actually tested that yet. */
439
440/* Keep a list of the property changes that are awaited. */
441
442struct prop_location
443{
444 int identifier;
445 Display *display;
446 Window window;
447 Atom property;
448 int desired_state;
449 int arrived;
450 struct prop_location *next;
451};
452
453static struct prop_location *expect_property_change ();
454static void wait_for_property_change ();
455static void unexpect_property_change ();
456static int waiting_for_other_props_on_window ();
457
458static int prop_location_identifier;
459
460static Lisp_Object property_change_reply;
461
462static struct prop_location *property_change_reply_object;
463
464static struct prop_location *property_change_wait_list;
465
440/* Send the reply to a selection request event EVENT. 466/* Send the reply to a selection request event EVENT.
441 TYPE is the type of selection data requested. 467 TYPE is the type of selection data requested.
442 DATA and SIZE describe the data to send, already converted. 468 DATA and SIZE describe the data to send, already converted.
@@ -492,7 +518,7 @@ x_reply_selection_request (event, format, data, size, type)
492 else 518 else
493 { 519 {
494 /* Send an INCR selection. */ 520 /* Send an INCR selection. */
495 int prop_id; 521 struct prop_location *wait_object;
496 522
497 BLOCK_INPUT; 523 BLOCK_INPUT;
498 524
@@ -501,8 +527,8 @@ x_reply_selection_request (event, format, data, size, type)
501#if 0 527#if 0
502 fprintf (stderr, "\nINCR %d\n", bytes_remaining); 528 fprintf (stderr, "\nINCR %d\n", bytes_remaining);
503#endif 529#endif
504 prop_id = expect_property_change (display, window, reply.property, 530 wait_object = expect_property_change (display, window, reply.property,
505 PropertyDelete); 531 PropertyDelete);
506 532
507 XChangeProperty (display, window, reply.property, Xatom_INCR, 533 XChangeProperty (display, window, reply.property, Xatom_INCR,
508 32, PropModeReplace, (unsigned char *) 534 32, PropModeReplace, (unsigned char *)
@@ -515,7 +541,7 @@ x_reply_selection_request (event, format, data, size, type)
515 541
516 /* First, wait for the requestor to ack by deleting the property. 542 /* First, wait for the requestor to ack by deleting the property.
517 This can run random lisp code (process handlers) or signal. */ 543 This can run random lisp code (process handlers) or signal. */
518 wait_for_property_change (prop_id); 544 wait_for_property_change (wait_object);
519 545
520 while (bytes_remaining) 546 while (bytes_remaining)
521 { 547 {
@@ -525,8 +551,9 @@ x_reply_selection_request (event, format, data, size, type)
525 551
526 BLOCK_INPUT; 552 BLOCK_INPUT;
527 553
528 prop_id = expect_property_change (display, window, reply.property, 554 wait_object
529 PropertyDelete); 555 = expect_property_change (display, window, reply.property,
556 PropertyDelete);
530#if 0 557#if 0
531 fprintf (stderr," INCR adding %d\n", i); 558 fprintf (stderr," INCR adding %d\n", i);
532#endif 559#endif
@@ -541,7 +568,7 @@ x_reply_selection_request (event, format, data, size, type)
541 /* Now wait for the requestor to ack this chunk by deleting the 568 /* Now wait for the requestor to ack this chunk by deleting the
542 property. This can run random lisp code or signal. 569 property. This can run random lisp code or signal.
543 */ 570 */
544 wait_for_property_change (prop_id); 571 wait_for_property_change (wait_object);
545 } 572 }
546 /* Now write a zero-length chunk to the property to tell the requestor 573 /* Now write a zero-length chunk to the property to tell the requestor
547 that we're done. */ 574 that we're done. */
@@ -708,50 +735,18 @@ x_handle_selection_clear (event)
708 /* Let random lisp code notice that the selection has been stolen. */ 735 /* Let random lisp code notice that the selection has been stolen. */
709 736
710 { 737 {
711 Lisp_Object rest = Vx_lost_selection_hooks; 738 Lisp_Object rest;
739 rest = Vx_lost_selection_hooks;
712 if (!EQ (rest, Qunbound)) 740 if (!EQ (rest, Qunbound))
713 for (; CONSP (rest); rest = Fcdr (rest)) 741 {
714 call1 (Fcar (rest), selection_symbol); 742 for (; CONSP (rest); rest = Fcdr (rest))
743 call1 (Fcar (rest), selection_symbol);
744 redisplay_preserve_echo_area ();
745 }
715 } 746 }
716} 747}
717 748
718 749
719/* This stuff is so that INCR selections are reentrant (that is, so we can
720 be servicing multiple INCR selection requests simultaneously.) I haven't
721 actually tested that yet. */
722
723static int prop_location_identifier;
724
725static Lisp_Object property_change_reply;
726static int property_change_reply_identifier;
727
728/* Keep a list of the property changes that are awaited. */
729
730struct prop_location
731{
732 int identifier;
733 Display *display;
734 Window window;
735 Atom property;
736 int desired_state;
737 struct prop_location *next;
738};
739
740static struct prop_location *property_change_wait_list;
741
742static int
743property_deleted_p (identifier)
744 void *identifier;
745{
746 struct prop_location *rest = property_change_wait_list;
747 while (rest)
748 if (rest->identifier == (int) identifier)
749 return 0;
750 else
751 rest = rest->next;
752 return 1;
753}
754
755/* Nonzero if any properties for DISPLAY and WINDOW 750/* Nonzero if any properties for DISPLAY and WINDOW
756 are on the list of what we are waiting for. */ 751 are on the list of what we are waiting for. */
757 752
@@ -774,7 +769,7 @@ waiting_for_other_props_on_window (display, window)
774 The return value is a number that uniquely identifies 769 The return value is a number that uniquely identifies
775 this awaited property change. */ 770 this awaited property change. */
776 771
777static int 772static struct prop_location *
778expect_property_change (display, window, property, state) 773expect_property_change (display, window, property, state)
779 Display *display; 774 Display *display;
780 Window window; 775 Window window;
@@ -789,21 +784,22 @@ expect_property_change (display, window, property, state)
789 pl->property = property; 784 pl->property = property;
790 pl->desired_state = state; 785 pl->desired_state = state;
791 pl->next = property_change_wait_list; 786 pl->next = property_change_wait_list;
787 pl->arrived = 0;
792 property_change_wait_list = pl; 788 property_change_wait_list = pl;
793 return pl->identifier; 789 return pl;
794} 790}
795 791
796/* Delete an entry from the list of property changes we are waiting for. 792/* Delete an entry from the list of property changes we are waiting for.
797 IDENTIFIER is the number that uniquely identifies the entry. */ 793 IDENTIFIER is the number that uniquely identifies the entry. */
798 794
799static void 795static void
800unexpect_property_change (identifier) 796unexpect_property_change (location)
801 int identifier; 797 struct prop_location *location;
802{ 798{
803 struct prop_location *prev = 0, *rest = property_change_wait_list; 799 struct prop_location *prev = 0, *rest = property_change_wait_list;
804 while (rest) 800 while (rest)
805 { 801 {
806 if (rest->identifier == identifier) 802 if (rest == location)
807 { 803 {
808 if (prev) 804 if (prev)
809 prev->next = rest->next; 805 prev->next = rest->next;
@@ -823,30 +819,37 @@ static Lisp_Object
823wait_for_property_change_unwind (identifierval) 819wait_for_property_change_unwind (identifierval)
824 Lisp_Object identifierval; 820 Lisp_Object identifierval;
825{ 821{
826 unexpect_property_change (XFASTINT (identifierval)); 822 unexpect_property_change (XPNTR (identifierval));
827} 823}
828 824
829/* Actually wait for a property change. 825/* Actually wait for a property change.
830 IDENTIFIER should be the value that expect_property_change returned. */ 826 IDENTIFIER should be the value that expect_property_change returned. */
831 827
832static void 828static void
833wait_for_property_change (identifier) 829wait_for_property_change (location)
830 struct prop_location *location;
834{ 831{
835 int secs, usecs; 832 int secs, usecs;
836 int count = specpdl_ptr - specpdl; 833 int count = specpdl_ptr - specpdl;
834 Lisp_Object tem;
835
836 XSET (tem, Lisp_Cons, location);
837 837
838 /* Make sure to do unexpect_property_change if we quit or err. */ 838 /* Make sure to do unexpect_property_change if we quit or err. */
839 record_unwind_protect (wait_for_property_change_unwind, 839 record_unwind_protect (wait_for_property_change_unwind, tem);
840 make_number (identifier));
841 840
842 XCONS (property_change_reply)->car = Qnil; 841 XCONS (property_change_reply)->car = Qnil;
843 property_change_reply_identifier = identifier;
844 secs = x_selection_timeout / 1000;
845 usecs = (x_selection_timeout % 1000) * 1000;
846 wait_reading_process_input (secs, usecs, property_change_reply, 0);
847 842
848 if (NILP (XCONS (property_change_reply)->car)) 843 if (! location->arrived)
849 error ("timed out waiting for property-notify event"); 844 {
845 property_change_reply_object = location;
846 secs = x_selection_timeout / 1000;
847 usecs = (x_selection_timeout % 1000) * 1000;
848 wait_reading_process_input (secs, usecs, property_change_reply, 0);
849
850 if (NILP (XCONS (property_change_reply)->car))
851 error ("timed out waiting for property-notify event");
852 }
850 853
851 unbind_to (count, Qnil); 854 unbind_to (count, Qnil);
852} 855}
@@ -873,9 +876,11 @@ x_handle_property_notify (event)
873 ->name->data); 876 ->name->data);
874#endif 877#endif
875 878
879 rest->arrived = 1;
880
876 /* If this is the one wait_for_property_change is waiting for, 881 /* If this is the one wait_for_property_change is waiting for,
877 tell it to wake up. */ 882 tell it to wake up. */
878 if (rest->identifier == property_change_reply_identifier) 883 if (rest == property_change_reply_object)
879 XCONS (property_change_reply)->car = Qt; 884 XCONS (property_change_reply)->car = Qt;
880 885
881 if (prev) 886 if (prev)
@@ -1100,7 +1105,7 @@ receive_incremental_selection (display, window, property, target_type,
1100 int *format_ret; 1105 int *format_ret;
1101{ 1106{
1102 int offset = 0; 1107 int offset = 0;
1103 int prop_id; 1108 struct prop_location *wait_object;
1104 *size_bytes_ret = min_size_bytes; 1109 *size_bytes_ret = min_size_bytes;
1105 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret); 1110 *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
1106#if 0 1111#if 0
@@ -1118,8 +1123,8 @@ receive_incremental_selection (display, window, property, target_type,
1118 BLOCK_INPUT; 1123 BLOCK_INPUT;
1119 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); 1124 XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask);
1120 XDeleteProperty (display, window, property); 1125 XDeleteProperty (display, window, property);
1121 prop_id = expect_property_change (display, window, property, 1126 wait_object = expect_property_change (display, window, property,
1122 PropertyNewValue); 1127 PropertyNewValue);
1123 XFlushQueue (); 1128 XFlushQueue ();
1124 UNBLOCK_INPUT; 1129 UNBLOCK_INPUT;
1125 1130
@@ -1127,7 +1132,7 @@ receive_incremental_selection (display, window, property, target_type,
1127 { 1132 {
1128 unsigned char *tmp_data; 1133 unsigned char *tmp_data;
1129 int tmp_size_bytes; 1134 int tmp_size_bytes;
1130 wait_for_property_change (prop_id); 1135 wait_for_property_change (wait_object);
1131 /* expect it again immediately, because x_get_window_property may 1136 /* expect it again immediately, because x_get_window_property may
1132 .. no it wont, I dont get it. 1137 .. no it wont, I dont get it.
1133 .. Ok, I get it now, the Xt code that implements INCR is broken. 1138 .. Ok, I get it now, the Xt code that implements INCR is broken.
@@ -1143,15 +1148,15 @@ receive_incremental_selection (display, window, property, target_type,
1143#endif 1148#endif
1144 if (! waiting_for_other_props_on_window (display, window)) 1149 if (! waiting_for_other_props_on_window (display, window))
1145 XSelectInput (display, window, STANDARD_EVENT_SET); 1150 XSelectInput (display, window, STANDARD_EVENT_SET);
1146 unexpect_property_change (prop_id); 1151 unexpect_property_change (wait_object);
1147 if (tmp_data) xfree (tmp_data); 1152 if (tmp_data) xfree (tmp_data);
1148 break; 1153 break;
1149 } 1154 }
1150 1155
1151 BLOCK_INPUT; 1156 BLOCK_INPUT;
1152 XDeleteProperty (display, window, property); 1157 XDeleteProperty (display, window, property);
1153 prop_id = expect_property_change (display, window, property, 1158 wait_object = expect_property_change (display, window, property,
1154 PropertyNewValue); 1159 PropertyNewValue);
1155 XFlushQueue (); 1160 XFlushQueue ();
1156 UNBLOCK_INPUT; 1161 UNBLOCK_INPUT;
1157 1162