Gerenciamento alternativo de janelas no Linux

Eu sou do tipo que atribui a troca de layout ao Caps Lock, porque não tenho paciência para pressionar duas teclas quando posso usar uma só. Eu até gostaria de ter duas teclas desnecessárias: uma eu usaria para ativar o layout em inglês e a segunda para o russo. Mas a segunda tecla desnecessária é a que chama o menu de contexto, que é tão desnecessária que muitas fabricantes de notebooks a removem. Então tenho que me contentar com o que existe.

E também não quero ficar procurando os ícones das janelas na barra de tarefas ao trocar de janelas, tentando reconhecer os nomes enquanto deslizo por Alt+Tab, passando pelos desktops e assim por diante. Eu quero pressionar uma combinação de teclas (idealmente uma só, mas não há mais teclas desnecessárias livres) e imediatamente acessar a janela que preciso. Por exemplo assim:

  • Alt+F: Firefox
  • Alt+D: Firefox (Navegação Privada)
  • Alt+T: Terminal
  • Alt+M: Calculadora
  • Alt+E: IntelliJ Idea
  • e assim por diante.

Além disso, ao pressionar, por exemplo, Alt+M eu quero ver a calculadora, independentemente de a programação estar aberta ou não. Se estiver aberta, a janela deve receber o foco; se não, a programação precisa ser iniciada e o foco deve ser transferido assim que ela carregar.

Para casos que não são cobertos pelo cenário anterior, eu quero ter combinações de teclas universais, às quais posso facilmente atribuir qualquer uma das janelas abertas. Por exemplo, tenho 10 combinações atribuídas a Alt+1 até Alt+0, que não estão ligadas a nenhum programa. Eu posso simplesmente pressionar Alt+1 e a janela que está atualmente em foco receberá o foco ao pressionar Alt+1.

Abaixo, uma descrição de mais algumas funcionalidades e uma resposta sobre como isso pode ser feito. Mas já vou avisar que essa personalização ‘para si mesmo’ pode causar uma forte dependência e até um processo de abstinência quando for necessário usar Windows, Mac OS ou até mesmo um computador com Linux de outra pessoa.

Na verdade, se pensarmos bem, usamos poucas programações no dia a dia. Navegador, terminal, IDE, algum mensageiro, gerenciador de arquivos, calculadora e, talvez, isso seja praticamente tudo. Não é necessário ter tantas combinações de teclas para cobrir 95% das tarefas diárias.

Para programas que têm várias janelas abertas, uma delas pode ser designada como principal. Por exemplo, se várias janelas do IntelliJ Idea estão abertas, atribuídas a Alt+E. Em condições normais, ao pressionar Alt+E alguma janela deste programa será aberta, provavelmente a que foi aberta primeiro. No entanto, se pressionar Alt+E Quando uma das janelas deste programa já estiver em foco, essa janela será designada como principal e receberá o foco em combinações de teclas subsequentes.

A janela principal pode ser redesignada. Para isso, a combinação deve primeiro ser redefinida e, em seguida, outra janela pode ser definida como a principal. Para redefinir a combinação, é preciso pressionar a própria combinação e depois uma combinação especial de redefinição, que eu a configurei como Alt+Backspace. Isso acionará um script que cancelará a atribuição da janela principal para a combinação anterior. Depois, pode-se designar uma nova janela principal, conforme descrito no parágrafo anterior. A redefinição de uma janela vinculada para combinações universais acontece da mesma forma.

A introdução ficou longa, mas queria primeiro explicar o que faremos e depois como fazer.

Para aqueles que estão cansados de ler

Resumindo, o link para os scripts estará no final do artigo.

Mas ainda assim, não será possível instalar e usar imediatamente. Será preciso entender primeiro como o script encontra a janela correta. Sem isso, não será possível indicar ao script para onde exatamente o foco deve ser enviado. E é necessário entender o que fazer se, de repente, a janela adequada não for encontrada.

Além disso, não vou me concentrar em como configurar a execução de scripts ao pressionar combinações de teclas. Por exemplo, no KDE, isso está em Configurações do Sistema → Atalhos → Atalhos Personalizados. Em outros gerenciadores de janelas, isso também deve existir.

