diff options
| author | Po Lu | 2022-04-06 20:29:30 +0800 |
|---|---|---|
| committer | Po Lu | 2022-04-06 20:30:24 +0800 |
| commit | c0bb11432ee07228d8819cc98c6ce29ccd42ae97 (patch) | |
| tree | 38ea48626b74e8fd4fd2826397b7dff1b212b39a /src | |
| parent | 406da54bc63b1099b6e51b3d3e025712a16a1912 (diff) | |
| download | emacs-c0bb11432ee07228d8819cc98c6ce29ccd42ae97.tar.gz emacs-c0bb11432ee07228d8819cc98c6ce29ccd42ae97.zip | |
Move some X11 drag and drop processing to Lisp
* lisp/term/x-win.el: Set unsupported drop function.
* lisp/x-dnd.el (x-dnd-handle-unsupported-drop): New function.
* src/keyboard.c (kbd_buffer_get_event): Handle
UNSUPPORTED_DROP_EVENT.
* src/termhooks.h (enum event_kind): New event
`UNSUPPORTED_DROP_EVENT'.
* src/xterm.c (x_dnd_send_unsupported_drop): Send those events
instead.
(x_dnd_do_unsupported_drop): Move actual unsupported drop
handling here.
(syms_of_xterm): New variable `x-dnd-unsupported-drop-function'.
* src/xterm.h: Update prototypes.
Diffstat (limited to 'src')
| -rw-r--r-- | src/keyboard.c | 35 | ||||
| -rw-r--r-- | src/termhooks.h | 19 | ||||
| -rw-r--r-- | src/xterm.c | 126 | ||||
| -rw-r--r-- | src/xterm.h | 3 |
4 files changed, 146 insertions, 37 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index d34bec48a6b..d99fe4be092 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -4006,6 +4006,41 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 4006 | } | 4006 | } |
| 4007 | break; | 4007 | break; |
| 4008 | 4008 | ||
| 4009 | #ifdef HAVE_X_WINDOWS | ||
| 4010 | case UNSUPPORTED_DROP_EVENT: | ||
| 4011 | { | ||
| 4012 | struct frame *f; | ||
| 4013 | |||
| 4014 | kbd_fetch_ptr = next_kbd_event (event); | ||
| 4015 | input_pending = readable_events (0); | ||
| 4016 | |||
| 4017 | f = XFRAME (event->ie.frame_or_window); | ||
| 4018 | |||
| 4019 | if (!FRAME_LIVE_P (f)) | ||
| 4020 | break; | ||
| 4021 | |||
| 4022 | if (!NILP (Vx_dnd_unsupported_drop_function)) | ||
| 4023 | { | ||
| 4024 | if (!NILP (call6 (Vx_dnd_unsupported_drop_function, | ||
| 4025 | XCAR (XCDR (event->ie.arg)), event->ie.x, | ||
| 4026 | event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))), | ||
| 4027 | make_uint (event->ie.code), | ||
| 4028 | event->ie.frame_or_window))) | ||
| 4029 | break; | ||
| 4030 | } | ||
| 4031 | |||
| 4032 | x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f), | ||
| 4033 | event->ie.frame_or_window, | ||
| 4034 | XCAR (event->ie.arg), | ||
| 4035 | XCAR (XCDR (event->ie.arg)), | ||
| 4036 | (Window) event->ie.code, | ||
| 4037 | XFIXNUM (event->ie.x), | ||
| 4038 | XFIXNUM (event->ie.y), | ||
| 4039 | event->ie.timestamp); | ||
| 4040 | break; | ||
| 4041 | } | ||
| 4042 | #endif | ||
| 4043 | |||
| 4009 | #ifdef HAVE_EXT_MENU_BAR | 4044 | #ifdef HAVE_EXT_MENU_BAR |
| 4010 | case MENU_BAR_ACTIVATE_EVENT: | 4045 | case MENU_BAR_ACTIVATE_EVENT: |
| 4011 | { | 4046 | { |
diff --git a/src/termhooks.h b/src/termhooks.h index 93ac9ba0d2e..0f02b56e9ee 100644 --- a/src/termhooks.h +++ b/src/termhooks.h | |||
| @@ -208,6 +208,25 @@ enum event_kind | |||
| 208 | representation of the dropped items. | 208 | representation of the dropped items. |
| 209 | .timestamp gives a timestamp (in | 209 | .timestamp gives a timestamp (in |
| 210 | milliseconds) for the click. */ | 210 | milliseconds) for the click. */ |
| 211 | #ifdef HAVE_X_WINDOWS | ||
| 212 | UNSUPPORTED_DROP_EVENT, /* Event sent when the regular C | ||
| 213 | drag-and-drop machinery could not | ||
| 214 | handle a drop to a window. | ||
| 215 | |||
| 216 | .code is the XID of the window that | ||
| 217 | could not be dropped to. | ||
| 218 | |||
| 219 | .arg is a list of the local value of | ||
| 220 | XdndSelection, a list of selection | ||
| 221 | targets, and the intended action to | ||
| 222 | be taken upon drop, and .timestamp | ||
| 223 | gives the timestamp where the drop | ||
| 224 | happened. | ||
| 225 | |||
| 226 | .x and .y give the coordinates of | ||
| 227 | the drop originating from the root | ||
| 228 | window. */ | ||
| 229 | #endif | ||
| 211 | USER_SIGNAL_EVENT, /* A user signal. | 230 | USER_SIGNAL_EVENT, /* A user signal. |
| 212 | code is a number identifying it, | 231 | code is a number identifying it, |
| 213 | index into lispy_user_signals. */ | 232 | index into lispy_user_signals. */ |
diff --git a/src/xterm.c b/src/xterm.c index b6aed004ed3..b6fe5fda0fa 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -2774,45 +2774,35 @@ x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo, | |||
| 2774 | 2774 | ||
| 2775 | Dropping on windows that do not support XDND | 2775 | Dropping on windows that do not support XDND |
| 2776 | 2776 | ||
| 2777 | Since middle clicking is the universal shortcut for pasting in X, | 2777 | Since middle clicking is the universal shortcut for pasting |
| 2778 | one can drop data into a window that does not support XDND by: | 2778 | in X, one can drop data into a window that does not support |
| 2779 | 2779 | XDND by: | |
| 2780 | 1. After the mouse has been released to trigger the drop, obtain | 2780 | |
| 2781 | ownership of XA_PRIMARY. | 2781 | 1. After the mouse has been released to trigger the drop, |
| 2782 | 2782 | obtain ownership of XA_PRIMARY. | |
| 2783 | 2. Send a ButtonPress event and then a ButtonRelease event to the | 2783 | |
| 2784 | deepest subwindow containing the mouse to simulate a middle click. | 2784 | 2. Send a ButtonPress event and then a ButtonRelease event to |
| 2785 | The times for these events should be the time of the actual button | 2785 | the deepest subwindow containing the mouse to simulate a |
| 2786 | release +1 and +2, respectively. These values will not be used by | 2786 | middle click. The times for these events should be the time |
| 2787 | anybody else, so one can unambiguously recognize the resulting | 2787 | of the actual button release +1 and +2, respectively. These |
| 2788 | XConvertSelection() request. | 2788 | values will not be used by anybody else, so one can |
| 2789 | 2789 | unambiguously recognize the resulting `XConvertSelection' | |
| 2790 | 3. If a request for XA_PRIMARY arrives bearing the timestamp of | 2790 | request. |
| 2791 | either the ButtonPress or the ButtonRelease event, treat it as a | 2791 | |
| 2792 | request for XdndSelection. Note that you must use the X data | 2792 | 3. If a request for XA_PRIMARY arrives bearing the timestamp |
| 2793 | types instead of the MIME types in this case. (e.g. XA_STRING | 2793 | of either the ButtonPress or the ButtonRelease event, treat |
| 2794 | instead of text/plain). */ | 2794 | it as a request for XdndSelection. Note that you must use |
| 2795 | static void | 2795 | the X data types instead of the MIME types in this case. |
| 2796 | x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window, | 2796 | (e.g. XA_STRING instead of text/plain). */ |
| 2797 | int root_x, int root_y, Time before) | 2797 | void |
| 2798 | x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo, | ||
| 2799 | Lisp_Object frame, Lisp_Object value, | ||
| 2800 | Lisp_Object targets, Window target_window, | ||
| 2801 | int root_x, int root_y, Time before) | ||
| 2798 | { | 2802 | { |
| 2799 | XEvent event; | 2803 | XEvent event; |
| 2800 | int dest_x, dest_y; | 2804 | int dest_x, dest_y; |
| 2801 | Window child_return, child; | 2805 | Window child_return, child; |
| 2802 | Lisp_Object frame; | ||
| 2803 | int i; | ||
| 2804 | |||
| 2805 | for (i = 0; i < x_dnd_n_targets; ++i) | ||
| 2806 | { | ||
| 2807 | if (x_dnd_targets[i] == XA_STRING | ||
| 2808 | || x_dnd_targets[i] == dpyinfo->Xatom_TEXT | ||
| 2809 | || x_dnd_targets[i] == dpyinfo->Xatom_COMPOUND_TEXT | ||
| 2810 | || x_dnd_targets[i] == dpyinfo->Xatom_UTF8_STRING) | ||
| 2811 | break; | ||
| 2812 | } | ||
| 2813 | |||
| 2814 | if (i == x_dnd_n_targets) | ||
| 2815 | return; | ||
| 2816 | 2806 | ||
| 2817 | event.xbutton.type = ButtonPress; | 2807 | event.xbutton.type = ButtonPress; |
| 2818 | event.xbutton.serial = 0; | 2808 | event.xbutton.serial = 0; |
| @@ -2822,8 +2812,6 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo | |||
| 2822 | event.xbutton.x_root = root_x; | 2812 | event.xbutton.x_root = root_x; |
| 2823 | event.xbutton.y_root = root_y; | 2813 | event.xbutton.y_root = root_y; |
| 2824 | 2814 | ||
| 2825 | XSETFRAME (frame, x_dnd_frame); | ||
| 2826 | |||
| 2827 | x_catch_errors (dpyinfo->display); | 2815 | x_catch_errors (dpyinfo->display); |
| 2828 | 2816 | ||
| 2829 | child = dpyinfo->root_window; | 2817 | child = dpyinfo->root_window; |
| @@ -2868,6 +2856,55 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo | |||
| 2868 | x_uncatch_errors (); | 2856 | x_uncatch_errors (); |
| 2869 | } | 2857 | } |
| 2870 | 2858 | ||
| 2859 | static void | ||
| 2860 | x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window, | ||
| 2861 | int root_x, int root_y, Time before) | ||
| 2862 | { | ||
| 2863 | struct input_event ie; | ||
| 2864 | Lisp_Object targets, arg; | ||
| 2865 | int i; | ||
| 2866 | char **atom_names, *name; | ||
| 2867 | |||
| 2868 | EVENT_INIT (ie); | ||
| 2869 | targets = Qnil; | ||
| 2870 | atom_names = alloca (sizeof *atom_names * x_dnd_n_targets); | ||
| 2871 | |||
| 2872 | if (!XGetAtomNames (dpyinfo->display, x_dnd_targets, | ||
| 2873 | x_dnd_n_targets, atom_names)) | ||
| 2874 | return; | ||
| 2875 | |||
| 2876 | for (i = x_dnd_n_targets; i > 0; --i) | ||
| 2877 | { | ||
| 2878 | targets = Fcons (build_string (atom_names[i - 1]), | ||
| 2879 | targets); | ||
| 2880 | XFree (atom_names[i - 1]); | ||
| 2881 | } | ||
| 2882 | |||
| 2883 | name = XGetAtomName (dpyinfo->display, | ||
| 2884 | x_dnd_wanted_action); | ||
| 2885 | |||
| 2886 | if (name) | ||
| 2887 | { | ||
| 2888 | arg = intern (name); | ||
| 2889 | XFree (name); | ||
| 2890 | } | ||
| 2891 | else | ||
| 2892 | arg = Qnil; | ||
| 2893 | |||
| 2894 | ie.kind = UNSUPPORTED_DROP_EVENT; | ||
| 2895 | ie.code = (unsigned) target_window; | ||
| 2896 | ie.arg = list3 (assq_no_quit (QXdndSelection, | ||
| 2897 | dpyinfo->terminal->Vselection_alist), | ||
| 2898 | targets, arg); | ||
| 2899 | ie.timestamp = before; | ||
| 2900 | |||
| 2901 | XSETINT (ie.x, root_x); | ||
| 2902 | XSETINT (ie.y, root_y); | ||
| 2903 | XSETFRAME (ie.frame_or_window, x_dnd_frame); | ||
| 2904 | |||
| 2905 | kbd_buffer_store_event (&ie); | ||
| 2906 | } | ||
| 2907 | |||
| 2871 | static Window | 2908 | static Window |
| 2872 | x_dnd_get_target_window (struct x_display_info *dpyinfo, | 2909 | x_dnd_get_target_window (struct x_display_info *dpyinfo, |
| 2873 | int root_x, int root_y, int *proto_out, | 2910 | int root_x, int root_y, int *proto_out, |
| @@ -23273,4 +23310,19 @@ It should either be nil, or accept two arguments FRAME and POSITION, | |||
| 23273 | where FRAME is the frame the mouse is on top of, and POSITION is a | 23310 | where FRAME is the frame the mouse is on top of, and POSITION is a |
| 23274 | mouse position list. */); | 23311 | mouse position list. */); |
| 23275 | Vx_dnd_movement_function = Qnil; | 23312 | Vx_dnd_movement_function = Qnil; |
| 23313 | |||
| 23314 | DEFVAR_LISP ("x-dnd-unsupported-drop-function", Vx_dnd_unsupported_drop_function, | ||
| 23315 | doc: /* Function called when trying to drop on an unsupported window. | ||
| 23316 | This function is called whenever the user tries to drop | ||
| 23317 | something on a window that does not support either the XDND or | ||
| 23318 | Motif protocols for drag-and-drop. It should return a non-nil | ||
| 23319 | value if the drop was handled by the function, and nil if it was | ||
| 23320 | not. It should accept several arguments TARGETS, X, Y, ACTION, | ||
| 23321 | WINDOW-ID and FRAME, where TARGETS is the list of targets that | ||
| 23322 | was passed to `x-begin-drag', WINDOW-ID is the numeric XID of | ||
| 23323 | the window that is being dropped on, X and Y are the root | ||
| 23324 | window-relative coordinates where the drop happened, ACTION | ||
| 23325 | is the action that was passed to `x-begin-drag', and FRAME is | ||
| 23326 | the frame which initiated the drag-and-drop operation. */); | ||
| 23327 | Vx_dnd_unsupported_drop_function = Qnil; | ||
| 23276 | } | 23328 | } |
diff --git a/src/xterm.h b/src/xterm.h index 4eb16d0c142..d8898162d11 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -1391,6 +1391,9 @@ extern void x_scroll_bar_configure (GdkEvent *); | |||
| 1391 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, | 1391 | extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, |
| 1392 | Lisp_Object, Atom *, const char **, | 1392 | Lisp_Object, Atom *, const char **, |
| 1393 | size_t, bool); | 1393 | size_t, bool); |
| 1394 | extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object, | ||
| 1395 | Lisp_Object, Lisp_Object, Window, int, | ||
| 1396 | int, Time); | ||
| 1394 | extern void x_set_dnd_targets (Atom *, int); | 1397 | extern void x_set_dnd_targets (Atom *, int); |
| 1395 | 1398 | ||
| 1396 | INLINE int | 1399 | INLINE int |