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
-
Os scripts precisam de
wmctrl
para serem instaladossudo apt-get install wmctrl
- 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. - Copie o script 2 em um arquivo vazio, salve-o como (exatamente)
next_focus.py
em um único diretório do script 1 . -
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.
-
-
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.