]> git.eshelyaron.com Git - emacs.git/commitdiff
Allow dragging files from dired to windows on the same frame
authorPo Lu <luangruo@yahoo.com>
Fri, 25 Mar 2022 13:24:03 +0000 (21:24 +0800)
committerPo Lu <luangruo@yahoo.com>
Fri, 25 Mar 2022 13:24:27 +0000 (21:24 +0800)
* doc/lispref/frames.texi (Drag and Drop): Document new
parameter to `x-begin-drag'.
* lisp/dired.el (dired-mouse-drag): Utilize new parameter.
* lisp/term/haiku-win.el (x-begin-drag): Add new parameter.
* src/xfns.c (Fx_begin_drag): New parameter
`allow-current-frame'.  Fix typo and update doc string.
* src/xterm.c (x_dnd_get_window_proto): Respect
`x_dnd_allow_current_frame'.
(x_dnd_begin_drag_and_drop): New parameter
`allow_current_frame'.
* src/xterm.h: Update prototypes.

doc/lispref/frames.texi
lisp/dired.el
lisp/term/haiku-win.el
src/xfns.c
src/xterm.c
src/xterm.h

index a031b25e47411d2e1f9fc359e4f244fc2cab3dc8..90924cf47b5eedc16f05f00af04a6970dc0b004b 100644 (file)
@@ -4042,12 +4042,13 @@ you want to alter Emacs behavior, you can customize these variables.
   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
@@ -4070,7 +4071,8 @@ 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.
+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
index d6c5721ca284d5cdff40f6a8399cdf167f64f302..b1208cec255dd556024f308a3b3aa6d904476b42 100644 (file)
@@ -1710,7 +1710,8 @@ see `dired-use-ls-dired' for more details.")
                                 "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)))))))))
 
index 1433620875b0079d0775297c7c55ce047a94b904..d04da2fdae402016a3f24f2917e2037bb35015b5 100644 (file)
@@ -199,7 +199,7 @@ This is necessary because on Haiku `use-system-tooltip' doesn't
 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"))
index 52649b38dd1a4fce4b4b73a0a5f3d95ca96b8bfb..3f3054422a840e179110111d4f02c497217ff81e 100644 (file)
@@ -6582,7 +6582,7 @@ The coordinates X and Y are interpreted in pixels relative to a position
   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
@@ -6612,7 +6612,7 @@ https://freedesktop.org/wiki/Specifications/XDND/.
 
 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
@@ -6620,9 +6620,13 @@ a string describing ITEM to the user.  The drop target is expected to
 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;
@@ -6650,7 +6654,7 @@ instead.  */)
          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
@@ -6725,7 +6729,8 @@ instead.  */)
   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;
index 968ea78c1a16856d0598ed169858d0c5aab48f16..6bd43511f8d8b2440bd94f4989b55bd8a01e42bc 100644 (file)
@@ -799,6 +799,7 @@ static bool x_dnd_in_progress;
 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'.
 
@@ -1368,7 +1369,8 @@ x_dnd_get_window_proto (struct x_display_info *dpyinfo, Window wdesc)
   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);
@@ -7310,7 +7312,7 @@ 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)
+                          size_t n_ask_actions, bool allow_current_frame)
 {
 #ifndef USE_GTK
   XEvent next_event;
@@ -7394,7 +7396,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
 
   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;
@@ -7405,6 +7407,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
   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)
     {
index 5a7b09925ea4026d6b312cfb242dcb4a40573517..a155245f810cc6f61b731363a0bdd2c813008f13 100644 (file)
@@ -1383,7 +1383,7 @@ extern void x_scroll_bar_configure (GdkEvent *);
 
 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