Package: xcompmgr Version: 1.1.5-1 Hi!
I'm writing a program that uses the SHAPE extensions to give a window a non-rectangular shape. This works up to the point where I try to modify the shape at runtime. The attached example program creates a simple window of 50x50 pixels. It then creates a moving square of 10x10 pixels inside that window which is not part of the window, using the SHAPE extension, so that you can watch the background or underlying window through this hole. While xcompmgr is running, the window isn't updated correctly. I tried this using fluxbox (which itself has some problems with X11 SHAPE), but it also happens with openbox, icewm or windowmaker, it even happens when not using any windowmanager at all. I tried using compiz as compositing and window manager, but failed getting it to run even halfway. The system is an old Mac Mini, using an ATI Radeon videochip and running a current Debian/testing system. Give me some feedback if you can't reproduce this, I'll try to circle in the other factors then. Cheers! Uli -- System Information: Debian Release: squeeze/sid APT prefers testing APT policy: (500, 'testing'), (500, 'stable'), (1, 'experimental') Architecture: powerpc (ppc) Kernel: Linux 2.6.32-5-powerpc Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages xcompmgr depends on: ii libc6 2.11.2-2 Embedded GNU C Library: Shared lib ii libx11-6 2:1.3.3-3 X11 client-side library ii libxcomposite1 1:0.4.2-1 X11 Composite extension library ii libxdamage1 1:1.1.3-1 X11 damaged region extension libra ii libxfixes3 1:4.0.5-1 X11 miscellaneous 'fixes' extensio ii libxrender1 1:0.9.6-1 X Rendering Extension client libra
// Example program for bug in xcompmgr // // This should display a window with a moving hole in it, but with xcompmgr // running, it isn't updated correctly. // // g++ -Wall `pkg-config xcb xcb-shape --cflags --libs` bug-shape-changer.cpp -o bug-shape-changer // #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; unsigned const window_size = 50; unsigned const hole_size = 10; int hole_position = 0; 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; } void set_window_mask() { // set rectangualar base outline first xcb_rectangle_t const rect = {0, 0, window_size, window_size}; xcb_shape_rectangles(connection, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, 0, win, 0, 0, // offset 1, &rect); // cut out moving rectangle xcb_rectangle_t const hole = {hole_position, hole_position, hole_size, hole_size}; xcb_shape_rectangles(connection, XCB_SHAPE_SO_SUBTRACT, XCB_SHAPE_SK_BOUNDING, 0, win, 0, 0, // offset 1, &hole); xcb_flush(connection); } int main(int argc, char** argv) { try { init_connection(); create_window(0, 0, window_size, window_size); set_window_mask(); // 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 = 100000; timeout.tv_sec = 0; 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; ++hole_position; if(hole_position==window_size) hole_position = -hole_size; set_window_mask(); 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; } }