emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master e161b5fa3c: Fix preservation of the original value of PRIMARY aft


From: Po Lu
Subject: master e161b5fa3c: Fix preservation of the original value of PRIMARY after dropping on xterm
Date: Wed, 29 Jun 2022 21:46:54 -0400 (EDT)

branch: master
commit e161b5fa3c8241a34961b378501247fb3978e6dc
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix preservation of the original value of PRIMARY after dropping on xterm
    
    * src/xselect.c (x_own_selection): New arg `dnd_data'.  Record
    it.
    (x_get_local_selection, x_handle_selection_request)
    (x_convert_selection): Convert the DND data instead if the
    situation warrants.
    (Fx_own_selection_internal, Fx_get_selection_internal)
    (Fx_get_local_selection): Update calls to x_get_local_selection.
    
    * src/xterm.c (x_dnd_do_unsupported_drop): If obtaining
    selection ownership failed, return.  Record DND value and
    preserve the current value of PRIMARY, if it exists.
    
    * src/xterm.h: Update prototypes.
---
 src/xselect.c | 62 +++++++++++++++++++++++++++++++++++++----------------------
 src/xterm.c   | 35 ++++++++++++++++++++++++++-------
 src/xterm.h   |  3 ++-
 3 files changed, 69 insertions(+), 31 deletions(-)

diff --git a/src/xselect.c b/src/xselect.c
index 5796b0034a..41fa837c5a 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -47,7 +47,7 @@ struct selection_data;
 
 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 *);
+                                struct x_display_info *, bool);
 static bool waiting_for_other_props_on_window (Display *, Window);
 static struct prop_location *expect_property_change (Display *, Window,
                                                      Atom, int);
@@ -250,20 +250,26 @@ x_atom_to_symbol (struct x_display_info *dpyinfo, Atom 
atom)
 
 /* Do protocol to assert ourself as a selection owner.
    FRAME shall be the owner; it must be a valid X frame.
+   TIMESTAMP should be the timestamp where selection ownership will be
+   assumed.
+   DND_DATA is the local value that will be used for selection requests
+   with `pending_dnd_time'.
    Update the Vselection_alist so that we can reply to later requests for
    our selection.  */
 
 void
 x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
