Search code examples
c++cscreenx11splash-screen

I want to make splash screen and now I have two problems?


1: I want to have a splash screen but I only have a window?so,how to do with sth like parm

2: I've used a while(!done) to draw the window so how to break out with a function or sth else

here is my code and much thx to you

g++ -o m_splash m_splash.cpp -lX11 -lImlib2

#include <stdio.h>
#include <X11/Xlib.h>
#include <Imlib2.h>
#include <unistd.h>

int main()
{
    Imlib_Image  m_img;
    Display     *m_dpy;
    Pixmap       m_pix;
    Window       m_root;
    Screen      *scn;
    int m_width, m_height;
    const char *filename = "/home/ang/so_zt/w.png";

    m_img = imlib_load_image(filename);
    if(!m_img)
    {
        printf("%s\n","init m_img faild");
    }
    imlib_context_set_image(m_img);
    m_width = imlib_image_get_width();
    m_height = imlib_image_get_height();

    m_dpy = XOpenDisplay(NULL);
    if(!m_dpy)
    {
        printf("%s\n","open display failed");
    }
    scn = DefaultScreenOfDisplay(m_dpy);
    int s = DefaultScreen(m_dpy);
    m_root = XCreateSimpleWindow(m_dpy, RootWindow(m_dpy,s),10,10,m_width,m_height,0,
                                 BlackPixel(m_dpy, s), WhitePixel(m_dpy, s));
    m_pix = XCreatePixmap(m_dpy, m_root, m_width, m_height, DefaultDepthOfScreen(scn));

    imlib_context_set_display(m_dpy);
    imlib_context_set_visual(DefaultVisualOfScreen(scn));
    imlib_context_set_colormap(DefaultColormapOfScreen(scn));
    imlib_context_set_drawable(m_pix);

    imlib_render_image_on_drawable(0,0);
    XSetWindowBackgroundPixmap(m_dpy, m_root, m_pix);
    XClearWindow(m_dpy, m_root);
    Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(m_dpy, m_root, &wmDeleteMessage, 1);

    XSelectInput(m_dpy, m_root, ExposureMask | KeyPressMask | StructureNotifyMask);
    XMapWindow(m_dpy, m_root);
    bool done = false;
    while (!done)
    {
        XEvent m_ev;
        XNextEvent(m_dpy, &m_ev);
        /* draw or redraw the window */
        if (m_ev.type == Expose)
        {
            XFillRectangle(m_dpy, m_root, DefaultGC(m_dpy, DefaultScreen(m_dpy)), 20, 20, 10, 10);
        }

    /* exit on key press */
        //usleep(1000000);
        //done = true;
        switch(m_ev.type)
        {
        case KeyPress:
            XDestroyWindow(m_dpy, m_root);
        break;

        case DestroyNotify:
            done = true;
        break;
        case ClientMessage:
            if (m_ev.xclient.data.l[0] == wmDeleteMessage)
            {
                done = true;
            }
        break;
        }
    }

    //XFreePixmap(m_dpy, m_pix);
    //imlib_free_image();
    //XCloseDisplay(m_dpy);
}

Solution

  • To make it a splash screen, use extended window manager hints.

    #include <X11/Xatom.h>
    
    Atom type = XInternAtom(m_dpy, "_NET_WM_WINDOW_TYPE", False);
    Atom value = XInternAtom(m_dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
    XChangeProperty(m_dpy, m_root, type, XA_ATOM, 32, PropModeReplace, reinterpret_cast<unsigned char*>(&value), 1);
    

    The window then appears without decorations and stays until clicked.

    When clicked you get an UnmapNotify event, so this what you should use to set done.

    To avoid having to get events, add

    XFlush(m_dpy);
    

    after mapping the window to display it and

    XUnmapWindow(m_dpy, m_root);
    

    when you want to get rid of it.

    In this example the program just sleeps for 5 seconds before continuing:

    #include <stdio.h>
    #include <X11/Xlib.h>
    #include <X11/Xatom.h>
    #include <Imlib2.h>
    #include <unistd.h>
    
    int main()
    {
        Imlib_Image  m_img;
        Display     *m_dpy;
        Pixmap       m_pix;
        Window       m_root;
        Screen      *scn;
        int m_width, m_height;
        const char *filename = "w.png";
    
        m_img = imlib_load_image(filename);
        if(!m_img)
        {
            printf("%s\n","init m_img faild");
        }
        imlib_context_set_image(m_img);
        m_width = imlib_image_get_width();
        m_height = imlib_image_get_height();
    
        m_dpy = XOpenDisplay(NULL);
        if(!m_dpy)
        {
            printf("%s\n","open display failed");
        }
        scn = DefaultScreenOfDisplay(m_dpy);
        int s = DefaultScreen(m_dpy);
        m_root = XCreateSimpleWindow(m_dpy, RootWindow(m_dpy,s),10,10,m_width,m_height,0,
                                     BlackPixel(m_dpy, s), WhitePixel(m_dpy, s));
        m_pix = XCreatePixmap(m_dpy, m_root, m_width, m_height, DefaultDepthOfScreen(scn));
    
        Atom type = XInternAtom(m_dpy, "_NET_WM_WINDOW_TYPE", False);
        Atom value = XInternAtom(m_dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
        XChangeProperty(m_dpy, m_root, type, XA_ATOM, 32, PropModeReplace, reinterpret_cast<unsigned char*>(&value), 1);
    
        imlib_context_set_display(m_dpy);
        imlib_context_set_visual(DefaultVisualOfScreen(scn));
        imlib_context_set_colormap(DefaultColormapOfScreen(scn));
        imlib_context_set_drawable(m_pix);
    
        imlib_render_image_on_drawable(0,0);
        XSetWindowBackgroundPixmap(m_dpy, m_root, m_pix);
        XClearWindow(m_dpy, m_root);
        Atom wmDeleteMessage = XInternAtom(m_dpy, "WM_DELETE_WINDOW", False);
        XSetWMProtocols(m_dpy, m_root, &wmDeleteMessage, 1);
    
        XMapWindow(m_dpy, m_root);
        XFlush(m_dpy);
        sleep(5);
        XUnmapWindow(m_dpy, m_root);
    }