| Home | Configs | Guides | About |
Imports
from libqtile import bar, layout, widget, hook from libqtile.config import Click, Drag, Group, Key, Match, Screen from libqtile.lazy import lazy, LazyCommandInterface from libqtile.utils import guess_terminal import os import subprocess
Variables & Constants
| Variable | Explanation |
|---|---|
| PRIMARY_COLOR | Primary color used in QTile Panel. |
| MOD_KEYS | List of potential modifier keys mapped to their names. Used by the Mod-Key widget |
| MOD_KEY_FILE | The path to the file that houses the current modifier key |
| keys | List of keybindings. Initialized empty and added to throughout the config |
PRIMARY_COLOR = ['#323945', '#323945'] MOD_KEYS = { 'mod1': 'Alt', 'mod4': 'Super', 'shift': 'Shift', 'control': 'Control' } MOD_KEY_FILE = os.path.expanduser('~/.config/qtile/modkey') keys = []
Modifier Key
This section loads the modifier key from the MOD_KEY_FILE.
See Mod Key Management for more information.
def get_mod(): with open(MOD_KEY_FILE, 'r') as f: return f.read().strip() or 'mod4' mod = get_mod()
Groups (Workspaces)
Groups in Qtile are synonymous with workspaces (or desktops) in other operating systems. In our configuration, the groups are displayed at the top left of our screen (in the panel). Groups hold windows and allow you to switch between them easily.
In this case, we are initializing 10 group (1 - 10).
See Groups for key bindings
groups = [Group(i) for i in "1234567890"]
Layouts
Layouts control how windows are positioned on the screen. In our case, we are initializing two layouts:
- MonadTall - Position the windows in a master+stack layout vertically
- MonadWide - Position the windows in a master+stack layout horizontally
We set the border_focus (the border that surrounds active windows) to the color (#848cab - This is a hex color code). We set the width of that border to 2.
We also set the margin (The empty space surrounding windows) to 8.
See Qtile Built-In Layouts for more information.
default_layout_config = { "border_focus": "#848cab", "border_width": 2, "margin": 8 } layouts = [ #layout.Columns(border_focus_stack=["#d75f5f", "#8f3d3d"], border_width=4), #layout.Max(), # Try more layouts by unleashing below layouts. # layout.Stack(num_stacks=2), # layout.Bsp(), # layout.Matrix(), layout.MonadTall(**default_layout_config), layout.MonadWide(**default_layout_config), # layout.RatioTile(), # layout.Tile(), # layout.TreeTab(), # layout.VerticalTile(), # layout.Zoomy(), ]
Floating Layout
This adds a floating layout to the layouts. A floating layout allows you to drag, resize and place windows anywhere on the screen.
Here we have three bindings that allow us to control floating windows:
| Binding | Action |
|---|---|
| mod+left click and drag | Move window |
| mod+right click | Bring window to front |
| mod+middle click and drag | Resize window |
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()), ] floating_layout = layout.Floating( float_rules=[ # Run the utility of `xprop` to see the wm class and name of an X client. *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 key password entry ] ) layouts.append(floating_layout)
Panel
This section controls the panel at the top of our screen. Below is an explanation of the default settings and all of the widgets within the panel.
| Setting | Value | Explanation |
|---|---|---|
| font | DejaVuSansMono | The font used for text in the widgets |
| fontsize | 16 | The font size used for text in the widgets |
| background | PRIMARY_COLOR | The background color used by the widget |
| Widget | Purpose |
|---|---|
| Current Layout | Displays the current-active Qtile layout |
| Sep | A separator line |
| GroupBox | A list of groups (workspaces) |
| Sep | A separator line |
| WindowName | Shows the currently active window's name |
| TextBox (ModKey) | A TextBox widget that displays the current modifier key |
| Sep | A separator line |
| Memory | Current memory usage percent |
| CPU | Current CPU usage percent |
| Sep | A separator line |
| Spacer | Just adds some space between the sperator line and the battery widget, as the battery widget did not have any padding |
| BatteryIcon | Show an icon of the current battery level. This may not work in virtual machines |
| Battery | Shows the current battery percentage |
| Sep | A separator line |
| Clock | Shows the current date/time |
| Sep | A separator line |
| Systray | System tray. If system tray applications are installed, they will appear here. |
widget_defaults = { 'font': "DejaVuSansMono", 'fontsize': 16, 'background': PRIMARY_COLOR } screens = [ Screen( top=bar.Bar( [ widget.CurrentLayout(**widget_defaults), widget.Sep(linewidth=2), widget.GroupBox(**widget_defaults, active=["#949494", "#949494"], inactive=["#ffffff", "#ffffff"]), widget.Sep(linewidth=2), widget.WindowName(**widget_defaults, format="{name}"), widget.TextBox(**widget_defaults, text=f'{MOD_KEYS.get(mod)}'), widget.Sep(linewidth=2), widget.Memory(**widget_defaults, format='Memory: {MemPercent}%'), widget.CPU(**widget_defaults, format='CPU: {load_percent}%'), widget.Sep(linewidth=2), widget.Spacer(length=5), widget.BatteryIcon(**widget_defaults, battery="/sys/class/power_supply/BAT0", update_interval=1), widget.Battery(**widget_defaults, battery="/sys/class/power_supply/BAT0", update_interval=15, format="{percent:2.0%}"), widget.Sep(linewidth=2), widget.Clock(**widget_defaults, format="%Y-%m-%d %a %H:%M:%S"), widget.Systray(**widget_defaults), ], 32, ), ), ]
Keybindings
| Modifier | Key | Section | Purpose |
|---|---|---|---|
| mod | r | Mod Key Management | Toggle the modifier key |
| mod | Return | Terminal | Opens alacritty |
| mod | Left | Groups | Switches to previous group |
| mod | Right | Groups | Switches to next group |
| mod | <group_num> | Groups | Switches to <group_num> group |
| mod+shift | <group_num> | Groups | Moves window to and switches to <group_num> |
| mod | space | Layouts | Switch to next layout |
| mod | h | Windows | Move focus left one window |
| mod | l | Windows | Move focus right one window |
| mod | j | Windows | Move focus down one window |
| mod | k | Windows | Move focus up one window |
| mod+control | h | Windows | Switch window with window to the left |
| mod+control | l | Windows | Switch window with window to the right |
| mod+control | j | Windows | Switch window with window below |
| mod+control | k | Windows | Switch window with window above |
| mod+shift | h | Windows | Decrease current window size |
| mod+shift | l | Windows | Increase current window size |
| mod | n | Windows | Reset window size |
| mod | q | Windows | Close current window |
| mod+shift | r | QTile Reload | Reload QTile config |
| mod+shift | d | Program Shortcuts | Runs dmenu |
| mod | b | Program Shortcuts | Runs the brave browser |
Mod Key Management
This feature allows switching between modifier keys with a key binding (mod+r in this case). The current modifier key is stored in a file "~/.config/qtile/modkey". When the key is pressed, it runs "~/.scripts/toggle_qtile_mod.py". This script is shown below
The mod key is set in the Modifier Key section.
keys.extend([
Key([mod], "r", lazy.spawn(os.path.expanduser('~/.scripts/toggle_qtile_mod.py')), lazy.reload_config())
]),
toggle_qtile_mod.py:
#!/usr/bin/python3 import os MOD_KEY_FILE = os.path.expanduser('~/.config/qtile/modkey') def get_mod(): with open(MOD_KEY_FILE, 'r') as f: saved_mod = f.read().strip() if not saved_mod: saved_mod = 'mod1' return saved_mod def set_mod(newmod): with open(MOD_KEY_FILE, 'w') as f: f.write(newmod) def toggle_mod(): mod = get_mod() if mod == 'mod4': set_mod('mod1') else: set_mod('mod4') toggle_mod()
Terminal
keys.append(Key([mod], "Return", lazy.spawn('alacritty')))
Groups
keys.extend([
Key([mod], "Left", lazy.screen.prev_group()),
Key([mod], "Right", lazy.screen.next_group()),
])
for i in groups:
keys.extend(
[
Key(
[mod],
i.name,
lazy.group[i.name].toscreen(),
desc="Switch to group {}".format(i.name),
),
Key(
[mod, "shift"],
i.name,
lazy.window.togroup(i.name, switch_group=True),
desc="Switch to & move focused window to group {}".format(i.name),
),
]
)
Layouts
keys.extend([
Key([mod], "space", lazy.layout.next()),
])
Windows
keys.extend([ Key([mod], "h", lazy.layout.left(), desc="Move focus to left"), Key([mod], "l", lazy.layout.right(), desc="Move focus to right"), Key([mod], "j", lazy.layout.down(), desc="Move focus down"), Key([mod], "k", lazy.layout.up(), desc="Move focus up"), Key([mod, "control"], "h", lazy.layout.shuffle_left(), desc="Move window to the left"), Key([mod, "control"], "l", lazy.layout.shuffle_right(), desc="Move window to the right"), Key([mod, "control"], "j", lazy.layout.shuffle_down(), desc="Move window down"), Key([mod, "control"], "k", lazy.layout.shuffle_up(), desc="Move window up"), Key([mod, "shift"], "h", lazy.layout.grow_left(), lazy.layout.shrink(), lazy.layout.decrease_ratio(), lazy.layout.add(), ), Key([mod, "shift"], "l", lazy.layout.grow_right(), lazy.layout.grow(), lazy.layout.increase_ratio(), lazy.layout.delete(), ), Key([mod], "n", lazy.layout.normalize(), desc="Reset all window sizes"), Key([mod], "q", lazy.window.kill(), desc="Kill focused window"), ])
QTile Reload
keys.extend([ Key([mod, "shift"], "r", lazy.reload_config(), desc="Reload the config"), ])
Program Shortcuts
keys.extend([ Key([mod, "shift"], "d", lazy.spawn('dmenu_run')), Key([mod], "b", lazy.spawn('brave')), ])
Startup Script
This section will run a startup script after Qtile loads. This will allow us to auto-start certain programs.
@hook.subscribe.startup_once def startup(): autostart = os.path.expanduser('~/.config/qtile/autostart.sh') subprocess.run([autostart])