Exemple #1
0
    def init_rules(self):
        return [
            # Floating types
            Rule(Match(wm_type=[
                "confirm",
                "download",
                "notification",
                "toolbar",
                "splash",
                "dialog",
                "error",
                "file_progress",
                "confirmreset",
                "pinentry",
                "sshaskpass",
            ]),
                 float=True),

            # Floating classes
            Rule(Match(wm_class=[
                "Gcolor2", "Gcolor3", "balena-etcher-electron", "Virt-manager",
                "Dragon-drag-and-drop",
                re.compile("VirtualBox")
            ]),
                 float=True,
                 break_on_match=False),

            # Floating names
            Rule(Match(title=[]), float=True)
        ]
class SliceConfig(Config):
    auto_fullscreen = True
    groups = [
        libqtile.config.Group("a"),
    ]

    layouts = [
        layout.Slice(side='left',
                     width=200,
                     match=Match(title='slice'),
                     fallback=layout.Stack(num_stacks=1, border_width=0)),
        layout.Slice(side='right',
                     width=200,
                     match=Match(title='slice'),
                     fallback=layout.Stack(num_stacks=1, border_width=0)),
        layout.Slice(side='top',
                     width=200,
                     match=Match(title='slice'),
                     fallback=layout.Stack(num_stacks=1, border_width=0)),
        layout.Slice(side='bottom',
                     width=200,
                     match=Match(title='slice'),
                     fallback=layout.Stack(num_stacks=1, border_width=0)),
    ]
    floating_layout = libqtile.resources.default_config.floating_layout
    keys = []
    mouse = []
    screens = []
    follow_mouse_focus = False
Exemple #3
0
 def init_rules(self):
     return [
         # Floating names
         Rule(
             Match(title=[
                 # "mpvfloat",
                 # "Create new database",
                 "Unlock Database - KeePassXC"
                 # "Sozi"
             ]),
             float=True),
         # Floating types
         Rule(Match(wm_type=[
             "confirm", "download", "notification", "toolbar", "splash",
             "dialog", "error", "file_progress", "confirmreset",
             "makebranch", "maketag", "branchdialog", "pinentry",
             "sshaskpass"
         ]),
              float=True),
         # # Floating classes
         # Rule(
         # 	Match(wm_class = [
         # 		"Xfce4-taskmanager",
         # 		"Gparted",
         # 		"Gsmartcontrol",
         # 		"Timeshift-gtk",
         # 		"Gufw.py",
         # 		"Bleachbit",
         # 		"Nitrogen",
         # 		"Lightdm-gtk-greeter-settings",
         # 		"Nm-connection-editor",
         # 		"Lxappearance",
         # 		"Pavucontrol",
         # 		"Volumeicon",
         # 		"hp-toolbox",
         # 		"System-config-printer.py",
         # 		"Arandr",
         # 		"qt5ct",
         # 		"Catfish",
         # 		# "Nemo",
         # 		"Thunar",
         # 		"Meld",
         # 		"Engrampa",
         # 		"File-roller",
         # 		"Simple-scan",
         # 		"Mousepad",
         # 		"Gnucash",
         # 		"Gcolor3",
         # 		"vlc",
         # 		"Gnome-multi-writer",
         # 		"balena-etcher-electron",
         # 		"Virt-manager",
         # 		re.compile("VirtualBox")
         # 	]),
         # 	float = True,
         # 	break_on_match = False
         # ),
     ]
Exemple #4
0
def init_group_names():
    return [("DEV", {
        'layout': 'max',
        'matches': [Match(wm_class=['Leafpad', 'Code', 'Vim', 'Gvim'])],
    }),
            ("WWW", {
                'layout':
                'max',
                'matches':
                [Match(wm_class=['Firefox', 'Chromium', 'Opera', 'Surf'])],
            }),
            ("SYS", {
                'layout': 'monadtall',
                'matches': [Match(wm_class=['Thunar'])],
            }),
            ("DOC", {
                'layout': 'monadtall',
                'matches': [Match(wm_class=['Okular'])],
            }),
            ("VBOX", {
                'layout': 'floating',
                'matches': [Match(wm_class=['VirtualBox', 'Vmware'])],
            }),
            ("CHAT", {
                'layout': 'bsp',
                'matches': [Match(wm_class=['Discord'])],
            }),
            ("MEDIA", {
                'layout': 'monadtall',
                'matches': [Match(wm_class=['Mpv', 'Clementine', 'Nomacs'])],
            }),
            ("GFX", {
                'layout': 'floating',
                'matches': [Match(wm_class=['Gimp', 'Kdenlive'])],
            })]
