diff --git a/lib/awful/titlebar.lua b/lib/awful/titlebar.lua index 81a5ba41..96bcbca8 100644 --- a/lib/awful/titlebar.lua +++ b/lib/awful/titlebar.lua @@ -12,6 +12,7 @@ local util = require("awful.util") local abutton = require("awful.button") local aclient = require("awful.client") local atooltip = require("awful.tooltip") +local clienticon = require("awful.widget.clienticon") local beautiful = require("beautiful") local drawable = require("wibox.drawable") local imagebox = require("wibox.widget.imagebox") @@ -572,14 +573,7 @@ end -- @param c The client for which an icon widget should be created. -- @return The icon widget. function titlebar.widget.iconwidget(c) - local ret = imagebox() - local function update() - ret:set_image(c.icon) - end - c:connect_signal("property::icon", update) - update() - - return ret + return clienticon(c) end --- Create a new button widget. A button widget displays an image and reacts to diff --git a/lib/awful/widget/clienticon.lua b/lib/awful/widget/clienticon.lua new file mode 100644 index 00000000..b5eb9810 --- /dev/null +++ b/lib/awful/widget/clienticon.lua @@ -0,0 +1,118 @@ +--- Container showing the icon of a client. +-- @author Uli Schlachter +-- @copyright 2017 Uli Schlachter +-- @classmod awful.widget.clienticon + +local base = require("wibox.widget.base") +local surface = require("gears.surface") +local util = require("awful.util") + +local clienticon = {} +local instances = setmetatable({}, { __mode = "k" }) + +local function find_best_icon(sizes, width, height) + local best, best_size + for k, size in ipairs(sizes) do + if not best then + best, best_size = k, size + else + local best_too_small = best_size[1] < width or best_size[2] < height + local best_too_large = best_size[1] > width or best_size[2] > height + local better_because_bigger = best_too_small and size[1] > best_size[1] and size[2] > best_size[2] + local better_because_smaller = best_too_large and size[1] < best_size[1] and size[2] < best_size[2] + and size[1] >= width and size[2] >= height + if better_because_bigger or better_because_smaller then + best, best_size = k, size + end + end + end + return best, best_size +end + +function clienticon:draw(_, cr, width, height) + local c = self._private.client + if not c.valid then + return + end + + local index, size = find_best_icon(c.icon_sizes, width, height) + if not index then + return + end + + local aspect_w = width / size[1] + local aspect_h = height / size[2] + local aspect = math.min(aspect_w, aspect_h) + cr:scale(aspect, aspect) + + local s = surface(c:get_icon(index)) + cr:set_source_surface(s, 0, 0) + cr:paint() +end + +function clienticon:fit(_, width, height) + local c = self._private.client + if not c.valid then + return 0, 0 + end + + local index, size = find_best_icon(c.icon_sizes, width, height) + if not index then + return 0, 0 + end + + local w, h = size[1], size[2] + + if w > width then + h = h * width / w + w = width + end + if h > height then + w = w * height / h + h = height + end + + if h == 0 or w == 0 then + return 0, 0 + end + + local aspect = math.min(width / w, height / h) + return w * aspect, h * aspect +end + +--- Returns a new clienticon. +-- @tparam client c The client whose icon should be displayed. +-- @treturn widget A new `widget` +-- @function awful.widget.clienticon +local function new(c) + local ret = base.make_widget(nil, nil, {enable_properties = true}) + + util.table.crush(ret, clienticon, true) + + ret._private.client = c + + instances[ret] = true + + return ret +end + +client.connect_signal("property::icon", function(c) + for obj in pairs(instances) do + if obj._private.client.valid and obj._private.client == c then + obj:emit_signal("widget::layout_changed") + obj:emit_signal("widget::redraw_needed") + end + end +end) + +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + +return setmetatable(clienticon, { + __call = function(_, ...) + return new(...) + end +}) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/awful/widget/init.lua b/lib/awful/widget/init.lua index b10f21c7..ca0ed617 100644 --- a/lib/awful/widget/init.lua +++ b/lib/awful/widget/init.lua @@ -20,6 +20,7 @@ return keyboardlayout = require("awful.widget.keyboardlayout"); watch = require("awful.widget.watch"); only_on_screen = require("awful.widget.only_on_screen"); + clienticon = require("awful.widget.clienticon"); } -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80