Skip to main content
Version: 2.0 (dev)

Fractional Scaling somewm-only

SomeWM supports fractional output scaling for HiDPI displays through the screen.scale property.

Choosing a Scale

ScaleEffectUse Case
1.0Native resolutionStandard 1080p/1440p
1.2525% larger1440p HiDPI
1.550% larger4K laptop displays
2.0Double size4K desktop / Retina

How scaling works under the hood, and why Wayland's version is crisp where X11's was blurry, is covered in Display Scaling Concepts.

Setting Scale from Lua

At Startup

In your rc.lua:

-- Set scale for all screens
awful.screen.connect_for_each_screen(function(s)
s.scale = 1.5
end)

-- Or just the primary screen
screen.primary.scale = 1.5

Per-Screen Configuration

awful.screen.connect_for_each_screen(function(s)
-- Different scale based on screen size
if s.geometry.width > 3000 then
s.scale = 1.5 -- 4K display
elseif s.geometry.width > 2000 then
s.scale = 1.25 -- 1440p display
else
s.scale = 1.0 -- 1080p or smaller
end
end)

Dynamic Adjustment

-- Keybinding to adjust scale
awful.keyboard.append_global_keybindings({
awful.key({ modkey }, "equal", function()
local s = awful.screen.focused()
s.scale = s.scale + 0.25
end, { description = "increase scale", group = "screen" }),

awful.key({ modkey }, "minus", function()
local s = awful.screen.focused()
s.scale = math.max(0.5, s.scale - 0.25)
end, { description = "decrease scale", group = "screen" }),
})

Setting Scale from CLI

Use somewm-client to adjust scale at runtime:

# Get current scale of focused screen
somewm-client screen scale

# Set focused screen to 1.5
somewm-client screen scale 1.5

# Set specific screen (by index)
somewm-client screen scale 1 1.5
somewm-client screen scale 2 1.0

Making Themes DPI-Aware

Use beautiful.xresources.apply_dpi() to scale theme values:

-- theme.lua
local xresources = require("beautiful.xresources")
local dpi = xresources.apply_dpi

local theme = {}

-- These values scale with DPI
theme.font = "sans " .. dpi(10)
theme.useless_gap = dpi(4)
theme.border_width = dpi(2)
theme.notification_width = dpi(300)

-- Icon sizes
theme.menu_height = dpi(20)
theme.menu_width = dpi(150)

-- Widget sizes
theme.wibar_height = dpi(24)
theme.systray_icon_spacing = dpi(4)

return theme

The dpi() function reads the system DPI and scales values accordingly.

Manual DPI Calculation

If you need more control:

local function scale_value(value)
local s = awful.screen.focused()
return math.floor(value * (s.scale or 1.0))
end

-- Usage
local margin = scale_value(8) -- 8 at 1x, 12 at 1.5x, etc.

Workarea and Geometry

When you change scale, screen geometry updates:

local s = screen.primary
print("Before:", s.geometry.width, s.geometry.height)

s.scale = 2.0

print("After:", s.geometry.width, s.geometry.height)
-- Width/height are now halved (logical pixels)

The workarea also recalculates to account for wibars at the new scale.

App Compatibility

Wayland-Native Apps

Apps supporting wp_fractional_scale_v1 render at native resolution and scale properly. Most modern GTK4 and Qt6 apps support this.

XWayland Apps

X11 apps through XWayland may appear blurry at fractional scales. Options:

  1. Use integer scaling (1.0, 2.0) for crisp XWayland apps
  2. Force per-app scaling via environment variables:
-- Force 2x for specific app, let Wayland downscale
awful.spawn.with_shell("GDK_SCALE=2 my-gtk-app")

GTK Apps

# Force GTK3 to use Wayland
export GDK_BACKEND=wayland

# Or set in rc.lua autostart
awful.spawn.with_shell("export GDK_BACKEND=wayland")

Qt Apps

# Enable Qt Wayland
export QT_QPA_PLATFORM=wayland
export QT_SCALE_FACTOR=1.5

Electron Apps

# Enable Wayland for Electron
export ELECTRON_OZONE_PLATFORM_HINT=wayland

Mixed-DPI Multi-Monitor

For setups with different DPI monitors:

awful.screen.connect_for_each_screen(function(s)
-- Identify screen by geometry or output name
if s.geometry.width == 3840 then
s.scale = 1.5 -- 4K monitor
else
s.scale = 1.0 -- 1080p monitor
end
end)

Handling Hotplug

screen.connect_signal("added", function(s)
-- New monitor connected, set appropriate scale
if s.geometry.width > 3000 then
s.scale = 1.5
else
s.scale = 1.0
end
end)

Common Scale Values

ResolutionDiagonalRecommended Scale
1920x108024"+1.0
2560x144027"1.0 - 1.25
3840x216027"1.5 - 2.0
3840x216032"1.25 - 1.5
2880x180015" (laptop)1.5 - 2.0

Troubleshooting

Blurry Text

  • Try integer scaling (1.0, 2.0) instead of fractional
  • Ensure app supports Wayland native rendering
  • Check font hinting settings

Widgets Wrong Size

Make sure you're using dpi() for all size values in theme.lua:

-- Wrong: fixed pixel values
theme.useless_gap = 4

-- Right: DPI-aware values
theme.useless_gap = dpi(4)

Scale Not Applying

Check that you're setting scale on the correct screen:

-- Debug: print all screens and their scales
for s in screen do
print("Screen " .. s.index .. ": scale = " .. (s.scale or "nil"))
end

See Also