Как вы эмулируете цифровую клавиатуру для использования с программным обеспечением для проектирования (таким как Blender)?

Возможно, вы сможете использовать встроенные привязки для функций завершения строки чтения, наблюдаемые с:

$ bind -p | grep glob
"\eg":   glob-complete-word
"\C-x*": glob-expand-word
"\C-xg": glob-list-expansions

Затем вы можете ввести несколько подстановочных символов(*и?)и развернуть их в строку с помощью Ctrl -x*или просто перечислить с помощью других команд.

2
15.04.2020, 20:34
1 ответ

Быстрый запуск

Если вас не интересуют какие-либо объяснения, (я знаю, что могу быть многословным ), просто используйте {цифры, выделенные жирным шрифтом в фигурных скобках} в начале некоторых абзацев. Выполняйте каждый из этих шагов по порядку, и вы, вероятно, сможете реализовать это за несколько минут. Обратите внимание, что это руководство предполагает некоторую компетенцию Unix (, способность создавать каталоги, создавать файлы, sudoповышать права до root-доступа и т. д. ). Также обратите внимание, что root-доступ требуется только там, где указано , поэтому вам не нужно использовать sudo, если это не указано.

Общее описание решения

Мы будем использовать xkb для добавления «блокировки» (типа Caps Lock )эмуляции цифровой клавиатуры в Linux. Я хотел бы, чтобы мои клавиши «jkluio789» представляли числовые представления чисел «123456789», а также несколько других включений («m», -> «0», «-= []» ->[цифровая клавиатура]" -+ *", "." ->[цифровая клавиатура]"." ). Я буду переключать этот «режим цифровой клавиатуры» с помощью комбинации клавиш [Shift+ Mod4+ [key]], где Mod4— код модификатора для клавиши моей операционной системы (, также называемой «Команда» или « Клавиша Windows», и иногда назначается коду модификатора Superили Hyper), а [key]— это любая из клавиш, используемых в моей эмулируемой цифровой клавиатуре (, например «j» или «[» ). Простые модификации этой настройки должны быть относительно простыми после прочтения полного решения.

Для этого мы определим пользовательский файл «типа» xkb, который сообщает xkb, как интерпретировать различные клавиши-модификаторы, которые мы будем использовать для инициализации нашей эмуляции клавиатуры, а также пользовательский файл «символов» xkb,который сообщает xkb, как каждая клавиша, которую мы нажимаем, должна вести себя нормально (Группа 1 ), как она должна вести себя во время эмуляции цифровой клавиатуры (Группа 2 )и как переключаться между ними (Действие уровня 3 для обеих групп ). Наконец, мы сделаем наше решение постоянным, интегрируя его в текущую xkbmap, используя sedкаждый раз, когда мы начинаем новый сеанс (, чтобы наше решение не стиралось при каждом обновлении xkb).

Подробное описание решения

Структура каталогов

{1} Первое, что мы сделаем, это определим каталог, в котором мы будем хранить наши различные файлы. Ваш может выглядеть как угодно, но мой выглядит так

/home
  +-<username>
    +-.xkb
      +-symbols
      +-types
      +-keymap
      +-log

Тип файла

Когда у нас есть дерево каталогов, давайте определим фактические файлы в нашем решении. Первое, что мы сделаем, это определим наш файл «type». Этот файл расскажет xkb, как перемещаться между «уровнями» (, например, как Shiftделает букву заглавной, переходя от первого уровня строчной буквы к верхнему уровню прописной буквы ). Эти уровни немного трудны для понимания, особенно для носителей английского языка, но интернациональные клавиатуры используют их с большим успехом для альтернативных букв и символов, а также для диакритических знаков.

Мы будем использовать его, чтобы определить, как мы намерены указать изменение в наших ключах. Другими словами, мы сообщаем ему, что мы ожидаем поведения «уровня 1», когда модификатор не нажат (, как правило, стандартная строчная буква в нашем «нормальном режиме» ), поведение «уровня 2», когда мы удерживаем кнопку Клавиша Shift(обычно является стандартной заглавной буквой в нашем «нормальном режиме» )и поведением «уровня 3» u, когда мы удерживаем обе клавиши Shift+Mod4(— особый случай для наших целей, который мы используйте, чтобы указать, что при использовании для изменения клавиши клавиша теперь будет переключаться между режимами ).

{2} Откройте новый файл, который мы назовем togglekeypad.Скопируйте в него следующий кодовый блок и сохраните его в каталоге typesпод \home\<username>\.xkb\types. ПРИМЕЧАНИЕ. :Возможно, вам придется изменить все экземпляры Mod4на любой модификатор, который соответствует вашей кнопке «Команда»/«Ключ Windows» (. Возможно, вам придется поэкспериментировать, см. эту веб-страницу в разделе «Ключи-модификаторы» . ] для руководства )или любой другой модификатор, который вы хотите.

