Posso ter uma janela mostrando pequena visualização ao vivo de outro espaço de trabalho?

29

É possível espelhar uma seção ativa de um espaço de trabalho para que fique visível no espaço de trabalho atual como uma janela que pode ser movida?

No outro dia, eu tinha uma VM do Windows 10 em execução no meu host Ubuntu 16.04 que demorou muito tempo para concluir a atualização. Fiquei checando seu progresso via Expo ( Super+ S) no Ubuntu. Isso me fez pensar que esse problema provavelmente já foi resolvido, já que ferramentas como o gravador de tela simples podem ser configuradas para gravar apenas uma parte da tela. No entanto, não conheço a terminologia adequada a ser usada na minha pesquisa no Google.

Gostaria de ver a captura de tela de 300 x 150 abaixo na forma de uma janela flutuante (com atualizações ao vivo) no canto superior direito de qualquer área de trabalho que estiver atual.

insira a descrição da imagem aqui

AnthonyK
fonte
1
@serg aqui um novo projeto para você
Rinzwind
@Rinzwind, você deve odiar Serg ... Nós (os dois) já vimos algo assim antes, não conseguimos.
precisa saber é o seguinte
1
Eu até coloquei uma recompensa nele desta vez: =) chegar a ele @JacobVlijm
Rinzwind 5/16
Seria um recurso interessante :) Não ajudará no caso da VM, mas existe uma solução para aplicativos de terminal: usando o Konsole. Possui duas opções úteis: "notificar sobre atividade" e "notificar sobre silêncio". O primeiro enviará uma notificação quando uma nova linha for exibida no terminal (útil ao usar tail -F file | grep patternnos logs para ser avisado de alguns eventos); o segundo enviará uma notificação quando houver algum tempo desde a última linha escrita (útil para saber quando uma construção terminou).
Kik6
@Rinzwind caramba, ele está indo para o trabalho ...
Jacob Vlijm

Respostas:

26

EDITAR

(Nova resposta)

FEITO.
A resposta abaixo está agora disponível de forma polida, como um indicador, como um ppa para Trusty, Xenial, Yakkety e Zesty:

sudo apt-add-repository ppa:vlijm/windowspy
sudo apt-get update
sudo apt-get install windowspy

O indicador (incluindo a janela de visualização) agora está com pouco suco. As opções incluem uma janela de configurações, configuração do tamanho / cor da borda da janela, tamanho da janela.

insira a descrição da imagem aqui

Enquanto isso, achei útil ficar de olho na janela da UA; veja se há alguma mensagem :)


RESPOSTA ANTIGA

( primeiro segundo conceito aproximado)

Ter uma representação minimizada de uma janela em outro espaço de trabalho

Para minha própria (grande) surpresa, isso pode ser efetivamente feito, seja com truques e enganos; ter uma representação atualizada de uma janela em outro espaço de trabalho. Não é adequado para assistir a um filme, definitivamente bom o suficiente para ficar de olho em uma janela em outro lugar (exemplo: janela da minha placa de TV):

Como funciona na prática

  1. Com a janela na frente, pressione uma tecla de atalho:

    insira a descrição da imagem aqui

    (a janela será minimizada)

  2. Vá para outro espaço de trabalho, pressione a tecla de atalho novamente, uma pequena representação da janela será exibida, atualizada a cada 4 segundos:

    insira a descrição da imagem aqui

    A janela sempre aparece em cima de outras janelas. Sendo assim, a janela tem 300 px (largura), mas pode ser definida para qualquer tamanho.

  3. Para finalizar, pressione (novamente) a tecla de atalho. A pequena janela será fechada, você passará para a janela de exibição da janela original, que aparecerá novamente, sem minimização.

