32 |
#include "buffer.h" |
#include "buffer.h" |
33 |
#include "process.h" |
#include "process.h" |
34 |
#include "termhooks.h" |
#include "termhooks.h" |
35 |
|
#include "keyboard.h" |
36 |
|
|
37 |
#include <X11/Xproto.h> |
#include <X11/Xproto.h> |
38 |
|
|
172 |
static Lisp_Object selection_data_to_lisp_data (); |
static Lisp_Object selection_data_to_lisp_data (); |
173 |
static Lisp_Object x_get_window_property_as_lisp_data (); |
static Lisp_Object x_get_window_property_as_lisp_data (); |
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 |
|
|
255 |
/* This converts a Lisp symbol to a server Atom, avoiding a server |
/* This converts a Lisp symbol to a server Atom, avoiding a server |
256 |
roundtrip whenever possible. */ |
roundtrip whenever possible. */ |
257 |
|
|
641 |
static struct prop_location *property_change_wait_list; |
static struct prop_location *property_change_wait_list; |
642 |
|
|
643 |
static Lisp_Object |
static Lisp_Object |
644 |
queue_selection_requests_unwind (frame) |
queue_selection_requests_unwind (tem) |
645 |
Lisp_Object frame; |
Lisp_Object tem; |
646 |
{ |
{ |
647 |
FRAME_PTR f = XFRAME (frame); |
x_stop_queuing_selection_requests (); |
|
|
|
|
if (! NILP (frame)) |
|
|
x_stop_queuing_selection_requests (FRAME_X_DISPLAY (f)); |
|
648 |
return Qnil; |
return Qnil; |
649 |
} |
} |
650 |
|
|
742 |
bother trying to queue them. */ |
bother trying to queue them. */ |
743 |
if (!NILP (frame)) |
if (!NILP (frame)) |
744 |
{ |
{ |
745 |
x_start_queuing_selection_requests (display); |
x_start_queuing_selection_requests (); |
746 |
|
|
747 |
record_unwind_protect (queue_selection_requests_unwind, |
record_unwind_protect (queue_selection_requests_unwind, |
748 |
frame); |
Qnil); |
749 |
} |
} |
750 |
|
|
751 |
if (x_window_to_frame (dpyinfo, window)) /* #### debug */ |
if (x_window_to_frame (dpyinfo, window)) /* #### debug */ |
779 |
XGetAtomName (display, reply.property)); |
XGetAtomName (display, reply.property)); |
780 |
wait_for_property_change (wait_object); |
wait_for_property_change (wait_object); |
781 |
} |
} |
782 |
|
else |
783 |
|
unexpect_property_change (wait_object); |
784 |
|
|
785 |
TRACE0 ("Got ACK"); |
TRACE0 ("Got ACK"); |
786 |
while (bytes_remaining) |
while (bytes_remaining) |
854 |
/* Handle a SelectionRequest event EVENT. |
/* Handle a SelectionRequest event EVENT. |
855 |
This is called from keyboard.c when such an event is found in the queue. */ |
This is called from keyboard.c when such an event is found in the queue. */ |
856 |
|
|
857 |
void |
static void |
858 |
x_handle_selection_request (event) |
x_handle_selection_request (event) |
859 |
struct input_event *event; |
struct input_event *event; |
860 |
{ |
{ |
869 |
struct x_display_info *dpyinfo |
struct x_display_info *dpyinfo |
870 |
= x_display_info_for_display (SELECTION_EVENT_DISPLAY (event)); |
= x_display_info_for_display (SELECTION_EVENT_DISPLAY (event)); |
871 |
|
|
872 |
|
TRACE0 ("x_handle_selection_request"); |
873 |
|
|
874 |
local_selection_data = Qnil; |
local_selection_data = Qnil; |
875 |
target_symbol = Qnil; |
target_symbol = Qnil; |
876 |
converted_selection = Qnil; |
converted_selection = Qnil; |
965 |
client cleared out our previously asserted selection. |
client cleared out our previously asserted selection. |
966 |
This is called from keyboard.c when such an event is found in the queue. */ |
This is called from keyboard.c when such an event is found in the queue. */ |
967 |
|
|
968 |
void |
static void |
969 |
x_handle_selection_clear (event) |
x_handle_selection_clear (event) |
970 |
struct input_event *event; |
struct input_event *event; |
971 |
{ |
{ |
978 |
struct x_display_info *dpyinfo = x_display_info_for_display (display); |
struct x_display_info *dpyinfo = x_display_info_for_display (display); |
979 |
struct x_display_info *t_dpyinfo; |
struct x_display_info *t_dpyinfo; |
980 |
|
|
981 |
|
TRACE0 ("x_handle_selection_clear"); |
982 |
|
|
983 |
/* If the new selection owner is also Emacs, |
/* If the new selection owner is also Emacs, |
984 |
don't clear the new selection. */ |
don't clear the new selection. */ |
985 |
BLOCK_INPUT; |
BLOCK_INPUT; |
1048 |
} |
} |
1049 |
} |
} |
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 |
|
|
1069 |
/* Clear all selections that were made from frame F. |
/* Clear all selections that were made from frame F. |
1070 |
We do this when about to delete a frame. */ |
We do this when about to delete a frame. */ |
1071 |
|
|
1196 |
/* Remove the property change expectation element for IDENTIFIER. */ |
/* Remove the property change expectation element for IDENTIFIER. */ |
1197 |
|
|
1198 |
static Lisp_Object |
static Lisp_Object |
1199 |
wait_for_property_change_unwind (identifierval) |
wait_for_property_change_unwind (loc) |
1200 |
Lisp_Object identifierval; |
Lisp_Object loc; |
1201 |
{ |
{ |
1202 |
unexpect_property_change ((struct prop_location *) |
struct prop_location *location = XSAVE_VALUE (loc)->pointer; |
1203 |
(XFASTINT (XCAR (identifierval)) << 16 |
|
1204 |
| XFASTINT (XCDR (identifierval)))); |
unexpect_property_change (location); |
1205 |
|
if (location == property_change_reply_object) |
1206 |
|
property_change_reply_object = 0; |
1207 |
return Qnil; |
return Qnil; |
1208 |
} |
} |
1209 |
|
|
1216 |
{ |
{ |
1217 |
int secs, usecs; |
int secs, usecs; |
1218 |
int count = SPECPDL_INDEX (); |
int count = SPECPDL_INDEX (); |
|
Lisp_Object tem; |
|
1219 |
|
|
1220 |
tem = Fcons (Qnil, Qnil); |
if (property_change_reply_object) |
1221 |
XSETCARFASTINT (tem, (EMACS_UINT)location >> 16); |
abort (); |
|
XSETCDRFASTINT (tem, (EMACS_UINT)location & 0xffff); |
|
1222 |
|
|
1223 |
/* Make sure to do unexpect_property_change if we quit or err. */ |
/* Make sure to do unexpect_property_change if we quit or err. */ |
1224 |
record_unwind_protect (wait_for_property_change_unwind, tem); |
record_unwind_protect (wait_for_property_change_unwind, |
1225 |
|
make_save_value (location, 0)); |
1226 |
|
|
1227 |
XSETCAR (property_change_reply, Qnil); |
XSETCAR (property_change_reply, Qnil); |
|
|
|
1228 |
property_change_reply_object = location; |
property_change_reply_object = location; |
1229 |
|
|
1230 |
/* If the event we are waiting for arrives beyond here, it will set |
/* If the event we are waiting for arrives beyond here, it will set |
1231 |
property_change_reply, because property_change_reply_object says so. */ |
property_change_reply, because property_change_reply_object says so. */ |
1232 |
if (! location->arrived) |
if (! location->arrived) |
1257 |
|
|
1258 |
while (rest) |
while (rest) |
1259 |
{ |
{ |
1260 |
if (rest->property == event->atom |
if (!rest->arrived |
1261 |
|
&& rest->property == event->atom |
1262 |
&& rest->window == event->window |
&& rest->window == event->window |
1263 |
&& rest->display == event->display |
&& rest->display == event->display |
1264 |
&& rest->desired_state == event->state) |
&& rest->desired_state == event->state) |
1274 |
if (rest == property_change_reply_object) |
if (rest == property_change_reply_object) |
1275 |
XSETCAR (property_change_reply, Qt); |
XSETCAR (property_change_reply, Qt); |
1276 |
|
|
|
if (prev) |
|
|
prev->next = rest->next; |
|
|
else |
|
|
property_change_wait_list = rest->next; |
|
|
xfree (rest); |
|
1277 |
return; |
return; |
1278 |
} |
} |
1279 |
|
|
1399 |
bother trying to queue them. */ |
bother trying to queue them. */ |
1400 |
if (!NILP (frame)) |
if (!NILP (frame)) |
1401 |
{ |
{ |
1402 |
x_start_queuing_selection_requests (display); |
x_start_queuing_selection_requests (); |
1403 |
|
|
1404 |
record_unwind_protect (queue_selection_requests_unwind, |
record_unwind_protect (queue_selection_requests_unwind, |
1405 |
frame); |
Qnil); |
1406 |
} |
} |
1407 |
UNBLOCK_INPUT; |
UNBLOCK_INPUT; |
1408 |
|
|
1558 |
BLOCK_INPUT; |
BLOCK_INPUT; |
1559 |
XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); |
XSelectInput (display, window, STANDARD_EVENT_SET | PropertyChangeMask); |
1560 |
TRACE1 (" Delete property %s", |
TRACE1 (" Delete property %s", |
1561 |
SDATA (XSYMBOL (x_atom_to_symbol (display, property))->xname)); |
SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property)))); |
1562 |
XDeleteProperty (display, window, property); |
XDeleteProperty (display, window, property); |
1563 |
TRACE1 (" Expect new value of property %s", |
TRACE1 (" Expect new value of property %s", |
1564 |
SDATA (XSYMBOL (x_atom_to_symbol (display, property))->xname)); |
SDATA (SYMBOL_NAME (x_atom_to_symbol (display, property)))); |
1565 |
wait_object = expect_property_change (display, window, property, |
wait_object = expect_property_change (display, window, property, |
1566 |
PropertyNewValue); |
PropertyNewValue); |
1567 |
XFlush (display); |
XFlush (display); |
1591 |
|
|
1592 |
if (! waiting_for_other_props_on_window (display, window)) |
if (! waiting_for_other_props_on_window (display, window)) |
1593 |
XSelectInput (display, window, STANDARD_EVENT_SET); |
XSelectInput (display, window, STANDARD_EVENT_SET); |
|
unexpect_property_change (wait_object); |
|
1594 |
/* Use xfree, not XFree, because x_get_window_property |
/* Use xfree, not XFree, because x_get_window_property |
1595 |
calls xmalloc itself. */ |
calls xmalloc itself. */ |
1596 |
if (tmp_data) xfree (tmp_data); |
if (tmp_data) xfree (tmp_data); |