diff --git a/event.h b/event.h index 5a1a6466..c92d511f 100644 --- a/event.h +++ b/event.h @@ -22,6 +22,7 @@ #ifndef AWESOME_EVENT_H #define AWESOME_EVENT_H +#include "systray.h" #include "wibox.h" #include "client.h" @@ -30,6 +31,7 @@ awesome_refresh(void) { banning_refresh(); wibox_refresh(); + systray_refresh(); client_stack_refresh(); return xcb_flush(globalconf.connection); } diff --git a/screen.h b/screen.h index 6db22d59..dc4c4b8c 100644 --- a/screen.h +++ b/screen.h @@ -37,6 +37,7 @@ struct a_screen xcb_window_t window; /** Systray window parent */ xcb_window_t parent; + bool registered; } systray; /** Previously focused client */ client_t *prev_client_focus; diff --git a/systray.c b/systray.c index dc51d454..a7b49414 100644 --- a/systray.c +++ b/systray.c @@ -27,6 +27,8 @@ #include "systray.h" #include "window.h" #include "widget.h" +#include "wibox.h" +#include "common/array.h" #include "common/atoms.h" #include "common/xutil.h" @@ -37,6 +39,46 @@ */ void systray_init(int phys_screen) +{ + xcb_screen_t *xscreen = xutil_screen_get(globalconf.connection, phys_screen); + + globalconf.screens.tab[phys_screen].systray.window = xcb_generate_id(globalconf.connection); + xcb_create_window(globalconf.connection, xscreen->root_depth, + globalconf.screens.tab[phys_screen].systray.window, + xscreen->root, + -1, -1, 1, 1, 0, + XCB_COPY_FROM_PARENT, xscreen->root_visual, 0, NULL); +} + + +/** Refresh all systrays registrations per physical screen + */ +void +systray_refresh() +{ + bool has_systray; + int nscreen = xcb_setup_roots_length(xcb_get_setup(globalconf.connection)); + + for(int phys_screen = 0; phys_screen < nscreen; phys_screen++) + { + has_systray = false; + foreach(w, globalconf.wiboxes) + if(phys_screen == (*w)->ctx.phys_screen) + has_systray |= (*w)->has_systray; + + if(has_systray) + systray_register(phys_screen); + else + systray_cleanup(phys_screen); + } +} + + +/** Register systray in X. + * \param phys_screen Physical screen. + */ +void +systray_register(int phys_screen) { xcb_client_message_event_t ev; xcb_screen_t *xscreen = xutil_screen_get(globalconf.connection, phys_screen); @@ -45,6 +87,11 @@ systray_init(int phys_screen) xcb_intern_atom_reply_t *atom_systray_r; xcb_atom_t atom_systray; + /* Set registered even if it fails to don't try again unless forced */ + if(globalconf.screens.tab[phys_screen].systray.registered) + return; + globalconf.screens.tab[phys_screen].systray.registered = true; + /* Send requests */ if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen))) { @@ -57,13 +104,6 @@ systray_init(int phys_screen) p_delete(&atom_name); - globalconf.screens.tab[phys_screen].systray.window = xcb_generate_id(globalconf.connection); - xcb_create_window(globalconf.connection, xscreen->root_depth, - globalconf.screens.tab[phys_screen].systray.window, - xscreen->root, - -1, -1, 1, 1, 0, - XCB_COPY_FROM_PARENT, xscreen->root_visual, 0, NULL); - /* Fill event */ p_clear(&ev, 1); ev.response_type = XCB_CLIENT_MESSAGE; @@ -101,6 +141,10 @@ systray_cleanup(int phys_screen) xcb_intern_atom_reply_t *atom_systray_r; char *atom_name; + if(!globalconf.screens.tab[phys_screen].systray.registered) + return; + globalconf.screens.tab[phys_screen].systray.registered = false; + if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", phys_screen)) || !(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, xcb_intern_atom_unchecked(globalconf.connection, diff --git a/systray.h b/systray.h index f877599a..829d5adf 100644 --- a/systray.h +++ b/systray.h @@ -26,6 +26,8 @@ #include "common/xembed.h" void systray_init(int); +void systray_refresh(void); +void systray_register(int); void systray_cleanup(int); int systray_request_handle(xcb_window_t, int, xembed_info_t *); bool systray_iskdedockapp(xcb_window_t); diff --git a/wibox.c b/wibox.c index 85dffdef..392a1909 100644 --- a/wibox.c +++ b/wibox.c @@ -417,6 +417,8 @@ wibox_systray_kickout(int phys_screen) static void wibox_systray_refresh(wibox_t *wibox) { + wibox->has_systray = false; + if(!wibox->screen) return; @@ -431,6 +433,8 @@ wibox_systray_refresh(wibox_t *wibox) xembed_window_t *em; int phys_screen = wibox->ctx.phys_screen; + wibox->has_systray = true; + if(wibox->visible && systray->widget->isvisible && systray->geometry.width) diff --git a/wibox.h b/wibox.h index 67035c20..4a8058fe 100644 --- a/wibox.h +++ b/wibox.h @@ -94,6 +94,8 @@ struct wibox_t /** The window's content and border */ image_t *bounding; } shape; + /** Has wibox an attached systray **/ + bool has_systray; }; void wibox_unref_simplified(wibox_t **);