emacs-diffs
[Top][All Lists]
Advanced

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

master 28f720e7c4: Make dragging stuff to a window above a frame work


From: Po Lu
Subject: master 28f720e7c4: Make dragging stuff to a window above a frame work
Date: Sun, 3 Apr 2022 06:59:57 -0400 (EDT)

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

    Make dragging stuff to a window above a frame work
    
    * doc/lispref/frames.texi (Mouse Tracking):
    * etc/NEWS: Announce new `drag-source' value of `track-mouse'.
    * lisp/mouse.el (mouse-drag-and-drop-region): Use new value of
    `track-mouse' during interprogram drag and drop.
    
    * src/keyboard.c (make_lispy_position): Handle nil values of f
    correctly.
    * src/xdisp.c (define_frame_cursor1): Ignore if `drag-source' as
    well.
    (syms_of_xdisp): New defsym `drag-source'.
    * src/xterm.c (XTmouse_position): Implement `drag-source'.
    (mouse_or_wdesc_frame): Likewise.
---
 doc/lispref/frames.texi | 16 ++++++++++++----
 etc/NEWS                |  6 ++++++
 lisp/mouse.el           | 32 ++++++++++++++++++++++----------
 src/keyboard.c          | 38 ++++++++++++++++++++++++--------------
 src/xdisp.c             |  4 +++-
 src/xterm.c             | 29 +++++++++++++++++++++++------
 6 files changed, 90 insertions(+), 35 deletions(-)

diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index ebf426fe50..057f070ccc 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -3512,10 +3512,18 @@ enabled.  Typically, @var{body} would use 
@code{read-event} to read
 the motion events and modify the display accordingly.  @xref{Motion
 Events}, for the format of mouse motion events.
 
-The value of @code{track-mouse} is that of the last form in @var{body}.
-You should design @var{body} to return when it sees the up-event that
-indicates the release of the button, or whatever kind of event means
-it is time to stop tracking.
+The value of @code{track-mouse} is that of the last form in
+@var{body}.  You should design @var{body} to return when it sees the
+up-event that indicates the release of the button, or whatever kind of
+event means it is time to stop tracking.  Its value also controls how
+mouse events are reported while a mouse button is held down: if it is
+@code{dropping} or @code{drag-source}, the motion events are reported
+relative to the frame underneath the pointer.  If there is no such
+frame, the events will be reported relative to the frame the mouse
+buttons were first pressed on.  In addition, the @code{posn-window} of
+the mouse position list will be @code{nil} if the value is
+@code{drag-source}.  This is useful to determine if a frame is not
+directly visible underneath the mouse pointer.
 
 The @code{track-mouse} form causes Emacs to generate mouse motion
 events by binding the variable @code{track-mouse} to a
diff --git a/etc/NEWS b/etc/NEWS
index 037a9724d8..f81d194a2f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1331,6 +1331,12 @@ functions.
 
 * Lisp Changes in Emacs 29.1
 