Exemple #5
0
class ManagerConfig(Config):
    auto_fullscreen = True
    groups = [
        libqtile.config.Group("a"),
        libqtile.config.Group("b"),
        libqtile.config.Group("c"),
        libqtile.config.Group("d")
    ]
    layouts = [
        libqtile.layout.stack.Stack(num_stacks=1),
        libqtile.layout.stack.Stack(num_stacks=2),
        libqtile.layout.tile.Tile(ratio=0.5),
        libqtile.layout.max.Max()
    ]
    floating_layout = libqtile.layout.floating.Floating(
        float_rules=[Match(wm_class='xclock')])
    keys = [
        libqtile.config.Key(
            ["control"],
            "k",
            lazy.layout.up(),
        ),
        libqtile.config.Key(
            ["control"],
            "j",
            lazy.layout.down(),
        ),
    ]
    mouse = []
    screens = [
        libqtile.config.Screen(bottom=libqtile.bar.Bar([
            libqtile.widget.GroupBox(),
        ], 20), )
    ]
    follow_mouse_focus = True
Exemple #6
0
def toggle_or_run(_exec, match=None):
    if match is None:
        match = Match(title=[_exec])

    @lazy.function
    def __inner(qtile):

        # If the app is already focused, toggle groups
        focused = qtile.current_group.current_window
        if focused is not None:
            if match.compare(focused):
                qtile.current_screen.toggle_group()
                return

        # Else, try to focus it
        for _id, window in qtile.windows_map.items():
            if match.compare(window):
                qtile.find_window(_id)
                return

        # If we couldn't find the app, launch it
        # Might be hard to focus it
        subprocess.Popen(_exec.split())

    return __inner
Exemple #7
0
 def __init__(self, **kwargs):
     self.matches = []
     for key, value in kwargs.items():
         if value is not None:
             if isinstance(value, str):
                 value = [value]
             self.matches.append(Match(**{key: value}))
Exemple #8
0
    def restore_state(self, state, restart: bool):
        """
        Restore the state of existing dropdown windows. Used for restoring state across
        Qtile restarts (`restart` == True) or config reloads (`restart` == False).
        """
        orphans = []
        for name, wid, visible in state:
            if name in self._dropdownconfig:
                if restart:
                    self._spawned[name] = Match(wid=wid)
                    if not visible:
                        self._to_hide.append(name)
                else:
                    # We are reloading the config; manage the clients now
                    self.dropdowns[name] = DropDownToggler(
                        self.qtile.windows_map[wid],
                        self.name,
                        self._dropdownconfig[name],
                    )
                    if not visible:
                        self.dropdowns[name].hide()
            else:
                orphans.append(wid)

        if self._spawned:
            # Handle re-managed clients after restarting
            assert restart
            hook.subscribe.client_new(self.on_client_new)

        if not restart and self.dropdowns:
            # We're only reloading so don't have these hooked via self.on_client_new
            hook.subscribe.client_killed(self.on_client_killed)
            hook.subscribe.float_change(self.on_float_change)

        return orphans
Exemple #9
0
    def _setup_groups(self):
        for group in self.groups:
            self.add_dgroup(group, group.init)

            if group.spawn and not self.qtile.no_spawn:
                pid = self.qtile.cmd_spawn(group.spawn)
                self.add_rule(Rule(Match(net_wm_pid=[pid]), group.name))
