Implement support for WM_CLIENT_LEADER
This commit is contained in:
parent
1bb6906c56
commit
ad9be5402a
@ -212,6 +212,10 @@ struct xoutput {
|
||||
struct Window {
|
||||
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_instance;
|
||||
|
||||
|
@ -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,
|
||||
xcb_window_t window, xcb_atom_t name,
|
||||
xcb_get_property_reply_t *reply);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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,
|
||||
uint8_t state, xcb_window_t window,
|
||||
xcb_atom_t name, xcb_get_property_reply_t *prop);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -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);
|
||||
|
||||
/**
|
||||
* Updates the CLIENT_LEADER (logical parent window).
|
||||
*
|
||||
*/
|
||||
void window_update_leader(i3Window *win, xcb_get_property_reply_t *prop);
|
||||
|
||||
#endif
|
||||
|
@ -53,9 +53,18 @@ void floating_enable(Con *con, bool automatic) {
|
||||
* to (0, 0), so we push them to a reasonable position
|
||||
* (centered over their leader) */
|
||||
if (nc->rect.x == 0 && nc->rect.y == 0) {
|
||||
/* TODO: client_leader support */
|
||||
nc->rect.x = 400;
|
||||
nc->rect.y = 400;
|
||||
Con *leader;
|
||||
if (con->window && con->window->leader != XCB_NONE &&
|
||||
(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);
|
||||
|
@ -846,6 +846,7 @@ int handle_transient_for(void *data, xcb_connection_t *conn, uint8_t state, xcb_
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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,
|
||||
xcb_atom_t name, xcb_get_property_reply_t *prop) {
|
||||
if (prop == NULL) {
|
||||
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
|
||||
false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL);
|
||||
if (prop == NULL)
|
||||
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;
|
||||
if (prop == NULL) {
|
||||
prop = xcb_get_property_reply(conn, xcb_get_property_unchecked(conn,
|
||||
false, window, WM_CLIENT_LEADER, WINDOW, 0, 32), NULL);
|
||||
if (prop == NULL)
|
||||
return 1;
|
||||
}
|
||||
|
||||
Con *con;
|
||||
if ((con = con_by_window_id(window)) == NULL || con->window == NULL)
|
||||
return 1;
|
||||
|
||||
window_update_leader(con->window, prop);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
@ -267,6 +267,9 @@ int main(int argc, char *argv[]) {
|
||||
/* Watch WM_NORMAL_HINTS (aspect ratio, size increments, …) */
|
||||
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 */
|
||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTED], ATOM, 32, 7, atoms);
|
||||
/* Set up the window manager’s name */
|
||||
|
@ -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_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_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);
|
||||
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);
|
||||
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
|
||||
* same window as its leader. This might be overwritten by
|
||||
* assignments afterwards. */
|
||||
|
19
src/window.c
19
src/window.c
@ -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_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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user