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.)
> 
> 
> 
>