Tkabber Wiki

Wish и русская раскладка в Windows
Login

Материал из Tkabber Wiki

Содержание

Проблема

Windows-версия библиотеки Tk имеет неприятный баг: нажатия одних и тех же клавиш на разных языках ввода клавиатуры (например, английской и русской) генирируют разные "символы клавиш" ("keysyms"), которые Tk использует при сопоставлении нажатия клавиши со списком клавиатурных акселераторов (они же "хоткеи", они же "горячие клавиши").

На самом деле в Windows-версии Tk имеет место "двойной" баг:

К примеру, нажатие клавиши a на английской раскладке возвращает keysym "a", а на русской — "ocircumflex".

В X (с xkb) keysym для клавиши a всегда — "a" независимо от текущего языка ввода.

Описанная проблема приводит к тому, что хоткеи в Ткаббере, запущенном под Windows, без дополнительных усилий работают только на оригинальной английской раскладке2.

Решение

Ткаббер

Этот баг частично обойдён разработчиками Ткаббера путём создания альтернативных привязок клавиш для описанных "странных" keysym'ов, парных соответствующим "нормальным". Например, такая привязка есть для палитры эмоциконок — Alt-e.

К сожалению, остаются две проблемы:

О том, как решать эти проблемы, написано ниже.

Как узнать альтернативный keysym

Придётся написать микроскопическую программу на Tcl/Tk. Набить её можно прямо в консоли Ткаббера, хотя, конечно же, подойдёт и просто wish или tkcon (в нём понадобится вначале выполнить команду package require Tk).

Вот эта программка:

toplevel .keytest
label .keytest.l -text {Нажимайте клавиши}
pack .keytest.l -fill both -expand true
bind .keytest <KeyPress> [list puts %K]

После выполнения этой программы вы увидите новое окно верхнего уровня с текстом "Нажимайте клавиши" внутри. Сделайте это окно активным, смените раскладку и нажимайте там интересующие вас клавиши. При этом вы увидите, что в вашу консоль (туда, где вы набрали программу) пишутся названия клавиш — те самые keysyms4.

Как применить полученные знания

Возьмём практический пример: предположим, вы хотите "русифицировать" хоткеи Ctrl-L и Ctrl-J (действия: "Подключиться" и "Отключиться", соответственно).

Для этого, во-первых, вам нужно выяснить названия соответствующих клавиш на русской раскладке.

Узнав, что клавише "l" на русской раскладке соответствует keysym "adiaresis", а клавише "j" — "icircumflex", мы можем написать в конфиг Ткаббера "русификацию":

hook::add finload_hook {
  bind . <Control-KeyPress-adiaeresis> [bind . <Control-KeyPress-l>]
  bind . <Control-KeyPress-icircumflex> [bind . <Control-KeyPress-j>]
}

Смысл этого куска кода состоит в следующем:

  1. Наш код "вешается" на хук "finload_hook", который выполняется по наступлению события "инициализация Ткаббера окончена, главное окно сконфигурировано и показано";
  2. Команда bind . возвращяет код Tcl, являющийся текущим обработчиком указанной комбинации клавиш;
  3. Этот код связывается с нашей новой комбинацией клавиш.
  4. Данная операция повторяется для каждой интересующей нас комбинации клавиш и окна, к которому она привязана.

Полезные советы

(!) Сделать: вообще-то напрашивается самостоятельный раздел "Собственные хоткеи в Ткаббере" где должно быть написано о привязке клавиш "вообще"; после чего бОльшая часть нижеприведённых советов должна уйти в этот раздел

Привязки

Всё это означает, что в некоторых (если не во всех) случаях не обойтись без ковыряния в исходиках Ткаббера с целью выяснения как и к чему привязан интересующий Вас хоткей.

Иногда соответствующие виртуальные события описаны в документации (Ткаббера, или, например, плагина к нему)6.

Обработчики

Если у вас плохо со знанием Tcl и вам трудно разбираться с исходниками Ткаббера, то самый простой способ повесить свой хоткей на действие, за которым некий хоткей уже закреплён, это "клонировать" существующий хоткей. Именно этим мы и занимались в нашем примере: брали обработчик существующего хоткея и связывали его с новым, собственным, хоткеем. Однако, иногда удобнее (и концептуально чище) указывать обработчик при создании привязки.

При "клонировании" хоткеев, привязанных к окнам (а не виртуальным событиям Тк), имейте в виду, что такое клонирование можно производить только в finload_hook, т.к. окно, к которому привязан интересующий нас хоткей должно существовать к моменту клонирования. Привязывать хоткеи к виртуальным событиям Tk можно в любой момент времени (и, соответственно, помещать код привязок в любое место конфига).

Дополнительная информация

... находится на Tclers' Wiki:

Примечания

1 Можете проверить сами:

Маску можно накладывать и не мысленно, например, напишите в консоли Ткаббера:

format 0x%X [expr {0x06C1 & 0xFF}]

2 Она является "оригинальной" потому, что в Ткаббере привязки клавиш деляются через их "английское" именование, например, <Ctrl-KeyPress-r>, поскольку это позволяет им без всяких пинков работать в X.

3 Строго говоря, наличие специальных "хаков" для поддержки русского языка прямо в программе "попахивает" не очень хорошо, ведь подобные проблемы имеют место с любым языком, у которого коды клавиш ≥ 256, а таких языков много. По этой причине обход этого бага неплохо бы вынести во внешние плагины (по одному для каждого языка). Для этого было бы очень удобно иметь виртуальные события Тк для всех действий, для которых определены хоткеи.

4 Учтите, что вывод будет попадать в консоль только в том случае, если вы не перенаправили стандартный поток вывода интерпретатора Tcl в файл; в этом случае либо ищите их там, либо поменяйте последнюю команду на такую:

bind .keytest <KeyPress> [list .keytest.l config -text %K]

в этом случае названия клавиш будут рисоваться прямо в окне, в котором вы эти клавиши нажимаете.

5 Существует идея постепенно перевести все клавиатурные привязки, существующие в Ткаббере, на виртуальные события Tk. Это сильно упростит создание пользовательских привязок.

6 Разработчикам плагинов настоятельно рекоммендуется использовать виртуальные события Тк, если требуется поддержка управления хоткеями или определёнными событиями мыши, а так же обязательно документировать эти события — пользователь не должен ковыряться в коде плагина для того, чтобы поменять настройку хоткея. В качестве примера может выступить документация от плагина "Postpone Text".