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.
This commit is contained in:
parent
441ce4672d
commit
28f720e7c4
6 changed files with 90 additions and 35 deletions
|
@ -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
|
||||
|
|
6
etc/NEWS
6
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
29
src/xterm.c
29
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
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue