add tray icons
This commit is contained in:
174
src/widgets/tray.cpp
Normal file
174
src/widgets/tray.cpp
Normal file
@@ -0,0 +1,174 @@
|
||||
#include "widgets/tray.hpp"
|
||||
|
||||
#include <utility>
|
||||
|
||||
TrayIconWidget::TrayIconWidget(TrayService &service, std::string id)
|
||||
: m_service(service), m_id(std::move(id)), m_container(Gtk::Orientation::HORIZONTAL)
|
||||
{
|
||||
set_has_frame(false);
|
||||
set_focusable(false);
|
||||
set_valign(Gtk::Align::CENTER);
|
||||
set_halign(Gtk::Align::CENTER);
|
||||
add_css_class("tray-icon");
|
||||
|
||||
m_picture.set_halign(Gtk::Align::CENTER);
|
||||
m_picture.set_valign(Gtk::Align::CENTER);
|
||||
m_picture.set_content_fit(Gtk::ContentFit::CONTAIN);
|
||||
m_picture.set_can_shrink(true);
|
||||
m_picture.set_size_request(20, 20);
|
||||
|
||||
m_image.set_pixel_size(20);
|
||||
m_image.set_halign(Gtk::Align::CENTER);
|
||||
m_image.set_valign(Gtk::Align::CENTER);
|
||||
|
||||
m_container.set_spacing(0);
|
||||
m_container.set_halign(Gtk::Align::CENTER);
|
||||
m_container.set_valign(Gtk::Align::CENTER);
|
||||
m_container.append(m_picture);
|
||||
m_container.append(m_image);
|
||||
|
||||
m_picture.set_visible(false);
|
||||
m_image.set_visible(true);
|
||||
set_child(m_container);
|
||||
|
||||
signal_clicked().connect(sigc::mem_fun(*this, &TrayIconWidget::on_primary_clicked));
|
||||
|
||||
m_secondaryGesture = Gtk::GestureClick::create();
|
||||
m_secondaryGesture->set_button(GDK_BUTTON_SECONDARY);
|
||||
m_secondaryGesture->signal_released().connect(sigc::mem_fun(*this, &TrayIconWidget::on_secondary_released));
|
||||
add_controller(m_secondaryGesture);
|
||||
}
|
||||
|
||||
void TrayIconWidget::update(const TrayService::Item &item)
|
||||
{
|
||||
if (item.iconPaintable)
|
||||
{
|
||||
m_picture.set_paintable(item.iconPaintable);
|
||||
m_picture.set_visible(true);
|
||||
m_image.set_visible(false);
|
||||
}
|
||||
else if (!item.iconName.empty())
|
||||
{
|
||||
m_image.set_from_icon_name(item.iconName);
|
||||
m_image.set_pixel_size(20);
|
||||
m_image.set_visible(true);
|
||||
m_picture.set_visible(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_picture.set_paintable({});
|
||||
m_image.set_visible(false);
|
||||
m_picture.set_visible(false);
|
||||
}
|
||||
|
||||
if (!item.title.empty())
|
||||
{
|
||||
set_tooltip_text(item.title);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_tooltip_text("");
|
||||
}
|
||||
|
||||
set_sensitive(item.status != "Passive");
|
||||
}
|
||||
|
||||
void TrayIconWidget::on_primary_clicked()
|
||||
{
|
||||
m_service.activate(m_id, 0, 0);
|
||||
}
|
||||
|
||||
void TrayIconWidget::on_secondary_released(int /*n_press*/, double /*x*/, double /*y*/)
|
||||
{
|
||||
m_service.contextMenu(m_id, 0, 0);
|
||||
}
|
||||
|
||||
TrayWidget::TrayWidget(TrayService &service)
|
||||
: Gtk::Box(Gtk::Orientation::HORIZONTAL), m_service(service)
|
||||
{
|
||||
set_spacing(6);
|
||||
set_valign(Gtk::Align::CENTER);
|
||||
set_halign(Gtk::Align::CENTER);
|
||||
set_visible(false);
|
||||
|
||||
m_addConnection = m_service.signal_item_added().connect(sigc::mem_fun(*this, &TrayWidget::on_item_added));
|
||||
m_removeConnection = m_service.signal_item_removed().connect(sigc::mem_fun(*this, &TrayWidget::on_item_removed));
|
||||
m_updateConnection = m_service.signal_item_updated().connect(sigc::mem_fun(*this, &TrayWidget::on_item_updated));
|
||||
|
||||
rebuild_existing();
|
||||
}
|
||||
|
||||
TrayWidget::~TrayWidget()
|
||||
{
|
||||
if (m_addConnection.connected())
|
||||
{
|
||||
m_addConnection.disconnect();
|
||||
}
|
||||
if (m_removeConnection.connected())
|
||||
{
|
||||
m_removeConnection.disconnect();
|
||||
}
|
||||
if (m_updateConnection.connected())
|
||||
{
|
||||
m_updateConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void TrayWidget::rebuild_existing()
|
||||
{
|
||||
auto items = m_service.snapshotItems();
|
||||
for (const auto &item : items)
|
||||
{
|
||||
on_item_added(item);
|
||||
}
|
||||
|
||||
set_visible(!m_icons.empty());
|
||||
}
|
||||
|
||||
void TrayWidget::on_item_added(const TrayService::Item &item)
|
||||
{
|
||||
auto it = m_icons.find(item.id);
|
||||
if (it != m_icons.end())
|
||||
{
|
||||
it->second->update(item);
|
||||
return;
|
||||
}
|
||||
|
||||
auto icon = std::make_unique<TrayIconWidget>(m_service, item.id);
|
||||
icon->update(item);
|
||||
auto *raw = icon.get();
|
||||
append(*raw);
|
||||
m_icons.emplace(item.id, std::move(icon));
|
||||
|
||||
set_visible(true);
|
||||
}
|
||||
|
||||
void TrayWidget::on_item_removed(const std::string &id)
|
||||
{
|
||||
auto it = m_icons.find(id);
|
||||
if (it == m_icons.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
remove(*it->second);
|
||||
it->second->unparent();
|
||||
m_icons.erase(it);
|
||||
|
||||
if (m_icons.empty())
|
||||
{
|
||||
set_visible(false);
|
||||
}
|
||||
}
|
||||
|
||||
void TrayWidget::on_item_updated(const TrayService::Item &item)
|
||||
{
|
||||
auto it = m_icons.find(item.id);
|
||||
if (it == m_icons.end())
|
||||
{
|
||||
on_item_added(item);
|
||||
return;
|
||||
}
|
||||
|
||||
it->second->update(item);
|
||||
}
|
||||
Reference in New Issue
Block a user