Posso minimizar uma janela em uma caixa no Unity?

17

No 4Dwm do Irix, havia a capacidade de minimizar as janelas em uma caixa (ao contrário da barra de tarefas usada pelos gerenciadores de janelas modernos). Eu já vi isso também em um HPUX antigo.

Veja o quadrado "console" na imagem vinculada:

insira a descrição da imagem aqui

É possível realizar no Ubuntu, com um plug-in ou talvez algum gerenciador de janelas que não seja o Unity?

Artium
fonte
Pergunta estranha, mas interessante :) Eu poderia pensar em algo assim. O ícone importaria ou poderia ser genérico? Como se comporta? como um ícone na área de trabalho ou uma "janela" mínima.
26630 Jacob Vlijm
@JacobVlijm O ícone não é genérico. Cada aplicativo possui seu próprio ícone como os ícones das janelas minimizadas no Unity)
Artium
Também poderia ser feito no Unity, mas a janela seria iconizada na área de trabalho (com o ícone do aplicativo correspondente e o nome da janela). Você gostaria de um tiro? (seria um interessante, mas desafiando trabalho, melhor perguntar antes de eu começar :))
Jacob Vlijm
1
Sim, isso pode ser útil para mim. Eu tenho que trabalhar com muitas janelas abertas e essa maneira de organizá-las é melhor na minha opinião. Eu não sei nada sobre o Unity, então só posso ajudar com os testes.
Artium

Respostas:

18

Para minha surpresa, ele funciona muito bem, desde que você não tenha muitas outras coisas na área de trabalho .

Eu trabalhei com ele por um tempo, e parece uma alternativa agradável , estranhamente estranha, mas suficiente para alternar frequentemente no espaço de trabalho. Atualizando por sua simplicidade.

Na prática

A solução é praticamente o que você descreve:

  • Pressionar uma combinação de teclas "encaixotará" a janela na área de trabalho, a partir de uma janela:

    insira a descrição da imagem aqui

    em um ícone, com a aparência do aplicativo:

    insira a descrição da imagem aqui

  • Clique duas vezes no ícone e a janela aparecerá novamente e o ícone desaparecerá.

Como funciona

A história curta (explicação):

  • Ao pressionar a tecla de atalho, o script é chamado com o argumento box:

    windowbox box
    
  • O script então:

    • lê o ID da janela da frente
    • verifica se é uma janela "normal" (você não deseja remover o mapa da área de trabalho, por exemplo)
    • Procura o nome do processo do aplicativo, que possui a janela.
    • Procura o ícone correspondente no .desktoparquivo do aplicativo correspondente em/usr/share/applications
    • cria um .desktoparquivo com nome exclusivo , com uma Exec=linha que chama o script (quando clicou duas vezes) com o argumento show:

      windowbox show
      

O .desktoparquivo adicionará vários argumentos adicionais, como o ID da janela, o nome (arquivo-) do .desktoparquivo.

Subseqüentemente:

  • O .desktoparquivo é então executado, para torná-lo um objeto clicável duas vezes.

  • Quando o .desktoparquivo é clicado duas vezes, a janela é (re) mapeada e o .desktoparquivo é removido da área de trabalho.

