如何在 Unity Launcher 中获取正在运行的 GUI 应用程序列表?

ovi*_*idb 9 launcher process unity-dash 14.04

我需要一个列表,其中仅包含当前在 Dash 中打开/运行的应用程序,即图标左侧带有白色小箭头的应用程序。

有什么办法可以得到吗?

带箭头的破折号屏幕截图

Jac*_*ijm 6

有趣的问题。

与往常一样,有多种方法可以获取这些应用程序的列表,每个应用程序都有特定的广告和缺点。

使用窗口列表获取在启动器中表示的进程列表

由于只有具有(映射)窗口的应用程序出现在启动器中,因此使用:

wmctrl -lp 
Run Code Online (Sandbox Code Playgroud)

wmctrl默认情况下未安装),我们可以获得打开的窗口列表和窗口所属的进程ID。输出的格式是:

0x05204641  0 12618  jacob-System-Product-Name verhaal (~) - gedit
Run Code Online (Sandbox Code Playgroud)

对我们来说,最重要的信息在哪里:

  • 第一个字符串 ( 0x05204641); 这是窗口-id
  • 第三个字符串 ( 12618); 这是窗口所属的进程ID(pid),并且,
  • 最后一节 ( verhaal (~) - gedit); 这是窗口名称

有了pid,我们就可以通过命令查找对应的进程

ps -p <pid> -o comm=
Run Code Online (Sandbox Code Playgroud)

我们可以编写上述步骤的脚本,并列出现有窗口的输出,如下所示(使用python):

{'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'thunderbird', 'soffice.bin'}
Run Code Online (Sandbox Code Playgroud)

并发症

这看起来很简单。然而,与往常一样,现实情况要复杂一些。我们需要注意一些例外情况和并发症:

  1. 某些窗口将属于pid 0,这将在尝试获取其属性时引发错误。的视窗IdlepythonIDE),或者tkinter是这样的窗口。
  2. 有些窗口不是“真实的”或窗口,例如瞬态窗口(从其他窗口调用并属于其他窗口的窗口)或例如桌面本身。这些窗口在 的输出中列为窗口wmctrl,但不会单独出现在 Dash 中。
  3. 在某些情况下,应用程序的名称与进程名称完全不同,例如在LibreOffice所有模块的进程名称为 的情况下soffice.bin。同时,运行该命令 soffice.bin将不起作用。如果你需要识别模块CalcWriter等)分开,你需要得到更多的信息,从该窗口的名称,例如。
  4. 另一个示例是 的进程名称gnome-terminal,它出现在进程列表中,如 的输出中ps -e ww。在 14.04 中,gnome-terminal显示为gnome-terminal,但是,在 15.04 / 15.10 中它显示:/usr/lib/gnome-terminal/gnome-terminal-server

我们至少需要修复什么

要解决上述最重要的问题,您需要:

  • 添加检查窗口是“真实”还是“正常”窗口,检查

    xprop -id <window_id>
    
    Run Code Online (Sandbox Code Playgroud)

    如果输出包括以下行:

    _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
    
    Run Code Online (Sandbox Code Playgroud)

    该窗口是 Unity Launcher 意义上的有效窗口

  • 要修复gnome-terminalin的进程名称15.x(假设您希望呈现的进程名称为gnome-terminal),我们需要添加一个例外,将进程名称重命名为,gnome-terminal如果它显示为 /usr/lib/gnome-terminal/gnome-terminal-server

脚本

wmctrl -lp 
Run Code Online (Sandbox Code Playgroud)

如何使用

  1. 脚本需要wmctrl

    sudo apt-get install wmctrl
    
    Run Code Online (Sandbox Code Playgroud)
  2. 将上面的脚本复制到一个空文件中,另存为 get_running.py

  3. 通过命令运行它:

    python3 /path/to/get_running.py
    
    Run Code Online (Sandbox Code Playgroud)

    它会输出如下:

    {'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'thunderbird', 'soffice.bin'}
    
    Run Code Online (Sandbox Code Playgroud)

    或者,使用参数运行-list

    thunderbird
    nautilus
    gnome-terminal
    firefox
    gedit
    GuitarPro.exe
    soffice.bin
    
    Run Code Online (Sandbox Code Playgroud)

笔记

从您的问题来看,并不完全清楚找到列表的确切目的是什么。如果您需要应用程序的名称,如界面中显示的那样(“可读”名称),则可能适合采用完全不同的方法:

  • 所有全局安装的应用程序确实有.desktop文件/usr/share/applications。大多数情况下,我们可以从应用程序的文件中推断出应用程序的进程名称接口名称.desktop。使用这些信息,我们可以相对容易地创建一个正在运行的 GUI 应用程序列表,以它们的“可读”名称表示。

然而,在这种情况下,现实也比理论更复杂,正如这里所解释的。


Ser*_*nyy 4

qdbus使用和界面执行此操作的方法org.ayatana.bamf

按文件列出的打开的应用程序列表.desktop

$ qdbus org.ayatana.bamf /org/ayatana/bamf/matcher \                           
> org.ayatana.bamf.matcher.RunningApplicationsDesktopFiles
/usr/share/applications/compiz.desktop
/usr/share/applications/firefox.desktop
/usr/share/applications/x-terminal-emulator.desktop
Run Code Online (Sandbox Code Playgroud)

使用org.ayatana.bamf.matcher.RunningApplicationsorg.ayatana.bamf.view.Name方法

$ qdbus org.ayatana.bamf /org/ayatana/bamf/matcher  \                          
> org.ayatana.bamf.matcher.RunningApplications | \                             
> xargs -I {} qdbus org.ayatana.bamf {} org.ayatana.bamf.view.Name
Firefox Web Browser
MY CUSTOM TERMINAL
Compiz
Run Code Online (Sandbox Code Playgroud)