On capable window systems, Emacs also supports dragging contents
from its frames to windows of other applications.
-@defun x-begin-drag targets &optional action frame return-frame
+@defun x-begin-drag targets &optional action frame return-frame allow-current-frame
This function begins a drag from @var{frame}, and returns when the
drag-and-drop operation ends, either because the drop was successful,
or because the drop was rejected. The drop occurs when all mouse
buttons are released on top of an X window other than @var{frame} (the
-@dfn{drop target}).
+@dfn{drop target}), or any X window if @var{allow-current-frame} is
+non-@code{nil}.
@var{targets} is a list of strings describing selection targets, much
like the @var{data-type} argument to @code{gui-get-selection}, that
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.
+while also being able to drag content to other programs, but 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
"text/x-dnd-username")
(if (eq 'dired-mouse-drag-files 'link)
'XdndActionLink
- 'XdndActionCopy)))
+ 'XdndActionCopy)
+ nil nil t))
(error (when (eq (event-basic-type new-event) 'mouse-1)
(push new-event unread-command-events)))))))))
take effect on menu items until the menu bar is updated again."
(force-mode-line-update t))
-(defun x-begin-drag (targets &optional action frame _return-frame)
+(defun x-begin-drag (targets &optional action frame _return-frame _allow-current-frame)
"SKIP: real doc in xfns.c."
(unless haiku-dnd-selection-value
(error "No local value for XdndSelection"))
return Qnil;
}
-DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 4, 0,
+DEFUN ("x-begin-drag", Fx_begin_drag, Sx_begin_drag, 1, 5, 0,
doc: /* Begin dragging contents on FRAME, with targets TARGETS.
TARGETS is a list of strings, which defines the X selection targets
that will be available to the drop target. Block until the mouse
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.
+FRAME. (This is not guaranteed to work on some systems.)
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
prompt the user to choose between any of the actions in the list.
If ACTION is not specified or nil, `XdndActionCopy' is used
-instead. */)
+instead.
+
+If ALLOW-CURRENT-FRAME is not specified or nil, then the drop target
+is allowed to be FRAME. Otherwise, no action will be taken if the
+mouse buttons are released on top of FRAME. */)
(Lisp_Object targets, Lisp_Object action, Lisp_Object frame,
- Lisp_Object return_frame)
+ Lisp_Object return_frame, Lisp_Object allow_current_frame)
{
struct frame *f = decode_window_system_frame (frame);
int ntargets = 0, nnames = 0;
scratch = SSDATA (XCAR (targets));
len = strlen (scratch);
target_names[ntargets] = SAFE_ALLOCA (len + 1);
- strncpy (target_names[ntargets], scratch, len + 1);;
+ strncpy (target_names[ntargets], scratch, len + 1);
ntargets++;
}
else
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,
- (const char **) &name_list, nnames);
+ (const char **) &name_list, nnames,
+ !NILP (allow_current_frame));
SAFE_FREE ();
return lval;
static bool x_dnd_waiting_for_finish;
static Window x_dnd_pending_finish_target;
static int x_dnd_waiting_for_finish_proto;
+static bool x_dnd_allow_current_frame;
/* Whether or not to return a frame from `x_dnd_begin_drag_and_drop'.
unsigned long n, left;
bool had_errors;
- if (wdesc == None || wdesc == FRAME_OUTER_WINDOW (x_dnd_frame))
+ if (wdesc == None || (!x_dnd_allow_current_frame
+ && wdesc == FRAME_OUTER_WINDOW (x_dnd_frame)))
return -1;
x_catch_errors (dpyinfo->display);
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)
+ size_t n_ask_actions, bool allow_current_frame)
{
#ifndef USE_GTK
XEvent next_event;
x_dnd_in_progress = true;
x_dnd_frame = f;
- x_dnd_last_seen_window = FRAME_OUTER_WINDOW (f);
+ x_dnd_last_seen_window = None;
x_dnd_last_protocol_version = -1;
x_dnd_mouse_rect_target = None;
x_dnd_action = None;
x_dnd_use_toplevels
= x_wm_supports (f, FRAME_DISPLAY_INFO (f)->Xatom_net_client_list_stacking);
x_dnd_toplevels = NULL;
+ x_dnd_allow_current_frame = allow_current_frame;
if (x_dnd_use_toplevels)
{
extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,
bool, Atom *, const char **,
- size_t);
+ size_t, bool);
extern void x_set_dnd_targets (Atom *, int);
INLINE int