$linuxjunkies
>

Fix Fractional Scaling and HiDPI on Wayland

Fix blurry apps on HiDPI Wayland displays: enable compositor fractional scaling, set GDK and Qt env vars for XWayland, and configure Electron's Ozone backend.

IntermediateUbuntuDebianFedoraArch9 min readUpdated June 7, 2026

Before you start

  • A Wayland session (GNOME on Wayland, KDE Plasma 6 Wayland, or Sway) — not an X11/Xorg session
  • A HiDPI display (typically 200 DPI or higher, e.g., a 4K monitor at 24–27 inches)
  • Basic terminal familiarity: editing files, exporting variables, and reloading your session
  • Sudo access is not required; all changes are per-user

Fractional scaling on Wayland—setting your display to 125%, 150%, or 175% instead of a whole-number multiple—has come a long way but still trips up many setups. The core problem is that Wayland compositors handle scaling natively for Wayland-native apps, but legacy X11 apps running under XWayland need separate treatment, and Electron-based apps add a third layer on top of that. This guide cuts through those layers so everything on your HiDPI display looks sharp without blurry upscaling.

Understand the Three App Categories

Before touching any settings, know which type of app you're dealing with:

  • Wayland-native (GTK4, modern Qt6, native SDL2): The compositor scales them directly. They benefit immediately from compositor-level fractional scaling.
  • XWayland apps (older GTK3, Qt5 without Wayland plugin, Wine, some Java GUIs): Run inside an X11 compatibility layer. They receive a 1× or 2× buffer from XWayland and must be told to scale themselves via environment variables.
  • Electron apps (VS Code, Slack, Discord, Obsidian): Ship their own Chromium and have their own set of flags. Some support Wayland natively now; others still run under XWayland.

You can check which protocol a running window uses on GNOME with the tool below. On KDE Plasma, right-click the title bar and inspect "More Actions → Window Information".

xprop -id $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f2) _NET_WM_NAME WM_CLASS | head -5

A cleaner check on any compositor: if xwininfo finds the window, it is running under XWayland.

Step 1: Enable Fractional Scaling in Your Compositor

GNOME (mutter) on Wayland

Fractional scaling in GNOME is stable since GNOME 44 but must be explicitly enabled:

gsettings set org.gnome.mutter experimental-features "['scale-monitor-framebuffer']"

Then open Settings → Displays and choose your desired fractional scale (e.g., 125% or 150%). Log out and back in. On GNOME 46+ this feature is enabled by default if your display is detected as HiDPI.

KDE Plasma 6 on Wayland

Plasma 6 ships with fractional scaling fully supported. Go to System Settings → Display and Monitor → Display Configuration, set the scale slider to any value. No extra flags required. Plasma uses a per-output scale stored in ~/.config/kwinrc and applies it cleanly to all Wayland-native windows.

Sway / wlroots compositors

Add or edit your output block in ~/.config/sway/config:

output eDP-1 scale 1.5

Reload with swaymsg reload. For a 1.25 or 1.75 scale, wlroots uses fractional-scale-v1; most GTK4 and Qt6 apps will render at the correct resolution. Older apps still need the env var treatment below.

Step 2: Fix XWayland Apps with Environment Variables

XWayland presents a fixed pixel density to X11 clients. You must either set the X server's DPI or tell individual toolkits to scale themselves.

GTK apps (GTK3 and older GTK4 fallbacks)

export GDK_SCALE=2           # integer only — use for 2× displays
export GDK_DPI_SCALE=0.5     # compensate if GDK_SCALE overshoots text size

For a 1.5× fractional target you cannot use GDK_SCALE=1.5 for XWayland GTK3 apps—it only accepts integers. The practical workaround is GDK_SCALE=2 with GDK_DPI_SCALE=0.75, which renders at 2× then scales text back down to an effective 1.5× appearance.

Put these in ~/.config/environment.d/hidpi.conf (systemd user environment, picked up by login sessions):

GDK_SCALE=2
GDK_DPI_SCALE=0.75

Qt apps (Qt5 / KDE apps under XWayland)

export QT_SCALE_FACTOR=1.5
export QT_AUTO_SCREEN_SCALE_FACTOR=0   # prevent Qt from second-guessing you

QT_SCALE_FACTOR accepts decimal values, so 1.5 works directly. Add these to the same hidpi.conf file. Qt6 apps running natively on Wayland ignore this variable and use the compositor scale, so there is no conflict.

Applying environment variables system-wide

The ~/.config/environment.d/ method is preferred over ~/.bashrc because it is read by systemd --user before the graphical session starts, so GUI apps launched from launchers (not terminals) also see the variables.

mkdir -p ~/.config/environment.d
cat >> ~/.config/environment.d/hidpi.conf << 'EOF'
GDK_SCALE=2
GDK_DPI_SCALE=0.75
QT_SCALE_FACTOR=1.5
QT_AUTO_SCREEN_SCALE_FACTOR=0
EOF

Step 3: Fix Electron Apps

Electron 22+ supports the Wayland Ozone backend, which means apps can run natively on Wayland and pick up the compositor scale automatically—no env vars needed. But you have to opt in, either per-app or globally.

