emacs-diffs
[Top][All Lists]
Advanced

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

master aea799838b: Improve behavior of dragging text to windows on top o


From: Po Lu
Subject: master aea799838b: Improve behavior of dragging text to windows on top of frames
Date: Mon, 4 Apr 2022 01:10:32 -0400 (EDT)

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

    Improve behavior of dragging text to windows on top of frames
    
    * doc/lispref/frames.texi (Drag and Drop): Document new meaning
    of `return-frame' in `x-begin-drag'.
    * lisp/mouse.el (mouse-drag-and-drop-region): Use `now' when
    calling `x-begin-drag'.
    * src/xfns.c (Fx_begin_drag): Update doc string.
    * src/xterm.c (x_dnd_begin_drag_and_drop): Accept return_frame
    as a Lisp_Object and handle Qnow correctly.
    (XTmouse_position): Ignore tooltip frames when processing
    `drag-source'.
    (syms_of_xterm): New defsym `now'.
    * src/xterm.h: Update prototypes.
---
 doc/lispref/frames.texi | 15 +++++++++------
 lisp/mouse.el           | 23 ++++++++++++++++++++---
 src/xfns.c              |  6 ++++--
 src/xterm.c             | 20 +++++++++++++++-----
 src/xterm.h             |  2 +-
 5 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 057f070ccc..85f92d4f62 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -4075,12 +4075,15 @@ describing the available actions, and strings that the 
drop target is
 expected to present to the user to choose between the available
 actions.
 
-If @var{return-frame} is non-nil and the mouse moves over an Emacs
-frame after first moving out of @var{frame}, then the frame to which
-the mouse moves will be returned immediately.  This is useful when you
-want to treat dragging content from one frame to another specially,
-while also being able to drag content to other programs, but is not
-guaranteed to work on all systems and window managers.
+If @var{return-frame} is non-@code{nil} and the mouse moves over an
+Emacs frame after first moving out of @var{frame}, then the frame to
+which the mouse moves will be returned immediately.  If
+@var{return-frame} is the symbol @code{now}, then any frame underneath
+the mouse pointer will be returned and no further work will be done.
+@var{return-frame} useful when you want to treat dragging content from
+one frame to another specially, while also being able to drag content
+to other programs, but it is not guaranteed to work on all systems and
+window managers.
 
 If the drop was rejected or no drop target was found, this function
 returns @code{nil}.  Otherwise, it returns a symbol describing the
diff --git a/lisp/mouse.el b/lisp/mouse.el
index f42492bb5d..26a17365da 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -3061,7 +3061,8 @@ is copied instead of being cut."
          value-selection    ; This remains nil when event was "click".
          text-tooltip
          states
-         window-exempt)
+         window-exempt
+         drag-again-mouse-position)
 
     ;; STATES stores for each window on this frame its start and point
     ;; positions so we can restore them on all windows but for the one
@@ -3171,7 +3172,14 @@ is copied instead of being cut."
                                            (frame-pixel-width frame))
                                         (> (cdr location)
                                            (frame-pixel-height frame)))))
