Une action de clic droit personnalisée dans Unity Launcher maintient le curseur occupé pendant 20 secondes

14

Pour avoir l'option "réduire la fenêtre" par un clic droit sur une icône du lanceur Unity (Ubuntu 14.04), j'ai suivi les instructions détaillées ici sur la modification d'un fichier .desktop et la création d'un programme de lancement personnalisé Firefox dans le dossier ~/.local/share/applications/ . La partie pertinente du fichier .desktop est:

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'action de bureau "Réduire" appelle un script shell simple, minimize.sh , ayant le contenu suivant:

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

Le script utilise xdotool , qui peut être installé à partir des référentiels officiels, pour rechercher toutes les fenêtres firefox , les parcourir et les minimiser.

Le script fonctionne et l'option de menu de droite du lanceur, "Réduire Windows", fonctionne également, mais dès que les fenêtres sont réduites au minimum, le pointeur de la souris passe en mode "occupé" et reste ainsi pendant environ 20 secondes (bien que la souris les actions sont toujours réactives).

Quelqu'un sait-il pourquoi le démarrage d'un script shell à partir d'une option de menu de droite dans Unity pourrait entraîner ce comportement?

MODIFIER : apparemment, la période d'attente est inévitable, comme l'explique la réponse de Jacob Vlijm. Puisque la souris reste sensible, éviter la transformation du pointeur dans le rouet constitue une solution de contournement esthétique partielle, comme expliqué à la page askubuntu .

EDIT2 : une meilleure solution consiste à donner au système une fausse fenêtre, comme l'explique Jacob ci-dessous.

    
posée Cosmin Saveanu 10.03.2016 - 08:00
la source

2 réponses

18

Excellente question.

La cause

Normalement, lors du démarrage des applications graphiques à partir du lanceur Unity, le lanceur attend qu'une fenêtre apparaisse. En attendant, il montre le "rouet". Il n'attendra pas pour toujours cependant; après environ 20 secondes, le lanceur suppose que la fenêtre n'apparaîtra pas et abandonne l'attente.

1. La commande principale du programme de lancement d'une application

Dans un fichier .desktop , concernant la première ligne Exec= (la commande principale), vous pouvez indiquer au lanceur d'attendre ou non, dans une ligne:

StartupNotify=true

pour le faire attendre ou

StartupNotify=false

pour le faire ne pas attendre.

2. Liste rapide d'un lanceur

Pour les éléments de liste rapide possibles (clic droit) d'un lanceur, la valeur par défaut est StartupNotify=true . Malheureusement, cette valeur est fixe et ne peut être modifiée par rien.

Cela signifie que si vous lancez une commande en cliquant avec le bouton droit de la souris sur l’icône du lanceur dans le lanceur Unity, celui-ci attend une fenêtre et attend qu’il affiche la roue en rotation.

En définitive, bien que cela puisse être expliqué, il ne semble pas y avoir de solution au problème pour le moment. Vous devez donc créer un programme de lancement dédié à votre script et ajouter la ligne StartupNotify=false au fichier.

La preuve

Vous pouvez tester le comportement vous-même. Créez deux lanceurs:

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

et:

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

Enregistrez les en tant que test1.desktop et test2.desktop , faites glisser les deux lanceurs sur le lanceur Unity. Cliquez dessus pour voir la différence de comportement.

Modifier; si cela vous vous dérange vraiment, donnez à Unity une fausse fenêtre

Si vous avez de nombreux scripts dans les listes rapides et / ou que cela vous dérange vraiment, il existe une autre solution esthétique. nous pouvons simuler , invisible (totalement transparent) pour afficher une fenêtre, à inclure dans votre script. votre script serait alors (par exemple)

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

où la commande fake_window appellera notre (fausse) fenêtre, faisant en sorte que Unity termine la roue en rotation.

Comment configurer

  1. Créez, s'il n'existe pas encore, le répertoire ~/bin
  2. Copiez le script ci-dessous dans un fichier vide, enregistrez-le sous fake_window (sans extension) dans ~/bin et rendez-le exécutable

    #!/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. Ajoutez à la toute fin de votre script la commande:

    fake_window
    
  4. Déconnectez-vous et reconnectez-vous (ou exécutez source ~/.profile )

Voilà, la roue ne tourne que tant que le script est exécuté.

Explication

Le script crée une fenêtre minimaliste. La fenêtre est cependant totalement transparente et a une taille de 0x0 pixels et est donc invisible. Il va se détruire instantanément une fois qu'il existe.

Si vous appelez la fenêtre à la fin de votre script, vous réaliserez le souhait de Unity de disposer d’une fenêtre, en arrêtant la roue de tourner.

    
réponse donnée Jacob Vlijm 10.03.2016 - 09:14
la source
4

Je voulais juste ajouter une autre implémentation de fake_window qui est un peu plus simple et qui ne déclenche pas les avertissements python sur un système 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()
    
réponse donnée Digikata 28.09.2016 - 22:55
la source

Lire d'autres questions sur les étiquettes