Como eu detecto se meu terminal tem foco na GUI de um script de shell?

1

Descrição do problema / objetivo

Idealmente, eu gostaria de uma maneira boa de detectar a partir de um script de shell se a janela tem ou não foco. De uma maneira "boa", quero dizer alguma maneira que requer passos mínimos e, de preferência, não requer peneirar cada janela aberta cegamente para encontrar a minha com base no título.

O objetivo é controlar as notificações em muitos scripts diferentes - por isso, estou apenas procurando uma solução geral que possa ser aplicada a todos e quaisquer um deles.

O que eu tenho até agora é indireto e hacky - é o seguinte:

  1. Defina meu título como algo único ou mecanicamente relevante (no meu modelo, é meu caminho PTS ou, mais robustamente, um UUID). Espero desesperadamente que este título não seja anulado por algo.

  2. Obtenha uma lista de todas as janelas abertas, por título.

  3. Itere pela lista para identificar minha janela, combinando-a com o elemento title. (Observe a possibilidade de erros aqui se outra janela tiver o mesmo elemento title.)

  4. Detectar se a dita janela tem ou não foco.

Deve-se notar que eu faço não quero implementar isso, e só o farei como último recurso. Então, o que eu estou pedindo aqui é algo que não é isso .

Compromissos

Esta solução é obviamente terrível, então eu gostaria de saber se há algo remotamente melhor, de qualquer forma. Eu preferiria algo portátil, elegante e perfeito, mas reconheço a necessidade potencial de compromisso. Por melhor , quero dizer qualquer um dos seguintes:

  1. Uma solução que só funciona com um emulador de terminal específico, por ex. fazendo com que o próprio emulador de terminal defina uma variável de ambiente, permitindo que o script detecte em qual janela ele está.

  2. Uma solução que não requer a definição do título e, em vez disso, usa outro marcador invisível no estado da janela que é acessível e detectável a partir de um script de shell anexado à referida janela.

  3. Recolocando a escada do processo pai para localizar o PID do emulador de terminal pai e trabalhando a partir dele (Observe que uma solução que funcione recusando a árvore de processos para detectar o processo pai que iniciou o script funcionará apenas se o script estiver sendo executado localmente, então esta solução está incompleta, mas continua boa!)

Condições

Eu estava recebendo perguntas sobre exatamente em quais condições minha solução preferida deveria funcionar, e a resposta é o maior número possível . Mas, no mínimo, gostaria de algo que funcione:

  1. Em uma sessão de terminal de guia única em execução nativa (cenário padrão).

  2. Em multiplexadores de terminal como o tmux. (A portabilidade entre diferentes multiplexadores de terminal é preferida, mas não é realmente necessária.)

Extras que eu realmente aprecio (em ordem de importância), incluem:

  1. Capacidade de funcionar em conexões remotas via telnet e SSH.

  2. Capacidade de distinguir qual guia está aberta em uma sessão de terminal com várias guias.

Resumo

Eu quero uma maneira boa de encontrar em qual janela do emulador de terminal meu shell script está anexado, para que eu possa detectar se ele tem foco ou não.

Note que eu já estou ciente da mecânica de como para iterar através de janelas abertas, e como detectar se eles têm ou não foco e quais títulos eles possuem. Estou ciente da existência de xdotool e xprop e esta questão não é sobre a mecânica básica dessas ferramentas (a menos que haja algum recurso de magia negra oculta que eu não conheça sobre os passos paralelos da intrincada imprecisão da minha solução atual.)

A razão pela qual eu não quero isso é porque é terrível. Qualquer outra solução que realiza a mesma coisa?

    
por Alexandria P. 06.11.2018 / 08:38

2 respostas

1
if [ "$(xdotool getwindowfocus)" -eq "$WINDOWID" ]; then
   echo I have the focus
fi

Isso não funcionará dentro da tela / tmux se eles foram iniciados de outro lugar e apenas anexados à janela atual.

    
por 06.11.2018 / 12:08
2

Há um modo FocusIn / FocusOut . Para ativar:

echo -ne '\e[?1004h'

Para desativar:

echo -ne '\e[?1004l'

Em cada evento de foco, você recebe \e[I (in) ou \e[O (out) do fluxo de entrada.

O Terminal GNOME (e outros terminais baseados em VTE) também reportam o estado atual quando você ativa este modo. Ou seja, você pode ativar e desativá-lo imediatamente para consultar o valor uma vez.

Você pode combinar read com um tempo limite ou especificar 3 caracteres para obter a resposta. Note, no entanto, que está sujeito a condições de corrida, por ex. caso você tenha digitado certos caracteres.

    
por 06.11.2018 / 16:16