Измените состояние светодиодных индикаторов клавиатуры из сеанса X без прав root

10

Я пытаюсь заставить загнанный капслок. xsetне работает для меня, поэтому я пытаюсь использовать setleds.

В графической консоли эта команда возвращает:

> LANG=C setleds -L +caps
KDGKBLED: Inappropriate ioctl for device
Error reading current flags setting. Maybe you are not on the console?

В виртуальном терминале это работает, однако эффект является локальным для этого виртуального терминала. Из того, что я понимаю, работает

> setleds -L +caps < /dev/tty1

с виртуального терминала (мой X-сервер сидит на tty1) должен работать. Однако для этого требуется root-доступ.

Есть ли способ отправить команду на консоль, лежащую в основе X-сервера, будь то с указанного сервера xserver или с другого VT, без рута?

Изменить: По предложению Марка Плотника и на основе кода, найденного здесь , я написал и скомпилировал следующее:

#include <X11/Xlib.h>
#include <X11/XKBlib.h>

#define SCROLLLOCK 1
#define CAPSLOCK 2
#define NUMLOCK 16

void setLeds(int leds) {
   Display *dpy = XOpenDisplay(0);
   XKeyboardControl values;
   values.led_mode = leds & SCROLLLOCK ? LedModeOn : LedModeOff;
   values.led = 3;
   XChangeKeyboardControl(dpy, KBLedMode, &values);
   XkbLockModifiers(dpy, XkbUseCoreKbd, CAPSLOCK | NUMLOCK,
                    leds & (CAPSLOCK | NUMLOCK) );
   XFlush(dpy);
   XCloseDisplay(dpy);
}

int main() {
   setLeds(CAPSLOCK);
   return 0;
}

Из того, о чем писал Жиль xset, я не ожидал, что это сработает, но это работает ... в некотором смысле: он устанавливает светодиод, но также устанавливает статус capslock. Я не до конца понимаю весь приведенный выше код, поэтому, возможно, я сделал глупую ошибку. Видимо, строка XChangeKeyboardControl...не меняет поведение программы, а XkbLockModifiersименно то, что задает светодиод и статус колпачка.

Т. Веррон
источник
Вы можете сделать что-то вроде xdotool key Caps_Lockавторизованного X-клиента, хотя на самом деле это включит caps lock.
Марк Плотник
@MarkPlotnick Дело не в том, чтобы включить CapsLock. Есть ли способ выключить CapsLock, не касаясь светодиодов?
Т. Веррон
Я посмотрел на xtermисточник, и он использует вызов XChangeKeyboardControl () для установки или сброса светодиодов, не влияя на состояние блокировки заглавных букв и т. Д. Поэтому, если вы можете скомпилировать код на C, это один из подходов.
Марк Плотник
@MarkPlotnick Влияет ли xtermна светодиоды? Звучит как хорошая идея, я отредактирую вопрос своими результатами.
Т. Веррон
Я xtermвключил светодиод ScrollLock, отправив escape-последовательность ESC [3 q, в соответствии с файлом, ctlseqs.txtкоторый поставляется с источником, но не смог заставить светодиоды Num или CapsLock загореться с параметрами 1 и 2. Возможно, мне нужно сделайте конфигурацию XKB, упомянутую в ответе. xtermзвонки XChangeKeyboardControlв xtermShowLEDи xtermClearLEDs, но не вызывает XkbLockModifiersвообще нигде.
Марк Плотник

Ответы:

7

В принципе, вы должны быть в состоянии сделать это с почтенной xsetкомандой.

xset led named 'Caps Lock'

или xset led 4установить светодиод № 4, если ваша система не распознает светодиоды по названию.

Тем не менее, это не работает надежно. На моей машине я могу только установить Scroll Lock, и я не единственный . Это , кажется, вопрос конфигурации XKB .

Должен работать следующий обходной путь на уровне пользователя (по большей части):

  1. Извлеките текущую конфигурацию xkb:

    xkbcomp $DISPLAY myconf.xkb
    
  2. Отредактируйте файл myconf.xkb, заменяя !allowExplicitс allowExplicitв соответствующих блоках:

    indicator "Caps Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= Lock;
    };
    indicator "Num Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= NumLock;
    };
    
  3. Загрузите новый файл

    xkbcomp myconf.xkb $DISPLAY
    

