Last active
August 30, 2021 15:37
-
-
Save cjbarnes18/4151805 to your computer and use it in GitHub Desktop.
Qtile config.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from subprocess import check_output, call | |
from libqtile.config import Key, Screen, Group, Drag, Click, Match | |
from libqtile.command import lazy | |
from libqtile import layout, bar, widget, hook, notify | |
#From libqtile.widget.crashme import _CrashMe | |
follow_mouse_focus = False | |
auto_fullscreen = True | |
mod = "mod4" | |
alt = "mod1" | |
ctl = "control" | |
term = "/home/craig/bin/term" | |
termcmd = "-e " | |
termtitle = "--title " | |
def term_run(cmd, title=None): | |
if title: | |
return term + " " + termtitle + "'" + title + "' " + termcmd + cmd | |
else: | |
return term + " " + termcmd + cmd | |
keys = [ | |
Key( | |
[mod], "x", | |
lazy.window.kill() | |
), | |
Key( | |
[mod], "Tab", | |
lazy.group.next_window()), | |
# this is usefull when floating windows get buried | |
Key( | |
[mod, alt], "Tab", | |
lazy.window.bring_to_front() | |
), | |
Key( | |
[mod], "grave", | |
lazy.window.to_next_screen() | |
), | |
Key( | |
[mod], "1", | |
lazy.to_screen(0), | |
), | |
Key( | |
[mod, 'shift'], "1", | |
lazy.group.toscreen(0) | |
), | |
Key( | |
[mod], "2", | |
lazy.to_screen(1), | |
), | |
Key( | |
[mod, 'shift'], "2", | |
lazy.group.toscreen(1) | |
), | |
Key( | |
[mod], "3", | |
lazy.to_screen(2), | |
), | |
Key( | |
[mod, 'shift'], "3", | |
lazy.group.toscreen(2) | |
), | |
Key( | |
[mod], "Left", | |
lazy.screen.prevgroup(True) | |
), | |
Key( | |
[mod], "Right", | |
lazy.screen.nextgroup(True) | |
), | |
Key( | |
[mod, ctl], "Left", | |
lazy.screen.prevgroup() | |
), | |
Key( | |
[mod, ctl], "Right", | |
lazy.screen.nextgroup() | |
), | |
Key( | |
[mod], "Up", | |
lazy.nextlayout() | |
), | |
Key( | |
[mod], "Down", | |
lazy.prevlayout() | |
), | |
Key( | |
[mod, alt], "Up", | |
lazy.window.up_opacity() | |
), | |
Key( | |
[mod, alt], "Down", | |
lazy.window.down_opacity() | |
), | |
# Bindings to control the layouts | |
Key( | |
[mod], "h", | |
lazy.layout.previous() | |
), | |
Key( | |
[mod], "l", | |
lazy.layout.next() | |
), | |
Key(WL_WPATable.asp | |
[mod], "j", | |
lazy.layout.up() | |
), | |
Key( | |
[mod], "k", | |
lazy.layout.down() | |
), | |
Key( | |
[mod], "v", | |
lazy.window.toggle_floating() | |
), | |
Key( | |
[mod], "F12", | |
lazy.window.toggle_fullscreen() | |
), | |
# These are unique to stack layout | |
Key( | |
[mod, "shift"], "l", | |
lazy.layout.client_to_next().when('stack') | |
), | |
Key( | |
[mod, "shift"], "h", | |
lazy.layout.client_to_previous().when('stack') | |
), | |
Key( | |
[mod, "shift"], "Return", | |
lazy.layout.toggle_split().when('stack') | |
), | |
# Multiple function keys | |
Key( | |
[mod, "shift"], "space", | |
lazy.layout.rotate().when('stack'), | |
lazy.layout.flip().when('xmonad-tall'), | |
), | |
Key( | |
[mod, "shift"], "k", | |
lazy.layout.shuffle_down().when('stack'), | |
lazy.layout.shuffle_down().when('xmonad-tall'), | |
), | |
Key( | |
[mod, "shift"], "j", | |
lazy.layout.shuffle_up().when('stack'), | |
lazy.layout.shuffle_up().when('xmonad-tall'), | |
), | |
Key( | |
[mod, ctl], "l", | |
lazy.layout.add().when('stack'), | |
lazy.layout.increase_ratio().when('tile'), | |
lazy.layout.maximize().when('xmonad-tall'), | |
), | |
Key( | |
[mod, ctl], "h", | |
lazy.layout.delete().when('stack'), | |
lazy.layout.decrease_ratio().when('tile'), | |
lazy.layout.normalize().when('xmonad-tall'), | |
), | |
Key( | |
[mod, ctl], "k", | |
lazy.layout.shrink().when('xmonad-tall'), | |
lazy.layout.decrease_nmaster().when('tile'), | |
), | |
Key( | |
[mod, ctl], "j", | |
lazy.layout.grow().when('xmonad-tall'), | |
lazy.layout.increase_nmaster().when('tile'), | |
), | |
## Launching applications | |
# Terminal Application | |
Key( | |
[mod], "Return", | |
lazy.spawn(term) | |
), | |
Key( | |
[mod], "backslash", | |
lazy.spawn(term) | |
), | |
# Qtile application launcher | |
Key( | |
[mod], "space", | |
lazy.spawncmd() | |
), | |
# Control the notify widget | |
Key( | |
[mod], "n", | |
lazy.widget['notify'].toggle() | |
), | |
Key( | |
[mod, alt], "n", | |
lazy.widget['notify'].prev() | |
), | |
Key( | |
[mod, alt], "m", | |
lazy.widget['notify'].next() | |
), | |
# Change background. | |
Key( | |
[mod], "BackSpace", | |
lazy.spawn("/home/craig/bin/wallpaperchanger2 -f /home/craig/wallpaper") | |
), | |
# Change the volume if our keyboard has keys | |
Key( | |
[], "XF86AudioRaiseVolume", | |
lazy.spawn("amixer -c 0 -q set Master 2dB+") | |
), | |
Key( | |
[], "XF86AudioLowerVolume", | |
lazy.spawn("amixer -c 0 -q set Master 2dB-") | |
), | |
Key( | |
[], "XF86AudioMute", | |
lazy.spawn("amixer -c 0 -q set Master toggle") | |
), | |
# control clementine. | |
Key( | |
[mod], "period", | |
lazy.spawn("clementine --play-pause") | |
), | |
Key( | |
[mod], "comma", | |
lazy.spawn("clementine --stop") | |
), | |
Key( | |
[mod], "F1", | |
lazy.spawn("xscreensaver-command -lock") | |
), | |
] | |
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() | |
), | |
] | |
layout_style = { | |
'border_normal': '#808080', | |
'border_focus': '#000080', | |
'margin': 2, | |
'border_width': 1, | |
} | |
# Layout instances: | |
layouts = [ | |
layout.Max(), | |
layout.Stack(stacks=2, **layout_style), | |
layout.Tile(**layout_style), | |
# layout.Matrix(**layout_style), | |
# layout.TreeTab(), | |
# layout.RatioTile(fancy=True, **layout_style), | |
layout.MonadTall(**layout_style), | |
# layout.MonadWide(**layout_style), | |
# layout.Zoomy(), | |
layout.Floating(), | |
] | |
floating_layout = layout.Floating( | |
float_rules=[ | |
{'wmclass': 'sun-awt-X11-XDialogPeer'}, # vue | |
{'wmclass': 'sun-awt-X11-XWindowPeer'}, # vue | |
{'wmclass': 'confirmreset'}, # gitk | |
{'wmclass': 'maketag'}, | |
{'wmclass': 'makebranch'}, | |
{'wmclass': 'confirm'}, | |
{'wmclass': 'error'}, | |
{'wmclass': 'ssh-askpass'}, | |
# {'wmclass': 'VCLSalFrame'}, #LibreOffice | |
{'wname': 'Sozi'}, # Inkscape | |
{'wname': 'IDLE Preferences'}, # Idle | |
{'wname': 'pinentry'}, # gpg key password entry | |
], | |
) | |
widget_defaults = dict( | |
font='Terminus', | |
fontshadow='000000', | |
margin_y=1, | |
margin_x=1, | |
padding=4, | |
margin=1, | |
) | |
screens = [ | |
Screen( | |
top=bar.Bar( | |
[ | |
widget.GroupBox(padding=0, borderwidth=2,), | |
widget.Sep(padding=0, height_percent=100), | |
widget.CurrentLayout(foreground="a0a0a0",), | |
widget.Sep(padding=0, height_percent=100,), | |
widget.Prompt(), | |
# widget.TextBox(name='note', text='', foreground='a000a0',), | |
widget.Notify(), | |
# widget.Spacer(), | |
widget.WindowName(foreground="a0a0a0"), | |
# widget.WindowTabs(foreground="a0a0a0"), | |
# widget.TaskList(), | |
widget.Sep(padding=0, height_percent=100), | |
# widget.Wlan(foreground='00a0a0'), | |
# widget.Mpd(foreground="50d050"), | |
widget.Volume(foreground="70ff70"), | |
widget.Systray(icon_size=14), | |
widget.Battery( | |
energy_now_file="charge_now", | |
energy_full_file="charge_full", | |
power_now_file="current_now", | |
update_delay=6, | |
foreground="7070ff", | |
charge_char=u'↑', | |
discharge_char=u'↓', | |
), | |
# widget.She(foreground='e0e040'), | |
# widget.ThermalSensor(foreground="ff7070",tag_sensor="Core 0"), | |
widget.CPUGraph( | |
width=20, | |
line_width=1, | |
samples=20, | |
border_color="217855", | |
border_width=1, | |
margin_x=0, | |
margin_y=2, | |
graph_color="16EBBA", | |
fill_color="16EB67.3", | |
), | |
# widget.NetGraph( | |
# width=20, | |
# line_width=1, | |
# samples=20, | |
# border_color="9955BB", | |
# border_width=1, | |
# margin_x=1, | |
# margin_y=2, | |
# graph_color="AA55CC", | |
# fill_color="9944BB.3", | |
# ), | |
widget.MemoryGraph( | |
width=20, | |
line_width=1, | |
samples=20, | |
margin_x=0, | |
margin_y=2, | |
), | |
widget.Clock(foreground="a0a0a0", fmt="%H:%M %d/%m/%Y"), | |
], | |
16, | |
background=['555555', '000000'], | |
opacity=0.7, | |
), | |
), | |
Screen(), # Bar free screen for projector use. | |
Screen(), | |
] | |
# Next, we specify group names, and use the group name list to generate an | |
# appropriate set of bindings for group switching. | |
groups = [] | |
static_groups = ['a', 's', 'd', 'f', 'g'] | |
for i in static_groups: | |
groups.append(Group(i)) | |
keys.append(Key([mod], i, lazy.screen.togglegroup(i))) | |
keys.append(Key([mod, "shift"], i, lazy.window.togroup(i))) | |
dynamic_groups = { | |
'qtile': { | |
'group': { | |
'layout': 'monadtall', | |
'matches': [Match(title=['config.py', 'Qtile log'])], | |
'exclusive': False, | |
'persist': False, | |
'init': False, | |
}, | |
'key': 'q', | |
'app_or_group': "emacsclient -a '' -c '/home/craig/.config/qtile/config.py'", | |
'app_match': Match(title=['config.py']), | |
'command': lazy.qtilecmd(), | |
}, | |
'www': { | |
'group': { | |
'layout': 'max', | |
'matches': [Match(wm_class=['Firefox', | |
'google-chrome', | |
'Google-chrome', | |
'iron', | |
'Iceweasel', | |
'Icecat', | |
'Navigator'])], | |
'exclusive': False, | |
'persist': False, | |
'init': False, | |
}, | |
'key': 'w', | |
'app_or_group': 'icecat', | |
'app_match': Match(wm_class=['Navigator']), | |
'command': lazy.spawncmd( | |
prompt='search', | |
command='icecat "https://duckduckgo.com/?q=%s"', | |
complete=None | |
), | |
}, | |
'emacs': { | |
'group': { | |
'layout': 'max', | |
'matches': [Match(wm_class=['emacs', 'Emacs'])], | |
'exclusive': False, | |
'persist': False, | |
'init': False, | |
}, | |
'key': 'e', | |
'app_or_group': "emacsclient -c -a ''", | |
'app_match': Match(title=['emacs@craig-eee', 'emacs']), | |
'command': lazy.spawncmd( | |
prompt='emacs open', | |
command="emacsclient -c -a '' '%s'", | |
complete='file' | |
), | |
}, | |
'irc': { | |
'group': { | |
'layout': 'max', | |
'matches': [Match(title=[weechat_title, 'WeeChat'])], | |
'exclusive': False, | |
'persist': False, | |
'init': False, | |
}, | |
'key': 'r', | |
'app_or_group': term_run('weechat-curses', 'WeeChat') | |
}, | |
'music': { | |
'group': { | |
'layout': 'max', | |
'matches': [Match(wm_class=['Clementine'])], | |
'exclusive': False, | |
'persist': False, | |
'init': False, | |
}, | |
'key': 't', | |
'app_or_group': 'clementine', | |
}, | |
} | |
#@hook.subscribe.addgroup | |
def goto_group(qtile, name): | |
if qtile.ready: | |
qtile.groupMap[name].cmd_toscreen() | |
@hook.subscribe.screen_change | |
def restart_on_screen_change(qtile, ev): | |
qtile.log.debug('screen change event: %s' % ev) | |
xrandr_state = check_output(['xrandr']) | |
qtile.log.debug('xrandr output:\n%s' % xrandr_state.decode("latin_1")) | |
if b'HDMI1 connected' in xrandr_state: | |
xrandr_setting = [ | |
'xrandr', | |
'--output', 'VGA1', '--off', | |
'--output', 'eDP1', '--auto', '--primary','--pos', '1024x380', | |
'--output', 'HDMI1', '--auto', '--left-of', 'eDP1', | |
'--pos', '0x0', '--rotate', 'left', | |
] | |
elif b'VGA1 connected' in xrandr_state: | |
xrandr_setting = [ | |
'xrandr', | |
'--output', 'HDMI1', '--off', | |
'--output', 'eDP1', '--auto', '--primary', '--pos 1280x124', | |
'--output', 'VGA1', '--mode', '1280x1024', '--auto', '--left-of', 'eDP1', '--pos', '0x0', | |
] | |
else: | |
xrandr_setting = [ | |
'xrandr', | |
'--output', 'VGA1', '--off', | |
'--output', 'HDMI1', '--off', | |
'--output', 'eDP1', '--auto', '--primary', | |
] | |
qtile.log.debug('applying screen change : %s' % ' '.join(xrandr_setting)) | |
call(xrandr_setting) | |
qtile.cmd_restart() | |
@hook.subscribe.startup | |
def after_start(): | |
call([ | |
'/home/craig/bin/wallpaperchanger2', | |
'-f', | |
'/home/craig/wallpaper' | |
]) | |
def app_or_group(app, group, match=None): | |
"""Go to group if it exists, or revert to last group if it is the current | |
group. Otherwise launch the application. This is for use with dynamic | |
groups configured to work with the application.""" | |
def f(qtile, match=match): | |
if group in qtile.groupMap.keys(): | |
if match: | |
running = [match.compare(w) | |
for w in qtile.groupMap[group].windows] | |
if True not in running: | |
qtile.cmd_spawn(app) | |
# qtile.groupMap[group].cmd_toscreen() | |
else: | |
qtile.currentScreen.cmd_togglegroup(group) | |
else: | |
qtile.currentScreen.cmd_togglegroup(group) | |
else: | |
qtile.cmd_spawn(app) | |
return f | |
for g in dynamic_groups: | |
k = dynamic_groups[g].get('key') | |
if k: | |
a = dynamic_groups[g].get('app_or_group') | |
l = dynamic_groups[g].get('lazy') | |
c = dynamic_groups[g].get('command') | |
if a: | |
keys.append(Key( | |
[mod], k, | |
lazy.function(app_or_group(a, g)) | |
)) | |
m = dynamic_groups[g].get('app_match') | |
if m: | |
keys.append(Key( | |
[mod, ctl], k, | |
lazy.function(app_or_group(a, g, m))) | |
) | |
elif l: | |
keys.append(Key([mod], k, l)) | |
keys.append(Key( | |
[mod, ctl], k, | |
lazy.eval("self.groupMap['%s'].cmd_toscreen()" % g) | |
)) | |
else: | |
keys.append(Key( | |
[mod], k, lazy.eval("self.groupMap['%s'].cmd_toscreen()" % g))) | |
keys.append(Key([mod, 'shift'], k, lazy.window.togroup(g))) | |
if c: | |
keys.append(Key([mod, alt], k, c)) | |
groups.append(Group(g, **dynamic_groups[g]['group'])) | |
def detect_screens(qtile): | |
""" | |
Detect if a new screen is plugged and reconfigure/restart qtile | |
""" | |
def setup_monitors(action=None, device=None): | |
if action == "change": | |
# setup monitors with xrandr | |
call("twoscreens") | |
lazy.restart() | |
#setup_monitors() | |
import pyudev | |
context = pyudev.Context() | |
monitor = pyudev.Monitor.from_netlink(context) | |
monitor.filter_by('drm') | |
monitor.enable_receiving() | |
# observe if the monitors change and reset monitors config | |
observer = pyudev.MonitorObserver(monitor, setup_monitors) | |
observer.start() | |
@hook.subscribe.client_new | |
def new_client(client): | |
if client.window.get_wm_class()[0] == "screenkey": | |
client.static(0) | |
def main(qtile): | |
qtile.ready = False | |
detect_screens(qtile) | |
# set logging level | |
qtile.cmd_warning() | |
def print_qtile(): | |
return dir(qtile) | |
qtile.cmd_print_qtile = print_qtile | |
def print_config(): | |
return [ (g.name, g.matches[0]) for g in qtile.config.groups ] | |
qtile.cmd_print_config = print_config | |
def show_stored_state(): | |
from libqtile.state import QtileState | |
return QtileState(qtile).__dict__ | |
qtile.cmd_print_state = show_stored_state | |
@hook.subscribe.startup | |
def qtile_is_ready(): | |
qtile.ready = True | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment