PálcikaWM IV. : Qtile

enlightened Ez az oldal a közösségért készül. heart Kövess minket máshol is:  Linux Mint Magyar Közösség a Mastodon-on  Telegram csatorna – csak hírek  Beszélgessünk a Telegram – Linux csevegő csoport  Hírek olvasása RSS segítségével  Linux Mint Hivatalos Magyar Közösség a Facebook-on      Linux Mint Baráti Kör a Facebook-on
wink Ha hasznosnak találod, és szeretnéd, hogy folytatódjon, támogasd a munkát Ko-fi vagy Paypal segítségével. laugh

Mielőtt belevágnánk mai témánk a Qtile kitárgyalásába, előbb következzen egy rövidke gondolatmenet friss élményeim alapján.
Aki már foglalkozott a pálcikawm világgal, nyilván nézegetett "guruk" által létrehozott konfigurációkat, csilli-villi képernyőképekkel. Szóval ezek az urak-hölgyek túltolják! Fölösleges szkriptek tucatjai, minden sorában megváltoztatott konfigurációs állományok, több tucat billentyűkombináció, amiből jó ha tízet használsz, stb., végeredmény pedig egy túlbonyolított, sokszor hibás rendszer! A konkrét élmény pedig az Archbang Linux volt bspwm ablakozóval, ahol a vége a kitty terminál képelőnézeti funkcióinak összeomlása, és ami még nagyobb gáz, a Gtk párbeszédablakok véletlenszerű eltünedezése lett...


Szerintem a pálcikawm világ lényege a hatékonyság és egyszerűség, szóval mi haladjunk ezen az úton!

A Qtile az egyik legérdekesebb pálcikawm Linuxra. A legtöbb konkurenssel szemben — mint például az i3 vagy a bspwm — a Qtile teljes konfigurációja Pythonban történik. Ez rendkívüli rugalmasságot ad, Pythonban programozni tudóknak pedig maga a Kánaán. Én sajnos semmilyen programozó nem vagyok, de némi időráfordítással azért remekül lehet boldogulni a konfigurációval.
Tehát röviden összefoglalva, a Qtile egy dinamikus csempéző ablakkezelő, Python-alapú konfigurációs rendszerrel, X11 és Wayland támogatással, alacsony erőforrásigénnyel.

Nézzük is a konfigurációs állományomat (~/.config/qtile/config.py):


###
# Berus Qtile konfiguráció
###

import os
import subprocess

from libqtile import bar, layout, qtile, widget, hook
from libqtile.config import Click, Drag, Group, Key, Match, Screen
from libqtile.lazy import lazy
#from libqtile.utils import guess_terminal

# Alapbeállítások
mod = "mod4"
#terminal = guess_terminal()
terminal = "kitty" 

