struct prop_location;
struct selection_data;
-static void x_decline_selection_request (struct input_event *);
-static bool x_convert_selection (struct input_event *, Lisp_Object,
- Lisp_Object, Atom, bool,
+static void x_decline_selection_request (struct selection_input_event *);
+static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom, bool,
struct x_display_info *);
static bool waiting_for_other_props_on_window (Display *, Window);
static struct prop_location *expect_property_change (Display *, Window,
#define TRACE2(fmt, a0, a1) (void) 0
#endif
-
-static Lisp_Object QSECONDARY, QSTRING, QINTEGER, QCLIPBOARD, QTIMESTAMP,
- QTEXT, QDELETE, QMULTIPLE, QINCR, QEMACS_TMP, QTARGETS, QATOM, QNULL,
- QATOM_PAIR, QCLIPBOARD_MANAGER, QSAVE_TARGETS;
-
-static Lisp_Object QCOMPOUND_TEXT; /* This is a type of selection. */
-static Lisp_Object QUTF8_STRING; /* This is a type of selection. */
-
-static Lisp_Object Qcompound_text_with_extensions;
-
-static Lisp_Object Qforeign_selection;
-static Lisp_Object Qx_lost_selection_functions, Qx_sent_selection_functions;
-
/* Bytes needed to represent 'long' data. This is as per libX11; it
is not necessarily sizeof (long). */
#define X_LONG_SIZE 4
struct selection_event_queue
{
- struct input_event event;
+ struct selection_input_event event;
struct selection_event_queue *next;
};
static int x_queue_selection_requests;
+/* True if the input events are duplicates. */
+
+static bool
+selection_input_event_equal (struct selection_input_event *a,
+ struct selection_input_event *b)
+{
+ return (a->kind == b->kind && a->dpyinfo == b->dpyinfo
+ && a->requestor == b->requestor && a->selection == b->selection
+ && a->target == b->target && a->property == b->property
+ && a->time == b->time);
+}
+
/* Queue up an SELECTION_REQUEST_EVENT *EVENT, to be processed later. */
static void
-x_queue_event (struct input_event *event)
+x_queue_event (struct selection_input_event *event)
{
struct selection_event_queue *queue_tmp;
This only happens for large requests which uses the incremental protocol. */
for (queue_tmp = selection_queue; queue_tmp; queue_tmp = queue_tmp->next)
{
- if (!memcmp (&queue_tmp->event, event, sizeof (*event)))
+ if (selection_input_event_equal (event, &queue_tmp->event))
{
TRACE1 ("DECLINE DUP SELECTION EVENT %p", queue_tmp);
x_decline_selection_request (event);
meaning we were unable to do what they wanted. */
static void
-x_decline_selection_request (struct input_event *event)
+x_decline_selection_request (struct selection_input_event *event)
{
XEvent reply_base;
XSelectionEvent *reply = &(reply_base.xselection);
/* This is the selection request currently being processed.
It is set to zero when the request is fully processed. */
-static struct input_event *x_selection_current_request;
+static struct selection_input_event *x_selection_current_request;
/* Display info in x_selection_request. */
static struct prop_location *property_change_wait_list;
+static void
+set_property_change_object (struct prop_location *location)
+{
+ /* Input must be blocked so we don't get the event before we set these. */
+ if (! input_blocked_p ())
+ emacs_abort ();
+ XSETCAR (property_change_reply, Qnil);
+ property_change_reply_object = location;
+}
+
\f
/* Send the reply to a selection request event EVENT. */
#endif /* TRACE_SELECTION */
static void
-x_reply_selection_request (struct input_event *event,
+x_reply_selection_request (struct selection_input_event *event,
struct x_display_info *dpyinfo)
{
XEvent reply_base;
{
int format_bytes = cs->format / 8;
bool had_errors_p = x_had_errors_p (display);
+
+ /* Must set this inside block_input (). unblock_input may read
+ events and setting property_change_reply in
+ wait_for_property_change is then too late. */
+ set_property_change_object (cs->wait_object);
unblock_input ();
bytes_remaining = cs->size;
: format_bytes);
XFlush (display);
had_errors_p = x_had_errors_p (display);
+ // See comment above about property_change_reply.
+ set_property_change_object (cs->wait_object);
unblock_input ();
if (had_errors_p) break;
This is called from keyboard.c when such an event is found in the queue. */
static void
-x_handle_selection_request (struct input_event *event)
+x_handle_selection_request (struct selection_input_event *event)
{
struct gcpro gcpro1, gcpro2;
Time local_selection_time;
AREF (multprop, 2*j+1));
if (subproperty != None)
- x_convert_selection (event, selection_symbol, subtarget,
+ x_convert_selection (selection_symbol, subtarget,
subproperty, true, dpyinfo);
}
success = true;
{
if (property == None)
property = SELECTION_EVENT_TARGET (event);
- success = x_convert_selection (event, selection_symbol,
+ success = x_convert_selection (selection_symbol,
target_symbol, property,
false, dpyinfo);
}
/* Run the `x-sent-selection-functions' abnormal hook. */
if (!NILP (Vx_sent_selection_functions)
&& !EQ (Vx_sent_selection_functions, Qunbound))
- {
- Lisp_Object args[4];
- args[0] = Qx_sent_selection_functions;
- args[1] = selection_symbol;
- args[2] = target_symbol;
- args[3] = success ? Qt : Qnil;
- Frun_hook_with_args (4, args);
- }
+ CALLN (Frun_hook_with_args, Qx_sent_selection_functions,
+ selection_symbol, target_symbol, success ? Qt : Qnil);
unbind_to (count, Qnil);
UNGCPRO;
Return true iff successful. */
static bool
-x_convert_selection (struct input_event *event, Lisp_Object selection_symbol,
+x_convert_selection (Lisp_Object selection_symbol,
Lisp_Object target_symbol, Atom property,
bool for_multiple, struct x_display_info *dpyinfo)
{
This is called from keyboard.c when such an event is found in the queue. */
static void
-x_handle_selection_clear (struct input_event *event)
+x_handle_selection_clear (struct selection_input_event *event)
{
Atom selection = SELECTION_EVENT_SELECTION (event);
Time changed_owner_time = SELECTION_EVENT_TIME (event);
tset_selection_alist (dpyinfo->terminal, Vselection_alist);
/* Run the `x-lost-selection-functions' abnormal hook. */
- {
- Lisp_Object args[2];
- args[0] = Qx_lost_selection_functions;
- args[1] = selection_symbol;
- Frun_hook_with_args (2, args);
- }
+ CALLN (Frun_hook_with_args, Qx_lost_selection_functions, selection_symbol);
redisplay_preserve_echo_area (20);
}
void
-x_handle_selection_event (struct input_event *event)
+x_handle_selection_event (struct selection_input_event *event)
{
TRACE0 ("x_handle_selection_event");
if (event->kind != SELECTION_REQUEST_EVENT)
&& EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (t->Vselection_alist)))))))
{
/* Run the `x-lost-selection-functions' abnormal hook. */
- Lisp_Object args[2];
- args[0] = Qx_lost_selection_functions;
- args[1] = Fcar (Fcar (t->Vselection_alist));
- Frun_hook_with_args (2, args);
+ CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
+ Fcar (Fcar (t->Vselection_alist)));
tset_selection_alist (t, XCDR (t->Vselection_alist));
}
if (CONSP (XCDR (rest))
&& EQ (frame, XCAR (XCDR (XCDR (XCDR (XCAR (XCDR (rest))))))))
{
- Lisp_Object args[2];
- args[0] = Qx_lost_selection_functions;
- args[1] = XCAR (XCAR (XCDR (rest)));
- Frun_hook_with_args (2, args);
+ CALLN (Frun_hook_with_args, Qx_lost_selection_functions,
+ XCAR (XCAR (XCDR (rest))));
XSETCDR (rest, XCDR (XCDR (rest)));
break;
}
{
ptrdiff_t count = SPECPDL_INDEX ();
- if (property_change_reply_object)
- emacs_abort ();
-
/* Make sure to do unexpect_property_change if we quit or err. */
record_unwind_protect_ptr (wait_for_property_change_unwind, location);
- XSETCAR (property_change_reply, Qnil);
- property_change_reply_object = location;
+ /* See comment in x_reply_selection_request about setting
+ property_change_reply. Do not do it here. */
/* If the event we are waiting for arrives beyond here, it will set
property_change_reply, because property_change_reply_object says so. */
wait_object = expect_property_change (display, window, property,
PropertyNewValue);
XFlush (display);
+ // See comment in x_reply_selection_request about property_change_reply.
+ set_property_change_object (wait_object);
unblock_input ();
while (true)
XDeleteProperty (display, window, property);
wait_object = expect_property_change (display, window, property,
PropertyNewValue);
+ // See comment in x_reply_selection_request about property_change_reply.
+ set_property_change_object (wait_object);
XFlush (display);
unblock_input ();
{
Time timestamp;
Atom selection_atom;
- union {
- struct selection_input_event sie;
- struct input_event ie;
- } event;
+ struct selection_input_event event;
struct frame *f = frame_for_x_selection (terminal);
struct x_display_info *dpyinfo;
the selection owner to None. The NCD server does, the MIT Sun4 server
doesn't. So we synthesize one; this means we might get two, but
that's ok, because the second one won't have any effect. */
- SELECTION_EVENT_DPYINFO (&event.sie) = dpyinfo;
- SELECTION_EVENT_SELECTION (&event.sie) = selection_atom;
- SELECTION_EVENT_TIME (&event.sie) = timestamp;
- x_handle_selection_clear (&event.ie);
+ SELECTION_EVENT_DPYINFO (&event) = dpyinfo;
+ SELECTION_EVENT_SELECTION (&event) = selection_atom;
+ SELECTION_EVENT_TIME (&event) = timestamp;
+ x_handle_selection_clear (&event);
return Qt;
}
{
AUTO_STRING (format, "X clipboard manager error: %s\n\
If the problem persists, set `x-select-enable-clipboard-manager' to nil.");
- Fmessage (2, (Lisp_Object []) {format, CAR (CDR (err))});
+ CALLN (Fmessage, format, CAR (CDR (err)));
return Qnil;
}
local_frame = XCAR (XCDR (XCDR (XCDR (local_selection))));
if (FRAME_LIVE_P (XFRAME (local_frame)))
{
- AUTO_STRING (saving, "Saving clipboard to X clipboard manager...");
- Fmessage (1, &saving);
+ message ("Saving clipboard to X clipboard manager...");
internal_condition_case_1 (x_clipboard_manager_save, local_frame,
Qt, x_clipboard_manager_error_2);
}
DEFSYM (QCLIPBOARD, "CLIPBOARD");
DEFSYM (QTIMESTAMP, "TIMESTAMP");
DEFSYM (QTEXT, "TEXT");
+
+ /* These are types of selection. */
DEFSYM (QCOMPOUND_TEXT, "COMPOUND_TEXT");
DEFSYM (QUTF8_STRING, "UTF8_STRING");
+
DEFSYM (QDELETE, "DELETE");
DEFSYM (QMULTIPLE, "MULTIPLE");
DEFSYM (QINCR, "INCR");
DEFSYM (QEMACS_TMP, "_EMACS_TMP_");
DEFSYM (QTARGETS, "TARGETS");
DEFSYM (QATOM, "ATOM");
- DEFSYM (QATOM_PAIR, "ATOM_PAIR");
DEFSYM (QCLIPBOARD_MANAGER, "CLIPBOARD_MANAGER");
DEFSYM (QSAVE_TARGETS, "SAVE_TARGETS");
DEFSYM (QNULL, "NULL");
- DEFSYM (Qcompound_text_with_extensions, "compound-text-with-extensions");
DEFSYM (Qforeign_selection, "foreign-selection");
DEFSYM (Qx_lost_selection_functions, "x-lost-selection-functions");
DEFSYM (Qx_sent_selection_functions, "x-sent-selection-functions");