Enable the Wayland backend per app

Most Electron apps respect a --flags file or a .conf file in ~/.config/. For VS Code:

mkdir -p ~/.config/code-flags.conf
echo '--enable-features=WaylandWindowDecorations,UseOzonePlatform' > ~/.config/code-flags.conf
echo '--ozone-platform=wayland' >> ~/.config/code-flags.conf

For other Electron apps (Slack, Discord, Obsidian), check whether the app ships a <appname>-flags.conf file under ~/.config/ or supports ELECTRON_OZONE_PLATFORM_HINT:

echo 'ELECTRON_OZONE_PLATFORM_HINT=auto' >> ~/.config/environment.d/hidpi.conf

Setting this to auto tells Electron to use Wayland when the session is Wayland and fall back to X11 otherwise. This is the safest global approach.

Electron apps still on XWayland

If an Electron app refuses to run natively on Wayland, force a DPI hint via the command line or the app's flags file:

--force-device-scale-factor=1.5

Add that flag to the relevant ~/.config/<app>-flags.conf or pass it when launching from a terminal to test first.

Step 4: Set the XWayland DPI for Remaining X11 Apps

Some old X11 apps read the server's DPI value directly from Xorg resources rather than env vars. Override it:

echo 'Xft.dpi: 144' >> ~/.Xresources
xrdb -merge ~/.Xresources

144 DPI corresponds to a 1.5× scale on a nominal 96 DPI display. Adjust proportionally: 120 DPI for 1.25×, 192 DPI for 2×. This only takes effect after XWayland restarts (i.e., after you log out and back in).

Verification

After logging out and back in, verify the variables loaded correctly:

systemctl --user show-environment | grep -E 'GDK|QT|ELECTRON|SCALE'

Expected output will vary but should list your configured variables. Open a test GTK3 app, a Qt5 app, and an Electron app side by side and compare text sharpness. On GNOME you can also run:

gsettings get org.gnome.mutter experimental-features

to confirm fractional scaling is still active after the session restart.

Troubleshooting

Everything is blurry despite settings

GNOME's fractional scaling feature renders XWayland surfaces at a higher resolution and then downsamples them. If XWayland apps still look blurry, you likely have a mismatch: the compositor is scaling to 1.5× but GDK_SCALE is still 1. Check systemctl --user show-environment to confirm the env vars are actually visible to the session, not just your terminal.

Qt apps are double-scaled (huge)

This happens when both the compositor fractional scale and QT_SCALE_FACTOR are active for a native Wayland Qt6 app. Set QT_SCALE_FACTOR=1 for Qt6 Wayland-native apps, or remove the variable entirely and let the compositor handle it. You can use a per-app wrapper script as a workaround for mixed Qt5/Qt6 environments.

App launcher icons look correct but the app window is blurry

The app is running under XWayland and ignoring toolkit scaling. Try passing --ozone-platform=wayland (Electron), setting QT_QPA_PLATFORM=wayland (Qt5), or using a Flatpak version of the app which ships newer toolkit libraries with better HiDPI support.

Sway: some apps scale fine, others don't

Confirm xwayland enable is in your sway config (it is the default). Then ensure env vars are exported in ~/.config/environment.d/ or sourced in the script that launches sway. Variables in ~/.bashrc are not read by apps launched via dmenu or wofi unless you explicitly source them in your sway exec chain.

tested on:Ubuntu 24.04Fedora 40Arch 2024-05Debian 12

Frequently asked questions

Why can't I just set GDK_SCALE=1.5 for fractional scaling in GTK3 apps?
GDK_SCALE only accepts integer values for GTK3. The workaround is GDK_SCALE=2 combined with GDK_DPI_SCALE=0.75, which renders at 2× internally and scales text back down to an effective 1.5× appearance.
Will these environment variables break apps on an external 1× monitor?
Wayland-native apps use per-output compositor scaling, so they are unaffected. XWayland apps will appear too large on a 1× monitor because those env vars apply globally. A per-app launcher script with unset GDK_SCALE is the cleanest workaround for mixed-DPI setups.
Does ELECTRON_OZONE_PLATFORM_HINT=auto work for all Electron apps?
It works for Electron 22 and later. Older bundled Electron versions (some apps ship Electron 14-19) do not recognize that variable and need --ozone-platform=wayland passed as a flag in the app-specific flags file instead.
My GNOME session shows the scale option but text is still slightly blurry after enabling it. What is wrong?
GNOME's fractional scaling renders XWayland surfaces at a higher buffer resolution and downsamples; some blurriness for XWayland apps is inherent to that approach. For noticeably blurry apps, the best fix is to migrate them to their Wayland-native version (e.g., install the Flatpak build) or use an integer scale like 200%.
How do I apply different scales to two monitors with different DPIs?
Wayland compositors handle per-output scaling natively: set separate scale values for each output in your compositor settings (Sway: two 'output' lines; KDE/GNOME: separate sliders per display). Wayland-native apps adapt automatically. XWayland apps only see one DPI and will look wrong on one of the two screens—this is a known limitation of XWayland.

Related guides