GameMode
org.
Ask the host to apply CPU governor and scheduling tweaks while your game is in the foreground.
Godot 4.4+ · GDExtension · MIT
Keep GameMode on, stop the screen blanking mid-cutscene, react to power-saver mode, open a URL, post a notification — from six lines of GDScript. Works inside a Flatpak sandbox, where the usual tricks quietly stop working.
No D-Bus in your game code. No shelling out. No broad sandbox permissions.
Everything a Linux game wants from the desktop sits behind D-Bus, and Godot cannot speak it. The usual workarounds break the moment your game ships as a Flatpak.
OS.execute("gdbus", ...) — fails in a sandbox, and spawns a process per call.gamemoded directly — needs a broad --talk-name that reviewers push back on.DesktopServices, with a typed API and real enums.--socket=session-bus and one --talk-name.
Each maps to an org.freedesktop.portal.* interface, discovered at
startup and version-gated where the spec requires it.
org.
Ask the host to apply CPU governor and scheduling tweaks while your game is in the foreground.
org.
Block idle, suspend, logout or user switching for as long as you hold the handle. Cutscenes stay on screen.
org.
Know when the machine enters power-saver mode so you can drop the frame cap instead of draining the battery.
org.
Open your manual, storefront or Discord in the user's browser. file: is refused, case-insensitively.
org.
Post a desktop notification with a priority, withdraw it later, and receive the action the player clicked.
version properties & capabilities
Ask what the running desktop actually exports before you use it. Ship one build for every distro and compositor.
The whole integration, from a real project.
Keep the screen awake during a cutscene
var _handle := "" func begin_cutscene() -> void: var flags := DesktopServices.InhibitFlags.IDLE | DesktopServices.InhibitFlags.SUSPEND _handle = DesktopServices.inhibit(flags, "Playing a cutscene") func end_cutscene() -> void: if _handle != "": DesktopServices.close_request(_handle) _handle = ""
Turn GameMode on, and follow the battery
func _ready() -> void: if DesktopServices.has_capability(DesktopServices.Capability.GAME_MODE): DesktopServices.request_game_mode() DesktopServices.power_saver_changed.connect(_on_power_saver_changed) func _on_power_saver_changed(enabled: bool) -> void: Engine.max_fps = 30 if enabled else 0
Unknown is a real answer, not a guess
# Returns true, false, or null — never a plausible-looking lie. var saving: Variant = DesktopServices.is_power_saver_enabled() if saving == null: pass # The portal could not tell us. Do nothing. elif saving: reduce_quality()
A portal that is missing, an old desktop, a machine with no session bus — each has a defined answer, and none of them is a fake success.
| Situation | What you get |
|---|---|
| Portal interface not exported | has_capability() is false; calls return false or "" |
| Power-saver state unreadable | null — never a guessed false |
Portal too old for SchemeSupported | null, because the question genuinely cannot be answered |
| User dismisses the "open with" dialog | Response.CANCELLED, not a success |
| Windows, mobile, web | Null backend; the addon loads and every call reports unavailable |
| macOS (experimental) | Power-saver state only; the other four capabilities report unavailable |
| Headless Linux, no session bus | Null backend with the reason attached, no crash |
Grab the release archive, or build the extension yourself.
From a release (v0.2.0, Linux x86-64 and arm64)
# godot-xdg-portals-0.2.0-linux-x86_64.zip (or -arm64), checked against its .sha256. # Extract addons/xdg_portals into your project, then enable # "XDG Portals" in Project Settings → Plugins. # The plugin installs the DesktopServices autoload for you.
From source
git clone https://github.com/KevinTCoughlin/godot-xdg-portals.git
cd godot-xdg-portals
sudo apt-get install build-essential cmake pkg-config libglib2.0-dev
./scripts/build.sh --target template_release
Flatpak manifest — the whole permission cost
finish-args: - --socket=session-bus - --talk-name=org.freedesktop.portal.Desktop