Added GeoClue2 privacy item

Rebased onto current master and fixed the privacy module build:
- privacy_item.hpp no longer includes privacy.hpp (it does not use the
  Privacy class); this broke the circular include that left PrivacyItem
  undeclared when privacy.hpp was reached first from privacy_item.cpp.
- privacy_item.cpp now includes gtkmm/label.h explicitly, since Gtk::Label
  was previously only pulled in transitively via privacy.hpp.
This commit is contained in:
Erik Reider
2026-07-04 01:42:35 +02:00
committed by Alexays
parent 46e96dfbaa
commit eeb7bc702e
15 changed files with 314 additions and 73 deletions
+88
View File
@@ -0,0 +1,88 @@
#include "util/geoclue_backend.hpp"
#include <giomm/dbuswatchname.h>
#include <string>
namespace waybar::util::GeoClueBackend {
GeoClueBackend::GeoClueBackend(PrivateConstructorTag tag)
: watcherID_(0), signal_conn(), connected(false), location_in_use(false) {
// Start watching DBUS
watcherID_ =
Gio::DBus::watch_name(Gio::DBus::BusType::BUS_TYPE_SYSTEM, "org.freedesktop.GeoClue2",
sigc::mem_fun(*this, &GeoClueBackend::onAppear),
sigc::mem_fun(*this, &GeoClueBackend::onVanished),
Gio::DBus::BusNameWatcherFlags::BUS_NAME_WATCHER_FLAGS_AUTO_START);
}
GeoClueBackend::~GeoClueBackend() {
if (watcherID_ > 0) {
Gio::DBus::unwatch_name(watcherID_);
watcherID_ = 0;
}
signal_conn.disconnect();
}
std::shared_ptr<GeoClueBackend> GeoClueBackend::getInstance() {
PrivateConstructorTag tag;
return std::make_shared<GeoClueBackend>(tag);
}
void GeoClueBackend::propertyChanged(
const Gio::DBus::Proxy::MapChangedProperties& changedProperties,
const std::vector<Glib::ustring>& invalidatedProperties) {
if (!connected) {
return;
}
if (auto in_use_variant = changedProperties.find("InUse");
in_use_variant != changedProperties.end()) {
bool in_use =
Glib::VariantBase::cast_dynamic<Glib::Variant<bool>>(in_use_variant->second).get();
location_in_use.store(in_use);
in_use_changed_signal_event.emit();
}
}
void GeoClueBackend::onAppear(const Glib::RefPtr<Gio::DBus::Connection>& conn,
const Glib::ustring& name, const Glib::ustring& name_owner) {
location_in_use.store(false);
signal_conn.disconnect();
connected = true;
proxy = Gio::DBus::Proxy::create_sync(conn, "org.freedesktop.GeoClue2",
"/org/freedesktop/GeoClue2/Manager",
"org.freedesktop.GeoClue2.Manager");
// Subscribe DBus events
signal_conn = proxy->signal_properties_changed().connect(
sigc::mem_fun(*this, &GeoClueBackend::propertyChanged));
// Get the initial value
auto callArgs = Glib::Variant<std::tuple<Glib::ustring, Glib::ustring>>::create(
std::make_tuple("org.freedesktop.GeoClue2.Manager", "InUse"));
Glib::VariantContainerBase base =
proxy->call_sync("org.freedesktop.DBus.Properties.Get", callArgs);
if (base.is_of_type(Glib::VariantType("(v)"))) {
Glib::Variant<std::tuple<bool>> variant_value;
base.get_child(variant_value, 0);
auto [value] = variant_value.get();
if (location_in_use != value) {
location_in_use.store(value);
}
}
in_use_changed_signal_event.emit();
}
void GeoClueBackend::onVanished(const Glib::RefPtr<Gio::DBus::Connection>& conn,
const Glib::ustring& name) {
signal_conn.disconnect();
connected = false;
location_in_use.store(false);
in_use_changed_signal_event.emit();
}
} // namespace waybar::util::GeoClueBackend
+7 -6
View File
@@ -5,7 +5,7 @@
namespace waybar::util::PipewireBackend {
static void getNodeInfo(void* data_, const struct pw_node_info* info) {
auto* pNodeInfo = static_cast<PrivacyNodeInfo*>(data_);
auto* pNodeInfo = static_cast<PWPrivacyNodeInfo*>(data_);
pNodeInfo->handleNodeEventInfo(info);
static_cast<PipewireBackend*>(pNodeInfo->data)->privacy_nodes_changed_signal_event.emit();
@@ -17,7 +17,7 @@ static const struct pw_node_events NODE_EVENTS = {
};
static void proxyDestroy(void* data) {
static_cast<PrivacyNodeInfo*>(data)->handleProxyEventDestroy();
static_cast<PWPrivacyNodeInfo*>(data)->handleProxyEventDestroy();
}
static const struct pw_proxy_events PROXY_EVENTS = {
@@ -127,12 +127,13 @@ void PipewireBackend::handleRegistryEventGlobal(uint32_t id, uint32_t permission
return;
}
auto* proxy = (pw_proxy*)pw_registry_bind(registry_, id, type, version, sizeof(PrivacyNodeInfo));
auto* proxy =
(pw_proxy*)pw_registry_bind(registry_, id, type, version, sizeof(PWPrivacyNodeInfo));
if (proxy == nullptr) return;
auto* pNodeInfo = (PrivacyNodeInfo*)pw_proxy_get_user_data(proxy);
new (pNodeInfo) PrivacyNodeInfo{};
auto* pNodeInfo = (PWPrivacyNodeInfo*)pw_proxy_get_user_data(proxy);
new (pNodeInfo) PWPrivacyNodeInfo{};
pNodeInfo->id = id;
pNodeInfo->data = this;
pNodeInfo->type = mediaType;
@@ -152,7 +153,7 @@ void PipewireBackend::handleRegistryEventGlobalRemove(uint32_t id) {
mutex_.lock();
auto iter = privacy_nodes.find(id);
if (iter != privacy_nodes.end()) {
privacy_nodes[id]->~PrivacyNodeInfo();
privacy_nodes[id]->~PWPrivacyNodeInfo();
privacy_nodes.erase(id);
}
mutex_.unlock();
+4 -4
View File
@@ -2,7 +2,7 @@
namespace waybar::util::PipewireBackend {
std::string PrivacyNodeInfo::getName() {
std::string PWPrivacyNodeInfo::getName() {
const std::vector<std::string*> names{&application_name, &node_name};
std::string name = "Unknown Application";
for (const auto& item : names) {
@@ -15,7 +15,7 @@ std::string PrivacyNodeInfo::getName() {
return name;
}
std::string PrivacyNodeInfo::getIconName() {
std::string PWPrivacyNodeInfo::getIconName() {
const std::vector<std::string*> names{&application_icon_name, &pipewire_access_portal_app_id,
&application_name, &node_name};
std::string name = "application-x-executable-symbolic";
@@ -27,12 +27,12 @@ std::string PrivacyNodeInfo::getIconName() {
return name;
}
void PrivacyNodeInfo::handleProxyEventDestroy() {
void PWPrivacyNodeInfo::handleProxyEventDestroy() {
spa_hook_remove(&proxy_listener);
spa_hook_remove(&object_listener);
}
void PrivacyNodeInfo::handleNodeEventInfo(const struct pw_node_info* info) {
void PWPrivacyNodeInfo::handleNodeEventInfo(const struct pw_node_info* info) {
state = info->state;
const struct spa_dict_item* item;