fix code style
This commit is contained in:
@@ -1,363 +1,326 @@
|
||||
#include "widgets/tray.hpp"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdkmm/rectangle.h>
|
||||
#include <gio/gmenu.h>
|
||||
#include <utility>
|
||||
#include <gtk/gtk.h>
|
||||
#include <iostream>
|
||||
#include <utility>
|
||||
|
||||
TrayIconWidget::TrayIconWidget(TrayService &service, std::string id)
|
||||
: m_service(service), m_id(std::move(id)), m_container(Gtk::Orientation::HORIZONTAL)
|
||||
{
|
||||
: service(service), id(std::move(id)),
|
||||
container(Gtk::Orientation::HORIZONTAL) {
|
||||
set_has_frame(false);
|
||||
set_focusable(false);
|
||||
set_valign(Gtk::Align::CENTER);
|
||||
set_halign(Gtk::Align::CENTER);
|
||||
|
||||
m_picture.set_halign(Gtk::Align::CENTER);
|
||||
m_picture.set_valign(Gtk::Align::CENTER);
|
||||
m_picture.set_can_shrink(true);
|
||||
m_picture.set_size_request(20, 20);
|
||||
picture.set_halign(Gtk::Align::CENTER);
|
||||
picture.set_valign(Gtk::Align::CENTER);
|
||||
picture.set_can_shrink(true);
|
||||
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);
|
||||
image.set_pixel_size(20);
|
||||
image.set_halign(Gtk::Align::CENTER);
|
||||
image.set_valign(Gtk::Align::CENTER);
|
||||
|
||||
m_container.set_halign(Gtk::Align::CENTER);
|
||||
m_container.set_valign(Gtk::Align::CENTER);
|
||||
m_container.append(m_picture);
|
||||
m_container.append(m_image);
|
||||
container.set_halign(Gtk::Align::CENTER);
|
||||
container.set_valign(Gtk::Align::CENTER);
|
||||
container.append(picture);
|
||||
container.append(image);
|
||||
|
||||
m_picture.set_visible(false);
|
||||
m_image.set_visible(true);
|
||||
set_child(m_container);
|
||||
picture.set_visible(false);
|
||||
image.set_visible(true);
|
||||
set_child(container);
|
||||
|
||||
m_primaryGesture = Gtk::GestureClick::create();
|
||||
m_primaryGesture->set_button(GDK_BUTTON_PRIMARY);
|
||||
m_primaryGesture->signal_released().connect(sigc::mem_fun(*this, &TrayIconWidget::on_primary_released));
|
||||
add_controller(m_primaryGesture);
|
||||
primaryGesture = Gtk::GestureClick::create();
|
||||
primaryGesture->set_button(GDK_BUTTON_PRIMARY);
|
||||
primaryGesture->signal_released().connect(
|
||||
sigc::mem_fun(*this, &TrayIconWidget::on_primary_released));
|
||||
add_controller(primaryGesture);
|
||||
|
||||
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);
|
||||
secondaryGesture = Gtk::GestureClick::create();
|
||||
secondaryGesture->set_button(GDK_BUTTON_SECONDARY);
|
||||
secondaryGesture->signal_released().connect(
|
||||
sigc::mem_fun(*this, &TrayIconWidget::on_secondary_released));
|
||||
add_controller(secondaryGesture);
|
||||
}
|
||||
|
||||
void TrayIconWidget::update(const TrayService::Item &item)
|
||||
{
|
||||
if (!item.menuAvailable)
|
||||
{
|
||||
m_menuModel.reset();
|
||||
m_menuActions.reset();
|
||||
m_menuPopupPending = false;
|
||||
if (m_menuChangedConnection.connected())
|
||||
{
|
||||
m_menuChangedConnection.disconnect();
|
||||
void TrayIconWidget::update(const TrayService::Item &item) {
|
||||
if (!item.menuAvailable) {
|
||||
menuModel.reset();
|
||||
menuActions.reset();
|
||||
menuPopupPending = false;
|
||||
if (menuChangedConnection.connected()) {
|
||||
menuChangedConnection.disconnect();
|
||||
}
|
||||
if (m_menuPopover)
|
||||
{
|
||||
m_menuPopover->insert_action_group("dbusmenu", Glib::RefPtr<Gio::ActionGroup>());
|
||||
m_menuPopover->set_menu_model({});
|
||||
m_menuPopover->unparent();
|
||||
m_menuPopover.reset();
|
||||
if (menuPopover) {
|
||||
menuPopover->insert_action_group("dbusmenu",
|
||||
Glib::RefPtr<Gio::ActionGroup>());
|
||||
menuPopover->set_menu_model({});
|
||||
menuPopover->unparent();
|
||||
menuPopover.reset();
|
||||
}
|
||||
}
|
||||
|
||||
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.iconPaintable) {
|
||||
picture.set_paintable(item.iconPaintable);
|
||||
picture.set_visible(true);
|
||||
image.set_visible(false);
|
||||
} else if (!item.iconName.empty()) {
|
||||
image.set_from_icon_name(item.iconName);
|
||||
image.set_pixel_size(20);
|
||||
image.set_visible(true);
|
||||
picture.set_visible(false);
|
||||
} else {
|
||||
picture.set_paintable({});
|
||||
image.set_visible(false);
|
||||
picture.set_visible(false);
|
||||
}
|
||||
|
||||
if (!item.title.empty())
|
||||
{
|
||||
if (!item.title.empty()) {
|
||||
set_tooltip_text(item.title);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
set_tooltip_text("");
|
||||
}
|
||||
|
||||
set_sensitive(item.status != "Passive");
|
||||
}
|
||||
|
||||
void TrayIconWidget::on_primary_released(int /*n_press*/, double x, double y)
|
||||
{
|
||||
m_service.activate(m_id, -1, -1);
|
||||
void TrayIconWidget::on_primary_released(int /*n_press*/, double x, double y) {
|
||||
service.activate(id, -1, -1);
|
||||
}
|
||||
|
||||
void TrayIconWidget::on_secondary_released(int /*n_press*/, double x, double y)
|
||||
{
|
||||
m_service.contextMenu(m_id, -1, -1);
|
||||
void TrayIconWidget::on_secondary_released(int /*n_press*/, double x,
|
||||
double y) {
|
||||
service.contextMenu(id, -1, -1);
|
||||
|
||||
if (!ensure_menu())
|
||||
{
|
||||
if (!ensure_menu()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_pendingX = x;
|
||||
m_pendingY = y;
|
||||
m_menuPopupPending = true;
|
||||
pendingX = x;
|
||||
pendingY = y;
|
||||
menuPopupPending = true;
|
||||
try_popup();
|
||||
}
|
||||
|
||||
bool TrayIconWidget::ensure_menu()
|
||||
{
|
||||
auto layoutOpt = m_service.get_menu_layout(m_id);
|
||||
if (!layoutOpt)
|
||||
{
|
||||
m_menuModel.reset();
|
||||
m_menuActions.reset();
|
||||
m_menuPopupPending = false;
|
||||
if (m_menuChangedConnection.connected())
|
||||
{
|
||||
m_menuChangedConnection.disconnect();
|
||||
bool TrayIconWidget::ensure_menu() {
|
||||
auto layoutOpt = service.get_menu_layout(id);
|
||||
if (!layoutOpt) {
|
||||
menuModel.reset();
|
||||
menuActions.reset();
|
||||
menuPopupPending = false;
|
||||
if (menuChangedConnection.connected()) {
|
||||
menuChangedConnection.disconnect();
|
||||
}
|
||||
if (m_menuPopover)
|
||||
{
|
||||
if (menuPopover) {
|
||||
remove_action_group("dbusmenu");
|
||||
m_menuPopover->set_menu_model({});
|
||||
m_menuPopover->unparent();
|
||||
m_menuPopover.reset();
|
||||
menuPopover->set_menu_model({});
|
||||
menuPopover->unparent();
|
||||
menuPopover.reset();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const auto &layout = *layoutOpt;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
auto menu = Gio::Menu::create();
|
||||
auto actions = Gio::SimpleActionGroup::create();
|
||||
|
||||
populate_menu_items(layout.children, menu, actions);
|
||||
|
||||
const auto itemCount = menu->get_n_items();
|
||||
std::cout << "[TrayIconWidget] menu update for " << m_id << ", items: " << itemCount << std::endl;
|
||||
if (itemCount == 0)
|
||||
{
|
||||
m_service.debug_dump_menu_layout(m_id);
|
||||
std::cout << "[TrayIconWidget] menu update for " << id
|
||||
<< ", items: " << itemCount << std::endl;
|
||||
if (itemCount == 0) {
|
||||
service.debug_dump_menu_layout(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_menuModel = menu;
|
||||
m_menuActions = actions;
|
||||
menuModel = menu;
|
||||
menuActions = actions;
|
||||
|
||||
if (!m_menuPopover)
|
||||
{
|
||||
if (!menuPopover) {
|
||||
auto *rawPopover = Gtk::make_managed<Gtk::PopoverMenu>();
|
||||
m_menuPopover = Glib::make_refptr_for_instance<Gtk::PopoverMenu>(rawPopover);
|
||||
if (!m_menuPopover)
|
||||
{
|
||||
menuPopover =
|
||||
Glib::make_refptr_for_instance<Gtk::PopoverMenu>(rawPopover);
|
||||
if (!menuPopover) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_menuPopover->set_has_arrow(false);
|
||||
m_menuPopover->set_autohide(true);
|
||||
m_menuPopover->set_parent(*this);
|
||||
menuPopover->set_has_arrow(false);
|
||||
menuPopover->set_autohide(true);
|
||||
menuPopover->set_parent(*this);
|
||||
}
|
||||
|
||||
m_menuPopover->remove_action_group("dbusmenu");
|
||||
m_menuPopover->insert_action_group("dbusmenu", m_menuActions);
|
||||
menuPopover->remove_action_group("dbusmenu");
|
||||
menuPopover->insert_action_group("dbusmenu", menuActions);
|
||||
|
||||
if (m_menuChangedConnection.connected())
|
||||
{
|
||||
m_menuChangedConnection.disconnect();
|
||||
if (menuChangedConnection.connected()) {
|
||||
menuChangedConnection.disconnect();
|
||||
}
|
||||
m_menuChangedConnection = m_menuModel->signal_items_changed().connect(sigc::mem_fun(*this, &TrayIconWidget::on_menu_items_changed));
|
||||
menuChangedConnection = menuModel->signal_items_changed().connect(
|
||||
sigc::mem_fun(*this, &TrayIconWidget::on_menu_items_changed));
|
||||
|
||||
m_menuPopover->set_menu_model(m_menuModel);
|
||||
menuPopover->set_menu_model(menuModel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TrayIconWidget::on_menu_items_changed(guint /*position*/, guint /*removed*/, guint /*added*/)
|
||||
{
|
||||
if (!m_menuModel)
|
||||
{
|
||||
void TrayIconWidget::on_menu_items_changed(guint /*position*/,
|
||||
guint /*removed*/, guint /*added*/) {
|
||||
if (!menuModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto count = m_menuModel->get_n_items();
|
||||
std::cout << "[TrayIconWidget] items changed for " << m_id << ": " << count << " entries" << std::endl;
|
||||
const auto count = menuModel->get_n_items();
|
||||
std::cout << "[TrayIconWidget] items changed for " << id << ": " << count
|
||||
<< " entries" << std::endl;
|
||||
try_popup();
|
||||
}
|
||||
|
||||
void TrayIconWidget::try_popup()
|
||||
{
|
||||
if (!m_menuPopupPending || !m_menuPopover || !m_menuModel)
|
||||
{
|
||||
void TrayIconWidget::try_popup() {
|
||||
if (!menuPopupPending || !menuPopover || !menuModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_menuModel->get_n_items() == 0)
|
||||
{
|
||||
if (menuModel->get_n_items() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gdk::Rectangle rect(static_cast<int>(m_pendingX), static_cast<int>(m_pendingY), 1, 1);
|
||||
m_menuPopover->set_pointing_to(rect);
|
||||
m_menuPopover->popup();
|
||||
m_menuPopupPending = false;
|
||||
Gdk::Rectangle rect(static_cast<int>(pendingX), static_cast<int>(pendingY),
|
||||
1, 1);
|
||||
menuPopover->set_pointing_to(rect);
|
||||
menuPopover->popup();
|
||||
menuPopupPending = false;
|
||||
}
|
||||
|
||||
void TrayIconWidget::populate_menu_items(const std::vector<TrayService::MenuNode> &nodes,
|
||||
const Glib::RefPtr<Gio::Menu> &menu,
|
||||
const Glib::RefPtr<Gio::SimpleActionGroup> &actions)
|
||||
{
|
||||
for (const auto &node : nodes)
|
||||
{
|
||||
if (!node.visible)
|
||||
{
|
||||
void TrayIconWidget::populate_menu_items(
|
||||
const std::vector<TrayService::MenuNode> &nodes,
|
||||
const Glib::RefPtr<Gio::Menu> &menu,
|
||||
const Glib::RefPtr<Gio::SimpleActionGroup> &actions) {
|
||||
for (const auto &node : nodes) {
|
||||
if (!node.visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node.separator)
|
||||
{
|
||||
if (node.separator) {
|
||||
auto section = Gio::Menu::create();
|
||||
menu->append_section("", section);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!node.children.empty())
|
||||
{
|
||||
if (!node.children.empty()) {
|
||||
auto submenu = Gio::Menu::create();
|
||||
populate_menu_items(node.children, submenu, actions);
|
||||
auto submenuItem = Gio::MenuItem::create(node.label, Glib::ustring());
|
||||
auto submenuItem =
|
||||
Gio::MenuItem::create(node.label, Glib::ustring());
|
||||
submenuItem->set_submenu(submenu);
|
||||
if (!node.enabled)
|
||||
{
|
||||
submenuItem->set_attribute_value("enabled", Glib::Variant<bool>::create(false));
|
||||
if (!node.enabled) {
|
||||
submenuItem->set_attribute_value(
|
||||
"enabled", Glib::Variant<bool>::create(false));
|
||||
}
|
||||
menu->append_item(submenuItem);
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string actionName = "item" + std::to_string(node.id);
|
||||
auto menuItem = Gio::MenuItem::create(node.label, "dbusmenu." + actionName);
|
||||
if (!node.enabled)
|
||||
{
|
||||
menuItem->set_attribute_value("enabled", Glib::Variant<bool>::create(false));
|
||||
auto menuItem =
|
||||
Gio::MenuItem::create(node.label, "dbusmenu." + actionName);
|
||||
if (!node.enabled) {
|
||||
menuItem->set_attribute_value("enabled",
|
||||
Glib::Variant<bool>::create(false));
|
||||
}
|
||||
|
||||
auto action = Gio::SimpleAction::create(actionName);
|
||||
action->set_enabled(node.enabled);
|
||||
action->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TrayIconWidget::on_menu_action), node.id));
|
||||
action->signal_activate().connect(sigc::bind(
|
||||
sigc::mem_fun(*this, &TrayIconWidget::on_menu_action), node.id));
|
||||
actions->add_action(action);
|
||||
|
||||
menu->append_item(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
void TrayIconWidget::on_menu_action(const Glib::VariantBase & /*parameter*/, int itemId)
|
||||
{
|
||||
m_service.activate_menu_item(m_id, itemId);
|
||||
if (m_menuPopover)
|
||||
{
|
||||
m_menuPopover->popdown();
|
||||
void TrayIconWidget::on_menu_action(const Glib::VariantBase & /*parameter*/,
|
||||
int itemId) {
|
||||
service.activate_menu_item(id, itemId);
|
||||
if (menuPopover) {
|
||||
menuPopover->popdown();
|
||||
}
|
||||
}
|
||||
|
||||
TrayWidget::TrayWidget(TrayService &service)
|
||||
: Gtk::Box(Gtk::Orientation::HORIZONTAL), m_service(service)
|
||||
{
|
||||
: Gtk::Box(Gtk::Orientation::HORIZONTAL), service(service) {
|
||||
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));
|
||||
addConnection = service.signal_item_added().connect(
|
||||
sigc::mem_fun(*this, &TrayWidget::on_item_added));
|
||||
removeConnection = service.signal_item_removed().connect(
|
||||
sigc::mem_fun(*this, &TrayWidget::on_item_removed));
|
||||
updateConnection = service.signal_item_updated().connect(
|
||||
sigc::mem_fun(*this, &TrayWidget::on_item_updated));
|
||||
|
||||
rebuild_existing();
|
||||
}
|
||||
|
||||
TrayWidget::~TrayWidget()
|
||||
{
|
||||
if (m_addConnection.connected())
|
||||
{
|
||||
m_addConnection.disconnect();
|
||||
TrayWidget::~TrayWidget() {
|
||||
if (addConnection.connected()) {
|
||||
addConnection.disconnect();
|
||||
}
|
||||
if (m_removeConnection.connected())
|
||||
{
|
||||
m_removeConnection.disconnect();
|
||||
if (removeConnection.connected()) {
|
||||
removeConnection.disconnect();
|
||||
}
|
||||
if (m_updateConnection.connected())
|
||||
{
|
||||
m_updateConnection.disconnect();
|
||||
if (updateConnection.connected()) {
|
||||
updateConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void TrayWidget::rebuild_existing()
|
||||
{
|
||||
auto items = m_service.snapshotItems();
|
||||
for (const auto &item : items)
|
||||
{
|
||||
void TrayWidget::rebuild_existing() {
|
||||
auto items = service.snapshotItems();
|
||||
for (const auto &item : items) {
|
||||
on_item_added(item);
|
||||
}
|
||||
|
||||
set_visible(!m_icons.empty());
|
||||
set_visible(!icons.empty());
|
||||
}
|
||||
|
||||
void TrayWidget::on_item_added(const TrayService::Item &item)
|
||||
{
|
||||
auto it = m_icons.find(item.id);
|
||||
if (it != m_icons.end())
|
||||
{
|
||||
void TrayWidget::on_item_added(const TrayService::Item &item) {
|
||||
auto it = icons.find(item.id);
|
||||
if (it != icons.end()) {
|
||||
it->second->update(item);
|
||||
return;
|
||||
}
|
||||
|
||||
auto icon = std::make_unique<TrayIconWidget>(m_service, item.id);
|
||||
auto icon = std::make_unique<TrayIconWidget>(service, item.id);
|
||||
icon->update(item);
|
||||
auto *raw = icon.get();
|
||||
append(*raw);
|
||||
m_icons.emplace(item.id, std::move(icon));
|
||||
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())
|
||||
{
|
||||
void TrayWidget::on_item_removed(const std::string &id) {
|
||||
auto it = icons.find(id);
|
||||
if (it == icons.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove(*it->second);
|
||||
it->second->unparent();
|
||||
m_icons.erase(it);
|
||||
icons.erase(it);
|
||||
|
||||
if (m_icons.empty())
|
||||
{
|
||||
if (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())
|
||||
{
|
||||
void TrayWidget::on_item_updated(const TrayService::Item &item) {
|
||||
auto it = icons.find(item.id);
|
||||
if (it == icons.end()) {
|
||||
on_item_added(item);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user