Skip to content

Instantly share code, notes, and snippets.

@TauPan
Last active February 7, 2024 20:31
Show Gist options
  • Select an option

  • Save TauPan/9c09bd9defc5ac3c9e06 to your computer and use it in GitHub Desktop.

Select an option

Save TauPan/9c09bd9defc5ac3c9e06 to your computer and use it in GitHub Desktop.

Revisions

  1. TauPan revised this gist Feb 18, 2021. 1 changed file with 215 additions and 69 deletions.
    284 changes: 215 additions & 69 deletions config.py
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,30 @@
    # -*- coding: utf-8 -*-
    import distutils.spawn
    import os
    import re
    import socket
    import subprocess

    from libqtile.config import Key, Screen, Group, Drag, Click
    from libqtile.command import lazy
    from libqtile import layout, bar, widget, hook
    import xcffib.xproto
    from libqtile import layout, bar, widget, hook
    from libqtile.command import lazy
    from libqtile.config import Key, Screen, Group, Drag, Click


    # copied from libqtile/resources/default_config.py and adapted by me

    mod = "mod4"


    def hostname():
    return socket.gethostname()


    gemini = (hostname == 'gemini')

    laptop = os.path.exists('/sys/class/power_supply/BAT0/status')


    # thanks to rogerduran for the implementation of my idea (borrowed
    # from stumpwm)
    class PrevFocus(object):
    @@ -37,7 +51,7 @@ def on_focus(self, window):
    group_focus["current"] = window

    def __call__(self, qtile):
    group = qtile.currentGroup
    group = qtile.current_group
    group_focus = self.groups_focus.get(group.name, {"prev": None})
    prev = group_focus["prev"]
    if prev and group.name == prev.group.name:
    @@ -62,7 +76,7 @@ def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    if windows:
    window = windows[0]
    qtile.currentScreen.setGroup(window.group)
    qtile.current_screen.set_group(window.group)
    window.group.focus(window, False)
    window.focus(window, False)

    @@ -80,10 +94,10 @@ def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    if windows:
    window = windows[0]
    if window.group != qtile.currentGroup:
    if window.group != qtile.current_group:
    if window.group.screen:
    qtile.cmd_to_screen(window.group.screen.index)
    qtile.currentScreen.setGroup(window.group)
    qtile.current_screen.set_group(window.group)
    window.group.focus(window, False)

    return lazy.function(callback)
    @@ -93,8 +107,8 @@ def callback(qtile):


    def make_sticky(qtile, *args):
    window = qtile.currentWindow
    screen = qtile.currentScreen.index
    window = qtile.current_window
    screen = qtile.current_screen.index
    window.static(
    screen,
    window.x,
    @@ -104,7 +118,6 @@ def make_sticky(qtile, *args):


    def pull_window_here(**kwargs):

    """pull the matched window to the current group and focus it
    matching behaviour is the same as in switch_to
    @@ -113,8 +126,8 @@ def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    if windows:
    window = windows[0]
    window.togroup(qtile.currentGroup.name)
    qtile.currentGroup.focus(window, False)
    window.togroup(qtile.current_group.name)
    qtile.current_group.focus(window, False)

    return lazy.function(callback)

    @@ -126,16 +139,16 @@ def windows_matching_shuffle(qtile, **kwargs):
    windows = sorted(
    [
    w
    for w in qtile.windowMap.values()
    for w in qtile.windows_map.values()
    if w.group and window_match_re(w, **kwargs)],
    key=lambda ww: ww.window.wid)
    idx = 0
    if qtile.currentWindow is not None:
    if qtile.current_window is not None:
    try:
    idx = windows.index(qtile.currentWindow)
    idx = windows.index(qtile.current_window)
    idx += 1
    except ValueError:
    pass
    idx += 1
    if idx >= len(windows):
    idx = 0
    return windows[idx:] + windows[:idx]
    @@ -185,40 +198,73 @@ def modifier_window_commands(match, spawn, *keys):
    for key in keys]


    TERM_PREFS = [
    ('st', 'st.*', '-e'),
    ('gnome-terminal', 'gnome-terminal-server', '--'),
    # assuming urxvtd has been run from .xsession:
    ('urxvtc', 'URxvt', '-e'),
    # Keybindings in shell are broken because of Meta-d opening a
    # menu, etc.
    ('xfce4-terminal', 'xfce4-terminal', '-x'),
    # Seems to break the terminal for weechat permanently:
    ('alacritty', 'Alacritty', '-e')
    ]


    # See https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python/12611523#12611523 # noqa
    for term_exec, term_class, term_cmd_prefix in TERM_PREFS:
    if distutils.spawn.find_executable(term_exec):
    break

    keys = (
    modifier_window_commands(
    {'wmclass': "URxvt"},
    "urxvtc -e tmux -2 new-session -A -s {} \; set-window-option -q allow-rename on \; set-window-option -q automatic-rename on".format(
    os.environ.get('TMUX_MAIN_SESSION', '0')),
    {'wmclass': term_class},
    f"{term_exec} {term_cmd_prefix} tmux -2 new-session -A -s {os.environ.get('TMUX_MAIN_SESSION', '0')} \\; set-window-option -q allow-rename on \\; set-window-option -q automatic-rename on", # noqa
    'a', '1') # I used to use Aterm
    + modifier_window_commands(
    {'wmclass': "Emacs"},
    "em",
    'e', '2') # Emacs
    + modifier_window_commands(
    {'role': "browser"},
    "chromium --remote-debugging-port=9222",
    "google-chrome --remote-debugging-port=9222",
    'g', '3') # Galeon used to be my browser
    + modifier_window_commands(
    {"wmname": ".*pdf$", "wmclass": "(Evince|Acroread|Xpdf|Okular)"},
    "evince",
    'd') # pDf
    + modifier_window_commands(
    {"wmclass": "jetbrains-pycharm"},
    "/afs/dfn-cert.de/pet/software/pycharm/pycharm-2016.3/bin/pycharm.sh",
    "/afs/dfn-cert.de/pet/software/bin/pycharm.sh",
    "c", '4') # pyCharm
    + modifier_window_commands(
    {"wmclass": "Dolphin"},
    {"wmclass": "dolphin"},
    "dolphin",
    "p") # dolpPhin
    + modifier_window_commands(
    {'wmclass': "Thunderbird"},
    "thunderbird",
    'z') # used to be: chatZilla is started from firefox but I
    # (normally) don't use firefox for anything else
    #
    # since chatZilla is not supported any more, I use thunderbird
    # chat for IRC
    + modifier_window_commands(
    {'wmclass': "Claws-mail"},
    "claws-mail",
    'm') # claws-Mail
    + modifier_window_commands(
    {'wmclass': "keepassxc"},
    "keepassxc",
    'k') # keepassxc
    + modifier_window_commands(
    {'wmclass': "TelegramDesktop"},
    "Telegram",
    't') # Telegram
    + [
    Key(
    [mod, "control", "shift"], "Return",
    lazy.spawn("sh -c 'screen -S tmuxttyS0 -X kill ; xlock -mode blank || xscreensaver-command -lock'")),

    Key(
    [mod, "control"], "y",
    lazy.spawn("keepass2 --auto-type")),
    lazy.spawn("sh -c 'screen -S tmuxttyS0 -X kill ; (i3lock --ignore-empty-password --show-failed-attempts --tiling --image ~/Bilder/OrionWF1920x1200.png || xlock -mode blank); while pgrep \"(xlock|i3lock)\"; do sleep 2; done; tmux-on-serial'")),

    # Switch between windows in current stack pane
    Key(
    @@ -232,11 +278,13 @@ def modifier_window_commands(match, spawn, *keys):

    Key(
    [mod], "Left",
    lazy.layout.previous()
    lazy.layout.next(),
    lazy.layout.left()
    ),
    Key(
    [mod], "Right",
    lazy.layout.next()
    lazy.layout.previous(),
    lazy.layout.right()
    ),

    # Move windows in current stack pane -> I'd like to have this, but
    @@ -252,31 +300,42 @@ def modifier_window_commands(match, spawn, *keys):

    Key(
    [mod, "shift"], "Left",
    lazy.layout.client_to_previous()
    lazy.layout.client_to_previous(),
    lazy.layout.shuffle_left()
    ),
    Key(
    [mod, "shift"], "Right",
    lazy.layout.client_to_next()
    lazy.layout.client_to_next(),
    lazy.layout.shuffle_right()
    ),

    # Move windows up or down in current stack
    # resize columns
    Key(
    [mod, "control"], "k",
    lazy.layout.shuffle_down()
    [mod, "control", "shift"], "Down",
    lazy.layout.grow_down()
    ),
    Key(
    [mod, "control"], "j",
    lazy.layout.shuffle_up()
    [mod, "control", "shift"], "Up",
    lazy.layout.grow_up()
    ),

    Key(
    [mod, "control", "shift"], "Left",
    lazy.layout.grow_left()
    ),
    Key(
    [mod, "control", "shift"], "Right",
    lazy.layout.grow_right()
    ),

    # Switch window focus to other pane(s) of stack
    Key(
    [mod], "Tab",
    lazy.layout.next()
    lazy.layout.previous()
    ),
    Key(
    [mod, "shift"], "Tab",
    lazy.layout.previous()
    lazy.layout.next()
    ),

    # Swap panes of split stack
    @@ -295,37 +354,97 @@ def modifier_window_commands(match, spawn, *keys):
    ),
    Key([mod], "Return", lazy.spawn("xterm")),

    Key(
    [mod, "shift"], "plus",
    lazy.layout.add_column()
    ),
    Key(
    [mod, "shift"], "minus",
    lazy.layout.remove_column()
    ),
    Key(
    [mod], "n",
    lazy.layout.normalize
    ),

    # Toggle between different layouts as defined below
    Key([mod], "space", lazy.next_layout()),
    Key([mod, "shift"], "space", lazy.prev_layout()),

    Key([mod, "control"], "r", lazy.restart()),
    Key([mod, "control"], "q", lazy.shutdown()),
    Key([mod], "r", lazy.spawncmd()),
    Key([mod, "shift"], "r", lazy.spawncmd()),
    Key([mod], "r", lazy.spawn("rofi -show-icons -show combi")),
    Key([mod], "x", lazy.qtilecmd()),
    Key([mod], "b", lazy.hide_show_bar()),
    Key([mod, "control"], "Delete", lazy.window.kill()),
    # Key([mod], "w", lazy.window.kill()),

    Key([mod], "minus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v -||amixer sset Master 1%-'")),
    Key([mod], "plus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    Key([mod], "y",
    lazy.function(PrevFocus())),
    Key([mod, "control"], "Left", lazy.prev_screen()),
    Key([mod, "control"], "Right", lazy.next_screen()),
    Key([mod, "control"], "f", lazy.window.toggle_floating()),
    Key([mod], "f", lazy.window.toggle_fullscreen()),
    Key([mod], "comma", lazy.window.toggle_minimize()),
    Key([mod], "period", lazy.window.toggle_maximize()),
    Key([mod], "s", lazy.spawn("rofi -show-icons -show window")),
    # not focusable or managable any more, use with caution
    Key([mod, "control"], "s", lazy.function(make_sticky)),
    Key(["shift"], "Scroll_Lock",
    lazy.spawn("xmodmap ~/.Xmodmap"))
    Key([mod, "mod1"], "s",
    lazy.spawn("sudo -n pm-suspend-hybrid")),
    Key([mod, "control", "mod1"], "s",
    lazy.spawn("sudo pm-suspend")),
    Key(["mod1", "mod4"], "Scroll_Lock",
    lazy.spawn("/usr/bin/env bash -c '"
    "autorandr --change; "
    "setxkbmap -variant basic; "
    "xmodmap ~/.Xmodmap; xmodmap ~/.Xmodmap.$(hostname)"
    "'"),
    lazy.restart()),
    Key([mod], "odiaeresis", lazy.spawn("playerctl previous")),
    Key([mod], "adiaeresis", lazy.spawn("playerctl next")),
    Key([mod], "numbersign", lazy.spawn("playerctl play-pause")),
    Key(["mod1", "mod4"], 'a', lazy.next_urgent()),
    Key(["control", "mod1", "mod4"], 'a',
    lazy.cmd_simulate_keypress([mod], "a"))
    ]
    )

    if gemini:
    keys.extend([
    Key(["mod5"], "b", lazy.spawn("gemini-brightness -")),
    Key(["mod5"], "n", lazy.spawn("gemini-brightness +")),
    Key([], "XF86MonBrightnessDown", lazy.spawn("gemini-brightness -")),
    Key([], "XF86MonBrightnessUp", lazy.spawn("gemini-brightness +")),
    Key(["mod5"], "XF86MonBrightnessDown",
    lazy.spawn("gemini-brightness -")),
    Key(["mod5"], "XF86MonBrightnessUp",
    lazy.spawn("gemini-brightness +")),
    Key(["mod5"], "c",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v -||amixer sset Master 1%-'")),
    Key(["mod5"], "v",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    Key([], "XF86AudioLowerVolume",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v -||amixer sset Master 1%-'")),
    Key([], "XF86AudioRaiseVolume",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    ])
    else:
    keys.extend([
    Key([mod], "minus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v -||amixer sset Master 1%-'")),
    Key([mod], "plus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    ])


    groups = [Group(i, persist=(int(i) < 4), init=(int(i) < 4))
    for i in "12345678"]

    @@ -342,39 +461,58 @@ def modifier_window_commands(match, spawn, *keys):

    layouts = [
    layout.Max(),
    layout.Columns(name="Columns", num_columns=2, fair=True),
    layout.RatioTile(),
    layout.Stack(autosplit=True, fair=True),
    layout.Floating()
    ]

    widget_defaults = dict(
    font='Arial',
    fontsize=16,
    padding=3,
    )
    if gemini:
    widget_defaults = dict(
    font='Bitstream Vera Sans',
    fontsize=23,
    padding=1,
    )
    else:
    widget_defaults = dict(
    font='Bitstream Vera Sans',
    fontsize=16,
    padding=3,
    )


    def _barstart():
    return [
    widget.GroupBox(this_current_screen_border='0000FF'),
    widget.GroupBox(this_current_screen_border='00FF00'),
    widget.Prompt(),
    # widget.WindowName(), # either this
    widget.TaskList(max_title_width=600,
    highlight_method='block'), # or this, not both!
    # or this, not both!:
    widget.TaskList(highlight_method='block',
    # I need this for windows without icons:
    unfocused_border='#333333'),
    widget.Sep(),
    # widget.TextBox("Friedel's config", name="config"),
    ]


    def _barend():
    return [
    widget.TextBox("Vol", name="volume_label"),
    widget.Volume(),
    widget.BatteryIcon(),
    ret = [
    # widget.TextBox("Vol", name="volume_label"),
    widget.Volume(fmt=" {}", emoji=True, volume_app="pavucontrol"),
    widget.Volume(volume_app="pavucontrol"),
    # widget.PulseVolume(volume_app="pavucontrol")
    ]
    if laptop:
    ret += [
    widget.BatteryIcon(),
    widget.Battery(format='{percent:2.0%} {hour:d}:{min:02d}'),
    ]
    ret += [
    widget.CurrentLayoutIcon(),
    widget.CurrentLayout(markup=True, fontsize=20, fontshadow='0000FF'),
    widget.Sep(),
    widget.Clock(format='%Y-%m-%d %a %H:%M:%S'),
    widget.Clock(format='🕒 %Y-%m-%d %a %H:%M:%S'),
    ]

    return ret

    screens = [
    Screen(
    @@ -416,6 +554,7 @@ def _barend():
    cursor_warp = False
    floating_layout = layout.Floating()
    auto_fullscreen = True
    focus_on_window_activation = "smart" # "never" is also possible

    # XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this
    # string besides java UI toolkits; you can see several discussions on the
    @@ -430,20 +569,21 @@ def _barend():

    # see
    # http://docs.qtile.org/en/latest/manual/faq.html#my-pointer-mouse-cursor-isn-t-the-one-i-expect-it-to-be # noqa
    # see https://wiki.dfn-cert.de/cgi-bin/wiki.pl/Workstations15.1Not_WorkingYet#toc15
    @hook.subscribe.startup
    def runner():
    import subprocess
    subprocess.Popen(['xsetroot', '-cursor_name', 'left_ptr'])


    # prevent xfce4-notifyd windows from jumping around by ignoring them


    @hook.subscribe.client_new
    def auto_sticky(window):
    if window.name == "xfce4-notifyd":
    if window.group:
    screen = window.group.screen.index
    else:
    screen = window.qtile.currentScreen.index
    screen = window.qtile.current_screen.index
    window.window.configure(stackmode=xcffib.xproto.StackMode.Above)
    window.static(screen)

    @@ -460,7 +600,13 @@ def floating_dialogs(window):

    @hook.subscribe.client_new
    def float_plasma(window):
    if window:
    plasma = window_match_re(window, wmclass="plasmashell")
    if plasma:
    window.floating = True
    if window and window_match_re(window, wmclass="plasmashell"):
    window.floating = True


    # from https://github.com/ramnes/qtile-config/blob/98e097cfd8d5dd1ab1858c70babce141746d42a7/config.py#L108
    @hook.subscribe.screen_change
    def set_screens(qtile, event):
    if not os.path.exists(os.path.expanduser('~/NO-AUTORANDR')):
    subprocess.run(["autorandr", "--change"])
    qtile.cmd_restart()
  2. TauPan revised this gist Aug 24, 2017. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions config.py
    Original file line number Diff line number Diff line change
    @@ -123,9 +123,12 @@ def windows_matching_shuffle(qtile, **kwargs):
    """return a list of windows matching window_match_re with **kwargs,
    ordered so that the current Window (if it matches) comes last
    """
    windows = [w
    for w in qtile.windowMap.values()
    if w.group and window_match_re(w, **kwargs)]
    windows = sorted(
    [
    w
    for w in qtile.windowMap.values()
    if w.group and window_match_re(w, **kwargs)],
    key=lambda ww: ww.window.wid)
    idx = 0
    if qtile.currentWindow is not None:
    try:
  3. TauPan revised this gist Aug 24, 2017. 1 changed file with 29 additions and 6 deletions.
    35 changes: 29 additions & 6 deletions config.py
    Original file line number Diff line number Diff line change
    @@ -88,6 +88,7 @@ def callback(qtile):

    return lazy.function(callback)


    switch_window = window_switch_to_screen_or_pull_group


    @@ -180,28 +181,37 @@ def modifier_window_commands(match, spawn, *keys):
    for mods, command in mapping
    for key in keys]


    keys = (
    modifier_window_commands(
    {'wmclass': "URxvt"},
    "urxvtc -e tmux -2 new-session -A -s {}".format(
    "urxvtc -e tmux -2 new-session -A -s {} \; set-window-option -q allow-rename on \; set-window-option -q automatic-rename on".format(
    os.environ.get('TMUX_MAIN_SESSION', '0')),
    'a', '1')
    'a', '1') # I used to use Aterm
    + modifier_window_commands(
    {'wmclass': "Emacs"},
    "em",
    'e', '2')
    'e', '2') # Emacs
    + modifier_window_commands(
    {'role': "browser"},
    "chromium --remote-debugging-port=9222",
    'g', '3')
    'g', '3') # Galeon used to be my browser
    + modifier_window_commands(
    {"wmname": ".*pdf$", "wmclass": "(Evince|Acroread|Xpdf|Okular)"},
    "evince",
    'd')
    'd') # pDf
    + modifier_window_commands(
    {"wmclass": "jetbrains-pycharm"},
    "/afs/dfn-cert.de/pet/software/pycharm/pycharm-2016.3/bin/pycharm.sh",
    "c", '4') # pyCharm
    + modifier_window_commands(
    {"wmclass": "Dolphin"},
    "dolphin",
    "p") # dolpPhin
    + [
    Key(
    [mod, "control", "shift"], "Return",
    lazy.spawn("xscreensaver-command -lock")),
    lazy.spawn("sh -c 'screen -S tmuxttyS0 -X kill ; xlock -mode blank || xscreensaver-command -lock'")),

    Key(
    [mod, "control"], "y",
    @@ -362,6 +372,7 @@ def _barend():
    widget.Clock(format='%Y-%m-%d %a %H:%M:%S'),
    ]


    screens = [
    Screen(
    bottom=bar.Bar(
    @@ -422,6 +433,18 @@ def runner():
    subprocess.Popen(['xsetroot', '-cursor_name', 'left_ptr'])


    # prevent xfce4-notifyd windows from jumping around by ignoring them
    @hook.subscribe.client_new
    def auto_sticky(window):
    if window.name == "xfce4-notifyd":
    if window.group:
    screen = window.group.screen.index
    else:
    screen = window.qtile.currentScreen.index
    window.window.configure(stackmode=xcffib.xproto.StackMode.Above)
    window.static(screen)


    # from http://qtile.readthedocs.org/en/latest/manual/config/hooks.html#automatic-floating-dialogs
    @hook.subscribe.client_new
    def floating_dialogs(window):
  4. TauPan renamed this gist Jun 12, 2017. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  5. TauPan revised this gist Jun 12, 2017. 1 changed file with 196 additions and 171 deletions.
    367 changes: 196 additions & 171 deletions My current qtile config
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    import os
    import re

    from libqtile.config import Key, Screen, Group, Drag, Click
    @@ -63,11 +64,46 @@ def pull_window_group_here(**kwargs):
    window = windows[0]
    qtile.currentScreen.setGroup(window.group)
    window.group.focus(window, False)
    window.focus(window, False)

    return lazy.function(callback)


    def window_switch_to_screen_or_pull_group(**kwargs):
    """If the group of the window matched by match_window_re with the
    given **kwargs is in a visible on another screen, switch to the
    screen, otherwise pull the group to the current screen

    """

    def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    if windows:
    window = windows[0]
    if window.group != qtile.currentGroup:
    if window.group.screen:
    qtile.cmd_to_screen(window.group.screen.index)
    qtile.currentScreen.setGroup(window.group)
    window.group.focus(window, False)

    return lazy.function(callback)

    switch_window = window_switch_to_screen_or_pull_group


    def make_sticky(qtile, *args):
    window = qtile.currentWindow
    screen = qtile.currentScreen.index
    window.static(
    screen,
    window.x,
    window.y,
    window.width,
    window.height)


    def pull_window_here(**kwargs):

    """pull the matched window to the current group and focus it

    matching behaviour is the same as in switch_to
    @@ -129,175 +165,153 @@ def window_match_re(window, wmname=None, wmclass=None, role=None):
    return False
    return ret

    keys = [
    # Use pull_here by default (just mod)
    # Use switch_to with additional ctrl

    def modifier_window_commands(match, spawn, *keys):
    # Use switch_window by default (just mod)
    # Use pull_window_here with additional ctrl
    # spawn new window with additional shift
    Key(
    [mod], "1",
    pull_window_here(wmclass="URxvt")),
    Key(
    [mod, "control"], "1",
    pull_window_group_here(wmclass="URxvt")),
    Key(
    [mod], "a",
    pull_window_here(wmclass="URxvt")),
    Key(
    [mod, "control"], "a",
    pull_window_group_here(wmclass="URxvt")),
    Key(
    [mod, "shift"], "a",
    lazy.spawn("urxvtc -e screen -xORR -S delgado-main")),

    Key(
    [mod], "2",
    pull_window_here(wmclass="Emacs")),
    Key(
    [mod, "control"], "2",
    pull_window_group_here(wmclass="Emacs")),
    Key(
    [mod], "e",
    pull_window_here(wmclass="Emacs")),
    Key(
    [mod, "control"], "e",
    pull_window_group_here(wmclass="Emacs")),
    Key(
    [mod, "shift"], "e",
    lazy.spawn("em")),

    Key(
    [mod], "3",
    pull_window_here(role="browser")),
    Key(
    [mod, "control"], "3",
    pull_window_group_here(role="browser")),
    Key(
    [mod], "g",
    pull_window_here(role="browser")),
    Key(
    [mod, "control"], "g",
    pull_window_group_here(role="browser")),
    Key(
    [mod, "shift"], "g",
    lazy.spawn("chromium")),

    Key(
    [mod], "d",
    pull_window_here(wmname=".*pdf$", wmclass="(Evince|Acroread|Xpdf|Okular)")),
    Key(
    [mod, "control"], "d",
    pull_window_group_here(wmname=".*pdf$", wmclass="(Evince|Acroread|Xpdf|Okular)")),

    Key(
    [mod, "control", "shift"], "Return",
    lazy.spawn("xscreensaver-command -lock")),

    Key(
    [mod, "control"], "y",
    lazy.spawn("keepass2 --auto-type")),

    # Switch between windows in current stack pane
    Key(
    [mod], "Down",
    lazy.layout.down()
    ),
    Key(
    [mod], "Up",
    lazy.layout.up()
    ),

    Key(
    [mod], "Left",
    lazy.layout.previous()
    ),
    Key(
    [mod], "Right",
    lazy.layout.next()
    ),

    # Move windows in current stack pane -> I'd like to have this, but
    # move_* commands do not exist
    Key(
    [mod, "shift"], "Down",
    lazy.layout.shuffle_down()
    ),
    Key(
    [mod, "shift"], "Up",
    lazy.layout.shuffle_up()
    ),

    Key(
    [mod, "shift"], "Left",
    lazy.layout.client_to_previous()
    ),
    Key(
    [mod, "shift"], "Right",
    lazy.layout.client_to_next()
    ),

    # Move windows up or down in current stack
    Key(
    [mod, "control"], "k",
    lazy.layout.shuffle_down()
    ),
    Key(
    [mod, "control"], "j",
    lazy.layout.shuffle_up()
    ),

    # Switch window focus to other pane(s) of stack
    Key(
    [mod], "Tab",
    lazy.layout.next()
    ),
    Key(
    [mod, "shift"], "Tab",
    lazy.layout.previous()
    ),

    # Swap panes of split stack
    Key(
    [mod, "control"], "space",
    lazy.layout.rotate()
    ),

    # Toggle between split and unsplit sides of stack.
    # Split = all windows displayed
    # Unsplit = 1 window displayed, like Max layout, but still with
    # multiple stack panes
    Key(
    [mod, "shift"], "Return",
    lazy.layout.toggle_split()
    ),
    Key([mod], "Return", lazy.spawn("xterm")),

    # Toggle between different layouts as defined below
    Key([mod], "space", lazy.next_layout()),
    Key([mod, "shift"], "space", lazy.prev_layout()),
    Key([mod], "w", lazy.window.kill()),

    Key([mod, "control"], "r", lazy.restart()),
    Key([mod, "control"], "q", lazy.shutdown()),
    Key([mod], "r", lazy.spawncmd()),
    Key([mod], "x", lazy.qtilecmd()),
    Key([mod], "b", lazy.hide_show_bar()),
    Key([mod, "control"], "Delete", lazy.window.kill()),

    Key([mod], "minus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v -||amixer sset Master 1%-'")),
    Key([mod], "plus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    Key([mod], "y",
    lazy.function(PrevFocus())),
    Key([mod, "control"], "Left", lazy.prev_screen()),
    Key([mod, "control"], "Right", lazy.next_screen()),
    Key([mod, "control"], "f", lazy.window.toggle_floating()),
    Key([mod], "f", lazy.window.toggle_fullscreen()),
    Key(["shift"], "Scroll_Lock",
    lazy.spawn("xmodmap ~/.Xmodmap"))
    ]
    # Use pull_window_group_here with additional shift (mod, "shift", "control")
    mapping = (
    ([mod], switch_window(**match)),
    ([mod, "control"], pull_window_here(**match)),
    ([mod, "shift"], lazy.spawn(spawn)),
    ([mod, "shift", "control"], pull_window_group_here(**match)))
    return [Key(mods, key, command)
    for mods, command in mapping
    for key in keys]

    keys = (
    modifier_window_commands(
    {'wmclass': "URxvt"},
    "urxvtc -e tmux -2 new-session -A -s {}".format(
    os.environ.get('TMUX_MAIN_SESSION', '0')),
    'a', '1')
    + modifier_window_commands(
    {'wmclass': "Emacs"},
    "em",
    'e', '2')
    + modifier_window_commands(
    {'role': "browser"},
    "chromium --remote-debugging-port=9222",
    'g', '3')
    + modifier_window_commands(
    {"wmname": ".*pdf$", "wmclass": "(Evince|Acroread|Xpdf|Okular)"},
    "evince",
    'd')
    + [
    Key(
    [mod, "control", "shift"], "Return",
    lazy.spawn("xscreensaver-command -lock")),

    Key(
    [mod, "control"], "y",
    lazy.spawn("keepass2 --auto-type")),

    # Switch between windows in current stack pane
    Key(
    [mod], "Down",
    lazy.layout.down()
    ),
    Key(
    [mod], "Up",
    lazy.layout.up()
    ),

    Key(
    [mod], "Left",
    lazy.layout.previous()
    ),
    Key(
    [mod], "Right",
    lazy.layout.next()
    ),

    # Move windows in current stack pane -> I'd like to have this, but
    # move_* commands do not exist
    Key(
    [mod, "shift"], "Down",
    lazy.layout.shuffle_down()
    ),
    Key(
    [mod, "shift"], "Up",
    lazy.layout.shuffle_up()
    ),

    Key(
    [mod, "shift"], "Left",
    lazy.layout.client_to_previous()
    ),
    Key(
    [mod, "shift"], "Right",
    lazy.layout.client_to_next()
    ),

    # Move windows up or down in current stack
    Key(
    [mod, "control"], "k",
    lazy.layout.shuffle_down()
    ),
    Key(
    [mod, "control"], "j",
    lazy.layout.shuffle_up()
    ),

    # Switch window focus to other pane(s) of stack
    Key(
    [mod], "Tab",
    lazy.layout.next()
    ),
    Key(
    [mod, "shift"], "Tab",
    lazy.layout.previous()
    ),

    # Swap panes of split stack
    Key(
    [mod, "control"], "space",
    lazy.layout.rotate()
    ),

    # Toggle between split and unsplit sides of stack.
    # Split = all windows displayed
    # Unsplit = 1 window displayed, like Max layout, but still with
    # multiple stack panes
    Key(
    [mod, "shift"], "Return",
    lazy.layout.toggle_split()
    ),
    Key([mod], "Return", lazy.spawn("xterm")),

    # Toggle between different layouts as defined below
    Key([mod], "space", lazy.next_layout()),
    Key([mod, "shift"], "space", lazy.prev_layout()),

    Key([mod, "control"], "r", lazy.restart()),
    Key([mod, "control"], "q", lazy.shutdown()),
    Key([mod], "r", lazy.spawncmd()),
    Key([mod], "x", lazy.qtilecmd()),
    Key([mod], "b", lazy.hide_show_bar()),
    Key([mod, "control"], "Delete", lazy.window.kill()),
    # Key([mod], "w", lazy.window.kill()),

    Key([mod], "minus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v -||amixer sset Master 1%-'")),
    Key([mod], "plus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    Key([mod], "y",
    lazy.function(PrevFocus())),
    Key([mod, "control"], "Left", lazy.prev_screen()),
    Key([mod, "control"], "Right", lazy.next_screen()),
    Key([mod, "control"], "f", lazy.window.toggle_floating()),
    Key([mod], "f", lazy.window.toggle_fullscreen()),
    # not focusable or managable any more, use with caution
    Key([mod, "control"], "s", lazy.function(make_sticky)),
    Key(["shift"], "Scroll_Lock",
    lazy.spawn("xmodmap ~/.Xmodmap"))
    ]
    )

    groups = [Group(i, persist=(int(i) < 4), init=(int(i) < 4))
    for i in "12345678"]
    @@ -343,8 +357,6 @@ def _barend():
    widget.TextBox("Vol", name="volume_label"),
    widget.Volume(),
    widget.BatteryIcon(),
    widget.Systray(),
    widget.Sep(),
    widget.CurrentLayout(markup=True, fontsize=20, fontshadow='0000FF'),
    widget.Sep(),
    widget.Clock(format='%Y-%m-%d %a %H:%M:%S'),
    @@ -360,12 +372,17 @@ screens = [
    widget.MemoryGraph(),
    widget.TextBox("N", name="net_label"),
    widget.NetGraph(),
    widget.Systray(),
    widget.Sep(),
    ] + _barend(),
    30)),
    Screen(
    bottom=bar.Bar(
    _barstart() + _barend(), 30))
    _barstart()
    + [
    widget.Sep()
    ]
    + _barend(), 30))
    ]

    # Drag floating layouts.
    @@ -413,3 +430,11 @@ def floating_dialogs(window):
    bubble = window.window.get_wm_window_role() == 'bubble'
    if dialog or transient or bubble:
    window.floating = True


    @hook.subscribe.client_new
    def float_plasma(window):
    if window:
    plasma = window_match_re(window, wmclass="plasmashell")
    if plasma:
    window.floating = True
  6. TauPan renamed this gist May 11, 2016. 1 changed file with 141 additions and 44 deletions.
    185 changes: 141 additions & 44 deletions ...empt at storing previously focused window → My current qtile config
    Original file line number Diff line number Diff line change
    @@ -46,7 +46,17 @@ class PrevFocus(object):
    # taken from
    # https://github.com/qtile/qtile-examples/blob/master/roger/config.py#L34
    # and adapted
    def switch_to(**kwargs):
    def pull_window_group_here(**kwargs):
    """Switch to the *next* window matched by match_window_re with the given
    **kwargs

    If you have multiple windows matching the args, switch_to will
    cycle through them.

    (Those semantics are similar to the fvwm Next commands with
    patterns)
    """

    def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    if windows:
    @@ -57,7 +67,25 @@ def switch_to(**kwargs):
    return lazy.function(callback)


    def pull_window_here(**kwargs):
    """pull the matched window to the current group and focus it

    matching behaviour is the same as in switch_to
    """
    def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    if windows:
    window = windows[0]
    window.togroup(qtile.currentGroup.name)
    qtile.currentGroup.focus(window, False)

    return lazy.function(callback)


    def windows_matching_shuffle(qtile, **kwargs):
    """return a list of windows matching window_match_re with **kwargs,
    ordered so that the current Window (if it matches) comes last
    """
    windows = [w
    for w in qtile.windowMap.values()
    if w.group and window_match_re(w, **kwargs)]
    @@ -74,9 +102,15 @@ def windows_matching_shuffle(qtile, **kwargs):


    def window_match_re(window, wmname=None, wmclass=None, role=None):
    """
    match windows by name/title, class or role, by regular expressions

    Multiple conditions will be OR'ed together
    """

    if not (wmname or wmclass or role):
    raise TypeError(
    "Either a name, a wmclass or a role must be specified"
    "at least one of name, wmclass or role must be specified"
    )
    ret = False
    if wmname:
    @@ -96,42 +130,71 @@ def window_match_re(window, wmname=None, wmclass=None, role=None):
    return ret

    keys = [
    # Use above switch_to
    # Use pull_here by default (just mod)
    # Use switch_to with additional ctrl
    # spawn new window with additional shift
    Key(
    [mod], "1",
    switch_to(wmclass="URxvt")),
    pull_window_here(wmclass="URxvt")),
    Key(
    [mod, "control"], "1",
    pull_window_group_here(wmclass="URxvt")),
    Key(
    [mod], "a",
    switch_to(wmclass="URxvt")),
    pull_window_here(wmclass="URxvt")),
    Key(
    [mod, "control"], "a",
    pull_window_group_here(wmclass="URxvt")),
    Key(
    [mod, "shift"], "a",
    lazy.spawn("urxvtc -e screen -xORR -S delgado-main")),

    Key(
    [mod], "2",
    switch_to(wmclass="Emacs")),
    pull_window_here(wmclass="Emacs")),
    Key(
    [mod, "control"], "2",
    pull_window_group_here(wmclass="Emacs")),
    Key(
    [mod], "e",
    switch_to(wmclass="Emacs")),
    pull_window_here(wmclass="Emacs")),
    Key(
    [mod, "control"], "e",
    pull_window_group_here(wmclass="Emacs")),
    Key(
    [mod, "shift"], "e",
    lazy.spawn("em")),

    Key(
    [mod], "3",
    switch_to(role="browser")),
    pull_window_here(role="browser")),
    Key(
    [mod, "control"], "3",
    pull_window_group_here(role="browser")),
    Key(
    [mod], "g",
    switch_to(role="browser")),
    pull_window_here(role="browser")),
    Key(
    [mod, "control"], "g",
    pull_window_group_here(role="browser")),
    Key(
    [mod, "shift"], "g",
    lazy.spawn("chromium")),

    Key(
    [mod], "d",
    pull_window_here(wmname=".*pdf$", wmclass="(Evince|Acroread|Xpdf|Okular)")),
    Key(
    [mod, "control"], "d",
    pull_window_group_here(wmname=".*pdf$", wmclass="(Evince|Acroread|Xpdf|Okular)")),

    Key(
    [mod, "control", "shift"], "Return",
    lazy.spawn("xscreensaver-command -lock")),

    Key(
    [mod], "d",
    switch_to(wmname=".*pdf$", wmclass="(Evince|Acroread|Xpdf|Okular)")),
    [mod, "control"], "y",
    lazy.spawn("keepass2 --auto-type")),

    # Switch between windows in current stack pane
    Key(
    @@ -145,30 +208,31 @@ keys = [

    Key(
    [mod], "Left",
    lazy.layout.left()
    lazy.layout.previous()
    ),
    Key(
    [mod], "Right",
    lazy.layout.right()
    lazy.layout.next()
    ),

    # Move windows in current stack pane -> I'd like to have this, but move_* commands do not exist
    # Move windows in current stack pane -> I'd like to have this, but
    # move_* commands do not exist
    Key(
    [mod, "shift"], "Down",
    lazy.layout.move_down()
    lazy.layout.shuffle_down()
    ),
    Key(
    [mod, "shift"], "Up",
    lazy.layout.move_up()
    lazy.layout.shuffle_up()
    ),

    Key(
    [mod, "shift"], "Left",
    lazy.layout.move_left()
    lazy.layout.client_to_previous()
    ),
    Key(
    [mod, "shift"], "Right",
    lazy.layout.move_right()
    lazy.layout.client_to_next()
    ),

    # Move windows up or down in current stack
    @@ -193,7 +257,7 @@ keys = [

    # Swap panes of split stack
    Key(
    [mod, "shift"], "space",
    [mod, "control"], "space",
    lazy.layout.rotate()
    ),

    @@ -208,12 +272,16 @@ keys = [
    Key([mod], "Return", lazy.spawn("xterm")),

    # Toggle between different layouts as defined below
    Key([mod], "space", lazy.nextlayout()),
    Key([mod], "space", lazy.next_layout()),
    Key([mod, "shift"], "space", lazy.prev_layout()),
    Key([mod], "w", lazy.window.kill()),

    Key([mod, "control"], "r", lazy.restart()),
    Key([mod, "control"], "q", lazy.shutdown()),
    Key([mod], "r", lazy.spawncmd()),
    Key([mod], "x", lazy.qtilecmd()),
    Key([mod], "b", lazy.hide_show_bar()),
    Key([mod, "control"], "Delete", lazy.window.kill()),

    Key([mod], "minus",
    lazy.spawn(
    @@ -223,9 +291,16 @@ keys = [
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    Key([mod], "y",
    lazy.function(PrevFocus())),
    Key([mod, "control"], "Left", lazy.prev_screen()),
    Key([mod, "control"], "Right", lazy.next_screen()),
    Key([mod, "control"], "f", lazy.window.toggle_floating()),
    Key([mod], "f", lazy.window.toggle_fullscreen()),
    Key(["shift"], "Scroll_Lock",
    lazy.spawn("xmodmap ~/.Xmodmap"))
    ]

    groups = [Group(i, persist=(int(i) < 3), init=(int(i) < 3)) for i in "12345678"]
    groups = [Group(i, persist=(int(i) < 4), init=(int(i) < 4))
    for i in "12345678"]

    for i in groups:
    # mod + F+ number of group = switch to group
    @@ -240,9 +315,8 @@ for i in groups:

    layouts = [
    layout.Max(),
    layout.TreeTab(),
    layout.Stack(num_stacks=2),
    layout.Matrix(),
    layout.RatioTile(),
    layout.Stack(autosplit=True, fair=True),
    ]

    widget_defaults = dict(
    @@ -251,35 +325,47 @@ widget_defaults = dict(
    padding=3,
    )

    mybar = lambda: bar.Bar(
    [
    widget.GroupBox(),

    def _barstart():
    return [
    widget.GroupBox(this_current_screen_border='0000FF'),
    widget.Prompt(),
    # widget.WindowName(), # either this
    widget.TaskList(max_title_width=1920), # or this, not both!
    widget.CurrentLayout(),
    widget.TaskList(max_title_width=600,
    highlight_method='block'), # or this, not both!
    widget.Sep(),
    # widget.TextBox("Friedel's config", name="config"),
    widget.TextBox("C", name="cpu_label"),
    widget.CPUGraph(),
    widget.TextBox("M", name="memory_label"),
    widget.MemoryGraph(),
    widget.TextBox("N", name="net_label"),
    widget.NetGraph(),
    ]


    def _barend():
    return [
    widget.TextBox("Vol", name="volume_label"),
    widget.Volume(),
    widget.BatteryIcon(),
    widget.Systray(),
    widget.Sep(),
    widget.CurrentLayout(markup=True, fontsize=20, fontshadow='0000FF'),
    widget.Sep(),
    widget.Clock(format='%Y-%m-%d %a %H:%M:%S'),
    ],
    30,
    )
    ]

    screens = [
    Screen(
    bottom=mybar(),
    ),
    bottom=bar.Bar(
    _barstart() + [
    widget.TextBox("C", name="cpu_label"),
    widget.CPUGraph(),
    widget.TextBox("M", name="memory_label"),
    widget.MemoryGraph(),
    widget.TextBox("N", name="net_label"),
    widget.NetGraph(),
    widget.Sep(),
    ] + _barend(),
    30)),
    Screen(
    bottom=mybar(),
    ),
    bottom=bar.Bar(
    _barstart() + _barend(), 30))
    ]

    # Drag floating layouts.
    @@ -296,7 +382,7 @@ dgroups_app_rules = []
    main = None
    follow_mouse_focus = True
    bring_front_click = True
    cursor_warp = True
    cursor_warp = False
    floating_layout = layout.Floating()
    auto_fullscreen = True

    @@ -311,8 +397,19 @@ auto_fullscreen = True
    wmname = "LG3D"


    # see http://docs.qtile.org/en/latest/manual/faq.html#my-pointer-mouse-cursor-isn-t-the-one-i-expect-it-to-be
    # see
    # http://docs.qtile.org/en/latest/manual/faq.html#my-pointer-mouse-cursor-isn-t-the-one-i-expect-it-to-be # noqa
    @hook.subscribe.startup
    def runner():
    import subprocess
    subprocess.Popen(['xsetroot', '-cursor_name', 'left_ptr'])


    # from http://qtile.readthedocs.org/en/latest/manual/config/hooks.html#automatic-floating-dialogs
    @hook.subscribe.client_new
    def floating_dialogs(window):
    dialog = window.window.get_wm_type() == 'dialog'
    transient = window.window.get_wm_transient_for()
    bubble = window.window.get_wm_window_role() == 'bubble'
    if dialog or transient or bubble:
    window.floating = True
  7. TauPan revised this gist Feb 10, 2015. 1 changed file with 41 additions and 33 deletions.
    Original file line number Diff line number Diff line change
    @@ -10,36 +10,42 @@ import xcffib.xproto
    mod = "mod4"


    # store current and previous focus, for switch_to_previous
    @hook.subscribe.client_focus
    def store_focus(window):
    old_current_focus = None
    last_focus = None
    if hasattr(window.group, 'current_focus'):
    old_current_focus = window.group.current_focus
    window.group.current_focus = window
    if hasattr(window.group, 'last_focus'):
    last_focus = window.group.last_focus
    if (last_focus and
    old_current_focus and
    last_focus.window.wid == old_current_focus.window.wid):
    return
    window.group.last_focus = old_current_focus


    @lazy.function
    def switch_to_previous(qtile):
    if hasattr(qtile.currentWindow.group, 'last_focus'):
    qtile.log.info('hasattr')
    window = qtile.currentWindow.group.last_focus
    qtile.log.info('window %s', window)
    qtile.log.info('current window %s', qtile.currentWindow.group.current_focus)
    if window:
    qtile.currentScreen.setGroup(window.group)
    window.group.focus(window, False)


    # taken from https://github.com/qtile/qtile-examples/blob/master/roger/config.py#L34
    # thanks to rogerduran for the implementation of my idea (borrowed
    # from stumpwm)
    class PrevFocus(object):
    """Store last focus per group and go back when called"""

    def __init__(self):
    self.focus = None
    self.old_focus = None
    self.groups_focus = {}
    hook.subscribe.client_focus(self.on_focus)

    def on_focus(self, window):
    group = window.group
    # only store focus if the group is set
    if not group:
    return
    group_focus = self.groups_focus.setdefault(group.name, {
    "current": None, "prev": None
    })
    # don't change prev if the current focus is the same as before
    if group_focus["current"] == window:
    return
    group_focus["prev"] = group_focus["current"]
    group_focus["current"] = window

    def __call__(self, qtile):
    group = qtile.currentGroup
    group_focus = self.groups_focus.get(group.name, {"prev": None})
    prev = group_focus["prev"]
    if prev and group.name == prev.group.name:
    group.focus(prev, False)


    # taken from
    # https://github.com/qtile/qtile-examples/blob/master/roger/config.py#L34
    # and adapted
    def switch_to(**kwargs):
    def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    @@ -77,8 +83,10 @@ def window_match_re(window, wmname=None, wmclass=None, role=None):
    ret = ret or re.match(wmname, window.name)
    try:
    if wmclass:
    for v in window.window.get_wm_class():
    ret = ret or re.match(wmclass, v)
    cls = window.window.get_wm_class()
    if cls:
    for v in cls:
    ret = ret or re.match(wmclass, v)
    if role:
    rol = window.window.get_wm_window_role()
    if rol:
    @@ -214,7 +222,7 @@ keys = [
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    Key([mod], "y",
    switch_to_previous),
    lazy.function(PrevFocus())),
    ]

    groups = [Group(i, persist=(int(i) < 3), init=(int(i) < 3)) for i in "12345678"]
  8. TauPan created this gist Feb 10, 2015.
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,310 @@
    import re

    from libqtile.config import Key, Screen, Group, Drag, Click
    from libqtile.command import lazy
    from libqtile import layout, bar, widget, hook
    import xcffib.xproto

    # copied from libqtile/resources/default_config.py and adapted by me

    mod = "mod4"


    # store current and previous focus, for switch_to_previous
    @hook.subscribe.client_focus
    def store_focus(window):
    old_current_focus = None
    last_focus = None
    if hasattr(window.group, 'current_focus'):
    old_current_focus = window.group.current_focus
    window.group.current_focus = window
    if hasattr(window.group, 'last_focus'):
    last_focus = window.group.last_focus
    if (last_focus and
    old_current_focus and
    last_focus.window.wid == old_current_focus.window.wid):
    return
    window.group.last_focus = old_current_focus


    @lazy.function
    def switch_to_previous(qtile):
    if hasattr(qtile.currentWindow.group, 'last_focus'):
    qtile.log.info('hasattr')
    window = qtile.currentWindow.group.last_focus
    qtile.log.info('window %s', window)
    qtile.log.info('current window %s', qtile.currentWindow.group.current_focus)
    if window:
    qtile.currentScreen.setGroup(window.group)
    window.group.focus(window, False)


    # taken from https://github.com/qtile/qtile-examples/blob/master/roger/config.py#L34
    def switch_to(**kwargs):
    def callback(qtile):
    windows = windows_matching_shuffle(qtile, **kwargs)
    if windows:
    window = windows[0]
    qtile.currentScreen.setGroup(window.group)
    window.group.focus(window, False)

    return lazy.function(callback)


    def windows_matching_shuffle(qtile, **kwargs):
    windows = [w
    for w in qtile.windowMap.values()
    if w.group and window_match_re(w, **kwargs)]
    idx = 0
    if qtile.currentWindow is not None:
    try:
    idx = windows.index(qtile.currentWindow)
    except ValueError:
    pass
    idx += 1
    if idx >= len(windows):
    idx = 0
    return windows[idx:] + windows[:idx]


    def window_match_re(window, wmname=None, wmclass=None, role=None):
    if not (wmname or wmclass or role):
    raise TypeError(
    "Either a name, a wmclass or a role must be specified"
    )
    ret = False
    if wmname:
    ret = ret or re.match(wmname, window.name)
    try:
    if wmclass:
    for v in window.window.get_wm_class():
    ret = ret or re.match(wmclass, v)
    if role:
    rol = window.window.get_wm_window_role()
    if rol:
    ret = ret or re.match(role, rol)
    except (xcffib.xproto.WindowError, xcffib.xproto.AccessError):
    return False
    return ret

    keys = [
    # Use above switch_to
    Key(
    [mod], "1",
    switch_to(wmclass="URxvt")),
    Key(
    [mod], "a",
    switch_to(wmclass="URxvt")),
    Key(
    [mod, "shift"], "a",
    lazy.spawn("urxvtc -e screen -xORR -S delgado-main")),
    Key(
    [mod], "2",
    switch_to(wmclass="Emacs")),
    Key(
    [mod], "e",
    switch_to(wmclass="Emacs")),
    Key(
    [mod, "shift"], "e",
    lazy.spawn("em")),
    Key(
    [mod], "3",
    switch_to(role="browser")),
    Key(
    [mod], "g",
    switch_to(role="browser")),
    Key(
    [mod, "shift"], "g",
    lazy.spawn("chromium")),

    Key(
    [mod, "control", "shift"], "Return",
    lazy.spawn("xscreensaver-command -lock")),

    Key(
    [mod], "d",
    switch_to(wmname=".*pdf$", wmclass="(Evince|Acroread|Xpdf|Okular)")),

    # Switch between windows in current stack pane
    Key(
    [mod], "Down",
    lazy.layout.down()
    ),
    Key(
    [mod], "Up",
    lazy.layout.up()
    ),

    Key(
    [mod], "Left",
    lazy.layout.left()
    ),
    Key(
    [mod], "Right",
    lazy.layout.right()
    ),

    # Move windows in current stack pane -> I'd like to have this, but move_* commands do not exist
    Key(
    [mod, "shift"], "Down",
    lazy.layout.move_down()
    ),
    Key(
    [mod, "shift"], "Up",
    lazy.layout.move_up()
    ),

    Key(
    [mod, "shift"], "Left",
    lazy.layout.move_left()
    ),
    Key(
    [mod, "shift"], "Right",
    lazy.layout.move_right()
    ),

    # Move windows up or down in current stack
    Key(
    [mod, "control"], "k",
    lazy.layout.shuffle_down()
    ),
    Key(
    [mod, "control"], "j",
    lazy.layout.shuffle_up()
    ),

    # Switch window focus to other pane(s) of stack
    Key(
    [mod], "Tab",
    lazy.layout.next()
    ),
    Key(
    [mod, "shift"], "Tab",
    lazy.layout.previous()
    ),

    # Swap panes of split stack
    Key(
    [mod, "shift"], "space",
    lazy.layout.rotate()
    ),

    # Toggle between split and unsplit sides of stack.
    # Split = all windows displayed
    # Unsplit = 1 window displayed, like Max layout, but still with
    # multiple stack panes
    Key(
    [mod, "shift"], "Return",
    lazy.layout.toggle_split()
    ),
    Key([mod], "Return", lazy.spawn("xterm")),

    # Toggle between different layouts as defined below
    Key([mod], "space", lazy.nextlayout()),
    Key([mod], "w", lazy.window.kill()),

    Key([mod, "control"], "r", lazy.restart()),
    Key([mod, "control"], "q", lazy.shutdown()),
    Key([mod], "r", lazy.spawncmd()),

    Key([mod], "minus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v -||amixer sset Master 1%-'")),
    Key([mod], "plus",
    lazy.spawn(
    "/usr/bin/env bash -c 'aumix -v +||amixer sset Master 1%+'")),
    Key([mod], "y",
    switch_to_previous),
    ]

    groups = [Group(i, persist=(int(i) < 3), init=(int(i) < 3)) for i in "12345678"]

    for i in groups:
    # mod + F+ number of group = switch to group
    keys.append(
    Key([mod], "F%d" % int(i.name), lazy.group[i.name].toscreen())
    )

    # mod1 + shift + letter of group = switch to & move focused window to group
    keys.append(
    Key([mod, "shift"], "F%d" % int(i.name), lazy.window.togroup(i.name))
    )

    layouts = [
    layout.Max(),
    layout.TreeTab(),
    layout.Stack(num_stacks=2),
    layout.Matrix(),
    ]

    widget_defaults = dict(
    font='Arial',
    fontsize=16,
    padding=3,
    )

    mybar = lambda: bar.Bar(
    [
    widget.GroupBox(),
    widget.Prompt(),
    # widget.WindowName(), # either this
    widget.TaskList(max_title_width=1920), # or this, not both!
    widget.CurrentLayout(),
    widget.Sep(),
    # widget.TextBox("Friedel's config", name="config"),
    widget.TextBox("C", name="cpu_label"),
    widget.CPUGraph(),
    widget.TextBox("M", name="memory_label"),
    widget.MemoryGraph(),
    widget.TextBox("N", name="net_label"),
    widget.NetGraph(),
    widget.Volume(),
    widget.Systray(),
    widget.Clock(format='%Y-%m-%d %a %H:%M:%S'),
    ],
    30,
    )

    screens = [
    Screen(
    bottom=mybar(),
    ),
    Screen(
    bottom=mybar(),
    ),
    ]

    # Drag floating layouts.
    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())
    ]

    dgroups_key_binder = None
    dgroups_app_rules = []
    main = None
    follow_mouse_focus = True
    bring_front_click = True
    cursor_warp = True
    floating_layout = layout.Floating()
    auto_fullscreen = True

    # XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this
    # string besides java UI toolkits; you can see several discussions on the
    # mailing lists, github issues, and other WM documentation that suggest setting
    # this string if your java app doesn't work correctly. We may as well just lie
    # and say that we're a working one by default.
    #
    # We choose LG3D to maximize irony: it is a 3D non-reparenting WM written in
    # java that happens to be on java's whitelist.
    wmname = "LG3D"


    # see http://docs.qtile.org/en/latest/manual/faq.html#my-pointer-mouse-cursor-isn-t-the-one-i-expect-it-to-be
    @hook.subscribe.startup
    def runner():
    import subprocess
    subprocess.Popen(['xsetroot', '-cursor_name', 'left_ptr'])