![如何找到链接到可执行文件的图标文件?](https://linux22.com/image/213224/%E5%A6%82%E4%BD%95%E6%89%BE%E5%88%B0%E9%93%BE%E6%8E%A5%E5%88%B0%E5%8F%AF%E6%89%A7%E8%A1%8C%E6%96%87%E4%BB%B6%E7%9A%84%E5%9B%BE%E6%A0%87%E6%96%87%E4%BB%B6%EF%BC%9F.png)
我正在构建一个窗口管理器,我需要找到与任务栏正在运行的可执行文件相关的图标。我找到了图标规范并能够找到所有图标/usr/share/icons/theme_name
(我在 arch linux 上,如果这很重要的话)。我还找到.desktop
了/usr/share/applications
.
问题是将.desktop
文件与正在运行的可执行文件链接起来。我认为正在运行的窗口的名称应该与.desktop
文件的名称相匹配;但是,正在运行的窗口的名称更具体于窗口本身。例如,在终端上调用XGetWindowProperty
将返回名称作为终端当前所在的目录,而 Visual Studio Code 将返回文件名、用户名和“Visual Studio Code”。
有什么方法可以将两者联系起来吗?就像知道.desktop
哪个运行窗口使用哪个文件一样。或者甚至直接知道哪个图标应该由哪个运行窗口使用?
答案1
正在运行的 X11 应用程序不会引用图标文件,它会使其图标图像数据在该_NET_WM_ICON
财产附加到应用程序窗口。通过解码可以找到要显示的图像数据:
这是客户端可能的图标数组。本规范没有规定这些图标的大小,但个别桌面环境或工具包可能会这样做。窗口管理器可以将这些图标中的任何一个缩放到适当的大小。
这是一个 32 位封装的 CARDINAL ARGB 数组,高字节为 A,低字节为 B。前两个基数是宽度、高度。数据按行排列,从左到右、从上到下。
答案2
Stephen Kitt 指出了 _NET_WM_ICON 属性。我最终弄清楚了如何从中获取图像数据。
以下是我的实现,其中img_data
是生成的 ARGB 原始图像数据。我使用 Imlib2 来显示图像。
const Atom NET_WM_ICON = XInternAtom(DISPLAY, "_NET_WM_ICON", false);
const Atom CARDINAL = XInternAtom(DISPLAY, "CARDINAL", false);
Atom type_return;
int format_return;
unsigned long nitems_return;
unsigned long bytes_after_return;
unsigned char* data_return;
XGetWindowProperty(DISPLAY, window, NET_WM_ICON, 0, 1, false, CARDINAL, &type_return, &format_return, &nitems_return, &bytes_after_return, &data_return);
const int width = *(int*)data_return;
XFree(data_return);
XGetWindowProperty(DISPLAY, window, NET_WM_ICON, 1, 1, false, CARDINAL, &type_return, &format_return, &nitems_return, &bytes_after_return, &data_return);
const int height = *(int*)data_return;
XFree(data_return);
XGetWindowProperty(DISPLAY, window, NET_WM_ICON, 2, width * height, false, CARDINAL, &type_return, &format_return, &nitems_return, &bytes_after_return, &data_return);
uint32_t* img_data = new uint32_t[width * height];
const ulong* ul = (ulong*)data_return;
for(int i = 0; i < nitems_return; i++)
{
img_data[i] = (uint32_t)ul[i];
}
XFree(data_return);
答案3
我们可以调用以下脚本来./gjs-script "org.gnome.Calculator.desktop"
获取图标:
#!/usr/bin/env gjs
const { Gio } = imports.gi;
let apps = Gio.AppInfo.get_all().find(a => a.get_id() == ARGV[0]);
print(apps.get_icon().to_string());