2010-10-06 12:42:56 +02:00
|
|
|
---------------------------------------------------------------------------
|
2021-12-21 06:54:15 +01:00
|
|
|
-- Container for the various system tray icons.
|
|
|
|
--
|
2010-10-06 12:42:56 +02:00
|
|
|
-- @author Uli Schlachter
|
|
|
|
-- @copyright 2010 Uli Schlachter
|
2019-06-06 08:15:53 +02:00
|
|
|
-- @widgetmod wibox.widget.systray
|
2021-03-27 20:41:28 +01:00
|
|
|
-- @supermodule wibox.widget.base
|
2010-10-06 12:42:56 +02:00
|
|
|
---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
local wbase = require("wibox.widget.base")
|
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>
2017-03-11 18:14:38 +01:00
|
|
|
local drawable = require("wibox.drawable")
|
2010-10-17 09:24:59 +02:00
|
|
|
local beautiful = require("beautiful")
|
2017-03-08 21:18:33 +01:00
|
|
|
local gtable = require("gears.table")
|
2016-03-05 16:49:49 +01:00
|
|
|
local capi = {
|
|
|
|
awesome = awesome,
|
|
|
|
screen = screen
|
|
|
|
}
|
2010-10-06 12:42:56 +02:00
|
|
|
local setmetatable = setmetatable
|
|
|
|
local error = error
|
2013-02-16 22:14:08 +01:00
|
|
|
local abs = math.abs
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2012-06-12 15:55:10 +02:00
|
|
|
local systray = { mt = {} }
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2016-03-05 16:39:25 +01:00
|
|
|
local instance = nil
|
2010-10-06 12:42:56 +02:00
|
|
|
local horizontal = true
|
2010-10-07 11:54:45 +02:00
|
|
|
local base_size = nil
|
2014-04-02 15:25:03 +02:00
|
|
|
local reverse = false
|
2016-03-05 16:49:49 +01:00
|
|
|
local display_on_screen = "primary"
|
|
|
|
|
2016-05-23 09:13:15 +02:00
|
|
|
--- The systray background color.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2021-12-21 06:54:15 +01:00
|
|
|
-- Please note that only solid+opaque colors are supported. It does **not**
|
|
|
|
-- support gradients, patterns or transparent colors.
|
|
|
|
--
|
2016-05-23 09:13:15 +02:00
|
|
|
-- @beautiful beautiful.bg_systray
|
2021-12-21 06:54:15 +01:00
|
|
|
-- @tparam string bg_systray The color (string like "#ff0000" only)
|
2016-05-23 09:13:15 +02:00
|
|
|
|
2021-12-30 22:22:31 +01:00
|
|
|
--- The maximum number of rows for systray icons. Icons will fill the
|
|
|
|
-- current column (orthogonally to the systray direction) before
|
|
|
|
-- filling the next column.
|
|
|
|
--
|
|
|
|
-- @beautiful beautiful.systray_max_rows
|
2021-12-21 06:54:15 +01:00
|
|
|
-- @tparam[opt=1] integer systray_max_rows The positive number of rows.
|
2021-12-30 22:22:31 +01:00
|
|
|
|
2016-05-23 09:13:15 +02:00
|
|
|
--- The systray icon spacing.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2016-05-23 09:13:15 +02:00
|
|
|
-- @beautiful beautiful.systray_icon_spacing
|
2021-12-21 06:54:15 +01:00
|
|
|
-- @tparam[opt=0] integer systray_icon_spacing The icon spacing
|
2016-05-23 09:13:15 +02:00
|
|
|
|
2016-03-05 16:49:49 +01:00
|
|
|
local function should_display_on(s)
|
|
|
|
if display_on_screen == "primary" then
|
|
|
|
return s == capi.screen.primary
|
|
|
|
end
|
|
|
|
return s == display_on_screen
|
|
|
|
end
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2015-08-08 13:18:54 +02:00
|
|
|
function systray:draw(context, cr, width, height)
|
2016-03-05 16:49:49 +01:00
|
|
|
if not should_display_on(context.screen) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2015-07-25 15:52:53 +02:00
|
|
|
local x, y, _, _ = wbase.rect_to_device_geometry(cr, 0, 0, width, height)
|
2010-10-06 12:42:56 +02:00
|
|
|
local num_entries = capi.awesome.systray()
|
2021-12-30 22:22:31 +01:00
|
|
|
local max_rows = math.floor(tonumber(beautiful.systray_max_rows) or 1)
|
|
|
|
local rows = math.max(math.min(num_entries, max_rows), 1)
|
|
|
|
local cols = math.ceil(num_entries / rows)
|
2012-11-27 22:55:42 +01:00
|
|
|
local bg = beautiful.bg_systray or beautiful.bg_normal or "#000000"
|
2014-05-10 06:08:42 +02:00
|
|
|
local spacing = beautiful.systray_icon_spacing or 0
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2015-10-10 20:30:08 +02:00
|
|
|
if context and not context.wibox then
|
|
|
|
error("The systray widget can only be placed inside a wibox.")
|
|
|
|
end
|
|
|
|
|
2013-02-16 22:14:08 +01:00
|
|
|
-- Figure out if the cairo context is rotated
|
|
|
|
local dir_x, dir_y = cr:user_to_device_distance(1, 0)
|
|
|
|
local is_rotated = abs(dir_x) < abs(dir_y)
|
|
|
|
|
2010-10-07 11:54:45 +02:00
|
|
|
local in_dir, ortho, base
|
2010-10-06 12:42:56 +02:00
|
|
|
if horizontal then
|
|
|
|
in_dir, ortho = width, height
|
2013-02-16 22:14:08 +01:00
|
|
|
is_rotated = not is_rotated
|
2010-10-06 12:42:56 +02:00
|
|
|
else
|
|
|
|
ortho, in_dir = width, height
|
|
|
|
end
|
2020-02-10 10:15:34 +01:00
|
|
|
-- The formula for a given base, spacing, and num_entries for the necessary
|
|
|
|
-- space is (draw a picture to convince yourself; this assumes horizontal):
|
2021-12-30 22:22:31 +01:00
|
|
|
-- height = (base + spacing) * rows - spacing
|
|
|
|
-- width = (base + spacing) * cols - spacing
|
2020-02-10 10:15:34 +01:00
|
|
|
-- Now, we check if we are limited by horizontal or vertical space: Which of
|
|
|
|
-- the two limits the base size more?
|
2021-12-30 22:22:31 +01:00
|
|
|
base = (ortho + spacing) / rows - spacing
|
|
|
|
if (base + spacing) * cols - spacing > in_dir then
|
2020-02-10 10:15:34 +01:00
|
|
|
-- Solving the "width" formula above for "base" (with width=in_dir):
|
2021-12-30 22:22:31 +01:00
|
|
|
base = (in_dir + spacing) / cols - spacing
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
2015-08-08 13:18:54 +02:00
|
|
|
capi.awesome.systray(context.wibox.drawin, math.ceil(x), math.ceil(y),
|
2021-12-30 22:22:31 +01:00
|
|
|
base, is_rotated, bg, reverse, spacing, rows)
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
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>
2017-03-11 18:14:38 +01:00
|
|
|
-- 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
|
|
|
|
|
2016-03-05 16:49:49 +01:00
|
|
|
function systray:fit(context, width, height)
|
|
|
|
if not should_display_on(context.screen) then
|
|
|
|
return 0, 0
|
|
|
|
end
|
|
|
|
|
2010-10-06 12:42:56 +02:00
|
|
|
local num_entries = capi.awesome.systray()
|
2021-12-30 22:22:31 +01:00
|
|
|
local max_rows = math.floor(tonumber(beautiful.systray_max_rows) or 1)
|
|
|
|
local rows = math.max(math.min(num_entries, max_rows), 1)
|
|
|
|
local cols = math.ceil(num_entries / rows)
|
2010-10-07 11:54:45 +02:00
|
|
|
local base = base_size
|
2014-05-10 06:08:42 +02:00
|
|
|
local spacing = beautiful.systray_icon_spacing or 0
|
2014-05-11 17:24:01 +02:00
|
|
|
if num_entries == 0 then
|
|
|
|
return 0, 0
|
|
|
|
end
|
2010-10-07 11:54:45 +02:00
|
|
|
if base == nil then
|
2021-12-30 22:22:31 +01:00
|
|
|
if horizontal then
|
|
|
|
base = math.min(math.floor((height + spacing) / rows) - spacing,
|
|
|
|
math.floor((width + spacing) / cols) - spacing)
|
2010-10-07 11:54:45 +02:00
|
|
|
else
|
2021-12-30 22:22:31 +01:00
|
|
|
base = math.min(math.floor((width + spacing) / rows) - spacing,
|
|
|
|
math.floor((height + spacing) / cols) - spacing)
|
2010-10-07 11:54:45 +02:00
|
|
|
end
|
|
|
|
end
|
2014-05-10 06:08:42 +02:00
|
|
|
base = base + spacing
|
2010-10-06 12:42:56 +02:00
|
|
|
if horizontal then
|
2021-12-30 22:22:31 +01:00
|
|
|
return base * cols - spacing, base * rows - spacing
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
2021-12-30 22:22:31 +01:00
|
|
|
return base * rows - spacing, base * cols - spacing
|
2010-10-06 12:42:56 +02:00
|
|
|
end
|
|
|
|
|
2016-03-05 16:39:25 +01:00
|
|
|
-- Check if the function was called like :foo() or .foo() and do the right thing
|
|
|
|
local function get_args(self, ...)
|
|
|
|
if self == instance then
|
|
|
|
return ...
|
|
|
|
end
|
|
|
|
return self, ...
|
|
|
|
end
|
|
|
|
|
|
|
|
--- Set the size of a single icon.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2016-03-05 16:39:25 +01:00
|
|
|
-- If this is set to nil, then the size is picked dynamically based on the
|
|
|
|
-- available space. Otherwise, any single icon has a size of `size`x`size`.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @property base_size
|
2022-07-10 09:29:33 +02:00
|
|
|
-- @tparam[opt=nil] integer|nil base_size The base size
|
2019-11-29 06:33:44 +01:00
|
|
|
-- @propemits true false
|
2019-06-06 22:32:53 +02:00
|
|
|
|
2016-03-05 16:39:25 +01:00
|
|
|
function systray:set_base_size(size)
|
|
|
|
base_size = get_args(self, size)
|
2016-03-05 16:53:38 +01:00
|
|
|
if instance then
|
|
|
|
instance:emit_signal("widget::layout_changed")
|
2019-11-29 06:33:44 +01:00
|
|
|
instance:emit_signal("property::base_size", size)
|
2016-03-05 16:53:38 +01:00
|
|
|
end
|
2016-03-05 16:39:25 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
--- Decide between horizontal or vertical display.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @property horizontal
|
2022-07-10 09:29:33 +02:00
|
|
|
-- @tparam[opt=true] boolean horizontal Use horizontal mode?
|
2019-11-29 06:33:44 +01:00
|
|
|
-- @propemits true false
|
2019-06-06 22:32:53 +02:00
|
|
|
|
2016-03-05 16:39:25 +01:00
|
|
|
function systray:set_horizontal(horiz)
|
|
|
|
horizontal = get_args(self, horiz)
|
2016-03-05 16:53:38 +01:00
|
|
|
if instance then
|
|
|
|
instance:emit_signal("widget::layout_changed")
|
2019-11-29 06:33:44 +01:00
|
|
|
instance:emit_signal("property::horizontal", horiz)
|
2016-03-05 16:53:38 +01:00
|
|
|
end
|
2016-03-05 16:39:25 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
--- Should the systray icons be displayed in reverse order?
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @property reverse
|
2022-07-10 09:29:33 +02:00
|
|
|
-- @tparam[opt=false] boolean reverse Display in reverse order.
|
2019-11-29 06:33:44 +01:00
|
|
|
-- @propemits true false
|
2019-06-06 22:32:53 +02:00
|
|
|
|
2016-03-05 16:39:25 +01:00
|
|
|
function systray:set_reverse(rev)
|
|
|
|
reverse = get_args(self, rev)
|
2016-03-05 16:53:38 +01:00
|
|
|
if instance then
|
|
|
|
instance:emit_signal("widget::redraw_needed")
|
2019-11-29 06:33:44 +01:00
|
|
|
instance:emit_signal("property::reverse", rev)
|
2016-03-05 16:53:38 +01:00
|
|
|
end
|
2016-03-05 16:39:25 +01:00
|
|
|
end
|
|
|
|
|
2016-03-05 16:49:49 +01:00
|
|
|
--- Set the screen that the systray should be displayed on.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2016-03-05 16:49:49 +01:00
|
|
|
-- This can either be a screen, in which case the systray will be displayed on
|
|
|
|
-- exactly that screen, or the string `"primary"`, in which case it will be
|
|
|
|
-- visible on the primary screen. The default value is "primary".
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2019-06-06 22:32:53 +02:00
|
|
|
-- @property screen
|
2022-07-10 09:29:33 +02:00
|
|
|
-- @tparam[opt=nil] screen|"primary" screen The screen to display on.
|
2019-11-29 06:33:44 +01:00
|
|
|
-- @propemits true false
|
2019-06-06 22:32:53 +02:00
|
|
|
|
2016-03-05 16:49:49 +01:00
|
|
|
function systray:set_screen(s)
|
|
|
|
display_on_screen = get_args(self, s)
|
2016-03-05 16:53:38 +01:00
|
|
|
if instance then
|
|
|
|
instance:emit_signal("widget::layout_changed")
|
2019-11-29 06:33:44 +01:00
|
|
|
instance:emit_signal("property::screen", s)
|
2016-03-05 16:53:38 +01:00
|
|
|
end
|
2016-03-05 16:49:49 +01:00
|
|
|
end
|
|
|
|
|
2016-05-23 08:54:01 +02:00
|
|
|
--- Create the systray widget.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2016-05-23 08:54:01 +02:00
|
|
|
-- Note that this widget can only exist once.
|
2019-11-29 06:33:44 +01:00
|
|
|
--
|
2021-12-21 06:54:15 +01:00
|
|
|
-- @tparam boolean reverse Show in the opposite direction
|
2016-05-23 08:54:01 +02:00
|
|
|
-- @treturn table The new `systray` widget
|
2019-06-07 20:59:34 +02:00
|
|
|
-- @constructorfct wibox.widget.systray
|
2021-12-21 06:54:15 +01:00
|
|
|
-- @usebeautiful beautiful.bg_systray
|
|
|
|
-- @usebeautiful beautiful.systray_icon_spacing
|
|
|
|
-- @usebeautiful beautiful.systray_max_rows
|
2016-05-23 08:54:01 +02:00
|
|
|
|
2014-04-02 15:25:03 +02:00
|
|
|
local function new(revers)
|
2017-03-11 18:46:40 +01:00
|
|
|
local ret = wbase.make_widget(nil, nil, {enable_properties = true})
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2017-03-08 21:18:33 +01:00
|
|
|
gtable.crush(ret, systray, true)
|
2014-04-02 15:25:03 +02:00
|
|
|
|
|
|
|
if revers then
|
|
|
|
ret:set_reverse(true)
|
|
|
|
end
|
2010-10-06 12:42:56 +02:00
|
|
|
|
|
|
|
capi.awesome.connect_signal("systray::update", function()
|
2015-06-14 16:37:07 +02:00
|
|
|
ret:emit_signal("widget::layout_changed")
|
2015-11-29 12:33:13 +01:00
|
|
|
ret:emit_signal("widget::redraw_needed")
|
2010-10-06 12:42:56 +02:00
|
|
|
end)
|
2016-03-05 16:49:49 +01:00
|
|
|
capi.screen.connect_signal("primary_changed", function()
|
|
|
|
if display_on_screen == "primary" then
|
|
|
|
ret:emit_signal("widget::layout_changed")
|
|
|
|
end
|
|
|
|
end)
|
2010-10-06 12:42:56 +02:00
|
|
|
|
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>
2017-03-11 18:14:38 +01:00
|
|
|
drawable._set_systray_widget(ret)
|
|
|
|
|
2010-10-06 12:42:56 +02:00
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
2012-06-12 15:55:10 +02:00
|
|
|
function systray.mt:__call(...)
|
2016-03-05 16:17:35 +01:00
|
|
|
if not instance then
|
|
|
|
instance = new(...)
|
|
|
|
end
|
|
|
|
return instance
|
2012-06-12 15:55:10 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return setmetatable(systray, systray.mt)
|
2010-10-06 12:42:56 +02:00
|
|
|
|
2011-09-11 16:50:01 +02:00
|
|
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|