diff options
| author | Po Lu | 2022-03-24 09:42:47 +0800 |
|---|---|---|
| committer | Po Lu | 2022-03-24 09:42:47 +0800 |
| commit | 17393c0db0fbd4ba9b7ddcdc668974ef8a65107d (patch) | |
| tree | e7ba375a3a7f75a1868f78c8c9ab328bfd3f278e /src | |
| parent | ac3bb7e75413c1df60cf2de5c29e999df518a62d (diff) | |
| download | emacs-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.c | 61 | ||||
| -rw-r--r-- | src/xterm.c | 43 | ||||
| -rw-r--r-- | src/xterm.h | 3 |
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 | |||
| 6614 | mouse pointer moves onto an Emacs frame, after first moving out of | 6614 | mouse pointer moves onto an Emacs frame, after first moving out of |
| 6615 | FRAME. | 6615 | FRAME. |
| 6616 | 6616 | ||
| 6617 | If ACTION is a list and not nil, its elements are assumed to be a cons | ||
| 6618 | of (ITEM . STRING), where ITEM is the name of an action, and STRING is | ||
| 6619 | a string describing ITEM to the user. The drop target is expected to | ||
| 6620 | prompt the user to choose between any of the actions in the list. | ||
| 6621 | |||
| 6617 | If ACTION is not specified or nil, `XdndActionCopy' is used | 6622 | If ACTION is not specified or nil, `XdndActionCopy' is used |
| 6618 | instead. */) | 6623 | instead. */) |
| 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 | ||
| 6943 | Lisp_Object | 6943 | Lisp_Object |
| 6944 | x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, | 6944 | x_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 | ||
| 1375 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, | 1375 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, |
| 1376 | bool); | 1376 | bool, Atom *, const char **, |
| 1377 | size_t); | ||
| 1377 | extern void x_set_dnd_targets (Atom *, int); | 1378 | extern void x_set_dnd_targets (Atom *, int); |
| 1378 | 1379 | ||
| 1379 | INLINE int | 1380 | INLINE int |