Como configurar

  1. Como praticamente sempre, quando você quer brincar com o Windows, o script precisa de ambos wmctrle xdotool:

    sudo apt-get install xdotool wmctrl
    
  2. Crie o diretório ~/bin( ~significa o diretório inicial)
  3. Copie o script abaixo em um arquivo vazio, salve-o como windowbox(sem extensão) em ~/bin.

    #!/usr/bin/env python3
    import subprocess
    import sys
    import os
    
    # --- On Unity, there is a (y-wise) deviation in window placement
    # set to zero for other window managers
    deviation = 28
    # ---
    
    args = sys.argv[1:]
    
    get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()
    
    def find_dtop():
        # get the localized path to the Desktop folder
        home = os.environ["HOME"]
        dr_file = home+"/.config/user-dirs.dirs"
        return [home+"/"+ l.split("/")[-1].strip() \
                for l in open(dr_file).readlines() \
                if l.startswith("XDG_DESKTOP_DIR=")][0].replace('"', "")
    
    def check_windowtype(w_id):
        # check the type of window; only unmap "NORMAL" windows
        return "_NET_WM_WINDOW_TYPE_NORMAL" in get(["xprop", "-id", w_id])
    
    def get_process(w_id):
        # get the name of the process, owning the window and window x/y position
        w_list = get(["wmctrl", "-lpG"]).splitlines()
        pid = [l for l in w_list if w_id in l][0].split()
        proc = get(["ps", "-p", pid[2], "-o", "comm="])
        xy = (" ").join(pid[3:5])
        return (proc, xy)
    
    def read_f(f, string, proc):
        # search for a possible match in a targeted .desktop file
        try:
            with open(f) as read:
                for l in read:
                    if all([l.startswith(string), proc in l]):
                        in_f = True
                        break
                    else:
                        in_f = False
        except:
            in_f = False
        return in_f
    
    def get_icon(proc, w_name):
        # search appropriate icon in /usr/share/applications
        exceptions = [item for item in [
            ["soffice", "libreoffice-main"],
            ["gnome-terminal", "utilities-terminal"],
            ["nautilus", "folder"],
            ] if item[0] in proc]
        if exceptions:
            if exceptions == [["soffice", "libreoffice-main"]]:
                loffice = [
                    ["Calc", "libreoffice-calc"],
                    ["Writer", "libreoffice-writer"],
                    ["Base", "libreoffice-base"],
                    ["Draw", "libreoffice-draw"],
                    ["Impress", "libreoffice-impress"],
                    ]
                match = [m[1] for m in loffice if m[0] in w_name]
                if match:
                    return match[0]
                else:
                    return exceptions[0][1]
            else:      
                return exceptions[0][1]
        else:
            default = "/usr/share/applications"
            dtfiles = [default+"/"+f for f in os.listdir(default)]
            for f in dtfiles:
                if read_f(f, "Exec=", proc) == True:   
                    for l in open(f).readlines():
                        if l.startswith("Icon="):
                            icon = l.replace("Icon=", "").strip()
                            print(f)
                            break
                    break
            return icon
    
    def create_name():
        # create unique (file-) name for boxed window
        n = 1
        while True:
            name = dtop+"/"+"boxed_"+str(n)+".desktop"
            if os.path.exists(name):
                n += 1
            else:
                break
        return name
    
    def convert_wid(w_id):
        # convert window- id, xdotool format, into wmctrl format
        w_id = hex(int(w_id))
        return w_id[:2]+(10-len(w_id))*"0"+w_id[2:]
    
    def create_icon(w_id, w_name, icon, pos):
        # create the launcher, representing the boxed window
        boxedwindow = create_name()
        f_content =[
                "[Desktop Entry]",
                "Name=[WINDOW] "+w_name,
                "Exec=windowbox show "+w_id+" '"+boxedwindow+"' "+pos,
                "Icon="+icon,
                "Type=Application",
                ]
        if icon == "generic":
            f_content.pop(3)
        with open(boxedwindow, "wt") as boxed:
            for l in f_content:
                boxed.write(l+"\n")
        command = "chmod +x "+"'"+boxedwindow+"'"
        subprocess.call(["/bin/bash", "-c", command])
    
    if args[0] == "box":
        dtop = find_dtop()
        w_id = convert_wid(get(["xdotool", "getactivewindow"]))
        w_name = get(["xdotool", "getwindowname", w_id])
        if check_windowtype(w_id) == True:
            procdata = get_process(w_id)
            procname = procdata[0]
            icon = get_icon(procname, w_name); icon = icon if icon != None else "generic"
            create_icon(w_id, w_name, icon, procdata[1])
            subprocess.call(["xdotool", "windowunmap", w_id])
    
    elif args[0] == "show":
        w_id = args[1]
        subprocess.call(["xdotool", "windowmap", w_id])    
        subprocess.call(["xdotool", "windowmove", "--sync", w_id, args[3], str(int(args[4])-deviation)])
        os.remove(args[2])
  4. Tornar o script executável

  5. Para fazer com que o diretório recém-criado "apareça" $PATH, efetue logout / in ou execute source ~/.profile(a partir de uma janela do terminal)
  6. Teste - execute o script a partir de uma janela de terminal pelo comando:

    windowbox box
    

    A janela deve desaparecer, a janela "em caixa" deve aparecer na sua área de trabalho.

  7. Se tudo funcionar bem, adicione o seguinte comando a uma tecla de atalho: escolha o ícone de roda dentada no canto superior direito da tela:

    Ícone de engrenagem

  8. Vá para System SettingsKeyboardShortcutsCustom Shortcuts. Clique no +e adicione o comando:

    windowbox box
    

