diff --git a/awesomerc.lua.in b/awesomerc.lua.in index 6c855f36..42064145 100644 --- a/awesomerc.lua.in +++ b/awesomerc.lua.in @@ -141,7 +141,7 @@ for s = 1, screen.count() do -- Widgets that are aligned to the right local right_layout = wibox.layout.fixed.horizontal() - --if s == 1 then right_layout:add(wibox.widget.systray(true)) end + if s == 1 then right_layout:add(wibox.widget.systray(true)) end right_layout:add(mytextclock) right_layout:add(mylayoutbox[s]) diff --git a/event.c b/event.c index 34963df8..d53ff45c 100644 --- a/event.c +++ b/event.c @@ -330,6 +330,7 @@ event_handle_destroynotify(xcb_destroy_notify_event_t *ev) if(globalconf.embedded.tab[i].win == ev->window) { xembed_window_array_take(&globalconf.embedded, i); + luaA_systray_invalidate(); } } @@ -561,6 +562,7 @@ event_handle_unmapnotify(xcb_unmap_notify_event_t *ev) { xembed_window_array_take(&globalconf.embedded, i); xcb_change_save_set(globalconf.connection, XCB_SET_MODE_DELETE, ev->window); + luaA_systray_invalidate(); } } diff --git a/event.h b/event.h index db3995d9..447394a9 100644 --- a/event.h +++ b/event.h @@ -22,14 +22,12 @@ #ifndef AWESOME_EVENT_H #define AWESOME_EVENT_H -#include "systray.h" #include "objects/client.h" static inline int awesome_refresh(void) { banning_refresh(); - systray_refresh(); stack_refresh(); return xcb_flush(globalconf.connection); } diff --git a/globalconf.h b/globalconf.h index 55ce0091..61713b4e 100644 --- a/globalconf.h +++ b/globalconf.h @@ -103,9 +103,7 @@ typedef struct { xcb_window_t window; /** Systray window parent */ - xcb_window_t parent; - /** Is awesome the systray owner? */ - bool registered; + drawin_t *parent; } systray; /** The monitor of startup notifications */ SnMonitorContext *snmonitor; diff --git a/luaa.c b/luaa.c index 8551b000..edfd3152 100644 --- a/luaa.c +++ b/luaa.c @@ -45,6 +45,7 @@ #include "screen.h" #include "event.h" #include "selection.h" +#include "systray.h" #include "common/xcursor.h" #include "common/buffer.h" #include "common/backtrace.h" @@ -545,6 +546,7 @@ luaA_init(xdgHandle* xdg) { "connect_signal", luaA_awesome_connect_signal }, { "disconnect_signal", luaA_awesome_disconnect_signal }, { "emit_signal", luaA_awesome_emit_signal }, + { "systray", luaA_systray }, { "__index", luaA_awesome_index }, { "__newindex", luaA_awesome_newindex }, { NULL, NULL } @@ -672,6 +674,7 @@ luaA_init(xdgHandle* xdg) signal_add(&global_signals, "debug::error"); signal_add(&global_signals, "debug::index::miss"); signal_add(&global_signals, "debug::newindex::miss"); + signal_add(&global_signals, "systray::update"); signal_add(&global_signals, "exit"); } diff --git a/luaa.h b/luaa.h index 9eb519e8..fcfdcc60 100644 --- a/luaa.h +++ b/luaa.h @@ -197,5 +197,7 @@ signal_array_t global_signals; int luaA_class_index_miss_property(lua_State *, lua_object_t *); int luaA_class_newindex_miss_property(lua_State *, lua_object_t *); +void luaA_systray_invalidate(void); + #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/objects/drawin.c b/objects/drawin.c index cf10bd79..9f676dd5 100644 --- a/objects/drawin.c +++ b/objects/drawin.c @@ -27,6 +27,7 @@ #include "xwindow.h" #include "luaa.h" #include "ewmh.h" +#include "systray.h" #include "common/xcursor.h" #include "common/xutil.h" @@ -37,20 +38,20 @@ LUA_OBJECT_FUNCS(drawin_class, drawin_t, drawin) /** Kick out systray windows. */ static void -drawin_systray_kickout(void) +drawin_systray_kickout(drawin_t *w) { - xcb_screen_t *s = globalconf.screen; - - if(globalconf.systray.parent != s->root) + if(globalconf.systray.parent == w) { /* Who! Check that we're not deleting a drawin with a systray, because it * may be its parent. If so, we reparent to root before, otherwise it will * hurt very much. */ + systray_cleanup(); xcb_reparent_window(globalconf.connection, globalconf.systray.window, - s->root, -512, -512); + globalconf.screen->root, + -512, -512); - globalconf.systray.parent = s->root; + globalconf.systray.parent = NULL; } } @@ -65,8 +66,7 @@ drawin_wipe_resources(drawin_t *w) /* Activate BMA */ client_ignore_enterleave_events(); /* Make sure we don't accidentally kill the systray window */ - if(globalconf.systray.parent == w->window) - drawin_systray_kickout(); + drawin_systray_kickout(w); xcb_destroy_window(globalconf.connection, w->window); /* Deactivate BMA */ client_restore_enterleave_events(); diff --git a/systray.c b/systray.c index 1b55cc08..b1877a7e 100644 --- a/systray.c +++ b/systray.c @@ -23,12 +23,14 @@ #include #include +#include "luaa.h" #include "screen.h" #include "systray.h" #include "xwindow.h" #include "common/array.h" #include "common/atoms.h" #include "common/xutil.h" +#include "objects/drawin.h" #define SYSTEM_TRAY_REQUEST_DOCK 0 /* Begin icon docking */ @@ -47,31 +49,9 @@ systray_init(void) XCB_COPY_FROM_PARENT, xscreen->root_visual, 0, NULL); } - -/** Refresh all systrays registrations per physical screen - */ -void -systray_refresh(void) -{ -#warning -#if 0 - bool has_systray = false; - foreach(w, globalconf.wiboxes) - if((*w)->has_systray) - /* Can't use "break" with foreach() :( */ - has_systray = true; - - if(has_systray) - systray_register(); - else - systray_cleanup(); -#endif -} - - /** Register systray in X. */ -void +static void systray_register(void) { xcb_client_message_event_t ev; @@ -81,11 +61,6 @@ systray_register(void) 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.systray.registered) - return; - globalconf.systray.registered = true; - /* Send requests */ if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", globalconf.default_screen))) { @@ -134,10 +109,6 @@ systray_cleanup(void) xcb_intern_atom_reply_t *atom_systray_r; char *atom_name; - if(!globalconf.systray.registered) - return; - globalconf.systray.registered = false; - if(!(atom_name = xcb_atom_name_by_screen("_NET_SYSTEM_TRAY", globalconf.default_screen)) || !(atom_systray_r = xcb_intern_atom_reply(globalconf.connection, xcb_intern_atom_unchecked(globalconf.connection, @@ -159,6 +130,9 @@ systray_cleanup(void) XCB_CURRENT_TIME); p_delete(&atom_systray_r); + + xcb_unmap_window(globalconf.connection, + globalconf.systray.window); } /** Handle a systray request. @@ -211,6 +185,7 @@ systray_request_handle(xcb_window_t embed_win, xembed_info_t *info) MIN(XEMBED_VERSION, em.info.version)); xembed_window_array_append(&globalconf.embedded, em); + luaA_systray_invalidate(); return 0; } @@ -287,4 +262,92 @@ xembed_process_client_message(xcb_client_message_event_t *ev) return 0; } +/** Inform lua that the systray needs to be updated. + */ +void +luaA_systray_invalidate(void) +{ + signal_object_emit(globalconf.L, &global_signals, "systray::update", 0); +} + +static void +systray_update(int base_size, bool horizontal) +{ + if(base_size <= 0) + return; + + /* Give the systray window the correct size */ + uint32_t config_vals[4] = { base_size, base_size, 0, 0 }; + if(horizontal) + config_vals[0] = base_size * globalconf.embedded.len; + else + config_vals[1] = base_size * globalconf.embedded.len; + xcb_configure_window(globalconf.connection, + globalconf.systray.window, + XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + config_vals); + + /* Now resize each embedded window */ + config_vals[0] = config_vals[1] = 0; + config_vals[2] = config_vals[3] = base_size; + for(int i = 0; i < globalconf.embedded.len; i++) + { + xembed_window_t *em = &globalconf.embedded.tab[i]; + xcb_configure_window(globalconf.connection, em->win, + XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, + config_vals); + xcb_map_window(globalconf.connection, em->win); + if(horizontal) + config_vals[0] += base_size; + else + config_vals[1] += base_size; + } +} + +/** Update the systray + * \param L The Lua VM state. + * \return The number of elements pushed on stack. + * \luastack + * \lparam The drawin to display the systray in. + * \lparam x X position for the systray. + * \lparam y Y position for the systray. + * \lparam base_size The size (width and height) each systray item gets. + * \lparam horiz If true, the systray is horizontal, else vertical + */ +int +luaA_systray(lua_State *L) +{ + if(lua_gettop(L) != 0) + { + drawin_t *w = luaA_checkudata(L, 1, &drawin_class); + int x = luaL_checknumber(L, 2); + int y = luaL_checknumber(L, 3); + int base_size = luaL_checknumber(L, 4); + bool horiz = lua_toboolean(L, 5); + + if(globalconf.systray.parent == NULL) + systray_register(); + + globalconf.systray.parent = w; + + if(globalconf.embedded.len != 0) + { + xcb_reparent_window(globalconf.connection, + globalconf.systray.window, + w->window, + x, y); + systray_update(base_size, horiz); + xcb_map_window(globalconf.connection, + globalconf.systray.window); + } + else + xcb_unmap_window(globalconf.connection, + globalconf.systray.window); + } + + lua_pushnumber(L, globalconf.embedded.len); + luaA_object_push(L, globalconf.systray.parent); + return 2; +} + // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80 diff --git a/systray.h b/systray.h index 3ccd8ec3..77be12e8 100644 --- a/systray.h +++ b/systray.h @@ -23,16 +23,16 @@ #define AWESOME_SYSTRAY_H #include +#include #include "common/xembed.h" void systray_init(void); -void systray_refresh(void); -void systray_register(void); void systray_cleanup(void); int systray_request_handle(xcb_window_t, xembed_info_t *); bool systray_iskdedockapp(xcb_window_t); int systray_process_client_message(xcb_client_message_event_t *); int xembed_process_client_message(xcb_client_message_event_t *); +int luaA_systray(lua_State *); #endif // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80