aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-06-10 11:45:27 +0800
committerPo Lu2022-06-10 11:45:49 +0800
commit66aaedffd6b595e03ffcc2bc16c24d7cdd710d40 (patch)
tree4ec9d15c42415b3e5de7a597a40e0f253f00b91d
parentfeb94707a9b1a1e35889ce743783d370fba2e739 (diff)
downloademacs-66aaedffd6b595e03ffcc2bc16c24d7cdd710d40.tar.gz
emacs-66aaedffd6b595e03ffcc2bc16c24d7cdd710d40.zip
Don't rely on TARGETS to read selection targets for Motif DND
* lisp/x-dnd.el (x-dnd-types-alist): (x-dnd-known-types): Fix formatting. (x-dnd-xm-unpack-targets-table-header): (x-dnd-xm-read-single-rec): (x-dnd-xm-read-targets-table): (x-dnd-xm-read-targets): New functions. (x-dnd-handle-motif): Read targets from the targets table of the drag window instead of the selection's TARGET target.
-rw-r--r--lisp/x-dnd.el99
1 files changed, 87 insertions, 12 deletions
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index 7befea7418f..85b4138f170 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -52,8 +52,7 @@ The default value for this variable is `x-dnd-default-test-function'."
52 52
53 53
54(defcustom x-dnd-types-alist 54(defcustom x-dnd-types-alist
55 `( 55 `((,(purecopy "text/uri-list") . x-dnd-handle-uri-list)
56 (,(purecopy "text/uri-list") . x-dnd-handle-uri-list)
57 (,(purecopy "text/x-moz-url") . x-dnd-handle-moz-url) 56 (,(purecopy "text/x-moz-url") . x-dnd-handle-moz-url)
58 (,(purecopy "_NETSCAPE_URL") . x-dnd-handle-uri-list) 57 (,(purecopy "_NETSCAPE_URL") . x-dnd-handle-uri-list)
59 (,(purecopy "FILE_NAME") . x-dnd-handle-file-name) 58 (,(purecopy "FILE_NAME") . x-dnd-handle-file-name)
@@ -64,8 +63,7 @@ The default value for this variable is `x-dnd-default-test-function'."
64 (,(purecopy "text/plain") . dnd-insert-text) 63 (,(purecopy "text/plain") . dnd-insert-text)
65 (,(purecopy "COMPOUND_TEXT") . x-dnd-insert-ctext) 64 (,(purecopy "COMPOUND_TEXT") . x-dnd-insert-ctext)
66 (,(purecopy "STRING") . dnd-insert-text) 65 (,(purecopy "STRING") . dnd-insert-text)
67 (,(purecopy "TEXT") . dnd-insert-text) 66 (,(purecopy "TEXT") . dnd-insert-text))
68 )
69 "Which function to call to handle a drop of that type. 67 "Which function to call to handle a drop of that type.
70If the type for the drop is not present, or the function is nil, 68If the type for the drop is not present, or the function is nil,
71the drop is rejected. The function takes three arguments, WINDOW, ACTION 69the drop is rejected. The function takes three arguments, WINDOW, ACTION
@@ -91,8 +89,7 @@ if drop is successful, nil if not."
91 "text/plain" 89 "text/plain"
92 "COMPOUND_TEXT" 90 "COMPOUND_TEXT"
93 "STRING" 91 "STRING"
94 "TEXT" 92 "TEXT"))
95 ))
96 "The types accepted by default for dropped data. 93 "The types accepted by default for dropped data.
97The types are chosen in the order they appear in the list." 94The types are chosen in the order they appear in the list."
98 :version "22.1" 95 :version "22.1"
@@ -588,6 +585,86 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent."
588 (reverse bytes) 585 (reverse bytes)
589 bytes))) 586 bytes)))
590 587
588(defun x-dnd-xm-unpack-targets-table-header (data)
589 "Decode the header of DATA, a Motif targets table.
590Return a list of the following fields with the given types:
591
592 Field name Type
593 - BYTE_ORDER BYTE
594 - PROTOCOL BYTE
595 - TARGET_LIST_COUNT CARD16
596 - TOTAL_DATA_SIZE CARD32"
597 (let* ((byte-order (aref data 0))
598 (protocol (aref data 1))
599 (target-list-count (x-dnd-get-motif-value
600 data 2 2 byte-order))
601 (total-data-size (x-dnd-get-motif-value
602 data 4 4 byte-order)))
603 (list byte-order protocol target-list-count
604 total-data-size)))
605
606(defun x-dnd-xm-read-single-rec (data i)
607 "Read a single rec from DATA, a Motif targets table.
608I is the offset into DATA to begin reading at. Return a list
609of (CONSUMED NTARGETS TARGETS), where CONSUMED is the number of
610bytes read from DATA, NTARGETS is the total number of targets
611inside the current rec, and TARGETS is a vector of atoms
612describing the selection targets in the current rec."
613 (let* ((byte-order (aref data 0))
614 (n-targets (x-dnd-get-motif-value
615 data i 2 byte-order))
616 (targets (make-vector n-targets nil))
617 (consumed 0))
618 (while (< consumed n-targets)
619 (aset targets consumed (x-dnd-get-motif-value
620 data (+ i 2 (* consumed 4))
621 4 byte-order))
622 (setq consumed (1+ consumed)))
623 (list (+ 2 (* consumed 4)) n-targets targets)))
624
625(defun x-dnd-xm-read-targets-table (frame)
626 "Read the Motif targets table on FRAME.
627Return a vector of vectors of numbers (the drop targets)."
628 (let* ((drag-window (x-window-property "_MOTIF_DRAG_WINDOW"
629 frame "WINDOW" 0 nil t))
630 (targets-data (x-window-property "_MOTIF_DRAG_TARGETS"
631 frame "_MOTIF_DRAG_TARGETS"
632 drag-window nil t))
633 (header (x-dnd-xm-unpack-targets-table-header targets-data))
634 (vec (make-vector (nth 2 header) nil))
635 (current-byte 8)
636 (i 0))
637 (unless (stringp targets-data)
638 (error "Expected format 8, got %s" (type-of targets-data)))
639 (prog1 vec
640 (while (< i (nth 2 header))
641 (let ((rec (x-dnd-xm-read-single-rec targets-data
642 current-byte)))
643 (aset vec i (nth 2 rec))
644 (setq current-byte (+ current-byte (car rec)))
645 (setq i (1+ i))))
646 (unless (eq current-byte (nth 3 header))
647 (error "Targets table header says size is %d, but it is actually %d"
648 (nth 3 header) current-byte)))))
649
650(defun x-dnd-xm-read-targets (frame window selection)
651 "Read targets of SELECTION on FRAME from the targets table.
652WINDOW should be the drag-and-drop operation's initiator.
653Return a vector of atoms containing the selection targets."
654 (let* ((targets-table (x-dnd-xm-read-targets-table frame))
655 (initiator-info (x-window-property selection frame
656 "_MOTIF_DRAG_INITIATOR_INFO"
657 window nil nil))
658 (byte-order (aref initiator-info 0))
659 (idx (x-dnd-get-motif-value initiator-info
660 2 2 byte-order))
661 (vector (aref targets-table idx))
662 (i 0))
663 (prog1 vector
664 (while (< i (length vector))
665 (aset vector i
666 (intern (x-get-atom-name (aref vector i))))
667 (setq i (1+ i))))))
591 668
592(defvar x-dnd-motif-message-types 669(defvar x-dnd-motif-message-types
593 '((0 . XmTOP_LEVEL_ENTER) 670 '((0 . XmTOP_LEVEL_ENTER)
@@ -625,14 +702,12 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent."
625 data 8 4 source-byteorder)) 702 data 8 4 source-byteorder))
626 (selection-atom (x-dnd-get-motif-value 703 (selection-atom (x-dnd-get-motif-value
627 data 12 4 source-byteorder)) 704 data 12 4 source-byteorder))
628 (atom-name (x-get-atom-name selection-atom)) 705 (atom-name (x-get-atom-name selection-atom))
629 (types (when atom-name 706 (types (x-dnd-xm-read-targets frame dnd-source
630 (x-get-selection-internal (intern atom-name) 707 atom-name)))
631 'TARGETS))))
632 (x-dnd-forget-drop frame) 708 (x-dnd-forget-drop frame)
633 (when types (x-dnd-save-state window nil nil 709 (when types (x-dnd-save-state window nil nil
634 types 710 types dnd-source))))
635 dnd-source))))
636 711
637 ;; Can not forget drop here, LEAVE comes before DROP_START and 712 ;; Can not forget drop here, LEAVE comes before DROP_START and
638 ;; we need the state in DROP_START. 713 ;; we need the state in DROP_START.