How to live on GNOME with pure Wayland
Here in 2023 Wayland become the default graphics session type for at least 2 most popular Linux distros: Fedora and Ubuntu.
However it is still not ideal, even though GTK4 and Qt6 claim full support for Wayland, many other toolkits have issues with it or Wayland backend is yet in progress.
This is usually eliminated by using XWayland
that is being started transparently
when you launch an application that is not capable of Wayland.
I have switched to Wayland a few years ago with Fedora 32. The main reason for me was the support of fractional scaling since I use 2 screens with different DPI and I usually set 125% scale for laptop screen, which makes UI size more or less the same on both of them.
Enabling fractional scaling in GNOME
It’s still an experimental option in Mutter, you have to enable it explicitly:
$ gsettings set org.gnome.mutter experimental-features "['scale-monitor-framebuffer']"
Re-login, go to Settings -> Displays -> your display and you will see
options like 125%
, 175%
and 225%
.
Fractional scaling in GNOME works in the following way: it renders the window at next integer scale first, and then downsizes the image in the compositor to 1.25x
. It allows to move the window between monitors and get the right scale on any of them without restart. In GNOME 44 there’s a wp_fractional_scale_v1
protocol supported in Qt6
and GTK4
, for drawing directly at desired scale.
The problem is that only applications using Wayland backend are capable of fractional
scaling, while those running through XWayland
are getting blurry.
Possible solution is to force using Wayland backend for the most applications. I gathered some known bugs and workarounds for toolkits I’m using every day and gonna share this below.
Wayland experience with different toolkits
-
GTK4: works perfectly out-of-the-box.
-
GTK3: pretty good experience, but it still has a long-standing bug with
GtkEntryCompletion
widget in multi-monitor configurations: #2794. It was reported by me in 2020 with related merge request, and as of now (2023) there are 3 merge requests resolving this, but developers still not accepted nor reviewed any of them.
The solution is to use my GTK3 COPR repo for Fedora with patchedgtk3
package. -
Qt6: pretty good experience out-of-the-box.
-
Qt5: works well with KDE patchset however some features like
XDG Activation
are still missing. I have backported support for XDG Activation as well some other quirks from Qt6.
One can use my Qt5 COPR repo with patchedqt5-qtwayland
package. To force Wayland backend, useQT_QPA_PLATFORM=wayland
environment variable or the following command-line argument:
$ ./qt5-app ... -platform wayland
-
QGnomePlatform: Fedora ships custom Qt Platform Theme QGnomePlatform which mimics GTK-style window decorations and uses adwaita-qt widget style that follows Adwaita theme.
I have pushed number of fixes to their upstream, but version shipped in Fedora is pretty old, so the solution is the same - usegnomeplatform
andadwaita-qt5
packages from my Qt5 COPR repo. -
Electron: Ozone platform works on Wayland quite well and since version 12 it supports GTK3-style titlebars via
libdecor
wrapper, which can be enabled by the following command-line arguments:
$ ./electron-app ... --enable-features=UseOzonePlatform,WaylandWindowDecorations \
--ozone-platform=wayland
I’ve written a simple bash script that launches an app on Wayland backend for Qt and Electron. It also handles case of running through Flatpak and falls back to X11 backend if launched from X11 session (gist):
#!/bin/sh
platform_args=""
flatpak_args=""
# Check platform argument
case "$1" in
-electron)
platform=electron
;;
-qt5)
platform=qt
;;
*)
echo "Usage: $0 -electron|-qt5 [command]"
exit 1
esac
# Extract app name and make $@ point to it's args
app="$2"
shift 2
if [ "$XDG_SESSION_TYPE" = "wayland" ]; then
# Check if an application is started through flatpak
test "$(basename "$app")" = "flatpak" && using_flatpak=1
# On GNOME retrieve cursor size from settings and pass to an application
gnome_cursor_size="$(gsettings get org.gnome.desktop.interface cursor-size 2>/dev/null)"
if [ -n "$gnome_cursor_size" ]; then
if [ -n "$using_flatpak" ]; then
flatpak_args="--env=XCURSOR_SIZE=$gnome_cursor_size --env=DISPLAY="
else
export XCURSOR_SIZE="$gnome_cursor_size"
export DISPLAY=
fi
fi
case "$platform" in
electron)
platform_args="--enable-features=UseOzonePlatform,WaylandWindowDecorations"
platform_args="$platform_args --ozone-platform=wayland"
;;
qt)
platform_args="-platform wayland"
if [ -n "$using_flatpak" ]; then
flatpak_args="$flatpak_args --env=QT_QPA_PLATFORM=wayland"
else
export QT_QPA_PLATFORM=wayland
fi
;;
esac
fi
exec "$app" $flatpak_args "$@" $platform_args
Call it wayland-launch
, put somewhere in /usr/local/bin/
and use like so:
$ wayland-launch -electron code
$ wayland-launch -electron flatpak run com.slack.Slack
$ wayland-launch -qt5 keepassx
Keeping monitor configuration between Wayland and X11 sessions
The last thing I’m going to cover here is that display configuration will be reset when launching X11 session if you have at least one screen with fractional scaling.
It happens because on X11 Mutter doesn’t support fractional scales and treats all the configuration as invalid.
The solution is to have separate monitor configurations for X11 and Wayland.
Monitor configuration is stored in ~/.config/monitors.xml
file and we can
fool Mutter by making it a symbolic link to either X11 or Wayland config, depending
on current session type:
- Create
~/.config/monitors.xml.wayland
and~/.config/monitors.xml.x11
:
$ cp ~/.config/monitors.xml ~/.config/monitors.xml.wayland
$ cp ~/.config/monitors.xml ~/.config/monitors.xml.x11
- Make it a symbolic link to the currently used configuration:
$ ln -sf ~/.config/monitors.xml.wayland ~/.config/monitors.xml
- Now add the following to
~/.bash_profile
to switch the symlink on session start:
if [ "${XDG_SESSION_TYPE}" = "wayland" -o "${XDG_SESSION_TYPE}" = "x11" ]
then
MONITORS_XML="${HOME}/.config/monitors.xml"
if [ -L "${MONITORS_XML}~" ]
then
cp "${MONITORS_XML}" $(readlink -f "${MONITORS_XML}~")
rm -f "${MONITORS_XML}~"
fi
ln -sf ${MONITORS_XML}{.${XDG_SESSION_TYPE},}
fi
- Profit! Separate monitor configurations for X11 and Wayland will never intersect.