Subject: bug#54040: 29.0.50; Text becomes blurry on PGTK/Wayland

From: Thomas Jost <[email-masked]>
Date: Thu, 17 Feb 2022 11:44:19 +0100

Hey folks,

I'm using a recent git build of Emacs on Arch Linux, with pgtk and
nativecomp. Since a recent update, text started becoming blurry when
scrolling with the mousewheel, or even just when inserting a newline. So
basically, any time text is "moved" without being fully redrawn.

I can reproduce it reliably with my own config, but can't with plain
`emacs -Q`. It also happens more reliably in emacsclient on my external
monitor, although it sometimes "flashes" as blurry text in emacs on my
laptop screen.

Other important details:
- I'm running Wayland with Sway (latest stable version)
- my laptop screen and external screen have different scale factor: 2
for laptop screen, 1 for external screen.

This can be fixed temporarily by focusing the blurred line/paragraph, or
with M-x redraw-display. But another scroll or newline will repeat the issue.

So, I used git bisect to try to find the faulty commit. The result is
that this behavior started with commit
6da021fce86a06a97b0bff76f69aa57759533dc9: "Fix artifacting on PGTK when
bits are copied with an alpha channel".

Attached is a patch that seems to solve this issue for me without
completely reverting that commit. I'm not sure if it's really a correct
fix; please email me if you need any more details or testing!

Best,
Thomas

In GNU Emacs 29.0.50 (build 8, x86_64-pc-linux-gnu, GTK+ Version 3.24.31, cairo version 1.17.4)
 of 2022-02-17 built on loki
Repository revision: eb0680bd57bd68ca369dc5133646e8ac9215854c
Repository branch: master
System Description: Arch Linux

Configured using:
 'configure --prefix=/usr --sysconfdir=/etc --libexecdir=/usr/lib
 --localstatedir=/var --mandir=/usr/share/man --with-gameuser=:games
 --with-sound=alsa --with-modules --without-libotf --without-m17n-flt
 --without-gconf --without-gsettings --with-native-compilation
 --with-xinput2 --with-pgtk --without-xaw3d --with-sound=no
 --without-gpm --without-compress-install
 '--program-transform-name=s/\([ec]tags\)/\1.emacs/'
 'CFLAGS=-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions
 -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security
 -fstack-clash-protection -fcf-protection'
 LDFLAGS=-Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now
 'CXXFLAGS=-march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions
 -Wp,-D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security
 -fstack-clash-protection -fcf-protection -Wp,-D_GLIBCXX_ASSERTIONS''

Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS HARFBUZZ JPEG JSON LCMS2
LIBSYSTEMD LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PGTK PNG
RSVG SECCOMP SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS WEBP XIM GTK3 ZLIB

Important settings:
  value of $LANG: fr_FR.UTF-8
  locale-coding-system: utf-8-unix

