Zmień status diod LED klawiatury, z poziomu sesji X, bez dostępu użytkownika root

10

Próbuję wymusić włączenie kapsla. xsetnie działa dla mnie, więc próbuję użyć setleds.

W konsoli graficznej to polecenie zwraca:

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

W terminalu wirtualnym działa, jednak efekt jest lokalny dla tego terminalu wirtualnego. Z tego co rozumiem, bieganie

> setleds -L +caps < /dev/tty1

z wirtualnego terminala (mój serwer X siedzi na tty1) powinien działać. Wymaga to jednak dostępu do konta root.

Czy istnieje sposób na wysłanie polecenia do konsoli leżącej u podstaw serwera X, czy to ze wspomnianego serwera Xserver, czy z innego VT bez roota?

Edycja: Na podstawie sugestii Marka Plotnika i na podstawie znalezionego tutaj kodu napisałem i skompilowałem:

#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;
}

Z tego, o czym pisał Gilles xset, nie spodziewałem się, że zadziała, ale działa ... w pewnym sensie: ustawia led, ale także ustawia stan Capslock. Nie do końca rozumiem cały powyższy kod, więc mogłem popełnić głupi błąd. Najwyraźniej linia XChangeKeyboardControl...nie zmienia zachowania programu i XkbLockModifiersjest tym, co określa status diody LED i stanu Capslock.

T. Verron
źródło
Możesz zrobić coś takiego jak xdotool key Caps_Lockz autoryzowanego klienta X, chociaż w rzeczywistości spowoduje to włączenie Caps Lock.
Mark Plotnick,
@MarkPlotnick Chodzi o to, aby nie włączać CapsLock. Czy istnieje sposób na wyłączenie CapsLock bez dotykania diody LED?
T. Verron,
Spojrzałem na xtermźródło, a ono używa wywołania XChangeKeyboardControl (), aby ustawić lub rozbroić diody LED bez wpływu na stan Caps Lock itp. Więc jeśli możesz skompilować kod C, to jest jedno podejście.
Mark Plotnick,
@MarkPlotnick Czy xtermwpływa na diody LED? Brzmi jak dobry pomysł, zedytuję pytanie z moimi wynikami.
T. Verron
Muszę xtermzapalić diodę ScrollLock, wysyłając sekwencję Escape ESC [3 q, zgodnie z plikiem ctlseqs.txtdostarczonym ze źródłem, ale nie udało mi się zapalić diod Num lub CapsLock za pomocą parametrów 1 i 2. Może potrzebuję wykonaj konfigurację XKB wymienioną w odpowiedzi. xtermdzwoni XChangeKeyboardControldo xtermShowLEDi xtermClearLEDs, ale nigdzie nie dzwoni XkbLockModifiers.
Mark Plotnick

Odpowiedzi:

7

Zasadniczo powinieneś być w stanie to zrobić za pomocą czcigodnego xsetpolecenia.

xset led named 'Caps Lock'

lub xset led 4ustawić LED numer 4, jeśli system nie rozpoznaje LED po nazwie.

Nie wydaje się to jednak działać niezawodnie. Na moim komputerze mogę ustawić Scroll Lock tylko w ten sposób i nie jestem jedyny . To wydaje się być kwestia konfiguracji XKB .

Poniższe obejście na poziomie użytkownika powinno działać (w przeważającej części):

  1. Wyodrębnij bieżącą konfigurację xkb:

    xkbcomp $DISPLAY myconf.xkb
    
  2. Edytuj plik myconf.xkb, zastępując !allowExplicitgo allowExplicitw odpowiednich blokach:

    indicator "Caps Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= Lock;
    };
    indicator "Num Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= NumLock;
    };
    
  3. Załaduj nowy plik

    xkbcomp myconf.xkb $DISPLAY
    

