summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2022-04-03 18:59:12 +0800
committerPo Lu <luangruo@yahoo.com>2022-04-03 18:59:12 +0800
commit28f720e7c483c37a6c94f6b561e8f175b3af51a4 (patch)
tree96634c9fca9a45633b1f913af066f79a14afad5e
parent441ce4672d4aab14d1bef078692fec7ad4ff0c0a (diff)
downloademacs-28f720e7c483c37a6c94f6b561e8f175b3af51a4.tar.gz
emacs-28f720e7c483c37a6c94f6b561e8f175b3af51a4.tar.bz2
emacs-28f720e7c483c37a6c94f6b561e8f175b3af51a4.zip
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.
-rw-r--r--doc/lispref/frames.texi16
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/mouse.el32
-rw-r--r--src/keyboard.c38
-rw-r--r--src/xdisp.c4
-rw-r--r--src/xterm.c29
6 files changed, 90 insertions, 35 deletions
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index ebf426fe501..057f070ccca 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 037a9724d8a..f81d194a2f0 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1332,6 +1332,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
the selection 'XdndSelection', and returns when a drop occurs.
diff --git a/lisp/mouse.el b/lisp/mouse.el
index 92e289b4ced..f42492bb5d3 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 8b451d834d1..d34bec48a6b 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 62c8f9d4d93..d7313081733 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 e7c671de744..aef3d2d840f 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
{