Posso ridurre a icona una finestra in una casella su Unity?


17

Sul 4Dwm di Irix, c'era la possibilità di minimizzare le finestre in una scatola (contrariamente alla barra delle attività utilizzata dai moderni gestori di finestre). L'ho visto anche su un vecchio HPUX.

Vedi il riquadro "console" nell'immagine collegata:

inserisci qui la descrizione dell'immagine

È possibile realizzare su Ubuntu, con un plugin o forse un gestore di finestre diverso da Unity?


Domanda strana ma interessante :) Potrei pensare a qualcosa del genere. L'icona avrebbe importanza o potrebbe essere generica? Come si comporta? come un'icona sul desktop o una "finestra" minima.
Jacob Vlijm,

@JacobVlijm L'icona non è generica. Ogni applicazione ha la propria icona come icona delle finestre ridotte a icona in Unity)
Artium

Potrebbe essere eseguito anche in Unity, ma la finestra sarebbe iconizzata sul desktop (con l'icona dell'applicazione corrispondente e il nome della finestra). Ti piacerebbe uno scatto? (sarebbe un lavoro interessante, ma stimolante, meglio chiedere prima di iniziare :))
Jacob Vlijm

1
Sì, questo può essere utile per me. Devo lavorare con molte finestre aperte e questo modo di organizzarle è migliore secondo me. Conosco nulla su Unity, quindi posso aiutare solo con i test.
Artium,

Risposte:


18

Con mia sorpresa, funziona abbastanza bene, purché non ci siano troppe altre cose sul desktop .

Ci ho lavorato per un po ', e sembra un'alternativa strana, ma stranamente piacevole ai frequenti cambi di area di lavoro. Rinfrescante per la sua semplicità.

In pratica

La soluzione è praticamente ciò che descrivi:

  • Premendo una combinazione di tasti si "box" la finestra sul desktop, da una finestra:

    inserisci qui la descrizione dell'immagine

    in un'icona, con l'aspetto dell'applicazione:

    inserisci qui la descrizione dell'immagine

  • Fare doppio clic sull'icona e la finestra riapparirà e l'icona scomparirà.

Come funziona

La breve storia (spiegazione):

  • Quando si preme il tasto di scelta rapida, lo script viene chiamato con l'argomento box:

    windowbox box
    
  • La sceneggiatura quindi:

    • legge l'ID della finestra più in primo piano
    • controlla se si tratta di una finestra "normale" (ad esempio non vorrai annullare il mapping del desktop)
    • Cerca il nome del processo dell'applicazione, possedendo la finestra.
    • Cerca l'icona corrispondente nel .desktopfile dell'applicazione corrispondente in/usr/share/applications
    • crea un .desktopfile con un nome univoco , con una Exec=linea che chiama lo script (quando si fa doppio clic) con l'argomento show:

      windowbox show
      

Il .desktopfile aggiungerà una serie di argomenti aggiuntivi, come l'id della finestra, il nome (file) del .desktopfile.

Successivamente:

  • Il .desktopfile viene quindi reso eseguibile, per renderlo un oggetto a doppio clic.

  • Quando si .desktopfa doppio clic sul file, la finestra viene (ri) mappata, il .desktopfile viene rimosso dal desktop.

Come impostare

  1. Come sempre, quando vuoi giocare con Windows, lo script ha bisogno di entrambi wmctrle xdotool:

    sudo apt-get install xdotool wmctrl
    
  2. Crea la directory ~/bin( ~sta per home directory)
  3. Copia lo script seguente in un file vuoto, salvalo come windowbox(senza estensione) in ~/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. Rendi eseguibile lo script

  5. Per rendere "pop-up" la directory appena creata $PATH, disconnettersi / accedere o eseguire source ~/.profile(da una finestra del terminale)
  6. Prova- esegui lo script da una finestra terminale con il comando:

    windowbox box
    

    La finestra dovrebbe scomparire, la finestra "in box" dovrebbe apparire sul desktop.

  7. Se tutto funziona correttamente, aggiungi il seguente comando a un tasto di scelta rapida: scegli l'icona a forma di ingranaggio in alto a destra sullo schermo:

    Icona ingranaggio

  8. Vai a System SettingsKeyboardShortcutsCustom Shortcuts. Fare clic su +e aggiungere il comando:

    windowbox box
    