Introdução ao wmctrl

Wmctrl é uma ferramenta de linha de comando para interagir com o X Window Manager. Este é um programa chave para o script. Vamos dar uma olhada rápida em como usá-lo.

Para começar, vamos exibir a lista de janelas abertas:

$ wmctrl -lx
0x01e0000e -1 plasmashell.plasmashell             N/A Desktop — Plasma
0x01e0001e -1 plasmashell.plasmashell             N/A Plasma
0x03a00001  0 skype.Skype                         N/A Skype
0x04400003  0 Navigator.Firefox                   N/A Google Tradutor - Mozilla Firefox
0x04400218  0 Navigator.Firefox                   N/A Melhores publicações do dia / Habr - Mozilla Firefox (Navegação Privada)
...

Opção --selector exibe uma lista de todas as janelas abertas, e -x adiciona ao output o nome da classe (skype.Skype, Navigator.Firefox etc). Precisamos aqui do id da janela (coluna 1), nome da classe (coluna 3) e título da janela (a última coluna).

Você pode tentar ativar uma janela usando a opção -a:

$ wmctrl -a skype.Skype -x

Se tudo ocorreu conforme o planejado, a janela do Skype deve aparecer na tela. Se em vez da opção -x usar a opção -i, então em vez do nome da classe, podemos especificar o id da janela. O problema com o id é que ele muda a cada vez que o aplicativo é iniciado e não podemos sabê-lo de antemão. Por outro lado, esse atributo identifica claramente a janela, o que pode ser importante quando o aplicativo abre mais de uma janela. Sobre isso mais adiante.

Neste estágio, precisamos lembrar que iremos procurar a janela necessária usando regex a partir da saída wmctrl -lx. Mas isso não significa que precisamos usar algo complicado. Geralmente, o nome da classe ou o título da janela é suficiente.

Basicamente, a ideia principal já deve estar clara. Nas configurações de hotkeys/atalhos globais para seu gerenciador de janelas, configuramos a combinação desejada para executar o script.

Como usar scripts

Primeiro, precisamos instalar as utilidades de linha de comando wmctrl e xdotool:

$ sudo apt-get install wmctrl xdotool

Em seguida, precisamos baixar os scripts e adicioná-los ao $PATH. Eu geralmente os coloco em ~/bin:

$ cd ~/bin
$ git clone https://github.com/masyamandev/Showwin-script.git
$ ln -s ./Showwin-script/showwin showwin
$ ln -s ./Showwin-script/showwinDetach showwinDetach

Se o diretório ~/bin não existia, precisamos criá-lo e reiniciar (ou fazer logoff), caso contrário, ~/bin não será adicionado ao $PATH. Se tudo estiver feito corretamente, os scripts devem estar disponíveis no console e a conclusão automática deve funcionar ao pressionar Tab.

O script principal showwin recebe 2 parâmetros: o primeiro é o regex, pelo qual procuraremos a janela desejada, e o segundo parâmetro é o comando a ser executado se a janela desejada não for encontrada.

Podemos tentar executar o script, por exemplo:

$ showwin "Mozilla Firefox$" firefox

Se o Firefox estiver instalado, ele deve receber o foco. Mesmo que o Firefox não tenha sido iniciado, ele deve ter sido iniciado.

Se funcionar, podemos tentar configurar a execução de comandos em combinações. Nas configurações de hotkeys/atalhos globais, adicionamos:

  • Alt+F: showwin «Mozilla Firefox$» firefox
  • Alt+D: showwin «Mozilla Firefox (Navegação Privada)$» «firefox -private-window»
  • Alt+C: showwin «chromium-browser.Chromium-browser N*» chromium-browser
  • Alt+X: showwin «chromium-browser.Chromium-browser I*» «chromium-browser -incognito»
  • Alt+S: showwin «skype.Skype» skypeforlinux
  • Alt+E: showwin «jetbrains-idea» idea.sh

E assim por diante. Cada um pode configurar as combinações de teclas e softwares da maneira que preferir.
Se tudo estiver correto, com as combinações mencionadas acima, poderemos alternar entre janelas com um simples pressionar de teclas.

