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

Чтобы использовать параметр "свернуть окно", щелкнув правой кнопкой мыши значок в панели запуска 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: дать системе поддельное окно - лучшее решение, как объяснил Джейкоб ниже.

2 ответа

Решение

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

Причина

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

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

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

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 открыть окно, останавливая вращение колеса.

Просто хотел добавить альтернативную реализацию 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()
Другие вопросы по тегам