aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-04-06 20:29:30 +0800
committerPo Lu2022-04-06 20:30:24 +0800
commitc0bb11432ee07228d8819cc98c6ce29ccd42ae97 (patch)
tree38ea48626b74e8fd4fd2826397b7dff1b212b39a /src
parent406da54bc63b1099b6e51b3d3e025712a16a1912 (diff)
downloademacs-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.c35
-rw-r--r--src/termhooks.h19
-rw-r--r--src/xterm.c126
-rw-r--r--src/xterm.h3
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
2795static void 2795 the X data types instead of the MIME types in this case.
2796x_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) 2797void
2798x_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
2859static void
2860x_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
2871static Window 2908static Window
2872x_dnd_get_target_window (struct x_display_info *dpyinfo, 2909x_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,
23273where FRAME is the frame the mouse is on top of, and POSITION is a 23310where FRAME is the frame the mouse is on top of, and POSITION is a
23274mouse position list. */); 23311mouse 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.
23316This function is called whenever the user tries to drop
23317something on a window that does not support either the XDND or
23318Motif protocols for drag-and-drop. It should return a non-nil
23319value if the drop was handled by the function, and nil if it was
23320not. It should accept several arguments TARGETS, X, Y, ACTION,
23321WINDOW-ID and FRAME, where TARGETS is the list of targets that
23322was passed to `x-begin-drag', WINDOW-ID is the numeric XID of
23323the window that is being dropped on, X and Y are the root
23324window-relative coordinates where the drop happened, ACTION
23325is the action that was passed to `x-begin-drag', and FRAME is
23326the 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 *);
1391extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom, 1391extern 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);
1394extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object,
1395 Lisp_Object, Lisp_Object, Window, int,
1396 int, Time);
1394extern void x_set_dnd_targets (Atom *, int); 1397extern void x_set_dnd_targets (Atom *, int);
1395 1398
1396INLINE int 1399INLINE int