L'azione del tasto destro del mouse personalizzata in Unity Launcher mantiene il cursore occupato per 20 secondi


14

Per avere un'opzione "minimizza finestra" facendo clic con il tasto destro sull'icona di Unity Launcher (Ubuntu 14.04), ho seguito le istruzioni dettagliate qui sulla modifica di un .desktopfile e ho creato un Firefoxlauncher personalizzato nella ~/.local/share/applications/cartella. La parte rilevante del file .desktop è:

Actions=NewWindow;NewPrivateWindow;Minimize

[Desktop Action NewWindow]
Name=Open a New Window
Exec=firefox -new-window
OnlyShowIn=Unity;

[Desktop Action NewPrivateWindow]
Name=Open a New Private Window
Exec=firefox -private-window
OnlyShowIn=Unity;

[Desktop Action Minimize]
Name=Minimize Windows
Exec=sh /home/myusername/Documents/xdotool_sh/minimize.sh firefox
OnlyShowIn=Unity;

L'azione desktop "Riduci a icona" richiama un semplice script shell, minimize.shche ha il seguente contenuto:

#/bin/bash
name=$1
for i in $(xdotool search --class "$name"); do
    xdotool windowminimize $i
done

Lo script utilizza xdotool, che può essere installato dai repository ufficiali, per trovare tutte le firefoxfinestre, scorrere su di esse e minimizzarle.

Lo script funziona e anche l'opzione di menu a destra del programma di avvio "Riduci a icona Windows" funziona, ma non appena le finestre sono ridotte a icona, il puntatore del mouse entra in modalità "occupato" e rimane così per circa 20 secondi (anche se le azioni del mouse sono ancora reattivo).

Qualcuno sa perché l'avvio di uno script di shell da un'opzione di menu corretta in Unity potrebbe portare a questo comportamento?

EDIT : Apparentemente il periodo di attesa è inevitabile, come spiegato nella risposta di Jacob Vlijm. Poiché il mouse rimane reattivo, evitare la trasformazione del puntatore nella ruota che gira è una soluzione alternativa parziale, come spiegato su askubuntu .

EDIT2 : dare al sistema una finta finestra è una soluzione migliore, come spiegato da Jacob di seguito.


Ciao Cosmin, ho aggiunto un'altra soluzione abbastanza pulita, credo.
Jacob Vlijm,

Grazie Jacob. Stavo pensando a quel tipo di soluzione ma non sapevo come si potesse fare. È bello che esista una soluzione.
Cosmin Saveanu,

Risposte:


18

Ottima domanda

La causa

Normalmente, quando si avviano le applicazioni della GUI da Unity Launcher, il launcher attende che appaia una finestra. Durante l'attesa, mostra la "ruota che gira". Non aspetterà per sempre comunque; dopo circa 20 secondi, il programma di avvio presuppone che la finestra non venga visualizzata e smette di aspettare.

1. Il comando principale del programma di avvio di un'applicazione

In un .desktopfile, relativo alla prima Exec=riga (il comando principale), puoi dire al programma di avvio di attendere o meno, in una riga:

StartupNotify=true

per farlo aspettare, o

StartupNotify=false

per non aspettare.

2. Elementi della Quicklist di un lanciatore

Per possibili elementi della lista rapida (clic con il tasto destro) di un programma di avvio, tuttavia, il valore predefinito è StartupNotify=true. Sfortunatamente, questo valore è fisso e non può essere modificato da nulla.

Ciò significa che se si avvia un comando facendo clic con il tasto destro sull'icona di un launcher in Unity Launcher, il launcher si aspetta una finestra e la attende, mostrando la ruota che gira.

La linea di fondo è che, sebbene possa essere spiegato, al momento non sembra esserci alcuna soluzione al problema, a parte la creazione di un launcher dedicato per lo script e l'aggiunta della riga StartupNotify=falseal file.

La prova

Puoi testare il comportamento da solo. Crea due lanciatori:

[Desktop Entry]
Name=Test
Exec=sh /home/myusername/Documents/xdotool_sh/minimize.sh firefox
Type=Application
StartupNotify=true

