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

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;

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

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

该脚本使用xdotool可从官方存储库安装的来查找所有firefox窗口、对其进行迭代并将其最小化。

脚本可以运行,并且启动器右侧菜单选项“最小化窗口”也可以运行,但是一旦窗口最小化,鼠标指针就会进入“忙碌”模式并保持这种状态约 20 秒(尽管鼠标操作仍然有响应)。

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

编辑:显然,等待时间是不可避免的,正如 Jacob Vlijm 的回答中解释的那样。由于鼠标仍然有响应,因此避免指针在旋转轮中的变换是一种部分美学解决方法,如问库本图

编辑2:给系统一个假的窗口是一个更好的解决方案,正如下面 Jacob 所解释的那样。

答案1

好问题。

原因

通常,当从 Unity Launcher 启动 GUI 应用程序时,启动器会等待窗口出现。等待期间,它会显示“旋转的轮子”。但它不会一直等待;大约 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.desktoptest2.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 对窗口的愿望,停止轮子旋转。

答案2

只是想添加一个替代的 fake_window 实现,它更简单一些,并且不会在 Ubuntu 16.04 系统上触发 python 警告。

#!/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()

相关内容