diff options
| author | Po Lu | 2022-06-10 11:45:27 +0800 |
|---|---|---|
| committer | Po Lu | 2022-06-10 11:45:49 +0800 |
| commit | 66aaedffd6b595e03ffcc2bc16c24d7cdd710d40 (patch) | |
| tree | 4ec9d15c42415b3e5de7a597a40e0f253f00b91d | |
| parent | feb94707a9b1a1e35889ce743783d370fba2e739 (diff) | |
| download | emacs-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.el | 99 |
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. |
| 70 | If the type for the drop is not present, or the function is nil, | 68 | If the type for the drop is not present, or the function is nil, |
| 71 | the drop is rejected. The function takes three arguments, WINDOW, ACTION | 69 | the 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. |
| 97 | The types are chosen in the order they appear in the list." | 94 | The 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. | ||
| 590 | Return 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. | ||
| 608 | I is the offset into DATA to begin reading at. Return a list | ||
| 609 | of (CONSUMED NTARGETS TARGETS), where CONSUMED is the number of | ||
| 610 | bytes read from DATA, NTARGETS is the total number of targets | ||
| 611 | inside the current rec, and TARGETS is a vector of atoms | ||
| 612 | describing 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. | ||
| 627 | Return 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. | ||
| 652 | WINDOW should be the drag-and-drop operation's initiator. | ||
| 653 | Return 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. |