Teraz włączanie i wyłączanie diod LED xsetpowinno działać. Według raportu o błędzie nie będzie można wyłączyć diod LED, gdy powinny one być włączone (na przykład, jeśli włączona jest funkcja CapsLock).

Gilles „SO- przestań być zły”
źródło
Dzięki! Próbowałem już xsetwcześniej i rzeczywiście to nie działa. Jednak nie widziałem tego zgłoszenia błędu. W każdym razie „Status: Resolved Wontfix” nie jest zbyt zachęcające ... Obejście problemu allowExplicitprawdopodobnie by dla mnie zadziałało (nie muszę wyłączać diody LED), ale zmiana go nadal wymaga rootowania.
T. Verron
@ T.Verron Nie musisz być rootem, aby zmienić konfigurację XKB. Możesz zadzwonić xkbcompw dowolnym momencie. Nie jestem wystarczająco zaznajomiony z XKB, aby powiedzieć ci dokładnie, co musisz zmienić (ustawienie konkretnego aspektu zamiast pełnej wstępnie zdefiniowanej mapy za pomocą XKB jest trochę uciążliwe), ale unix.stackexchange.com/questions/166844/mapping -key-bindings /… powinien mieć kilka wskaźników.
Gilles „SO- przestań być zły”
Dobra racja. Cóż, jako pierwsza próba: spróbowałem: xkbcomp $DISPLAY output.xkbzastąpiłem !allowExplicitallowExplicitw indicator "Caps Lock"sekcji, a następnie ponownie załadowałem plik xkbcomp output.xkb. Jest wiele ostrzeżeń, a później xset nie działa lepiej. Przeczytam trochę więcej o xkb.
T. Verron
1
Ten rodzaj działał dla mnie. Po zaimportowaniu zmodyfikowanego pliku otrzymałem kilka komunikatów o błędach i mogłem zapalić diody LED, ale inne rzeczy się popsuły, a ponadto nie przetrwało to ponownego uruchomienia. Więc poszedłem naprzód zredagowany /usr/share/X11/xkb/compat/ledcapsi ... / lednum i to sprawiło, że stał się trwały.
jtgd
0

Za pomocą sed

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

Po wylogowaniu i ponownym zalogowaniu Caps Lockmożna teraz sterować diodą LED bez żadnych rootuprawnień za pomocą poleceń:

$ xset led named 'Caps Lock'
$ xset -led named 'Caps Lock'
Serge Stroobandt
źródło
Ale to wymaga rootowania.
T. Verron,
@ T.Verron Tylko raz, aby zmienić plik konfiguracyjny za pomocą, sudoa potem nigdy więcej. Aby dowiedzieć się, dlaczego może to być tak ważne dla niektórych użytkowników, zobacz tę vimaplikację .
Serge Stroobandt,
Będąc tym, który zadał pytanie 3 lata temu, zdecydowanie rozumiem, dlaczego może być ważny dla niektórych użytkowników (w moim przypadku było to obejście głupiego opóźnienia, jakie mają klawisze jabłkowe podczas aktywacji capslocka, po ponownym mapowaniu capslocka do kontroli). Ale wtedy szczególnie potrzebowałem rozwiązania bez dostępu do roota, ponieważ było to przeznaczone dla komputera w pracy. Przyjęta odpowiedź wymaga jeszcze kilku kroków, ale działa bez sudo.
T. Verron,
@ T.Verron Rozumiem. Systemy współdzielone to kolejny przypadek, w którym to nie zadziała. Niezależnie od tego, podobał mi się prostota ostatniego komentatora odnośnie do przyjętej odpowiedzi i zrobiłem z tego sedjedno-linijkę.
Serge Stroobandt
0

Połączenie podejścia opartego na braku rootowania przez @Gilles z ideą pełnej automatyzacji przez @Serge_Stroobandt.

Aby włączyć sterowanie diodami Caps Lock , Num Lock i 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

Aby włączyć lub wyłączyć diodę LED:

# 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
źródło