Exemple #10
0
class ManagerConfig(Config):
    auto_fullscreen = True
    groups = [
        libqtile.config.Group("a"),
        libqtile.config.Group("b"),
        libqtile.config.Group("c"),
        libqtile.config.Group("d"),
    ]
    layouts = [
        libqtile.layout.stack.Stack(num_stacks=1),
        libqtile.layout.stack.Stack(num_stacks=2),
        libqtile.layout.tile.Tile(ratio=0.5),
        libqtile.layout.max.Max(),
    ]
    floating_layout = libqtile.layout.floating.Floating(
        float_rules=[
            *libqtile.layout.floating.Floating.default_float_rules,
            Match(wm_class="float"),
            Match(title="float"),
        ]
    )
    keys = [
        libqtile.config.Key(
            ["control"],
            "k",
            lazy.layout.up(),
        ),
        libqtile.config.Key(
            ["control"],
            "j",
            lazy.layout.down(),
        ),
    ]
    mouse = []
    screens = [
        libqtile.config.Screen(
            bottom=libqtile.bar.Bar(
                [
                    libqtile.widget.Prompt(),
                    libqtile.widget.GroupBox(),
                ],
                20,
            ),
        )
    ]
    follow_mouse_focus = True
    reconfigure_screens = False
Exemple #11
0
def build_rules() -> List[Rule]:
    return [
        # Floating types
        Rule(
            Match(
                wm_type=[
                    "confirm",
                    "dialog",
                    "download",
                    "notification",
                    "toolbar",
                    "splash",
                    "dialog",
                    "error",
                    "file_progress",
                    "confirmreset",
                    "makebranch",
                    "maketag",
                    "branchdialog",
                    "pinentry",
                    "sshaskpass",
                ]
            ),
            float=True,
            break_on_match=False,
        ),
        # Floating classes
        Rule(
            Match(
                wm_class=[
                    "Nitrogen",
                    "Lightdm-gtk-greeter-settings",
                    "Pavucontrol",
                    "Volumeicon",
                    "Virt-manager",
                    "Gnome-calculator",
                    "Arandr",
                    "vlc",
                    "Gucharmap",
                    re.compile("VirtualBox"),
                ]
            ),
            float=True,
            break_on_match=False,
        ),
    ]
Exemple #12
0
    def __init__(self, float_rules=None, no_reposition_rules=None, **config):
        """
        If you have certain apps that you always want to float you can provide
        ``float_rules`` to do so. ``float_rules`` are a list of
        Match objects::

            from libqtile.config import Match
            Match(title=WM_NAME, wm_class=WM_CLASS, role=WM_WINDOW_ROLE)

        When a new window is opened its ``match`` method is called with each of
        these rules.  If one matches, the window will float.  The following
        will float GIMP and Skype::

            from libqtile.config import Match
            float_rules=[Match(wm_class="skype"), Match(wm_class="gimp")]

        Specify these in the ``floating_layout`` in your config.

        Floating layout will try to center most of floating windows by default,
        but if you don't want this to happen for certain windows that are
        centered by mistake, you can use ``no_reposition_rules`` option to
        specify them and layout will rely on windows to position themselves in
        correct location on the screen.
        """
        Layout.__init__(self, **config)
        self.clients = []
        self.focused = None
        self.group = None

        if float_rules is None:
            float_rules = self.default_float_rules
        else:
            warned = False
            for index, rule in enumerate(float_rules):
                if isinstance(rule, Match):
                    continue

                if not warned:
                    message = "Non-config.Match objects in float_rules are " \
                              "deprecated"
                    warnings.warn(message, DeprecationWarning)
                    logger.warning(message)
                    warned = True

                match = Match(title=rule.get("wname"),
                              wm_class=rule.get("wmclass"),
                              role=rule.get("role"),
                              wm_type=rule.get("wm_type"),
                              wm_instance_class=rule.get("wm_instance_class"),
                              net_wm_pid=rule.get("net_wm_pid"))

                float_rules[index] = match

        self.float_rules = float_rules
        self.no_reposition_rules = no_reposition_rules or []
        self.add_defaults(Floating.defaults)
