I want to set a icon in Linux/X11 at the start of my C++ program.
The following code i tried does not work at all - nether in XFCE or Gnome or KDE. Did i something wrong here, i dont see any mistakes?
fpl_internal void fpl__X11LoadWindowIcon(const fpl__X11Api *x11Api, fpl__X11WindowState *x11WinState, fplWindowSettings *windowSettings) {
// @TODO(final): Setting the window icon on X11 does not fail, but it does not show up in any of the bars
// In gnome/ubuntu the icon is always shown as "unset"
int iconSourceCount = 0;
fplImageSource iconSources[2] = FPL_ZERO_INIT;
if (windowSettings->icons[0].width > 0) {
iconSources[iconSourceCount++] = windowSettings->icons[0];
}
if (windowSettings->icons[1].width > 0) {
iconSources[iconSourceCount++] = windowSettings->icons[1];
}
if (iconSourceCount > 0) {
int targetSize = 0;
for (int i = 0; i < iconSourceCount; ++i) {
targetSize += 2 + iconSources[i].width * iconSources[i].height;
}
// @MEMORY(final): Do not allocate memory here, use a static memory block or introduce a temporary memory arena!
uint32_t *data = (uint32_t *) fplMemoryAllocate(sizeof(uint32_t) * targetSize);
uint32_t *target = data;
for (int i = 0; i < iconSourceCount; ++i) {
const fplImageSource *iconSource = iconSources + i;
FPL_ASSERT(iconSource->type == fplImageType_RGBA);
*target++ = (int32_t) iconSource->width;
*target++ = (int32_t) iconSource->height;
const uint32_t *source = (const uint32_t *)iconSource->data;
for (int j = 0; j < iconSource->width * iconSource->height; ++j) {
// @TODO(final): Do we need to swap the byte order of the icon in X11?
#if 0
*target++ = (iconSource->data[j * 4 + 0] << 16) |
(iconSource->data[j * 4 + 1] << 8) |
(iconSource->data[j * 4 + 2] << 0) |
(iconSource->data[j * 4 + 3] << 24);
#else
*target++ = *source;
#endif
}
}
x11Api->XChangeProperty(x11WinState->display, x11WinState->window, x11WinState->netWMIcon, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) data, targetSize);
// @MEMORY(final): Do not free memory here, see note above!
fplMemoryFree(data);
} else {
x11Api->XDeleteProperty(x11WinState->display, x11WinState->window, x11WinState->netWMIcon);
}
x11Api->XFlush(x11WinState->display);
}