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
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
(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
(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)))
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
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));
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
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;
}
}
- 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
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;
/* 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
{
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");
#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);