From: Po Lu Date: Tue, 12 Jul 2022 07:14:04 +0000 (+0800) Subject: Fix preserving selections if `x-lost-selection-functions' signals X-Git-Tag: emacs-29.0.90~1447^2~995 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=93b31707e97f8ddf11aa8acbf5c61bc29b5f7528;p=emacs.git Fix preserving selections if `x-lost-selection-functions' signals * src/xterm.c (x_preserve_selections): Get selection owner and run lost selection hook separately. --- diff --git a/src/xterm.c b/src/xterm.c index f86e4708ec5..a13162d61be 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -27960,7 +27960,10 @@ x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost) { Lisp_Object tail, frame, new_owner, tem; Time timestamp; - Window owner; + Window *owners; + Atom *names; + ptrdiff_t nowners, counter; + struct selection_input_event clear; new_owner = Qnil; @@ -27975,10 +27978,12 @@ x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost) } tail = lost; + nowners = 0; FOR_EACH_TAIL_SAFE (tail) { tem = XCAR (tail); + ++nowners; /* The selection is really lost (since we cannot find a new owner), so run the appropriate hooks. */ @@ -27994,13 +27999,54 @@ x_preserve_selections (struct x_display_info *dpyinfo, Lisp_Object lost) x_own_selection (XCAR (tem), XCAR (XCDR (tem)), new_owner, XCAR (XCDR (XCDR (XCDR (XCDR (tem))))), timestamp); + } + } + + if (!NILP (new_owner)) + { + owners = alloca (sizeof *owners * nowners); + names = alloca (sizeof *names * nowners); + + tail = lost; + nowners = 0; + counter = 0; + + FOR_EACH_TAIL_SAFE (tail) + { + tem = XCAR (tail); /* Now check if we still don't own that selection, which can happen if another program set itself as the owner. */ - owner = XGetSelectionOwner (dpyinfo->display, - symbol_to_x_atom (dpyinfo, XCAR (tem))); + names[counter++] = symbol_to_x_atom (dpyinfo, XCAR (tem)); + owners[nowners++] = XGetSelectionOwner (dpyinfo->display, + names[counter - 1]); + + if (owners[nowners - 1] != FRAME_X_WINDOW (XFRAME (new_owner))) + { + /* Clear the local selection, since we know we don't own + it any longer. */ + CONS_TO_INTEGER (XCAR (XCDR (XCDR (tem))), Time, timestamp); + + clear.kind = SELECTION_CLEAR_EVENT; + + SELECTION_EVENT_DPYINFO (&clear) = dpyinfo; + SELECTION_EVENT_SELECTION (&clear) = names[nowners - 1]; + SELECTION_EVENT_TIME (&clear) = timestamp; + + x_handle_selection_event (&clear); + } + } + + tail = lost; + nowners = 0; + + FOR_EACH_TAIL_SAFE (tail) + { + tem = XCAR (tail); - if (owner != FRAME_X_WINDOW (XFRAME (new_owner))) + /* If the selection isn't owned by us anymore, note that the + selection was lost. */ + if (owners[nowners++] != FRAME_X_WINDOW (XFRAME (new_owner))) CALLN (Frun_hook_with_args, Qx_lost_selection_functions, XCAR (tem)); }