# Billetyűparancsok
keys = [
    # Az elérhető parancsok listája, amiket billentyűkhöz lehet kötni, itt található:
    # https://docs.qtile.org/en/latest/manual/config/lazy.html

    # Ablakok közötti váltás (fókusz)
    Key([mod], "h", lazy.layout.left(), desc="Fókusz mozgatása balra"),
    Key([mod], "l", lazy.layout.right(), desc="Fókusz mozgatása jobbra"),
    Key([mod], "j", lazy.layout.down(), desc="Fókusz mozgatása lefelé"),
    Key([mod], "k", lazy.layout.up(), desc="Fókusz mozgatása felfelé"),
    Key([mod], "space", lazy.layout.next(), desc="Fókusz mozgatása a következő ablakra"),

    # Ablakok mozgatása az oszlopok között vagy a jelenlegi stack-ben.
    # Ha a Columns elrendezésben túlmegyünk a határon, új oszlop jön létre.
    Key([mod, "shift"], "h", lazy.layout.shuffle_left(), desc="Ablak mozgatása balra"),
    Key([mod, "shift"], "l", lazy.layout.shuffle_right(), desc="Ablak mozgatása jobbra"),
    Key([mod, "shift"], "j", lazy.layout.shuffle_down(), desc="Ablak mozgatása lefelé"),
    Key([mod, "shift"], "k", lazy.layout.shuffle_up(), desc="Ablak mozgatása felfelé"),

    # Ablakok átméretezése (növelés). Ha az ablak a képernyő szélén van és abba az 
    # irányba toljuk tovább, az ablak zsugorodni fog.
    Key([mod, "control"], "h", lazy.layout.grow_left(), desc="Ablak növelése balra"),
    Key([mod, "control"], "l", lazy.layout.grow_right(), desc="Ablak növelése jobbra"),
    Key([mod, "control"], "j", lazy.layout.grow_down(), desc="Ablak növelése lefelé"),
    Key([mod, "control"], "k", lazy.layout.grow_up(), desc="Ablak növelése felfelé"),
    Key([mod], "n", lazy.layout.normalize(), desc="Ablakméretek alaphelyzetbe állítása"),

    # Váltás az osztott (split) és nem osztott oldalak között.
    # Split = minden ablak megjelenik
    # Unsplit = csak 1 ablak látszik (mint a Max elrendezésnél), de több stack-kel
    Key(
        [mod, "shift"],
        "Return",
        lazy.layout.toggle_split(),
        desc="Váltás az osztott és nem osztott nézet között",
    ),
    Key([mod], "Return", lazy.spawn(terminal), desc="Terminál indítása"),

    # Váltás az alább definiált elrendezések (layouts) között
    Key([mod], "Tab", lazy.next_layout(), desc="Váltás az elrendezések között"),
    Key([mod], "q", lazy.window.kill(), desc="Fókuszált ablak bezárása"),
    Key(
        [mod],
        "f",
        lazy.window.toggle_fullscreen(),
        desc="Teljes képernyős mód ki/be",
    ),
    Key([mod], "t", lazy.window.toggle_floating(), desc="Lebegő mód ki/be"),
    Key([mod, "control"], "r", lazy.reload_config(), desc="Konfiguráció újratöltése"),
    Key([mod, "shift"], "e", lazy.shutdown(), desc="Qtile leállítása"),
    Key([mod], "r", lazy.spawncmd(), desc="Parancs futtatása prompt widget segítségével"),
    Key([mod], "d", lazy.spawn("rofi -show drun"), desc="Alkalmazásindító"),
]

# VT (virtuális terminál) váltás Wayland alatt.
# Nem tudjuk ellenőrizni a qtile.core.name-et az alapértelmezett konfigban, 
# mert az előbb töltődik be, mint a qtile. Ezért a .when(func=...) használatával késleltetjük.
for vt in range(1, 8):
    keys.append(
        Key(
            ["control", "mod1"],
            f"f{vt}",
            lazy.core.change_vt(vt).when(func=lambda: qtile.core.name == "wayland"),
            desc=f"Váltás a(z) VT{vt} terminálra",
        )
    )

# Asztalok, panel létrehozása és elrendezése
groups = [Group(i) for i in "123456789"]

for i in groups:
    keys.extend(
        [
            # mod + csoport száma = váltás az adott csoportra
            Key(
                [mod],
                i.name,
                lazy.group[i.name].toscreen(),
                desc=f"Váltás a(z) {i.name}. csoportra",
            ),
            # mod + shift + csoport száma = ablak mozgatása a csoportba és váltás oda
            Key(
                [mod, "shift"],
                i.name,
                lazy.window.togroup(i.name, switch_group=True),
                desc=f"Ablak mozgatása és váltás a(z) {i.name}. csoportra",
            ),
            # Vagy használd az alábbit, ha nem akarsz oda is váltani:
            # Key([mod, "shift"], i.name, lazy.window.togroup(i.name),
            #     desc="Ablak mozgatása a(z) {}. csoportba".format(i.name)),
        ]
    )

