global-shortcut-portal
A pure-Python library for the Wayland Global Shortcut Portal (org.freedesktop.portal.GlobalShortcuts).
Lets any application register and receive global keyboard shortcuts on Wayland — without X11 key grabbing.
AI was used heavily during development, with human review and testing of all code.
This is a personal library I wanted and I'm sharing it in case it's useful to others.
Requirements
- Python >= 3.10
dbus-next(pure Python, no C extensions)- A Wayland compositor with a Global Shortcuts portal backend (KDE Plasma 6+, GNOME 48+, Hyprland, etc.)
Installation
pip install global-shortcut-portal
On systems with an externally managed environment (e.g. recent Debian/Ubuntu, Fedora, Arch Linux with system Python) use
pip install --useror a virtual environment. Alternatively, install withuv:uv pip install global-shortcut-portalFor development, clone the repo and run:
uv sync
Reference Example
The repository includes a fully-commented reference app at
examples/reference_example_app.py that demonstrates the
complete session lifecycle with interactive controls:
| Key | Action |
|---|---|
b |
Bind example shortcuts with default triggers |
e |
Register shortcuts without triggers |
c |
Open the native config dialog |
r |
Reset the session |
q |
Quit |
python examples/reference_example_app.py
Documentation
- docs/overview.md — the Global Shortcut Portal and this library
- docs/usage.md — full API guide with code examples
- examples/reference_example_app.py — interactive reference app
Quick Start
import asyncio
from global_shortcut_portal import GlobalShortcutsSession, Portal, Shortcut, SessionCallback
class MyCallback(SessionCallback):
def on_activated(self, event):
print(f"Shortcut activated: {event.shortcut_id}")
def on_deactivated(self, event):
print(f"Shortcut deactivated: {event.shortcut_id}")
async def main():
portal = Portal()
await portal.connect()
session = GlobalShortcutsSession(
portal,
app_id="org.example.MyApp",
callback=MyCallback(),
)
await session.connect()
shortcuts = [
Shortcut(
id="toggle-overlay",
description="Toggle overlay window",
preferred_trigger="<Control><Alt>space",
),
]
bound = await session.bind(shortcuts)
for s in bound:
print(f"Bound: {s.id} -> {s.trigger_description}")
await asyncio.Event().wait()
asyncio.run(main())
Features
- Async API via
dbus-next(pure Python asyncio D-Bus library) - Session life-cycle management (create, bind, list, configure, close)
- Supports
Registry.Registerfor xdg-desktop-portal >= 1.20 - Full signal handling (Activated, Deactivated, ShortcutsChanged)
- Shortcut trigger parsing and formatting (XDG shortcuts specification)
- Version 2 portal features (ConfigureShortcuts)
Notes
- Desktop environment persistence: Some DEs (notably Plasma/KDE) persist
shortcut triggers per
app_id. Once registered,BindShortcutscannot overwrite these stored values. Use the native config dialog or remove entries in System Settings > Keyboard > Shortcuts while the app is closed.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file global_shortcut_portal-0.1.0.tar.gz.
File metadata
- Download URL: global_shortcut_portal-0.1.0.tar.gz
- Upload date:
- Size: 25.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bae2d6ba9f70e2b2b3d1d052b06cfd264abc04b7004dd3f847f3f429c22aebda
|
|
| MD5 |
1e9f0aa9ae5b6a9fb14241966743fb94
|
|
| BLAKE2b-256 |
86baf818e9294e29c4f6af60dcec6318f003efb57fccb9acab82aac8b988b37e
|
File details
Details for the file global_shortcut_portal-0.1.0-py3-none-any.whl.
File metadata
- Download URL: global_shortcut_portal-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4512ca320f2478f86680b12b6bc7fec5e2ec453799e01f2513247bdd86817f0
|
|
| MD5 |
5f31d28c280409b9ceb60995940df3a9
|
|
| BLAKE2b-256 |
634f3e38cceeec6554ebf1c2f2ab66c9acd05fbe26a1ef58b46c944c6f74705c
|