Package: fluxbox
Version: 1.3.1~dfsg1-2

The attached file is an excerpt from a program. It creates a single window, 
undecorated, on top of other windows and in the upper left corner of the 
screen. At least it should do that, and it used to. At the moment, it only 
achieves parts of this, the resulting position is wrong.

The program uses XCB, but I have tried an earlier version of the program that 
uses Xlib, and it suddenly has the same problems, so that is not the cause for 
problems.

I have tried openbox, sawfish and icewm, and all three the WMs work as 
expected. I have also tried fluxbox 1.1.1+dfsg2-1 and it shows the same wrong 
behaviour as the current version. If that had always been the case, I'm pretty 
sure that I would have noticed before, because I've been running fluxbox for 
ages. That again makes me wonder if this is really just a problem with 
fluxbox, at least I suspect other influences, like possibly in the X server.


Cheers!

Uli
// g++ -g -O0 -W test.cpp $(pkg-config xcb xcb-icccm xcb-shape xcb-image --libs --cflags)

#include <xcb/xcb.h>
#include <xcb/xcb_icccm.h>
#include <stdint.h>
#include <stdexcept>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <iomanip>

xcb_connection_t* connection = 0;

xcb_atom_t
resolve_atom_name(char const* name)
{
    size_t const len = strlen(name);
    if(static_cast<uint16_t>(len) != len)
        throw std::runtime_error("xatom: name too long");
    xcb_intern_atom_cookie_t cookie = xcb_intern_atom(connection,
                                                      0, // only_if_exists
                                                      static_cast<uint16_t>(len),
                                                      name);
    xcb_generic_error_t* error = 0;
    xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(connection, cookie, &error);
    if(error)
        throw std::runtime_error("xcb_intern_atom_reply failed with error");
    if(!reply)
        throw std::runtime_error("xcb_intern_atom_reply failed without reply");
    xcb_atom_t const res = reply->atom;
    free(reply);
    return res;
}

int
main()
{
    try
    {
        /* open connection with the server */
        connection = xcb_connect(NULL,NULL);
        if (xcb_connection_has_error(connection))
            throw std::runtime_error("xcb_connect() failed");

        /* retrieve the setup */
        xcb_setup_t const* setup = xcb_get_setup(connection);
        if(!setup)
            throw std::runtime_error("xcb_get_setup() failed");

        /* get the first screen */
        xcb_screen_t* screen = xcb_setup_roots_iterator(setup).data;
        if(!screen)
            throw std::runtime_error("missing root screen");

        /* create window */
        uint32_t const win_values[] =
        {
            screen->white_pixel,
            ( XCB_EVENT_MASK_EXPOSURE
             |XCB_EVENT_MASK_BUTTON_PRESS
             |XCB_EVENT_MASK_BUTTON_RELEASE)
        };
        xcb_window_t window_id = xcb_generate_id(connection);
        xcb_create_window(connection,
                          XCB_COPY_FROM_PARENT, // depth
                          window_id,
                          screen->root, // parent
                          0, 0, // position
                          100, 100, // 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);

        // resolve properties, (IDs, types and values)
        xcb_atom_t const wm_name_atom = resolve_atom_name("_NET_WM_NAME");
        xcb_atom_t const wm_window_type_atom = resolve_atom_name("_NET_WM_WINDOW_TYPE");
        xcb_atom_t const win_layer_atom = resolve_atom_name("_WIN_LAYER");
        xcb_atom_t const utf8_string_atom = resolve_atom_name("UTF8_STRING");
        xcb_atom_t const cardinal_atom = resolve_atom_name("CARDINAL");
        xcb_atom_t const atom_atom = resolve_atom_name("ATOM");
        xcb_atom_t const wm_window_type_desktop_atom = resolve_atom_name("_NET_WM_WINDOW_TYPE_DESKTOP");

        // set window name
        xcb_change_property(connection,
                            XCB_PROP_MODE_REPLACE,
                            window_id,
                            wm_name_atom,
                            utf8_string_atom,
                            8,
                            strlen("test"), "test");

        // set layer to 10 (above dock)
        uint32_t layer = 10;
        xcb_change_property(connection,
                            XCB_PROP_MODE_REPLACE,
                            window_id,
                            win_layer_atom,
                            cardinal_atom,
                            32,
                            1, &layer);

        // set window type to desktop element to avoid decoration
        xcb_change_property(connection,
                            XCB_PROP_MODE_REPLACE,
                            window_id,
                            wm_window_type_atom,
                            atom_atom,
                            32,
                            1, &wm_window_type_desktop_atom);

        // create graphics context
        uint32_t const gc_values[] =
        {
            0x00bbffff, // foreground color
            0 // graphics exposures flag
        };
        xcb_gcontext_t gc_id = xcb_generate_id(connection);
        xcb_create_gc(connection,
                      gc_id,
                      window_id,
                      XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES, gc_values);

        xcb_map_window(connection, window_id);


        uint32_t const values[] = {0, 0};
        xcb_configure_window(connection,
                             window_id,
                             XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);

        xcb_flush(connection);

        bool shutdown = false;
        while(!shutdown)
        {
            if(xcb_generic_event_t* e = xcb_poll_for_event(connection))
            {
                switch (e->response_type & ~0x80)
                {
                case XCB_EXPOSE:
                    {
                        xcb_expose_event_t const& expose = *(xcb_expose_event_t const*)e;
                        std::cout << "received event XCB_EXPOSE" << std::endl;
                        /* Ignore expose events if further of them follow, we always
                        repaint all of it anyway. */
                        if(expose.count == 0)
                            xcb_flush(connection);
                    }
                    break;
                case XCB_BUTTON_PRESS:
                    std::cout << "received event XCB_BUTTON_PRESS" << std::endl;
                    shutdown = true;
                    break;
                default:
                    std::cout << "received event 0x" << std::hex << std::setfill('0')
                        << std::setw(2) << unsigned(e->response_type) << std::endl;
                    break;
                }

                free(e);
            }
            else
            {
                usleep(1000);
            }
        }
    }
    catch(std::exception const& e)
    {
        std::cerr << "caught exception: " << e.what() << std::endl;
    }
}

Reply via email to