Суть задачи в следующем: нужно получить иконку из окна приложения посредством xlib и поместить её в объект wxIcon (или wxImage или wxBitmap - не важно). Как мне удалось выяснить, есть два способа это сделать: используя свойство окна _NET_WM_ICON
или через вызов XGetWMHints
получить объект XWMHints
, а из него достать icon_pixmap
. Однако, со вторым методом проблемы возникли со старта: icon_pixmap
определён как обычный unsigned long
и как оттуда получить XPM-содержимое иконки я так и не нашел. Вот моя попытка реализовать первый вариант:
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);
}
С его помощью, получается выцепить какую-то картинку, но она совсем не такая, как есть у приложения:
Первые три окна должны быть иконки терминала, примерно такие:
Но по факту получается что-то всоем не то. Вроде как, делал все в соответствии со спецификацией, но в итоге ерунда какая-то.
Может кто подсказать, что не так в моей реализации или как получить XPM-содержимое иконки из icon_pixmap
?
Спасибо.
Если вдруг кто-нибудь еще столкнется с этой проблемой, то вот решение, которое сработало для меня. Идея в том, что бы из ARGB представления иконки самому собрать wxImage, ну и не стоит забывать, что _NET_WM_ICON возвращает содержимое в формате BGRA.
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);
}
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Виртуальный выделенный сервер (VDS) становится отличным выбором
Как сделать переход из одного фрагмента в другой с помощью кнопки на экране?(без TabLayout)Если можно,буду благодарен за код
как создать ImageTextButton, в интернете гораздо меньше информации об этом, чем о простом ImageButton, есть у кого-то пример создания этой кнопочки с текстом?