Para minha própria surpresa, funciona muito bem, contanto que você não tenha muitas outras coisas na sua área de trabalho .
Eu trabalhei com isso por um tempo, e parece uma alternativa estranha, mas estranhamente legal para frequentar switches do espaço de trabalho. Refrescante por sua simplicidade.
Na prática
A solução é basicamente o que você descreve:
-
Pressionar uma combinação de teclas "marcará" a janela da sua área de trabalho, em uma janela:
emumícone,comaaparênciadoaplicativo:
Cliqueduasvezesnoíconeeajanelaseráexibidanovamenteeoíconedesaparecerá.
Comofunciona
Oconto(explicação):
Aopressionaratecladeatalho,oscriptéchamadocomoargumento
box
:windowboxbox
Oscriptentão:
- lêoiddajaneladaprimeirajanela
- verificaseéumajanela"normal" (você não desejaria desmapear sua área de trabalho, por exemplo)
- pesquisa o nome do processo do aplicativo, possuindo a janela.
- pesquisa o ícone correspondente no arquivo
.desktop
do aplicativo correspondente em/usr/share/applications
-
cria um arquivo
.desktop
com o nome exclusivo, com uma linhaExec=
que chama o script (quando clicado duas vezes) com o argumentoshow
:windowbox show
O arquivo .desktop
adicionará vários argumentos de argumentos adicionais, como o id da janela, o nome (arquivo) do arquivo .desktop
.
Posteriormente:
-
O arquivo
.desktop
é então executado como executável, para torná-lo um objeto que pode ser clicado duas vezes. -
Quando o arquivo
.desktop
é clicado duas vezes, a janela é (re) mapeada, o arquivo.desktop
é removido da sua área de trabalho.
Como configurar
-
Como praticamente sempre, quando você quer brincar com o Windows, o script precisa de ambos
wmctrl
exdotool
:sudo apt-get install xdotool wmctrl
- Crie o diretório
~/bin
(~
significa seu diretório inicial) -
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])
-
Torne o script executável
- Para tornar o diretório recém-criado "pop-up" em
$PATH
, efetue logout / in ou executesource ~/.profile
(a partir de uma janela de terminal) -
Teste- execute o script a partir de uma janela de terminal pelo comando:
windowbox box
A janela deve desaparecer, a janela "boxed" deve aparecer na sua área de trabalho.
-
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:
VáparaConfiguraçõesdoSistema→Teclado→Atalhos→AtalhosPersonalizados.Cliqueno+eadicioneocomando:
windowboxbox
Issodeveserfeito.
Notaimportante
Oscriptusaxdotool
windowunmap
paratornarajanelainvisível.A"caixa" criada (ícone) na sua área de trabalho é o único "portão" para a janela oculta. Em outras palavras: não remova o (s) arquivo (s) da área de trabalho manualmente. A janela será perdida definitivamente se você fizer isso.
Trabalho a fazer [editar 20-12: feito ]
O script ainda poderia usar algum refinamento:
- A geometria da janela não é restaurada por definição. Pode ser consertado muito bem, mas eu pensei em te mostrar o primeiro resultado.
- Na maioria dos casos, a janela na caixa tem seu ícone correto. A função
get_process(w_id)
poderia, no entanto, melhorar. Se o processo não for encontrado como um comando em/usr/share/applications
, o arquivo terá um ícone genérico.
Dar aos ícones de janelas com caixas um tamanho diferente dos outros ícones
O script nomeia os arquivos .desktop
criados sempre boxed_1.desktop
, boxed_2.desktop
etc, dependendo do nome "disponível" no momento da criação (nomes de arquivos, não o nome exibido).
Você pode redimensionar os arquivos (em geral), clicando com o botão direito > 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ê já redimensionou as janelas em caixa (por exemplo, 1-5), elas sempre terão o mesmo tamanho quando você (o script) as criar novamente ! p>