Desculpe, amantes do Chrome: uma janela normal não pode ser diferenciada da janela anônima a partir da saída. wmctrl não é possível, pois eles têm nomes de classes e títulos de janelas iguais. Nos regex sugeridos, os caracteres N* e I* são necessários apenas para que esses regex sejam distintos entre si e para que possamos designar janelas principais diferentes.

Para redefinir a janela principal da combinação anterior (na verdade, para o regex que showwin foi chamado pela última vez), é necessário chamar o script showwinDetach. Este script está atribuído à combinação de teclas Alt+Backspace.

O script showwin tem mais uma função. Quando chamado com um único parâmetro (neste caso, o parâmetro é simplesmente um identificador), ele não verifica o regex e considera todas as janelas adequadas. Isso pode parecer inútil, mas dessa forma podemos designar qualquer janela como principal e alternar rapidamente para ela.

Eu configurei as seguintes combinações:

  • Alt+1: showwin «CustomKey1»
  • Alt+2: showwin «CustomKey2»
  • …
  • Alt+0: showwin «CustomKey0»
  • Alt+Backspace: showwinDetach

Dessa forma, posso vincular qualquer janela às combinações Alt+1…Alt+0. Basta pressionar Alt+1 para vincular a janela atual a essa combinação. Posso desfazer a vinculação pressionando Alt+1, e então Alt+Backspace. Ou fechar a janela, isso também funciona.

A seguir, vou falar um pouco sobre detalhes técnicos. Você pode não ler isso e simplesmente tentar configurar e ver como funciona. Mas eu ainda recomendaria entender os scripts de outras pessoas antes de executá-los em seu computador :).

Como diferenciar janelas diferentes de um aplicativo

Basicamente, o primeiro exemplo «wmctrl -a skype.Skype -x» funcionou e pode ser usado. Mas vamos dar mais uma olhada no exemplo com o Firefox, onde duas janelas estão abertas:

0x04400003  0 Navigator.Firefox                   N/A Google Tradutor - Mozilla Firefox
0x04400218  0 Navigator.Firefox                   N/A As melhores publicações do dia / Habr - Mozilla Firefox (Navegação Privada)

A primeira janela é o modo normal, e a segunda é a Navegação Privada. Gostaríamos de considerar essas janelas como aplicativos diferentes e alternar entre elas usando diferentes combinações de teclas.

Precisamos complicar o script que alterna as janelas. Eu usei a seguinte solução: listar todas as janelas, fazer grep por regex, pegar a primeira linha usando head, extrair a primeira coluna (isso será o id da janela) usando cut, alternar para a janela pelo id.

Aqui deveria ter uma piada sobre expressões regulares e dois problemas, mas na verdade não estou usando nada complicado. Preciso de regex para poder indicar o final da linha (símbolo «$») e diferenciar «Mozilla Firefox$» de «Mozilla Firefox (Navegação Privada)$».

A equipe se parece aproximadamente com isso:

$ wmctrl -i -a `wmctrl -lx | grep -i "Mozilla Firefox$" | head -1 | cut -d" " -f1`

Aqui já podemos deduzir a segunda característica do script: se o grep não retornar nada, significa que o aplicativo desejado não está aberto e precisa ser iniciado com o comando do segundo parâmetro. E depois, verificar periodicamente se a janela necessária foi aberta, para dar foco a ela. Não vou me detiver muito nisso, quem precisar, pode consultar os códigos-fonte.

Quando as janelas do aplicativo não são distinguíveis

Então, aprendemos a dar foco à janela do aplicativo desejado. Mas e se houver mais de uma janela do aplicativo aberta? A qual delas devemos dar foco? O script acima provavelmente dará foco à primeira janela aberta. No entanto, gostaríamos de mais flexibilidade. Seria bom poder lembrar exatamente qual janela precisamos e alternar para essa janela.

A ideia era a seguinte: se quisermos lembrar uma janela específica para uma combinação de teclas, devemos pressionar essa combinação quando a janela desejada estiver em foco. Assim, nas pressões futuras dessa combinação, o foco será dado a essa janela. Enquanto a janela não for fechada ou não fizermos um reset para essa combinação do script. showwinDetach.

