-
-
Notifications
You must be signed in to change notification settings - Fork 42
/
Copy pathsystemtray.py
115 lines (102 loc) · 4.3 KB
/
systemtray.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import gi
gi.require_version("Gray", "0.1")
from gi.repository import Gray, Gtk, Gdk, GdkPixbuf, GLib
import config.data as data
class SystemTray(Gtk.Box):
def __init__(self, pixel_size: int = 20, **kwargs) -> None:
orientation = Gtk.Orientation.HORIZONTAL if not data.VERTICAL else Gtk.Orientation.VERTICAL
super().__init__(
name="systray",
orientation=orientation,
spacing=8,
**kwargs
)
self.enabled = True # Flag to track if component should be shown
self.set_visible(False) # Initially hidden when empty.
self.pixel_size = pixel_size
self.watcher = Gray.Watcher()
self.watcher.connect("item-added", self.on_item_added)
def set_visible(self, visible):
"""Override to track external visibility setting"""
self.enabled = visible
# Only show if enabled AND has children
if visible and len(self.get_children()) > 0:
super().set_visible(True)
else:
super().set_visible(False)
def _update_visibility(self):
# Update visibility based on the number of child widgets and enabled state
if self.enabled and len(self.get_children()) > 0:
super().set_visible(True)
else:
super().set_visible(False)
def on_item_added(self, _, identifier: str):
item = self.watcher.get_item_for_identifier(identifier)
item_button = self.do_bake_item_button(item)
item.connect("removed", lambda *args: (item_button.destroy(), self._update_visibility()))
self.add(item_button)
item_button.show_all()
self._update_visibility()
def do_bake_item_button(self, item: Gray.Item) -> Gtk.Button:
button = Gtk.Button()
button.connect(
"button-press-event",
lambda button, event: self.on_button_click(button, item, event),
)
pixmap = Gray.get_pixmap_for_pixmaps(item.get_icon_pixmaps(), self.pixel_size)
try:
if pixmap is not None:
pixbuf = pixmap.as_pixbuf(self.pixel_size, GdkPixbuf.InterpType.HYPER)
else:
icon_name = item.get_icon_name()
icon_theme_path = item.get_icon_theme_path()
# Use custom theme path if available
if icon_theme_path:
custom_theme = Gtk.IconTheme.new()
custom_theme.prepend_search_path(icon_theme_path)
try:
pixbuf = custom_theme.load_icon(
icon_name,
self.pixel_size,
Gtk.IconLookupFlags.FORCE_SIZE,
)
except GLib.Error:
# Fallback to default theme if custom path fails
pixbuf = Gtk.IconTheme.get_default().load_icon(
icon_name,
self.pixel_size,
Gtk.IconLookupFlags.FORCE_SIZE,
)
else:
pixbuf = Gtk.IconTheme.get_default().load_icon(
icon_name,
self.pixel_size,
Gtk.IconLookupFlags.FORCE_SIZE,
)
except GLib.Error:
# Fallback to 'image-missing' icon
pixbuf = Gtk.IconTheme.get_default().load_icon(
"image-missing",
self.pixel_size,
Gtk.IconLookupFlags.FORCE_SIZE,
)
button.set_image(Gtk.Image.new_from_pixbuf(pixbuf))
return button
def on_button_click(self, button, item: Gray.Item, event):
if event.button == Gdk.BUTTON_PRIMARY: # Left click
try:
item.activate(event.x, event.y)
except Exception as e:
print(f"Error activating item: {e}")
elif event.button == Gdk.BUTTON_SECONDARY: # Right click
menu = item.get_menu()
if menu:
menu.set_name("system-tray-menu")
menu.popup_at_widget(
button,
Gdk.Gravity.SOUTH,
Gdk.Gravity.NORTH,
event,
)
else:
item.context_menu(event.x, event.y)