[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 5359062be6: Avoid ClientMessage overhead when dragging stuff to o
From: |
Po Lu |
Subject: |
master 5359062be6: Avoid ClientMessage overhead when dragging stuff to other frames |
Date: |
Fri, 25 Mar 2022 22:16:07 -0400 (EDT) |
branch: master
commit 5359062be603e22d1ee07c21b0840fdb98a704a3
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Avoid ClientMessage overhead when dragging stuff to other frames
* lisp/dired.el (dired-mouse-drag): Handle correctly dragging
from dired buffers in nonselected windows.
* lisp/x-dnd.el (x-dnd-handle-drag-n-drop-event): Understand new
client message type.
* src/xterm.c (x_dnd_send_enter, x_dnd_send_position)
(x_dnd_send_leave): Ignore if window is the top window of a
frame.
(x_dnd_send_drop): Send special DND event in that case.
---
lisp/dired.el | 7 +++++--
lisp/x-dnd.el | 55 ++++++++++++++++++++++++++++++++++----------------
src/xterm.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 108 insertions(+), 19 deletions(-)
diff --git a/lisp/dired.el b/lisp/dired.el
index c5e389c9ce..3c37a887ba 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -1704,7 +1704,8 @@ see `dired-use-ls-dired' for more details.")
(when mark-active
(deactivate-mark))
(save-excursion
- (goto-char (posn-point (event-end event)))
+ (with-selected-window (posn-window (event-end event))
+ (goto-char (posn-point (event-end event))))
(track-mouse
(let ((new-event (read-event)))
(if (not (eq (event-basic-type new-event) 'mouse-movement))
@@ -1715,7 +1716,9 @@ see `dired-use-ls-dired' for more details.")
(condition-case nil
(progn
(gui-backend-set-selection 'XdndSelection
- (dired-file-name-at-point))
+ (with-selected-window (posn-window
+ (event-end
event))
+ (dired-file-name-at-point)))
(x-begin-drag '("text/uri-list"
"text/x-dnd-username")
(if (eq 'dired-mouse-drag-files 'link)
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index 0529d223db..e801c4fdfc 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -115,6 +115,9 @@ the type we want for the drop,
the action we want for the drop,
any protocol specific data.")
+(declare-function x-get-selection-internal "xselect.c"
+ (selection-symbol target-type &optional time-stamp terminal))
+
(defvar x-dnd-empty-state [nil nil nil nil nil nil nil])
(declare-function x-register-dnd-atom "xselect.c")
@@ -336,21 +339,41 @@ nil if not."
Currently XDND, Motif and old KDE 1.x protocols are recognized."
(interactive "e")
(let* ((client-message (car (cdr (cdr event))))
- (window (posn-window (event-start event)))
- (message-atom (aref client-message 0))
- (frame (aref client-message 1))
- (format (aref client-message 2))
- (data (aref client-message 3)))
-
- (cond ((equal "DndProtocol" message-atom) ; Old KDE 1.x.
- (x-dnd-handle-old-kde event frame window message-atom format data))
-
- ((equal "_MOTIF_DRAG_AND_DROP_MESSAGE" message-atom) ; Motif
- (x-dnd-handle-motif event frame window message-atom format data))
-
- ((and (> (length message-atom) 4) ; XDND protocol.
- (equal "Xdnd" (substring message-atom 0 4)))
- (x-dnd-handle-xdnd event frame window message-atom format data)))))
+ (window (posn-window (event-start event))))
+ (if (eq (and (consp client-message)
+ (car client-message))
+ 'XdndSelection)
+ ;; This is an internal Emacs message caused by something being
+ ;; dropped on top of a frame.
+ (progn
+ (let ((action (cdr (assoc (symbol-name (cadr client-message))
+ x-dnd-xdnd-to-action)))
+ (targets (cddr client-message)))
+ (x-dnd-save-state window nil nil
+ (apply #'vector targets))
+ (x-dnd-maybe-call-test-function window action)
+ (unwind-protect
+ (x-dnd-drop-data event (if (framep window) window
+ (window-frame window))
+ window
+ (x-get-selection-internal
+ 'XdndSelection
+ (intern (x-dnd-current-type window)))
+ (x-dnd-current-type window))
+ (x-dnd-forget-drop window))))
+ (let ((message-atom (aref client-message 0))
+ (frame (aref client-message 1))
+ (format (aref client-message 2))
+ (data (aref client-message 3)))
+ (cond ((equal "DndProtocol" message-atom) ; Old KDE 1.x.
+ (x-dnd-handle-old-kde event frame window message-atom format
data))
+
+ ((equal "_MOTIF_DRAG_AND_DROP_MESSAGE" message-atom) ; Motif
+ (x-dnd-handle-motif event frame window message-atom format data))
+
+ ((and (> (length message-atom) 4) ; XDND protocol.
+ (equal "Xdnd" (substring message-atom 0 4)))
+ (x-dnd-handle-xdnd event frame window message-atom format
data)))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -425,8 +448,6 @@ otherwise return the frame coordinates."
(declare-function x-get-atom-name "xselect.c" (value &optional frame))
(declare-function x-send-client-message "xselect.c"
(display dest from message-type format values))
-(declare-function x-get-selection-internal "xselect.c"
- (selection-symbol target-type &optional time-stamp terminal))
(defun x-dnd-version-from-flags (flags)
"Return the version byte from the 32 bit FLAGS in an XDndEnter message."
diff --git a/src/xterm.c b/src/xterm.c
index 6bd43511f8..deb6d62a27 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1396,6 +1396,9 @@ x_dnd_send_enter (struct frame *f, Window target, int
supported)
int i;
XEvent msg;
+ if (x_top_window_to_frame (dpyinfo, target))
+ return;
+
msg.xclient.type = ClientMessage;
msg.xclient.message_type = dpyinfo->Xatom_XdndEnter;
msg.xclient.format = 32;
@@ -1443,6 +1446,9 @@ x_dnd_send_position (struct frame *f, Window target, int
supported,
return;
}
+ if (x_top_window_to_frame (dpyinfo, target))
+ return;
+
msg.xclient.type = ClientMessage;
msg.xclient.message_type = dpyinfo->Xatom_XdndPosition;
msg.xclient.format = 32;
@@ -1470,6 +1476,9 @@ x_dnd_send_leave (struct frame *f, Window target)
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
XEvent msg;
+ if (x_top_window_to_frame (dpyinfo, target))
+ return;
+
msg.xclient.type = ClientMessage;
msg.xclient.message_type = dpyinfo->Xatom_XdndLeave;
msg.xclient.format = 32;
@@ -1491,6 +1500,62 @@ x_dnd_send_drop (struct frame *f, Window target, Time
timestamp,
{
struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
XEvent msg;
+ struct input_event ie;
+ struct frame *self_frame;
+ int root_x, root_y, win_x, win_y, i;
+ unsigned int mask;
+ Window root, child;
+ Lisp_Object lval;
+ char **atom_names;
+ char *name;
+
+ self_frame = x_top_window_to_frame (dpyinfo, target);
+
+ if (self_frame)
+ {
+ /* Send a special drag-and-drop event when dropping on top of an
+ Emacs frame to avoid all the overhead involved with sending
+ client events. */
+ EVENT_INIT (ie);
+
+ if (XQueryPointer (dpyinfo->display, FRAME_X_WINDOW (self_frame),
+ &root, &child, &root_x, &root_y, &win_x, &win_y,
+ &mask))
+ {
+ ie.kind = DRAG_N_DROP_EVENT;
+ XSETFRAME (ie.frame_or_window, self_frame);
+
+ lval = Qnil;
+ atom_names = alloca (x_dnd_n_targets * sizeof *atom_names);
+ name = XGetAtomName (dpyinfo->display, x_dnd_wanted_action);
+
+ if (!XGetAtomNames (dpyinfo->display, x_dnd_targets,
+ x_dnd_n_targets, atom_names))
+ {
+ XFree (name);
+ return;
+ }
+
+ for (i = x_dnd_n_targets; i != 0; --i)
+ {
+ lval = Fcons (intern (atom_names[i - 1]), lval);
+ XFree (atom_names[i - 1]);
+ }
+
+ lval = Fcons (intern (name), lval);
+ lval = Fcons (QXdndSelection, lval);
+ ie.arg = lval;
+ ie.timestamp = CurrentTime;
+
+ XSETINT (ie.x, win_x);
+ XSETINT (ie.y, win_y);
+
+ XFree (name);
+ kbd_buffer_store_event (&ie);
+
+ return;
+ }
+ }
msg.xclient.type = ClientMessage;
msg.xclient.message_type = dpyinfo->Xatom_XdndDrop;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 5359062be6: Avoid ClientMessage overhead when dragging stuff to other frames,
Po Lu <=