Os scripts

  1. O script de controle

    #!/usr/bin/env python3
    import subprocess
    import os
    import sys
    import time
    
    # paths
    imagepath = os.path.join(os.environ["HOME"], ".showcase")
    wfile = os.path.join(imagepath, "currentwindow")
    vpfile = os.path.join(imagepath, "last_vp")
    # setup path
    if not os.path.exists(imagepath):
        os.mkdir(imagepath)
    
    def get(command):
        try:
            return subprocess.check_output(command).decode("utf-8").strip()
        except subprocess.CalledProcessError:
            pass
    
    def get_vp():
        open(vpfile, "wt").write(get(["wmctrl", "-d"]).split()[5])
    
    def run(command):
        subprocess.Popen(command)
    
    def convert_tohex(widxd):
        return widxd[:2]+((10-len(widxd))*"0")+widxd[2:]
    
    def check_windowtype(wid):
        check = get(["xprop", "-id", wid])
        return not any([s in check for s in [
            "_NET_WM_WINDOW_TYPE_DOCK",
            "_NET_WM_WINDOW_TYPE_DESKTOP"]])
    
    def edit_winprops(wid, convert=True):
        run(["xdotool", "windowminimize", wid])
        if convert:
            widxd = convert_tohex(hex(int(wid)))
        else:
            widxd = wid
        run(["wmctrl", "-i", "-r", widxd, "-b", "add,sticky"])
        get_vp()
        open(os.path.join(imagepath, "currentwindow"), "wt").write(widxd)
    
    def initiate_min():
        # if not, minmize window, write the file
        wid = get(["xdotool", "getactivewindow"])
        if check_windowtype(wid):
            edit_winprops(wid)
        else:
            pidinfo = [l.split() for l in wlist.splitlines()]
            match = [l for l in pidinfo if all([
                get(["ps", "-p", l[2], "-o", "comm="]) == "VirtualBox",
                not "Manager" in l])]
            if match:
                edit_winprops(match[0][0], convert=False)
    
    # windowlist
    wlist = get(["wmctrl", "-lp"])
    
    if "Window preview" in wlist:
        # kill the miniwindow
        pid = get(["pgrep", "-f", "showmin"])
        run(["kill", pid])
        window = open(wfile).read().strip()
        viewport = open(vpfile).read().strip()
        run(["wmctrl", "-o", viewport])
        time.sleep(0.3)
        run(["wmctrl", "-i", "-r", window, "-b", "remove,sticky"])
        run(["wmctrl", "-ia", window])
        os.remove(wfile)
    
    else:
        # check if windowfile exists
        wfileexists = os.path.exists(wfile)
        if wfileexists:
            # if file exists, try to run miniwindow
            window = open(wfile).read().strip()
            if window in wlist:
                # if the window exists, run!
                run(["showmin", window])
            else:
                # if not, minmize window, write the file
                initiate_min()
        else:
            # if not, minmize window, write the file
            initiate_min()
  2. A representação da janela

    #!/usr/bin/env python3
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk, GObject
    from PIL import Image
    import os
    import subprocess
    import time
    from threading import Thread
    import sys
    
    wid = sys.argv[1]
    xsize = 300
    
    imagepath = os.path.join(os.environ["HOME"], ".showcase")
    if not os.path.exists(imagepath):
        os.mkdir(imagepath)
    img_in = os.path.join(imagepath, "image.png")
    resized = os.path.join(imagepath, "resized.png")
    
    def get_img():
        subprocess.Popen([
            "import", "-window", wid, "-resize", str(xsize),  resized
            ])
    
    get_img()
    
    class Splash(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="Window preview")
            maingrid = Gtk.Grid()
            self.add(maingrid)
            self.image = Gtk.Image()
            # set the path to the image below
            self.resized = resized
            self.image.set_from_file(self.resized)
            maingrid.attach(self.image, 0, 0, 1, 1)
            maingrid.set_border_width(3)
            self.update = Thread(target=self.update_preview)
            self.update.setDaemon(True)
            self.update.start()
    
        def update_preview(self):
            while True:
                get_img()
                time.sleep(3)
                GObject.idle_add(
                    self.image.set_from_file, self.resized,
                    priority=GObject.PRIORITY_DEFAULT
                    )
    
    def miniwindow():
        window = Splash()
        window.set_decorated(False)
        window.set_resizable(False)
        window.set_keep_above(True)
        window.set_wmclass("ShowCase", "showcase")
        window.connect("destroy", Gtk.main_quit)
        GObject.threads_init()
        window.show_all()
        window.move(70, 50)
        Gtk.main()
    
    miniwindow()

Como usar

  1. Instalar python3-pil, xdotoolewmctrl

    sudo apt-get install xdotool wmctrl python3-pil
    
  2. Criar, se ele ainda não existe, o diretório ~/bin.

  3. Copie o script 1, ele controla o script, como (exatamente) showcase_control(sem extensão) ~/bine torne-o executável .
  4. Copie o script 2, o script da mini-janela, como (exatamente) showmin(sem extensão) ~/bine torne-o executável .
  5. Efetue logout e logon novamente e adicione o seguinte comando a um atalho de sua escolha:

    showcase_control
    

    Escolha: Configurações do sistema> "Teclado"> "Atalhos"> "Atalhos personalizados". Clique no "+" e adicione o comando:

    showcase_control
    

    e deve funcionar!

    • Pressione a tecla uma vez para acessar a janela atual
    • mova para o outro espaço de trabalho em que você gostaria da mini-janela
    • Pressione novamente para mostrar a mini janela
    • Pressione novamente para voltar para a área de trabalho original, (automaticamente) des minimize a janela original e feche a minifone.

Desvantagens?

  • A configuração, como está atualmente, adiciona algum trabalho ao seu processador. No meu sistema (muito) antigo, no entanto, ele adiciona (em média) appr. 4-5% acho que não percebi de forma alguma .

    Atualização: Acontece que importpode redimensionar a imagem em uma etapa, juntamente com a busca da imagem da janela. Isso significa uma redução substancial na carga do processador. Ao mesmo tempo, o tempo de atualização é mais curto (3 segundos agora), ainda com "custos" mais baixos.

