aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-03-24 09:42:47 +0800
committerPo Lu2022-03-24 09:42:47 +0800
commit17393c0db0fbd4ba9b7ddcdc668974ef8a65107d (patch)
treee7ba375a3a7f75a1868f78c8c9ab328bfd3f278e /src
parentac3bb7e75413c1df60cf2de5c29e999df518a62d (diff)
downloademacs-17393c0db0fbd4ba9b7ddcdc668974ef8a65107d.tar.gz
emacs-17393c0db0fbd4ba9b7ddcdc668974ef8a65107d.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/xfns.c61
-rw-r--r--src/xterm.c43
-rw-r--r--src/xterm.h3
3 files changed, 99 insertions, 8 deletions
diff --git a/src/xfns.c b/src/xfns.c
index eae409eed24..c4b924e007f 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
6614mouse pointer moves onto an Emacs frame, after first moving out of 6614mouse pointer moves onto an Emacs frame, after first moving out of
6615FRAME. 6615FRAME.
6616 6616
6617If ACTION is a list and not nil, its elements are assumed to be a cons
6618of (ITEM . STRING), where ITEM is the name of an action, and STRING is
6619a string describing ITEM to the user. The drop target is expected to
6620prompt the user to choose between any of the actions in the list.
6621
6617If ACTION is not specified or nil, `XdndActionCopy' is used 6622If ACTION is not specified or nil, `XdndActionCopy' is used
6618instead. */) 6623instead. */)
6619 (Lisp_Object targets, Lisp_Object action, Lisp_Object frame, 6624 (Lisp_Object targets, Lisp_Object action, Lisp_Object frame,
6620 Lisp_Object return_frame) 6625 Lisp_Object return_frame)
6621{ 6626{
6622 struct frame *f = decode_window_system_frame (frame); 6627 struct frame *f = decode_window_system_frame (frame);
6623 int ntargets = 0; 6628 int ntargets = 0, nnames = 0;
6629 ptrdiff_t len;
6624 char *target_names[2048]; 6630 char *target_names[2048];
6625 Atom *target_atoms; 6631 Atom *target_atoms;
6626 Lisp_Object lval, original; 6632 Lisp_Object lval, original, tem, t1, t2;
6627 Atom xaction; 6633 Atom xaction;
6634 Atom action_list[2048];
6635 char *name_list[2048];
6636 char *scratch;
6637
6638 USE_SAFE_ALLOCA;
6628 6639
6629 CHECK_LIST (targets); 6640 CHECK_LIST (targets);
6630 original = targets; 6641 original = targets;
@@ -6650,10 +6661,48 @@ instead. */)
6650 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove; 6661 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove;
6651 else if (EQ (action, QXdndActionLink)) 6662 else if (EQ (action, QXdndActionLink))
6652 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink; 6663 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink;
6653 else if (EQ (action, QXdndActionAsk))
6654 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
6655 else if (EQ (action, QXdndActionPrivate)) 6664 else if (EQ (action, QXdndActionPrivate))
6656 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate; 6665 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate;
6666 else if (CONSP (action))
6667 {
6668 xaction = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionAsk;
6669 original = action;
6670
6671 CHECK_LIST (action);
6672 for (; CONSP (action); action = XCDR (action))
6673 {
6674 tem = XCAR (action);
6675 CHECK_CONS (tem);
6676 t1 = XCAR (tem);
6677 t2 = XCDR (tem);
6678 CHECK_SYMBOL (t1);
6679 CHECK_STRING (t2);
6680
6681 if (nnames < 2048)
6682 {
6683 if (EQ (t1, QXdndActionCopy))
6684 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionCopy;
6685 else if (EQ (t1, QXdndActionMove))
6686 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionMove;
6687 else if (EQ (t1, QXdndActionLink))
6688 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionLink;
6689 else if (EQ (t1, QXdndActionPrivate))
6690 action_list[nnames] = FRAME_DISPLAY_INFO (f)->Xatom_XdndActionPrivate;
6691 else
6692 signal_error ("Invalid drag-and-drop action", tem);
6693
6694 scratch = SSDATA (ENCODE_UTF_8 (t2));
6695 len = strlen (scratch);
6696 name_list[nnames] = SAFE_ALLOCA (len + 1);
6697 strncpy (name_list[nnames], scratch, len + 1);
6698
6699 nnames++;
6700 }
6701 else
6702 error ("Too many actions");
6703 }
6704 CHECK_LIST_END (action, original);
6705 }
6657 else 6706 else
6658 signal_error ("Invalid drag-and-drop action", action); 6707 signal_error ("Invalid drag-and-drop action", action);
6659 6708
@@ -6666,8 +6715,10 @@ instead. */)
6666 6715
6667 x_set_dnd_targets (target_atoms, ntargets); 6716 x_set_dnd_targets (target_atoms, ntargets);
6668 lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time, 6717 lval = x_dnd_begin_drag_and_drop (f, FRAME_DISPLAY_INFO (f)->last_user_time,
6669 xaction, !NILP (return_frame)); 6718 xaction, !NILP (return_frame), action_list,
6719 (const char **) &name_list, nnames);
6670 6720
6721 SAFE_FREE ();
6671 return lval; 6722 return lval;
6672} 6723}
6673 6724
diff --git a/src/xterm.c b/src/xterm.c
index e4c17644e42..0543f152eda 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)
6942 6942
6943Lisp_Object 6943Lisp_Object
6944x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, 6944x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
6945 bool return_frame_p) 6945 bool return_frame_p, Atom *ask_action_list,
6946 const char **ask_action_names,
6947 size_t n_ask_actions)
6946{ 6948{
6947#ifndef USE_GTK 6949#ifndef USE_GTK
6948 XEvent next_event; 6950 XEvent next_event;
@@ -6951,9 +6953,11 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
6951 XWindowAttributes root_window_attrs; 6953 XWindowAttributes root_window_attrs;
6952 struct input_event hold_quit; 6954 struct input_event hold_quit;
6953 struct frame *any; 6955 struct frame *any;
6954 char *atom_name; 6956 char *atom_name, *ask_actions;
6955 Lisp_Object action, ltimestamp; 6957 Lisp_Object action, ltimestamp;
6956 specpdl_ref ref; 6958 specpdl_ref ref;
6959 ptrdiff_t i, end, fill;
6960 XTextProperty prop;
6957 6961
6958 if (!FRAME_VISIBLE_P (f)) 6962 if (!FRAME_VISIBLE_P (f))
6959 error ("Frame is invisible"); 6963 error ("Frame is invisible");
@@ -6972,6 +6976,41 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
6972 else 6976 else
6973 x_dnd_selection_timestamp = XFIXNUM (ltimestamp); 6977 x_dnd_selection_timestamp = XFIXNUM (ltimestamp);
6974 6978
6979 if (n_ask_actions)
6980 {
6981 ask_actions = NULL;
6982 end = 0;
6983
6984 for (i = 0; i < n_ask_actions; ++i)
6985 {
6986 fill = end;
6987 end += strlen (ask_action_names[i]) + 1;
6988
6989 if (ask_actions)
6990 ask_actions = xrealloc (ask_actions, end);
6991 else
6992 ask_actions = xmalloc (end);
6993
6994 strncpy (ask_actions + fill,
6995 ask_action_names[i],
6996 end - fill);
6997 }
6998
6999 prop.value = (unsigned char *) ask_actions;
7000 prop.encoding = XA_STRING;
7001 prop.format = 8;
7002 prop.nitems = end;
7003
7004 XSetTextProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7005 &prop, FRAME_DISPLAY_INFO (f)->Xatom_XdndActionDescription);
7006 xfree (ask_actions);
7007
7008 XChangeProperty (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7009 FRAME_DISPLAY_INFO (f)->Xatom_XdndActionList, XA_ATOM, 32,
7010 PropModeReplace, (unsigned char *) ask_action_list,
7011 n_ask_actions);
7012 }
7013
6975 x_dnd_in_progress = true; 7014 x_dnd_in_progress = true;
6976 x_dnd_frame = f; 7015 x_dnd_frame = f;
6977 x_dnd_last_seen_window = FRAME_X_WINDOW (f); 7016 x_dnd_last_seen_window = FRAME_X_WINDOW (f);
diff --git a/src/xterm.h b/src/xterm.h
index 2a11f87e167..4a71968b047 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1373,7 +1373,8 @@ extern void x_scroll_bar_configure (GdkEvent *);
1373#endif 1373#endif
1374 1374
1375extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, 1375extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,
1376 bool); 1376 bool, Atom *, const char **,
1377 size_t);
1377extern void x_set_dnd_targets (Atom *, int); 1378extern void x_set_dnd_targets (Atom *, int);
1378 1379
1379INLINE int 1380INLINE int