Alterar o status dos leds do teclado, de dentro de uma sessão X, sem acesso root

10

Estou tentando forçar o capslock liderado. xsetnão funciona para mim, então estou tentando usar setleds.

Em um console gráfico, este comando retorna:

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

Em um terminal virtual, ele funciona, no entanto, o efeito é local para esse terminal virtual. Pelo que entendi, correndo

> setleds -L +caps < /dev/tty1

de um terminal virtual (meu servidor X está no tty1) deve funcionar. No entanto, isso requer acesso root.

Existe uma maneira de enviar um comando para o console subjacente a um servidor X, seja do referido xserver ou de outro VT, sem raiz?

Edit: A partir de uma sugestão de Mark Plotnik, e com base no código encontrado aqui , escrevi e compilei o seguinte:

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

Pelo que Gilles escreveu xset, eu não esperava que funcionasse, mas funciona ... em certo sentido: define o led, mas também define o status do capslock. Como não entendo completamente todo o código acima, posso ter cometido um erro bobo. Aparentemente, a linha XChangeKeyboardControl...não altera o comportamento do programa e XkbLockModifiersé o que define o status do led e do capslock.

T. Verron
fonte
Você pode fazer algo como xdotool key Caps_Lockum cliente X autorizado, embora isso realmente ative o caps lock.
Mark Plotnick
@MarkPlotnick O ponto é realmente não ativar o CapsLock. Existe uma maneira de desativar o CapsLock, sem tocar no led?
T. Verron
Eu olhei para a xtermfonte e ela usa uma chamada para XChangeKeyboardControl () para definir ou desabilitar os LEDs sem afetar o estado do caps lock etc. Portanto, se você pode compilar o código C, essa é uma abordagem.
Mark Plotnick
@MarkPlotnick Afeta xtermos leds? Parece uma boa ideia, editarei a pergunta com meus resultados.
T. Verron
Eu xtermacendi o LED ScrollLock enviando a seqüência de escape ESC [3 q, conforme o arquivo ctlseqs.txtque acompanha a fonte, mas não consegui que os LEDs Num ou CapsLock acendessem com os parâmetros 1 e 2. Talvez eu precise faça a configuração XKB mencionada na resposta. xtermchamadas XChangeKeyboardControlem xtermShowLEDe xtermClearLEDs, mas não chama XkbLockModifiersa lugar nenhum.
Mark Plotnick

Respostas:

7

Em princípio, você deve conseguir fazê-lo com o venerável xsetcomando.

xset led named 'Caps Lock'

ou xset led 4para definir o número 4 do LED, se o seu sistema não reconhecer os LEDs pelo nome.

No entanto, isso não parece funcionar de maneira confiável. Na minha máquina, só posso definir o Scroll Lock dessa maneira e não sou o único . Isso parece ser uma questão de configuração do XKB .

A seguinte solução alternativa no nível do usuário deve funcionar (na maior parte):

  1. Extraia sua configuração atual do xkb:

    xkbcomp $DISPLAY myconf.xkb
    
  2. Edite o arquivo myconf.xkb, substituindo !allowExplicitpor allowExplicitnos blocos relevantes:

    indicator "Caps Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= Lock;
    };
    indicator "Num Lock" {
        allowExplicit;
        whichModState= locked;
        modifiers= NumLock;
    };
    
  3. Carregue o novo arquivo

    xkbcomp myconf.xkb $DISPLAY
    

Agora, ativar e desativar os leds xsetdeve funcionar. De acordo com o relatório de erros, você não poderá desativar os leds quando eles devem estar ligados (por exemplo, se o CapsLock estiver ativado).

Gilles 'SO- parar de ser mau'
fonte
Obrigado! Eu tinha tentado xsetantes, e de fato não funciona. Eu ainda não tinha visto este relatório de bug. Enfim, "Status: Resolvido Wontfix" não é realmente encorajador ... A solução alternativa allowExplicitprovavelmente funcionaria para mim (não preciso desligar o led), mas alterá-lo ainda requer raiz.
T. Verron
@ T.Verron Você não precisa ser root para alterar a configuração do XKB. Você pode ligar xkbcompa qualquer momento. Não estou familiarizado o suficiente com o XKB para dizer exatamente o que você precisa alterar (definir um aspecto específico em vez de um mapa predefinido completo com o XKB é um pouco trabalhoso), mas unix.stackexchange.com/questions/166844/mapping -key-bindings /… deve ter alguns ponteiros.
Gilles 'SO- stop be evil'
Oh, bom argumento. Bem, como primeira tentativa, tentei xkbcomp $DISPLAY output.xkb:, substituindo !allowExplicitpor allowExplicitna indicator "Caps Lock"seção e recarregando o arquivo por xkbcomp output.xkb. Existem muitos avisos e o xset não funciona melhor depois. Vou ler um pouco mais sobre o xkb.
T. Verron
1
Isso meio que funcionou para mim. Depois de importar o arquivo modificado, recebi algumas mensagens de erro e pude acender os LEDs, mas outras coisas foram alteradas, além de não sobreviver a uma reinicialização. Então eu fui adiante com um edited /usr/share/X11/xkb/compat/ledcapse ... / lednum e isso o tornou permanente.
Jtgd
0

Usando sed

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

Após o logoff e logon novamente, o Caps LockLED agora pode ser controlado sem rootprivilégios usando os comandos:

$ xset led named 'Caps Lock'
$ xset -led named 'Caps Lock'
Serge Stroobandt
fonte
Mas isso requer raiz.
T. Verron
@ T.Verron Apenas uma vez para alterar um arquivo de configuração sudoe nunca mais. Para entender por que isso pode ser tão importante para determinados usuários, consulte este vimaplicativo .
Serge Stroobandt
Sendo a pessoa que fez a pergunta há 3 anos, eu definitivamente entendo por que isso pode ser importante para alguns usuários (no meu caso, foi para contornar o atraso estúpido que os teclados da apple têm ao ativar o capslock, depois de remapear o capslock para controlar). Mas naquela época, eu precisava especificamente de uma solução sem acesso root, porque era para um computador de trabalho. A resposta aceita envolve mais algumas etapas, mas funciona sem o sudo.
T. Verron
@ T.Verron eu entendo. Sistemas compartilhados são outro caso em que isso não funcionaria. Não obstante, gostei da franqueza do último comentarista na resposta aceita e fiz seddela uma frase única.
Serge Stroobandt
0

Uma combinação da abordagem sem raiz do @Gilles com a idéia de automação completa do @Serge_Stroobandt.

Para ativar o controle dos LEDs Caps Lock , Num Lock e 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

Para ligar e desligar um 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
fonte