Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Qtile config.py
# -*- 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