Questo dovrebbe farlo.

Nota importante

Lo script usa xdotool's windowunmapper rendere invisibile la finestra. La "scatola" (icona) creata sul desktop è l'unica "porta" alla finestra nascosta. In altre parole: non rimuovere manualmente i file del desktop. Se lo fai, la finestra andrà persa per sempre.

Lavoro da fare [modifica 20-12: fatto ]

La sceneggiatura potrebbe ancora usare un po 'di raffinatezza:

  • La geometria della finestra non viene ripristinata per definizione. Può essere risolto molto bene, ma ho pensato di mostrarti il ​​primo risultato.
  • Nella maggior parte dei casi, la finestra inscatolata ha l'icona corretta. La funzione get_process(w_id)potrebbe tuttavia utilizzare alcuni miglioramenti. Se il processo non viene trovato come comando in /usr/share/applications, il file ha un'icona generica.

Dare alle icone delle finestre a scatola una dimensione diversa rispetto alle altre icone

Lo script nomina sempre i.desktop file creati , ecc., A seconda del nome "disponibile" al momento della creazione (nomi dei file, non del nome visualizzato). boxed_1.desktopboxed_2.desktop

È possibile ridimensionare i file (in generale), facendo clic con il tasto destro> dimensione dell'icona. La buona notizia è che se si rimuove il file e lo si ricrea, la dimensione viene ricordata. Anche se si crea nuovamente il file dopo un riavvio. Ciò significa che se hai mai ridimensionato le finestre in scatola (ad esempio) 1-5, avranno sempre le stesse dimensioni quando tu (lo script) le crei di nuovo!

inserisci qui la descrizione dell'immagine


2
Non posso resistere senza lasciare un commento, bella risposta da parte tua :)
Ravan

Bello! Pochi commenti: 1. Ho sostituito la linea dtop = "/home/jacob/Bureaublad"con un percorso sul mio desktop ( dtop = "/home/" + user + "/Desktop") 2. Il ripristino con un doppio clic non ha funzionato. Ho il sospetto che source ~/.profilenon sia sufficiente per accedere / disconnettersi prontamente per testare questo. 3. In unità è possibile ridimensionare manualmente le icone (tasto destro -> icona ridimensiona), è possibile aggiungere alcuni parametri f_contentper impostare la dimensione dell'icona?
Artium,

4
Quando ho iniziato a leggere il primo paragrafo di questa risposta, sapevo solo che ci sarebbe stata un'icona arancione in fondo! ;-): P
Fabby,

1
Ciao @Artium Ho aggiornato lo script, ora ha alcuni importanti miglioramenti, tra cui una migliore ricerca di icone e ripristino della geometria, Buon divertimento!
Jacob Vlijm,

1
@Artium Lo so, ma prova quello nello script, è la solita icona della cartella, simile alla tua immagine. probabilmente solo un link alla stessa icona.
Jacob Vlijm,

7

Puoi usare fvwm per farlo.

  1. Installa fvwm:

    sudo apt-get update
    sudo apt-get install fvwm
    
  2. Trovane uno che utilizza la funzione iconify: ce ne sono diversi qui: http://www.jmcunx.com/fvwm_theme.html Molti sembrano lo screenshot che mostri.

  3. Copia il testo del tema, quindi vai a ~/.fvwm/(mostra prima i file nascosti), quindi crea un file.fvwm2rc

  4. Apri quel file in un editor di testo (come gedit) e incolla il testo del tema in esso.

  5. Riavvia il computer, seleziona fvwm e accedi.

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.