-                Lisp_Object frame)
+                Lisp_Object frame, Lisp_Object dnd_data, Time timestamp)
 {
   struct frame *f = XFRAME (frame);
   Window selecting_window = FRAME_X_WINDOW (f);
   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   Display *display = dpyinfo->display;
-  Time timestamp = dpyinfo->last_user_time;
   Atom selection_atom = symbol_to_x_atom (dpyinfo, selection_name);
 
+  if (!timestamp)
+    timestamp = dpyinfo->last_user_time;
+
   block_input ();
   x_catch_errors (display);
   XSetSelectionOwner (display, selection_atom, selecting_window, timestamp);
@@ -276,8 +282,9 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object 
selection_value,
     Lisp_Object selection_data;
     Lisp_Object prev_value;
 
-    selection_data = list4 (selection_name, selection_value,
-                           INT_TO_INTEGER (timestamp), frame);
+    selection_data = list5 (selection_name, selection_value,
+                           INT_TO_INTEGER (timestamp), frame,
+                           dnd_data);
     prev_value = LOCAL_SELECTION (selection_name, dpyinfo);
 
     tset_selection_alist
@@ -310,12 +317,15 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object 
selection_value,
    If LOCAL_VALUE is non-nil, use it as the local copy.  Also allow
    quitting in that case, and let DPYINFO be NULL.
 
+   If NEED_ALTERNATE is true, use the drag-and-drop local value
+   instead.
+
    This calls random Lisp code, and may signal or gc.  */
 
 static Lisp_Object
 x_get_local_selection (Lisp_Object selection_symbol, Lisp_Object target_type,
                       bool local_request, struct x_display_info *dpyinfo,
-                      Lisp_Object local_value)
+                      Lisp_Object local_value, bool need_alternate)
 {
   Lisp_Object tem;
   Lisp_Object handler_fn, value, check;
@@ -354,7 +364,10 @@ x_get_local_selection (Lisp_Object selection_symbol, 
Lisp_Object target_type,
       if (CONSP (handler_fn))
        handler_fn = XCDR (handler_fn);
 
-      tem = XCAR (XCDR (local_value));
+      if (!need_alternate)
+       tem = XCAR (XCDR (local_value));
+      else
+       tem = XCAR (XCDR (XCDR (XCDR (XCDR (local_value)))));
 
       if (STRINGP (tem))
        {
@@ -788,7 +801,7 @@ x_handle_selection_request (struct selection_input_event 
*event)
   Lisp_Object local_selection_data;
   bool success = false;
   specpdl_ref count = SPECPDL_INDEX ();
-  bool pushed;
+  bool pushed, use_alternate;
   Lisp_Object alias, tem;
 
   alias = Vx_selection_alias_alist;
@@ -814,14 +827,6 @@ x_handle_selection_request (struct selection_input_event 
*event)
   if (!dpyinfo)
     goto REALLY_DONE;
 
-  /* This is how the XDND protocol recommends dropping text onto a
-     target that doesn't support XDND.  */
-  if (SELECTION_EVENT_TIME (event) == pending_dnd_time + 1
-      || SELECTION_EVENT_TIME (event) == pending_dnd_time + 2)
-    /* Always reply with the contents of PRIMARY, since that's where
-       the selection data is.  */
-    selection_symbol = QPRIMARY;
-
   local_selection_data = LOCAL_SELECTION (selection_symbol, dpyinfo);
 
   /* Decline if we don't own any selections.  */
@@ -834,6 +839,14 @@ x_handle_selection_request (struct selection_input_event 
*event)
       && local_selection_time > SELECTION_EVENT_TIME (event))
     goto DONE;
 
+  use_alternate = false;
+
+  /* This is how the XDND protocol recommends dropping text onto a
+     target that doesn't support XDND.  */
+  if (SELECTION_EVENT_TIME (event) == pending_dnd_time + 1
+      || SELECTION_EVENT_TIME (event) == pending_dnd_time + 2)
+    use_alternate = true;
+
   block_input ();
   pushed = true;
   x_push_current_selection_request (event, dpyinfo);
@@ -874,7 +887,8 @@ x_handle_selection_request (struct selection_input_event 
*event)
 
          if (subproperty != None)
            subsuccess = x_convert_selection (selection_symbol, subtarget,
-                                             subproperty, true, dpyinfo);
+                                             subproperty, true, dpyinfo,
+                                             use_alternate);
          if (!subsuccess)
            ASET (multprop, 2*j+1, Qnil);
        }
@@ -891,7 +905,8 @@ x_handle_selection_request (struct selection_input_event 
*event)
        property = SELECTION_EVENT_TARGET (event);
       success = x_convert_selection (selection_symbol,
                                     target_symbol, property,
-                                    false, dpyinfo);
+                                    false, dpyinfo,
+                                    use_alternate);
     }
 
  DONE:
@@ -926,7 +941,8 @@ x_handle_selection_request (struct selection_input_event 
*event)
 static bool
 x_convert_selection (Lisp_Object selection_symbol,
                     Lisp_Object target_symbol, Atom property,
-                    bool for_multiple, struct x_display_info *dpyinfo)
+                    bool for_multiple, struct x_display_info *dpyinfo,
+                    bool use_alternate)
 {
   Lisp_Object lisp_selection;
   struct selection_data *cs;
@@ -934,7 +950,7 @@ x_convert_selection (Lisp_Object selection_symbol,
 
   lisp_selection
     = x_get_local_selection (selection_symbol, target_symbol,
-                            false, dpyinfo, Qnil);
+                            false, dpyinfo, Qnil, use_alternate);
 
   frame = selection_request_stack;
 
@@ -2100,7 +2116,7 @@ On Nextstep, FRAME is unused.  */)
 
   CHECK_SYMBOL (selection);
   if (NILP (value)) error ("VALUE may not be nil");
