Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions ert-tests/simpleclip-test.el
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,51 @@
(simpleclip-set-contents kept))))


;;; Unicode / X selection target fallback

(defvar simpleclip-test-latin1-emoji
(string 240 159 153 130)
"Raw UTF-8 bytes of U+1F642 as a unibyte string.")

(defun simpleclip-test--make-selection-reader (selections)
"Return a fake selection reader backed by hash table SELECTIONS."
(lambda (type)
(gethash type selections)))

(ert-deftest simpleclip-get-contents-utf8-fallback nil
"When `x-select-request-type' is nil, prefer UTF8_STRING over STRING.
This mirrors `gui--selection-value-internal' and avoids interpreting
UTF-8 bytes as Latin-1."
(let ((selections (make-hash-table :test 'equal))
(x-select-request-type nil))
(puthash 'UTF8_STRING "馃檪" selections)
(puthash 'STRING simpleclip-test-latin1-emoji selections)
(should (equal (simpleclip--get-selection-contents
'x
(simpleclip-test--make-selection-reader selections))
"馃檪"))))

(ert-deftest simpleclip-get-contents-utf8-fallback-order nil
"Fall back to STRING when UTF8_STRING is unavailable."
(let ((selections (make-hash-table :test 'equal))
(x-select-request-type nil))
(puthash 'STRING simpleclip-test-latin1-emoji selections)
(should (equal (simpleclip--get-selection-contents
'x
(simpleclip-test--make-selection-reader selections))
simpleclip-test-latin1-emoji))))

(ert-deftest simpleclip-get-contents-explicit-string nil
"When `x-select-request-type' is `STRING', use exactly that target."
(let ((selections (make-hash-table :test 'equal))
(x-select-request-type 'STRING))
(puthash 'STRING simpleclip-test-latin1-emoji selections)
(should (equal (simpleclip--get-selection-contents
'x
(simpleclip-test--make-selection-reader selections))
simpleclip-test-latin1-emoji))))


;;
;; Emacs
;;
Expand Down
34 changes: 28 additions & 6 deletions simpleclip.el
Original file line number Diff line number Diff line change
Expand Up @@ -340,12 +340,15 @@ in GNU Emacs 24.1 or higher."
(and (and (featurep 'mac)
(fboundp 'x-get-selection))
(x-get-selection 'CLIPBOARD 'NSStringPboardType))
;; todo, this should try more than one request type, as in gui--selection-value-internal
(and (fboundp 'gui-get-selection)
(gui-get-selection 'CLIPBOARD (car x-select-request-type)))
;; todo, this should try more than one request type, as in gui--selection-value-internal
(and (fboundp 'x-get-selection)
(x-get-selection 'CLIPBOARD (car x-select-request-type))))))
;; Mirror `gui--selection-value-internal': try each clipboard
;; data type in order, falling back from UTF-8 to legacy targets.
(simpleclip--get-selection-contents
(window-system)
(lambda (type)
(or (and (fboundp 'gui-get-selection)
(gui-get-selection 'CLIPBOARD type))
(and (fboundp 'x-get-selection)
(x-get-selection 'CLIPBOARD type))))))))
(t
(error "Clipboard support not available")))
(error
Expand All @@ -370,6 +373,25 @@ in GNU Emacs 24.1 or higher."
(error
(error "Clipboard support not available"))))))

(defun simpleclip--get-selection-contents (win-system get-selection)
"Get clipboard contents using selection target fallback.
WIN-SYSTEM is the current window-system symbol. GET-SELECTION is
a function (TYPE) that returns the selection for that data type.
Mirrors `gui--selection-value-internal'."
(when (memq win-system '(x pgtk haiku))
(let ((request-type (or x-select-request-type
'(UTF8_STRING COMPOUND_TEXT STRING text/plain\;charset=utf-8)))
text)
(with-demoted-errors "simpleclip--get-selection-contents: %S"
(if (consp request-type)
(while (and request-type (not text))
(setq text (funcall get-selection (car request-type)))
(setq request-type (cdr request-type)))
(setq text (funcall get-selection request-type))))
(when text
(remove-text-properties 0 (length text) '(foreign-selection nil) text))
text)))

;;;###autoload
(defun simpleclip-set-contents (str-val)
"Set the contents of the system clipboard to STR-VAL."
Expand Down