Unity Launcher 中的自定义右键单击操作使光标保持忙碌 20 秒

Cos*_*anu 14 scripts unity launcher quicklists .desktop

要通过右键单击 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;
Run Code Online (Sandbox Code Playgroud)

桌面操作“最小化”调用一个简单的 shell 脚本,minimize.sh其内容如下:

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

该脚本使用xdotool,可以从官方存储库安装,查找所有firefox窗口,遍历它们并最小化它们。

该脚本有效,启动器右侧菜单选项“最小化 Windows”也有效,但是一旦窗口最小化,鼠标指针就会进入“忙碌”模式并保持大约 20 秒(尽管鼠标操作仍然有反应)。

有谁知道为什么从 Unity 中的右侧菜单选项启动 shell 脚本会导致这种行为?

编辑:显然等待期是不可避免的,正如 Jacob Vlijm 的回答所解释的那样。由于鼠标保持响应,因此避免在旋转轮中变换指针是一种局部美学解决方法,如askubuntu所述

EDIT2:给系统一个假窗口是一个更好的解决方案,如下面的 Jacob 解释。

Jac*_*ijm 18

很好的问题。

原因

通常,当从 Unity Launcher 启动 GUI 应用程序时,启动器会等待一个窗口出现。在等待时,它显示“旋转轮”。然而,它不会永远等待;大约 20 秒后,启动器假定窗口不会出现并放弃等待。

1. 应用程序启动器的主要命令

.desktop文件中,关于第一Exec=行(主命令),您可以在一行中告诉启动器是否等待:

StartupNotify=true
Run Code Online (Sandbox Code Playgroud)

让它等待,或

StartupNotify=false
Run Code Online (Sandbox Code Playgroud)

让它等待。

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
Run Code Online (Sandbox Code Playgroud)

和:

[Desktop Entry]
Name=Test
Exec=sh /home/myusername/Documents/xdotool_sh/minimize.sh firefox
Type=Application
StartupNotify=false
Run Code Online (Sandbox Code Playgroud)

将它们另存为test1.desktopand test2.desktop,将两个启动器拖到 Unity 启动器上。单击它们并查看行为的差异。


编辑; 如果它真的困扰你,给 Unity 一个假窗口

如果您在快速列表中有很多脚本,和/或它真的困扰着您,那么还有另一种美容解决方案;我们可以伪造,不可见(完全透明)以显示一个窗口,以包含在您的脚本中。你的脚本将是(例如)

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

该命令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()
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将命令添加到脚本的最后:

    fake_window
    
    Run Code Online (Sandbox Code Playgroud)
  4. 注销并重新登录(或运行source ~/.profile

就是这样,轮子现在只会在脚本运行时旋转。

解释

该脚本确实创建了一个简约的窗口。然而,窗口是完全透明的,大小为 0x0 像素,因此是不可见的。一旦存在,它就会立即毁灭自己。

在脚本末尾调用窗口,您将满足 Unity 对窗口的期望,停止轮子旋转。