1

My purpose is to draw an icon into the title bar of a basic wm i'm trying to create.

I already googled, and tried different solutions, but so far none is working (maybe just because of my lack of knowledge), i managed to display something from an icon, but it is not even close to what the icon is:

Current output

The icon was a floppy disk (with colours) So the code i used to display it is the following:

void get_system_icon(char* icon_name, Display *display, Window win){
    printf("Placeholder");
    unsigned int img_h;
    unsigned int img_w;
    unsigned int hotspot_x;
    unsigned int hotspot_y;

    Pixmap icon;
    XTextProperty icon_name_property;
    
    int width, height;
    int h_x, h_y;
    char *filename = "../default.ico";
    Imlib_Image img;
    img = imlib_load_image(filename);
    if(img == NULL){
            printf("Error loading imlibimage");
    }
    ScreenInfos infos = get_screen_informations(display);
    Screen *screen = DefaultScreenOfDisplay(display);
    imlib_context_set_image(img);
    img_w = imlib_image_get_width();
    img_h = imlib_image_get_height();
    printf("Img size: %d - %d\n", img_w, img_h);
    imlib_blend_image_onto_image(img,0,0,0, img_w, img_h, 0,0, infos.width,infos.height);
    Pixmap my_pix;
    my_pix = XCreatePixmap(display, win, img_w, img_h, DefaultDepthOfScreen(screen));
    imlib_context_set_display(display);
    imlib_context_set_visual(DefaultVisualOfScreen(screen));
    imlib_context_set_colormap(DefaultColormapOfScreen(screen));
    imlib_context_set_drawable(my_pix);
    imlib_render_image_on_drawable(0, 0);

    XSizeHints* win_size_hints;
    XWMHints* win_hints;
    int return_code;
    return_code = XStringListToTextProperty(&icon_name,
                               1,
                               &icon_name_property);
    if(return_code == 0) {
        printf("Error");
    }
    XSetWMIconName(display, win, &icon_name_property);
    win_hints = XAllocWMHints();
    if (!win_size_hints) {
        fprintf(stderr, "XAllocSizeHints - out of memory\n");
        exit(1);
    }
    win_hints->flags = IconPixmapHint | StateHint | IconPositionHint;
    win_hints->icon_pixmap = my_pix;
    win_hints->initial_state = IconicState;
    win_hints->icon_x = 0;
    win_hints->icon_y = 0;

    /* pass the hints to the window manager. */
    XSetWMHints(display, win, win_hints);

    /* finally, we can free the WM hints structure. */
    GC gc;
    gc = XCreateGC(display, win, 0, NULL);
    //XPutImage(display, win, gc, 
    XSetBackground(display, gc, WhitePixel(display, DefaultScreen(display)));   
    //WhitePixel(display, DefaultScreen(display));

    XCopyPlane(display, my_pix, win, gc,
                0, 0,
                30, 30,
                0, 0,
                1); 

    XFree(win_hints);
XFlush(display);
}

there are several question that i didn't found an answer anywhere,

  • in many of the solution that i searched, i noticed that the icon data was stored into the WM_HINTS, but it was not clear if that structure was just holding the icon information for future references, or was actually displaying the icon somehow (i think more the first case applies, and in the examples i found that displayed an icon i suppose was because the current window manager was adding it).
  • I used a similar code to set the background to the wm, and it that case it worked (check here: https://github.com/inuyasha82/uwm/blob/master/src/background.c) so i supposed i should do something similar, but apparently not, what is wrong?
  • I tried to use .bmp and .ico format and what i noticed is that the output was different (but always 2 colors, and completely wrong)

So I'm pretty sure that my code is all wrong, but i can't find anywhere a good example of how to draw an icon on a window, can someone help me please?

Ivan
  • 4,186
  • 5
  • 39
  • 72

1 Answers1

0

So finally after more than one year I found a solution (more or less) to this issue.

I found the answer on a similar SO question: How to load bmp file using x11 window background

So basically the first part of my code was pretty correct (the image loading using imlib).

But the wholse WM_Hints part was not necessary, and also to draw the pixmap i was using a GC (probably there is a way to draw with it too, but i don't know).

Tshe only thing needed once the image is loaded is to use XSetWindowBackgroundPixmap:

XSetWindowBackgroundPixmap(dpy, root, pix);

So the updated function now is:

void get_system_icon(char* icon_name, Display *display, Window win){
    unsigned int img_h;
    unsigned int img_w;
    char *filename = "../default.bmp";
    Pixmap my_pix;
    Imlib_Image img;

    img = imlib_load_image(filename);
    if(img == NULL){
            printf("Error loading imlibimage");
    }
    Screen *screen = DefaultScreenOfDisplay(display);
    imlib_context_set_image(img);
    img_w = imlib_image_get_width();
    img_h = imlib_image_get_height();
    printf("Img size: %d - %d\n", img_w, img_h);
    my_pix = XCreatePixmap(display, win, img_w, img_h, DefaultDepthOfScreen(screen));
    imlib_context_set_display(display);
    imlib_context_set_visual(DefaultVisualOfScreen(screen));
    imlib_context_set_colormap(DefaultColormapOfScreen(screen));
    imlib_context_set_drawable(my_pix);
    imlib_render_image_on_drawable(0, 0);
    XSetWindowBackgroundPixmap(display, win, my_pix);
    XClearWindow(display, win);
    XFreePixmap(display, my_pix);
    imlib_free_image();
}

It basically:

  • loads an image using imlib (in this case is default.bmp)
  • It creates a pixmap on the window win of the size of the image
  • sets the X drawable to which images will be rendered as the pixmap created.
  • Set the pixmap as a background of the window.
  • It frees the resources once done

In this way the image is showed correctly on the window. I don't know if it isn't the correct way to do it, but at least it is working.

Ivan
  • 4,186
  • 5
  • 39
  • 72