Explicação

  • Meu ponto de partida foi o modo como o OP mencionou que ele queria usar a opção para ficar de olho em uma janela em outro espaço de trabalho, esperando que algo terminasse.
  • Enquanto literalmente ter uma exata (mini) cópia de uma janela para outra área de trabalho parece impossível, nós pode fazer uma imagem de uma janela existente com o import-command, uma vez que temos o id janela. Embora isso funcione em janelas minimizadas ou sem foco, há um problema: a janela precisa estar no espaço de trabalho atual .
  • O truque é, então, temporariamente (enquanto a mini-janela é usada) tornar a janela "pegajosa" (estar praticamente disponível em todos os espaços de trabalho) com wmctrl, mas minimizada ao mesmo tempo.
  • Como tudo é feito automaticamente, a diferença efetivamente é nenhuma, já que também o retorno à janela de visualização inicial "desapega" a janela original e a minimiza, é feita automaticamente.

Em resumo:

  1. Pressionando o atalho uma vez: a janela direcionada fica pegajosa, mas minimizada
  2. Pressionando-o novamente (presumivelmente em outro espaço de trabalho): uma pequena versão mini da janela aparece no canto superior esquerdo, atualizada uma vez a cada quatro segundos.
  3. Pressionando novamente: a mini- janela é fechada, a área de trabalho se move para o espaço de trabalho inicial da janela, a janela é restaurada sem aderência e sem minimização.

Especificamente para o VirtualBox

Quando a janela do VBox está na frente, as teclas de atalho do Ubuntu estão desabilitadas (!), Portanto, o script de controle precisa ser iniciado de outra maneira. Abaixo alguns breves.

Opção 1

Eu editei o script de controle. Agora apenas no caso do VirtualBox:

  • Clique em qualquer lugar da área de trabalho e pressione a tecla de atalho. Depois disso, basta usar a tecla de atalho para mostrar a janela e sair.

    Explicação: O script de controle foi criado para sair se a janela fosse do tipo "área de trabalho", pois você não desejaria minimizar a área de trabalho. Agora, o script primeiro procura possíveis janelas existentes do VirtualBox, para direcionar, se a janela atualmente ativa for a área de trabalho.

opção 2

  • Copie o ícone abaixo (clique com o botão direito do mouse -> salvar como), salve-o como minwinicon.png

    insira a descrição da imagem aqui

  • Copie as linhas abaixo em um arquivo vazio, salve-o como minwin.desktopem ~/.local/share/applications:

    [Desktop Entry]
    Type=Application
    Name=Window Spy
    Exec=showcase_control 
    Icon=/path/to/minwinicon.png
    StartupNotify=false
    

    Você precisaria sair e voltar para o iniciador para "encontrar" o ~/bincaminho local !
    Arraste o ícone para o iniciador para usá-lo.

A segunda solução tem uma desvantagem importante: depois de usá-la no iniciador, ela continuará piscando por alguns segundos, aguardando o aparecimento de uma janela. Durante isso, clicar novamente não terá efeito. Isso pode ser resolvido, conforme descrito aqui , mas incluir isso nesta resposta realmente levaria muito tempo. Se você deseja usar a opção dois, consulte o link.

Jacob Vlijm
fonte
Então, o bom e velho importpode fazê-lo, enquanto a captura de tela do gnomo não pode. Muito, muito interessante. Estou currious o que exatamente é a diferença entre a forma como eles funcionam
Sergiy Kolodyazhnyy
@Serg sim, eu fiquei muito surpreendido, pensei que não poderia ser feito com apenas ferramentas de cozinha :)
Jacob Vlijm
1
@ThatGuy trabalhando nisso :)
Jacob Vlijm
1
@jymbob Obrigado pelo comentário! Eles não têm dúvidas no sistema, mas a questão é se eles estão disponíveis externamente. Se os desenvolvedores não fornecerem uma opção CLI ou uma API de forma alguma, a invasão do código seria um trabalho de uma ordem completamente diferente. Eu adoraria ter a opção embora.
22816 Jacob Vlijm
1
@JacobVlijm Fair point. Possivelmente mais informações aqui stackoverflow.com/questions/18595951/… mas muito acima do meu nível de competência!
jymbob
1

Algo que parece exagero, mas que funciona totalmente para esse fim, é o Open Broadcaster . Na caixa de listagem "Fontes", clique no sinal de mais, selecione "Captura de janela" e siga as instruções para selecionar a janela em que está interessado. Não há sentido em bater um recorde; basta usar a visualização. Está disponível para praticamente qualquer sistema operacional , com instruções para o Ubuntu aqui , que copiei abaixo.

sudo apt-get install ffmpeg
sudo add-apt-repository ppa:obsproject/obs-studio
sudo apt-get update
sudo apt-get install obs-studio

Se você quiser, pode entrar no menu "Visualizar" e ocultar todos os elementos da interface do usuário.

golvok
fonte