Implement support for WM_CLIENT_LEADER

This commit is contained in:
Michael Stapelberg 2010-11-12 23:46:03 +01:00
parent 1bb6906c56
commit ad9be5402a
8 changed files with 59 additions and 26 deletions

View File

@ -212,6 +212,10 @@ struct xoutput {
struct Window { struct Window {
xcb_window_t id; xcb_window_t id;
/** Holds the xcb_window_t (just an ID) for the leader window (logical
* parent for toolwindows and similar floating windows) */
xcb_window_t leader;
char *class_class; char *class_class;
char *class_instance; char *class_instance;

View File

@ -191,6 +191,7 @@ int handle_hints(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t
int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state,
xcb_window_t window, xcb_atom_t name, xcb_window_t window, xcb_atom_t name,
xcb_get_property_reply_t *reply); xcb_get_property_reply_t *reply);
#endif
/** /**
* Handles changes of the WM_CLIENT_LEADER atom which specifies if this is a * Handles changes of the WM_CLIENT_LEADER atom which specifies if this is a
@ -200,6 +201,5 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state,
int handle_clientleader_change(void *data, xcb_connection_t *conn, int handle_clientleader_change(void *data, xcb_connection_t *conn,
uint8_t state, xcb_window_t window, uint8_t state, xcb_window_t window,
xcb_atom_t name, xcb_get_property_reply_t *prop); xcb_atom_t name, xcb_get_property_reply_t *prop);
#endif
#endif #endif

View File

@ -24,4 +24,10 @@ void window_update_name(i3Window *win, xcb_get_property_reply_t *prop);
*/ */
void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop); void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop);
/**
* Updates the CLIENT_LEADER (logical parent window).
*
*/
void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop);
#endif #endif

View File

@ -53,9 +53,18 @@ void floating_enable(Con *con, bool automatic) {
* to (0, 0), so we push them to a reasonable position * to (0, 0), so we push them to a reasonable position
* (centered over their leader) */ * (centered over their leader) */
if (nc->rect.x == 0 && nc->rect.y == 0) { if (nc->rect.x == 0 && nc->rect.y == 0) {
/* TODO: client_leader support */ Con *leader;
nc->rect.x = 400; if (con->window && con->window->leader != XCB_NONE &&
nc->rect.y = 400; (leader = con_by_window_id(con->window->leader)) != NULL) {
DLOG("Centering above leader\n");
nc->rect.x = leader->rect.x + (leader->rect.width / 2) - (nc->rect.width / 2);
nc->rect.y = leader->rect.y + (leader->rect.height / 2) - (nc->rect.height / 2);
} else {
/* center the window on workspace as fallback */
Con *ws = nc->parent;
nc->rect.x = ws->rect.x + (ws->rect.width / 2) - (nc->rect.width / 2);
nc->rect.y = ws->rect.y + (ws->rect.height / 2) - (nc->rect.height / 2);
}
} }
TAILQ_INSERT_TAIL(&(nc->nodes_head), con, nodes); TAILQ_INSERT_TAIL(&(nc->nodes_head), con, nodes);

View File

@ -846,6 +846,7 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_
return 1; return 1;
} }
#endif
/* /*
* Handles changes of the WM_CLIENT_LEADER atom which specifies if this is a * Handles changes of the WM_CLIENT_LEADER atom which specifies if this is a
@ -854,25 +855,18 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_
*/ */
int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window, int handle_clientleader_change(void *data, xcb_connection_t *conn, uint8_t state, xcb_window_t window,
xcb_atom_t name, xcb_get_property_reply_t *prop) { xcb_atom_t name, xcb_get_property_reply_t *prop) {
if (prop == NULL) { if (prop == NULL) {
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn, prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL); false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL);
if (prop == NULL) if (prop == NULL)
return 1; return 1;
} }
Client *client = table_get(&by_child, window);
if (client == NULL)
return 1;
xcb_window_t *leader = xcb_get_property_value(prop);
if (leader == NULL)
return 1;
DLOG("Client leader changed to %08x\n", *leader);
client->leader = *leader;
Con *con;
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
return 1; return 1;
window_update_leader(con->window, prop);
return 1;
} }
#endif

View File

@ -267,6 +267,9 @@ int main(int argc, char *argv[]) {
/* Watch WM_NORMAL_HINTS (aspect ratio, size increments, …) */ /* Watch WM_NORMAL_HINTS (aspect ratio, size increments, …) */
xcb_property_set_handler(&prophs, WM_NORMAL_HINTS, UINT_MAX, handle_normal_hints, NULL); xcb_property_set_handler(&prophs, WM_NORMAL_HINTS, UINT_MAX, handle_normal_hints, NULL);
/* Watch WM_CLIENT_LEADER (= logical parent window for toolbars etc.) */
xcb_property_set_handler(&prophs, atoms[WM_CLIENT_LEADER], UINT_MAX, handle_clientleader_change, NULL);
/* Set up the atoms we support */ /* Set up the atoms we support */
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTED], ATOM, 32, 7, atoms); xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTED], ATOM, 32, 7, atoms);
/* Set up the window managers name */ /* Set up the window managers name */

View File

@ -144,6 +144,7 @@ void manage_window(xcb_window_t window, xcb_get_window_attributes_cookie_t cooki
window_update_class(cwindow, xcb_get_property_reply(conn, class_cookie, NULL)); window_update_class(cwindow, xcb_get_property_reply(conn, class_cookie, NULL));
window_update_name_legacy(cwindow, xcb_get_property_reply(conn, title_cookie, NULL)); window_update_name_legacy(cwindow, xcb_get_property_reply(conn, title_cookie, NULL));
window_update_name(cwindow, xcb_get_property_reply(conn, utf8_title_cookie, NULL)); window_update_name(cwindow, xcb_get_property_reply(conn, utf8_title_cookie, NULL));
window_update_leader(cwindow, xcb_get_property_reply(conn, leader_cookie, NULL));
xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, wm_type_cookie, NULL); xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, wm_type_cookie, NULL);
if (xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_DOCK])) { if (xcb_reply_contains_atom(reply, atoms[_NET_WM_WINDOW_TYPE_DOCK])) {
@ -321,9 +322,6 @@ void reparent_window(xcb_connection_t *conn, xcb_window_t child,
preply = xcb_get_property_reply(conn, class_cookie, NULL); preply = xcb_get_property_reply(conn, class_cookie, NULL);
handle_windowclass_change(NULL, conn, 0, new->child, WM_CLASS, preply); handle_windowclass_change(NULL, conn, 0, new->child, WM_CLASS, preply);
preply = xcb_get_property_reply(conn, leader_cookie, NULL);
handle_clientleader_change(NULL, conn, 0, new->child, atoms[WM_CLIENT_LEADER], preply);
/* if WM_CLIENT_LEADER is set, we put the new window on the /* if WM_CLIENT_LEADER is set, we put the new window on the
* same window as its leader. This might be overwritten by * same window as its leader. This might be overwritten by
* assignments afterwards. */ * assignments afterwards. */

View File

@ -96,3 +96,22 @@ void window_update_name_legacy(i3Window *win, xcb_get_property_reply_t *prop) {
win->name_json = strdup(new_name); win->name_json = strdup(new_name);
win->name_len = strlen(new_name); win->name_len = strlen(new_name);
} }
/**
* Updates the CLIENT_LEADER (logical parent window).
*
*/
void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop) {
if (prop == NULL || xcb_get_property_value_length(prop) == 0) {
DLOG("prop == NULL\n");
return;
}
xcb_window_t *leader = xcb_get_property_value(prop);
if (leader == NULL)
return;
DLOG("Client leader changed to %08x\n", *leader);
win->leader = *leader;
}