[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 17393c0db0: Allow dragging and dropping multiple actions
From: |
Po Lu |
Subject: |
master 17393c0db0: Allow dragging and dropping multiple actions |
Date: |
Wed, 23 Mar 2022 21:43:09 -0400 (EDT) |
branch: master
commit 17393c0db0fbd4ba9b7ddcdc668974ef8a65107d
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Allow dragging and dropping multiple actions
* doc/lispref/frames.texi (Drag and Drop): Document new meaning
of `action'.
* lisp/term/haiku-win.el (x-begin-drag): Correct for new meaning
of `action'.
* src/xfns.c (Fx_begin_drag): Handle new alist meaning of
`action'.
* src/xterm.c (x_dnd_begin_drag_and_drop): New parameters
`ask_action_list', `ask_action_names' and `n_ask_actions'.
* src/xterm.h: Update prototypes.
---
doc/lispref/frames.texi | 5 ++++
lisp/term/haiku-win.el | 4 +++-
src/xfns.c | 61 +++++++++++++++++++++++++++++++++++++++++++++----
src/xterm.c | 43 ++++++++++++++++++++++++++++++++--
src/xterm.h | 3 ++-
5 files changed, 107 insertions(+), 9 deletions(-)
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 9717fa2978..a031b25e47 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -4061,6 +4061,11 @@ the drop target; or @code{XdndActionMove}, which means
copy as with
@code{XdndActionCopy}, and in addition the caller should delete
whatever was stored in that selection after copying it.
+@var{action} may also be an alist which associates between symbols
+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
diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el
index 8ec959a758..1433620875 100644
--- a/lisp/term/haiku-win.el
+++ b/lisp/term/haiku-win.el
@@ -224,7 +224,9 @@ take effect on menu items until the menu bar is updated
again."
(push (cadr selection-result)
(cdr (alist-get (car selection-result) message
nil nil #'equal))))))))
- (prog1 (or action 'XdndActionCopy)
+ (prog1 (or (and (symbolp action)
+ action)
+ 'XdndActionCopy)
(haiku-drag-message (or frame (selected-frame))
message))))
diff --git a/src/xfns.c b/src/xfns.c
index eae409eed2..c4b924e007 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -6614,17 +6614,28 @@ 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.
+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
+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. */)
(Lisp_Object targets, Lisp_Object action, Lisp_Object frame,
Lisp_Object return_frame)
{
struct frame *f = decode_window_system_frame (frame);
- int ntargets = 0;
+ int ntargets = 0, nnames = 0;
+ ptrdiff_t len;
char *target_names[2048];
Atom *target_atoms;
- Lisp_Object lval, original;
+ Lisp_Object lval, original, tem, t1, t2;
Atom xaction;
+ Atom action_list[2048];
+ char *name_list[2048];
+ char *scratch;
+
+ USE_SAFE_ALLOCA;
CHECK_LIST (targets);
original = targets;
@@ -6650,10 +6661,48 @@ instead. */)
xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove;
else if (EQ (action, QXdndActionLink))
xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink;
- else if (EQ (action, QXdndActionAsk))
- xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
else if (EQ (action, QXdndActionPrivate))
xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate;
+ else if (CONSP (action))
+ {
+ xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
+ original = action;
+
+ CHECK_LIST (action);
+ for (; CONSP (action); action = XCDR (action))
+ {
+ tem = XCAR (action);
+ CHECK_CONS (tem);
+ t1 = XCAR (tem);
+ t2 = XCDR (tem);
+ CHECK_SYMBOL (t1);
+ CHECK_STRING (t2);
+
+ if (nnames < 2048)
+ {
+ if (EQ (t1, QXdndActionCopy))
+ action_list[nnames] = FRAME_DISPLAY_INFO
(f)->Xatom_XdndActionCopy;
+ else if (EQ (t1, QXdndActionMove))
+ action_list[nnames] = FRAME_DISPLAY_INFO
(f)->Xatom_XdndActionMove;
+ else if (EQ (t1, QXdndActionLink))
+ action_list[nnames] = FRAME_DISPLAY_INFO
(f)->Xatom_XdndActionLink;
+ else if (EQ (t1, QXdndActionPrivate))
+ action_list[nnames] = FRAME_DISPLAY_INFO
(f)->Xatom_XdndActionPrivate;
+ else
+ signal_error ("Invalid drag-and-drop action", tem);
+
+ scratch = SSDATA (ENCODE_UTF_8 (t2));
+ len = strlen (scratch);
+ name_list[nnames] = SAFE_ALLOCA (len + 1);
+ strncpy (name_list[nnames], scratch, len + 1);
+
+ nnames++;
+ }
+ else
+ error ("Too many actions");
+ }
+ CHECK_LIST_END (action, original);
+ }
else
signal_error ("Invalid drag-and-drop action", action);
@@ -6666,8 +6715,10 @@ 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));
+ xaction, !NILP (return_frame), action_list,
+ (const char **) &name_list, nnames);
+ SAFE_FREE ();
return lval;
}
diff --git a/src/xterm.c b/src/xterm.c
index e4c17644e4..0543f152ed 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -6942,7 +6942,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)
+ bool return_frame_p, Atom *ask_action_list,
+ const char **ask_action_names,
+ size_t n_ask_actions)
{
#ifndef USE_GTK
XEvent next_event;
@@ -6951,9 +6953,11 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
XWindowAttributes root_window_attrs;
struct input_event hold_quit;
struct frame *any;
- char *atom_name;
+ char *atom_name, *ask_actions;
Lisp_Object action, ltimestamp;
specpdl_ref ref;
+ ptrdiff_t i, end, fill;
+ XTextProperty prop;
if (!FRAME_VISIBLE_P (f))
error ("Frame is invisible");
@@ -6972,6 +6976,41 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
else
x_dnd_selection_timestamp = XFIXNUM (ltimestamp);
+ if (n_ask_actions)
+ {
+ ask_actions = NULL;
+ end = 0;
+
+ for (i = 0; i < n_ask_actions; ++i)
+ {
+ fill = end;
+ end += strlen (ask_action_names[i]) + 1;
+
+ if (ask_actions)
+ ask_actions = xrealloc (ask_actions, end);
+ else
+ ask_actions = xmalloc (end);
+
+ strncpy (ask_actions + fill,
+ ask_action_names[i],
+ end - fill);
+ }
+
+ prop.value = (unsigned char *) ask_actions;
+ prop.encoding = XA_STRING;
+ prop.format = 8;
+ prop.nitems = end;
+
+ XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ &prop, FRAME_DISPLAY_INFO
(f)->Xatom_XdndActionDescription);
+ xfree (ask_actions);
+
+ XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+ FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM,
32,
+ PropModeReplace, (unsigned char *) ask_action_list,
+ n_ask_actions);
+ }
+
x_dnd_in_progress = true;
x_dnd_frame = f;
x_dnd_last_seen_window = FRAME_X_WINDOW (f);
diff --git a/src/xterm.h b/src/xterm.h
index 2a11f87e16..4a71968b04 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1373,7 +1373,8 @@ extern void x_scroll_bar_configure (GdkEvent *);
#endif
extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,
- bool);
+ bool, Atom *, const char **,
+ size_t);
extern void x_set_dnd_targets (Atom *, int);
INLINE int
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 17393c0db0: Allow dragging and dropping multiple actions,
Po Lu <=