Czy mogę zminimalizować okno do pudełka w Unity?

17

W 4Dwm Irixa była możliwość zminimalizowania okien do pudełka (w przeciwieństwie do paska zadań używanego przez współczesnych menedżerów okien). Widziałem to także na starym HPUX.

Zobacz kwadrat „konsoli” w połączonym obrazie:

wprowadź opis zdjęcia tutaj

Czy można to osiągnąć na Ubuntu, albo za pomocą wtyczki, a może menedżera okien innego niż Unity?

Artium
źródło
Dziwne, ale ciekawe pytanie :) Mógłbym wymyślić coś takiego. Czy ikona miałaby znaczenie, czy może być ogólna? Jak się zachowuje? jak ikona na pulpicie lub minimalne „okno”.
Jacob Vlijm,
@JacobVlijm Ikona nie jest ogólna. Każda aplikacja ma własną ikonę jako ikony zminimalizowanych okien w Unity)
Artium
Można to również zrobić w ramach Unity, ale okno będzie ikonizowane na pulpicie (z odpowiednią ikoną aplikacji i nazwą okna). Czy chciałbyś spróbować? (byłaby interesująca, ale wymagająca praca, lepiej zapytaj zanim zacznę :))
Jacob Vlijm
1
Tak, to może mi pomóc. Muszę pracować z wieloma otwartymi oknami i moim zdaniem ten sposób ich organizowania jest lepszy. Nic nie wiem o Jedności, więc mogę pomóc tylko przy testowaniu.
Artium,

Odpowiedzi:

18

Ku memu zdziwieniu działa całkiem nieźle, o ile nie ma zbyt wielu innych rzeczy na pulpicie .

Pracowałem z tym przez chwilę i wydaje się to dziwną, ale dziwnie wystarczająco dobrą alternatywą dla częstych przełączników obszaru roboczego. Odświeżający ze względu na swoją prostotę.

W praktyce

Rozwiązanie jest właściwie tym, co opisujesz:

  • Naciśnięcie kombinacji klawiszy spowoduje „wstawienie” okna na pulpicie z okna:

    wprowadź opis zdjęcia tutaj

    w ikonę z wyglądem aplikacji:

    wprowadź opis zdjęcia tutaj

  • Kliknij dwukrotnie ikonę, okno pojawi się ponownie, a ikona zniknie.

Jak to działa

Krótka historia (wyjaśnienie):

  • Po naciśnięciu klawisza skrótu skrypt jest wywoływany z argumentem box:

    windowbox box
    
  • Skrypt następnie:

    • odczytuje identyfikator okna z przodu
    • sprawdza, czy jest to „normalne” okno (na przykład nie chcesz odmapować pulpitu)
    • Wyszukuje nazwę procesu aplikacji, która jest właścicielem okna.
    • Wyszukuje odpowiednią ikonę w .desktoppliku odpowiedniej aplikacji w/usr/share/applications
    • tworzy .desktopplik o unikalnej nazwie z Exec=linią, która wywołuje skrypt (po dwukrotnym kliknięciu) z argumentem show:

      windowbox show
      

.desktopPlik będzie dodać kilka dodatkowych argumentów argumentów, takich jak identyfikator okna, The (Plik-) nazwę.desktop pliku.

Następnie:

  • .desktopPlik jest następnie wykonywalny, aby to podwójnie kliknąć obiekt.

  • Po .desktopdwukrotnym kliknięciu pliku okno jest (ponownie) mapowane, .desktopplik jest usuwany z pulpitu.

Jak skonfigurować

  1. Jak praktycznie zawsze, kiedy chcesz się bawić z okien, skrypt potrzebuje zarówno wmctrla xdotool:

    sudo apt-get install xdotool wmctrl
    
  2. Utwórz katalog ~/bin( ~oznacza katalog domowy)
  3. Skopiuj poniższy skrypt do pustego pliku, zapisz go jako windowbox(bez rozszerzenia) w ~/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. Spraw, by skrypt był wykonywalny

  5. Aby nowo utworzony katalog „wyskakiwał” $PATH, wyloguj się / zaloguj lub uruchom source ~/.profile(z okna terminala)
  6. Testuj - uruchom skrypt z okna terminala za pomocą polecenia:

    windowbox box
    

    Okno powinno zniknąć, okno „zapakowane” powinno pojawić się na pulpicie.

  7. Jeśli wszystko działa poprawnie, dodaj następujące polecenie do klawisza skrótu: wybierz ikonę koła zębatego w prawym górnym rogu ekranu:

    Ikona zębatki

  8. Przejdź do System SettingsKeyboardShortcutsCustom Shortcuts. Kliknij +i dodaj polecenie:

    windowbox box
    

