Hi!

I noticed in a different context that fluxbow was sending superfluous "expose" 
events when losing and gaining focus. These events are normally sent when 
parts of a window were exposed and thus need redrawing. I guess these could be 
responsible for the anomalous flickering.

The attached example program just creates a simple window using the X11 SHAPE 
extension. You can see that when losing focus, the window receives two expose 
events and when the window gains focus it receives four expose events. All 
these events are seemingly unnecessary, since nothing in the window was 
actually exposed.

Notes:
 - I also tried the same program under icewm, where these events are not sent.
 - I have noticed that both gmplayer and xine suffer from the flickering, but 
I don't actually know if it is caused by the expose events.
 - I'm not sure if this is related, but #593061 is also about focus handling. 
I noticed here that when entering the window created by the example program, 
the window doesn't always receive focus. In particular when I cross the border 
quickly it seems to sometimes miss this.

I hope this helps a bit.

Uli
// Example program for Debian bug #544112
//
// g++ -Wall `pkg-config xcb xcb-shape --cflags --libs`
//

#include <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/shape.h>
#include <iostream>
#include <stdexcept>
#include <assert.h>

/* global objects, the connection to the X server and the window
created there. */
xcb_connection_t* connection = 0;
xcb_window_t win;


void
init_connection()
{
    /* open connection to the server */
    connection = xcb_connect(NULL,NULL);
    if (xcb_connection_has_error(connection))
        throw std::runtime_error("xcb_connect() failed");
}


void
check_shape_extension()
{
    // query for availability
    xcb_query_extension_reply_t const* reply = xcb_get_extension_data(
        connection, &xcb_shape_id);
    if(!reply)
        throw std::runtime_error("xcb_get_extension_data failed");
    if(!reply->present)
        throw std::runtime_error("X11 shape extension not present");

    // query version
    xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version_unchecked(connection);
    xcb_shape_query_version_reply_t* version = xcb_shape_query_version_reply(connection,
        cookie, 0);
    if(!version)
        throw std::runtime_error("xcb_shape_query_version failed");
}


void
create_window(int16_t x, int16_t y, uint16_t width, uint16_t height)
{
    /* retrieve the first screen from the setup */
    xcb_setup_t const* setup = xcb_get_setup(connection);
    if(!setup)
        throw std::runtime_error("xcb_get_setup() failed");
    xcb_screen_t* screen = xcb_setup_roots_iterator(setup).data;
    if(!screen)
        throw std::runtime_error("missing root screen");

    // create window
    xcb_window_t id = xcb_generate_id(connection);
    uint32_t const win_values[] =
    {
        screen->black_pixel,
        XCB_EVENT_MASK_EXPOSURE
    };
    xcb_create_window(connection,
        XCB_COPY_FROM_PARENT, // depth
        id,
        screen->root, // parent
        x, y, width, height, // position, size
        0, // border width
        XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
        XCB_COPY_FROM_PARENT, // visual
        XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, win_values);
    win = id;
}


int
main(int argc, char** argv)
{
    try
    {
        init_connection();

        create_window(0, 0, 50, 50);

        // set rectangualar base outline
        xcb_rectangle_t const rect = {0, 0, 50, 50};
        xcb_shape_rectangles(connection,
            XCB_SHAPE_SO_SET,
            XCB_SHAPE_SK_BOUNDING,
            0,
            win,
            0, 0, // offset
            1, &rect);

        // actually display window
        xcb_map_window(connection, win);

        int const e = xcb_flush(connection);
        if(e<=0)
            // TODO: provide more detailed diagnostics if possible
            throw std::runtime_error("xcb_flush failed");

        // poll connection's file descriptor for events
        int const ss = xcb_get_file_descriptor(connection);
        while(true)
        {
            // wait on the connection socket
            fd_set fd;
            FD_ZERO(&fd);
            FD_SET( ss, &fd);
            timeval timeout;
            timeout.tv_usec = 0;
            timeout.tv_sec =  1;
            switch(select( ss+1, &fd, 0, 0, &timeout))
            {
            case -1:
                throw std::runtime_error("select failed");
            case 0:
                std::cout << "select timed out" << std::endl;
                break;
            case 1:
                break;
            default:
                std::cout << "select return unexpected value" << std::endl;
                break;
            }

            // handle all available events
            xcb_generic_event_t* e = 0;
            while((e = xcb_poll_for_event(connection)))
            {
                switch (e->response_type & ~0x80)
                {
                case XCB_EXPOSE:
                    {
                        /* Note: Filling the whole window with background color is done
                        automatically, so we don't have to do anything here at all. */
                        xcb_expose_event_t const& expose = (xcb_expose_event_t const&)*e;
                        std::cout << "expose_event x=" << expose.x
                            << ", y=" << expose.y
                            << ", width=" << expose.width
                            << ", height=" << expose.height
                            << ", count=" << expose.count
                            << std::endl;
                    }
                    break;
                default:
                    std::cout << "received response " << unsigned(e->response_type) << std::endl;
                    break;
                }
                free(e);
            }

            // check for connection errors
            if (xcb_connection_has_error(connection))
                throw std::runtime_error("connection lost");
        }

        return EXIT_SUCCESS;
    }
    catch(std::exception const& e)
    {
        std::cerr << "error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }
}

Reply via email to