partial default xkb_types "togglekeypad" { // Name of this type file
        type "TOGGLEKEYPAD" { // Name of this "type"
                modifiers = Shift+Mod4; // The modifiers that this type concerns itself with
                map[Shift] = level2; // Shift brings us to level 2
                map[Mod4+Shift] = level3; // Windows key plus shift brings us to level 3
                level_name[Level1] = "Base"; // Human-readable names for each level (not really used, but convenient)
                level_name[Level2] = "Shift";
                level_name[Level3] = "Transfer";
        };
};

{3} Мы также должны скопировать этот файл в каталог /usr/share/X11/xkb/types/. Для этого потребуются привилегии суперпользователя, что, к сожалению, противоречит цели xkbбыть пользовательским -космическим приложением, но я не могу заставить setxkbmapраспознать файл без этого. Предложения приветствуются!

Файл символов

Следующее, что мы сделаем, это сообщим xkbчто должен делать каждый ключ при изменении каждым из способов, которые мы описали в файле типов.

Мы скажем, что хотим использовать две группы в нашем файле символов. Это означает, что каждая клавиша имеет два различных общих поведения, между которыми мы каким-то образом будем переключаться, это обычное поведение при наборе текста и новое поведение эмуляции цифровой клавиатуры. Для каждого ключа мы скажем, что 1 )мы хотим использовать тип TOGGLEKEYPAD, 2 )мы определим символы (, то есть то, что компьютер видит ), связанные с каждым из физических ключей в обе группы для всех уровней и 3 )мы определим любые действия (любые специальные вещи, которые xkbдолжны делать )связанные с каждой клавишей для обеих групп на всех уровнях. Это звучит довольно запутанно, но должно быть немного понятнее, если взглянуть на пример.

Первая клавиша, которую мы видим в файле символов, который я вставил ниже, это клавиша <AC07>. Это соответствует клавише «J» на большинстве клавиатур, в соответствии с картой, показанной здесь (, рис. 2 ). Для этого физического ключа мы говорим, что в обычном режиме :на уровне 1 (без модификаторов, согласно нашему файлу типов ), он будет просто набирать «j»,а в модификаторе(Shiftуровня 2 )он просто наберет «J». На уровне 3 он делает что-то особенное :, здесь нет символа, связанного с уровнем 3, но есть действие, и это действие должно LockGroup(group=2). Другими словами, переключите нас на нашу вторую группу, нашу группу «Клавиатура». Если мы посмотрим на следующие несколько строк, мы увидим, что у нас есть больше символов и действий, определенных для группы 2 для этой же клавиши. В нем говорится, что на уровне 1 (никакие модификаторы )не вводят символ, а RedirectKey(keycode=<KP1>). Другими словами, зарегистрируйте эту клавишу, как если бы мы на самом деле только что нажали клавишу <KP1>, которая соответствует «1» на клавиатуре. (Примечание :мы могли бы снова поставить NoAction ()и использовать символ KP_1, которому соответствует клавиша <KP1>, но я подумал, что это даст наилучшую совместимость ). Для уровня 2 сделайте то же самое, но добавьте к ключу модификатор Shift. Наконец, для уровня 3 мы возвращаемся к Группе 1, «Стандартному» режиму.

{4} Откройте новый файл, который мы назовем togglekeypad_symbols. Скопируйте в него следующий кодовый блок и сохраните его в каталоге symbolsпод \home\<username>\.xkb\symbols.

