Gire o foco pelos monitores

5

Eu tenho 3 monitores na minha máquina de desenvolvimento, que roda o Ubuntu + Unity. Eu costumo dedicar um monitor para navegação na web e IM, e os outros dois para terminais onde executo o vim ou insiro comandos. Eu estou procurando por uma sequência de chave única para alternar entre eles à vontade.

Gostaria de saber como posso mudar o foco para as janelas (de topo) em cada monitor. O comportamento que estou procurando ou é como ALT + TAB, exceto em vez de girar entre aplicativos (o que apenas disponibiliza a instância de aplicativo usada mais recentemente na rotação), posso girar o foco entre os monitores.

Como um compromisso, eu poderia suportar usar o mecanismo ALT + TAB se eu pudesse ter todas as janelas da lista. Eu ainda imagino isso ficando chato, no entanto.

    
por San Jacinto 29.10.2015 / 12:37

1 resposta

2

Script (s) para girar o foco através de monitores

Na configuração abaixo, dois scripts estão envolvidos: um script de fundo para acompanhar o histórico de janelas focadas (veja a explicação na parte inferior para ler porque é necessário), e um " ação "script para colocar sob uma tecla de atalho, para definir o foco na próxima tela. Se a tela seguinte não tiver uma janela para definir o foco, será exibida uma mensagem:

Osscripts

Script1;oscriptdesegundoplano,salve-o(exatamente)comofocus_track.py

#!/usr/bin/env python3 import subprocess import time import os rootdata = os.environ["HOME"]+"/.focus_history" def get_screendata(): return sorted([int(s.split("+")[-2]) for s in subprocess.check_output(["xrandr"]).decode("utf-8").split() if s.count("+") == 2]) def current_windows(): try: return subprocess.check_output(["wmctrl", "-lG"]).decode("utf-8") except subprocess.CalledProcessError: pass def convert_format(w_id): return w_id[:2]+(10-len(w_id))*"0"+w_id[2:] def read_data(): return open(rootdata).read().splitlines() def get_top(wlist): top = convert_format([l.split("#")[-1].strip() for l in \ subprocess.check_output(["xprop", "-root"]).decode("utf-8").splitlines() \ if "_NET_ACTIVE_WINDOW(WINDOW)" in l][0]) return [l for l in wlist if top in l][0] if __name__ == "__main__": open(rootdata, "wt").write("This is an empty line") while True: time.sleep(1) wdata = current_windows() if wdata != None: wlist = wdata.splitlines() # get frontmost window (as in wmctrl -lG) top = get_top(wlist) oldlist = read_data() if not top == oldlist[0]: # clean up closed windows [oldlist.remove(l) for l in oldlist if not l.split()[0] in wdata] # remove possible other mentions of the active window [oldlist.remove(l) for l in oldlist if l.startswith(top.split()[0])] open(rootdata, "wt").write(("\n").join([top]+oldlist))

Script 2; o script de ação, salve-o como next_focus.py Em um único e mesmo diretório como script 1 .

#!/usr/bin/env python3
import subprocess
import focus_track

# read existing windows and their order (x-wise) from file
windows = [w.split() for w in focus_track.read_data()]
w_data = [[w[0], int(w[2])] for w in windows]
# get position of currently focussed window
currfocus = focus_track.get_top(focus_track.current_windows().splitlines()).split()[2]
# get screendata
screens = focus_track.get_screendata()

def screen_pos(x):
    return [(int(x) > n) for n in screens].count(True)

scr_position = screen_pos(currfocus)
next_screen = 1 if scr_position == len(screens) else scr_position+1
try:
    next_focus = [w for w in w_data if screen_pos(w[1]) == next_screen][0]
    subprocess.Popen(["wmctrl", "-ia", next_focus[0]])
except IndexError:
    subprocess.Popen(["notify-send", "No window to focus on next screen"])

Como usar

  1. Os scripts precisam de wmctrl para serem instalados

    sudo apt-get install wmctrl
    
  2. Copie o script 1 em um arquivo vazio, salve-o como (exatamente) focus_track.py . O nome é importante, já que ambos os scripts compartilham funções; o script 1 é importado para o script 2.
  3. Copie o script 2 em um arquivo vazio, salve-o como (exatamente) next_focus.py em um único diretório do script 1 .
  4. Teste- execute a configuração: N.B. Inicie o script de segundo plano antes de abrir (e, portanto, focalizar) as janelas. O Windows, aberto antes do início do script de segundo plano, não é "gravado" até que esteja focado

    • Inicie o script de segundo plano (por exemplo, de um terminal) com o comando:

      python3 /path/to/focus_track.py
      
    • Nas suas diferentes telas, abra as janelas.

    • Execute o script 2 com o comando:

      python3 /path/to/next_focus.py
      

    O foco deve mudar para a próxima tela. Se a tela atual é a última da fila, o foco muda para a primeira tela.

  5. Se tudo funcionar bem, adicione o script 1 a Startup Applications: Dash > Aplicativos de inicialização > Adicione o comando:

    python3 /path/to/focus_track.py
    

    e adicione o script 2 a um atalho de teclado: escolha: Configurações do sistema > "Teclado" > "Atalhos" > "Atalhos personalizados". Clique no botão "+" e adicione o comando:

    python3 /path/to/next_focus.py
    

    para uma tecla de atalho do seu gosto.

Notas

  • Como o script de plano de fundo mantém o foco do histórico , para funcionamento imediato, ele deve começar de preferência antes de começar a funcionar no computador, por exemplo no login (usando aplicativos de inicialização).
  • O script presume que as telas estão configuradas da esquerda para a direita, sem sobreposição. Seu alinhamento vertical é irrelevante, no entanto.
  • Para "economizar combustível" e tornar a carga do script pequena demais, o script atualiza o histórico de foco (apenas) uma vez por segundo. Uma janela é, portanto, definida como focalizada se tiver foco pelo menos entre 0,5 e 1 segundo.
  • Embora eu tenha testado em uma configuração de duas telas, ele deve (e tenho certeza que funciona) em uma configuração com 3 (+) telas.



Explicação:

O que é preciso

Para mudar o foco de uma tela para outra, é necessário determinar qual é a janela mais frontal por tela . A questão principal é, no entanto, que as janelas, distribuídas em várias telas, são, na verdade, todas em uma e a mesma pilha e, portanto, ordenadas em uma única e mesma sucessão (z-wise). As ferramentas que temos ( wmctrl , xdotool , xprop etc.) no melhor dos casos só podem determinar a janela atualmente ativa . Eles não nos dão nenhuma informação sobre a ordem das janelas nas outras telas, já que as janelas estão abaixo da janela ativa .

Portanto, à primeira vista, parece bastante impossível mudar o foco de uma tela para outra.
No entanto:

Como obter as informações

Com uma solução alternativa, há uma fuga: se fizermos um script de plano de fundo acompanhar a janela focalizada no momento e manter um registro de histórico de alterações (enquanto a janela existir), na verdade conclua qual é a ordem z das janelas atualmente abertas. Se também rastrearmos sua geometria e posição, temos todas as informações de que precisamos.

Um exemplo:
Atualmente, temos cinco janelas: A, B, C, D, E. Se o foco deles mudar através de D, E, A, C, B, sabemos que a ordem z das janelas é: B, C, A, E, D (frente para trás)

Juntamente com suas posições (x-wise) e os dados da tela (a resolução x das telas), temos todas as informações de que precisamos. Para mudar o foco para a próxima tela, basta procurar a primeira janela, localizada na próxima tela.

    
por Jacob Vlijm 31.10.2015 / 07:24