La acción personalizada de hacer clic con el botón derecho en Unity Launcher mantiene el cursor ocupado durante 20 segundos

14

Para tener una opción de "minimizar ventana" haciendo clic derecho en un ícono en el iniciador de Unity (Ubuntu 14.04), seguí las instrucciones detalladas aquí sobre cómo cambiar un .desktoparchivo e hice un Firefoxiniciador personalizado en la ~/.local/share/applications/carpeta. La parte relevante del archivo .desktop es:

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;

La acción de escritorio "Minimizar" invoca un script de shell simple, minimize.shque tiene el siguiente contenido:

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

El script usa xdotool, que se puede instalar desde los repositorios oficiales, para encontrar todas las firefoxventanas, iterar sobre ellas y minimizarlas.

El script funciona y la opción del menú derecho del iniciador "Minimizar Windows" también funciona, pero tan pronto como se minimizan las ventanas, el puntero del mouse se pone en modo "ocupado" y permanece así durante unos 20 segundos (aunque las acciones del mouse siguen siendo sensible).

¿Alguien sabe por qué iniciar un script de shell desde una opción de menú correcta en Unity podría conducir a este comportamiento?

EDITAR : Aparentemente, el período de espera es inevitable, como se explica en la respuesta de Jacob Vlijm. Como el mouse permanece receptivo, evitar la transformación del puntero en la rueda giratoria es una solución estética parcial, como se explica en askubuntu .

EDIT2 : dar al sistema una ventana falsa es una mejor solución, como explica Jacob a continuación.

Cosmin Saveanu
fuente
Hola Cosmin, creo que agregué otra solución bastante limpia.
Jacob Vlijm
Gracias Jacob Estaba pensando en ese tipo de solución, pero no sabía cómo podría hacerse. Es genial que exista una solución.
Cosmin Saveanu

Respuestas:

18

Excelente pregunta

La causa

Normalmente, al iniciar aplicaciones GUI desde el Lanzador de Unity, el iniciador espera a que aparezca una ventana. Mientras espera, muestra la "rueca". Sin embargo, no esperará para siempre; Después de unos 20 segundos, el iniciador asume que la ventana no aparecerá y deja de esperar.

1. El comando principal del iniciador de una aplicación

En un .desktoparchivo, relacionado con la primera Exec=línea (el comando principal), puede decirle al iniciador que espere o no, en una línea:

StartupNotify=true

para hacerla esperar, o

StartupNotify=false

para que no espere

2. Elementos de la lista rápida de un lanzador

Sin embargo, para posibles elementos de lista rápida (clic derecho) de un lanzador, el valor predeterminado es StartupNotify=true. Desafortunadamente, este valor es fijo y no puede ser cambiado por nada.

Eso significa que si comienzas cualquier comando haciendo clic derecho en el ícono del iniciador en el Iniciador de Unity, el iniciador espera una ventana y la espera, mostrando la rueda giratoria.

La conclusión es que, aunque se puede explicar, parece que no hay solución al problema en este momento, aparte de crear un iniciador dedicado para su script y agregar la línea StartupNotify=falseal archivo.

La prueba

Puede probar el comportamiento usted mismo. Crea dos lanzadores:

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

y:

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

Guárdelos como test1.desktopy test2.desktoparrastre ambos lanzadores al iniciador de Unity. Haga clic en ellos y vea la diferencia en el comportamiento.


Editar; si realmente te molesta, dale a Unity una ventana falsa

Si tiene muchos scripts en las listas rápidas, y / o realmente le molesta, hay otra solución cosmética; podemos falsificar , invisible (totalmente transparente) para mostrar una ventana, que se incluirá en su secuencia de comandos. su guión sería entonces (por ejemplo)

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

donde el comando fake_windowllamará a nuestra ventana (falsa), haciendo que Unity termine la rueda giratoria.

Como instalar

  1. Cree, si aún no existe, el directorio ~/bin
  2. Copie el script a continuación en un archivo vacío, guárdelo como fake_window(sin extensión) ~/bin y hágalo ejecutable

    #!/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. Agregue al final de su script el comando:

    fake_window
  4. Cerrar sesión y volver a iniciar sesión (o ejecutarsource ~/.profile)

Eso es todo, la rueda ahora solo girará mientras se ejecute el script.

Explicación

El guión hace crear una ventana minimalista. Sin embargo, la ventana es totalmente transparente y tiene un tamaño de 0x0 píxeles y, por lo tanto, es invisible. Se destruirá a sí mismo instantáneamente una vez que exista.

Llamando a la ventana al final de su guión, satisfará el deseo de Unity de una ventana, deteniendo la rueda para girar.

Jacob Vlijm
fuente
Gracias por la explicación detallada y las ediciones de la pregunta. Da ideas sobre posibles soluciones alternativas.
Cosmin Saveanu
Gran idea: dar una ventana falsa. Me gusta
Sergiy Kolodyazhnyy
@Serg engaño y engaño, pero funciona :)
Jacob Vlijm
4

Solo quería agregar una implementación alternativa de fake_window que sea un poco más simple y no active advertencias de Python en 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()
Digikata
fuente
¡Agradable! nunca noté esta adición hasta ahora :)
Jacob Vlijm