Skip to content

Commit afb3ffb

Browse files
authored
Merge pull request #13 from meowrch/feat/system-tray-improvement
feat(system-tray): Windows-style toggle arrow + floating popover
2 parents e6d1136 + d889f52 commit afb3ffb

File tree

5 files changed

+326
-137
lines changed

5 files changed

+326
-137
lines changed

src/mewline/constants.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,11 @@
115115
"10": "10",
116116
},
117117
},
118-
"system_tray": {"icon_size": 16, "ignore": []},
118+
"system_tray": {
119+
"icon_size": 16,
120+
"ignore": [],
121+
"pinned": ["Telegram"]
122+
},
119123
"power": {"icon": "", "icon_size": "16px", "tooltip": True},
120124
"datetime": {"format": "%d-%m-%y %H:%M"},
121125
"battery": {

src/mewline/shared/popover.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def __init__(self):
2626
name="popover-overlay",
2727
style_classes="popover-overlay",
2828
anchor="left top right bottom",
29+
margin="-50px 0px 0px 0px",
2930
exclusivity="auto",
3031
layer="overlay",
3132
type="top-level",
@@ -87,14 +88,14 @@ def popover_closed(widget: Widget): ...
8788

8889
@GObject.type_register
8990
class Popover(Widget):
90-
"""Memory-efficient popover implementation (ported from Tsumiki style)."""
91+
"""Memory-efficient popover implementation"""
9192

9293
__gsignals__: ClassVar = {
9394
"popover-opened": (GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()),
9495
"popover-closed": (GObject.SignalFlags.RUN_LAST, GObject.TYPE_NONE, ()),
9596
}
9697

97-
def __init__(self, content=None, point_to=None, gap: int = 2):
98+
def __init__(self, content=None, point_to=None, gap: int = 4):
9899
super().__init__()
99100
self._content_factory = None
100101
self._point_to = point_to
@@ -122,22 +123,30 @@ def open(self, *_):
122123
def _calculate_margins(self):
123124
widget_allocation = self._point_to.get_allocation()
124125
popover_size = self._content_window.get_size()
126+
125127
display = Gdk.Display.get_default()
126128
screen = display.get_default()
127-
monitor_at_window = screen.get_monitor_at_window(self._point_to.get_window())
129+
monitor_at_window = screen.get_monitor_at_window(
130+
self._point_to.get_window()
131+
)
128132
monitor_geometry = monitor_at_window.get_geometry()
129-
# Center under widget horizontally
133+
134+
# Center horizontally under the widget
130135
x = (
131136
widget_allocation.x
132-
+ (widget_allocation.width / 2)
133-
- (popover_size.width / 2)
137+
+ widget_allocation.width / 2
138+
- popover_size.width / 2
134139
)
135-
y = widget_allocation.y + widget_allocation.height + self._gap
140+
141+
y = widget_allocation.y + self._gap
142+
143+
# Horizontal bounds check
136144
if x <= 0:
137145
x = widget_allocation.x
138146
elif x + popover_size.width >= monitor_geometry.width:
139147
x = widget_allocation.x - popover_size.width + widget_allocation.width
140-
return [y, 0, 0, int(x)]
148+
149+
return [int(y), 0, 0, int(x)]
141150

142151
def set_position(self, position: tuple[int, int, int, int] | None = None):
143152
if position is None:
@@ -157,11 +166,8 @@ def _create_popover(self):
157166
self._content_window.add(
158167
Box(style_classes="popover-content", children=self._content)
159168
)
160-
# Key and focus handling
161169
try:
162170
self._content_window.connect("key-press-event", self._on_key_press)
163-
# Do not auto-close on focus-out to avoid closing
164-
# while interacting with sliders
165171
self._content_window.set_can_focus(True)
166172
except Exception:
167173
...
@@ -173,8 +179,6 @@ def _create_popover(self):
173179
self._content_window.grab_focus()
174180

175181
self._visible = True
176-
self._content_window.show()
177-
self._visible = True
178182

179183
def hide_popover(self):
180184
if not self._visible or not self._content_window:
@@ -195,7 +199,6 @@ def _on_key_press(self, widget, event):
195199

196200
return False
197201

198-
# Compatibility helpers
199202
def close(self):
200203
return self.hide_popover()
201204

src/mewline/styles/system_tray.scss

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,89 @@
22
@use "variable.scss";
33
@use "common/functions.scss";
44

5+
// ── Status-bar toggle capsule ──────────────────────────────────────────────
56
#system-tray {
6-
padding: 0.125em 0.7em;
7-
color: theme.$text-color;
7+
padding: 0.2em 1em;
8+
border-radius: variable.$radius-large;
9+
10+
#system-tray-pinned {
11+
// Pinned icons sit flush next to the chevron
12+
}
813

