Advertisement

[Solved] How to set the window + bars icon in X11

Started by July 19, 2018 06:52 PM
1 comment, last by Finalspace 6 years, 1 month ago

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);
}

 

 

Solved.

The function was almost correct. Using uint32_t as a buffer was my mistake. It must be unsigned long instead!

Also the RGBA byte swap was required, otherwise you get a weird or blank icon.

This topic is closed to new replies.

Advertisement