-                             (not (posn-window (event-end event)))))
+                             (and (or (not drag-again-mouse-position)
+                                      (let ((mouse-position 
(mouse-absolute-pixel-position)))
+                                        (or (< 5 (abs (- (car 
drag-again-mouse-position)
+                                                         (car 
mouse-position))))
+                                            (< 5 (abs (- (cdr 
drag-again-mouse-position)
+                                                         (cdr 
mouse-position)))))))
+                                  (not (posn-window (event-end event))))))
+                (setq drag-again-mouse-position nil)
                 (mouse-drag-and-drop-region-hide-tooltip)
                 (gui-set-selection 'XdndSelection value-selection)
                 (let ((drag-action-or-frame
@@ -3182,9 +3190,18 @@ is copied instead of being cut."
                                          (if 
mouse-drag-and-drop-region-cut-when-buffers-differ
                                              'XdndActionMove
                                            'XdndActionCopy)
-                                         (posn-window (event-end event)) t)
+                                         (posn-window (event-end event)) 'now)
                          (quit nil))))
                   (when (framep drag-action-or-frame)
+                    ;; With some window managers `x-begin-drag'
+                    ;; returns a frame sooner than `mouse-position'
+                    ;; will return one, due to over-wide frame windows
+                    ;; being drawn by the window manager.  To avoid
+                    ;; that, we just require the mouse move a few
+                    ;; pixels before beginning another cross-program
+                    ;; drag.
+                    (setq drag-again-mouse-position
+                          (mouse-absolute-pixel-position))
                     (throw 'drag-again nil))
 
                   (let ((min-char (point)))
diff --git a/src/xfns.c b/src/xfns.c
index 4fa919f36a..5cf3eb4199 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -6712,7 +6712,9 @@ https://freedesktop.org/wiki/Specifications/XDND/.
 
 If RETURN-FRAME is non-nil, this function will return the frame if the
 mouse pointer moves onto an Emacs frame, after first moving out of
-FRAME.  (This is not guaranteed to work on some systems.)
+FRAME.  (This is not guaranteed to work on some systems.)  If
+RETURN-FRAME is the symbol `now', any frame underneath the mouse
+pointer will be returned immediately.
 
 If ACTION is a list and not nil, its elements are assumed to be a cons
 of (ITEM . STRING), where ITEM is the name of an action, and STRING is
@@ -6828,7 +6830,7 @@ mouse buttons are released on top of FRAME.  */)
 
   x_set_dnd_targets (target_atoms, ntargets);
   lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time,
-                                   xaction, !NILP (return_frame), action_list,
+                                   xaction, return_frame, action_list,
                                    (const char **) &name_list, nnames,
                                    !NILP (allow_current_frame));
 
diff --git a/src/xterm.c b/src/xterm.c
index e3935bacb9..c70b31c5ad 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -2295,6 +2295,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
 
 static int x_dnd_get_window_proto (struct x_display_info *, Window);
 static Window x_dnd_get_window_proxy (struct x_display_info *, Window);
+static void x_dnd_update_state (struct x_display_info *, Time);
 
 #ifdef USE_XCB
 static void
@@ -8933,9 +8934,9 @@ x_top_window_to_frame (struct x_display_info *dpyinfo, 
int wdesc)
 
 Lisp_Object
 x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
-                          bool return_frame_p, Atom *ask_action_list,
-                          const char **ask_action_names,
-                          size_t n_ask_actions, bool allow_current_frame)
+                          Lisp_Object return_frame, Atom *ask_action_list,
+                          const char **ask_action_names, size_t n_ask_actions,
+                          bool allow_current_frame)
 {
 #ifndef USE_GTK
   XEvent next_event;
@@ -9046,9 +9047,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, 
Atom xaction,
        }
     }
 
-  if (return_frame_p)
+  if (!NILP (return_frame))
     x_dnd_return_frame = 1;
 
+  if (EQ (return_frame, Qnow))
+    x_dnd_return_frame = 2;
+
 #ifdef USE_GTK
   current_count = 0;
 #endif
@@ -9070,6 +9074,9 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, 
Atom xaction,
 
   while (x_dnd_in_progress || x_dnd_waiting_for_finish)
     {
+      if (EQ (return_frame, Qnow))
+       x_dnd_update_state (FRAME_DISPLAY_INFO (f), CurrentTime);
+
       hold_quit.kind = NO_EVENT;
 #ifdef USE_GTK
       current_finish = X_EVENT_NORMAL;
@@ -9951,7 +9958,9 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
                                   /* Child of win.  */
                                   &child);
 
-           if (!EQ (track_mouse, Qdrag_source))
+           if (!EQ (track_mouse, Qdrag_source)
+               /* Don't let tooltips interfere.  */
+               || (f1 && FRAME_TOOLTIP_P (f1)))
              f1 = dpyinfo->last_mouse_frame;
            else
              {
@@ -22662,6 +22671,7 @@ syms_of_xterm (void)
 
   DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
   DEFSYM (Qlatin_1, "latin-1");
+  DEFSYM (Qnow, "now");
 
 #ifdef USE_GTK
   xg_default_icon_file = build_pure_c_string 
("icons/hicolor/scalable/apps/emacs.svg");
diff --git a/src/xterm.h b/src/xterm.h
index 062b34b35c..57036af2bb 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1389,7 +1389,7 @@ extern void x_scroll_bar_configure (GdkEvent *);
 #endif
 
 extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,
-                                             bool, Atom *, const char **,
+                                             Lisp_Object, Atom *, const char 
**,
                                              size_t, bool);
 extern void x_set_dnd_targets (Atom *, int);
 



reply via email to

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