e:

[Desktop Entry]
Name=Test
Exec=sh /home/myusername/Documents/xdotool_sh/minimize.sh firefox
Type=Application
StartupNotify=false

Salvali come test1.desktope test2.desktop, trascina entrambi i lanciatori su Unity Launcher. Fare clic su di essi e vedere la differenza di comportamento.


Modificare; se ti dà davvero fastidio, dai a Unity una finta finestra

Se hai molti script nelle liste di scelta rapida e / o ti disturba davvero, c'è un'altra soluzione cosmetica; possiamo fingere , invisibile (completamente trasparente) per mostrare una finestra, da includere nella tua sceneggiatura. la tua sceneggiatura sarebbe quindi (ad es.)

#/bin/bash
name=$1
for i in $(xdotool search --class "$name"); do
    xdotool windowminimize $i
done
fake_window

dove il comando fake_windowchiamerà la nostra finestra (falsa), facendo finire Unity alla ruota che gira.

Come impostare

  1. Creare, se non esiste ancora, la directory ~/bin
  2. Copia lo script seguente in un file vuoto, salvalo come fake_window(senza estensione) ~/bin e rendilo eseguibile

    #!/usr/bin/env python3
    from gi.repository import Gtk
    from threading import Thread
    import time
    import subprocess
    
    """
    This is a self-destroying window, to "feed" Unity a fake-window, preventing
    the launcher to show a spinning wheel, waiting for a window to appear.
    Include the command to run this script at the end of the (your) script.
    """
    
    class FakeWin(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self, title="1526closeme")
            Thread(target = self.close).start()
    
        def close(self):
            t = 0
            while t < 150:
                time.sleep(0.2)
                try:
                    pid = subprocess.check_output(["pgrep", "-f", "fake_window"])\
                          .decode("utf-8").strip()
                    subprocess.Popen(["kill", pid])
                    break
                except subprocess.CalledProcessError:
                    pass
                t += 1
    
    def fakewindow():
        window = FakeWin()
        # make our window transparent
        window.set_opacity(0)
        window.set_default_size(0,0)
        window.show_all()
        Gtk.main()
    
    fakewindow()
  3. Aggiungi alla fine del tuo script il comando:

    fake_window
  4. Esci e rientra (o eseguisource ~/.profile)

Ecco fatto, la ruota ora gira solo per tutto il tempo in cui lo script è in esecuzione.

Spiegazione

Lo script fa creare una finestra minimalista. La finestra tuttavia è completamente trasparente e ha una dimensione di 0x0 pixel ed è quindi invisibile. Si distruggerà all'istante una volta che esiste.

Chiamando la finestra alla fine della sceneggiatura, soddisferai il desiderio di Unity di una finestra, fermando la ruota.


Grazie per la spiegazione dettagliata e le modifiche alla domanda. Fornisce idee su possibili soluzioni alternative.
Cosmin Saveanu,

Ottima idea: dare una finta finestra. Mi piace
Sergiy Kolodyazhnyy il

@Sergo inganno e inganno, ma funziona :)
Jacob Vlijm

4

Volevo solo aggiungere un'implementazione alternativa di fake_window che è un po 'più semplice e non attiva avvisi di Python su un sistema Ubuntu 16.04.

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '3.0')

from gi.repository import Gtk
from gi.repository import GLib

"""
This is a self-destroying window, to "feed" Unity a fake-window, preventing
the launcher to show a spinning wheel, waiting for a window to appear.
Include the command to run this script at the end of the (your) script.
"""

def timer_cb():
    Gtk.main_quit()
    return False

def show_cb(widget, data=None):
    GLib.timeout_add(500, timer_cb)

def fakewindow():
    window = Gtk.Window()
    # make our window transparent
    window.set_opacity(0)
    window.set_default_size(0,0)

    window.connect("show", show_cb)

    window.show_all()

    Gtk.main()

fakewindow()

Bello! mai notato questa aggiunta fino ad ora :)
Jacob Vlijm
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.