A ação personalizada com o botão direito do mouse no Unity Launcher mantém o cursor ocupado por 20 segundos

14

Para ter uma opção "minimizar janela" clicando com o botão direito em um ícone no Unity launcher (Ubuntu 14.04), eu segui as instruções detalhadas aqui sobre como alterar um arquivo .desktop e criou um Firefox launcher personalizado na pasta ~/.local/share/applications/ . A parte relevante do arquivo .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;

A ação de área de trabalho "Minimizar" chama um script de shell simples, minimize.sh , com o seguinte conteúdo:

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

O script usa xdotool , que pode ser instalado a partir dos repositórios oficiais, para encontrar todas as firefox janelas, iterar sobre elas e minimizá-las.

O script funciona e a opção de menu direito do lançador "Minimize Windows" também funciona, mas assim que as janelas são minimizadas, o ponteiro do mouse fica no modo "ocupado" e permanece assim por cerca de 20 segundos (embora o mouse as ações ainda são responsivas).

Alguém sabe por que iniciar um script de shell a partir de uma opção de menu à direita no Unity poderia levar a esse comportamento?

EDIT : Aparentemente, o período de espera é inevitável, conforme explicado na resposta de Jacob Vlijm. Como o mouse permanece responsivo, evitar a transformação do ponteiro na roda de fiar é uma solução estética parcial, como explicado em askubuntu .

EDIT2 : dar ao sistema uma janela falsa é uma solução melhor, como explicado por Jacob abaixo.

    
por Cosmin Saveanu 10.03.2016 / 08:00

2 respostas

18

Excelente pergunta.

A causa

Normalmente, ao iniciar aplicativos GUI a partir do Unity Launcher, o ativador aguarda a exibição de uma janela. Enquanto espera, mostra a "roda de fiar". Não vai esperar para sempre no entanto; depois de cerca de 20 segundos, o lançador assume que a janela não aparecerá e desiste de esperar.

1. O principal comando do lançador de um aplicativo

Em um arquivo .desktop , referente à primeira linha Exec= (o comando principal), você pode informar ao que o lançador espere ou não, em uma linha:

StartupNotify=true

para esperar ou

StartupNotify=false

para que não aguarde.

2. Itens da lista rápida de um iniciador

Para possíveis itens de lista rápida (clique com o botão direito) de um lançador, o valor padrão é StartupNotify=true . Infelizmente, esse valor é fixo e não pode ser alterado por nada.

Isso significa que se você iniciar qualquer comando clicando com o botão direito no ícone de um lançador no Unity Launcher, o lançador está esperando uma janela e espera por ela, mostrando a roda girando.

O resultado é que, embora possa ser explicado, parece não haver solução para o problema no momento, além de criar um lançador dedicado para o seu script e adicionar a linha StartupNotify=false ao arquivo.

A prova

Você pode testar o comportamento sozinho. Crie dois lançadores:

[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

Salve-os como test1.desktop e test2.desktop , arraste os dois ativadores para o iniciador do Unity. Clique neles e veja a diferença de comportamento.

Editar; se isso realmente o incomoda, dê uma janela falsa ao Unity

Se você tem muitos scripts em listas rápidas, e / ou realmente incomoda você, há outra solução cosmética; podemos fingir , invisível (totalmente transparente) para mostrar uma janela, para ser incluída no seu script. seu script seria então (por exemplo)

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

onde o comando fake_window chamará nossa (falsa) janela, fazendo com que Unity termine a roda de fiar.

Como configurar

  1. Crie, se ainda não existir, o diretório ~/bin
  2. Copie o script abaixo em um arquivo vazio, salve-o como fake_window (sem extensão) em ~/bin e torne-o executável

    #!/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. Adicione ao final do seu script o comando:

    fake_window
    
  4. Faça logout e volte em (ou execute source ~/.profile )

É isso, a roda girará somente enquanto o script for executado.

Explicação

O script faz criar uma janela minimalista. A janela, no entanto, é totalmente transparente e tem um tamanho de 0x0 pixels e, portanto, é invisível. Ele irá se destruir instantaneamente quando existir.

Chamando a janela no final do seu roteiro, você irá satisfazer o desejo de Unity por uma janela, parando a roda girar.

    
por Jacob Vlijm 10.03.2016 / 09:14
4

Só queria adicionar uma implementação alternativa de fake_window que seja um pouco mais simples e não acione avisos python em um 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()
    
por Digikata 28.09.2016 / 22:55