mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-24 07:20:37 +00:00
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.
This commit is contained in:
parent
406da54bc6
commit
c0bb11432e
@ -86,6 +86,7 @@
|
||||
(defvar x-session-id)
|
||||
(defvar x-session-previous-id)
|
||||
(defvar x-dnd-movement-function)
|
||||
(defvar x-dnd-unsupported-drop-function)
|
||||
|
||||
(defun x-handle-no-bitmap-icon (_switch)
|
||||
(setq default-frame-alist (cons '(icon-type) default-frame-alist)))
|
||||
@ -1583,6 +1584,7 @@ frames on all displays."
|
||||
(redisplay))
|
||||
|
||||
(setq x-dnd-movement-function #'x-dnd-movement)
|
||||
(setq x-dnd-unsupported-drop-function #'x-dnd-handle-unsupported-drop)
|
||||
|
||||
(provide 'x-win)
|
||||
(provide 'term/x-win)
|
||||
|
@ -779,6 +779,19 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent."
|
||||
|
||||
;;;
|
||||
|
||||
|
||||
|
||||
;;; Handling drops.
|
||||
|
||||
(defun x-dnd-handle-unsupported-drop (targets _x _y action _window-id _frame)
|
||||
"Return non-nil if the drop described by TARGETS and ACTION should not proceeed."
|
||||
(not (and (or (eq action 'XdndActionCopy)
|
||||
(eq action 'XdndActionMove))
|
||||
(or (member "STRING" targets)
|
||||
(member "UTF8_STRING" targets)
|
||||
(member "COMPOUND_TEXT" targets)
|
||||
(member "TEXT" targets)))))
|
||||
|
||||
(provide 'x-dnd)
|
||||
|
||||
;;; x-dnd.el ends here
|
||||
|
@ -4006,6 +4006,41 @@ 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);
|
||||
|
||||
f = XFRAME (event->ie.frame_or_window);
|
||||
|
||||
if (!FRAME_LIVE_P (f))
|
||||
break;
|
||||
|
||||
if (!NILP (Vx_dnd_unsupported_drop_function))
|
||||
{
|
||||
if (!NILP (call6 (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)))
|
||||
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
|
||||
|
||||
#ifdef HAVE_EXT_MENU_BAR
|
||||
case MENU_BAR_ACTIVATE_EVENT:
|
||||
{
|
||||
|
@ -208,6 +208,25 @@ 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.
|
||||
|
||||
.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. */
|
||||
|
120
src/xterm.c
120
src/xterm.c
@ -2774,45 +2774,35 @@ x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
|
||||
|
||||
Dropping on windows that do not support XDND
|
||||
|
||||
Since middle clicking is the universal shortcut for pasting in X,
|
||||
one can drop data into a window that does not support XDND by:
|
||||
Since middle clicking is the universal shortcut for pasting
|
||||
in X, one can drop data into a window that does not support
|
||||
XDND by:
|
||||
|
||||
1. After the mouse has been released to trigger the drop, obtain
|
||||
ownership of XA_PRIMARY.
|
||||
1. After the mouse has been released to trigger the drop,
|
||||
obtain ownership of XA_PRIMARY.
|
||||
|
||||
2. Send a ButtonPress event and then a ButtonRelease event to the
|
||||
deepest subwindow containing the mouse to simulate a middle click.
|
||||
The times for these events should be the time of the actual button
|
||||
release +1 and +2, respectively. These values will not be used by
|
||||
anybody else, so one can unambiguously recognize the resulting
|
||||
XConvertSelection() request.
|
||||
2. Send a ButtonPress event and then a ButtonRelease event to
|
||||
the deepest subwindow containing the mouse to simulate a
|
||||
middle click. The times for these events should be the time
|
||||
of the actual button release +1 and +2, respectively. These
|
||||
values will not be used by anybody else, so one can
|
||||
unambiguously recognize the resulting `XConvertSelection'
|
||||
request.
|
||||
|
||||
3. If a request for XA_PRIMARY arrives bearing the timestamp of
|
||||
either the ButtonPress or the ButtonRelease event, treat it as a
|
||||
request for XdndSelection. Note that you must use the X data
|
||||
types instead of the MIME types in this case. (e.g. XA_STRING
|
||||
instead of text/plain). */
|
||||
static void
|
||||
x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_window,
|
||||
int root_x, int root_y, Time before)
|
||||
3. If a request for XA_PRIMARY arrives bearing the timestamp
|
||||
of either the ButtonPress or the ButtonRelease event, treat
|
||||
it as a request for XdndSelection. Note that you must use
|
||||
the X data types instead of the MIME types in this case.
|
||||
(e.g. XA_STRING instead of text/plain). */
|
||||
void
|
||||
x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
|
||||
Lisp_Object frame, Lisp_Object value,
|
||||
Lisp_Object targets, Window target_window,
|
||||
int root_x, int root_y, Time before)
|
||||
{
|
||||
XEvent event;
|
||||
int dest_x, dest_y;
|
||||
Window child_return, child;
|
||||
Lisp_Object frame;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < x_dnd_n_targets; ++i)
|
||||
{
|
||||
if (x_dnd_targets[i] == XA_STRING
|
||||
|| x_dnd_targets[i] == dpyinfo->Xatom_TEXT
|
||||
|| x_dnd_targets[i] == dpyinfo->Xatom_COMPOUND_TEXT
|
||||
|| x_dnd_targets[i] == dpyinfo->Xatom_UTF8_STRING)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == x_dnd_n_targets)
|
||||
return;
|
||||
|
||||
event.xbutton.type = ButtonPress;
|
||||
event.xbutton.serial = 0;
|
||||
@ -2822,8 +2812,6 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo
|
||||
event.xbutton.x_root = root_x;
|
||||
event.xbutton.y_root = root_y;
|
||||
|
||||
XSETFRAME (frame, x_dnd_frame);
|
||||
|
||||
x_catch_errors (dpyinfo->display);
|
||||
|
||||
child = dpyinfo->root_window;
|
||||
@ -2868,6 +2856,55 @@ x_dnd_send_unsupported_drop (struct x_display_info *dpyinfo, Window target_windo
|
||||
x_uncatch_errors ();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
|
||||
x_dnd_n_targets, atom_names))
|
||||
return;
|
||||
|
||||
for (i = x_dnd_n_targets; i > 0; --i)
|
||||
{
|
||||
targets = Fcons (build_string (atom_names[i - 1]),
|
||||
targets);
|
||||
XFree (atom_names[i - 1]);
|
||||
}
|
||||
|
||||
name = XGetAtomName (dpyinfo->display,
|
||||
x_dnd_wanted_action);
|
||||
|
||||
if (name)
|
||||
{
|
||||
arg = intern (name);
|
||||
XFree (name);
|
||||
}
|
||||
else
|
||||
arg = Qnil;
|
||||
|
||||
ie.kind = UNSUPPORTED_DROP_EVENT;
|
||||
ie.code = (unsigned) target_window;
|
||||
ie.arg = list3 (assq_no_quit (QXdndSelection,
|
||||
dpyinfo->terminal->Vselection_alist),
|
||||
targets, arg);
|
||||
ie.timestamp = before;
|
||||
|
||||
XSETINT (ie.x, root_x);
|
||||
XSETINT (ie.y, root_y);
|
||||
XSETFRAME (ie.frame_or_window, x_dnd_frame);
|
||||
|
||||
kbd_buffer_store_event (&ie);
|
||||
}
|
||||
|
||||
static Window
|
||||
x_dnd_get_target_window (struct x_display_info *dpyinfo,
|
||||
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,
|
||||
where FRAME is the frame the mouse is on top of, and POSITION is a
|
||||
mouse position list. */);
|
||||
Vx_dnd_movement_function = Qnil;
|
||||
|
||||
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 handled by the function, and nil if it was
|
||||
not. It should accept several arguments TARGETS, X, Y, ACTION,
|
||||
WINDOW-ID and FRAME, where TARGETS is the list of targets that
|
||||
was passed to `x-begin-drag', WINDOW-ID is the numeric XID of
|
||||
the window that is being dropped on, X and Y are the root
|
||||
window-relative coordinates where the drop happened, ACTION
|
||||
is the action that was passed to `x-begin-drag', and FRAME is
|
||||
the frame which initiated the drag-and-drop operation. */);
|
||||
Vx_dnd_unsupported_drop_function = Qnil;
|
||||
}
|
||||
|
@ -1391,6 +1391,9 @@ extern void x_scroll_bar_configure (GdkEvent *);
|
||||
extern Lisp_Object x_dnd_begin_drag_and_drop (struct frame *, Time, Atom,
|
||||
Lisp_Object, Atom *, const char **,
|
||||
size_t, bool);
|
||||
extern void x_dnd_do_unsupported_drop (struct x_display_info *, Lisp_Object,
|
||||
Lisp_Object, Lisp_Object, Window, int,
|
||||
int, Time);
|
||||
extern void x_set_dnd_targets (Atom *, int);
|
||||
|
||||
INLINE int
|
||||
|
Loading…
Reference in New Issue
Block a user