Existe uma maneira de impedir que suas janelas se movam quando um monitor externo está conectado?

9

Então, eu estou usando o Ubuntu 14.10 no meu laptop e ocasionalmente conecto-o na minha TV para uma segunda tela. Minha TV está à esquerda da minha mesa. Quando eu o habilito como monitor externo à esquerda da tela do meu laptop, todas as janelas que estavam na tela do meu laptop passam para a tela da TV. Posso movê-los de volta, mas é realmente irritante ter que fazê-lo sempre, especialmente quando há várias janelas abertas.

TV à esquerda

As janelas não se moverão, no entanto, se eu definir a tela da minha TV à direita da tela do meu laptop (virtualmente). Mas isso é compreensivelmente confuso de usar, pois é o oposto da configuração física. Além disso, não quero mudar minha mesa.

TV à direita

Parece que o Ubuntu ou o servidor de exibição simplesmente assume que o monitor mais à esquerda é o principal e onde todas as janelas devem estar. Existe uma maneira de desativar esse comportamento?

Estive verificando esses fóruns, mas realmente não vi ninguém postar sobre isso. O tópico mais próximo que encontrei foi este, embora não seja exatamente o mesmo problema.

Faça o Ubuntu NÃO mover janelas ao desligar um dos vários monitores

Alguém tem alguma ideia? Por favor, avise-me se você fizer. Obrigado!

K0j0
fonte

Respostas:

2

Não encontrei uma configuração "secreta" para alterar o comportamento do comportamento projetado, ao que parece. Parece mesmo que a tela esquerda é considerada a tela "base".

No entanto, é muito bem possível criar uma solução alternativa, com essencialmente o mesmo resultado. Você pode criar um script que, na ocasião de conectar uma segunda tela, liste todas as janelas. Posteriormente, todas as janelas que são movidas inicialmente para a tela esquerda, voltam para a tela à direita, dentro de um ou dois segundos. O tamanho de todas as janelas será preservado.
É isso que o script abaixo faz.

Duas versões

Você pode restaurar suas janelas organizadas de duas maneiras:

  • Ocasionalmente, com uma tecla de atalho para executar após a segunda tela ser conectada.
  • Automaticamente, executando o script em segundo plano, aguardando a conexão da tela.

Como usar

preparações

  • Instalar wmctrl

    sudo apt-get install wmctrl

  • Procure os nomes das duas telas com a ajuda de xrandr, os nomes das telas estarão logo antes da palavra "conectado".

  • Copiar Qualquer um dos scripts abaixo, na seção head, substitui nessas duas linhas os nomes de tela pelos corretos:

    screen_1 = "LVDS1"     # your main screen (laptop)
    screen_2 = "VGA1"      # secundary screen (on the left)
    

    salve o script como move_windows.py

  • Certifique-se de que, nas configurações de exibição, sua tela secundária esteja à esquerda. As linhas superiores das duas telas precisam estar alinhadas (como na primeira imagem da sua pergunta).

Execute o script
- Se você usar um para executar ocasionalmente, execute-o após a segunda tela estar conectada.

    python3 /path/to/move_windows.py

Convém adicioná-lo a um atalho de teclado, se achar que ele faz o que deve ser feito, escolha: Configurações do sistema> "Teclado"> "Atalhos"> "Atalhos personalizados". Clique no "+" e adicione o comando:

  • Se você usar esse para executar em segundo plano, execute-o também pelo comando:

    python3 /path/to/move_windows.py
    

    Se ele funcionar como você pretendia, adicione-o aos aplicativos de inicialização: Dash> Startup Applications> Add

Testei o script com meu laptop (à direita) e duas telas diferentes (à esquerda). O resultado foi o mesmo.

tela do laptop

insira a descrição da imagem aqui

conectando sem script

insira a descrição da imagem aqui

conectando com o script em execução

insira a descrição da imagem aqui

