From b00fbaa3e86c8f358fbf76269ab51ba6fcea7e08 Mon Sep 17 00:00:00 2001 From: notAxion Date: Sun, 29 Mar 2026 17:40:49 +0530 Subject: [PATCH 1/9] fix(launch): no module named '_version' --- discover_overlay/discover_overlay.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discover_overlay/discover_overlay.py b/discover_overlay/discover_overlay.py index 753591b..e44f067 100755 --- a/discover_overlay/discover_overlay.py +++ b/discover_overlay/discover_overlay.py @@ -22,12 +22,12 @@ import importlib_resources from configparser import ConfigParser from ctypes import CDLL -from ._version import __version__ CDLL("libgtk4-layer-shell.so") import gi +from ._version import __version__ from .overlay import OverlayWindow from .settings_window import Settings from .voice_overlay import VoiceOverlayWindow From e6d2ddca3f6840b562c8c46c3de2e06d281e031c Mon Sep 17 00:00:00 2001 From: notAxion Date: Sun, 29 Mar 2026 21:25:06 +0530 Subject: [PATCH 2/9] fix(enabled): enabled config logic should be handled per overlay basis --- discover_overlay/notification_overlay.py | 9 +++++++++ discover_overlay/text_overlay.py | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/discover_overlay/notification_overlay.py b/discover_overlay/notification_overlay.py index c92ae76..0631208 100644 --- a/discover_overlay/notification_overlay.py +++ b/discover_overlay/notification_overlay.py @@ -11,6 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Notification window for text""" + import logging import json import cairo @@ -92,10 +93,17 @@ def __init__(self, discover): self.text_align = "left" self.align_x = HorzAlign.RIGHT self.align_y = VertAlign.TOP + self.enabled = False self.show() + def set_enabled(self, enabled): + """Set if notifications should be enabled""" + self.enabled = enabled + def add_notification_message(self, data): """Add new message to dataset""" + if not self.enabled: + return if "data" in data: data = data["data"] if "body" in data or "title" in data: @@ -201,6 +209,7 @@ def update_all(self): def set_config(self, config): """Read in config section and set self and children accordingly""" + self.set_enabled(config.getboolean("enabled", fallback=False)) font = config.get("font", fallback=None) self.align_x = get_h_align(config.get("align_x", "right")) self.align_y = get_v_align(config.get("align_y", "top")) diff --git a/discover_overlay/text_overlay.py b/discover_overlay/text_overlay.py index b874a98..e8aac2a 100644 --- a/discover_overlay/text_overlay.py +++ b/discover_overlay/text_overlay.py @@ -11,6 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Overlay window for text""" + import logging import gi import cairo @@ -45,8 +46,13 @@ def __init__(self, discover): self.height_limit = 300 self.align_x = HorzAlign.RIGHT self.align_y = VertAlign.BOTTOM + self.enabled = False self.show() + def set_enabled(self, enabled): + """Set if text overlay should be enabled""" + self.enabled = enabled + def set_blank(self): """Set contents blank and redraw""" child = self.get_first_child() @@ -58,6 +64,8 @@ def set_blank(self): def new_line(self, message): """Add a new message to text overlay. Does not sanity check the data""" + if not self.enabled: + return message = Message(self, message) if not message.skip: self.append(message) @@ -104,6 +112,7 @@ def update_all(self): def set_config(self, config): """Set self and children from config""" + self.set_enabled(config.getboolean("enabled", fallback=False)) channel = config.get("channel", fallback="0") guild = config.get("guild", fallback="0") self.discover.connection.set_text_channel(channel, guild) From 71ca8f67d7602dc49936e9baf7414b474bc37263 Mon Sep 17 00:00:00 2001 From: notAxion Date: Mon, 30 Mar 2026 01:51:52 +0530 Subject: [PATCH 3/9] fix(redraw): redraw the userbox everytime sometime updates seems to fix few known issues - changing the text side option from the settings menu wouldn't update the overlay right away - somehow adding an initial padding when opened on a environment with no previous config still not sure if this is the right way to fix this. --- discover_overlay/voice_overlay.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 38f9768..a9c0317 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -594,6 +594,10 @@ def set_config(self, config): self.update_all() + for child in self: + if isinstance(child, UserBox): + child.queue_resize() + def set_css(self, css_id, rule): """Add or replace CSS Rule""" self.get_root().set_css(css_id, rule) From 808ec546e9864a3c7ad73910aac3aea70098f7f7 Mon Sep 17 00:00:00 2001 From: notAxion Date: Mon, 30 Mar 2026 02:40:48 +0530 Subject: [PATCH 4/9] fix(color-picker): bring back the opacity selector grk color button is deprecated, migrated to gtk color dialog --- discover_overlay/glade/settings.xml | 143 +++++++++++++++++++++++----- 1 file changed, 117 insertions(+), 26 deletions(-) diff --git a/discover_overlay/glade/settings.xml b/discover_overlay/glade/settings.xml index 94a2761..06697df 100644 --- a/discover_overlay/glade/settings.xml +++ b/discover_overlay/glade/settings.xml @@ -400,11 +400,18 @@ - + voice_talking_foreground 1 1 - + + + Select Color + 1 + 1 + + + 3 1 @@ -412,11 +419,18 @@ - + voice_talking_background 1 1 - + + + Select Color + 1 + 1 + + + 4 1 @@ -424,11 +438,18 @@ - + voice_talking_border 1 1 - + + + Select Color + 1 + 1 + + + 5 1 @@ -436,11 +457,18 @@ - + voice_idle_foreground 1 1 - + + + Select Color + 1 + 1 + + + 3 2 @@ -448,11 +476,18 @@ - + voice_idle_background 1 1 - + + + Select Color + 1 + 1 + + + 4 2 @@ -460,11 +495,18 @@ - + voice_idle_border 1 1 - + + + Select Color + 1 + 1 + + + 5 2 @@ -472,11 +514,18 @@ - + voice_mute_foreground 1 1 - + + + Select Color + 1 + 1 + + + 3 3 @@ -484,11 +533,18 @@ - + voice_mute_background 1 1 - + + + Select Color + 1 + 1 + + + 4 3 @@ -496,11 +552,18 @@ - + voice_avatar_background 1 1 - + + + Select Color + 1 + 1 + + + 4 4 @@ -1429,11 +1492,18 @@ - + text_background_colour 1 1 - + + + Select Color + 1 + 1 + + + 1 8 @@ -1452,11 +1522,18 @@ - + text_colour 1 1 - + + + Select Color + 1 + 1 + + + 1 7 @@ -1858,11 +1935,18 @@ - + notification_text_colour 1 1 - + + + Select Color + 1 + 1 + + + 1 5 @@ -1870,11 +1954,18 @@ - + notification_background_colour 1 1 - + + Select Color + 1 + 1 + + + 1 From 7a62e170f77e3ffc77fb728a5386f84e645c161e Mon Sep 17 00:00:00 2001 From: notAxion Date: Mon, 30 Mar 2026 03:28:40 +0530 Subject: [PATCH 5/9] fix(set-function): handler functions of the settings ui now gets called and config set correctly _param=None is just another param because i had to change to a different signal (to notifiy::rgba) --- discover_overlay/settings_window.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index ddf6024..6dc54e3 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -886,47 +886,47 @@ def voice_display_speakers_grace_period(self, button): def voice_toggle_test_content(self, button): self.config_set("main", "show_dummy", f"{button.get_active()}") - def voice_talking_foreground_changed(self, button): + def voice_talking_foreground_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "fg_hi_col", json.dumps(colour)) - def voice_talking_background_changed(self, button): + def voice_talking_background_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "hi_col", json.dumps(colour)) - def voice_talking_border_changed(self, button): + def voice_talking_border_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "tk_col", json.dumps(colour)) - def voice_idle_foreground_changed(self, button): + def voice_idle_foreground_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "fg_col", json.dumps(colour)) - def voice_idle_background_changed(self, button): + def voice_idle_background_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "bg_col", json.dumps(colour)) - def voice_idle_border_changed(self, button): + def voice_idle_border_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "bo_col", json.dumps(colour)) - def voice_mute_foreground_changed(self, button): + def voice_mute_foreground_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "mt_col", json.dumps(colour)) - def voice_mute_background_changed(self, button): + def voice_mute_background_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "mt_bg_col", json.dumps(colour)) - def voice_avatar_background_changed(self, button): + def voice_avatar_background_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("main", "avatar_bg_col", json.dumps(colour)) @@ -1028,12 +1028,12 @@ def text_channel_changed(self, button): def text_font_changed(self, button): self.config_set("text", "font", button.get_font()) - def text_colour_changed(self, button): + def text_colour_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("text", "fg_col", json.dumps(colour)) - def text_background_colour_changed(self, button): + def text_background_colour_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("text", "bg_col", json.dumps(colour)) @@ -1083,12 +1083,12 @@ def notification_limit_popup_width_changed(self, button): def notification_font_changed(self, button): self.config_set("notification", "font", button.get_font()) - def notification_text_colour_changed(self, button): + def notification_text_colour_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("notification", "fg_col", json.dumps(colour)) - def notification_background_colour_changed(self, button): + def notification_background_colour_changed(self, button, _param=None): colour = button.get_rgba() colour = [colour.red, colour.green, colour.blue, colour.alpha] self.config_set("notification", "bg_col", json.dumps(colour)) From 60a3e5dab7f9efa55f5ace128225012256514fc6 Mon Sep 17 00:00:00 2001 From: notAxion Date: Mon, 30 Mar 2026 05:55:38 +0530 Subject: [PATCH 6/9] fix(make_colour): colours were not getting shown on the color dialog button after reading config file seems this is the way to initialize RGBA now --- discover_overlay/settings_window.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index 6dc54e3..29bb605 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -737,7 +737,12 @@ def read_config(self): def make_colour(self, col): """Create a Gdk Color from a col tuple""" col = json.loads(col) - return Gdk.RGBA(col[0], col[1], col[2], col[3]) + rgba = Gdk.RGBA() + rgba.red = col[0] + rgba.green = col[1] + rgba.blue = col[2] + rgba.alpha = col[3] + return rgba def parse_guild_ids(self, guild_ids_str): """Parse the guild_ids from a str and return them in a list""" @@ -954,7 +959,7 @@ def voice_border_width_changed(self, button): self.config_set("main", "border_width", f"{int(button.get_value())}") def voice_avatar_circle_changed(self, button): - self.config_set("main", "square_avatar", f"{ not button.get_active()}") + self.config_set("main", "square_avatar", f"{not button.get_active()}") def voice_show_title_changed(self, button): self.config_set("main", "show_title", f"{button.get_active()}") From c803a20cd87163ba58cc64c5f0fe76db85581aee Mon Sep 17 00:00:00 2001 From: notAxion Date: Mon, 30 Mar 2026 17:12:35 +0530 Subject: [PATCH 7/9] feat(border): show border around the avatar instead of wrapping the whole user with name also fixes the border showing on the background while avatar is transparent --- discover_overlay/voice_overlay.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index a9c0317..235d540 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -356,33 +356,30 @@ def set_overflow_style(self, overflow): def set_borders(self): """Update all border CSS rules based on config""" width = self.border_width + half = width / 2 col = col_to_css(self.border_col) talk_col = col_to_css(self.talk_col) rounded = "border-radius: 50%;" if self.rounded_avatar else "" - - drop_shadow_normal = "" - drop_shadow_talking = "" - for j in range(0, width+1): - drop_shadow_talking += f" drop-shadow(0px 0px {width}px {talk_col})" - drop_shadow_normal += f" drop-shadow(0px 0px {width}px {col})" - # Pile up extra filters to darken the effect... This is such a stupid idea - self.set_css( "talking-border", f""" - .talking.user + .talking .usericon {{ - filter: {drop_shadow_talking}; + outline: {width}px solid {talk_col}; + outline-offset: -{half}px; + {rounded} }} - .user + .usericon {{ - filter: {drop_shadow_normal}; + outline: {width}px solid {col}; + outline-offset: -{half}px; + {rounded} }} .usericon, .usermute, .userdeaf {{ {rounded} }} - .container {{ padding: {width*2}px; }} + .container {{ padding: {width}px; }} """, ) From fee2def9ef4fbea5305015bdfaed776a7e7e75f5 Mon Sep 17 00:00:00 2001 From: notAxion Date: Tue, 31 Mar 2026 14:03:35 +0530 Subject: [PATCH 8/9] fix(border): changing avatar opacity would change the border opacity together gtk box was created to have a separete css class so only avatar gets affected when changing the opacity --- discover_overlay/layout.py | 3 ++- discover_overlay/userbox.py | 10 ++++++++-- discover_overlay/voice_overlay.py | 8 ++++---- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/discover_overlay/layout.py b/discover_overlay/layout.py index 90b6214..13a8762 100644 --- a/discover_overlay/layout.py +++ b/discover_overlay/layout.py @@ -11,6 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Collection of LayoutManagers used throughout""" + import logging from enum import Enum import gi @@ -288,7 +289,7 @@ def do_allocate(self, widget, width, height, _baseline): else: widget.label.set_valign(Gtk.Align.END) - widget.image.size_allocate(img_alloc, -1) + widget.image_wrapper.size_allocate(img_alloc, -1) widget.label.size_allocate(lbl_alloc, -1) widget.mute.size_allocate(img_alloc, -1) widget.deaf.size_allocate(img_alloc, -1) diff --git a/discover_overlay/userbox.py b/discover_overlay/userbox.py index 9a6d211..ee7e05f 100644 --- a/discover_overlay/userbox.py +++ b/discover_overlay/userbox.py @@ -11,6 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . """A Gtk Box with direction""" + import gettext import logging import gi @@ -55,9 +56,14 @@ def __init__(self, overlay, userid): self.deaf = Gtk.Image() self.image.set_overflow(Gtk.Overflow.HIDDEN) + self.image.add_css_class("usericon-image") + + self.image_wrapper = Gtk.Box() + self.image_wrapper.add_css_class("usericon") + self.image_wrapper.append(self.image) - self.image.add_css_class("usericon") self.label.add_css_class("userlabel") + self.mute.add_css_class("usermute") self.deaf.add_css_class("userdeaf") @@ -69,7 +75,7 @@ def __init__(self, overlay, userid): self.deaf.set_valign(Gtk.Align.CENTER) self.append(self.label) - self.append(self.image) + self.append(self.image_wrapper) self.append(self.mute) self.append(self.deaf) diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 235d540..2eb1acd 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -11,6 +11,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Overlay window for voice""" + import random import gettext import logging @@ -298,7 +299,6 @@ def overlay_fadeout(self): now = perf_counter() time_percent = (now - self.fade_start) / self.inactive_fade_time if time_percent >= 1.0: - fade_opacity = self.fade_out_limit self.fadeout_timeout = None self.set_css("fade-out", ".container { opacity: %2.2f;}" % (fade_opacity)) @@ -375,9 +375,9 @@ def set_borders(self): outline-offset: -{half}px; {rounded} }} - .usericon, .usermute, .userdeaf + .usericon-image, .usermute, .userdeaf {{ - {rounded} + {rounded} }} .container {{ padding: {width}px; }} """, @@ -562,7 +562,7 @@ def set_config(self, config): self.set_css( "icon_transparency", - ".usericon { opacity: %2.2f; }" + ".usericon-image { opacity: %2.2f; }" % (config.getfloat("icon_transparency", fallback=1.0)), ) From b58d572d2fcce2c080e9d350f93343cd531436e4 Mon Sep 17 00:00:00 2001 From: notAxion Date: Thu, 9 Apr 2026 20:05:45 +0530 Subject: [PATCH 9/9] feat(border): show border around the username, with a setting to turn it off --- discover_overlay/glade/settings.xml | 54 ++++++++++++++++++++--------- discover_overlay/layout.py | 16 +++++++-- discover_overlay/settings_window.py | 7 ++++ discover_overlay/voice_overlay.py | 15 ++++++++ 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/discover_overlay/glade/settings.xml b/discover_overlay/glade/settings.xml index 06697df..0cd8af3 100644 --- a/discover_overlay/glade/settings.xml +++ b/discover_overlay/glade/settings.xml @@ -705,7 +705,7 @@ 5 - 11 + 12 @@ -716,7 +716,7 @@ 0 4 - 11 + 12 @@ -1197,6 +1197,28 @@ + + + voice_text_border_label + Border around text + 0 + + 4 + 5 + + + + + + voice_text_border + 1 + + + 5 + 5 + + + voice_border_width_label @@ -1204,7 +1226,7 @@ 0 4 - 5 + 6 @@ -1218,7 +1240,7 @@ 5 - 5 + 6 @@ -1229,7 +1251,7 @@ 0 4 - 6 + 7 @@ -1242,7 +1264,7 @@ 5 - 6 + 7 @@ -1255,7 +1277,7 @@ 5 - 12 + 14 @@ -1266,7 +1288,7 @@ 0 4 - 7 + 8 @@ -1277,7 +1299,7 @@ 0 4 - 8 + 9 @@ -1288,7 +1310,7 @@ 0 4 - 9 + 10 @@ -1299,7 +1321,7 @@ 0 4 - 10 + 11 @@ -1310,7 +1332,7 @@ 5 - 7 + 8 @@ -1325,7 +1347,7 @@ swapped="no" /> 5 - 8 + 9 @@ -1338,7 +1360,7 @@ 5 - 9 + 10 @@ -1351,7 +1373,7 @@ 5 - 10 + 11 @@ -2308,4 +2330,4 @@ - \ No newline at end of file + diff --git a/discover_overlay/layout.py b/discover_overlay/layout.py index 13a8762..6e2451c 100644 --- a/discover_overlay/layout.py +++ b/discover_overlay/layout.py @@ -274,13 +274,23 @@ def do_allocate(self, widget, width, height, _baseline): lbl_alloc.x = lbl_alloc.y = 0 lbl_alloc.width = width - tx = widget.overlay.text_x_align - if tx == "left": + # i hope this isn't needed anymore + # tx = widget.overlay.text_x_align + # if tx == "left": + # widget.label.set_halign(Gtk.Align.START) + # elif tx == "middle": + # widget.label.set_halign(Gtk.Align.CENTER) + # else: + # widget.label.set_halign(Gtk.Align.END) + if direction == Direction.LTR: widget.label.set_halign(Gtk.Align.START) - elif tx == "middle": + elif direction == Direction.TTB: + widget.label.set_halign(Gtk.Align.CENTER) + elif direction == Direction.BTT: widget.label.set_halign(Gtk.Align.CENTER) else: widget.label.set_halign(Gtk.Align.END) + ty = widget.overlay.text_y_align if ty == "top": widget.label.set_valign(Gtk.Align.START) diff --git a/discover_overlay/settings_window.py b/discover_overlay/settings_window.py index 29bb605..cd8e6be 100644 --- a/discover_overlay/settings_window.py +++ b/discover_overlay/settings_window.py @@ -533,6 +533,10 @@ def read_config(self): config.getint("main", "order", fallback=0) ) + self.widget["voice_text_border"].set_active( + config.getboolean("main", "text_border", fallback=True) + ) + self.widget["voice_border_width"].set_value( config.getint("main", "border_width", fallback=2) ) @@ -955,6 +959,9 @@ def voice_fancy_avatar_shapes_changed(self, button): def voice_order_avatars_by_changed(self, button): self.config_set("main", "order", f"{button.get_active()}") + def voice_text_border_changed(self, button): + self.config_set("main", "text_border", f"{button.get_active()}") + def voice_border_width_changed(self, button): self.config_set("main", "border_width", f"{int(button.get_value())}") diff --git a/discover_overlay/voice_overlay.py b/discover_overlay/voice_overlay.py index 2eb1acd..e9008c6 100644 --- a/discover_overlay/voice_overlay.py +++ b/discover_overlay/voice_overlay.py @@ -62,6 +62,7 @@ def __init__(self, discover): self.use_dummy = False self.dummy_count = 10 self.border_width = 2 + self.text_border = True self.only_speaking_grace_period = 0 self.text_side = 3 self.rounded_avatar = True @@ -360,6 +361,18 @@ def set_borders(self): col = col_to_css(self.border_col) talk_col = col_to_css(self.talk_col) rounded = "border-radius: 50%;" if self.rounded_avatar else "" + text_border = "" + if self.text_border: + text_border = f""" + .userlabel + {{ + outline: {width}px solid {col}; + }} + .talking .userlabel + {{ + outline: {width}px solid {talk_col}; + }} + """ self.set_css( "talking-border", f""" @@ -380,6 +393,7 @@ def set_borders(self): {rounded} }} .container {{ padding: {width}px; }} + {text_border} """, ) @@ -557,6 +571,7 @@ def set_config(self, config): config.getboolean("show_disconnected", fallback=True) ) self.border_width = config.getint("border_width", fallback=2) + self.text_border = config.getboolean("text_border", fallback=True) self.show_avatar = config.getboolean("show_avatar", fallback=True)