layouts = [
    layout.Columns(margin=10, border_focus_stack=["#d75f5f", "#8f3d3d"], border_width=2, border_on_single=True),
    layout.Max(),
    # További elrendezések kipróbálásához vedd ki a kommentet:
    # layout.Stack(num_stacks=2),
    # layout.Bsp(),
    # layout.Matrix(),
    # layout.MonadTall(),
    # layout.MonadWide(),
    # layout.RatioTile(),
    # layout.Tile(),
    # layout.TreeTab(),
    # layout.VerticalTile(),
    # layout.Zoomy(),
]

widget_defaults = dict(
    font="sans",
    fontsize=12,
    padding=3,
)
extension_defaults = widget_defaults.copy()

screens = [
    Screen(
        bottom=bar.Bar(
            [
                widget.GroupBox(),
                widget.Prompt(),
                widget.WindowName(),
                widget.Chord(
                    chords_colors={
                        "launch": ("#ff0000", "#ffffff"),
                    },
                    name_transform=lambda name: name.upper(),
                ),
                # FIGYELEM: A Systray nem kompatibilis a Waylanddel, használd helyette a StatusNotifiert
                # widget.StatusNotifier(),
                widget.CurrentLayout(),
                widget.TextBox("|"),
                widget.Clock(format="%Y-%m-%d %a %I:%M %p"),
                #widget.QuickExit(),
                widget.Systray(),
            ],
            24,
            # border_width=[2, 0, 2, 0],  # Alsó-felső szegély
            # border_color=["ff00ff", "000000", "ff00ff", "000000"]  # Magenta szegélyek
        ),
        # Vedd ki a kommentet, ha X11 alatt a lebegő ablakok átméretezése/mozgatása akadna.
        # Alapértelmezés szerint késleltetve kezeljük ezeket a teljesítmény javítása érdekében.
        # x11_drag_polling_rate = 60,
    ),
]

# Lebegő ablakok egérrel való kezelése
mouse = [
    Drag([mod], "Button1", lazy.window.set_position_floating(), start=lazy.window.get_position()),
    Drag([mod], "Button3", lazy.window.set_size_floating(), start=lazy.window.get_size()),
    Click([mod], "Button2", lazy.window.bring_to_front()),
]

dgroups_key_binder = None
dgroups_app_rules = []  # típus: lista
follow_mouse_focus = True
bring_front_click = False
floats_kept_above = True
cursor_warp = False
floating_layout = layout.Floating(
    float_rules=[
        # Használd az `xprop` eszközt az ablak wm_class és name lekéréséhez.
        *layout.Floating.default_float_rules,
        Match(wm_class="confirmreset"),  # gitk
        Match(wm_class="makebranch"),  # gitk
        Match(wm_class="maketag"),  # gitk
        Match(wm_class="ssh-askpass"),  # ssh-askpass
        Match(title="branchdialog"),  # gitk
        Match(title="pinentry"),  # GPG kulcs jelszó bekérő
    ]
)
auto_fullscreen = True
focus_on_window_activation = "smart"
reconfigure_screens = True

# Ha bizonyos programok minimalizálni akarják magukat fókuszvesztéskor,
# figyelembe vegyük-e ezt?
auto_minimize = True

# Wayland backend használata esetén itt konfigurálhatók a beviteli eszközök.
wl_input_rules = None

# xcursor téma (string vagy None) és méret (egész szám) Waylandhez
wl_xcursor_theme = None
wl_xcursor_size = 24

# XXX: Itt "hazudunk". Valójában senkit nem érdekel ez a string a Java UI toolkit-eken kívül;
# Számos fórum és dokumentáció javasolja ennek beállítását, ha a Java alkalmazások nem működnek jól.
# Úgy teszünk, mintha egy támogatott ablakkezelő lennénk.
#
# Az LG3D-t választottuk az irónia kedvéért: ez egy Java-ban írt 3D-s WM, ami rajta van a Java fehérlistáján.
wmname = "LG3D"

