i3bar: fake DestroyNotify and send MANAGER ClientMessages to fix tray restarts
fixes #745
This commit is contained in:
parent
2043076518
commit
e9503a1fa3
|
@ -49,6 +49,10 @@ int screen;
|
||||||
xcb_screen_t *root_screen;
|
xcb_screen_t *root_screen;
|
||||||
xcb_window_t xcb_root;
|
xcb_window_t xcb_root;
|
||||||
|
|
||||||
|
/* selection window for tray support */
|
||||||
|
static xcb_window_t selwin = XCB_NONE;
|
||||||
|
static xcb_intern_atom_reply_t *tray_reply = NULL;
|
||||||
|
|
||||||
/* This is needed for integration with libi3 */
|
/* This is needed for integration with libi3 */
|
||||||
xcb_connection_t *conn;
|
xcb_connection_t *conn;
|
||||||
|
|
||||||
|
@ -991,6 +995,31 @@ void init_xcb_late(char *fontname) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Inform clients waiting for a new _NET_SYSTEM_TRAY that we took the
|
||||||
|
* selection.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void send_tray_clientmessage(void) {
|
||||||
|
uint8_t buffer[32] = { 0 };
|
||||||
|
xcb_client_message_event_t *ev = (xcb_client_message_event_t*)buffer;
|
||||||
|
|
||||||
|
ev->response_type = XCB_CLIENT_MESSAGE;
|
||||||
|
ev->window = xcb_root;
|
||||||
|
ev->type = atoms[MANAGER];
|
||||||
|
ev->format = 32;
|
||||||
|
ev->data.data32[0] = XCB_CURRENT_TIME;
|
||||||
|
ev->data.data32[1] = tray_reply->atom;
|
||||||
|
ev->data.data32[2] = selwin;
|
||||||
|
|
||||||
|
xcb_send_event(xcb_connection,
|
||||||
|
0,
|
||||||
|
xcb_root,
|
||||||
|
0xFFFFFF,
|
||||||
|
(char*)buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initializes tray support by requesting the appropriate _NET_SYSTEM_TRAY atom
|
* Initializes tray support by requesting the appropriate _NET_SYSTEM_TRAY atom
|
||||||
* for the X11 display we are running on, then acquiring the selection for this
|
* for the X11 display we are running on, then acquiring the selection for this
|
||||||
|
@ -1003,11 +1032,11 @@ void init_tray(void) {
|
||||||
char atomname[strlen("_NET_SYSTEM_TRAY_S") + 11];
|
char atomname[strlen("_NET_SYSTEM_TRAY_S") + 11];
|
||||||
snprintf(atomname, strlen("_NET_SYSTEM_TRAY_S") + 11, "_NET_SYSTEM_TRAY_S%d", screen);
|
snprintf(atomname, strlen("_NET_SYSTEM_TRAY_S") + 11, "_NET_SYSTEM_TRAY_S%d", screen);
|
||||||
xcb_intern_atom_cookie_t tray_cookie;
|
xcb_intern_atom_cookie_t tray_cookie;
|
||||||
xcb_intern_atom_reply_t *tray_reply;
|
if (tray_reply == NULL)
|
||||||
tray_cookie = xcb_intern_atom(xcb_connection, 0, strlen(atomname), atomname);
|
tray_cookie = xcb_intern_atom(xcb_connection, 0, strlen(atomname), atomname);
|
||||||
|
|
||||||
/* tray support: we need a window to own the selection */
|
/* tray support: we need a window to own the selection */
|
||||||
xcb_window_t selwin = xcb_generate_id(xcb_connection);
|
selwin = xcb_generate_id(xcb_connection);
|
||||||
uint32_t selmask = XCB_CW_OVERRIDE_REDIRECT;
|
uint32_t selmask = XCB_CW_OVERRIDE_REDIRECT;
|
||||||
uint32_t selval[] = { 1 };
|
uint32_t selval[] = { 1 };
|
||||||
xcb_create_window(xcb_connection,
|
xcb_create_window(xcb_connection,
|
||||||
|
@ -1033,9 +1062,11 @@ void init_tray(void) {
|
||||||
1,
|
1,
|
||||||
&orientation);
|
&orientation);
|
||||||
|
|
||||||
if (!(tray_reply = xcb_intern_atom_reply(xcb_connection, tray_cookie, NULL))) {
|
if (tray_reply == NULL) {
|
||||||
ELOG("Could not get atom %s\n", atomname);
|
if (!(tray_reply = xcb_intern_atom_reply(xcb_connection, tray_cookie, NULL))) {
|
||||||
exit(EXIT_FAILURE);
|
ELOG("Could not get atom %s\n", atomname);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_set_selection_owner(xcb_connection,
|
xcb_set_selection_owner(xcb_connection,
|
||||||
|
@ -1062,23 +1093,7 @@ void init_tray(void) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Inform clients waiting for a new _NET_SYSTEM_TRAY that we are here */
|
send_tray_clientmessage();
|
||||||
void *event = scalloc(32);
|
|
||||||
xcb_client_message_event_t *ev = event;
|
|
||||||
ev->response_type = XCB_CLIENT_MESSAGE;
|
|
||||||
ev->window = xcb_root;
|
|
||||||
ev->type = atoms[MANAGER];
|
|
||||||
ev->format = 32;
|
|
||||||
ev->data.data32[0] = XCB_CURRENT_TIME;
|
|
||||||
ev->data.data32[1] = tray_reply->atom;
|
|
||||||
ev->data.data32[2] = selwin;
|
|
||||||
xcb_send_event(xcb_connection,
|
|
||||||
0,
|
|
||||||
xcb_root,
|
|
||||||
0xFFFFFF,
|
|
||||||
(char*)ev);
|
|
||||||
free(event);
|
|
||||||
free(tray_reply);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1138,6 +1153,9 @@ void get_atoms(void) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void kick_tray_clients(i3_output *output) {
|
void kick_tray_clients(i3_output *output) {
|
||||||
|
if (TAILQ_EMPTY(output->trayclients))
|
||||||
|
return;
|
||||||
|
|
||||||
trayclient *trayclient;
|
trayclient *trayclient;
|
||||||
while (!TAILQ_EMPTY(output->trayclients)) {
|
while (!TAILQ_EMPTY(output->trayclients)) {
|
||||||
trayclient = TAILQ_FIRST(output->trayclients);
|
trayclient = TAILQ_FIRST(output->trayclients);
|
||||||
|
@ -1153,6 +1171,20 @@ void kick_tray_clients(i3_output *output) {
|
||||||
* event afterwards, but better safe than sorry. */
|
* event afterwards, but better safe than sorry. */
|
||||||
TAILQ_REMOVE(output->trayclients, trayclient, tailq);
|
TAILQ_REMOVE(output->trayclients, trayclient, tailq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fake a DestroyNotify so that Qt re-adds tray icons.
|
||||||
|
* We cannot actually destroy the window because then Qt will not restore
|
||||||
|
* its event mask on the new window. */
|
||||||
|
uint8_t buffer[32] = { 0 };
|
||||||
|
xcb_destroy_notify_event_t *event = (xcb_destroy_notify_event_t*)buffer;
|
||||||
|
|
||||||
|
event->response_type = XCB_DESTROY_NOTIFY;
|
||||||
|
event->event = selwin;
|
||||||
|
event->window = selwin;
|
||||||
|
|
||||||
|
xcb_send_event(conn, false, selwin, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (char*)event);
|
||||||
|
|
||||||
|
send_tray_clientmessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue