I am writing a window list into my C application that shows all of the top level windows, including shaded, minimized, and on other desktops. I would like to restore unmapped (minimized) windows, raise the window, and switch to the window's desktop/workspace when one is selected.
I had written something to accomplish this in the past using Xlib. I used XSendEvent() to send a ClientMessage event of type _NET_ACTIVE_WINDOW followed by XMapRaised() previously, and it worked fairly well, but not perfectly.
I am now rewriting the application and decided to use XCB for the window list code rather than Xlib and hoped to create a better and more efficient implementation. XCB has no equivalent to XMapRaised() and xcb_map_window() does not seem to work for me. I've found a fair amount of documentation on creating and configuring new windows but very little that would be of use for implementing a window manager or utility programs like pagers, iconboxes, taskbars, etc. The generated documentation for XCB is rather vague about what some of the functions actually do as well. If anyone is aware of additional documentation that would be of value for this, that would be great, too.
EDIT:
I duplicated a portion of the old code that uses Xlib in a small utility program and it does actually do most of what I want and seems to work consistently:
#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
int main(int argc, char **argv) {
Display *display = XOpenDisplay("");
Window rootwin = XDefaultRootWindow(display);
if (argc < 2)
{
printf("usage: %s windowid\n", argv[0]);
return 0;
}
Window window = (Window)strtoul(argv[1], NULL, 0);
printf("switch to window: 0x%lx\n", window);
Atom ActiveWindowAtom = XInternAtom(display, "_NET_ACTIVE_WINDOW", False);
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.window = window;
xev.xclient.message_type = ActiveWindowAtom;
xev.xclient.format = 32;
xev.xclient.data.l[0] = 1U;
xev.xclient.data.l[1] = 1U;
xev.xclient.data.l[2] = 0U;
xev.xclient.data.l[3] = 0U;
xev.xclient.data.l[4] = 0U;
XSendEvent(display, rootwin, False, SubstructureRedirectMask, &xev);
XMapRaised(display, window);
XCloseDisplay(display);
return 0;
}
...and then I unpacked the libX11 sources and confirmed that it does just wrap the XCB functions, but the wrappers use some libX11 data structures instead of the ones defined in XCB and there are so many macros being used that it's difficult to see exactly what is going on. This is the XCB equivalent I came up with, and it does not appear to work:
#include <stdlib.h>
#include <stdio.h>
#include <xcb/xcb.h>
#include "atom_cache.h"
int main(int argc, char **argv) {
xcb_connection_t *connection;
const xcb_setup_t *setup;
xcb_screen_iterator_t screen_iter;
xcb_screen_t *screen;
xcb_window_t rootwin, window;
xcb_void_cookie_t void_cookie;
xcb_client_message_event_t client_message_event;
if (argc < 2)
{
printf("usage: %s windowid\n", argv[0]);
return 0;
}
window = (xcb_window_t)strtoul(argv[1], NULL, 0);
printf("switch to window: 0x%x\n", window);
connection = xcb_connect(NULL, NULL);
setup = xcb_get_setup(connection);
screen_iter = xcb_setup_roots_iterator(setup);
screen = screen_iter.data;
rootwin = screen->root;
// send _net_active_window request
client_message_event.response_type = XCB_CLIENT_MESSAGE;
client_message_event.format = 32;
client_message_event.sequence = 0;
client_message_event.window = window;
client_message_event.type = get_atom(connection, "_NET_ACTIVE_WINDOW");
client_message_event.data.data32[0] = 1UL; // source: 1=application 2=pager
client_message_event.data.data32[1] = 1UL; // timestamp
client_message_event.data.data32[2] = 0UL; // my currently active window?
client_message_event.data.data32[3] = 0UL;
client_message_event.data.data32[4] = 0UL;
void_cookie = xcb_send_event(connection, 1, rootwin, XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&client_message_event);
uint32_t values[] = { XCB_STACK_MODE_ABOVE };
xcb_configure_window(connection, window, XCB_CONFIG_WINDOW_STACK_MODE, values);
xcb_map_window(connection, window);
xcb_flush(connection);
xcb_disconnect(connection);
return 0;
}
I'm still trying to figure this out.