使用 Xlib 获取应用程序的图标?
Get application's icon using Xlib?
我花了大约两天的时间才达到目标,但是我没有做到我需要的。我的目标是在我的 C++ 应用程序中从应用程序的 window 获取图标并将其保存到 wxIcon (或 wxImage 或 wxBitmap - 无关紧要)对象中。
正如我在互联网上发现的那样,有两种变体可以检索图标:使用 _NET_WM_ICON
window 属性 和使用 XGetWMHints
(通过从 XWMHints
结构获取像素图) .
这就是我尝试实现第一种方法的方式:
void ApplicationHelper::GetIcon(SRunningWindow* pDesc, void* pDisplay,
TWindow iWindow, unsigned long uiIconAtom)
{
unsigned long nitems, bytesafter;
unsigned char *ret;
int format;
Atom type;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 0, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int width = *(int*)ret;
XFree(ret);
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 1, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int height = *(int*)ret;
XFree(ret);
int size = width * height;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 2, size, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
unsigned char* imgData = new unsigned char[width * height * 3]; // RGB data
unsigned char* alphaData = new unsigned char[width * height]; // alpha chanel
int offset = sizeof(long) == 8 ? 8 : 4; // for 64bit systems data represented in order: blue, green, red, alpha, followed by 4 zeros
int imgIdx = 0;
int alphaIdx = 0;
for (int i=0; i < nitems; i += offset)
{
imgData[imgIdx] = ret[i + 2]; // R
imgData[imgIdx + 1] = ret[i + 1]; // G
imgData[imgIdx + 2] = ret[i]; // B
alphaData[alphaIdx++] = ret[i + 3]; // A
imgIdx += 3;
}
XFree(ret);
wxImage img(width, height, imgData, alphaData);
img.Rescale(16, 16);
wxBitmap bmp(img);
pDesc->icon.CopyFromBitmap(bmp);
}
但是我用这段代码得到的图标与应用程序的图标不一样:
关于获取图标的第二种变体(从 XGetWMHints
结构获取像素图)我发现,icon_pixmap
字段被定义为 XID
,即 unsigned long
而我没有找不到如何从此 icon_pixmap
.
获取 XPM 数据
所以你能解释一下我在代码中做错了什么或者如何从 XWMHints
结构的 'icon_pixmap' 字段中获取图标吗?
谢谢。
以防万一其他人需要解决方案:
void ApplicationHelper::GetIcon(SRunningWindow* pDesc, void* pDisplay, TWindow iWindow, unsigned long uiIconAtom)
{
unsigned long nitems, bytesafter;
unsigned char *ret;
int format;
Atom type;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 0, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int width = *(int*)ret;
XFree(ret);
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 1, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int height = *(int*)ret;
XFree(ret);
int size = width * height;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 2, size, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
unsigned int* imgData = new unsigned int[size];
unsigned long* ul = (unsigned long*)ret;
for (int i=0; i < nitems; ++i)
{
imgData[i] = (unsigned int)ul[i];
}
XFree(ret);
wxImage img(width, height);
img.InitAlpha();
unsigned char* argb = (unsigned char*)imgData;
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{
unsigned char a = argb[3];
unsigned char r = argb[2] * a / 255;
unsigned char g = argb[1] * a / 255;
unsigned char b = argb[0] * a / 255;
img.SetRGB(x, y, r, g, b);
img.SetAlpha(x, y, a);
argb += 4;
}
}
img.Rescale(32, 32);
wxBitmap bmp(img);
delete[]imgData;
pDesc->icon.CopyFromBitmap(bmp);
}
这个想法只是从 "raw" 数据创建 wxImage。在 x64 Ubuntu 16.04 上有效
我花了大约两天的时间才达到目标,但是我没有做到我需要的。我的目标是在我的 C++ 应用程序中从应用程序的 window 获取图标并将其保存到 wxIcon (或 wxImage 或 wxBitmap - 无关紧要)对象中。
正如我在互联网上发现的那样,有两种变体可以检索图标:使用 _NET_WM_ICON
window 属性 和使用 XGetWMHints
(通过从 XWMHints
结构获取像素图) .
这就是我尝试实现第一种方法的方式:
void ApplicationHelper::GetIcon(SRunningWindow* pDesc, void* pDisplay,
TWindow iWindow, unsigned long uiIconAtom)
{
unsigned long nitems, bytesafter;
unsigned char *ret;
int format;
Atom type;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 0, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int width = *(int*)ret;
XFree(ret);
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 1, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int height = *(int*)ret;
XFree(ret);
int size = width * height;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 2, size, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
unsigned char* imgData = new unsigned char[width * height * 3]; // RGB data
unsigned char* alphaData = new unsigned char[width * height]; // alpha chanel
int offset = sizeof(long) == 8 ? 8 : 4; // for 64bit systems data represented in order: blue, green, red, alpha, followed by 4 zeros
int imgIdx = 0;
int alphaIdx = 0;
for (int i=0; i < nitems; i += offset)
{
imgData[imgIdx] = ret[i + 2]; // R
imgData[imgIdx + 1] = ret[i + 1]; // G
imgData[imgIdx + 2] = ret[i]; // B
alphaData[alphaIdx++] = ret[i + 3]; // A
imgIdx += 3;
}
XFree(ret);
wxImage img(width, height, imgData, alphaData);
img.Rescale(16, 16);
wxBitmap bmp(img);
pDesc->icon.CopyFromBitmap(bmp);
}
但是我用这段代码得到的图标与应用程序的图标不一样:
关于获取图标的第二种变体(从 XGetWMHints
结构获取像素图)我发现,icon_pixmap
字段被定义为 XID
,即 unsigned long
而我没有找不到如何从此 icon_pixmap
.
所以你能解释一下我在代码中做错了什么或者如何从 XWMHints
结构的 'icon_pixmap' 字段中获取图标吗?
谢谢。
以防万一其他人需要解决方案:
void ApplicationHelper::GetIcon(SRunningWindow* pDesc, void* pDisplay, TWindow iWindow, unsigned long uiIconAtom)
{
unsigned long nitems, bytesafter;
unsigned char *ret;
int format;
Atom type;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 0, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int width = *(int*)ret;
XFree(ret);
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 1, 1, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
int height = *(int*)ret;
XFree(ret);
int size = width * height;
XGetWindowProperty((Display*) pDisplay, iWindow, uiIconAtom, 2, size, 0, AnyPropertyType, &type, &format, &nitems, &bytesafter, &ret);
unsigned int* imgData = new unsigned int[size];
unsigned long* ul = (unsigned long*)ret;
for (int i=0; i < nitems; ++i)
{
imgData[i] = (unsigned int)ul[i];
}
XFree(ret);
wxImage img(width, height);
img.InitAlpha();
unsigned char* argb = (unsigned char*)imgData;
for(int y = 0; y < height; y++)
{
for(int x = 0; x < width; x++)
{
unsigned char a = argb[3];
unsigned char r = argb[2] * a / 255;
unsigned char g = argb[1] * a / 255;
unsigned char b = argb[0] * a / 255;
img.SetRGB(x, y, r, g, b);
img.SetAlpha(x, y, a);
argb += 4;
}
}
img.Rescale(32, 32);
wxBitmap bmp(img);
delete[]imgData;
pDesc->icon.CopyFromBitmap(bmp);
}
这个想法只是从 "raw" 数据创建 wxImage。在 x64 Ubuntu 16.04 上有效