Niestandardowa akcja kliknięcia prawym przyciskiem myszy w Unity Launcher utrzymuje kursor zajęty przez 20 sekund

14

Aby mieć możliwość minimalizacji „okno” poprzez kliknięcie prawym przyciskiem myszy na ikonę w wyrzutni Unity (Ubuntu 14.04), I po szczegółowe instrukcje tutaj o zmianę .desktoppliku i wykonane niestandardowego Firefoxwyrzutni w ~/.local/share/applications/folderze. Odpowiednia część pliku .desktop to:

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;

Akcja „Minimalizuj” na pulpicie wywołuje prosty skrypt powłoki, minimize.shktóry ma następującą treść:

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

Skrypt wykorzystuje xdotool, które można zainstalować z oficjalnych repozytoriów, aby znaleźć wszystkie firefoxokna, iterować je i minimalizować.

Skrypt działa, a opcja menu uruchamiania „Minimalizuj system Windows” również działa, ale gdy tylko okna zostaną zminimalizowane, wskaźnik myszy przechodzi w tryb „zajęty” i pozostaje taki przez około 20 sekund (chociaż akcje myszy są nadal czuły).

Czy ktoś wie, dlaczego uruchomienie skryptu powłoki z odpowiedniej opcji menu w Unity może prowadzić do takiego zachowania?

EDYCJA : Najwyraźniej okres oczekiwania jest nieunikniony, jak wyjaśniono w odpowiedzi Jacoba Vlijma. Ponieważ mysz pozostaje responsywna, uniknięcie transformacji wskaźnika w obracającym się kole jest częściowym obejściem estetycznym, jak wyjaśniono na askubuntu .

EDYCJA 2 : nadanie systemowi fałszywego okna jest lepszym rozwiązaniem, jak wyjaśnił Jacob poniżej.

Cosmin Saveanu
źródło
Cześć Cosmin, dodałem inne, całkiem czyste rozwiązanie.
Jacob Vlijm
Dziękuję Jacob. Myślałem o takim rozwiązaniu, ale nie wiedziałem, jak to zrobić. To wspaniałe, że istnieje rozwiązanie.
Cosmin Saveanu,

Odpowiedzi:

18

Doskonałe pytanie.

Powód

Zwykle podczas uruchamiania aplikacji GUI z Unity Launcher, program uruchamiający czeka na pojawienie się okna. Podczas oczekiwania pokazuje „obracające się koło”. Nie będzie jednak czekać wiecznie; po około 20 sekundach program uruchamiający zakłada, że ​​okno się nie pojawi i rezygnuje z czekania.

1. Główne polecenie programu uruchamiającego aplikację

W .desktoppliku dotyczącym pierwszego Exec=wiersza (polecenia głównego) możesz powiedzieć programowi uruchamiającemu, aby poczekał lub nie, w wierszu:

StartupNotify=true

aby poczekać, lub

StartupNotify=false

żeby nie czekać.

2. Skrócona lista elementów programu uruchamiającego

Jednak w przypadku możliwych szybkich pozycji (kliknięcie prawym przyciskiem) elementów uruchamiających domyślną wartością jest StartupNotify=true. Niestety, ta wartość jest stała i nie może być zmieniona przez nic.

Oznacza to, że jeśli uruchomisz dowolne polecenie, klikając prawym przyciskiem myszy ikonę programu uruchamiającego w Unity Launcher, program uruchamiający oczekuje okna i czeka na niego, pokazując obracające się koło.

Najważniejsze jest to, że chociaż można to wyjaśnić, wydaje się, że obecnie nie ma rozwiązania tego problemu, oprócz stworzenia dedykowanego programu uruchamiającego dla skryptu i dodania wiersza StartupNotify=falsedo pliku.

Dowód

Możesz sam sprawdzić zachowanie. Utwórz dwa wyrzutnie:

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

i:

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

Zapisz je jako test1.desktopi test2.desktopprzeciągnij oba programy uruchamiające do programu uruchamiającego Unity. Kliknij je i zobacz różnicę w zachowaniu.


Edytować; jeśli naprawdę Ci to przeszkadza, nakarm Unity fałszywym oknem

Jeśli masz wiele skryptów na krótkich listach i / lub naprawdę Ci to przeszkadza, istnieje inne rozwiązanie kosmetyczne; możemy sfałszować , niewidoczny (w pełni przezroczysty), aby pokazać okno, które zostanie uwzględnione w twoim skrypcie. Twój skrypt byłby wtedy (np.)

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

gdzie polecenie fake_windowwywoła nasze (fałszywe) okno, sprawiając, że Unity zakończy wirujące koło.

Jak skonfigurować

  1. Utwórz, jeśli jeszcze nie istnieje, katalog ~/bin
  2. Skopiuj poniższy skrypt do pustego pliku, zapisz go jako fake_window(bez rozszerzenia) ~/bin i włącz

    #!/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. Dodaj na samym końcu skryptu polecenie:

    fake_window
  4. Wyloguj się i zaloguj ponownie (lub uruchomsource ~/.profile)

To wszystko, koło będzie się teraz obracać tylko tak długo, jak długo uruchomi się skrypt.

Wyjaśnienie

Skrypt ma stworzyć minimalistyczny okno. Okno jest jednak w pełni przezroczyste i ma rozmiar 0x0 pikseli i dlatego jest niewidoczne. Zniszczy się natychmiast, gdy będzie istniał.

Wywołując okno na końcu skryptu, spełnisz życzenie Unity dotyczące okna, zatrzymując koło.

Jacob Vlijm
źródło
Dziękujemy za szczegółowe wyjaśnienie i zmiany w pytaniu. Daje pomysły na temat potencjalnych obejść.
Cosmin Saveanu
Świetny pomysł - dać fałszywe okno. Podoba mi się
Sergiy Kolodyazhnyy
@Serg oszustwo i oszustwo, ale działa :)
Jacob Vlijm
4

Chciałem tylko dodać alternatywną implementację fałszywego okna, która jest nieco prostsza i nie wyzwala ostrzeżeń pythonowych w systemie 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
źródło
Ładny! do tej pory nie zauważyłem tego dodatku :)
Jacob Vlijm