Exemple #13
0
def get_group_names():
    groups = []
    groups.append(( "DEV", { 'layout': 'monadtall',})) # 'layouts': ['monadtall'] }))
    groups.append(( "WWW", { 'layout': 'max', 'matches': [Match(wm_class=["firefox"])], }))
    groups.append(( "SYS", {'layout': 'monadtall'}))
    groups.append(("DOC", {'layout': 'monadtall'}))
    groups.append(("VBOX", {'layout': 'floating'}))
    groups.append(("CHAT", {'layout': 'bsp'}))
    groups.append(("MEDIA", {'layout': 'monadtall'}))
    groups.append(("GFX", {'layout': 'floating'}))
    return groups
Exemple #14
0
def init_rules():
    return [
        # Floating types
        Rule(Match(wm_type=[
            "confirm", "download", "notification", "toolbar", "splash",
            "dialog", "error", "file_progress", "confirmreset", "makebranch",
            "maketag", "branchdialog", "pinentry", "sshaskpass"
        ]),
             float=True),

        # Floating classes
        Rule(Match(wm_class=[
            "Xfce4-taskmanager", "Gparted", "Nitrogen",
            "Lightdm-gtk-greeter-settings", "Nm-connection-editor",
            "Lxappearance", "Pavucontrol", "Arandr", "qt5ct", "Thunar",
            "Engrampa", "File-roller", "Simple-scan",
            re.compile("VirtualBox")
        ]),
             float=True,
             break_on_match=False)
    ]
Exemple #15
0
    def _setup_groups(self):
        for group in self.groups:
            self.add_dgroup(group, group.init)

            if group.spawn and not self.qtile.no_spawn:
                if isinstance(group.spawn, str):
                    spawns = [group.spawn]
                else:
                    spawns = group.spawn
                for spawn in spawns:
                    pid = self.qtile.cmd_spawn(spawn)
                    self.add_rule(Rule(Match(net_wm_pid=[pid]), group.name))
Exemple #16
0
    def init_groups(self) -> list[Group]:
        """Inits and returns the groups."""

        self.groups = [
            Group(
                f"{group['num']}",
                layout=group["layout"],
                label=group["icon"],
                matches=[Match(wm_class=[m]) for m in group["matches"]],
            ) for group in self.groups_settings.groups.values()
        ]

        return self.groups
Exemple #17
0
def run_or_kill(_exec, match=None):
    if match is None:
        match = Match(title=[_exec])

    def __inner(qtile):
        print('00')
        # Trying to kill it
        for _id, window in qtile.windows_map.items():
            if match.compare(window):
                window.kill()
                return

        # Trying to launch it
        subprocess.Popen(_exec.split())
Exemple #18
0
    def _spawn(self, ddconfig):
        """
        Spawn a process by defined command.
        Method is only called if no window is associated. This is either on the
        first call to show or if the window was killed.
        The process id of spawned process is saved and compared to new windows.
        In case of a match the window gets associated to this DropDown object.
        """
        name = ddconfig.name
        if name not in self._spawned:
            if not self._spawned:
                hook.subscribe.client_new(self.on_client_new)

            pid = self.qtile.cmd_spawn(ddconfig.command)
            self._spawned[name] = ddconfig.match or Match(net_wm_pid=pid)
Exemple #19
0
def init_groups() -> List[Group]:
    groups = [
        Group(name="1",
              label="",
              matches=[
                  Match(wm_class=[TERM])
              ]
              ),
        Group(
            name="2",
            label="",
            matches=[
                Match(wm_class=["firefox"]),
                Match(wm_class=["qutebrowser"])
            ],
        ),
        Group(name="3",
              label="",
              matches=[Match(wm_class=["spotify", "Spotify"])]),
        Group(name="4", label=""),
        Group(name="5", label="", matches=[Match(wm_class=["discord"])]),
        Group(name="6", label=""),
    ]
    return groups
