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.
This commit is contained in:
parent
9ff2f0be32
commit
aea799838b
5 changed files with 49 additions and 17 deletions
|
@ -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
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -6712,7 +6712,9 @@ Emacs. For that reason, they are not mentioned here. Consult
|
|||
|
||||
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));
|
||||
|
||||
|
|
20
src/xterm.c
20
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");
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue