| # ~/.config/qtile/config.py
|
| from typing import List, Any
|
| qtile: Any
|
| from libqtile import bar, layout, widget, hook
|
| from libqtile.config import Key, Group, ScratchPad, Match, Screen, Drag, Click, DropDown
|
| from libqtile.lazy import lazy
|
| import subprocess, os
|
|
|
| @hook.subscribe.startup_once
|
| def set_wallpapers():
|
| import subprocess, os
|
|
|
| # 1. First, lock in your specific arandr monitor arrangement
|
| layout_script = os.path.expanduser("~/.config/qtile/monitor_setup.sh")
|
| if os.path.exists(layout_script):
|
| subprocess.call(["sh", layout_script])
|
|
|
| # 2. Let nitrogen seamlessly restore the independent scaled images
|
| # across your off-center screen arrangement
|
| subprocess.Popen(["nitrogen", "--restore"])
|
|
|
| # ==================== MOD KEYS ====================
|
| mod = "mod4"
|
|
|
| # ==================== APPS ====================
|
| # terminal = "xfce4-terminal"
|
| terminal = "alacritty"
|
| browser = "brave-browser-stable"
|
|
|
| # ==================== COLORS ====================
|
| colors = {
|
| "bg": "#282828",
|
| "fg": "#ebdbb2",
|
| "red": "#fb4934",
|
| "orange": "#fe8019",
|
| "yellow": "#fabd2f",
|
| "green": "#b8bb26",
|
| "aqua": "#8ec07c",
|
| "blue": "#83a598",
|
| "purple": "#d3869b",
|
| "muted": "#928374",
|
| }
|
|
|
| # ==================== KEYBINDINGS ====================
|
| keys = [
|
| Key([mod], "Return", lazy.spawn(terminal), desc="Terminal"),
|
| Key([mod], "b", lazy.spawn(browser), desc="Browser"),
|
| Key([mod], "r", lazy.spawn("rofi -show drun"), desc="Rofi"),
|
| Key([mod, "shift"], "r", lazy.spawn("rofi -show run"), desc="Rofi"),
|
|
|
| Key([mod], "h", lazy.layout.left(), desc="Focus left"),
|
| Key([mod], "l", lazy.layout.right(), desc="Focus right"),
|
| Key([mod], "j", lazy.layout.down(), desc="Focus down"),
|
| Key([mod], "k", lazy.layout.up(), desc="Focus up"),
|
|
|
| Key([mod, "control"], "h", lazy.layout.shuffle_left(), desc="Shuffle left"),
|
| Key([mod, "control"], "l", lazy.layout.shuffle_right(), desc="Shuffle right"),
|
| Key([mod, "control"], "j", lazy.layout.shuffle_down(), desc="Shuffle down"),
|
| Key([mod, "control"], "k", lazy.layout.shuffle_up(), desc="Shuffle up"),
|
|
|
| # Resize bindings for MonadTall in Qtile 0.35
|
| Key([mod, "shift"], "k", lazy.layout.grow(), desc="Grow window"),
|
| Key([mod, "shift"], "j", lazy.layout.shrink(), desc="Shrink window"),
|
| Key([mod, "shift"], "h", lazy.layout.grow_main(), desc="Grow main pane"),
|
| Key([mod, "shift"], "l", lazy.layout.shrink_main(), desc="Shrink main pane"),
|
| Key([mod], "n", lazy.layout.normalize(), desc="Reset all sizes"),
|
|
|
| Key([mod, "shift"], "q", lazy.window.kill(), desc="Kill window"),
|
| Key([mod], "f", lazy.window.toggle_fullscreen(), desc="Toggle fullscreen"),
|
| Key([mod], "space", lazy.next_layout(), desc="Next layout"),
|
|
|
| Key([mod, "control"], "r", lazy.restart(), desc="Restart Qtile"),
|
| Key([mod, "control"], "q", lazy.shutdown(), desc="Shutdown Qtile"),
|
|
|
| # Volume Control
|
| Key([], "XF86AudioRaiseVolume", lazy.spawn("pactl set-sink-volume @DEFAULT_SINK@ +3%")),
|
| Key([], "XF86AudioLowerVolume", lazy.spawn("pactl set-sink-volume @DEFAULT_SINK@ -3%")),
|
| Key([], "XF86AudioMute", lazy.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle")),
|
|
|
| # Quake alacritty
|
| Key(["mod1"], "1", lazy.group['scratch'].dropdown_toggle('quake'), desc="Toggle quake dropdown"),
|
|
|
| # Lock screen
|
| Key(["control", "mod1"], "l", lazy.spawn("sh -c 'light-locker-command -l'"), desc="Lock screen"),
|
|
|
| # Switch focus between physical monitors natively
|
| Key([mod], "o", lazy.next_screen(), desc="Move focus to next screen"),
|
| Key([mod], "i", lazy.prev_screen(), desc="Move focus to previous screen"),
|
|
|
| # Simple shift right (l) and left (h)
|
| Key([mod, "control", "shift"], "l",
|
| lazy.window.function(lambda w: w.togroup(str(int(w.group.name) + 1), switch_group=True) if int(w.group.name) < 6 else None),
|
| desc="Shift window right"),
|
| Key([mod, "control", "shift"], "h",
|
| lazy.window.function(lambda w: w.togroup(str(int(w.group.name) - 1), switch_group=True) if int(w.group.name) > 1 else None),
|
| desc="Shift window left"),
|
| ]
|
|
|
| # ==================== GROUPS ====================
|
| group_names = ["1", "2", "3", "4", "5", "6", "7", "8"]
|
| groups = [Group(i) for i in group_names]
|
|
|
| groups.append(
|
| ScratchPad("scratch", [
|
| DropDown(
|
| "quake",
|
| # "alacritty --class alacritty",
|
| "alacritty --class Alacritty",
|
| width=1,
|
| height=1,
|
| x=0,
|
| y=0,
|
| opacity=.96,
|
| on_focus_lost_hide=True,
|
| )
|
| ])
|
| )
|
|
|
|
|
| # for i, g in enumerate(groups, 1):
|
| # keys.append(Key([mod], str(i), lazy.group[g.name].toscreen()))
|
| # keys.append(Key([mod, "shift"], str(i), lazy.window.togroup(g.name, switch_group=True)))
|
| # ==================== KEYBINDINGS FOR GROUPS ====================
|
| for g in groups:
|
| # Skip the scratchpad so it doesn't break our number math
|
| if g.name == "scratch":
|
| continue
|
|
|
| keys.extend([
|
| # Mod + [1-5] = Switch to workspace
|
| Key([mod], g.name, lazy.group[g.name].toscreen(),
|
| desc=f"Switch to group {g.name}"),
|
|
|
| # Mod + Shift + [1-5] = Move window to workspace
|
| Key([mod, "shift"], g.name, lazy.window.togroup(g.name, switch_group=True),
|
| desc=f"Move window to group {g.name}"),
|
| ])
|
|
|
| # ==================== LAYOUTS ====================
|
| layouts = [
|
| layout.MonadWide(
|
| margin=8,
|
| border_focus=colors["blue"],
|
| border_normal=colors["muted"],
|
| border_width=2,
|
| ratio=0.6,
|
| ),
|
| layout.Max(),
|
| layout.Floating(),
|
| layout.MonadTall(
|
| margin=8,
|
| border_focus=colors["blue"],
|
| border_normal=colors["muted"],
|
| border_width=2,
|
| ratio=0.6,
|
| ),
|
| layout.Max(),
|
| layout.Floating(),
|
| ]
|
|
|
| floating_layout = layout.Floating(
|
| float_rules=[
|
| *layout.Floating.default_float_rules,
|
| Match(wm_type="dialog"),
|
| Match(title="Confirmation"),
|
| ]
|
| )
|
|
|
| # ==================== WIDGET DEFAULTS ====================
|
| widget_defaults = dict(
|
| font="DejaVu Sans Mono",
|
| fontsize=13,
|
| padding=6,
|
| background=colors["bg"],
|
| foreground=colors["fg"],
|
| )
|
|
|
| # ==================== SCREENS ====================
|
| screens = [
|
| # Screen 0: Primary Laptop Display
|
| Screen(
|
| top=bar.Bar(
|
| [
|
| widget.GroupBox(
|
| font="DejaVu Sans Mono Bold",
|
| fontsize=13,
|
| margin_x=4,
|
| padding_x=8,
|
| padding_y=4,
|
| active=colors["fg"],
|
| inactive=colors["muted"],
|
| highlight_method="line",
|
| this_current_screen_border=colors["yellow"],
|
| urgent_border=colors["red"],
|
| rounded=False,
|
| background=colors["bg"],
|
| ),
|
| widget.Sep(linewidth=1, padding=12, foreground=colors["muted"], background=colors["bg"]),
|
| widget.CurrentLayout(
|
| scale=0.7,
|
| padding=8,
|
| foreground=colors["fg"],
|
| background=colors["bg"],
|
| ),
|
| # widget.WindowName(
|
| # padding=10,
|
| # max_chars=60,
|
| # background=colors["bg"]
|
| # ),
|
| widget.Spacer(background=colors["bg"]),
|
| widget.CPU(
|
| format='CPU: {load_percent}%',
|
| foreground=colors["orange"],
|
| background=colors["bg"]
|
| ),
|
| widget.Memory(
|
| format='RAM: {MemUsed:.0f}M',
|
| foreground=colors["aqua"],
|
| background=colors["bg"]
|
| ),
|
| widget.Sep(linewidth=1, padding=12, foreground=colors["muted"], background=colors["bg"]),
|
| widget.Volume(
|
| format='Vol: {volume}%',
|
| foreground=colors["purple"],
|
| background=colors["bg"],
|
| padding=8,
|
| update_interval=2,
|
| unmute_format='Vol: {volume}%',
|
| mute_format='Muted',
|
| mouse_callbacks={
|
| 'Button3': lazy.spawn('pavucontrol') # right-click -> open pavucontrol
|
| }
|
| ),
|
| widget.Sep(linewidth=1, padding=12, foreground=colors["muted"], background=colors["bg"]),
|
| widget.GenPollText(
|
| func=lambda: subprocess.check_output(
|
| "echo '🔋 Bat: '$(cat /sys/class/power_supply/BAT0/capacity)'%' $(cat /sys/class/power_supply/BAT0/status | sed 's/Charging/↑/;s/Discharging/↓/;s/Full/⚡/')",
|
| shell=True, text=True
|
| ).strip(),
|
| update_interval=5,
|
| foreground=colors["green"],
|
| background=colors["bg"],
|
| padding=8,
|
| ),
|
| widget.Sep(linewidth=1, padding=12, foreground=colors["muted"], background=colors["bg"]),
|
| widget.Clock(
|
| format="%Y-%m-%d %a %I:%M %p",
|
| foreground=colors["yellow"],
|
| padding=10,
|
| background=colors["bg"]
|
| ),
|
| widget.Systray(
|
| padding=8,
|
| icon_size=18,
|
| background=colors["bg"]
|
| ),
|
| ],
|
| size=28,
|
| background=colors["bg"],
|
| margin=[0, 0, 0, 0],
|
| opacity=1.0,
|
| ),
|
| ),
|
| # Screen 1: External Monitor Display
|
| Screen(
|
| top=bar.Bar(
|
| [
|
| widget.GroupBox(
|
| font="DejaVu Sans Mono Bold",
|
| fontsize=13,
|
| margin_x=4,
|
| padding_x=8,
|
| padding_y=4,
|
| active=colors["fg"],
|
| inactive=colors["muted"],
|
| highlight_method="line",
|
| this_current_screen_border=colors["yellow"],
|
| urgent_border=colors["red"],
|
| rounded=False,
|
| background=colors["bg"],
|
| ),
|
| widget.Sep(linewidth=1, padding=12, foreground=colors["muted"], background=colors["bg"]),
|
| widget.CurrentLayout(
|
| scale=0.7,
|
| padding=8,
|
| foreground=colors["fg"],
|
| background=colors["bg"],
|
| ),
|
| # widget.WindowName(
|
| # padding=10,
|
| # max_chars=60,
|
| # background=colors["bg"]
|
| # ),
|
| widget.Spacer(background=colors["bg"]),
|
| widget.Clock(
|
| format="%Y-%m-%d %a %I:%M %p",
|
| foreground=colors["yellow"],
|
| padding=10,
|
| background=colors["bg"]
|
| ),
|
| ],
|
| size=28,
|
| background=colors["bg"],
|
| margin=[0, 0, 0, 0],
|
| opacity=1.0,
|
| ),
|
| )
|
| ]
|
|
|
| # ==================== MOUSE ====================
|
| 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()),
|
| ]
|
|
|
| # ==================== SETTINGS ====================
|
| dgroups_key_binder = None
|
| dgroups_app_rules: List = []
|
| follow_mouse_focus = True
|
| bring_front_click = False
|
| cursor_warp = True
|
| auto_fullscreen = True
|
| focus_on_window_activation = "smart"
|
| wmname = "LG3D"
|
|
|
| # ==================== AUTOSTART ====================
|
| @hook.subscribe.startup_once
|
| def autostart():
|
| script = os.path.expanduser("~/.config/qtile/autostart.sh")
|
| if os.path.exists(script):
|
| subprocess.Popen([script])
|