Major mode: C/*l

Minor modes in effect:
  company-mode: t
  bug-reference-prog-mode: t
  counsel-mode: t
  ivy-mode: t
  global-emojify-mode: t
  emojify-mode: t
  lsp-treemacs-sync-mode: t
  yas-global-mode: t
  yas-minor-mode: t
  treemacs-filewatch-mode: t
  treemacs-follow-mode: t
  treemacs-git-mode: t
  treemacs-fringe-indicator-mode: t
  projectile-mode: t
  global-git-commit-mode: t
  magit-auto-revert-mode: t
  windmove-mode: t
  flycheck-pos-tip-mode: t
  global-flycheck-mode: t
  flycheck-mode: t
  shell-dirtrack-mode: t
  editorconfig-mode: t
  volatile-highlights-mode: t
  global-undo-tree-mode: t
  undo-tree-mode: t
  viking-global-mode: t
  viking-mode: t
  global-auto-revert-mode: t
  which-key-mode: t
  global-so-long-mode: t
  auto-read-only-mode: t
  which-function-mode: t
  tree-sitter-hl-mode: t
  global-tree-sitter-mode: t
  tree-sitter-mode: t
  override-global-mode: t
  global-subword-mode: t
  subword-mode: t
  desktop-save-mode: t
  save-place-mode: t
  delete-selection-mode: t
  global-hl-line-mode: t
  display-time-mode: t
  tooltip-mode: t
  global-eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  column-number-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: (only . t)
  abbrev-mode: t

Load-path shadows:
/home/schnouki/.quicklisp/dists/quicklisp/software/slime-v2.26.1/slime hides /home/schnouki/.emacs.d/elpa/slime-20220210.1512/slime
/home/schnouki/.quicklisp/dists/quicklisp/software/slime-v2.26.1/slime-autoloads hides /home/schnouki/.emacs.d/elpa/slime-20220210.1512/slime-autoloads
/home/schnouki/.quicklisp/dists/quicklisp/software/slime-v2.26.1/slime-tests hides /home/schnouki/.emacs.d/elpa/slime-20220210.1512/slime-tests
/home/schnouki/.emacs.d/elpa/transient-20220130.1941/transient hides /home/schnouki/tmp/emacs-git/src/emacs-git/lisp/transient
/home/schnouki/.emacs.d/elpa/faceup-20170925.1946/faceup hides /home/schnouki/tmp/emacs-git/src/emacs-git/lisp/emacs-lisp/faceup

Features:
(shadow sort footnote mail-extr emacsbug sendmail lsp-zig lsp-steep
lsp-svelte lsp-sqls lsp-yaml lsp-xml lsp-vimscript lsp-vhdl lsp-vetur
lsp-html lsp-verilog lsp-vala lsp-v lsp-toml lsp-terraform lsp-tex
lsp-sorbet lsp-solargraph lsp-rust lsp-rf lsp-remark lsp-r
lsp-purescript lsp-pylsp lsp-pyls lsp-pwsh lsp-php lsp-perl lsp-ocaml
lsp-nix lsp-nim lsp-nginx lsp-markdown lsp-lua lsp-kotlin lsp-json
lsp-javascript lsp-haxe lsp-groovy lsp-hack lsp-graphql lsp-go
lsp-gdscript lsp-fsharp lsp-fortran lsp-eslint lsp-erlang lsp-elixir
lsp-elm lsp-dockerfile lsp-dhall lsp-d lsp-css lsp-csharp gnutls
lsp-crystal lsp-cmake lsp-clojure lsp-semantic-tokens lsp-clangd
lsp-beancount lsp-bash lsp-angular lsp-ada lsp-actionscript dtrt-indent
lsp-diagnostics lsp-modeline lsp-completion lsp-ui lsp-ui-flycheck
lsp-ui-doc goto-addr lsp-ui-imenu lsp-ui-peek lsp-ui-sideline
lsp-ui-util face-remap auto-virtualenvwrapper virtualenvwrapper gud
python-el-fgallina-expansions python vc macrostep-c cmacexp
company-oddmuse company-keywords company-etags company-gtags
company-dabbrev-code company-dabbrev company-files company-clang
company-cmake company-semantic company-bbdb company-capf company-tabnine
unicode-escape company-template company vc-git vc-dispatcher
bug-reference guess-language flyspell ispell editorconfig-core
editorconfig-core-handle editorconfig-fnmatch counsel xdg swiper ivy
ivy-faces ivy-overlay colir emojify apropos defproject
smart-mode-line-respectful-theme smart-mode-line rich-minority
zenburn-theme lsp-treemacs lsp-pyright lsp-mode lsp-protocol yasnippet
tree-widget spinner network-stream nsm ewoc lsp-treemacs-themes f
treemacs-projectile treemacs-magit treemacs treemacs-header-line
treemacs-compatibility treemacs-mode treemacs-interface
treemacs-extensions treemacs-mouse-interface treemacs-tags
treemacs-persistence treemacs-filewatch-mode treemacs-follow-mode
treemacs-rendering treemacs-async treemacs-workspaces treemacs-dom
treemacs-visuals treemacs-fringe-indicator treemacs-scope pulse
treemacs-faces treemacs-icons treemacs-themes treemacs-core-utils
pfuture ht inline treemacs-logging treemacs-customization
treemacs-macros ibuffer-projectile ibuf-macs projectile grep ibuf-ext
ibuffer ibuffer-loaddefs gitignore-mode conf-mode magit-submodule
magit-obsolete magit-blame magit-stash magit-reflog magit-bisect
magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit
magit-sequence magit-notes magit-worktree magit-tag magit-merge
magit-branch magit-reset magit-files magit-refs magit-status magit
magit-repos magit-apply magit-wip magit-log magit-diff smerge-mode
diff-mode git-commit log-edit message yank-media rmc puny rfc822 mml
mml-sec epa epg rfc6068 epg-config gnus-util mm-decode mm-bodies
mm-encode mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums
mail-prsvr mailabbrev gmm-utils pcvs-util add-log magit-core
magit-autorevert magit-margin magit-transient magit-process with-editor
server magit-mode transient magit-git magit-utils crm blacken
flycheck-mypy faceup flycheck-package package-lint finder lisp-mnt
flycheck-grammarly grammarly websocket bindat request mailheader
mail-utils dom hydra-examples windmove jq-format reformatter just-mode
slime-fancy slime-indentation slime-cl-indent cl-indent
slime-trace-dialog slime-fontifying-fu slime-package-fu slime-references
slime-compiler-notes-tree slime-scratch slime-presentations bridge
slime-macrostep macrostep slime-mdot-fu slime-enclosing-context
slime-fuzzy slime-fancy-trace slime-fancy-inspector slime-c-p-c
slime-editing-commands slime-autodoc slime-repl slime-parse slime
hyperspec nix-mode ffap nix-repl nix-shell nix-store magit-section
nix-instantiate nix-shebang nix-format nix scad-mode flycheck-nim
flycheck-plantuml plantuml-mode flycheck-pos-tip pos-tip flycheck
find-func nim-mode commenter nim-fill nim-smie let-alist nim-helper
nim-util nim-syntax nim-rx nim-vars cargo cargo-process markdown-mode
color noutline outline rust-utils rust-mode rust-rustfmt rust-playpen
rust-compile rust-cargo d-mode cc-langs cc-mode-expansions cc-mode
cc-fonts cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine cc-vars
cc-defs loop fennel-mode inf-lisp docker-tramp tramp-cache tramp
tramp-loaddefs trampver tramp-integration cus-edit cus-load wid-edit
files-x tramp-compat shell pcomplete parse-time iso8601 time-date
ls-lisp format-spec uuidgen calc-misc calc-ext calc calc-loaddefs rect
calc-macs editorconfig etags fileloop generator volatile-highlights
undo-tree diff viking-mode autorevert filenotify which-key
visual-fill-column so-long auto-read-only restclient-jq jq-mode pcase
smie expand-region subword-mode-expansions text-mode-expansions
er-basic-expansions thingatpt expand-region-core expand-region-custom
which-func imenu tree-sitter-langs tree-sitter-langs-build tar-mode
arc-mode archive-mode pp tree-sitter-hl tree-sitter tree-sitter-load
tree-sitter-cli tsc tsc-dyn tsc-dyn-get compile text-property-search
comint ansi-color dired-aux dired dired-loaddefs tsc-obsolete xref
project s list-utils dash edmacro kmacro hydra ring lv view alert log4e
notifications dbus xml gntp diminish use-package use-package-ensure
use-package-delight use-package-diminish use-package-bind-key bind-key
easy-mmode use-package-core derived finder-inf cap-words superword
subword desktop frameset saveplace ediff ediff-merg ediff-mult
ediff-wind ediff-diff ediff-help ediff-init ediff-util delsel hl-line
comp comp-cstr warnings cl-extra help-mode time cl slime-autoloads rx
advice info package browse-url url url-proxy url-privacy url-expand
url-methods url-history url-cookie url-domsuf url-util mailcap
url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs
eieio-loaddefs password-cache json map url-vars seq gv subr-x byte-opt
bytecomp byte-compile cconv cl-loaddefs cl-lib iso-transl tooltip eldoc
paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode
mwheel term/pgtk-win pgtk-win term/common-win tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu
timer select scroll-bar mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer cl-generic cham georgian utf-8-lang
misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms
cp51932 hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese composite emoji-zwj charscript charprop case-table
epa-hook jka-cmpr-hook help simple abbrev obarray cl-preloaded nadvice
button loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads dbusbind inotify
dynamic-setting font-render-setting cairo gtk pgtk lcms2 multi-tty
make-network-process native-compile emacs)

Memory information:
((conses 16 1455501 799687)
 (symbols 48 79315 4)
 (strings 32 781537 91826)
 (string-bytes 1 48029787)
 (vectors 16 125486)
 (vector-slots 8 3943096 1928905)
 (floats 8 440 2087)
 (intervals 56 2724 379)
 (buffers 992 20))

-- 
Thomas
diff --git src/pgtkterm.c src/pgtkterm.c
index 65408801cfd..b5b05912333 100644
--- src/pgtkterm.c
+++ src/pgtkterm.c
@@ -2928,13 +2928,11 @@ pgtk_copy_bits (struct frame *f, cairo_rectangle_t *src_rect,
   GdkWindow *window;
   cairo_surface_t *surface;	/* temporary surface */
 
-  window = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
-
   surface =
-    gdk_window_create_similar_surface (window, CAIRO_CONTENT_COLOR_ALPHA,
-				       FRAME_CR_SURFACE_DESIRED_WIDTH (f),
-				       FRAME_CR_SURFACE_DESIRED_HEIGHT
-				       (f));
+    cairo_surface_create_similar (FRAME_CR_SURFACE (f),
+				 CAIRO_CONTENT_COLOR_ALPHA,
+				 (int) src_rect->width,
+				 (int) src_rect->height);
 
   cr = cairo_create (surface);
   cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), -src_rect->x,