Skip to content

Commit 49fad9c

Browse files
committed
Show a Linux tray icon's title as its label, not in the tooltip
The StatusNotifierItem put SetTitle's text into the ToolTip heading, and into its body when no tooltip was set, so hosts showed the title on hover. The ToolTip now carries the tooltip alone; the title is the XAyatanaLabel (with XAyatanaNewLabel), which GNOME's AppIndicator extension draws next to the icon as macOS draws the title, and as libayatana's app_indicator_set_label did; KDE and most bars ignore it. Title names the application, as the SNI spec has it, which hosts list the item by and show for an empty tooltip.
1 parent 9d6b50d commit 49fad9c

1 file changed

Lines changed: 23 additions & 5 deletions

File tree

‎src/platform/linux/tray_icon_linux.cpp‎

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ static const char kSniIntrospectionXml[] =
112112
" <property name='ToolTip' type='(sa(iiay)ss)' access='read'/>"
113113
" <property name='ItemIsMenu' type='b' access='read'/>"
114114
" <property name='Menu' type='o' access='read'/>"
115+
" <property name='XAyatanaLabel' type='s' access='read'/>"
116+
" <property name='XAyatanaLabelGuide' type='s' access='read'/>"
115117
" <method name='ContextMenu'>"
116118
" <arg type='i' direction='in' name='x'/>"
117119
" <arg type='i' direction='in' name='y'/>"
@@ -133,6 +135,10 @@ static const char kSniIntrospectionXml[] =
133135
" <signal name='NewAttentionIcon'/>"
134136
" <signal name='NewOverlayIcon'/>"
135137
" <signal name='NewToolTip'/>"
138+
" <signal name='XAyatanaNewLabel'>"
139+
" <arg type='s' name='label'/>"
140+
" <arg type='s' name='guide'/>"
141+
" </signal>"
136142
" <signal name='NewStatus'>"
137143
" <arg type='s' name='status'/>"
138144
" </signal>"
@@ -624,8 +630,19 @@ class TrayIcon::Impl {
624630
if (g_strcmp0(property_name, "Id") == 0)
625631
return g_variant_new_string(self->identifier_.c_str());
626632

627-
if (g_strcmp0(property_name, "Title") == 0)
633+
// The SNI Title names the application; hosts list the item by it and fall
634+
// back to it for an empty tooltip. SetTitle's text is the Ayatana label below.
635+
if (g_strcmp0(property_name, "Title") == 0) {
636+
const char* name = g_get_application_name();
637+
return g_variant_new_string(name ? name : self->identifier_.c_str());
638+
}
639+
640+
// Drawn next to the icon by hosts that know it (GNOME's AppIndicator
641+
// extension), as macOS draws the title; KDE and most bars ignore it.
642+
if (g_strcmp0(property_name, "XAyatanaLabel") == 0)
628643
return g_variant_new_string(self->title_.value_or("").c_str());
644+
if (g_strcmp0(property_name, "XAyatanaLabelGuide") == 0)
645+
return g_variant_new_string("");
629646

630647
if (g_strcmp0(property_name, "Status") == 0)
631648
return g_variant_new_string(self->visible_ ? "Active" : "Passive");
@@ -651,10 +668,10 @@ class TrayIcon::Impl {
651668
if (g_strcmp0(property_name, "AttentionMovieName") == 0) return g_variant_new_string("");
652669

653670
if (g_strcmp0(property_name, "ToolTip") == 0) {
654-
// (sa(iiay)ss): iconName, iconPixmap[], title, description
655-
const std::string& tip = self->tooltip_.value_or(self->title_.value_or(""));
671+
// (sa(iiay)ss): iconName, iconPixmap[], title, description. The tooltip
672+
// is the heading; hosts show an empty one as the item's Title.
656673
return g_variant_new("(s@a(iiay)ss)", "", PixbufToSniIconPixmaps(nullptr),
657-
self->title_.value_or("").c_str(), tip.c_str());
674+
self->tooltip_.value_or("").c_str(), "");
658675
}
659676

660677
if (g_strcmp0(property_name, "ItemIsMenu") == 0)
@@ -1095,7 +1112,8 @@ std::shared_ptr<View> TrayIcon::GetContentView() const {
10951112

10961113
void TrayIcon::SetTitle(std::optional<std::string> title) {
10971114
pimpl_->title_ = title;
1098-
pimpl_->EmitSignal("NewTitle");
1115+
pimpl_->EmitSignal("XAyatanaNewLabel",
1116+
g_variant_new("(ss)", pimpl_->title_.value_or("").c_str(), ""));
10991117
}
11001118

11011119
std::optional<std::string> TrayIcon::GetTitle() {

0 commit comments

Comments
 (0)