Теперь включение и выключение светодиодов xsetдолжно работать. Согласно отчету об ошибке, вы не сможете отключить светодиоды, когда они должны быть включены (например, если включен CapsLock).

Жиль "ТАК - перестань быть злым"
источник
Спасибо! Я пытался xsetраньше, и это действительно не работает. Я не видел этот отчет об ошибке, хотя. В любом случае, «Status: Resolved Wontfix» на самом деле не обнадеживает ... Обход, allowExplicitвероятно, будет работать для меня (мне не нужно выключать индикатор ), но для его изменения все еще требуется root.
Т. Веррон
@ T.Verron Вам не нужно быть пользователем root, чтобы изменить конфигурацию XKB. Вы можете позвонить xkbcompв любое время. Я не достаточно знаком с XKB, чтобы точно сказать, что вам нужно изменить (установка определенного аспекта, а не полной предопределенной карты с помощью XKB - это немного больно), но unix.stackexchange.com/questions/166844/mapping -key-bindings /… должно иметь несколько указателей.
Жиль "ТАК - перестань быть злым"
О, хорошая мысль. Ну, как первая попытка, я попробовал: xkbcomp $DISPLAY output.xkb, а затем заменить !allowExplicitна allowExplicitв indicator "Caps Lock"секции, затем загрузить файл с xkbcomp output.xkb. Предупреждений много, а потом xset не работает лучше. Я прочитаю еще немного о xkb.
Т. Веррон
1
Этот вид работал для меня. После того, как я импортировал измененный файл, у меня появилось несколько сообщений об ошибках, и я смог зажечь светодиоды, но другие вещи испортились, плюс он не пережил перезапуск. Поэтому я продолжил редактировать /usr/share/X11/xkb/compat/ledcapsи ... / lednum, и это сделало его постоянным.
Jtgd
0

С помощью sed

$ sudo sed -i 's|\!allowExplicit|allowExplicit|g' /usr/share/X11/xkb/compat/ledcaps

После выхода и повторного входа Caps Lockсветодиод теперь можно контролировать без каких-либо rootпривилегий с помощью команд:

$ xset led named 'Caps Lock'
$ xset -led named 'Caps Lock'
Серж Строобандт
источник
Но для этого нужен root.
Т. Веррон
@ T.Verron Только один раз, чтобы изменить файл конфигурации, sudoа затем никогда больше. Чтобы понять, почему это может быть так важно для определенных пользователей, просмотрите это vimприложение .
Серж Строобандт
Будучи тем, кто задал вопрос 3 года назад, я определенно понимаю, почему это может быть важно для некоторых пользователей (в моем случае это было обходить глупую задержку, которую имеют яблочные клавиатуры при активации capslock, после переназначения capslock для контроля). Но в то время мне было необходимо решение без какого-либо root-доступа, потому что оно было для рабочего компьютера. Принятый ответ включает в себя еще несколько шагов, но он работает без sudo.
Т. Веррон
@ Т.Веррон, я понимаю. Совместно используемые системы - еще один случай, когда это не будет работать. Несмотря на это, мне понравилась прямолинейность последнего комментатора в отношении принятого ответа и я сделал из него sedодну строчку.
Серж Строобандт
0

Комбинация безрукого подхода @Gilles с идеей полной автоматизации @Serge_Stroobandt.

Чтобы включить управление индикаторами Caps Lock , Num Lock и Shift Lock :

#!/bin/bash
# Enables to control keyboard LEDs that are not available for control by default
xkbcomp $DISPLAY /tmp/my_conf.xkb
cat /tmp/my_conf.xkb | awk -e '
    BEGIN {
        change = 0
    }

    {
        if (change == 1) {
            if ($1 == "!allowExplicit;") {
                gsub("!", "", $0)
            }
            change = 0
        }
        print $0

    }

    /indicator "Caps Lock"/ {
        change = 1
    }
    /indicator "Num Lock"/ {
        change = 1
    }
    /indicator "Shift Lock"/ {
        change = 1
    }
    ' > /tmp/my_conf_modified.xkb
xkbcomp /tmp/my_conf_modified.xkb $DISPLAY

Чтобы включить и выключить светодиод:

# Turns the LED on
xset led named 'Caps Lock'

# wait 1s
sleep 1

# Resets the LED to the actual state,
# so it might still be on, if Caps Lock is activated.
xset -led named 'Caps Lock'
hoijui
источник