]> git.eshelyaron.com Git - emacs.git/commitdiff
Make dragging stuff to a window above a frame work
authorPo Lu <luangruo@yahoo.com>
Sun, 3 Apr 2022 10:59:12 +0000 (18:59 +0800)
committerPo Lu <luangruo@yahoo.com>
Sun, 3 Apr 2022 10:59:12 +0000 (18:59 +0800)
* 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
etc/NEWS
lisp/mouse.el
src/keyboard.c
src/xdisp.c
src/xterm.c

index ebf426fe501c8a5c180bf6871514cd34b5582218..057f070cccae22a35dd02e8419b5d342d50c0609 100644 (file)
@@ -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
index 037a9724d8a252c4cf581494d3ba2a9691dc92e0..f81d194a2f031632ffc2916977fa2d8ea24d155c 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1331,6 +1331,12 @@ functions.
 \f
 * 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
index 92e289b4cedc077999de0b3ac23b0517d2156444..f42492bb5d33eadba946ab87fcd9affa993a1a36 100644 (file)
@@ -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
index 8b451d834d1a79b796356a4cea5b22467844e5f9..d34bec48a6b8ebe558979d840afdf702acc091b7 100644 (file)
@@ -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
index 62c8f9d4d9317a3878f910d0f87b121398c6b6b8..d7313081733666eb6a3eac2bfe2efa0f0f779de5 100644 (file)
@@ -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");
index e7c671de744e73f5f95dab38c8c1b2506f5ece48..aef3d2d840f983612a1ec11e105aa7c6f69be8f9 100644 (file)
@@ -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
     {