bug#81417: 30.2; pgtk: textual selection targets are served as Latin-1 on Wayland, causing mojibake when pasting into Cromium
Eli Zaretskii <[email protected]> Sat, 01 Aug 2026 11:35:58 +0300
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <[email protected]> |
Ping! Po Lu, could you please chime in? > Cc: [email protected] > Date: Wed, 15 Jul 2026 17:59:48 +0300 > From: Eli Zaretskii <[email protected]> > > > Date: Wed, 15 Jul 2026 11:46:09 +0200 > > From: Victor Vollbrecht <[email protected]> > > > > > > > > Severity: minor > > Tags: pgtk, wayland, clipboard > > > > On the pgtk build running natively on Wayland, copying text containing > > non-ASCII characters from Emacs and pasting it into a Chromium-based > > browser (tested with Vivaldi 8.1 running with --ozone-platform=wayland) > > corrupts the non-ASCII characters. For example, copying > > > > ongeïsoleerde > > > > pastes as > > > > onge�soleerde > > > > where � is U+FFFD REPLACEMENT CHARACTER. > > > > Analysis > > -------- > > > > When Emacs owns the CLIPBOARD selection on Wayland, GDK advertises the > > selection targets from `selection-converter-alist' as Wayland mime > > types. Inspecting each offered type with wl-clipboard after copying > > "ongeïsoleerde" in Emacs shows that they are encoded inconsistently > > (od -A x -t x1z output for the "ï", full dumps below): > > > > text/plain;charset=utf-8 c3 af (UTF-8, correct) > > UTF8_STRING c3 af (UTF-8, correct) > > TEXT ef (Latin-1) > > COMPOUND_TEXT ef (Latin-1) > > STRING ef (Latin-1) > > text/plain ef (Latin-1) > > > > The Latin-1 encodings come from xselect--encode-string in select.el, > > which implements the ICCCM conventions: STRING is hardwired to > > iso-8859-1, bare text/plain accepts only a `charset'-type coding system > > (so it falls back to ascii/latin-1 and cannot be switched to UTF-8 even > > with (set-selection-coding-system 'utf-8), since utf-8 is of type > > `utf-8', not `charset'), and TEXT is polymorphic, resolving to STRING > > for strings representable in Latin-1. > > > > These conventions are correct for X11, where the requestor knows that > > STRING means Latin-1. On Wayland, however, mime types carry no such > > convention and clients universally assume that textual data is UTF-8. > > Chromium in particular picks the first offered text-like type - Emacs > > offers TEXT before any UTF-8 variant - and decodes it as UTF-8, so the > > lone 0xEF byte becomes U+FFFD. Everything Emacs offers under a textual > > Wayland mime type is decoded as UTF-8 by real-world clients, so serving > > Latin-1 bytes under TEXT/STRING/COMPOUND_TEXT/text/plain is effectively > > always wrong on that platform. > > > > Note the asymmetry: pasting the same string from foot (a terminal that > > offers only UTF-8) into Chromium works, and pasting from Emacs into > > native Wayland clients that request text/plain;charset=utf-8 (e.g. foot > > itself) also works. Only consumers that pick one of the legacy targets > > are affected - which includes Chromium/Electron both natively on > > Wayland and behind XWayland. > > > > Recipe to reproduce > > ------------------- > > > > 1. emacs -Q (pgtk build) on any Wayland compositor. > > 2. Insert: ongeïsoleerde > > 3. Select the word and M-w. > > 4. From a terminal: > > wl-paste --list-types > > wl-paste -n -t TEXT | od -A x -t x1z > > wl-paste -n -t "text/plain;charset=utf-8" | od -A x -t x1z > > Observe 0xEF (Latin-1) under TEXT vs 0xC3 0xAF (UTF-8) under > > text/plain;charset=utf-8. > > 5. Paste into any Chromium-based browser running on Wayland: > > the ï is replaced with U+FFFD. > > > > Suggested fix > > ------------- > > > > On pgtk (at least when the GDK backend is Wayland), the textual > > selection targets should all be encoded as UTF-8, or Emacs should stop > > advertising the legacy X11 text atoms as Wayland mime types altogether > > and offer only text/plain;charset=utf-8 (plus text/plain encoded as > > UTF-8, matching what GTK applications do). > > > > Workaround > > ---------- > > > > Overriding the converters for the legacy targets restores correct > > pastes everywhere: > > > > (defun my/xselect-utf8-converter (type) > > (lambda (selection _type value) > > (let ((res (xselect-convert-to-string > > selection 'text/plain\;charset=utf-8 value))) > > (when res (cons type (cdr res)))))) > > > > (dolist (type '(TEXT COMPOUND_TEXT STRING text/plain)) > > (setf (alist-get type selection-converter-alist) > > (my/xselect-utf8-converter type))) > > > > Environment > > ----------- > > > > In GNU Emacs 30.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.x) > > Windowing system: PGTK, running natively on Wayland (niri compositor; > > also reproduced with Chromium behind XWayland via xwayland-satellite). > > System: NixOS 26.11, nixpkgs emacs-pgtk 30.2. > > Thanks. > > Po Lu, any comments? (ISTR that we already had this kind of > discussion at some point in the past.) > > > >