## Automatikus indítás szkript
@hook.subscribe.startup_once
def autostart():
    home = os.path.expanduser("~/.config/qtile/autostart.sh")
    subprocess.Popen([home])

Némi magyarázat hozzá!

Mindjárt az elején, ha a rendszerben alapértelmezett terminált akarjuk használni, vegyük ki a kommentet ezek elől: #from libqtile.utils import guess_terminal és #terminal = guess_terminal().
A konfigurációmban a kitty-t választottam alapértelmezett terminálnak, módosító pedig a megszokott bal Win billentyű.
A Vim-stílusú navigáció (mod+ h, j, k, l) alapvető nálam. A fókusz mozgatása mellett a 'control' billentyűvel kombinálva az ablakok átméretezése történik. Ha pedig káosz van, a 'mod + n' gombbal lehet rendet rakni.
A konfiguráció automatikusan generál 9 munkaasztalt: groups = [Group(i) for i in "123456789"].
Alapvetően a "Columns" elrendezést használom: layout.Columns(margin=10, border_focus_stack=["#d75f5f", "#8f3d3d"], border_width=2, border_on_single=True), tehát térköz 10-re állítva, keret színezése (azért használjuk a border_focus_stack formulát, mert így a 'max' elrendezésnél is látjuk, ha több ablak van egymáson), keret szélessége 2, és ha csak egy ablakunk van, akkor is legyen keret.
A képernyő alján lévő panelen (bottom=bar.Bar) is takarítottam kicsit, itt látszanak a virtuális asztalok (GroupBox), az éppen aktív ablak neve (WindowName), az elrendezés (CurrentLayout), az óra (Clock), és a rendszertálca (Systray). Itt jelenik meg a Qtile saját programindítója is (mod+r), de nálam telepítve van a Rofi indító is (mod+d).

A konfiguráció helyességét a következő paranccsal ellenőrizhetjük: python -m py_compile ~/.config/qtile/config.py.

Következzen az autostart.sh szkriptem:

#!/usr/bin/env bash

# Ha már futnak, lőjük le őket
killall picom nm-applet redshift-gtk

# Most indítsuk el őket újra
picom &
redshift-gtk &
nm-applet &

# A háttérkép beállítása (ez általában felülírja az előzőt, nem kell pkill)
/home/berus/.fehbg &

# Hang
# Ha már futnak, lőjük le őket
killall pipewire wireplumber pipewire-pulse pasystray

# Indítsuk el a folyamatokat sorban
# Fontos a sorrend és a háttérbe küldés (&)
pipewire &
sleep 1
wireplumber &
sleep 1
pipewire-pulse &
sleep 1

# Jöhet a tálca ikon 
pasystray &

Elég egyértelmű, de azért a hangkeltésről ejtsünk néhány szót...! Szóval jelenlegi Linuxos életem egyik fontos eleme, hogy próbálok szabadulni a systemd nevezetű borzalomtól, sikerrel! De ez néha megnehezíti az életet, így pl. Devuan+ Sysv+ Qtile (vagy bármelyik pálcikawm) esetén a pipewire hangmodul életre keltése nem triviális, a fentebb látható módon az autostart.sh szkriptben kezeljük, és ahogy ott is írtam, figyeljünk az indítási sorrendre!

Kedvcsinálónak ennyit, barátunk a man, és rengeteg példát találunk a hálón, ahonnan szedegethetünk ötleteket!

 

Berus
 

Hozzászólások

Konfig változás!

Értékelés: 

0
Még nincs értékelve

Közben változtattam a koncepción, minden elrendezéshez (layouts) ugyanazt a beállítást használom, a layout_theme rész került a konfigba!

layout_theme = {
    "border_width": 2,
    "margin": 10,
    "border_focus": "6c757d",
    "border_normal": "343a40",
    "border_focus_stack": "a77eff",
    "border_on_single": True
}

layouts = [
    layout.Columns(**layout_theme),