Exemple #20
0
def get_floating_layout():
    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

        # Match(wm_class='pavucontrol'),
        # Match(wm_class='pamac-manager'),
        Match(wm_class='Conky'),
        Match(wm_class='pentablet'),
    ], **layout_theme)
    return floating_layout
Exemple #21
0
def _floating_layout():
    return 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
    ])
Exemple #22
0
def init_groups():
    def _inner(key, name, match):
        keys.append(Key("M-" + key, lazy.group[name].toscreen()))
        keys.append(Key("M-S-" + key, lazy.window.togroup(name)))
        return Group(name, matches=match)

    #groups = [("1", "1")]
    #groups = [(str(i), "0" + str(i)) for i in range(1, 10)]
    groups = [("1", "", [Match(wm_class=['LilyTerm'])]),
              ("2", "", [Match(wm_class=['Nightly'])]),
              ("3", "", [Match(wm_class=['Emacs'])]),
              ("4", "", [Match(wm_class=['jetbrains-idea'])]),
              ("5", "", [Match(wm_class=['Thunderbird', 'Wine', 'qq.exe'])]),
              ("6", "", [Match(wm_class=['Steam'])]),
              ("7", "",
               [Match(wm_class=['VirtualBox', 'rdesktop', 'TeamViewer'])]),
              ("8", "", [Match(wm_class=['qutebrowser'])])]
    #groups += [("0", "10"), ("minus", "11"), ("equal", "12")]
    return [_inner(*i) for i in groups]
Exemple #23
0
    def cmd_add_rule(self, match_args, rule_args, min_priorty=False):
        """Add a dgroup rule, returns rule_id needed to remove it

        Parameters
        ==========
        match_args :
            config.Match arguments
        rule_args :
            config.Rule arguments
        min_priorty :
            If the rule is added with minimum priority (last) (default: False)
        """
        if not self.dgroups:
            logger.warning('No dgroups created')
            return

        match = Match(**match_args)
        rule = Rule([match], **rule_args)
        return self.dgroups.add_rule(rule, min_priorty)
Exemple #24
0
 def floating_layout(self):
     return 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
         ],
         border_focus=self.cm.active_border.get_hex_l(),
         border_normal=self.cm.inactive_border.get_hex_l(),
     )
Exemple #25
0
         lazy.window.set_size_floating(),
         start=lazy.window.get_size()),
    Click([mod], "Button2", lazy.window.bring_to_front())
]

dgroups_app_rules = []  # type: List
follow_mouse_focus = True
bring_front_click = False
cursor_warp = False

floating_layout = layout.Floating(float_rules=[
    # Run the utility of `xprop` to see the wm class and name of an X client.
    # default_float_rules include: utility, notification, toolbar, splash, dialog,
    # file_progress, confirm, download and error.
    *layout.Floating.default_float_rules,
    Match(title='Confirmation'),  # tastyworks exit box
    Match(title='Qalculate!'),  # qalculate-gtk
    Match(wm_class='kdenlive'),  # kdenlive
    Match(wm_class='pinentry-gtk-2'),  # GPG key password entry
])
auto_fullscreen = True
focus_on_window_activation = "smart"
reconfigure_screens = True

# If things like steam games want to auto-minimize themselves when losing
# focus, should we respect this or not?
auto_minimize = True


@hook.subscribe.startup_once
def start_once():
Exemple #26
0
    # Toggle between different layouts as defined below9
    Key([mod], "space", lazy.next_layout()),
    Key([mod], "q", lazy.window.function(smart_kill)),

    # Toggle different keyboard layouts
    Key([mod], "Caps_Lock", lazy.widget['keyboardlayout'].next_keyboard()),
    Key([mod, "mod4"], "r", lazy.restart()),
    Key([mod, "mod4"], "q", lazy.shutdown()),
    Key([mod, "mod4"], "p", lazy.spawn("maim")),
    Key([mod], "r", lazy.spawncmd()),
]
groups = [
    Group("a",
          layouts=[layout.Max(),
                   layout.MonadTall(border_width=1, ratio=0.65)],
          matches=[Match(wm_instance_class=["chromium"])]),
    Group("s",
          layouts=[layout.MonadTall(border_width=1, ratio=0.65),
                   layout.Max()],
          matches=[
              Match(wm_class=[
                  "jetbrains-pycharm-ce", "jetbrains-idea-ce", "dota2"
              ])
          ]),
    Group("d",
          layouts=[
              layout.MonadTall(border_width=1, ratio=0.5),
              layout.Matrix(border_focus='#ff0000')
          ],
          matches=[Match(wm_class=["Skype", "Steam", "discord"])]),
    Group("f",
Exemple #27
0
    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 = []  # type: List
follow_mouse_focus = True
bring_front_click = False
cursor_warp = False
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
])
auto_fullscreen = True
focus_on_window_activation = "smart"
reconfigure_screens = True