Depois que o script fez seu trabalho, as janelas serão "deixadas em paz" (é claro), e você poderá organizá-las à sua maneira.

Os scripts

1. Versão "Manual", a ser executada após a conexão da tela

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

#--
screen_2 = "LVDS1"       # replace with your internal screen (right)
screen_2 = "VGA1"        # replace with your external screen (left)
#--

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c",  cmd]).decode("utf-8")

def get_shift(xr_output):
    lines = [l for l in xr_output.splitlines() if " connected" in l][0].split()
    return int([it for it in lines if "x" in it][0].split("x")[0])

def shift_windows(shift):
    w_data = [l.split() for l in get("wmctrl -lG").splitlines()]
    relevant = []
    for w in w_data:
        props = get("xprop -id "+w[0])
        if (int(w[2]) < shift, "_TYPE_NORMAL" in props, "TYPE_DIALOG" in props).count(True) == 2:
            command = "wmctrl -ir "+w[0]+" -e 0,"+(",").join([str(int(w[2])+shift), w[3], w[4], w[5]])
            subprocess.Popen(["/bin/bash", "-c", command])

shift_windows(get_shift(get("xrandr")))

2. Versão automática, para executar em segundo plano

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

#--
screen_2 = "LVDS1"       # replace with your internal screen (right)
screen_2 = "VGA1"        # replace with your external screen (left)
#--

def get(cmd):
    return subprocess.check_output(["/bin/bash", "-c",  cmd]).decode("utf-8")

def get_shift(xr_output):
    lines = [l for l in xr_output.splitlines() if " connected" in l][0].split()
    return int([it for it in lines if "x" in it][0].split("x")[0])

def shift_windows(shift):
    w_data = [l.split() for l in get("wmctrl -lG").splitlines()]
    relevant = []
    for w in w_data:
        props = get("xprop -id "+w[0])
        if (int(w[2]) < shift, "_TYPE_NORMAL" in props, "TYPE_DIALOG" in props).count(True) == 2:
            command = "wmctrl -ir "+w[0]+" -e 0,"+(",").join([str(int(w[2])+shift), w[3], w[4], w[5]])
            subprocess.Popen(["/bin/bash", "-c", command])

while True:
    try:
        screen_info1 = get("xrandr")
        time.sleep(5)
        screen_info2 = get("xrandr")
        check = screen_2+" connected"
        if (check in screen_info1, check in screen_info2) == (False, True):
            time.sleep(5)
            shift_windows(get_shift(screen_info2))
    except:
        pass
Jacob Vlijm
fonte
Habilidades seriamente doentes, Jacob!
don.joey
@ K0j0 Você conseguiu?
Jacob Vlijm
@JacobVlijm Não tenho certeza se a pesquisa a cada 5 segundos é a melhor solução (não há possibilidade orientada a eventos?). De qualquer forma, se você estiver interessado em transformar esse script em um indicador do Unity ( como estes aqui ), entre em contato.
Peterino
@ Peterino Se existir um sinal orientado a eventos, seria minha primeira escolha. Ao mesmo tempo: se um script em segundo plano é bem escrito, sua carga adicional deve (e pode) ser praticamente nenhuma, e eu sempre testo meus scripts especificamente nisso. Eu mesmo executo um número variável de scripts em segundo plano. Mesmo todos juntos não têm nenhum efeito perceptível. Lembre-se de que vários loops estão sendo executados por definição em seu sistema. Sobre a sugestão do indicador Unity: Estou definitivamente interessado em aprender como criar um indicador, para esta ou outra situação :).
27615 Jacob Vlijm
@JacobVlijm Parece que o posicionamento automático do Windows acontecerá automaticamente a partir de um dos próximos lançamentos do Ubuntu ("trabalho em andamento"), de acordo com uma fonte da Canonical . Provavelmente não vale a pena investir nos meses restantes no lançamento atual. Mas vou verificar com os desenvolvedores do Mir no IRC # ubuntu-mir @ freenode.
Peterino 27/11/2015