Że należy to zrobić.

Ważna uwaga

Skrypt używa xdotools, windowunmapaby okno było niewidoczne. Utworzone „pudełko” (ikona) na pulpicie jest jedyną „bramą” do ukrytego okna. Innymi słowy: nie usuwaj plików pulpitu ręcznie. Jeśli tak zrobisz, okno zostanie utracone na dobre.

Pracuj do zrobienia [edytuj 20-12: gotowe ]

Skrypt nadal może zawierać pewne udoskonalenia:

  • Geometria okna nie jest przywracana z definicji. Można to naprawić bardzo dobrze, ale pomyślałem, że pokażę ci pierwszy wynik.
  • W większości przypadków okno w ramce ma poprawną ikonę. Funkcja get_process(w_id)mogłaby jednak nieco poprawić. Jeśli proces nie zostanie znaleziony jako polecenie w /usr/share/applications, plik ma ogólną ikonę.

Nadawanie ikonom okna w pudełku innego rozmiaru niż inne ikony

Nazwy skryptów utworzone .desktoppliki zawsze boxed_1.desktop , boxed_2.desktopetc, w zależności od nazwy „dostępne” w momencie stworzenia (nazwy plików, nie wyświetlana nazwa).

Możesz zmienić rozmiar plików (ogólnie), klikając prawym przyciskiem myszy> rozmiar ikony. Dobrą wiadomością jest to, że jeśli usuniesz plik i utworzysz go ponownie, rozmiar zostanie zapamiętany. Nawet jeśli plik zostanie utworzony ponownie po ponownym uruchomieniu. Oznacza to, że jeśli kiedykolwiek zmienisz rozmiar pudełkowanych okien (np. 1-5), będą one zawsze miały ten sam rozmiar, kiedy Ty (skrypt) utworzysz je ponownie!

wprowadź opis zdjęcia tutaj

Jacob Vlijm
źródło
2
Nie mogę się oprzeć bez komentarza, bardzo ładna odpowiedź od ciebie :)
Ravan
Ładny! Kilka komentarzy: 1. Zamieniłem wiersz dtop = "/home/jacob/Bureaublad"na ścieżkę do pulpitu ( dtop = "/home/" + user + "/Desktop") 2. Przywracanie przez podwójne kliknięcie nie działało. Podejrzewam, że source ~/.profileto za mało, natychmiast się wyloguje / wyloguje, aby przetestować ten test. 3. W jedności możliwe jest ręczne zmienianie rozmiaru ikon (prawy przycisk myszy -> zmiana rozmiaru ikony), czy można dodać jakiś parametr, f_contentaby ustawić rozmiar ikony?
Artium,
4
Kiedy zacząłem czytać pierwszy akapit tej odpowiedzi, po prostu wiedziałem, że na dole będzie pomarańczowa ikona! ;-): P
Fabby
1
Cześć @ Artium Zaktualizowałem skrypt, teraz ma kilka ważnych ulepszeń, w tym lepsze wyszukiwanie ikon i przywracanie geometrii, baw się dobrze!
Jacob Vlijm,
1
@ Artium Wiem, ale wypróbuj ten ze skryptu, jest to zwykła ikona folderu, podobna do twojego obrazu. prawdopodobnie tylko link do tej samej ikony.
Jacob Vlijm,
7

Aby to zrobić, możesz użyć programu fvwm .

  1. Zainstaluj fvwm:

    sudo apt-get update
    sudo apt-get install fvwm
    
  2. Znajdź je, które korzystają z funkcji iconify - jest ich tutaj kilka: http://www.jmcunx.com/fvwm_theme.html Kilka z nich wygląda jak zrzut ekranu.

  3. Skopiuj tekst motywu, a następnie przejdź do ~/.fvwm/(najpierw pokaż ukryte pliki), a następnie utwórz plik.fvwm2rc

  4. Otwórz ten plik w edytorze tekstu (np. Gedit) i wklej do niego tekst motywu.

  5. Uruchom ponownie komputer, wybierz fvwm i zaloguj się.

wprowadź opis zdjęcia tutaj

Mateo
źródło