Qtile - ArchWiki

Jump to content
From ArchWiki

Related articles

- Comparison of tiling window managers
- Window manager

From the project's website:

  Qtile is a full-featured, hackable tiling window manager written in Python. Qtile is simple, small, and extensible. It is easy to write your own layouts, widgets, and built-in commands. It is written and configured entirely in Python, which means you can leverage the full power and flexibility of the language to make it fit your needs.

## Installation

Install one of the following packages:

- qtile for the latest official release.
- qtile-gitAUR for the development version.

In order to run Qtile as a Wayland compositor you will need to install python-pywlroots.

## Starting

### Xorg

To run Qtile as an X11 window manager, run `qtile start` with xinit.

### Wayland

Start Qtile as a Wayland compositor by running `qtile start -b wayland`.

For the status of the Wayland development progress of Qtile, see https://github.com/qtile/qtile/discussions/2409.

## Configuration

Note: This chapter only explains the basics of the configuration of Qtile. For more complete information, look at the official documentation or the alternate documentation.

As described in Configuration Lookup (or in the alternate documentation), Qtile provides a default configuration file that will be used in absence of user-defined ones.

The default configuration includes the shortcut `Super+Enter` to open a new terminal (selected from a hardcoded list), and `Super+Ctrl+q` to quit Qtile.

In order to start customizing Qtile, copy it to `~/.config/qtile/config.py`:

    $ mkdir -p ~/.config/qtile/
    $ cp /usr/share/doc/qtile_dir/default_config.py ~/.config/qtile/config.py

Where `qtile_dir` is the name of the package you installed.

Alternatively, the most recent default configuration file can be downloaded from the git repository at libqtile/resources/default_config.py.

Several more complete configuration file examples can be found in the qtile-examples repository.

The configuration is fully done in Python: for a very quick introduction to the language you can read this tutorial.

Before restarting Qtile you can test your configuration file for syntax errors using the command:

    $ python -m py_compile ~/.config/qtile/config.py

If the command gives no output, your script is correct.

### Groups

In Qtile, the workspaces (or views) are called Groups. They can be defined as following:

    from libqtile.config import Group, Match
    ...
    groups = [
        Group("term"),
        Group("irc"),
        Group("web", matches=[Match(title=["Firefox"])]),
       ]
    ...

### Group Rules

The following example shows how you can automatically move applications to workspaces based on properties such as title and wm_class. You might want to use xprop if you are running on X to get these.

    from libqtile.config import Group, Match
    ...
    def is_text_editor(window):
        result = "neovim" in (window.name or "").lower()
        return result

    def is_terminal(window):
        result = "kitty" in (window.name or "").lower() and not is_text_editor(window)
        return result
    ...
    groups = [
        Group(name=str(idx), **group)
        for idx, group in enumerate(
            [
                {
                    "label": "term",
                    # restrict layouts since tiling is handled by kitty
                    "layouts": [layout.Max()],
                    "matches": [
                        Match(func=is_terminal),
                    ],
                },
                {
                    "label": "browser",
                    "matches": [
                        Match(role="browser"),
                    ],
                },
                {
                    "label": "music",
                    "matches": [
                        Match(title="YouTube Music"),
                    ],
                },
                {"label": "text editor", "matches": [Match(func=is_text_editor)]},
                {"label": "other"},
            ],
            start=1,
        )
    ]
    ...

### Keys

You can configure your shortcuts with the Key class. Here is an example of the shortcut `Alt+Shift+q` to quit the window manager.

    from libqtile.config import Key
    from libqtile.command import lazy
    ...
    keys = [
        Key(
            ["mod1", "shift"], "q",
            lazy.shutdown())
       ]
    ...

You can find out which `modX` corresponds to which key with the command Xmodmap.

#### Sound

You can add shortcuts to easily control the sound volume and state by adding a user to the audio group and using the `alsamixer` command-line interface, which can be installed through the alsa-utils package.

    keys= [
        ...
        # Sound
        Key([], "XF86AudioMute", lazy.spawn("amixer -q set Master toggle")),
        Key([], "XF86AudioLowerVolume", lazy.spawn("amixer -c 0 sset Master 1- unmute")),
        Key([], "XF86AudioRaiseVolume", lazy.spawn("amixer -c 0 sset Master 1+ unmute"))
       ]

#### Language

You can add shortcuts to easily switch between keyboard layouts in different languages using setxkbmap for example :

    keys= [
        ...
        # Language
            Key([mod], "F1",
                lazy.spawn("setxkbmap us"),
                desc= "Change to US layout"),
            Key([mod],"F2",
                lazy.spawn("setxkbmap gr"),
                desc= "Change to Greek layout"),
           ]

### Screens

Create one Screen class for every monitor you have. The bars of Qtile are configured in the Screen class as in the following example:

    from libqtile.config import Screen
    from libqtile import bar, widget
    import os.path
    ...
    screens = [
        Screen(
            wallpaper=os.path.join(os.path.expanduser("~"), "Photos/Wallpapers/arch_fill.png"),
            wallpaper_mode="fill",
            bottom=bar.Bar([          # add a bar to the bottom of the screen
                widget.GroupBox(),    # display the current Group
                widget.WindowName()   # display the name of the window that currently has focus
                ], 30))
       ]
    ...

#### Bars and widgets

You can find a list of all the built-in widgets in the official documentation (or in the alternate documentation).

If you want to add a widget to your bar, just add it like in the example above (for the `WindowName` widget). For example, if we want to add a battery notification, we can use the `Battery` widget:

    from libqtile.config import Screen
    from libqtile import bar, widget
    ...
    screens = [
        Screen(top=bar.Bar([
            widget.GroupBox(),    # display the current Group
            widget.Battery()      # display the battery state
           ], 30))
       ]
    ...

#### Using Polybar as the main bar

To use Polybar instead of the default bar, you need to delete contents of the screen class:

    from libqtile.config import Screen
    from libqtile import bar, widget
    ...
    screens = [
        Screen()
    ]
    ...

To restart Polybar with Qtile, add Polybar's launching script with `spawn` command to restart Key in #Keys class, for example:

    ...
    keys = [
        Key([mod, "control"], "r", lazy.reload_config(), lazy.spawn("~/.config/polybar/launch.sh"),
    ]
    ...

### Startup

You can start up applications using hooks, specifically the `startup` hook. For a list of available hooks see the documentation (or the alternate documentation).

Here is an example where an application starts only once:

    import os
    import subprocess
    from libqtile import hook

    @hook.subscribe.startup_once
    def autostart():
        home = os.path.expanduser('~')
        subprocess.Popen([home + '/.config/qtile/autostart.sh'])

## Debugging

Qtile writes its log into `~/.local/share/qtile/qtile.log`

### xinit

Starting Qtile on a different virtual screen can help diagnosing issues:

    $ echo "exec qtile start" > /tmp/.start_qtile; xinit /tmp/.start_qtile -- :2

### Xephyr

Qtile provides a Xephyr development script that can be easily modified to instantiate a system-installed package by replacing:

    env DISPLAY=${XDISPLAY} QTILE_XEPHYR=1 ${PYTHON} "${HERE}"/../bin/qtile start -l ${LOG_LEVEL} $@ &

with

    env DISPLAY=${XDISPLAY} QTILE_XEPHYR=1 qtile start -l ${LOG_LEVEL} $@ &

## See also

- Qtile website
- The official documentation
- An alternate source of official documentation which can be used while "docs.qtile.org" is down, as seen in issue 4295
- Qtile examples

Category:

- Tiling window managers