A Sway egy Wayland alapú tiling ablakkezelő, ami az i3 WM Wayland alpú alternatívája.
Nagyban kompatibilis az i3 konfigurációs szintaxisával, de natív Wayland (wlroots) támogatással, hardveres gyorsítással és modern grafikus stack-kel.
Tehát a Laci i3-as cikkében leírtak jó eséllyel ráhúzhatóak a Sway-re, ezért ez egy rövidebb bemutató lesz...

Először is nézzük a Wayland alapú eszközöket, amikre szükségünk van/lehet:
- swaylock: képernyőzároló;
- swayidle: képernyőkímélő;
- swaybg: háttérkép;
- swaymsg: üzenet küldő;
- swaynag: hibajelző;
- grim és slurp: képernyőkép készítés;
- waybar: panel (használhatjuk a beépítettet is, a swaybart);
- wlogout: "power" menü;
- wlsunset: gamma-korrekció (gyk. redshift klón);
- rofi: alkalmazás indító (már natív Wayland támogatással, alternatíva wofi);
- bemenu: alkalmazás indító (dmenu klón, működik X alatt is).
Nézzük is a konfigurációs állományomat ( ~/.config/sway/config ):
# Berus Sway konfiguráció
### Változók (Variables)
# Módosító billentyű.
set $mod Mod4
# Iránybillentyűk, mint a vim-ben
set $left h
set $down j
set $up k
set $right l
# A preferált terminál
set $term kitty
# A preferált alkalmazásindítód
# Megjegyzés: a végső parancsot add át a swaymsg-nek, hogy az eredményül kapott ablak
# az eredeti munkaterületen nyíljon meg, ahol a parancsot futtattad.
set $rofi_cmd rofi \
-terminal '$term'
#set $menu $rofi_cmd -show combi -combi-modes drun#run -modes combi
set $menu $rofi_cmd -show drun
### Kimeneti konfiguráció (Output configuration)
# Alapértelmezett háttérkép
# Szükséges: desktop-backgrounds-compat, swaybg, jxl-pixbuf-loader
output * bg /home/berus/Képek/wp.jpg fill
#
# Példa konfiguráció:
#
# output HDMI-A-1 resolution 1920x1080 position 1920,0
#
# A kimenetek nevét a következő futtatásával kaphatod meg: swaymsg -t get_outputs
### Üresjárati (Idle) konfiguráció
# Példa konfiguráció:
#
# exec swayidle -w \
# timeout 300 'swaylock -f -c 000000' \
# timeout 600 'swaymsg "output * power off"' resume 'swaymsg "output * power on"' \
# before-sleep 'swaylock -f -c 000000'
#
# Ez 300 másodperc inaktivitás után zárolja a képernyőt, majd további 300 másodperc után
# kikapcsolja a kijelzőket, és újra bekapcsolja őket, amikor folytatódik a munka.
# A számítógép alvás előtti zárolását is elvégzi.
### Bemeneti konfiguráció (Input configuration)
# Példa konfiguráció:
#
# input "2:14:SynPS/2_Synaptics_TouchPad" {
# dwt enabled
# tap enabled
# natural_scroll enabled
# middle_emulation enabled
# }
#
# A bemenetek nevét a következő futtatásával kaphatod meg: swaymsg -t get_inputs
### Billentyűparancsok (Key bindings)
# Alapok (Basics):
#
# Terminál indítása
bindsym $mod+Return exec $term
# A fókuszált ablak bezárása
bindsym $mod+q kill
# Az indító (launcher) elindítása
bindsym $mod+d exec $menu
# Lebegő ablakok mozgatása a $mod és a bal egérgomb lenyomva tartásával.
# Átméretezésük a jobb egérgomb + $mod használatával.
# Cseréld normal-ról inverse-re, ha a bal egérgombot az átméretezéshez, a jobbat pedig a húzáshoz szeretnéd használni.
floating_modifier $mod normal
# A konfigurációs fájl újratöltése
bindsym $mod+Shift+c reload
# Kilépés a sway-ből (kijelentkezés a Wayland munkamenetből)
# Figyelmeztető üzenet megjelenítése, mielőtt ténylegesen kilép
bindsym $mod+Shift+e exec swaynag -t warning -m 'Biztosan ki akarsz lépni a Swayből? Ezzel befejezed a Wayland-es munkamenetedet.' -B 'Igen, kilépés.' 'swaymsg exit'
# Power menü
bindsym $mod+Shift+p exec wlogout
### Ablakkeret Színek Beállítása (Client Colors)
# A színek hexadecimális formátumban (#RRGGBB) adandók meg.
# Szintaxis: client.<állapot> border_color background_color text_color indicator_color child_border_color
# Fókuszált ablak kerete (Jelenleg aktív ablak)
#client.focused #4c7899 #285577 #ffffff #2e9ef4 #285577
client.focused #AFD700 #AFD700 #000000 #AFD700
# Fókuszált, de NEM aktív munkaterületen lévő ablak kerete
#client.focused_inactive #333333 #5f676a #ffffff #484e50 #5f676a
client.focused_inactive #111111 #768e10 #000000 #000000
# Nem fókuszált ablak kerete (Egyéb ablakok)
#client.unfocused #333333 #5f676a #888888 #292d2e #5f676a
client.unfocused #111111 #768e10 #000000 #000000
# Sürgősnek jelölt ablak (pl. új üzenet érkezett) kerete
#client.urgent #2f343a #900000 #ffffff #900000 #900000
client.urgent #d42121 #d42121 #f7f7f7 #d42121
# Tartalék (Placeholder) keret
#client.placeholder #000000 #0c0c0c #ffffff #000000 #0c0c0c
client.placeholder #111111 #768e10 #000000 #000000
# Szegély vastagság és stílus (gyk. ablakcímmező ki)
default_border pixel 2
default_floating_border pixel 2
# Mozgás (Moving around):
#
# A fókusz mozgatása
bindsym $mod+$left focus left
bindsym $mod+$down focus down
bindsym $mod+$up focus up
bindsym $mod+$right focus right
# Vagy használd a $mod+[fel|le|bal|jobb] nyilakat
bindsym $mod+Left focus left
bindsym $mod+Down focus down
bindsym $mod+Up focus up
bindsym $mod+Right focus right
# A fókuszált ablak mozgatása ugyanígy, de Shift hozzáadásával
bindsym $mod+Shift+$left move left
bindsym $mod+Shift+$down move down
bindsym $mod+Shift+$up move up
bindsym $mod+Shift+$right move right
# Ugyanez, nyíl billentyűkkel
bindsym $mod+Shift+Left move left
bindsym $mod+Shift+Down move down
bindsym $mod+Shift+Up move up
bindsym $mod+Shift+Right move right
# Munkaterületek (Workspaces):
#
# Váltás munkaterületre
bindsym $mod+1 workspace number 1
bindsym $mod+2 workspace number 2
bindsym $mod+3 workspace number 3
bindsym $mod+4 workspace number 4
bindsym $mod+5 workspace number 5
bindsym $mod+6 workspace number 6
bindsym $mod+7 workspace number 7
bindsym $mod+8 workspace number 8
bindsym $mod+9 workspace number 9
bindsym $mod+0 workspace number 10
# A fókuszált konténer áthelyezése munkaterületre
bindsym $mod+Shift+1 move container to workspace number 1
bindsym $mod+Shift+2 move container to workspace number 2
bindsym $mod+Shift+3 move container to workspace number 3
bindsym $mod+Shift+4 move container to workspace number 4
bindsym $mod+Shift+5 move container to workspace number 5
bindsym $mod+Shift+6 move container to workspace number 6
bindsym $mod+Shift+7 move container to workspace number 7
bindsym $mod+Shift+8 move container to workspace number 8
bindsym $mod+Shift+9 move container to workspace number 9
bindsym $mod+Shift+0 move container to workspace number 10
# Megjegyzés: a munkaterületeknek bármilyen nevet adhatsz, nem csak számokat.
# Elrendezés (Layout stuff):
#
# Az aktuálisan fókuszált objektumot "feloszthatod" (split)
# $mod+b-vel vízszintesen és $mod+v-vel függőlegesen.
bindsym $mod+b splith
bindsym $mod+v splitv
# A jelenlegi konténer váltása különböző elrendezési stílusok között
bindsym $mod+s layout stacking
bindsym $mod+w layout tabbed
bindsym $mod+e layout toggle split
# A jelenlegi fókusz teljes képernyőre állítása
bindsym $mod+f fullscreen
# A jelenlegi fókusz váltása csempéző és lebegő mód között
bindsym $mod+Shift+space floating toggle
# Fókusz váltása a csempéző terület és a lebegő terület között
bindsym $mod+space focus mode_toggle
# Fókusz áthelyezése a szülő konténerre
bindsym $mod+a focus parent
# Jegyzettömb (Scratchpad):
#
# A Sway rendelkezik egy "jegyzettömbbel" (scratchpad).
# Küldhetsz oda ablakokat, és később visszahozhatod őket.
# A jelenleg fókuszált ablak áthelyezése a jegyzettömbbe
bindsym $mod+Shift+minus move scratchpad
# A következő jegyzettömb ablak megjelenítése vagy a fókuszált jegyzettömb ablak elrejtése.
# Ha több jegyzettömb ablak van, ez a parancs ciklikusan vált köztük.
bindsym $mod+minus scratchpad show
# Konténerek átméretezése (Resizing containers):
#
mode "resize" {
# left csökkenti a konténer szélességét
# right növeli a konténer szélességét
# up csökkenti a konténer magasságát
# down növeli a konténer magasságát
bindsym $left resize shrink width 10px
bindsym $down resize grow height 10px
bindsym $up resize shrink height 10px
bindsym $right resize grow width 10px
# Ugyanez, nyíl billentyűkkel
bindsym Left resize shrink width 10px
bindsym Down resize grow height 10px
bindsym Up resize shrink height 10px
bindsym Right resize grow width 10px
# Visszatérés az alapértelmezett módba
bindsym Return mode "default"
bindsym Escape mode "default"
}
bindsym $mod+r mode "resize"
# Konfigurációk befoglalása (Include configs)
# Konfigurációk befoglalása 3 helyről:
# - /usr/share/sway/config.d
# - /etc/sway/config.d
# - $XDG_CONFIG_HOME/sway/config.d ($HOME/.config/sway/config.d)
#
# Ha több könyvtár is tartalmaz azonos nevű fájlokat, a később szereplő könyvtár élvez elsőbbséget;
# a `$XDG_CONFIG_HOME/sway/config.d/20-swayidle.conf`
# mindig be lesz töltve a `/usr/share/sway/config.d/20-swayidle.conf`
# vagy a `/etc/sway/config.d/20-swayidle.conf` helyett.
#
# Ez a mechanizmus lehetővé teszi az alapértelmezett konfiguráció felülírását rendszerszinten
# (/etc) vagy felhasználónként ($XDG_CONFIG_HOME) is.
# Egyszerűen hozd létre a módosítani/felülírni kívánt fájlt a magasabb szintű könyvtárban.
#
include '$(/usr/libexec/sway/layered-include "/usr/share/sway/config.d/*.conf" "/etc/sway/config.d/*.conf" "${XDG_CONFIG_HOME:-$HOME/.config}/sway/config.d/*.conf")'
# Hézagok (Gaps)
gaps inner 5
gaps outer 5
# Automatikus indítás (Autostart)
exec /home/berus/.config/sway/xkb-config
exec wlsunset -t NAPPALI -T ÉJSZAKAI -l SZÉLESSÉG -L HOSSZÚSÁG -g GAMMA
# exec foot -sSzokás szerint magyarázatokkal ellátott, ill. a Laci cikke is segít a megértésben, így nem részletezném, csak annyi megjegyzés, hogy a billentyűzet beállításokat külön szkriptből állítom be (Fedora féle xkb-config),
ami átveszi a localectl beállításait, de természetesen hagyományosan a fenti fájlban is beállítható pl. a magyar kiosztás. A szkript (Fedora xkb-config):
#!/usr/bin/python3
"""
Sync Sway input configuration with org.freedesktop.locale1.
Usage:
Configure keyboard mappings with `localectl set-x11-keymap`.
Add `exec /path/to/script` to your Sway config.
See also:
https://www.freedesktop.org/software/systemd/man/org.freedesktop.locale1.html
Dependencies: dbus-next, i3ipc
"""
import argparse
import asyncio
import logging
from typing import Any, Dict
from dbus_next import BusType, DBusError, Variant
from dbus_next.aio import MessageBus
from i3ipc.aio import Connection
DEFAULT_DEVICE = 'type:keyboard'
LOG = logging.getLogger("sway.locale1")
LOCALE1_BUS_NAME = "org.freedesktop.locale1"
LOCALE1_OBJECT_PATH = "/org/freedesktop/locale1"
LOCALE1_INTERFACE = "org.freedesktop.locale1"
PROPERTIES_INTERFACE = "org.freedesktop.DBus.Properties"
PROPERTIES = {
'X11Layout': 'layout',
'X11Model': 'model',
'X11Variant': 'variant',
'X11Options': 'options'
}
class Locale1Client:
"""Handle org.freedesktop.locale1 updates and pass XKB configuration to Sway"""
layout: str = ''
model: str = ''
variant: str = ''
options: str = ''
def __init__(self,
bus: MessageBus,
conn: Connection,
device: str = DEFAULT_DEVICE):
self._bus = bus
self._conn = conn
self._proxy = None
self._device = device
async def connect(self):
"""asynchronous initialization code"""
introspection = await self._bus.introspect(LOCALE1_BUS_NAME,
LOCALE1_OBJECT_PATH)
self._proxy = self._bus.get_proxy_object(LOCALE1_BUS_NAME,
LOCALE1_OBJECT_PATH,
introspection)
self._proxy.get_interface(PROPERTIES_INTERFACE).on_properties_changed(
self.on_properties_changed)
locale1 = self._proxy.get_interface(LOCALE1_INTERFACE)
self.layout = await locale1.get_x11_layout()
self.model = await locale1.get_x11_model()
self.variant = await locale1.get_x11_variant()
self.options = await locale1.get_x11_options()
await self.update()
async def on_properties_changed(self,
interface: str,
changed: Dict[str, Any],
_invalidated=None):
"""Handle updates from localed"""
if interface != LOCALE1_INTERFACE:
return
apply = False
for name, value in changed.items():
if name not in PROPERTIES:
continue
if isinstance(value, Variant):
value = value.value
self.__dict__[PROPERTIES[name]] = value
apply = True
if apply:
await self.update()
async def update(self):
"""Pass the updated xkb configuration to Sway"""
LOG.info("xkb(%s): layout '%s' model '%s', variant '%s' options '%s'",
self._device, self.layout, self.model, self.variant,
self.options)
cmd = [f"input {self._device} xkb_variant ''"]
cmd.extend([
f"input {self._device} xkb_{name} '{self.__dict__[name]}'"
for name in PROPERTIES.values()
])
replies = await self._conn.command(', '.join(cmd))
for cmd, reply in zip(cmd, replies):
if reply.error is not None:
LOG.error("command '%s' failed: %s", cmd, reply.error)
async def main(args: argparse.Namespace):
"""Async entrypoint"""
try:
bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
conn = await Connection(auto_reconnect=False).connect()
await Locale1Client(bus, conn, device=args.device).connect()
if not args.oneshot:
await conn.main()
except DBusError as exc:
LOG.error("DBus connection error: %s", exc)
except (ConnectionError, EOFError) as exc:
LOG.error("Sway IPC connection error: %s", exc)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Sync Sway input configuration with org.freedesktop.locale1"
)
parser.add_argument(
"-l",
"--loglevel",
choices=["critical", "error", "warning", "info", "debug"],
default="info",
dest="loglevel",
help="set logging level",
)
parser.add_argument(
"--device",
default=DEFAULT_DEVICE,
metavar='identifier',
nargs='?',
type=str,
help="control settings for a specific device "
"(see man sway-input; default: %(default)s)",
)
parser.add_argument("--oneshot",
action='store_true',
help="apply current settings and exit immediately")
args = parser.parse_args()
logging.basicConfig(level=args.loglevel.upper())
asyncio.run(main(args))Tipp: ha a Foot terminált (kifejezetten Wayland-hez tervezve) akarjuk használni, érdemes a foot -s paranccsal szerver módban indítani és footclient-ként meghívni ($term változó), én maradok a Kitty vonalon...
Ha már Wayland, akkor szerintem érdemes a wlroots vonalon (Sway, Hyprland, River) elindulni, tisztább, szárazabb érzés, ahogy szoktuk volt mondani, ezek a probléma mentesebb megoldások kevesebb anomáliával. Szerintem jelenleg egyértelmüen a wlroots adja a legstabilabb alapot a Wayland-hez.
Az i3 ismeretekkel rendelkezőknek nem is kérdés, a Sway a helyes választás, de a pálcikawm világban újaknak is ez talán a legegyszerűbb kiindulópont ha Wayland alapon építünk rendszert.
Laci i3-as cikke: https://www.linuxmint.hu/blog/2025/09/i3-konfiguralasa-magyarul
Berus
