My Qtile window manager configuration
git clone https://github.com/m-col/qtile-config
Files | Refs | Readme

-rw-r--r-- wayland.py


      1 """
      2 Wayland-specific configuration
      3 """
      4 
      5 import asyncio
      6 import os
      7 import subprocess
      8 
      9 from libqtile import hook, qtile
     10 from libqtile.backend.wayland import InputConfig
     11 from libqtile.backend.wayland.xdgwindow import XdgWindow
     12 from libqtile.backend.wayland.xwindow import XWindow
     13 from libqtile.backend.wayland.layer import LayerStatic
     14 from libqtile.lazy import lazy
     15 
     16 IS_XEPHYR = int(os.environ.get("QTILE_XEPHYR", 0))
     17 mod = "mod1" if IS_XEPHYR else "mod4"
     18 
     19 term = "footclient"
     20 keys_backend = []
     21 
     22 
     23 # Keys to change VT
     24 keys_backend.extend(
     25     [
     26         ([mod], "F1", lazy.core.change_vt(1), "Change to VT 1"),
     27         ([mod], "F2", lazy.core.change_vt(2), "Change to VT 2"),
     28         ([mod], "F3", lazy.core.change_vt(3), "Change to VT 3"),
     29         ([mod], "F4", lazy.core.change_vt(4), "Change to VT 4"),
     30     ]
     31 )
     32 
     33 # Inputs configuration
     34 wl_input_rules = {
     35     "type:keyboard": InputConfig(
     36         kb_options="caps:swapescape,altwin:swap_alt_win",
     37         kb_layout="gb",
     38         kb_repeat_rate=50,
     39         kb_repeat_delay=250,
     40     ),
     41     # All touchpads
     42     "type:touchpad": InputConfig(drag=True, tap=True, dwt=False, pointer_accel=0.3),
     43     # Roccat Kiro mouse
     44     "7805:11320:ROCCAT ROCCAT Kiro Mouse": InputConfig(
     45         #left_handed=True,
     46         pointer_accel=-1.0,
     47     ),
     48     # Anker mouse
     49     "7119:5:USB Optical Mouse": InputConfig(pointer_accel=-1.0),
     50 }
     51 
     52 
     53 # Shadows configuration
     54 # wl_shadows = {
     55 #    "radius": 12,
     56 #    "color": "#05001088",
     57 #    "offset": (-6, -6),
     58 # }
     59 wl_shadows = {
     60     "radius": 5,
     61     "color": "#ff000044",
     62     "offset": (0, 0),
     63 }
     64 
     65 
     66 @hook.subscribe.client_new
     67 def _(win):
     68     # Auto-float some windows
     69     if isinstance(win, XdgWindow):
     70         max_width = win.surface.toplevel._ptr.current.max_width
     71         if 0 < max_width < 1920:
     72             win.floating = True
     73     elif isinstance(win, XWindow):
     74         if hints := win.surface.size_hints:
     75             max_width = hints.max_width
     76             if 0 < max_width < 1920:
     77                 win.floating = True
     78 
     79 
     80 @hook.subscribe.client_managed
     81 async def _(win):
     82     # Some other miscellaneous rules
     83     if win.name == "Firefox — Sharing Indicator":
     84         win.place(win.x + win.borderwidth, 0, win.width, win.height, 0, None)
     85         return
     86 
     87     wm_class = win.get_wm_class() or []
     88     if win.name == "Navigator" and "libreoffice-startcenter" in wm_class:
     89         x = qtile.current_screen.x
     90         win.place(x, 240, 450, 600, win.borderwidth, win.bordercolor)
     91         return
     92 
     93     if "mpv" in wm_class:
     94         # Resizing mpv if it's sized itself too big to fit on screen
     95         sw = qtile.current_screen.width
     96         sh = qtile.current_screen.height
     97         x = y = w = h = None
     98         if win.height > sh:
     99             h = sh
    100             y = qtile.current_screen.y
    101         if win.width > sw:
    102             w = sw
    103             x = qtile.current_screen.x
    104         if w is not None or h is not None:
    105             if h is None:
    106                 h = win.height
    107                 y = win.y
    108             else:
    109                 w = win.width
    110                 x = win.x
    111             bw = win.borderwidth
    112             win.place(x - bw, y - bw, w + 2 * bw, h + 2 * bw, 0, None)
    113         return
    114 
    115 
    116 @hook.subscribe.startup_once
    117 async def _():
    118     # Run a startup script
    119     HOME = os.path.expanduser("~")
    120     p = subprocess.Popen(f"{HOME}/.config/qtile/startup.sh")
    121     hook.subscribe.shutdown(p.terminate)
    122 
    123 
    124 ## I don't use this monitor, but keep this around for testing
    125 #
    126 #@hook.subscribe.screen_change
    127 #def _(*_):
    128 #    # Temporary hacky fix for the dell monitor on my desk which for some mysterious
    129 #    # reason doesn't advertise that it supports any HD mode. Qtile does support setting
    130 #    # custom modes via the protocol, but neither kanshi nor wdisplays do. So instead,
    131 #    # I'll detect if that monitor is present and set the desired custom mode here.
    132 #    for output in qtile.core.outputs:
    133 #        wlr_output = output.wlr_output
    134 #        # Not only does this monitor not report modes correctly, it ALSO doesn't report
    135 #        # a make or model.
    136 #        if wlr_output.make == wlr_output.model == "<Unknown>":
    137 #            if wlr_output.current_mode.width == 1024:
    138 #                break
    139 #    else:
    140 #        return
    141 #
    142 #    wlr_output.set_custom_mode(1920, 1080, 0)
    143 #    # Lastly, while reconfigure_screens will be fired right after this hook, as it
    144 #    # gets subscribed to this hook right after the config is loaded, the backend doesn't
    145 #    # get a chance to actually apply the mode, so let's flush it.
    146 #    qtile.core.flush()
    147 
    148 
    149 ## UNNECESSARY? The backend should update the output with reconfigre_screens=True
    150 #
    151 #if IS_XEPHYR:
    152 #    # To adapt to whatever window size it was given
    153 #    @hook.subscribe.startup_once
    154 #    async def _():
    155 #        await asyncio.sleep(0.5)
    156 #        qtile.reconfigure_screens()
    157