9-
// Recolor tray icons (symbolic via CSS, raster are tinted in code)
10-
image,
11-
.tray-icon {
14+
#nerd-icon.chevron-icon {
15+
font-size: 0.75em;
1216
color: theme.$text-color;
17+
opacity: 0.8;
1318
}
1419

15-
& > button {
16-
margin: 0 0.1em;
17-
padding: 0 0.15em;
18-
border-radius: variable.$radius-large;
20+
&.active,
21+
&:active {
22+
background-color: theme.$background-highlight;
23+
24+
#nerd-icon.chevron-icon {
25+
color: theme.$accent-color;
26+
opacity: 1;
27+
}
28+
}
29+
30+
&:hover {
31+
background-color: theme.$background-highlight;
32+
}
33+
34+
// Pinned icon buttons
35+
.tray-item-btn {
36+
padding: 0 0.1em;
37+
border-radius: variable.$radius;
38+
background: transparent;
39+
min-width: 0;
40+
min-height: 0;
41+
42+
&:hover {
43+
background-color: theme.$background-highlight;
44+
}
45+
}
46+
}
47+
48+
// ── Popup grid ────────────────────────────────────────────────────────────
49+
#system-tray-popup {
50+
background-color: theme.$background-base;
51+
border-radius: variable.$radius;
52+
padding: 0;
53+
54+
.tray-item-btn {
55+
padding: 0.35em;
56+
border-radius: variable.$radius;
57+
background: transparent;
58+
min-width: 32px;
59+
min-height: 32px;
60+
1961
&:hover {
2062
background-color: theme.$background-highlight;
2163
}
2264

2365
&:active {
24-
background-color: theme.$text-color;
66+
opacity: 0.7;
67+
}
68+
69+
image {
70+
color: theme.$text-color;
2571
}
2672
}
2773
}
2874

75+
// ── GTK context menus (right-click on a tray icon) ────────────────────────
2976
#system-tray-menu > menuitem menu,
3077
#system-tray-menu {
3178
background-color: theme.$background-highlight;
32-
border-radius: 1em;
79+
border-radius: variable.$radius;
3380
padding: functions.toEm(10);
3481
min-width: 100px;
3582
font-weight: bold;
3683
}
3784

3885
#system-tray-menu > menuitem menu > menuitem,
3986
#system-tray-menu > menuitem {
40-
margin: 5px 0px;
87+
margin: 5px 0;
4188
background-color: theme.$background-highlight;
4289
padding: 0.3em 0.5em;
4390
border-radius: variable.$radius;
@@ -50,13 +97,11 @@
5097
}
5198

5299
#system-tray-menu > menuitem menu > menuitem:hover,
53-
#system-tray-menu > menuitem:hover,
54-
#submenu-button:hover {
100+
#system-tray-menu > menuitem:hover {
55101
background-color: theme.$background-highlight;
56102
color: theme.$accent-color;
57103
}
58104

59-
// Ensure symbolic icons inside tray menus also get the accent color
60105
#system-tray-menu image {
61106
color: theme.$text-color;
62107
}

src/mewline/utils/config_structure.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class WorkspacesModule(BaseModel):
6363
class TrayModule(BaseModel):
6464
icon_size: int
6565
ignore: list[str]
66+
pinned: list[str]
6667

6768

6869
class PowerModule(BaseModel):

0 commit comments

Comments
 (0)