Isso deve resolver.

Nota importante

O script usa xdotool's windowunmappara tornar a janela invisível. A "caixa" (ícone) criada na área de trabalho é o único "portão" da janela oculta. Em outras palavras: não remova os arquivos da área de trabalho manualmente. A janela será perdida para sempre se você o fizer.

Trabalho a fazer [editar 20-12: concluído ]

O script ainda pode usar algum refinamento:

  • A geometria da janela não é restaurada por definição. Pode ser corrigido muito bem, mas pensei em mostrar o primeiro resultado.
  • Na maioria dos casos, a janela em caixa tem seu ícone correto. A função get_process(w_id)pode usar algumas melhorias, no entanto. Se o processo não for encontrado como um comando /usr/share/applications, o arquivo terá um ícone genérico.

Atribuir aos ícones da janela em caixas um tamanho diferente dos outros ícones

O script nomeia sempre os.desktop arquivos criados , etc, dependendo do nome "disponível" no momento da criação (nomes de arquivos, não o nome exibido). boxed_1.desktopboxed_2.desktop

Você pode redimensionar os arquivos (em geral) clicando com o botão direito do mouse> tamanho do ícone. A boa notícia é que, se você remover o arquivo e recriá-lo, o tamanho será lembrado. Mesmo se você criar o arquivo novamente após uma reinicialização. Isso significa que, se você redimensionadas as janelas caixas (por exemplo) 1-5, eles vão sempre têm o mesmo tamanho quando você (o roteiro) criá-los novamente!

insira a descrição da imagem aqui

Jacob Vlijm
fonte
2
Não consigo resistir a mim mesma sem deixar um comentário, resposta muito legal de você :)
Ravan
Agradável! Alguns comentários: 1. Substituí a linha dtop = "/home/jacob/Bureaublad"por um caminho para minha área de trabalho (dtop = "/home/" + user + "/Desktop" ) 2. Restaurar com um clique duplo não funcionou. Suspeito que isso source ~/.profilenão seja suficiente, faça logon / out imediatamente para testar isso. 3. Na unidade, é possível redimensionar os ícones manualmente (clique com o botão direito do mouse -> redimensionar ícone), é possível adicionar algum parâmetro f_contentpara definir o tamanho do ícone?
Artium
4
Quando comecei a ler o primeiro parágrafo desta resposta, sabia que haveria um ícone laranja na parte inferior! ;-): P
Fabby
1
Oi @Artium Atualizei o script, ele tem algumas melhorias importantes agora, incluindo uma melhor descoberta de ícones e restauração de geometria, divirta-se!
Jacob Vlijm
1
@ Artium eu sei, mas tente o do script, é o ícone de pasta usual, semelhante à sua imagem. provavelmente apenas um link para o mesmo ícone.
Jacob Vlijm
7

Você pode usar o fvwm para fazer isso.

  1. Instale o fvwm:

    sudo apt-get update
    sudo apt-get install fvwm
    
  2. Encontre um que use a função iconify - existem vários aqui: http://www.jmcunx.com/fvwm_theme.html Vários se parecem com a captura de tela que você mostra.

  3. Copie o texto do tema, navegue até ~/.fvwm/(mostrar os arquivos ocultos primeiro) e crie um arquivo.fvwm2rc

  4. Abra esse arquivo em um editor de texto (como o gedit) e cole o texto do tema nele.

  5. Reinicie o computador e selecione fvwm e faça o login.

insira a descrição da imagem aqui

Mateo
fonte