default partial
xkb_symbols "togglekeypad" {
    name[Group1]= "Standard";
    name[Group2]= "Keypad";

    key <AC07> { // J
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ j,  J, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP1>), RedirectKey(keyCode=<KP1>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AC08> { // K
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ k,  K, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP2>), RedirectKey(keyCode=<KP2>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AC09> { // L
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ l,  L, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP3>), RedirectKey(keyCode=<KP3>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD07> { // U
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ u,  U, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP4>), RedirectKey(keyCode=<KP4>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD08> { // I
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ i,  I, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP5>), RedirectKey(keyCode=<KP5>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD09> { // O
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ o,  O, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP6>), RedirectKey(keyCode=<KP6>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE07> { // 7
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 7,  ampersand, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP7>), RedirectKey(keyCode=<KP7>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE08> { // 8
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 8,  asterisk, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],     
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP8>), RedirectKey(keyCode=<KP8>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE09> { // 9
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 9,  parenleft, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP9>), RedirectKey(keyCode=<KP9>), LockGroup(group=1)]
    };
    
    // NumLock
    key <AE06> { // 6
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 6,  asciicircum, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<NMLK>), RedirectKey(keyCode=<NMLK>), LockGroup(group=1)]
    };
    
    // Bottom Row (and zero)
    key <AB07> { // M
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ m,  M, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP0>), RedirectKey(keyCode=<KP0>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE10> { // 0
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ 0,  parenright, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KP0>), RedirectKey(keyCode=<KP0>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AB09> { //.
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ period,  greater, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPDL>), RedirectKey(keyCode=<KPDL>, modifiers=Shift), LockGroup(group=1)]
    };
    
    // Arithmetic Operators
    key <AE11> { // -
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ minus,  underscore, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPSU>), RedirectKey(keyCode=<KPSU>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AE12> { // +
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ equal,  plus, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPAD>), RedirectKey(keyCode=<KPAD>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD12> { // [
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ bracketleft,  braceleft, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPDV>), RedirectKey(keyCode=<KPDV>, modifiers=Shift), LockGroup(group=1)]
    };
    
    key <AD12> { // ]
        type = "TOGGLEKEYPAD",
        symbols[Group1] = [ bracketright,  braceright, NoSymbol],
        actions[Group1] = [NoAction(), NoAction(), LockGroup(group=2)],
        
        symbols[Group2] = [NoSymbol, NoSymbol, NoSymbol],
        actions[Group2] = [RedirectKey(keyCode=<KPMU>), RedirectKey(keyCode=<KPMU>, modifiers=Shift), LockGroup(group=1)]
    };
};

Протестируйте нашу клавиатуру

{5} Чтобы протестировать конфигурацию клавиатуры как есть, откройте окно Terminalи введите

setxkbmap -types complete+togglekeypad -print | sed -e '/xkb_symbols/s/"[[:space:]]/+togglekeypad_symbols(togglekeypad)&/' > $HOME/.xkb/keymap/customMap
xkbcomp -I$HOME/.xkb -R$HOME/.xkb keymap/customMap $DISPLAY

Это захватит текущие настройки нашей xkbкарты (с использованиемsetxkbmap - print)при установке типов, используемых дляcomplete+togglekeypad(всего в файле /usr/share/X11/xkb/types/complete, а также включая наш файл типов в/usr/share/X11/xkb/types/togglekeypad). Затем он передаст это в sed, который добавит наши символы togglekeypadиз нашего файла togglekeypad_symbolsв используемые файлы символов. Наконец, мы использовали xkbcompдля компиляции новой раскладки.

Обратите внимание, что на моей машине NumLock предположительно отключен (, потому что на моей машине нет цифровой клавиатуры ), поэтому клавиши цифровой клавиатуры фактически отправят компьютеру свои основные функции, т. е. Home, End, PG Up, PG Down и т. д. Чтобы ввести числа при использовании эмулированной цифровой клавиатуры, удерживайте Shift.Я пробовал различные методы, чтобы изменить это поведение (, меняя аргумент modifersмежду уровнями в файле символов, назначая новую клавишу для эмуляции клавиши NumLock <NMLK>и переключая ее ), но пока ничего не сработало. для меня. К счастью, при тестировании в Blender он работает точно так, как ожидалось, без необходимости удерживать Shift.

{6} Если на данный момент что-то пошло не так, не беспокойтесь, просто выйдите/войдите в систему (или, в худшем случае, перезапустите ), выполните отладку и повторите попытку. Если все работает, давайте сделаем это постоянным.

Создание постоянного решения

Конечно, есть несколько более элегантных способов сделать наше решение постоянным между сеансами, но самым простым и надежным способом для меня было просто поместить приведенные выше команды в конец моего файла ~/.bashrc. Я использовал решение, предложенное здесь , которое добавляет немного проверки ошибок, и добавил немного больше (, чтобы я мог видеть любые выходные данные об ошибках ).

{7} Откройте файл ~/.bashrc. Добавьте в конец следующий скрипт:

    # Setup custom keyboard remapping to emulate a number pad when "Shift+Cmd+numap_key" is pressed to initialize
if [ -d $HOME/.xkb/keymap ]; then
  setxkbmap -types complete+togglekeypad -print | \
    sed -e '/xkb_symbols/s/"[[:space:]]/+togglekeypad_symbols(togglekeypad)&/' > $HOME/.xkb/keymap/customMap 2> $HOME/.xkb/log/sedErrors
  xkbcomp -w0 -I$HOME/.xkb -R$HOME/.xkb keymap/customMap $DISPLAY > $HOME/.xkb/log/outputOfCommand 2>&1
fi

{8} После перезапуска эмуляция цифровой клавиатуры теперь должна быть постоянной!

Заключение

Хотя объяснение длинное, сам метод относительно короткий. Недостатки заключаются в том, что для правильной работы Blender требуется метод блокировки, в то время как я бы предпочел вместо этого метод удержания, а также то, что ему требуется root-доступ, чтобы получить xkbдля распознавания нашего файла пользовательских типов по какой-то причине. Тем не менее, в целом, это, кажется, работает хорошо для меня. Если у вас есть какие-либо вопросы или предложения, пожалуйста, не стесняйтесь оставлять их ниже!

4
19.03.2021, 02:28

Теги

Похожие вопросы