Пользовательское действие по щелчку правой кнопкой мыши в Unity Launcher держит курсор занятым на 20 секунд

14

Чтобы иметь опцию «минимизировать окно» через правую кнопку мыши на иконке в панели запуска Unity (Ubuntu 14.04), я следовал подробным инструкциям здесь об изменении .desktopфайла и сделал пользовательский Firefoxгранатомет в ~/.local/share/applications/папке. Соответствующая часть файла .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;

Действие рабочего стола «Свернуть» вызывает простой сценарий оболочки, minimize.shкоторый имеет следующее содержимое:

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

Скрипт использует xdotool, которые могут быть установлены из официальных репозиториев, чтобы найти все firefoxокна, перебрать их и свести к минимуму.

Сценарий работает, и в правом меню панели запуска «Свернуть Windows» также работает, но как только окна свернуты, указатель мыши переходит в режим «занят» и остается таким примерно 20 секунд (хотя действия мыши все еще остаются отзывчивый).

Кто-нибудь знает, почему запуск сценария оболочки из правильной опции меню в Unity может привести к такому поведению?

РЕДАКТИРОВАТЬ : Очевидно, период ожидания неизбежен, как объяснено в ответе Якоба Влиима. Так как мышь остается отзывчивой, избегание преобразования указателя в вращающемся колесе является частичным эстетическим обходным путем , как объясняется в Askubuntu .

РЕДАКТИРОВАТЬ 2 : дать системе поддельное окно - лучшее решение, как объяснил Джейкоб ниже.

Космин Савяну
источник
Привет Космин, я добавил еще одно, довольно чистое решение, я думаю.
Джейкоб Влейм
Спасибо, Джейкоб. Я думал о таком решении, но не знал, как это можно сделать. Это здорово, что решение существует.
Космин Савяну

Ответы:

18

Отличный вопрос.

Причина

Обычно, когда запускаются приложения с графическим интерфейсом из Unity Launcher, программа запуска ожидает появления окна. В ожидании показывает «вращающееся колесо». Это не будет ждать вечно однако; примерно через 20 секунд программа запуска предполагает, что окно не появится, и перестает ждать.

1. Основная команда запуска приложения

В .desktopфайле, относящемся к первой Exec=строке (основной команде), вы можете указать программе запуска ждать или нет, в строке:

StartupNotify=true

чтобы подождать, или

StartupNotify=false

чтобы не ждать.

2. Быстрый список предметов лаунчера

Однако для возможных элементов списка быстрого запуска (щелчка правой кнопкой мыши) по умолчанию используется значение StartupNotify=true. К сожалению, это значение является фиксированным и не может быть изменено ничем.

Это означает, что если вы запустите любую команду, щелкнув правой кнопкой мыши значок запуска в Unity Launcher, программа запуска ожидает окно и ждет его, показывая вращающееся колесо.

Суть в том, что, хотя это можно объяснить, в данный момент, похоже, нет решения этой проблемы, кроме создания выделенного модуля запуска для вашего сценария и добавления строки StartupNotify=falseв файл.

Доказательство

Вы можете проверить поведение самостоятельно. Создайте две пусковые установки:

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

и:

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

Сохраните их как test1.desktopи test2.desktop, перетащите оба модуля запуска на модуль запуска Unity. Нажмите на них и увидите разницу в поведении.


Редактировать; если это действительно беспокоит вас, накормите Unity поддельным окном

Если у вас есть много сценариев в быстрых списках, и / или это действительно беспокоит вас, есть другое косметическое решение; мы можем подделать , невидимую (полностью прозрачную), чтобы показать окно, которое будет включено в ваш скрипт. ваш сценарий будет (например)

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

где команда fake_windowвызовет наше (поддельное) окно, заставляя Unity прекратить вращающееся колесо.

Как настроить

  1. Создайте, если он еще не существует, каталог ~/bin
  2. Скопируйте приведенный ниже скрипт в пустой файл, сохраните его как fake_window(без расширения) ~/bin и сделайте его исполняемым

    #!/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. Добавьте в самый конец вашего скрипта команду:

    fake_window
  4. Выйти и вернуться (или запуститьsource ~/.profile)

Вот и все, колесо будет вращаться только до тех пор, пока работает скрипт.

объяснение

Скрипт делает создать минималистичный окно. Однако окно полностью прозрачно, имеет размер 0x0 пикселей и поэтому невидимо. Он уничтожит себя немедленно, как только он будет существовать.

Вызывая окно в конце вашего сценария, вы удовлетворите желание Unity открыть окно, останавливая вращение колеса.

Якоб Влейм
источник
Спасибо за подробное объяснение и изменения по этому вопросу. Дает идеи о возможных обходных путях.
Космин Савяну
Отличная идея - дать поддельное окно. мне это нравится
Сергей Колодяжный
@ Серг обман и обман, но это работает :)
Джейкоб Влейм
4

Просто хотел добавить альтернативную реализацию fake_window, которая немного проще и не вызывает предупреждений Python в системе 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
источник
Ницца! никогда не замечал этого дополнения до сих пор :)
Джейкоб Влейм