From 016ec1a186ec8f6652f2175f7526e6dc6a638c43 Mon Sep 17 00:00:00 2001 From: elParaguayo Date: Mon, 23 Dec 2024 14:17:16 +0000 Subject: [PATCH] Add ability to mask StatusNotifier icons Allows users to use icons as a mask and paint with a custom colour. --- qtile_extras/widget/statusnotifier.py | 50 +++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/qtile_extras/widget/statusnotifier.py b/qtile_extras/widget/statusnotifier.py index 315d7f3..84b6072 100644 --- a/qtile_extras/widget/statusnotifier.py +++ b/qtile_extras/widget/statusnotifier.py @@ -23,6 +23,7 @@ import os from typing import TYPE_CHECKING +import cairocffi from libqtile.log_utils import logger from libqtile.widget.helpers.status_notifier import StatusNotifierItem, host from libqtile.widget.statusnotifier import StatusNotifier as QtileStatusNotifier @@ -77,6 +78,11 @@ class StatusNotifier(QtileStatusNotifier, DbusMenuMixin): _screenshots = [("statusnotifier.png", "Widget showing Remmina icon and context menu.")] + defaults = [ + ("mask", False, "Use icon as mask. Use 'foreground' to set icon colour."), + ("foreground", "fff", "Colour for masked icons"), + ] + def __init__(self, **config): QtileStatusNotifier.__init__(self, **config) self.add_defaults(DbusMenuMixin.defaults) @@ -109,3 +115,47 @@ def show_menu(self): if not self.selected_item: return self.selected_item.get_menu(callback=self.display_menu) + + def _draw_icon(self, icon, x, y): + ctx = self.drawer.ctx + ctx.save() + + if self.mask: + ctx.translate(x, y) + self.drawer.set_source_rgb(self.foreground) + ctx.set_operator(cairocffi.OPERATOR_SOURCE) + ctx.mask(cairocffi.SurfacePattern(icon)) + ctx.fill() + + else: + ctx.set_source_surface(icon, x, y) + ctx.paint() + + ctx.restore() + + def draw(self): + self.drawer.clear(self.background or self.bar.background) + + if self.bar.horizontal: + xoffset = self.padding + yoffset = (self.bar.height - self.icon_size) // 2 + + for item in self.available_icons: + icon = item.get_icon(self.icon_size) + self._draw_icon(icon, xoffset, yoffset) + + xoffset += self.icon_size + self.padding + + self.drawer.draw(offsetx=self.offset, offsety=self.offsety, width=self.length) + + else: + xoffset = (self.bar.width - self.icon_size) // 2 + yoffset = self.padding + + for item in self.available_icons: + icon = item.get_icon(self.icon_size) + self._draw_icon(icon, xoffset, yoffset) + + yoffset += self.icon_size + self.padding + + self.drawer.draw(offsety=self.offset, offsetx=self.offsetx, height=self.length)