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.
This commit is contained in:
parent
ac3bb7e754
commit
17393c0db0
5 changed files with 107 additions and 9 deletions
|
@ -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
|
||||
|
|
|
@ -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))))
|
||||
|
||||
|
|
61
src/xfns.c
61
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;
|
||||
}
|
||||
|
||||
|
|
43
src/xterm.c
43
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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue