We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Configured keyboards limited to 3
### The issue:

In my config I've defined 4 keyboard layouts, however in the widget on the bar, it never reaches the fourth layout when left-clicking. When the third layout is removed (moving the fourth into the third position) it is suddenly accessible so it's not a problem with the layout itself. I don't notice any logs that would apply to this.

```
widget.KeyboardLayout(
    font = defaults['font'],
    fontsize = defaults['fontsize'],
    configured_keyboards = ['us', 'es', 'semimak-jq', 'mtgap'],
    display_map = { #makes everything lowercase
        'us': 'us',
        'es': 'es',
        'workman': 'wm',
        'semimak': 'sm',
        'mtgap': 'mt',
    }
),
```

From my config, I defined us, es, semimak-jq, and mtgap, but I can never rotate onto mtgap unless I remove semimak-jq. When I manually set the layout with setxkbmap, it is correctly displayed as 'mt' in the widget, I just can't rotate onto it via left-click on the widget.

Qtile Version: 0.22.1, X11

### Required:

- [X] I have searched past issues to see if this bug has already been reported.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `libqtile/widget/keyboardlayout.py`
Content:
```
1 # Copyright (c) 2013 Jacob Mourelos
2 # Copyright (c) 2014 Shepilov Vladislav
3 # Copyright (c) 2014-2015 Sean Vig
4 # Copyright (c) 2014 Tycho Andersen
5 # Copyright (c) 2019 zordsdavini
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 # SOFTWARE.
24 
25 from __future__ import annotations
26 
27 import re
28 from abc import ABCMeta, abstractmethod
29 from subprocess import CalledProcessError, check_output
30 from typing import TYPE_CHECKING
31 
32 from libqtile.command.base import expose_command
33 from libqtile.confreader import ConfigError
34 from libqtile.log_utils import logger
35 from libqtile.widget import base
36 
37 if TYPE_CHECKING:
38     from libqtile.core.manager import Qtile
39 
40 
41 class _BaseLayoutBackend(metaclass=ABCMeta):
42     def __init__(self, qtile: Qtile):
43         """
44         This handles getting and setter the keyboard layout with the appropriate
45         backend.
46         """
47 
48     @abstractmethod
49     def get_keyboard(self) -> str:
50         """
51         Return the currently used keyboard layout as a string
52 
53         Examples: "us", "us dvorak".  In case of error returns "unknown".
54         """
55 
56     def set_keyboard(self, layout: str, options: str | None) -> None:
57         """
58         Set the keyboard layout with specified options.
59         """
60 
61 
62 class _X11LayoutBackend(_BaseLayoutBackend):
63     kb_layout_regex = re.compile(r"layout:\s+(?P<layout>\w+)")
64     kb_variant_regex = re.compile(r"variant:\s+(?P<variant>\w+)")
65 
66     def get_keyboard(self) -> str:
67         try:
68             command = "setxkbmap -verbose 10 -query"
69             setxkbmap_output = check_output(command.split(" ")).decode()
70         except CalledProcessError:
71             logger.exception("Can not get the keyboard layout:")
72             return "unknown"
73         except OSError:
74             logger.exception("Please, check that xset is available:")
75             return "unknown"
76 
77         match_layout = self.kb_layout_regex.search(setxkbmap_output)
78         if match_layout is None:
79             return "ERR"
80         keyboard = match_layout.group("layout")
81 
82         match_variant = self.kb_variant_regex.search(setxkbmap_output)
83         if match_variant:
84             keyboard += " " + match_variant.group("variant")
85         return keyboard
86 
87     def set_keyboard(self, layout: str, options: str | None) -> None:
88         command = ["setxkbmap"]
89         command.extend(layout.split(" "))
90         if options:
91             command.extend(["-option", options])
92         try:
93             check_output(command)
94         except CalledProcessError:
95             logger.error("Can not change the keyboard layout:")
96         except OSError:
97             logger.error("Please, check that setxkbmap is available:")
98 
99 
100 class _WaylandLayoutBackend(_BaseLayoutBackend):
101     def __init__(self, qtile: Qtile) -> None:
102         self.set_keymap = qtile.core.set_keymap
103         self._layout: str = ""
104 
105     def get_keyboard(self) -> str:
106         return self._layout
107 
108     def set_keyboard(self, layout: str, options: str | None) -> None:
109         maybe_variant: str | None = None
110         if " " in layout:
111             layout_name, maybe_variant = layout.split(" ", maxsplit=1)
112         else:
113             layout_name = layout
114         self.set_keymap(layout_name, options, maybe_variant)
115         self._layout = layout
116 
117 
118 layout_backends = {
119     "x11": _X11LayoutBackend,
120     "wayland": _WaylandLayoutBackend,
121 }
122 
123 
124 class KeyboardLayout(base.InLoopPollText):
125     """Widget for changing and displaying the current keyboard layout
126 
127     To use this widget effectively you need to specify keyboard layouts you want to use
128     (using "configured_keyboards") and bind function "next_keyboard" to specific keys in
129     order to change layouts.
130 
131     For example:
132 
133         Key([mod], "space", lazy.widget["keyboardlayout"].next_keyboard(), desc="Next keyboard layout."),
134 
135     When running Qtile with the X11 backend, this widget requires setxkbmap to be available.
136     """
137 
138     defaults = [
139         ("update_interval", 1, "Update time in seconds."),
140         (
141             "configured_keyboards",
142             ["us"],
143             "A list of predefined keyboard layouts "
144             "represented as strings. For example: "
145             "['us', 'us colemak', 'es', 'fr'].",
146         ),
147         (
148             "display_map",
149             {},
150             "Custom display of layout. Key should be in format "
151             "'layout variant'. For example: "
152             "{'us': 'us', 'lt sgs': 'sgs', 'ru phonetic': 'ru'}",
153         ),
154         ("option", None, "string of setxkbmap option. Ex., 'compose:menu,grp_led:scroll'"),
155     ]
156 
157     def __init__(self, **config):
158         base.InLoopPollText.__init__(self, **config)
159         self.add_defaults(KeyboardLayout.defaults)
160         self.add_callbacks({"Button1": self.next_keyboard})
161 
162     def _configure(self, qtile, bar):
163         base.InLoopPollText._configure(self, qtile, bar)
164 
165         if qtile.core.name not in layout_backends:
166             raise ConfigError("KeyboardLayout does not support backend: " + qtile.core.name)
167 
168         self.backend = layout_backends[qtile.core.name](qtile)
169         self.backend.set_keyboard(self.configured_keyboards[0], self.option)
170 
171     @expose_command()
172     def next_keyboard(self):
173         """set the next layout in the list of configured keyboard layouts as
174         new current layout in use
175 
176         If the current keyboard layout is not in the list, it will set as new
177         layout the first one in the list.
178         """
179 
180         current_keyboard = self.backend.get_keyboard()
181         if current_keyboard in self.configured_keyboards:
182             # iterate the list circularly
183             next_keyboard = self.configured_keyboards[
184                 (self.configured_keyboards.index(current_keyboard) + 1)
185                 % len(self.configured_keyboards)
186             ]
187         else:
188             next_keyboard = self.configured_keyboards[0]
189 
190         self.backend.set_keyboard(next_keyboard, self.option)
191 
192         self.tick()
193 
194     def poll(self):
195         keyboard = self.backend.get_keyboard()
196         if keyboard in self.display_map.keys():
197             return self.display_map[keyboard]
198         return keyboard.upper()
199
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/libqtile/widget/keyboardlayout.py b/libqtile/widget/keyboardlayout.py
--- a/libqtile/widget/keyboardlayout.py
+++ b/libqtile/widget/keyboardlayout.py
@@ -60,7 +60,7 @@
 
 
 class _X11LayoutBackend(_BaseLayoutBackend):
-    kb_layout_regex = re.compile(r"layout:\s+(?P<layout>\w+)")
+    kb_layout_regex = re.compile(r"layout:\s+(?P<layout>[\w-]+)")
     kb_variant_regex = re.compile(r"variant:\s+(?P<variant>\w+)")
 
     def get_keyboard(self) -> str:

{"golden_diff": "diff --git a/libqtile/widget/keyboardlayout.py b/libqtile/widget/keyboardlayout.py\n--- a/libqtile/widget/keyboardlayout.py\n+++ b/libqtile/widget/keyboardlayout.py\n@@ -60,7 +60,7 @@\n \n \n class _X11LayoutBackend(_BaseLayoutBackend):\n-    kb_layout_regex = re.compile(r\"layout:\\s+(?P<layout>\\w+)\")\n+    kb_layout_regex = re.compile(r\"layout:\\s+(?P<layout>[\\w-]+)\")\n     kb_variant_regex = re.compile(r\"variant:\\s+(?P<variant>\\w+)\")\n \n     def get_keyboard(self) -> str:\n", "issue": "Configured keyboards limited to 3\n### The issue:\n\nIn my config I've defined 4 keyboard layouts, however in the widget on the bar, it never reaches the fourth layout when left-clicking. When the third layout is removed (moving the fourth into the third position) it is suddenly accessible so it's not a problem with the layout itself. I don't notice any logs that would apply to this.\r\n\r\n```\r\nwidget.KeyboardLayout(\r\n    font = defaults['font'],\r\n    fontsize = defaults['fontsize'],\r\n    configured_keyboards = ['us', 'es', 'semimak-jq', 'mtgap'],\r\n    display_map = { #makes everything lowercase\r\n        'us': 'us',\r\n        'es': 'es',\r\n        'workman': 'wm',\r\n        'semimak': 'sm',\r\n        'mtgap': 'mt',\r\n    }\r\n),\r\n```\r\n\r\nFrom my config, I defined us, es, semimak-jq, and mtgap, but I can never rotate onto mtgap unless I remove semimak-jq. When I manually set the layout with setxkbmap, it is correctly displayed as 'mt' in the widget, I just can't rotate onto it via left-click on the widget.\r\n\r\nQtile Version: 0.22.1, X11\n\n### Required:\n\n- [X] I have searched past issues to see if this bug has already been reported.\n", "before_files": [{"content": "# Copyright (c) 2013 Jacob Mourelos\n# Copyright (c) 2014 Shepilov Vladislav\n# Copyright (c) 2014-2015 Sean Vig\n# Copyright (c) 2014 Tycho Andersen\n# Copyright (c) 2019 zordsdavini\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n\nfrom __future__ import annotations\n\nimport re\nfrom abc import ABCMeta, abstractmethod\nfrom subprocess import CalledProcessError, check_output\nfrom typing import TYPE_CHECKING\n\nfrom libqtile.command.base import expose_command\nfrom libqtile.confreader import ConfigError\nfrom libqtile.log_utils import logger\nfrom libqtile.widget import base\n\nif TYPE_CHECKING:\n    from libqtile.core.manager import Qtile\n\n\nclass _BaseLayoutBackend(metaclass=ABCMeta):\n    def __init__(self, qtile: Qtile):\n        \"\"\"\n        This handles getting and setter the keyboard layout with the appropriate\n        backend.\n        \"\"\"\n\n    @abstractmethod\n    def get_keyboard(self) -> str:\n        \"\"\"\n        Return the currently used keyboard layout as a string\n\n        Examples: \"us\", \"us dvorak\".  In case of error returns \"unknown\".\n        \"\"\"\n\n    def set_keyboard(self, layout: str, options: str | None) -> None:\n        \"\"\"\n        Set the keyboard layout with specified options.\n        \"\"\"\n\n\nclass _X11LayoutBackend(_BaseLayoutBackend):\n    kb_layout_regex = re.compile(r\"layout:\\s+(?P<layout>\\w+)\")\n    kb_variant_regex = re.compile(r\"variant:\\s+(?P<variant>\\w+)\")\n\n    def get_keyboard(self) -> str:\n        try:\n            command = \"setxkbmap -verbose 10 -query\"\n            setxkbmap_output = check_output(command.split(\" \")).decode()\n        except CalledProcessError:\n            logger.exception(\"Can not get the keyboard layout:\")\n            return \"unknown\"\n        except OSError:\n            logger.exception(\"Please, check that xset is available:\")\n            return \"unknown\"\n\n        match_layout = self.kb_layout_regex.search(setxkbmap_output)\n        if match_layout is None:\n            return \"ERR\"\n        keyboard = match_layout.group(\"layout\")\n\n        match_variant = self.kb_variant_regex.search(setxkbmap_output)\n        if match_variant:\n            keyboard += \" \" + match_variant.group(\"variant\")\n        return keyboard\n\n    def set_keyboard(self, layout: str, options: str | None) -> None:\n        command = [\"setxkbmap\"]\n        command.extend(layout.split(\" \"))\n        if options:\n            command.extend([\"-option\", options])\n        try:\n            check_output(command)\n        except CalledProcessError:\n            logger.error(\"Can not change the keyboard layout:\")\n        except OSError:\n            logger.error(\"Please, check that setxkbmap is available:\")\n\n\nclass _WaylandLayoutBackend(_BaseLayoutBackend):\n    def __init__(self, qtile: Qtile) -> None:\n        self.set_keymap = qtile.core.set_keymap\n        self._layout: str = \"\"\n\n    def get_keyboard(self) -> str:\n        return self._layout\n\n    def set_keyboard(self, layout: str, options: str | None) -> None:\n        maybe_variant: str | None = None\n        if \" \" in layout:\n            layout_name, maybe_variant = layout.split(\" \", maxsplit=1)\n        else:\n            layout_name = layout\n        self.set_keymap(layout_name, options, maybe_variant)\n        self._layout = layout\n\n\nlayout_backends = {\n    \"x11\": _X11LayoutBackend,\n    \"wayland\": _WaylandLayoutBackend,\n}\n\n\nclass KeyboardLayout(base.InLoopPollText):\n    \"\"\"Widget for changing and displaying the current keyboard layout\n\n    To use this widget effectively you need to specify keyboard layouts you want to use\n    (using \"configured_keyboards\") and bind function \"next_keyboard\" to specific keys in\n    order to change layouts.\n\n    For example:\n\n        Key([mod], \"space\", lazy.widget[\"keyboardlayout\"].next_keyboard(), desc=\"Next keyboard layout.\"),\n\n    When running Qtile with the X11 backend, this widget requires setxkbmap to be available.\n    \"\"\"\n\n    defaults = [\n        (\"update_interval\", 1, \"Update time in seconds.\"),\n        (\n            \"configured_keyboards\",\n            [\"us\"],\n            \"A list of predefined keyboard layouts \"\n            \"represented as strings. For example: \"\n            \"['us', 'us colemak', 'es', 'fr'].\",\n        ),\n        (\n            \"display_map\",\n            {},\n            \"Custom display of layout. Key should be in format \"\n            \"'layout variant'. For example: \"\n            \"{'us': 'us', 'lt sgs': 'sgs', 'ru phonetic': 'ru'}\",\n        ),\n        (\"option\", None, \"string of setxkbmap option. Ex., 'compose:menu,grp_led:scroll'\"),\n    ]\n\n    def __init__(self, **config):\n        base.InLoopPollText.__init__(self, **config)\n        self.add_defaults(KeyboardLayout.defaults)\n        self.add_callbacks({\"Button1\": self.next_keyboard})\n\n    def _configure(self, qtile, bar):\n        base.InLoopPollText._configure(self, qtile, bar)\n\n        if qtile.core.name not in layout_backends:\n            raise ConfigError(\"KeyboardLayout does not support backend: \" + qtile.core.name)\n\n        self.backend = layout_backends[qtile.core.name](qtile)\n        self.backend.set_keyboard(self.configured_keyboards[0], self.option)\n\n    @expose_command()\n    def next_keyboard(self):\n        \"\"\"set the next layout in the list of configured keyboard layouts as\n        new current layout in use\n\n        If the current keyboard layout is not in the list, it will set as new\n        layout the first one in the list.\n        \"\"\"\n\n        current_keyboard = self.backend.get_keyboard()\n        if current_keyboard in self.configured_keyboards:\n            # iterate the list circularly\n            next_keyboard = self.configured_keyboards[\n                (self.configured_keyboards.index(current_keyboard) + 1)\n                % len(self.configured_keyboards)\n            ]\n        else:\n            next_keyboard = self.configured_keyboards[0]\n\n        self.backend.set_keyboard(next_keyboard, self.option)\n\n        self.tick()\n\n    def poll(self):\n        keyboard = self.backend.get_keyboard()\n        if keyboard in self.display_map.keys():\n            return self.display_map[keyboard]\n        return keyboard.upper()\n", "path": "libqtile/widget/keyboardlayout.py"}], "after_files": [{"content": "# Copyright (c) 2013 Jacob Mourelos\n# Copyright (c) 2014 Shepilov Vladislav\n# Copyright (c) 2014-2015 Sean Vig\n# Copyright (c) 2014 Tycho Andersen\n# Copyright (c) 2019 zordsdavini\n#\n# Permission is hereby granted, free of charge, to any person obtaining a copy\n# of this software and associated documentation files (the \"Software\"), to deal\n# in the Software without restriction, including without limitation the rights\n# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n# copies of the Software, and to permit persons to whom the Software is\n# furnished to do so, subject to the following conditions:\n#\n# The above copyright notice and this permission notice shall be included in\n# all copies or substantial portions of the Software.\n#\n# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n# SOFTWARE.\n\nfrom __future__ import annotations\n\nimport re\nfrom abc import ABCMeta, abstractmethod\nfrom subprocess import CalledProcessError, check_output\nfrom typing import TYPE_CHECKING\n\nfrom libqtile.command.base import expose_command\nfrom libqtile.confreader import ConfigError\nfrom libqtile.log_utils import logger\nfrom libqtile.widget import base\n\nif TYPE_CHECKING:\n    from libqtile.core.manager import Qtile\n\n\nclass _BaseLayoutBackend(metaclass=ABCMeta):\n    def __init__(self, qtile: Qtile):\n        \"\"\"\n        This handles getting and setter the keyboard layout with the appropriate\n        backend.\n        \"\"\"\n\n    @abstractmethod\n    def get_keyboard(self) -> str:\n        \"\"\"\n        Return the currently used keyboard layout as a string\n\n        Examples: \"us\", \"us dvorak\".  In case of error returns \"unknown\".\n        \"\"\"\n\n    def set_keyboard(self, layout: str, options: str | None) -> None:\n        \"\"\"\n        Set the keyboard layout with specified options.\n        \"\"\"\n\n\nclass _X11LayoutBackend(_BaseLayoutBackend):\n    kb_layout_regex = re.compile(r\"layout:\\s+(?P<layout>[\\w-]+)\")\n    kb_variant_regex = re.compile(r\"variant:\\s+(?P<variant>\\w+)\")\n\n    def get_keyboard(self) -> str:\n        try:\n            command = \"setxkbmap -verbose 10 -query\"\n            setxkbmap_output = check_output(command.split(\" \")).decode()\n        except CalledProcessError:\n            logger.exception(\"Can not get the keyboard layout:\")\n            return \"unknown\"\n        except OSError:\n            logger.exception(\"Please, check that xset is available:\")\n            return \"unknown\"\n\n        match_layout = self.kb_layout_regex.search(setxkbmap_output)\n        if match_layout is None:\n            return \"ERR\"\n        keyboard = match_layout.group(\"layout\")\n\n        match_variant = self.kb_variant_regex.search(setxkbmap_output)\n        if match_variant:\n            keyboard += \" \" + match_variant.group(\"variant\")\n        return keyboard\n\n    def set_keyboard(self, layout: str, options: str | None) -> None:\n        command = [\"setxkbmap\"]\n        command.extend(layout.split(\" \"))\n        if options:\n            command.extend([\"-option\", options])\n        try:\n            check_output(command)\n        except CalledProcessError:\n            logger.error(\"Can not change the keyboard layout:\")\n        except OSError:\n            logger.error(\"Please, check that setxkbmap is available:\")\n\n\nclass _WaylandLayoutBackend(_BaseLayoutBackend):\n    def __init__(self, qtile: Qtile) -> None:\n        self.set_keymap = qtile.core.set_keymap\n        self._layout: str = \"\"\n\n    def get_keyboard(self) -> str:\n        return self._layout\n\n    def set_keyboard(self, layout: str, options: str | None) -> None:\n        maybe_variant: str | None = None\n        if \" \" in layout:\n            layout_name, maybe_variant = layout.split(\" \", maxsplit=1)\n        else:\n            layout_name = layout\n        self.set_keymap(layout_name, options, maybe_variant)\n        self._layout = layout\n\n\nlayout_backends = {\n    \"x11\": _X11LayoutBackend,\n    \"wayland\": _WaylandLayoutBackend,\n}\n\n\nclass KeyboardLayout(base.InLoopPollText):\n    \"\"\"Widget for changing and displaying the current keyboard layout\n\n    To use this widget effectively you need to specify keyboard layouts you want to use\n    (using \"configured_keyboards\") and bind function \"next_keyboard\" to specific keys in\n    order to change layouts.\n\n    For example:\n\n        Key([mod], \"space\", lazy.widget[\"keyboardlayout\"].next_keyboard(), desc=\"Next keyboard layout.\"),\n\n    When running Qtile with the X11 backend, this widget requires setxkbmap to be available.\n    \"\"\"\n\n    defaults = [\n        (\"update_interval\", 1, \"Update time in seconds.\"),\n        (\n            \"configured_keyboards\",\n            [\"us\"],\n            \"A list of predefined keyboard layouts \"\n            \"represented as strings. For example: \"\n            \"['us', 'us colemak', 'es', 'fr'].\",\n        ),\n        (\n            \"display_map\",\n            {},\n            \"Custom display of layout. Key should be in format \"\n            \"'layout variant'. For example: \"\n            \"{'us': 'us', 'lt sgs': 'sgs', 'ru phonetic': 'ru'}\",\n        ),\n        (\"option\", None, \"string of setxkbmap option. Ex., 'compose:menu,grp_led:scroll'\"),\n    ]\n\n    def __init__(self, **config):\n        base.InLoopPollText.__init__(self, **config)\n        self.add_defaults(KeyboardLayout.defaults)\n        self.add_callbacks({\"Button1\": self.next_keyboard})\n\n    def _configure(self, qtile, bar):\n        base.InLoopPollText._configure(self, qtile, bar)\n\n        if qtile.core.name not in layout_backends:\n            raise ConfigError(\"KeyboardLayout does not support backend: \" + qtile.core.name)\n\n        self.backend = layout_backends[qtile.core.name](qtile)\n        self.backend.set_keyboard(self.configured_keyboards[0], self.option)\n\n    @expose_command()\n    def next_keyboard(self):\n        \"\"\"set the next layout in the list of configured keyboard layouts as\n        new current layout in use\n\n        If the current keyboard layout is not in the list, it will set as new\n        layout the first one in the list.\n        \"\"\"\n\n        current_keyboard = self.backend.get_keyboard()\n        if current_keyboard in self.configured_keyboards:\n            # iterate the list circularly\n            next_keyboard = self.configured_keyboards[\n                (self.configured_keyboards.index(current_keyboard) + 1)\n                % len(self.configured_keyboards)\n            ]\n        else:\n            next_keyboard = self.configured_keyboards[0]\n\n        self.backend.set_keyboard(next_keyboard, self.option)\n\n        self.tick()\n\n    def poll(self):\n        keyboard = self.backend.get_keyboard()\n        if keyboard in self.display_map.keys():\n            return self.display_map[keyboard]\n        return keyboard.upper()\n", "path": "libqtile/widget/keyboardlayout.py"}]}