++++
+** 'track-mouse' can be a new value 'drag-source'.
+This means the same as 'dropping', but modifies the mouse position
+list in reported motion events if there is no frame underneath the
+mouse pointer.
+
 +++
 ** New function 'x-begin-drag'.
 This function initiates a drag-and-drop request with the contents of
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 92e289b4ce..f42492bb5d 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -3085,7 +3085,18 @@ is copied instead of being cut."
     (ignore-errors
       (catch 'cross-program-drag
         (track-mouse
-          (setq track-mouse 'dropping)
+          (setq track-mouse (if mouse-drag-and-drop-region-cross-program
+                                ;; When `track-mouse' is `drop', we
+                                ;; get events with a posn-window of
+                                ;; the grabbed frame even if some
+                                ;; window is between that and the
+                                ;; pointer.  This makes dragging to a
+                                ;; window on top of a frame
+                                ;; impossible.  With this value of
+                                ;; `track-mouse', no frame is returned
+                                ;; in that particular case.
+                                'drag-source
+                              'drop))
           ;; When event was "click" instead of "drag", skip loop.
           (while (progn
                    (setq event (read-key))      ; read-event or read-key
@@ -3151,15 +3162,16 @@ is copied instead of being cut."
               (when (and mouse-drag-and-drop-region-cross-program
                          (display-graphic-p)
                          (fboundp 'x-begin-drag)
-                         (framep (posn-window (event-end event)))
-                         (let ((location (posn-x-y (event-end event)))
-                               (frame (posn-window (event-end event))))
-                           (or (< (car location) 0)
-                               (< (cdr location) 0)
-                               (> (car location)
-                                  (frame-pixel-width frame))
-                               (> (cdr location)
-                                  (frame-pixel-height frame)))))
+                         (or (and (framep (posn-window (event-end event)))
+                                  (let ((location (posn-x-y (event-end event)))
+                                        (frame (posn-window (event-end 
event))))
+                                    (or (< (car location) 0)
+                                        (< (cdr location) 0)
+                                        (> (car location)
+                                           (frame-pixel-width frame))
+                                        (> (cdr location)
+                                           (frame-pixel-height frame)))))
+                             (not (posn-window (event-end event)))))
                 (mouse-drag-and-drop-region-hide-tooltip)
                 (gui-set-selection 'XdndSelection value-selection)
                 (let ((drag-action-or-frame
diff --git a/src/keyboard.c b/src/keyboard.c
index 8b451d834d..d34bec48a6 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5253,13 +5253,13 @@ make_lispy_position (struct frame *f, Lisp_Object x, 
Lisp_Object y,
 
   /* Report mouse events on the tab bar and (on GUI frames) on the
      tool bar.  */
-  if ((WINDOWP (f->tab_bar_window)
-       && EQ (window_or_frame, f->tab_bar_window))
+  if (f && ((WINDOWP (f->tab_bar_window)
+            && EQ (window_or_frame, f->tab_bar_window))
 #ifndef HAVE_EXT_TOOL_BAR
-      || (WINDOWP (f->tool_bar_window)
-         && EQ (window_or_frame, f->tool_bar_window))
+           || (WINDOWP (f->tool_bar_window)
+               && EQ (window_or_frame, f->tool_bar_window))
 #endif
-      )
+           ))
     {
       /* While 'track-mouse' is neither nil nor t, do not report this
         event as something that happened on the tool or tab bar since
@@ -5283,7 +5283,7 @@ make_lispy_position (struct frame *f, Lisp_Object x, 
Lisp_Object y,
       window_or_frame = Qnil;
     }
 
-  if (FRAME_TERMINAL (f)->toolkit_position_hook)
+  if (f && FRAME_TERMINAL (f)->toolkit_position_hook)
     {
       FRAME_TERMINAL (f)->toolkit_position_hook (f, mx, my, &menu_bar_p,
                                                 &tool_bar_p);
@@ -5524,9 +5524,16 @@ make_lispy_position (struct frame *f, Lisp_Object x, 
Lisp_Object y,
        }
 #endif
     }
-
   else
-    window_or_frame = Qnil;
+    {
+      if (EQ (track_mouse, Qdrag_source))
+       {
+         xret = mx;
+         yret = my;
+       }
+
+      window_or_frame = Qnil;
+    }
 
   return Fcons (window_or_frame,
                Fcons (posn,
@@ -12563,12 +12570,15 @@ and the minor mode maps regardless of 
`overriding-local-map'.  */);
               doc: /* Non-nil means generate motion events for mouse motion.
 The special values `dragging' and `dropping' assert that the mouse
 cursor retains its appearance during mouse motion.  Any non-nil value
-but `dropping' asserts that motion events always relate to the frame
-where the mouse movement started.  The value `dropping' asserts
-that motion events relate to the frame where the mouse cursor is seen
-when generating the event.  If there's no such frame, such motion
-events relate to the frame where the mouse movement started.  */);
-
+but `dropping' or `drag-source' asserts that motion events always
+relate to the frame where the mouse movement started.  The value
+`dropping' asserts that motion events relate to the frame where the
+mouse cursor is seen when generating the event.  If there's no such
+frame, such motion events relate to the frame where the mouse movement
+started.  The value `drag-source' is like `dropping', but the
+`posn-window' will be nil in mouse position lists inside mouse
+movement events if there is no frame directly visible underneath the
+mouse pointer.  */);
   DEFVAR_KBOARD ("system-key-alist", Vsystem_key_alist,
                 doc: /* Alist of system-specific X windows key symbols.
 Each element should have the form (N . SYMBOL) where N is the
diff --git a/src/xdisp.c b/src/xdisp.c
index 62c8f9d4d9..d731308173 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -33856,7 +33856,8 @@ define_frame_cursor1 (struct frame *f, Emacs_Cursor 
cursor, Lisp_Object pointer)
     return;
 
   /* Do not change cursor shape while dragging mouse.  */
-  if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping))
+  if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
+      || EQ (track_mouse, Qdrag_source))
     return;
 
   if (!NILP (pointer))
@@ -35678,6 +35679,7 @@ be let-bound around code that needs to disable messages 
temporarily. */);
 
   DEFSYM (Qdragging, "dragging");
   DEFSYM (Qdropping, "dropping");
+  DEFSYM (Qdrag_source, "drag-source");
 
   DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
   DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
diff --git a/src/xterm.c b/src/xterm.c
index e7c671de74..aef3d2d840 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -9811,7 +9811,8 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
 
        x_catch_errors (FRAME_X_DISPLAY (*fp));
 
-       if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping))
+       if (gui_mouse_grabbed (dpyinfo) && !EQ (track_mouse, Qdropping)
+           && !EQ (track_mouse, Qdrag_source))
          {
            /* If mouse was grabbed on a frame, give coords for that frame
               even if the mouse is now outside it.  */
@@ -9900,7 +9901,8 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
          }
 
        if ((!f1 || FRAME_TOOLTIP_P (f1))
-           && EQ (track_mouse, Qdropping)
+           && (EQ (track_mouse, Qdropping)
+               || EQ (track_mouse, Qdrag_source))
            && gui_mouse_grabbed (dpyinfo))
          {
            /* When dropping then if we didn't get a frame or only a
@@ -9916,12 +9918,26 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
                                   root_x, root_y, &win_x, &win_y,
                                   /* Child of win.  */
                                   &child);
-           f1 = dpyinfo->last_mouse_frame;
+
+           if (!EQ (track_mouse, Qdrag_source))
+             f1 = dpyinfo->last_mouse_frame;
+           else
+             {
+               /* Don't set FP but do set WIN_X and WIN_Y in this
+                  case, so make_lispy_movement knows which
+                  coordinates to report.  */
+               *bar_window = Qnil;
+               *part = 0;
+               *fp = NULL;
+               XSETINT (*x, win_x);
+               XSETINT (*y, win_y);
+               *timestamp = dpyinfo->last_mouse_movement_time;
+             }
          }
        else if (f1 && FRAME_TOOLTIP_P (f1))
          f1 = NULL;
 
-       if (x_had_errors_p (FRAME_X_DISPLAY (*fp)))
+       if (x_had_errors_p (dpyinfo->display))
          f1 = NULL;
 
        x_uncatch_errors_after_check ();
@@ -9931,7 +9947,7 @@ XTmouse_position (struct frame **fp, int insist, 
Lisp_Object *bar_window,
          {
            struct scroll_bar *bar;
 
-            bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win, 2);
+            bar = x_window_to_scroll_bar (dpyinfo->display, win, 2);
 
            if (bar)
              {
@@ -12735,7 +12751,8 @@ mouse_or_wdesc_frame (struct x_display_info *dpyinfo, 
int wdesc)
                        ? dpyinfo->last_mouse_frame
                        : NULL);
 
-  if (lm_f && !EQ (track_mouse, Qdropping))
+  if (lm_f && !EQ (track_mouse, Qdropping)
+      && !EQ (track_mouse, Qdrag_source))
     return lm_f;
   else
     {



reply via email to

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