С изучением языков возникает проблема переключения раскладок клавиатуры. Когда два языка все просто, жамкаешь ALT+SHIFT (или что там у вас) и переключаешься на следующий язык. И ты всегда знаешь на какой именно язык переключился. Когда раскладок становится хотя бы 3 это уже вызывает проблемы. Потому что нажать ALT+SHIFT нужно один или несколько раз и непонятно сколько именно, не посмотрев в угол экрана
Я использую 6 языков, но раскладок у меня 4. Потому что для английского, испанского и немецкого, используется одна English international with AltGR dead keys. Скриншот из Ubuntu. В Windows она тоже есть.
По сути это просто английская раскладка, но и использованием правого ALT'а можно печатать дополнительные символы: ñáúéí¡¿ из испанского и äöüß из немецкого.
Таким образом вместо 6 раскладок у меня 4, но это все равно много.
Я долго мучался. Одно время вешал разные раскладки на разные комбинации клавиш например ALT+1 - английкский, ALT+2 - русский, ALT + 3 польский и так далее. Но это было неудобно по двум причинам. Во-первых, эти сочетания клавиш уже задействованы в IDE, а во-вторых, ALT+SHIFT как-то поудобнее чем ALT + 1. Поэтому я отказался от этого и продолжил мучаться с ALT+SHIFT, никогда не зная, на какой следующий язык я переключусь.
Потом я стал думать в направлении того, как разделить сочетания клавиш для основных и дополнительных языков. Т.е. например между en / ru я переключаюсь и использованием левых ALT+SHIFT, а между pl / uk с помощью правых ALT+SHIFT.
Возможно существуют какие-то инструменты, которые так умеют. Но я ничего подобного не нашел. Написать самому, казалось достаточно просто, берем готовую библиотеку для хоткеев, и потом остается отправить какие-то команды операционной системе на переключение раскладки.
Я использую Ubuntu, поэтому мое решение работает под этой ОС. Сначала я поискал библиотеки для перехвата горячих клавиш.
https://github.com/boppreh/keyboard (python) - не подошла, т.к. требует root.
https://github.com/timeyyy/system_hotkey (python) - умеет ловить хоткеи, но кроме ALT/CTRL/SHIFT в сочетании всегда должен быть какой-то символ например CTRL+A. Мне хотелось именно привычного ALT+SHIFT.
https://github.com/jamesbirtles/hotkey-rs (rust) - такая же проблема, как у предыдущей плюс на одном компе она работала, а на втором нет.
https://github.com/golang-design/hotkey (go) - судя по документации у нее такая же проблема как у предыдущих двух.
https://crates.io/crates/inputbot (rust) - требует root.
https://github.com/moses-palmer/pynput (python) - сначала я подумал, что наконец то нашел, то что нужно. Но с ней был ряд проблем. Во-первых, не работает правый ALT (есть даже issue на эту тему). Но эту проблему удалось победить. Но с левым альтом было еще хуже. В зависимости от того нажат сначала ALT или SHIFT выдаются разные коды (назовем их ALT и WTF_ALT), поэтому сочетания клавиш работает через раз. Я частично решил эту проблему, забиндив 3 комбинации клавиш ALT+SHIFT, WTF_ALT+SHIFT и ALT+WTF_ALT+SHIFT. Но там возникли дополнительные проблемы - для WTF_ALT срабатывает событие PRESSED но нет события RELEASED. Это тоже можно было победить. Но мне надоело городить костыли вокруг этой библиотеки и я пошел искать дальше.
А дальше никакой волшебной библиотеки я не нашел, зато нашел пример кода на stackoverflow. Я конечно уже видел его раньше, но после всех мучений с библиотеками решил попробовать его. Там нет готовых функций для отслеживания комбинаций клавиш, зато можно вручную отследить события PRESSSED и RELEASED. Далее нужно уже самостоятельно куда-то складывать нажатые клавиши, удалять их и сравнивать с образцами.
Еще оставалось выяснить как получить список языков и как их переключать. Ответ нашелся все там же)
Получить текущий индекс языка:
gdbus call --session \
--dest org.gnome.Shell \
--object-path /org/gnome/Shell \
--method org.gnome.Shell.Eval \
"imports.ui.status.keyboard.getInputSourceManager().currentSource.index"
Активировать язык по индексу:
gdbus call --session \
--dest org.gnome.Shell \
--object-path /org/gnome/Shell \
--method org.gnome.Shell.Eval \
"imports.ui.status.keyboard.getInputSourceManager().inputSources[0].activate()"
Этого хватило, чтобы написать прототип, захардкодив языки в переменных и вызывая эти команды через subprocess:
cmd = "gdbus call --session --dest ....
subprocess.call(cmd, shell=True).
Далее нужно было немного обработать напильником.
Еще нужно поместить скрипт в автозагрузку, можно сделать это через GUI или создав файлик нужного формата в директорию ~/.config/autostart/
В итоге получился небольшой проект, который можно скачать и установить себе.