[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master eb6d74a26c: Return the correct action from the Lisp side of drag-
From: |
Po Lu |
Subject: |
master eb6d74a26c: Return the correct action from the Lisp side of drag-and-drop |
Date: |
Fri, 1 Jul 2022 21:08:02 -0400 (EDT) |
branch: master
commit eb6d74a26c64e6aa444f21b12a7ab9951a00bfa5
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Return the correct action from the Lisp side of drag-and-drop
* lisp/x-dnd.el (x-dnd-handle-drag-n-drop-event): Select
`window' when handling internal DND events.
(x-dnd-handle-unsupported-drop): Return an appropriate action.
* src/keyboard.c (kbd_buffer_get_event):
* src/termhooks.h (enum event_kind): Delete
`UNSUPPORTED_DROP_EVENT'.
* src/xterm.c (x_dnd_send_unsupported_drop): Set flags instead
of recording input event.
(x_clear_dnd_monitors): Rename to `x_clear_dnd_variables'. Also
clear unsupported drop data.
(x_dnd_begin_drag_and_drop): Run unsupported drop function
inline (and safely), and use its return value if it returned a
symbol.
(syms_of_xterm): Update doc string of
`x-dnd-unsupported-drop-function'.
* src/xterm.h: Update declarations.
---
lisp/x-dnd.el | 34 +++++++----
src/keyboard.c | 50 ----------------
src/termhooks.h | 24 --------
src/xterm.c | 180 ++++++++++++++++++++++++++------------------------------
src/xterm.h | 1 -
5 files changed, 106 insertions(+), 183 deletions(-)
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index d78f926ee7..8a7f3e2436 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -422,6 +422,8 @@ Currently XDND, Motif and old KDE 1.x protocols are
recognized."
x-dnd-xdnd-to-action)))
(targets (cddr client-message))
(local-value (nth 2 client-message)))
+ (when (windowp window)
+ (select-window window))
(x-dnd-save-state window nil nil
(apply #'vector targets))
(x-dnd-maybe-call-test-function window action)
@@ -1154,19 +1156,25 @@ X and Y are the root window coordinates of the drop.
FRAME is the frame the drop originated on.
WINDOW-ID is the X window the drop should happen to.
LOCAL-SELECTION-DATA is the local selection data of the drop."
- (not (and (or (eq action 'XdndActionCopy)
- (eq action 'XdndActionMove))
- (not (and x-dnd-use-offix-drop local-selection-data
- (or (not (eq x-dnd-use-offix-drop 'files))
- (member "FILE_NAME" targets))
- (x-dnd-do-offix-drop targets x
- y frame window-id
- local-selection-data)))
- (or
- (member "STRING" targets)
- (member "UTF8_STRING" targets)
- (member "COMPOUND_TEXT" targets)
- (member "TEXT" targets)))))
+ (let ((chosen-action nil))
+ (not (and (or (eq action 'XdndActionCopy)
+ (eq action 'XdndActionMove))
+ (not (and x-dnd-use-offix-drop local-selection-data
+ (or (not (eq x-dnd-use-offix-drop 'files))
+ (member "FILE_NAME" targets))
+ (when (x-dnd-do-offix-drop targets x
+ y frame window-id
+ local-selection-data)
+ (setq chosen-action 'XdndActionCopy))))
+ (let ((delegate-p (or (member "STRING" targets)
+ (member "UTF8_STRING" targets)
+ (member "COMPOUND_TEXT" targets)
+ (member "TEXT" targets))))
+ (prog1 delegate-p
+ ;; A string will avoid the drop emulation done in C
+ ;; code, but won't be returned from `x-begin-drag'.
+ (setq chosen-action (unless delegate-p ""))))))
+ chosen-action))
(defvar x-dnd-targets-list)
(defvar x-dnd-native-test-function)
diff --git a/src/keyboard.c b/src/keyboard.c
index 4cac20eb4b..bed8307b6f 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4036,56 +4036,6 @@ kbd_buffer_get_event (KBOARD **kbp,
}
break;
-#ifdef HAVE_X_WINDOWS
- case UNSUPPORTED_DROP_EVENT:
- {
- struct frame *f;
-
- kbd_fetch_ptr = next_kbd_event (event);
- input_pending = readable_events (0);
-
- /* This means this event was already handled in
- `x_dnd_begin_drag_and_drop'. */
- if (event->ie.modifiers < x_dnd_unsupported_event_level)
- break;
-
- f = XFRAME (event->ie.frame_or_window);
-
- if (!FRAME_LIVE_P (f))
- break;
-
- if (!NILP (Vx_dnd_unsupported_drop_function))
- {
- if (!NILP (call8 (Vx_dnd_unsupported_drop_function,
- XCAR (XCDR (event->ie.arg)), event->ie.x,
- event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))),
- make_uint (event->ie.code),
- event->ie.frame_or_window,
- make_int (event->ie.timestamp),
- Fcopy_sequence (XCAR (event->ie.arg)))))
- break;
- }
-
- /* `x-dnd-unsupported-drop-function' could have deleted the
- event frame. */
- if (!FRAME_LIVE_P (f)
- /* This means `x-dnd-use-unsupported-drop' was nil when the
- event was generated. */
- || NILP (XCAR (XCDR (XCDR (XCDR (event->ie.arg))))))
- break;
-
- x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f),
- event->ie.frame_or_window,
- XCAR (event->ie.arg),
- XCAR (XCDR (event->ie.arg)),
- (Window) event->ie.code,
- XFIXNUM (event->ie.x),
- XFIXNUM (event->ie.y),
- event->ie.timestamp);
- break;
- }
-#endif
-
case MONITORS_CHANGED_EVENT:
{
kbd_fetch_ptr = next_kbd_event (event);
diff --git a/src/termhooks.h b/src/termhooks.h
index a1e3e2cde9..c5f1e286e9 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -209,30 +209,6 @@ enum event_kind
representation of the dropped items.
.timestamp gives a timestamp (in
milliseconds) for the click. */
-#ifdef HAVE_X_WINDOWS
- UNSUPPORTED_DROP_EVENT, /* Event sent when the regular C
- drag-and-drop machinery could not
- handle a drop to a window.
-
- .code is the XID of the window that
- could not be dropped to.
-
- .arg is a list of the local value of
- XdndSelection, a list of selection
- targets, and the intended action to
- be taken upon drop, and .timestamp
- gives the timestamp where the drop
- happened.
-
- .modifiers gives a number that
- determines if an event was already
- handled by
- `x_dnd_begin_drag_and_drop'.
-
- .x and .y give the coordinates of
- the drop originating from the root
- window. */
-#endif
USER_SIGNAL_EVENT, /* A user signal.
code is a number identifying it,
index into lispy_user_signals. */
diff --git a/src/xterm.c b/src/xterm.c
index c83ddc6b9e..061bca0684 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1128,10 +1128,6 @@ static Window x_get_window_below (Display *, Window,
int, int, int *, int *);
/* Flag that indicates if a drag-and-drop operation is in progress. */
bool x_dnd_in_progress;
-/* Number that indicates the last "generation" of
- UNSUPPORTED_DROP_EVENTs handled. */
-unsigned x_dnd_unsupported_event_level;
-
/* The frame where the drag-and-drop operation originated. */
struct frame *x_dnd_frame;
@@ -1146,6 +1142,20 @@ struct frame *x_dnd_finish_frame;
important information. */
bool x_dnd_waiting_for_finish;
+/* Flag that means (when set in addition to
+ `x_dnd_waiting_for_finish') to run the unsupported drop function
+ with the given arguments. */
+static bool x_dnd_run_unsupported_drop_function;
+
+/* The "before"-time of the unsupported drop. */
+static Time x_dnd_unsupported_drop_time;
+
+/* The target window of the unsupported drop. */
+static Window x_dnd_unsupported_drop_window;
+
+/* The Lisp data associated with the unsupported drop function. */
+static Lisp_Object x_dnd_unsupported_drop_data;
+
/* Whether or not to move the tooltip along with the mouse pointer
during drag-and-drop. */
static bool x_dnd_update_tooltip;
@@ -3881,12 +3891,10 @@ static void
x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window
target_window,
int root_x, int root_y, Time before)
{
- struct input_event ie;
Lisp_Object targets, arg;
int i;
char **atom_names, *name;
- EVENT_INIT (ie);
targets = Qnil;
atom_names = alloca (sizeof *atom_names * x_dnd_n_targets);
@@ -3894,8 +3902,6 @@ x_dnd_send_unsupported_drop (struct x_display_info
*dpyinfo, Window target_windo
x_dnd_n_targets, atom_names))
return;
- x_dnd_action = dpyinfo->Xatom_XdndActionPrivate;
-
for (i = x_dnd_n_targets; i > 0; --i)
{
targets = Fcons (build_string (atom_names[i - 1]),
@@ -3914,20 +3920,17 @@ x_dnd_send_unsupported_drop (struct x_display_info
*dpyinfo, Window target_windo
else
arg = Qnil;
- ie.kind = UNSUPPORTED_DROP_EVENT;
- ie.code = (unsigned) target_window;
- ie.modifiers = x_dnd_unsupported_event_level;
- ie.arg = list4 (assq_no_quit (QXdndSelection,
- dpyinfo->terminal->Vselection_alist),
- targets, arg, (x_dnd_use_unsupported_drop
- ? Qt : Qnil));
- ie.timestamp = before;
-
- XSETINT (ie.x, root_x);
- XSETINT (ie.y, root_y);
- XSETFRAME (ie.frame_or_window, x_dnd_frame);
+ x_dnd_run_unsupported_drop_function = true;
+ x_dnd_unsupported_drop_time = before;
+ x_dnd_unsupported_drop_window = target_window;
+ x_dnd_unsupported_drop_data
+ = listn (5, assq_no_quit (QXdndSelection,
+ dpyinfo->terminal->Vselection_alist),
+ targets, arg, make_fixnum (root_x),
+ make_fixnum (root_y));
- kbd_buffer_store_event (&ie);
+ x_dnd_waiting_for_finish = true;
+ x_dnd_finish_display = dpyinfo->display;
}
static Window
@@ -4529,10 +4532,14 @@ x_free_dnd_targets (void)
x_dnd_n_targets = 0;
}
+/* Clear some Lisp variables after the drop finishes, so they are
+ freed by the GC. */
+
static void
-x_clear_dnd_monitors (void)
+x_clear_dnd_variables (void)
{
x_dnd_monitors = Qnil;
+ x_dnd_unsupported_drop_data = Qnil;
}
static void
@@ -11311,7 +11318,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
XWindowAttributes root_window_attrs;
struct input_event hold_quit;
char *atom_name, *ask_actions;
- Lisp_Object action, ltimestamp;
+ Lisp_Object action, ltimestamp, val;
specpdl_ref ref, count, base;
ptrdiff_t i, end, fill;
XTextProperty prop;
@@ -11324,9 +11331,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
#ifndef USE_GTK
struct x_display_info *event_display;
#endif
- union buffered_input_event *events, *event;
- int n_events;
- struct frame *event_frame;
base = SPECPDL_INDEX ();
@@ -11334,70 +11338,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
Fx_begin_drag. */
specbind (Qx_dnd_targets_list, selection_target_list);
- /* Before starting drag-and-drop, walk through the keyboard buffer
- to see if there are any UNSUPPORTED_DROP_EVENTs, and run them now
- if they exist, to prevent race conditions from happening due to
- multiple unsupported drops running at once. */
-
- block_input ();
- events = alloca (sizeof *events * KBD_BUFFER_SIZE);
- n_events = 0;
- event = kbd_fetch_ptr;
-
- while (event != kbd_store_ptr)
- {
- if (event->ie.kind == UNSUPPORTED_DROP_EVENT
- && event->ie.modifiers < x_dnd_unsupported_event_level)
- events[n_events++] = *event;
-
- event = (event == kbd_buffer + KBD_BUFFER_SIZE - 1
- ? kbd_buffer : event + 1);
- }
-
- x_dnd_unsupported_event_level += 1;
- unblock_input ();
-
- for (i = 0; i < n_events; ++i)
- {
- maybe_quit ();
-
- event = &events[i];
- event_frame = XFRAME (event->ie.frame_or_window);
-
- if (!FRAME_LIVE_P (event_frame))
- continue;
-
- if (!NILP (Vx_dnd_unsupported_drop_function))
- {
- if (!NILP (call8 (Vx_dnd_unsupported_drop_function,
- XCAR (XCDR (event->ie.arg)), event->ie.x,
- event->ie.y, XCAR (XCDR (XCDR (event->ie.arg))),
- make_uint (event->ie.code),
- event->ie.frame_or_window,
- make_int (event->ie.timestamp),
- Fcopy_sequence (XCAR (event->ie.arg)))))
- continue;
- }
-
- /* `x-dnd-unsupported-drop-function' could have deleted the
- event frame. */
- if (!FRAME_LIVE_P (event_frame)
- /* This means `x-dnd-use-unsupported-drop' was nil when the
- event was generated. */
- || NILP (XCAR (XCDR (XCDR (XCDR (event->ie.arg))))))
- continue;
-
- x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (event_frame),
- event->ie.frame_or_window,
- XCAR (event->ie.arg),
- XCAR (XCDR (event->ie.arg)),
- (Window) event->ie.code,
- XFIXNUM (event->ie.x),
- XFIXNUM (event->ie.y),
- event->ie.timestamp);
- break;
- }
-
if (!FRAME_VISIBLE_P (f))
error ("Frame must be visible");
@@ -11500,6 +11440,8 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
unbind_to (count, Qnil);
}
+ record_unwind_protect_void (x_clear_dnd_variables);
+
if (follow_tooltip)
{
#if defined HAVE_XRANDR || defined USE_GTK
@@ -11510,8 +11452,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
#endif
x_dnd_monitors
= Fx_display_monitor_attributes_list (frame);
-
- record_unwind_protect_void (x_clear_dnd_monitors);
}
x_dnd_update_tooltip = follow_tooltip;
@@ -11558,6 +11498,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
x_dnd_xm_use_help = false;
x_dnd_motif_setup_p = false;
x_dnd_end_window = None;
+ x_dnd_run_unsupported_drop_function = false;
x_dnd_use_toplevels
= x_wm_supports (f, FRAME_DISPLAY_INFO
(f)->Xatom_net_client_list_stacking);
x_dnd_toplevels = NULL;
@@ -11812,6 +11753,50 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time,
Atom xaction,
unbind_to (ref, Qnil);
}
+ if (x_dnd_run_unsupported_drop_function
+ && x_dnd_waiting_for_finish)
+ {
+ x_dnd_run_unsupported_drop_function = false;
+ x_dnd_waiting_for_finish = false;
+ x_dnd_unwind_flag = true;
+
+ ref = SPECPDL_INDEX ();
+ record_unwind_protect_ptr (x_dnd_cleanup_drag_and_drop, f);
+
+ if (!NILP (Vx_dnd_unsupported_drop_function))
+ val = call8 (Vx_dnd_unsupported_drop_function,
+ XCAR (XCDR (x_dnd_unsupported_drop_data)),
+ Fnth (make_fixnum (3),
x_dnd_unsupported_drop_data),
+ Fnth (make_fixnum (4),
x_dnd_unsupported_drop_data),
+ Fnth (make_fixnum (2),
x_dnd_unsupported_drop_data),
+ make_uint (x_dnd_unsupported_drop_window),
+ frame, make_uint (x_dnd_unsupported_drop_time),
+ Fcopy_sequence (XCAR
(x_dnd_unsupported_drop_data)));
+ else
+ val = Qnil;
+
+ if (NILP (val))
+ x_dnd_do_unsupported_drop (FRAME_DISPLAY_INFO (f),
+ frame, XCAR
(x_dnd_unsupported_drop_data),
+ XCAR (XCDR
(x_dnd_unsupported_drop_data)),
+ x_dnd_unsupported_drop_window,
+ XFIXNUM (Fnth (make_fixnum (3),
+
x_dnd_unsupported_drop_data)),
+ XFIXNUM (Fnth (make_fixnum (4),
+
x_dnd_unsupported_drop_data)),
+ x_dnd_unsupported_drop_time);
+
+ if (SYMBOLP (val))
+ x_dnd_action_symbol = val;
+
+ x_dnd_unwind_flag = false;
+ unbind_to (ref, Qnil);
+
+ /* Break out of the loop now, since DND has
+ completed. */
+ break;
+ }
+
#ifdef USE_GTK
if (xg_pending_quit_event.kind != NO_EVENT)
{
@@ -27809,6 +27794,9 @@ syms_of_xterm (void)
x_dnd_selection_alias_cell = Fcons (Qnil, Qnil);
staticpro (&x_dnd_selection_alias_cell);
+ x_dnd_unsupported_drop_data = Qnil;
+ staticpro (&x_dnd_unsupported_drop_data);
+
DEFSYM (Qvendor_specific_keysyms, "vendor-specific-keysyms");
DEFSYM (Qlatin_1, "latin-1");
DEFSYM (Qnow, "now");
@@ -28033,7 +28021,6 @@ mouse position list. */);
DEFVAR_LISP ("x-dnd-unsupported-drop-function",
Vx_dnd_unsupported_drop_function,
doc: /* Function called when trying to drop on an unsupported window.
-
This function is called whenever the user tries to drop something on a
window that does not support either the XDND or Motif protocols for
drag-and-drop. It should return a non-nil value if the drop was
@@ -28046,8 +28033,11 @@ where the drop happened, ACTION is the action that was
passed to
`x-begin-drag', FRAME is the frame which initiated the drag-and-drop
operation, TIME is the X server time when the drop happened, and
LOCAL-SELECTION is the contents of the `XdndSelection' when
-`x-begin-drag' was run, which can be passed to
-`x-get-local-selection'. */);
+`x-begin-drag' was run; its contents can be retrieved by calling the
+function `x-get-local-selection'.
+
+If a symbol is returned, then it will be used as the return value of
+`x-begin-drag'. */);
Vx_dnd_unsupported_drop_function = Qnil;
DEFVAR_INT ("x-color-cache-bucket-size", x_color_cache_bucket_size,
diff --git a/src/xterm.h b/src/xterm.h
index 76d35aaf34..eee7672426 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1669,7 +1669,6 @@ extern bool x_dnd_in_progress;
extern bool x_dnd_waiting_for_finish;
extern struct frame *x_dnd_frame;
extern struct frame *x_dnd_finish_frame;
-extern unsigned x_dnd_unsupported_event_level;
extern int x_error_message_count;
#ifdef HAVE_XINPUT2
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master eb6d74a26c: Return the correct action from the Lisp side of drag-and-drop,
Po Lu <=