Source code for libqtile.widget.keyboardlayout

import subprocess
from subprocess import CalledProcessError
from . import base
import re


[docs]class KeyboardLayout(base.InLoopPollText): """ Widget for changing and displaying the current keyboard layout. It requires setxkbmap to be available in the sytem. """ defaults = [ ("update_interval", 1, "Update time in seconds."), ("configured_keyboards", "us", "A list of predefined keyboard layouts " "represented as strings. For example: " "['us', 'us colemak', 'es', 'fr']."), ] def __init__(self, **config): base.InLoopPollText.__init__(self, **config) self.add_defaults(KeyboardLayout.defaults) def button_press(self, x, y, button): if button == 1: self.next_keyboard() def next_keyboard(self): """ Set the next layout in the list of configured keyboard layouts as new current layout in use. If the current keyboard layout is not in the list, it will set as new layout the first one in the list. """ current_keyboard = self.poll() if current_keyboard in self.configured_keyboards: # iterate the list circularly next_keyboard = self.configured_keyboards[ (self.configured_keyboards.index(current_keyboard) + 1) % len(self.configured_keyboards)] else: next_keyboard = self.configured_keyboards[0] self._set_keyboard(next_keyboard) def poll(self): """ Return the currently used keyboard layout as a string. Examples: "us", "us dvorak". In case of error returns "unknown". """ try: xset_output = subprocess.check_output(["xset", "-q"]).decode() keyboard = _Keyboard(self.configured_keyboards).get_keyboard_layout(xset_output).upper() return str(keyboard) except CalledProcessError as e: self.log.error('Can not change the keyboard layout: {0}' .format(e)) except OSError as e: self.log.error('Please, check that setxkbmap is available: {0}' .format(e)) return "unknown" def _set_keyboard(self, keyboard): command = ['setxkbmap'] command.extend(keyboard.split(" ")) try: subprocess.check_call(command) except CalledProcessError as e: self.log.error('Can not change the keyboard layout: {0}' .format(e)) except OSError as e: self.log.error('Please, check that setxkbmap is available: {0}' .format(e))
class _Keyboard(object): def __init__(self, configured_keyboards): if len(configured_keyboards) == 1: self.languages = { 'first': configured_keyboards[0], 'second': 'None', } else: self.languages = { 'first': configured_keyboards[0], 'second': configured_keyboards[1], } self.regular_strings = { 'hexadecimal': { 'first': """\w{4}e\w{3}""", 'second': """\w{4}f\w{3}""", }, 'binary': { 'first': """\w{4}0\w{3}""", 'second': """\w{4}1\w{3}""", }, "inetger": "\d{8}", "led_mask": """LED mask:\s\s\w{8}""", } def get_keyboard_layout(self, xset_output): raw_list = [] for item in xset_output.strip().splitlines(): if re.search(self.regular_strings['led_mask'], item): raw_led_mask = re.search(self.regular_strings['led_mask'], item).group() raw_list = raw_led_mask.split(':') led_mask = raw_list[1].strip() break if not re.search(self.regular_strings['inetger'], led_mask): cur_regular_strings = self.regular_strings['hexadecimal'] else: cur_regular_strings = self.regular_strings['binary'] if re.search(cur_regular_strings['first'], led_mask): result = self.languages['first'] elif re.search(cur_regular_strings['second'], led_mask): result = self.languages['second'] else: result = "ERR" return result