I am trying to make a very simple window manager for learning purposes. I am using C
and the xcb
library. I am trying to get an event raised if a new application is launched.
For now, I create a root window where I can receive mouse and keyboard events. I also draw a colored bar on the top of the window. When I press enter, xterm will launch using fork and execvp. This all works great.
When xterm (or any application I think) launches, it gets drawn on top of the bar (x = 0, y = 0). I would like to move it a bit lower (x = 0, y = 16). I think I know how to move the window, using xcb_configure_window
. But I don't know how to get an event for the newly launched application.
Edit:
After some messing around I came to the following conclusions:
If I create my parent window like this:
xcb_window_t window_root = screen->root;
uint32_t mask = 0;
uint32_t values[2];
mask = XCB_CW_EVENT_MASK;
values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY;
xcb_change_window_attributes_checked(connection, window_root, mask, values);
xcb_flush(connection);
i will receive a XCB_CREATE_NOTIFY when I spawn a new terminal. However, I am not able to draw anything on the screen, because I am not "subscribed" to the XCB_EVENT_MASK_EXPOSE
event. If I change the values[0] line to this:
values[0] = XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_EXPOSURE;
i will still receive creation events, but the expose event does not get called as soon as the program starts, so my bar will not get drawn. It will get an expose event as soon as I launch a new terminal though, but my initial drawing won't happen.
My old method of creating a parent window was:
xcb_window_t window = xcb_generate_id(connection);
uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
uint32_t values[2] = {screen->white_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY };
xcb_create_window(connection, 0, window, screen->root, 0, 0, screen->width_in_pixels, screen->height_in_pixels, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, mask, values);
xcb_map_window(connection, window);
This will draw a white background and draw my colored bar, because it immediately gets an XCB_EVENT_MASK_EXPOSURE event. But it won't get an XCB_CREATE_NOTIFY event.
So what is the correct way to get both the XCB_CREATE_NOTIFY events and the XCB_EVENT_MASK_EXPOSURE events?