# If things like steam games want to auto-minimize themselves when losing
# focus, should we respect this or not?
auto_minimize = True

# XXX: Gasp! We're lying here. In fact, nobody really uses or cares about this
Exemple #28
0
         start=lazy.window.get_size())
]

dgroups_key_binder = None
#dgroups_app_rules = []
main = None
follow_mouse_focus = False
bring_front_click = False
cursor_warp = True
auto_fullscreen = False
focus_on_window_activation = "smart"

floating_layout = layout.Floating(
    float_rules=[
        *layout.Floating.default_float_rules,
        Match(wm_class='confirmreset'),  # gitk
        Match(wm_class='makebranch'),  # gitk
        Match(wm_class='maketag'),  # gitk
        Match(wm_class='dialog'),
        Match(wm_class='download'),
        Match(wm_class='error'),
        Match(wm_class='file_progress'),
        Match(wm_class='notification'),
        Match(wm_class='splash'),
        Match(wm_class='toolbar'),
        Match(wm_class='confirmreset'),
        Match(wm_class='makebranch'),
        Match(wm_class='maketag'),
        Match(wm_class='Gimp'),
        Match(wm_class='zoom'),
        Match(wm_class='skype'),
Exemple #29
0
                     width=0.9,
                     height=0.6),
            # Dropdown calendar using calcurse
            DropDown("calendar",
                     "alacritty -e calcurse",
                     opacity=0.99,
                     x=0.05,
                     width=0.9,
                     height=0.6)
        ]),
    Group("a", layout="monadtall"),
    Group("s", spawn="firefox", layout="max"),
    Group("d", spawn="alacritty", layout="monadtall"),
    Group("f", layout="monadwide"),
    Group("u"),
    Group("i", matches=[Match(wm_class=["Lutris"])], spawn="lutris"),
    Group("o",
          matches=[Match(wm_class=["thunderbird", "Mozilla Thunderbird"])],
          spawn="thunderbird",
          layout="max"),
    Group("p",
          matches=[Match(wm_class=["discord"])],
          spawn="discord",
          layout="max"),
]

##### LAYOUTS #####
layout_config = dict(
    margin=6,  # Gap between windows
    border_focus=def_colors["window active"],  # Focused window border color
    border_normal=def_colors[
Exemple #30
0
    "parenleft",
    "minus",
    "egrave",
    "underscore",
    "ccedilla",
    "agrave",
    "parenright",
    "equal",
]

groups = [
    Group("[1 emacs]", spawn="emacsclient -c --alternate-editor=''"),
    Group("[2 sh]", spawn="urxvt"),
    Group("[3 www]", spawn="google-chrome --profile-directory='Default'"),
    Group("[4 www]", spawn="google-chrome --profile-directory='Profile 1'"),
    Group("[5 music]", spawn="spotify", matches=[Match(title="Spotify")]),
    Group("[6 etc]"),
    Group("[7 etc]"),
]

for i, group in enumerate(groups):
    keys.extend([
        # mod1 + letter of group = switch to group
        Key(
            [mod],
            _group_keys[i],
            lazy.group[group.name].toscreen(),
            desc="Switch to group {}".format(group.name),
        ),
        # mod1 + shift + letter of group = switch to & move focused window to group
        Key(