-  x_own_selection (selection, value, frame);
+  x_own_selection (selection, value, frame, Qnil, 0);
   return value;
 }
 
@@ -2150,7 +2166,7 @@ On Nextstep, TIME-STAMP and TERMINAL are unused.  */)
     }
 
   val = x_get_local_selection (selection_symbol, target_type, true,
-                              FRAME_DISPLAY_INFO (f), Qnil);
+                              FRAME_DISPLAY_INFO (f), Qnil, false);
 
   if (NILP (val) && FRAME_LIVE_P (f))
     {
@@ -2318,7 +2334,7 @@ run.  */)
   check_window_system (decode_live_frame (frame));
 
   result = x_get_local_selection (name, target, true,
-                                 NULL, value);
+                                 NULL, value, false);
 
   if (CONSP (result) && SYMBOLP (XCAR (result)))
     {
diff --git a/src/xterm.c b/src/xterm.c
index 76da1064eb..9d260ded83 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -3798,7 +3798,14 @@ x_dnd_do_unsupported_drop (struct x_display_info 
*dpyinfo,
 {
   XEvent event;
   int dest_x, dest_y;
-  Window child_return, child;
+  Window child_return, child, owner;
+  Lisp_Object current_value;
+  struct frame *f;
+
+  f = decode_window_system_frame (frame);
+
+  if (NILP (value))
+    return;
 
   event.xbutton.serial = 0;
   event.xbutton.send_event = True;
@@ -3806,7 +3813,6 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
   event.xbutton.root = dpyinfo->root_window;
   event.xbutton.x_root = root_x;
   event.xbutton.y_root = root_y;
-
   x_catch_errors (dpyinfo->display);
 
   child = dpyinfo->root_window;
@@ -3819,11 +3825,25 @@ x_dnd_do_unsupported_drop (struct x_display_info 
*dpyinfo,
         && child_return != None)
     child = child_return;
 
-  if (CONSP (value))
-    x_own_selection (QPRIMARY, Fnth (make_fixnum (1), value),
-                    frame);
-  else
-    error ("Lost ownership of XdndSelection");
+  if (!CONSP (value))
+    goto cancel;
+
+  current_value = assq_no_quit (QPRIMARY,
+                               dpyinfo->terminal->Vselection_alist);
+
+  if (!NILP (current_value))
+    current_value = XCAR (XCDR (current_value));
+
+  x_own_selection (QPRIMARY, current_value, frame,
+                  XCAR (XCDR (value)), before);
+
+  owner = XGetSelectionOwner (dpyinfo->display, XA_PRIMARY);
+
+  /* If we didn't successfully obtain selection ownership, refrain
+     from generating events that will insert something else.  */
+
+  if (owner != FRAME_X_WINDOW (f))
+    goto cancel;
 
   event.xbutton.window = child;
   event.xbutton.subwindow = None;
@@ -3847,6 +3867,7 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
   XSendEvent (dpyinfo->display, child,
              True, ButtonReleaseMask, &event);
 
+ cancel:
   x_uncatch_errors ();
 }
 
diff --git a/src/xterm.h b/src/xterm.h
index f7b93529cb..76d35aaf34 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1600,7 +1600,8 @@ extern void x_clipboard_manager_save_all (void);
 extern Lisp_Object x_timestamp_for_selection (struct x_display_info *,
                                              Lisp_Object);
 extern void x_set_pending_dnd_time (Time);
-extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object);
+extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object,
+                            Lisp_Object, Time);
 extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
                                  bool);
 extern char *x_get_atom_name (struct x_display_info *, Atom, bool *)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]