O algoritmo do script showwin é aproximadamente assim:

  • Verificar se já lembramos anteriormente do id da janela à qual devemos dar foco.
    Se lembramos e essa janela ainda existir, então damos foco a ela e saímos.
  • Verificamos qual janela está atualmente em foco e, se ela se encaixar em nossa solicitação, lembramos seu id para poder voltar a ela mais tarde e saímos.
  • Passamos para alguma janela adequada, se existir, ou abrimos o aplicativo desejado.

Para saber qual janela está agora em foco, podemos usar a ferramenta de console xdotool, convertendo sua saída para o formato hexadecimal:

$ printf "0xx" `xdotool getwindowfocus`

É mais fácil lembrar de algo no bash criando arquivos em um sistema de arquivos virtual que reside na memória. No Ubuntu, isso está conectado por padrão em /dev/shm/. Sobre outras distribuições, não posso dizer nada, espero que algo semelhante também exista. Podemos verificar com o comando:

$ mount -l | grep tmpfs

O script criará diretórios vazios nesta pasta, assim: /dev/shm/$USER/showwin/$SEARCH_REGEX/$WINDOW_ID. Além disso, a cada chamada ele criará um symlink /dev/shm/$USER/showwin/showwin_last para /dev/shm/$USER/showwin/$SEARCH_REGEX. Isso será necessário para que, se necessário, possamos remover o id da janela para uma determinada combinação com o uso do script. showwinDetach.

O que pode ser melhorado

Primeiramente, os scripts precisam ser configurados manualmente. Certamente, devido à necessidade de entender e fazer muitas coisas manualmente, muitos de vocês podem nem tentar configurar o sistema. Se houvesse a possibilidade de simplesmente instalar um pacote e configurar tudo de forma mais simples, isso provavelmente ganharia alguma popularidade. E quem sabe, acabaria sendo incluído nos distribuições padrão.

E, talvez, seja mais fácil fazer isso. Se a partir do ID da janela é possível descobrir o ID do processo que a criou, e a partir do ID do processo saber qual comando o gerou, poderia ser possível automatizar a configuração. Na verdade, eu não investiguei se o que escrevi neste parágrafo é viável. O fato é que, pessoalmente, estou satisfeito com a forma como funciona atualmente. Mas se alguém além de mim achar o método conveniente e encontrar uma maneira de melhorá-lo, eu ficaria feliz em usar a melhor solução.

Outro problema, como já mencionei, é que em alguns casos as janelas não podem ser distinguidas uma da outra. Até agora, só observei isso com o modo incógnito no Chrome/Chromium, mas, possivelmente, há outros casos semelhantes. No pior cenário, sempre existem combinações universais. Alt+1…Alt+0. Novamente, utilizo o Firefox e, pessoalmente, este problema não é significativo para mim.

Mas um problema significativo para mim é que, no trabalho, utilizo Mac OS e não consegui configurar nada semelhante. A utilidade wmctrl parece que consegui instalar, mas ela não funciona bem no Mac OS. Algo pode ser feito com o aplicativo Automator, mas ele trava tanto que é inconveniente até mesmo quando está funcionando. Também não consegui configurar combinações de teclas para que funcionassem em todos os programas. Se por acaso alguém encontrar uma solução — ficaria feliz em utilizá-la.

Em conclusão

Surpreendentemente, consegui escrever muitas palavras sobre uma funcionalidade que, à primeira vista, parecia simples. Queria transmitir a ideia sem sobrecarregar o texto, mas ainda não pensei em como contar de forma mais simples. Talvez em formato de vídeo fosse melhor, mas aqui isso não é bem aceito.

Falei um pouco sobre o que está por trás do script e como configurá-lo. Não entrei em detalhes sobre o script em si, mas ele tem apenas 50 linhas, portanto não é difícil de entender.

Espero que alguém experimente essa ideia e, talvez, até a avalie. Posso dizer que o script foi escrito há cerca de 3 anos e é MUITO conveniente para mim. Tão conveniente que causa um sério desconforto ao trabalhar em computadores de outras pessoas. E com meu MacBook de trabalho.

Link para os scripts

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster