Partly fix removal of systray from a wibox

This commit changes the systray widget, wibox.drawable and the C code to
fix the following bug: When the systray widget is removed from a
drawable without being moved somewhere else, the systray stayed visible.
This was because the systray is not drawn by awesome, but only placed.
When the widget is no longer "drawn", it stays wherever it was placed
last.

This change works by detecting the situation when the systray is
removed. Then, the C code is specifically told to remove the systray
window from the drawable.

Note that this is only a partial fix. This change works correctly when
the widget is removed completely, because it is no longer placed by its
parent widget. However, for example, when you do
wibox.widget.systray().visible = false, the effect is just that the
systray widget gets size 0x0. This is not really visible, but as far as
this change is concerned, the widget is still part of the drawable.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2017-03-11 18:14:38 +01:00
parent e1fe1de98f
commit 51e4a47938
5 changed files with 35 additions and 2 deletions

View file

@ -25,6 +25,8 @@ local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility
local visible_drawables = {}
local systray_widget
-- Get the widget context. This should always return the same table (if
-- possible), so that our draw and fit caches can work efficiently.
local function get_widget_context(self)
@ -76,8 +78,15 @@ local function do_redraw(self)
if self._need_relayout or self._need_complete_repaint then
self._need_relayout = false
if self._widget_hierarchy and self.widget then
local had_systray = systray_widget and self._widget_hierarchy:get_count(systray_widget) > 0
self._widget_hierarchy:update(context,
self.widget, width, height, self._dirty_area)
local has_systray = systray_widget and self._widget_hierarchy:get_count(systray_widget) > 0
if had_systray and not has_systray then
systray_widget:_kickout(context)
end
else
self._need_complete_repaint = true
if self.widget then
@ -209,6 +218,11 @@ function drawable:find_widgets(x, y)
return result
end
-- Private API. Not documented on purpose.
function drawable._set_systray_widget(widget)
hierarchy.count_widget(widget)
systray_widget = widget
end
--- Set the widget that the drawable displays
function drawable:set_widget(widget)

View file

@ -5,6 +5,7 @@
---------------------------------------------------------------------------
local wbase = require("wibox.widget.base")
local drawable = require("wibox.drawable")
local beautiful = require("beautiful")
local gtable = require("gears.table")
local capi = {
@ -72,6 +73,13 @@ function systray:draw(context, cr, width, height)
base, is_rotated, bg, reverse, spacing)
end
-- Private API. Does not appear in LDoc on purpose. This function is called
-- some time after the systray is removed from some drawable. It's purpose is to
-- really remove the systray.
function systray:_kickout(context)
capi.awesome.systray(context.wibox.drawin)
end
function systray:fit(context, width, height)
if not should_display_on(context.screen) then
return 0, 0
@ -171,6 +179,8 @@ local function new(revers)
end
end)
drawable._set_systray_widget(ret)
return ret
end

View file

@ -166,6 +166,12 @@ drawin_systray_kickout(drawin_t *w)
}
}
void
luaA_drawin_systray_kickout(lua_State *L)
{
drawin_systray_kickout(luaA_checkudata(L, 1, &drawin_class));
}
static void
drawin_wipe(drawin_t *w)
{

View file

@ -47,8 +47,8 @@ struct drawin_t
ARRAY_FUNCS(drawin_t *, drawin, DO_NOTHING)
drawin_t * drawin_getbywin(xcb_window_t);
void drawin_refresh_pixmap_partial(drawin_t *, int16_t, int16_t, uint16_t, uint16_t);
void luaA_drawin_systray_kickout(lua_State *);
void drawin_class_setup(lua_State *);

View file

@ -337,7 +337,10 @@ luaA_systray(lua_State *L)
{
systray_register();
if(lua_gettop(L) != 0)
if(lua_gettop(L) == 1)
luaA_drawin_systray_kickout(L);
if(lua_gettop(L) > 1)
{
size_t bg_len;
drawin_t *w = luaA_checkudata(L, 1, &drawin_class);