summaryrefslogtreecommitdiff
path: root/awesome/lib/awful/widget/taglist.lua
diff options
context:
space:
mode:
Diffstat (limited to 'awesome/lib/awful/widget/taglist.lua')
-rw-r--r--awesome/lib/awful/widget/taglist.lua452
1 files changed, 452 insertions, 0 deletions
diff --git a/awesome/lib/awful/widget/taglist.lua b/awesome/lib/awful/widget/taglist.lua
new file mode 100644
index 0000000..d8cf475
--- /dev/null
+++ b/awesome/lib/awful/widget/taglist.lua
@@ -0,0 +1,452 @@
+---------------------------------------------------------------------------
+--- Taglist widget module for awful
+--
+-- @author Julien Danjou <julien@danjou.info>
+-- @copyright 2008-2009 Julien Danjou
+-- @classmod awful.widget.taglist
+---------------------------------------------------------------------------
+
+-- Grab environment we need
+local capi = { screen = screen,
+ awesome = awesome,
+ client = client }
+local setmetatable = setmetatable
+local pairs = pairs
+local ipairs = ipairs
+local table = table
+local common = require("awful.widget.common")
+local util = require("awful.util")
+local tag = require("awful.tag")
+local beautiful = require("beautiful")
+local fixed = require("wibox.layout.fixed")
+local surface = require("gears.surface")
+local timer = require("gears.timer")
+
+local function get_screen(s)
+ return s and capi.screen[s]
+end
+
+local taglist = { mt = {} }
+taglist.filter = {}
+
+--- The tag list main foreground (text) color.
+-- @beautiful beautiful.taglist_fg_focus
+-- @param[opt=fg_focus] color
+-- @see gears.color
+
+--- The tag list main background color.
+-- @beautiful beautiful.taglist_bg_focus
+-- @param[opt=bg_focus] color
+-- @see gears.color
+
+--- The tag list urgent elements foreground (text) color.
+-- @beautiful beautiful.taglist_fg_urgent
+-- @param[opt=fg_urgent] color
+-- @see gears.color
+
+--- The tag list urgent elements background color.
+-- @beautiful beautiful.taglist_bg_urgent
+-- @param[opt=bg_urgent] color
+-- @see gears.color
+
+--- The tag list occupied elements background color.
+-- @beautiful beautiful.taglist_bg_occupied
+-- @param color
+-- @see gears.color
+
+--- The tag list occupied elements foreground (text) color.
+-- @beautiful beautiful.taglist_fg_occupied
+-- @param color
+-- @see gears.color
+
+--- The tag list empty elements background color.
+-- @beautiful beautiful.taglist_bg_empty
+-- @param color
+-- @see gears.color
+
+--- The tag list empty elements foreground (text) color.
+-- @beautiful beautiful.taglist_fg_empty
+-- @param color
+-- @see gears.color
+
+--- The selected elements background image.
+-- @beautiful beautiful.taglist_squares_sel
+-- @param surface
+-- @see gears.surface
+
+--- The unselected elements background image.
+-- @beautiful beautiful.taglist_squares_unsel
+-- @param surface
+-- @see gears.surface
+
+--- The selected empty elements background image.
+-- @beautiful beautiful.taglist_squares_sel_empty
+-- @param surface
+-- @see gears.surface
+
+--- The unselected empty elements background image.
+-- @beautiful beautiful.taglist_squares_unsel_empty
+-- @param surface
+-- @see gears.surface
+
+--- If the background images can be resized.
+-- @beautiful beautiful.taglist_squares_resize
+-- @param boolean
+
+--- Do not display the tag icons, even if they are set.
+-- @beautiful beautiful.taglist_disable_icon
+-- @param boolean
+
+--- The taglist font.
+-- @beautiful beautiful.taglist_font
+-- @param string
+
+--- The main shape used for the elements.
+-- This will be the fallback for state specific shapes.
+-- To get a shape for the whole taglist, use `wibox.container.background`.
+-- @beautiful beautiful.taglist_shape
+-- @param[opt=rectangle] gears.shape
+-- @see gears.shape
+-- @see beautiful.taglist_shape_empty
+-- @see beautiful.taglist_shape_focus
+-- @see beautiful.taglist_shape_urgent
+
+--- The shape elements border width.
+-- @beautiful beautiful.taglist_shape_border_width
+-- @param[opt=0] number
+-- @see wibox.container.background
+
+--- The elements shape border color.
+-- @beautiful beautiful.taglist_shape_border_color
+-- @param color
+-- @see gears.color
+
+--- The shape used for the empty elements.
+-- @beautiful beautiful.taglist_shape_empty
+-- @param[opt=rectangle] gears.shape
+-- @see gears.shape
+
+--- The shape used for the empty elements border width.
+-- @beautiful beautiful.taglist_shape_border_width_empty
+-- @param[opt=0] number
+-- @see wibox.container.background
+
+--- The empty elements shape border color.
+-- @beautiful beautiful.taglist_shape_border_color_empty
+-- @param color
+-- @see gears.color
+
+--- The shape used for the selected elements.
+-- @beautiful beautiful.taglist_shape_focus
+-- @param[opt=rectangle] gears.shape
+-- @see gears.shape
+
+--- The shape used for the selected elements border width.
+-- @beautiful beautiful.taglist_shape_border_width_focus
+-- @param[opt=0] number
+-- @see wibox.container.background
+
+--- The selected elements shape border color.
+-- @beautiful beautiful.taglist_shape_border_color_focus
+-- @param color
+-- @see gears.color
+
+--- The shape used for the urgent elements.
+-- @beautiful beautiful.taglist_shape_urgent
+-- @param[opt=rectangle] gears.shape
+-- @see gears.shape
+
+--- The shape used for the urgent elements border width.
+-- @beautiful beautiful.taglist_shape_border_width_urgent
+-- @param[opt=0] number
+-- @see wibox.container.background
+
+--- The urgents elements shape border color.
+-- @beautiful beautiful.taglist_shape_border_color_urgent
+-- @param color
+-- @see gears.color
+
+local instances = nil
+
+function taglist.taglist_label(t, args)
+ if not args then args = {} end
+ local theme = beautiful.get()
+ local fg_focus = args.fg_focus or theme.taglist_fg_focus or theme.fg_focus
+ local bg_focus = args.bg_focus or theme.taglist_bg_focus or theme.bg_focus
+ local fg_urgent = args.fg_urgent or theme.taglist_fg_urgent or theme.fg_urgent
+ local bg_urgent = args.bg_urgent or theme.taglist_bg_urgent or theme.bg_urgent
+ local bg_occupied = args.bg_occupied or theme.taglist_bg_occupied
+ local fg_occupied = args.fg_occupied or theme.taglist_fg_occupied
+ local bg_empty = args.bg_empty or theme.taglist_bg_empty
+ local fg_empty = args.fg_empty or theme.taglist_fg_empty
+ local taglist_squares_sel = args.squares_sel or theme.taglist_squares_sel
+ local taglist_squares_unsel = args.squares_unsel or theme.taglist_squares_unsel
+ local taglist_squares_sel_empty = args.squares_sel_empty or theme.taglist_squares_sel_empty
+ local taglist_squares_unsel_empty = args.squares_unsel_empty or theme.taglist_squares_unsel_empty
+ local taglist_squares_resize = theme.taglist_squares_resize or args.squares_resize or "true"
+ local taglist_disable_icon = args.taglist_disable_icon or theme.taglist_disable_icon or false
+ local font = args.font or theme.taglist_font or theme.font or ""
+ local text = nil
+ local sel = capi.client.focus
+ local bg_color = nil
+ local fg_color = nil
+ local bg_image
+ local icon
+ local shape = args.shape or theme.taglist_shape
+ local shape_border_width = args.shape_border_width or theme.taglist_shape_border_width
+ local shape_border_color = args.shape_border_color or theme.taglist_shape_border_color
+ -- TODO: Re-implement bg_resize
+ local bg_resize = false -- luacheck: ignore
+ local is_selected = false
+ local cls = t:clients()
+
+ if sel and taglist_squares_sel then
+ -- Check that the selected client is tagged with 't'.
+ local seltags = sel:tags()
+ for _, v in ipairs(seltags) do
+ if v == t then
+ bg_image = taglist_squares_sel
+ bg_resize = taglist_squares_resize == "true"
+ is_selected = true
+ break
+ end
+ end
+ end
+ if #cls == 0 and t.selected and taglist_squares_sel_empty then
+ bg_image = taglist_squares_sel_empty
+ bg_resize = taglist_squares_resize == "true"
+ elseif not is_selected then
+ if #cls > 0 then
+ if taglist_squares_unsel then
+ bg_image = taglist_squares_unsel
+ bg_resize = taglist_squares_resize == "true"
+ end
+ if bg_occupied then bg_color = bg_occupied end
+ if fg_occupied then fg_color = fg_occupied end
+ else
+ if taglist_squares_unsel_empty then
+ bg_image = taglist_squares_unsel_empty
+ bg_resize = taglist_squares_resize == "true"
+ end
+ if bg_empty then bg_color = bg_empty end
+ if fg_empty then fg_color = fg_empty end
+
+ if args.shape_empty or theme.taglist_shape_empty then
+ shape = args.shape_empty or theme.taglist_shape_empty
+ end
+
+ if args.shape_border_width_empty or theme.taglist_shape_border_width_empty then
+ shape_border_width = args.shape_border_width_empty or theme.taglist_shape_border_width_empty
+ end
+
+ if args.shape_border_color_empty or theme.taglist_shape_border_color_empty then
+ shape_border_color = args.shape_border_color_empty or theme.taglist_shape_border_color_empty
+ end
+ end
+ end
+ if t.selected then
+ bg_color = bg_focus
+ fg_color = fg_focus
+
+ if args.shape_focus or theme.taglist_shape_focus then
+ shape = args.shape_focus or theme.taglist_shape_focus
+ end
+
+ if args.shape_border_width_focus or theme.taglist_shape_border_width_focus then
+ shape = args.shape_border_width_focus or theme.taglist_shape_border_width_focus
+ end
+
+ if args.shape_border_color_focus or theme.taglist_shape_border_color_focus then
+ shape = args.shape_border_color_focus or theme.taglist_shape_border_color_focus
+ end
+
+ elseif tag.getproperty(t, "urgent") then
+ if bg_urgent then bg_color = bg_urgent end
+ if fg_urgent then fg_color = fg_urgent end
+
+ if args.shape_urgent or theme.taglist_shape_urgent then
+ shape = args.shape_urgent or theme.taglist_shape_urgent
+ end
+
+ if args.shape_border_width_urgent or theme.taglist_shape_border_width_urgent then
+ shape_border_width = args.shape_border_width_urgent or theme.taglist_shape_border_width_urgent
+ end
+
+ if args.shape_border_color_urgent or theme.taglist_shape_border_color_urgent then
+ shape_border_color = args.shape_border_color_urgent or theme.taglist_shape_border_color_urgent
+ end
+ end
+
+ if not tag.getproperty(t, "icon_only") then
+ text = "<span font_desc='"..font.."'>"
+ if fg_color then
+ text = text .. "<span color='" .. util.ensure_pango_color(fg_color) ..
+ "'>" .. (util.escape(t.name) or "") .. "</span>"
+ else
+ text = text .. (util.escape(t.name) or "")
+ end
+ text = text .. "</span>"
+ end
+ if not taglist_disable_icon then
+ if t.icon then
+ icon = surface.load(t.icon)
+ end
+ end
+
+ local other_args = {
+ shape = shape,
+ shape_border_width = shape_border_width,
+ shape_border_color = shape_border_color,
+ }
+
+ return text, bg_color, bg_image, not taglist_disable_icon and icon or nil, other_args
+end
+
+local function taglist_update(s, w, buttons, filter, data, style, update_function)
+ local tags = {}
+ for _, t in ipairs(s.tags) do
+ if not tag.getproperty(t, "hide") and filter(t) then
+ table.insert(tags, t)
+ end
+ end
+
+ local function label(c) return taglist.taglist_label(c, style) end
+
+ update_function(w, buttons, label, data, tags)
+end
+
+--- Create a new taglist widget. The last two arguments (update_function
+-- and base_widget) serve to customize the layout of the taglist (eg. to
+-- make it vertical). For that, you will need to copy the
+-- awful.widget.common.list_update function, make your changes to it
+-- and pass it as update_function here. Also change the base_widget if the
+-- default is not what you want.
+-- @param screen The screen to draw taglist for.
+-- @param filter Filter function to define what clients will be listed.
+-- @param buttons A table with buttons binding to set.
+-- @tparam[opt={}] table style The style overrides default theme.
+-- @tparam[opt=nil] string|pattern style.fg_focus
+-- @tparam[opt=nil] string|pattern style.bg_focus
+-- @tparam[opt=nil] string|pattern style.fg_urgent
+-- @tparam[opt=nil] string|pattern style.bg_urgent
+-- @tparam[opt=nil] string|pattern style.bg_occupied
+-- @tparam[opt=nil] string|pattern style.fg_occupied
+-- @tparam[opt=nil] string|pattern style.bg_empty
+-- @tparam[opt=nil] string|pattern style.fg_empty
+-- @tparam[opt=nil] string style.taglist_squares_sel
+-- @tparam[opt=nil] string style.taglist_squares_unsel
+-- @tparam[opt=nil] string style.taglist_squares_sel_empty
+-- @tparam[opt=nil] string style.taglist_squares_unsel_empty
+-- @tparam[opt=nil] string style.taglist_squares_resize
+-- @tparam[opt=nil] string style.taglist_disable_icon
+-- @tparam[opt=nil] string style.font
+-- @tparam[opt=nil] number style.spacing The spacing between tags.
+-- @param[opt] update_function Function to create a tag widget on each
+-- update. See `awful.widget.common`.
+-- @param[opt] base_widget Optional container widget for tag widgets. Default
+-- is wibox.layout.fixed.horizontal().
+-- @param base_widget.bg_focus The background color for focused client.
+-- @param base_widget.fg_focus The foreground color for focused client.
+-- @param base_widget.bg_urgent The background color for urgent clients.
+-- @param base_widget.fg_urgent The foreground color for urgent clients.
+-- @param[opt] base_widget.squares_sel A user provided image for selected squares.
+-- @param[opt] base_widget.squares_unsel A user provided image for unselected squares.
+-- @param[opt] base_widget.squares_sel_empty A user provided image for selected squares for empty tags.
+-- @param[opt] base_widget.squares_unsel_empty A user provided image for unselected squares for empty tags.
+-- @param[opt] base_widget.squares_resize True or false to resize squares.
+-- @param base_widget.font The font.
+-- @function awful.taglist
+function taglist.new(screen, filter, buttons, style, update_function, base_widget)
+ screen = get_screen(screen)
+ local uf = update_function or common.list_update
+ local w = base_widget or fixed.horizontal()
+
+ if w.set_spacing and (style and style.spacing or beautiful.taglist_spacing) then
+ w:set_spacing(style and style.spacing or beautiful.taglist_spacing)
+ end
+
+ local data = setmetatable({}, { __mode = 'k' })
+
+ local queued_update = {}
+ function w._do_taglist_update()
+ -- Add a delayed callback for the first update.
+ if not queued_update[screen] then
+ timer.delayed_call(function()
+ if screen.valid then
+ taglist_update(screen, w, buttons, filter, data, style, uf)
+ end
+ queued_update[screen] = false
+ end)
+ queued_update[screen] = true
+ end
+ end
+ if instances == nil then
+ instances = setmetatable({}, { __mode = "k" })
+ local function u(s)
+ local i = instances[get_screen(s)]
+ if i then
+ for _, tlist in pairs(i) do
+ tlist._do_taglist_update()
+ end
+ end
+ end
+ local uc = function (c) return u(c.screen) end
+ local ut = function (t) return u(t.screen) end
+ capi.client.connect_signal("focus", uc)
+ capi.client.connect_signal("unfocus", uc)
+ tag.attached_connect_signal(nil, "property::selected", ut)
+ tag.attached_connect_signal(nil, "property::icon", ut)
+ tag.attached_connect_signal(nil, "property::hide", ut)
+ tag.attached_connect_signal(nil, "property::name", ut)
+ tag.attached_connect_signal(nil, "property::activated", ut)
+ tag.attached_connect_signal(nil, "property::screen", ut)
+ tag.attached_connect_signal(nil, "property::index", ut)
+ tag.attached_connect_signal(nil, "property::urgent", ut)
+ capi.client.connect_signal("property::screen", function(c, old_screen)
+ u(c.screen)
+ u(old_screen)
+ end)
+ capi.client.connect_signal("tagged", uc)
+ capi.client.connect_signal("untagged", uc)
+ capi.client.connect_signal("unmanage", uc)
+ capi.screen.connect_signal("removed", function(s)
+ instances[get_screen(s)] = nil
+ end)
+ end
+ w._do_taglist_update()
+ local list = instances[screen]
+ if not list then
+ list = setmetatable({}, { __mode = "v" })
+ instances[screen] = list
+ end
+ table.insert(list, w)
+ return w
+end
+
+--- Filtering function to include all nonempty tags on the screen.
+-- @param t The tag.
+-- @return true if t is not empty, else false
+function taglist.filter.noempty(t)
+ return #t:clients() > 0 or t.selected
+end
+
+--- Filtering function to include selected tags on the screen.
+-- @param t The tag.
+-- @return true if t is not empty, else false
+function taglist.filter.selected(t)
+ return t.selected
+end
+
+--- Filtering function to include all tags on the screen.
+-- @return true
+function taglist.filter.all()
+ return true
+end
+
+function taglist.mt:__call(...)
+ return taglist.new(...)
+end
+
+return setmetatable(taglist, taglist.mt)
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80