From 4741de838a447dac8aca8122a1ac7b8c751501aa Mon Sep 17 00:00:00 2001 From: trigg Date: Tue, 3 Feb 2026 01:52:44 +0000 Subject: [PATCH 01/17] util: network manager --- src/panel/widgets/network.cpp | 428 +++------------------------- src/panel/widgets/network.hpp | 75 +---- src/util/meson.build | 6 + src/util/network/bluetooth.hpp | 41 +++ src/util/network/connection.hpp | 73 +++++ src/util/network/manager.cpp | 384 +++++++++++++++++++++++++ src/util/network/manager.hpp | 95 ++++++ src/util/network/modem.hpp | 199 +++++++++++++ src/util/network/network-widget.cpp | 371 ++++++++++++++++++++++++ src/util/network/network-widget.hpp | 65 +++++ src/util/network/network.cpp | 103 +++++++ src/util/network/network.hpp | 50 ++++ src/util/network/null.hpp | 25 ++ src/util/network/vpn.hpp | 21 ++ src/util/network/wifi-ap.cpp | 79 +++++ src/util/network/wifi-ap.hpp | 25 ++ src/util/network/wifi.cpp | 152 ++++++++++ src/util/network/wifi.hpp | 38 +++ src/util/network/wired.cpp | 27 ++ src/util/network/wired.hpp | 12 + 20 files changed, 1813 insertions(+), 456 deletions(-) create mode 100644 src/util/network/bluetooth.hpp create mode 100644 src/util/network/connection.hpp create mode 100644 src/util/network/manager.cpp create mode 100644 src/util/network/manager.hpp create mode 100644 src/util/network/modem.hpp create mode 100644 src/util/network/network-widget.cpp create mode 100644 src/util/network/network-widget.hpp create mode 100644 src/util/network/network.cpp create mode 100644 src/util/network/network.hpp create mode 100644 src/util/network/null.hpp create mode 100644 src/util/network/vpn.hpp create mode 100644 src/util/network/wifi-ap.cpp create mode 100644 src/util/network/wifi-ap.hpp create mode 100644 src/util/network/wifi.cpp create mode 100644 src/util/network/wifi.hpp create mode 100644 src/util/network/wired.cpp create mode 100644 src/util/network/wired.hpp diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 788a6745..ae2ad551 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -1,367 +1,16 @@ #include "network.hpp" +#include "glib.h" +#include "glibmm/main.h" +#include "network/network.hpp" #include #include #include #include +#include -#define NM_DBUS_NAME "org.freedesktop.NetworkManager" -#define ACTIVE_CONNECTION "PrimaryConnection" -#define STRENGTH "Strength" - -std::string WfNetworkConnectionInfo::get_control_center_section(DBusProxy& nm) -{ - Glib::Variant wifi; - nm->get_cached_property(wifi, "WirelessEnabled"); - - return wifi.get() ? "wifi" : "network"; -} - -void WfNetworkConnectionInfo::spawn_control_center(DBusProxy& nm) -{ - std::string command = "env XDG_CURRENT_DESKTOP=GNOME gnome-control-center "; - command += get_control_center_section(nm); - - Glib::spawn_command_line_async(command); -} - -struct NoConnectionInfo : public WfNetworkConnectionInfo -{ - std::string get_icon_name(WfConnectionState state) - { - return "network-offline-symbolic"; - } - - int get_connection_strength() - { - return 0; - } - - std::string get_strength_str() - { - return "none"; - } - - std::string get_ip() - { - return "127.0.0.1"; - } - - virtual ~NoConnectionInfo() - {} -}; - -struct WifiConnectionInfo : public WfNetworkConnectionInfo -{ - WayfireNetworkInfo *widget; - DBusProxy ap; - sigc::connection ap_sig; - - WifiConnectionInfo(const DBusConnection& connection, std::string path, - WayfireNetworkInfo *widget) - { - this->widget = widget; - - ap = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, path, - "org.freedesktop.NetworkManager.AccessPoint"); - - if (ap) - { - ap_sig = ap->signal_properties_changed().connect( - sigc::mem_fun(*this, &WifiConnectionInfo::on_properties_changed)); - } - } - - void on_properties_changed(DBusPropMap changed, DBusPropList invalid) - { - bool needs_refresh = false; - for (auto& prop : changed) - { - if (prop.first == STRENGTH) - { - needs_refresh = true; - } - } - - if (needs_refresh) - { - widget->update_icon(); - widget->update_status(); - } - } - - int get_strength() - { - assert(ap); - - Glib::Variant vstr; - ap->get_cached_property(vstr, STRENGTH); - - return vstr.get(); - } - - std::string get_strength_str() - { - int value = get_strength(); - - if (value > 80) - { - return "excellent"; - } - - if (value > 55) - { - return "good"; - } - - if (value > 30) - { - return "ok"; - } - - if (value > 5) - { - return "weak"; - } - - return "none"; - } - - virtual std::string get_icon_name(WfConnectionState state) - { - if ((state <= CSTATE_ACTIVATING) || (state == CSTATE_DEACTIVATING)) - { - return "network-wireless-acquiring-symbolic"; - } - - if (state == CSTATE_DEACTIVATED) - { - return "network-wireless-disconnected-symbolic"; - } - - if (ap) - { - return "network-wireless-signal-" + get_strength_str() + "-symbolic"; - } else - { - return "network-wireless-no-route-symbolic"; - } - } - - virtual int get_connection_strength() - { - if (ap) - { - return get_strength(); - } else - { - return 100; - } - } - - virtual std::string get_ip() - { - return "0.0.0.0"; - } - - virtual ~WifiConnectionInfo() - {} -}; - -struct EthernetConnectionInfo : public WfNetworkConnectionInfo -{ - DBusProxy ap; - EthernetConnectionInfo(const DBusConnection& connection, std::string path) - {} - - virtual std::string get_icon_name(WfConnectionState state) - { - if ((state <= CSTATE_ACTIVATING) || (state == CSTATE_DEACTIVATING)) - { - return "network-wired-acquiring-symbolic"; - } - - if (state == CSTATE_DEACTIVATED) - { - return "network-wired-disconnected-symbolic"; - } - - return "network-wired-symbolic"; - } - - std::string get_connection_name() - { - return "Ethernet - " + connection_name; - } - - std::string get_strength_str() - { - return "excellent"; - } - - virtual int get_connection_strength() - { - return 100; - } - - virtual std::string get_ip() - { - return "0.0.0.0"; - } - - virtual ~EthernetConnectionInfo() - {} -}; - - -/* TODO: handle Connectivity */ - -static WfConnectionState get_connection_state(DBusProxy connection) -{ - if (!connection) - { - return CSTATE_DEACTIVATED; - } - - Glib::Variant state; - connection->get_cached_property(state, "State"); - return (WfConnectionState)state.get(); -} - -void WayfireNetworkInfo::update_icon() -{ - auto icon_name = info->get_icon_name( - get_connection_state(active_connection_proxy)); - icon.set_from_icon_name(icon_name); -} - -struct status_color +WayfireNetworkInfo::WayfireNetworkInfo() { - int point; - Gdk::RGBA rgba; -} status_colors[] = { - {0, Gdk::RGBA{"#ff0000"}}, - {25, Gdk::RGBA{"#ff0000"}}, - {40, Gdk::RGBA{"#ffff55"}}, - {100, Gdk::RGBA{"#00ff00"}}, -}; - -#define MAX_COLORS (sizeof(status_colors) / sizeof(status_color)) - -void WayfireNetworkInfo::update_status() -{ - std::string description = info->get_connection_name(); - - status.set_text(description); - button.set_tooltip_text(description); - status.remove_css_class("excellent"); - status.remove_css_class("good"); - status.remove_css_class("weak"); - status.remove_css_class("none"); - if (status_color_opt) - { - status.add_css_class(info->get_strength_str()); - } -} - -void WayfireNetworkInfo::update_active_connection() -{ - Glib::Variant active_conn_path; - nm_proxy->get_cached_property(active_conn_path, ACTIVE_CONNECTION); - - if (active_conn_path && (active_conn_path.get() != "/")) - { - active_connection_proxy = Gio::DBus::Proxy::create_sync( - connection, NM_DBUS_NAME, active_conn_path.get(), - "org.freedesktop.NetworkManager.Connection.Active"); - } else - { - active_connection_proxy = DBusProxy(); - } - - auto set_no_connection = [=] () - { - info = std::unique_ptr(new NoConnectionInfo()); - info->connection_name = "No connection"; - }; - - if (!active_connection_proxy) - { - set_no_connection(); - } else - { - Glib::Variant vtype, vobject; - active_connection_proxy->get_cached_property(vtype, "Type"); - active_connection_proxy->get_cached_property(vobject, "SpecificObject"); - auto type = vtype.get(); - auto object = vobject.get(); - - if (type.find("wireless") != type.npos) - { - info = std::unique_ptr( - new WifiConnectionInfo(connection, object, this)); - } else if (type.find("ethernet") != type.npos) - { - info = std::unique_ptr( - new EthernetConnectionInfo(connection, object)); - } else if (type.find("bluetooth")) - { - std::cout << "Unimplemented: bluetooth connection" << std::endl; - set_no_connection(); - // TODO - } else - { - std::cout << "Unimplemented: unknown connection type" << std::endl; - set_no_connection(); - // TODO: implement Unknown connection - } - - Glib::Variant vname; - active_connection_proxy->get_cached_property(vname, "Id"); - info->connection_name = vname.get(); - } - - update_icon(); - update_status(); -} - -void WayfireNetworkInfo::on_nm_properties_changed( - const Gio::DBus::Proxy::MapChangedProperties& properties, - const std::vector& invalidated) -{ - for (auto & prop : properties) - { - if (prop.first == ACTIVE_CONNECTION) - { - update_active_connection(); - } - } -} - -bool WayfireNetworkInfo::setup_dbus() -{ - auto cancellable = Gio::Cancellable::create(); - connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::SYSTEM, cancellable); - if (!connection) - { - std::cerr << "Failed to connect to dbus" << std::endl; - return false; - } - - nm_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, - "/org/freedesktop/NetworkManager", - "org.freedesktop.NetworkManager"); - if (!nm_proxy) - { - std::cerr << "Failed to connect to network manager, " << - "are you sure it is running?" << std::endl; - return false; - } - - signals.push_back(nm_proxy->signal_properties_changed().connect( - sigc::mem_fun(*this, &WayfireNetworkInfo::on_nm_properties_changed))); - - return true; } void WayfireNetworkInfo::on_click() @@ -369,30 +18,22 @@ void WayfireNetworkInfo::on_click() if ((std::string)click_command_opt != "default") { Glib::spawn_command_line_async((std::string)click_command_opt); - } else - { - info->spawn_control_center(nm_proxy); } } void WayfireNetworkInfo::init(Gtk::Box *container) { - if (!setup_dbus()) - { - enabled = false; - return; - } + network_manager = NetworkManager::getInstance(); + button = std::make_unique("panel"); + button->add_css_class("widget-icon"); + button->add_css_class("flat"); + button->add_css_class("network"); - button.add_css_class("widget-icon"); - button.add_css_class("flat"); - button.add_css_class("network"); + container->append(*button); + button->set_child(button_content); + button->add_css_class("flat"); - container->append(button); - button.set_child(button_content); - button.add_css_class("flat"); - - signals.push_back(button.signal_clicked().connect( - sigc::mem_fun(*this, &WayfireNetworkInfo::on_click))); + //button->get_popover()->set_child(control); button_content.set_valign(Gtk::Align::CENTER); button_content.append(icon); @@ -400,34 +41,33 @@ void WayfireNetworkInfo::init(Gtk::Box *container) button_content.set_spacing(6); icon.set_valign(Gtk::Align::CENTER); - signals.push_back(icon.property_scale_factor().signal_changed().connect( - sigc::mem_fun(*this, &WayfireNetworkInfo::update_icon))); - icon.add_css_class("network-icon"); + window_undo_me.set_child(control); + window_undo_me.present(); - update_active_connection(); - handle_config_reload(); + signals.push_back(network_manager->signal_default_changed().connect( + sigc::mem_fun(*this,&WayfireNetworkInfo::set_connection) + )); } -void WayfireNetworkInfo::handle_config_reload() +void WayfireNetworkInfo::set_connection(std::shared_ptr network) { - if (status_opt.value() == NETWORK_STATUS_ICON) + if (network == nullptr) { - if (status.get_parent()) - { - button_content.remove(status); - } - } else + return; + } + status.remove_css_class("none"); + status.remove_css_class("weak"); + status.remove_css_class("bad"); + status.remove_css_class("ok"); + status.remove_css_class("excellent"); + + status.set_label(network->get_name()); + icon.set_from_icon_name(network->get_icon_symbolic()); + auto color = network->get_color_name(); + if (color != "") { - if (!status.get_parent()) - { - button_content.append(status); - } + status.add_css_class(color); } - - // TODO: show IP for "full" status - - update_icon(); - update_status(); } WayfireNetworkInfo::~WayfireNetworkInfo() diff --git a/src/panel/widgets/network.hpp b/src/panel/widgets/network.hpp index e6ab1d90..a79b0765 100644 --- a/src/panel/widgets/network.hpp +++ b/src/panel/widgets/network.hpp @@ -5,82 +5,33 @@ #include #include #include +#include #include +#include "wf-popover.hpp" #include "../widget.hpp" - -using DBusConnection = Glib::RefPtr; -using DBusProxy = Glib::RefPtr; - -using DBusPropMap = const Gio::DBus::Proxy::MapChangedProperties&; -using DBusPropList = const std::vector&; - -enum WfConnectionState // NmActiveConnectionState -{ - CSTATE_UNKNOWN = 0, - CSTATE_ACTIVATING = 1, - CSTATE_ACTIVATED = 2, - CSTATE_DEACTIVATING = 3, - CSTATE_DEACTIVATED = 4, -}; - -struct WfNetworkConnectionInfo -{ - std::string connection_name; - - virtual void spawn_control_center(DBusProxy& nm); - virtual std::string get_control_center_section(DBusProxy& nm); - - virtual std::string get_connection_name() - { - return connection_name; - } - - virtual std::string get_icon_name(WfConnectionState state) = 0; - virtual int get_connection_strength() = 0; - virtual std::string get_ip() = 0; - virtual std::string get_strength_str() = 0; - - virtual ~WfNetworkConnectionInfo() - {} -}; - -static const std::string NETWORK_STATUS_ICON = "none"; -static const std::string NETWORK_STATUS_CONN_NAME = "connection"; -static const std::string NETWORK_STATUS_NAME_IP = "full"; +#include "../../util/network/manager.hpp" +#include "network/network-widget.hpp" class WayfireNetworkInfo : public WayfireWidget { - DBusConnection connection; - DBusProxy nm_proxy, active_connection_proxy; - - std::unique_ptr info; - std::vector signals; - - Gtk::Button button; + std::shared_ptr network_manager; + std::unique_ptr button; Gtk::Box button_content; Gtk::Image icon; Gtk::Label status; - - bool enabled = true; WfOption status_opt{"panel/network_status"}; WfOption status_color_opt{"panel/network_status_use_color"}; WfOption status_font_opt{"panel/network_status_font"}; WfOption click_command_opt{"panel/network_onclick_command"}; - - bool setup_dbus(); - void update_active_connection(); - void on_nm_properties_changed(DBusPropMap properties, - DBusPropList invalidated); - - void on_click(); - + + NetworkControlWidget control; + Gtk::Window window_undo_me; public: - void update_icon(); - void update_status(); - + WayfireNetworkInfo(); + ~WayfireNetworkInfo(); void init(Gtk::Box *container); - void handle_config_reload(); - virtual ~WayfireNetworkInfo(); + void on_click(); + void set_connection(std::shared_ptr network); }; diff --git a/src/util/meson.build b/src/util/meson.build index 5621206e..2f1195c5 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -8,6 +8,12 @@ util = static_library( 'css-config.cpp', 'wf-ipc.cpp', 'animated-scale.cpp', + 'network/manager.cpp', + 'network/wifi.cpp', + 'network/wired.cpp', + 'network/network-widget.cpp', + 'network/wifi-ap.cpp', + 'network/network.cpp', ], dependencies: [wf_protos, gtklayershell, wayland_client, gtkmm, wfconfig, libinotify, json], ) diff --git a/src/util/network/bluetooth.hpp b/src/util/network/bluetooth.hpp new file mode 100644 index 00000000..ad34bc58 --- /dev/null +++ b/src/util/network/bluetooth.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include + +#include "giomm/dbusproxy.h" +#include "network.hpp" +class BluetoothNetwork : public Network +{ + public: + std::shared_ptr bluetooth_proxy; + BluetoothNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr bluetooth_proxy): + Network(path, device_proxy), bluetooth_proxy(bluetooth_proxy) + { + + } + + std::string get_name() override + { + return ""; + } + + std::string get_icon_name() override + { + if(is_active()) + { + return "network-bluetooth-activated"; + } + return "network-bluetooth-inactive"; + } + + std::string get_color_name() override + { + return ""; + } + + std::string get_friendly_name() override + { + return "Bluetooth"; + } +}; \ No newline at end of file diff --git a/src/util/network/connection.hpp b/src/util/network/connection.hpp new file mode 100644 index 00000000..f53a253f --- /dev/null +++ b/src/util/network/connection.hpp @@ -0,0 +1,73 @@ +#pragma once +#include "giomm/dbusproxy.h" +#include "network.hpp" +#include "sigc++/connection.h" +#include +/* Information about an active connection */ +class Connection : public Network { + public: + bool has_vpn; + std::vector signals; + std::shared_ptr connection_proxy, vpn_proxy; + std::vector> devices; + Connection(std::string path, std::shared_ptr connection_proxy, std::vector> devices): + Network(path, nullptr), connection_proxy(connection_proxy), devices(devices) + { + /* Bubble up emits from any device here */ + for(auto &it : devices) + { + signals.push_back(it->signal_network_altered().connect( + [this] () { + network_altered.emit(); + } + )); + } + + Glib::Variant vpn_data; + connection_proxy->get_cached_property(vpn_data, "Vpn"); + has_vpn = vpn_data.get(); + } + + ~Connection() + { + for (auto signal : signals){ + signal.disconnect(); + } + } + + std::string get_name() + { + if (devices.size() ==0) + { + return "No connection"; + } + std::string secure = ""; + if (has_vpn) + { + secure = " with VPN"; + } + return devices[0]->get_name()+secure; + } + + std::string get_icon_name(){ + if (devices.size() == 0) + { + return "network-disconnected"; + } + std::string secure = ""; + if (has_vpn) + { + secure = "-secure"; + } + return devices[0]->get_icon_name()+secure; + } + + std::string get_color_name(){ + if (devices.size() == 0) + { + return "none"; + } + return devices[0]->get_color_name(); + } + +}; \ No newline at end of file diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp new file mode 100644 index 00000000..c4c984fe --- /dev/null +++ b/src/util/network/manager.cpp @@ -0,0 +1,384 @@ +#include +#include +#include +#include +#include + +#include "manager.hpp" +#include "giomm/dbusproxy.h" +#include "glib.h" +#include "glibmm/main.h" +#include "glibmm/ustring.h" +#include "glibmm/variant.h" +#include "network/bluetooth.hpp" +#include "network/connection.hpp" +#include "network/network.hpp" +#include "network/vpn.hpp" +#include "wifi.hpp" +#include "modem.hpp" +#include "wired.hpp" +#include "null.hpp" +#define NM_DBUS_NAME "org.freedesktop.NetworkManager" +#define ACTIVE_CONNECTION "PrimaryConnection" +#define STRENGTH "Strength" + +#define NM_PATH "/org/freedesktop/NetworkManager" + +#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" +#define NM_INTERFACE "org.freedesktop.NetworkManager" + +#define ETHERNET_TYPE 1 +#define WIFI_TYPE 2 +#define MODEM_TYPE 8 +#define GENERIC_TYPE 14 +#define BLUETOOTH_TYPE 5 + +NetworkManager::NetworkManager() +{ + all_devices.emplace("/", new NullNetwork()); + auto cancellable = Gio::Cancellable::create(); + connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::SYSTEM, cancellable); + if (!connection) + { + std::cerr << "Failed to connect to dbus" << std::endl; + return; + } + + /* Get known VPNs */ + settings_proxy = Gio::DBus::Proxy::create_sync(connection, + NM_DBUS_NAME, + "/org/freedesktop/NetworkManager/Settings", + "org.freedesktop.NetworkManager.Settings"); + + auto ret1 = settings_proxy->call_sync("ListConnections").get_child(); + Glib::Variant> ret = Glib::VariantBase::cast_dynamic>>(ret1); + for (auto &it : ret.get()){ + check_add_vpn(it); + vpn_added.emit(it); + } + + settings_proxy->signal_signal().connect( + [this] (const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) { + if (signal == "ConnectionRemoved") + { + auto var = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + all_vpns.erase(var); + vpn_removed.emit(var); + } else if (signal == "NewConnection") + { + auto var = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + check_add_vpn(var); + vpn_added.emit(var); + } + } + ); + + + nm_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, + NM_PATH, + NM_INTERFACE); + if (!nm_proxy) + { + std::cerr << "Failed to connect to network manager, " << + "are you sure it is running?" << std::endl; + return; + } + + signals.push_back(nm_proxy->signal_properties_changed().connect( + sigc::mem_fun(*this, &NetworkManager::on_nm_properties_changed))); + + signals.push_back(nm_proxy->signal_signal().connect( + sigc::mem_fun(*this, &NetworkManager::on_nm_signal))); + + /* Fill Initial List*/ + + nm_proxy->call("GetAllDevices", sigc::mem_fun(*this, &NetworkManager::get_all_devices_cb)); +} + +void NetworkManager::check_add_vpn(std::string path) +{ + auto proxy = Gio::DBus::Proxy::create_sync(connection, + NM_DBUS_NAME, + path, + "org.freedesktop.NetworkManager.Settings.Connection" + ); + + auto values = Glib::VariantBase::cast_dynamic>>>(proxy->call_sync("GetSettings").get_child()); + + auto hash = values.get(); + if (hash.count("connection")==1 && hash["connection"].count("id")==1 && + hash["connection"].count("type")==1) + { + auto contype = hash["connection"]["type"]; + auto conname = hash["connection"]["id"]; + auto strtype = Glib::VariantType("s"); + if (contype.is_of_type(strtype) && conname.is_of_type(strtype)) + { + auto name = Glib::VariantBase::cast_dynamic>(conname).get(); + auto contype_str = Glib::VariantBase::cast_dynamic>(contype).get(); + if(contype_str == "vpn") + { + all_vpns[path] = std::make_shared(path, proxy, name); + } + } else { + std::cerr << "INVALID TYPES "<< conname.get_type_string() << " " << contype.get_type_string()< async) +{ + auto list = Glib::VariantBase::cast_dynamic>> (nm_proxy->call_finish(async).get_child()).get(); + for (auto &val : list) + { + add_network(val); + } + /* Now get the current connection */ + Glib::signal_idle().connect([this] () { + Glib::Variant path_read; + nm_proxy->get_cached_property(path_read, "PrimaryConnection"); + changed_primary(path_read.get()); + return G_SOURCE_REMOVE; + }); +} + +void NetworkManager::add_network(std::string path){ + Glib::RefPtr device_proxy = Gio::DBus::Proxy::create_sync(connection, + NM_DBUS_NAME, + path, + "org.freedesktop.NetworkManager.Device" + ); + Glib::Variant type; + device_proxy->get_cached_property(type, "DeviceType"); + uint connection_type = type.get(); + if (connection_type == WIFI_TYPE) + { + auto wifi_proxy = Gio::DBus::Proxy::create_sync(connection, + NM_DBUS_NAME, + path, + "org.freedesktop.NetworkManager.Device.Wireless"); + all_devices.emplace(path, new WifiNetwork(path, device_proxy, wifi_proxy)); + device_added.emit(all_devices[path]); + } else if (connection_type == MODEM_TYPE) + { + auto modem_proxy = Gio::DBus::Proxy::create_sync(connection, + NM_DBUS_NAME, + path, + "org.freedesktop.NetworkManager.Device.Modem"); + all_devices.emplace(path, new ModemNetwork(path, device_proxy, modem_proxy)); + device_added.emit(all_devices[path]); + } else if (connection_type == BLUETOOTH_TYPE) + { + auto bluetooth_proxy =Gio::DBus::Proxy::create_sync(connection, + NM_DBUS_NAME, + path, + "org.freedesktop.NetworkManager.Devices.Bluetooth"); + all_devices.emplace(path, new BluetoothNetwork(path, device_proxy, bluetooth_proxy)); + device_added.emit(all_devices[path]); + } else if (connection_type == ETHERNET_TYPE) + { + all_devices.emplace(path, new WiredNetwork(path, device_proxy)); + device_added.emit(all_devices[path]); + } +} + +void NetworkManager::on_nm_properties_changed(const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) +{ + for (auto &it : properties) + { + if (it.first == "PrimaryConnection") + { + auto value = Glib::VariantBase::cast_dynamic>(it.second).get(); + changed_primary(value); + } else if (it.first == "NetworkingEnabled" || it.first == "WirelessEnabled" || it.first == "WirelessHardwareEnabled" || + it.first == "WwanEnabled" || it.first == "WwanHardwareEnabled") + { + global_change.emit(); + } + } +} + +void NetworkManager::changed_primary(std::string value) +{ + if (value != primary_connection) + { + if (primary_signal) + { + primary_signal.disconnect(); + } + primary_connection = value; + auto network = get_connection(value); + primary_connection_obj = network; + + /* Any change inside the primary connection also called default_changed */ + primary_signal = network->signal_network_altered().connect( + [this, network] () { + default_changed.emit(network); + } + ); + /* Tell clients */ + default_changed.emit(network); + + } +} + + +std::shared_ptr NetworkManager::get_connection(std::string path) +{ + auto connection_proxy = Gio::DBus::Proxy::create_sync(connection, + NM_DBUS_NAME, + path, + "org.freedesktop.NetworkManager.Connection.Active" + ); + + std::vector> list; + Glib::Variant> paths; + connection_proxy->get_cached_property(paths, "Devices"); + if (paths) + { + for (auto &it : paths.get()) + { + list.push_back(all_devices[it]); + } + } + return std::make_shared(path, connection_proxy, list); +} + +void NetworkManager::on_nm_signal(const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) +{ + if (signal == "DeviceAdded") + { + auto val = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + add_network(val); + } else if (signal == "DeviceRemoved") + { + auto val = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + all_devices.erase(val); + } else + { + return; + } + /* NM list changed, but let's not send instantly */ + if (debounce) + { + debounce.disconnect(); + } + debounce = Glib::signal_timeout().connect([this] () { + signal_device_list_changed().emit(all_devices); + return G_SOURCE_REMOVE; + }, 100); +} + +std::shared_ptr NetworkManager::get_primary_network() +{ + return primary_connection_obj; +} + +void NetworkManager::activate_connection(std::string p1, std::string p2, std::string p3) +{ + auto manager = NetworkManager::getInstance()->get_nm_proxy(); + Glib::VariantStringBase path1,path2,path3; + Glib::VariantStringBase::create_object_path(path1, p1); + Glib::VariantStringBase::create_object_path(path2, p2); + Glib::VariantStringBase::create_object_path(path3, p3); + auto paths = Glib::VariantContainerBase::create_tuple({path1, path2, path3}); + //auto data = Glib::VariantContainerBase::create_tuple(paths); + + try { + manager->call_sync("ActivateConnection", paths); + } catch (...) + { + /* Most likely no password*/ + /* TODO */ + } +} + +void NetworkManager::deactivate_connection(std::string p1) +{ + auto manager = NetworkManager::getInstance()->get_nm_proxy(); + Glib::VariantStringBase path1; + Glib::VariantStringBase::create_object_path(path1, p1); + auto paths = Glib::VariantContainerBase::create_tuple({path1}); + //auto data = Glib::VariantContainerBase::create_tuple(paths); + + try { + manager->call_sync("DeactivateConnection", paths); + } catch (...) + { + /* Most likely no password*/ + /* TODO */ + } +} + +/* Is Wifi Enabled, in software and in rfkill */ +std::tuple NetworkManager::wifi_global_enabled() +{ + Glib::Variant wifisoft, wifihard; + nm_proxy->get_cached_property(wifisoft, "WirelessEnabled"); + nm_proxy->get_cached_property(wifihard, "WirelessHardwareEnabled"); + return {wifisoft.get(), wifihard.get()}; +} +/* Is Mobile Data Enabled, in software and in rfkill */ +std::tuple NetworkManager::mobile_global_enabled() +{ + Glib::Variant modemsoft, modemhard; + nm_proxy->get_cached_property(modemsoft, "WwanEnabled"); + nm_proxy->get_cached_property(modemhard, "WwanHardwareEnabled"); + return {modemsoft.get(), modemhard.get()}; +} +/* Is Networking enabled */ +bool NetworkManager::networking_global_enabled() +{ + Glib::Variant enabled; + nm_proxy->get_cached_property(enabled, "NetworkingEnabled"); + return enabled.get(); +} + +void NetworkManager::wifi_global_set(bool value) +{ + auto another_proxy = Gio::DBus::Proxy::create_sync(nm_proxy->get_connection(), + NM_DBUS_NAME, + NM_PATH, + DBUS_PROPERTIES_INTERFACE + ); + + auto params = Glib::VariantContainerBase::create_tuple( + { + Glib::Variant::create(NM_INTERFACE), + Glib::Variant::create("WirelessEnabled"), + Glib::Variant::create(Glib::Variant::create(value)) + } + ); + another_proxy->call_sync("Set", params); +} + +void NetworkManager::mobile_global_set(bool value) +{ + auto another_proxy = Gio::DBus::Proxy::create_sync(nm_proxy->get_connection(), + NM_DBUS_NAME, + NM_PATH, + DBUS_PROPERTIES_INTERFACE + ); + + auto params = Glib::VariantContainerBase::create_tuple( + { + Glib::Variant::create(NM_INTERFACE), + Glib::Variant::create("WwanEnabled"), + + Glib::Variant::create(Glib::Variant::create(value)) + } + ); + another_proxy->call_sync("Set", params); +} +void NetworkManager::networking_global_set(bool value) +{ + auto params = Glib::VariantContainerBase::create_tuple(Glib::Variant::create(value)); + nm_proxy->call_sync("Enable", params); +} + +NetworkManager::~NetworkManager() +{ + +} \ No newline at end of file diff --git a/src/util/network/manager.hpp b/src/util/network/manager.hpp new file mode 100644 index 00000000..6ba08dba --- /dev/null +++ b/src/util/network/manager.hpp @@ -0,0 +1,95 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "giomm/dbusconnection.h" +#include "giomm/dbusproxy.h" +#include "network.hpp" +#include "connection.hpp" +#include "sigc++/connection.h" +#include "vpn.hpp" + +using type_signal_network = sigc::signal)>; +using type_signal_device_list_changed = sigc::signal>)>; +using type_signal_simple = sigc::signal; +using type_signal_path = sigc::signal; + +class NetworkManager +{ + private: + type_signal_network default_changed, device_added, device_removed; + type_signal_device_list_changed device_list_changed; + type_signal_simple global_change; + type_signal_path vpn_added, vpn_removed; + + + Glib::RefPtr connection; + Glib::RefPtr nm_proxy, settings_proxy; + + std::vector signals; + sigc::connection debounce, primary_signal; + + std::string primary_connection = ""; + + std::shared_ptr primary_connection_obj; + + std::map> all_devices; + std::map> all_vpns; + + void on_nm_properties_changed(const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated); + void on_nm_signal(const Glib::ustring&, const Glib::ustring&, const Glib::VariantContainerBase&); + void get_all_devices_cb(std::shared_ptr); + void add_network(std::string path); + void check_add_vpn(std::string path); + void changed_primary(std::string path); + + + public: + /* Emitted when the default connection or it's properties change */ + type_signal_network signal_default_changed() { return default_changed; } + /* Emitted when any network device is connected or disconnected */ + type_signal_device_list_changed signal_device_list_changed() { return device_list_changed; } + /* Emitted when a networking device is added */ + type_signal_network signal_device_added() { return device_added; } + /* Emitted when a networking device is removed */ + type_signal_network signal_device_removed() { return device_removed; } + /* Emitted when any of the global enable toggles is changed */ + type_signal_simple signal_global_toggle() { return global_change; } + type_signal_path signal_vpn_added() { return vpn_added; } + type_signal_path signal_vpn_removed() { return vpn_removed; } + std::shared_ptr get_nm_proxy() { return nm_proxy; } + /* A list of current networks. */ + + std::map> get_all_vpns() {return all_vpns; } + std::map> get_all_devices() { return all_devices; } + + /* TODO Consider allowing this to lose last reference */ + static std::shared_ptr getInstance() + { + static std::shared_ptr instance; + if (!instance) + { + instance = std::make_shared(); + } + return instance; + } + NetworkManager(); + ~NetworkManager(); + + std::shared_ptr get_primary_network(); + std::shared_ptr get_connection(std::string path); + void activate_connection(std::string connection_path, std::string device_path, std::string details_path); + void deactivate_connection(std::string connection_path); + + + std::tuple wifi_global_enabled(); + std::tuple mobile_global_enabled(); + bool networking_global_enabled(); + + void wifi_global_set(bool value); + void mobile_global_set(bool value); + void networking_global_set(bool value); +}; \ No newline at end of file diff --git a/src/util/network/modem.hpp b/src/util/network/modem.hpp new file mode 100644 index 00000000..4b1b97fc --- /dev/null +++ b/src/util/network/modem.hpp @@ -0,0 +1,199 @@ +#pragma once +#include "giomm/dbusproxy.h" +#include "glibmm/variant.h" +#include "network.hpp" +#include +#include + +#define CAP_5G 16 +#define CAP_4G 8 +#define CAP_3G 4 +#define CAP_2G 2 +#define CAP_CS 1 + +class ModemNetwork : public Network { + public: + unsigned char strength=0; + int caps = 8; + std::shared_ptr modem_proxy; + std::shared_ptr mm_proxy; + ModemNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr modem_proxy): + Network(path, device_proxy), modem_proxy(modem_proxy) + { + Glib::Variant device_data; + modem_proxy->get_cached_property(device_data, "DeviceId"); + + find_mm_proxy(device_data.get()); + } + + void find_mm_proxy(std::string dev_id) + { + auto mm_om_proxy = Gio::DBus::Proxy::create_sync(modem_proxy->get_connection(), + "org.freedesktop.ModemManager1", + "/org/freedesktop/ModemManager1", + "org.freedesktop.DBus.ObjectManager"); + + auto ret1 = mm_om_proxy->call_sync("GetManagedObjects").get_child(); + auto ret = Glib::VariantBase::cast_dynamic>>>>(ret1); + + for (auto &it : ret.get()) + { + std::string modem_path = it.first; + for (auto &next : it.second) + { + if (next.first == "org.freedesktop.ModemManager1.Modem") + { + for (auto &why : next.second) + { + if (why.first == "DeviceIdentifier") + { + auto devid = Glib::VariantBase::cast_dynamic>(why.second); + if (devid.get() == dev_id) + { + + mm_proxy = Gio::DBus::Proxy::create_sync(device_proxy->get_connection(), + "org.freedesktop.ModemManager1", + modem_path, + "org.freedeskop.ModemManager1.Modem"); + } + } + } + } + } + } + if (mm_proxy) + { + mm_proxy->signal_properties_changed().connect( + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { + for (auto &it : properties) + { + if (it.first == "SignalQuality") + { + auto container = Glib::VariantBase::cast_dynamic(it.second); + Glib::Variant signal_data; + container.get_child(signal_data,0); + // "(ub)" => percent 0-100, 'is recent' + strength = signal_data.get(); + + } + if (it.first == "CurrentModes") + { + auto container = Glib::VariantBase::cast_dynamic(it.second); + Glib::Variant mode_data; + container.get_child(mode_data,1); + caps = mode_data.get(); + } + } + }); + } else + { + std::cerr << "Could not get extra modem details" << std::endl; + } + + } + + ~ModemNetwork() + { + + } + + std::string strength_string() + { + if (strength >= 80) + { + return "excellent"; + } + + if (strength >= 55) + { + return "good"; + } + + if (strength >= 30) + { + return "ok"; + } + + if (strength >= 5) + { + return "weak"; + } + + return "none"; + } + + std::string get_name() + { + if (!mm_proxy) + { + return "Misconfigured Mobile"; + } + /* TODO Get Carrier from MM */ + return "Mobile"; + } + + std::string get_signal_band() + { + if (strength == 100) + { + return "100"; + } else if (strength >= 80) + { + return "80"; + } else if (strength >= 60) + { + return "60"; + } else if (strength >= 40) + { + return "40"; + } else if (strength >= 20) + { + return "20"; + } + return "0"; + } + + std::string get_connection_type_string() + { + if (caps & CAP_5G) + { + return "5g"; + } else if (caps & CAP_4G) + { + return "lte"; + } else if (caps & CAP_3G) + { + return "hspa"; + } else if (caps & CAP_2G) + { + return "gprs"; + } else if (caps & CAP_CS) + { + return "edge"; + } + return "edge"; + } + + std::string get_icon_name() + { + if (!mm_proxy) + { + return "network-mobile-off"; + } + if (!is_active()) + { + return "network-mobile-off"; + } + return "network-mobile-"+get_signal_band()+"-"+get_connection_type_string(); + } + + std::string get_color_name() + { + return strength_string(); + } + + std::string get_friendly_name() + { + return "Mobile Data"; + } +}; \ No newline at end of file diff --git a/src/util/network/network-widget.cpp b/src/util/network/network-widget.cpp new file mode 100644 index 00000000..ae2c8b9b --- /dev/null +++ b/src/util/network/network-widget.cpp @@ -0,0 +1,371 @@ +#include "network-widget.hpp" +#include "gtkmm/enums.h" +#include "gtkmm/gestureclick.h" +#include "network/bluetooth.hpp" +#include "network/manager.hpp" +#include "network/modem.hpp" +#include "network/network.hpp" +#include "network/vpn.hpp" +#include "network/wifi-ap.hpp" +#include "network/wifi.hpp" +#include "network/wired.hpp" +#include "sigc++/functors/mem_fun.h" +#include + +AccessPointWidget::AccessPointWidget(std::string path_in, std::shared_ptr ap_in): + ap(ap_in),path(path_in) +{ + add_css_class("access-point"); + append(image); + append(label); + + auto update_ap = [this] () { + label.set_label(ap->get_ssid()); + image.set_from_icon_name(ap->get_icon_name()); + }; + signal = ap_in->signal_altered().connect(update_ap); + update_ap(); +} + +AccessPointWidget::~AccessPointWidget() +{ + signal.disconnect(); +} + +VPNControlWidget::VPNControlWidget(std::shared_ptr config): + config(config) +{ + append(image); + append(label); + label.set_label(config->name); + image.set_from_icon_name("network-vpn-symbolic"); +} + +DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): + network(network) +{ + + add_css_class("device"); + set_halign(Gtk::Align::FILL); + set_orientation(Gtk::Orientation::VERTICAL); + append(topbox); + append(revealer); + topbox.append(image); + topbox.append(label); + revealer.set_child(revealer_box); + revealer_box.set_orientation(Gtk::Orientation::VERTICAL); + auto wifi = std::dynamic_pointer_cast(network); + auto mobile = std::dynamic_pointer_cast(network); + auto wired = std::dynamic_pointer_cast(network); + auto bt = std::dynamic_pointer_cast(network); + if(wifi) + { + type="wifi"; + /* TODO Sort*/ + for (auto &it : wifi->get_access_points()) + { + add_access_point(it.second); + } + + wifi->signal_add_access_point().connect( + [this] (std::shared_ptr ap) { + add_access_point(ap); + } + ); + + wifi->signal_remove_access_point().connect( + [this] (std::shared_ptr ap) { + remove_access_point(ap->get_path()); + } + ); + + auto wifi_cb = + [this, wifi] () { + if (wifi->get_current_access_point_path() == "/") + { + revealer.set_reveal_child(true); + topbox.hide(); + } else + { + revealer.set_reveal_child(false); + topbox.show(); + } + }; + network->signal_network_altered().connect(wifi_cb); + wifi_cb(); + } else if (wired) + { + type="wired"; + revealer.hide(); + } else if (bt) + { + type="bt"; + revealer.hide(); + } else if (mobile) + { + type="mobile"; + revealer.hide(); + } else + { + type="broken"; + revealer.hide(); + } + + /* Click toggles connection on/off */ + auto click = Gtk::GestureClick::create(); + click->signal_released().connect( + [network] (int, double, double) { + network->toggle(); + } + ); + label.add_controller(click); + + /* Set label and image based on friendly info */ + auto network_change_cb = [this, network] () { + image.set_from_icon_name(network->get_icon_symbolic()); + label.set_label(network->get_name()); + if (network->is_active()) + { + label.add_css_class("active"); + } else + { + label.remove_css_class("active"); + } + }; + network->signal_network_altered().connect(network_change_cb); + network_change_cb(); + +} + +void DeviceControlWidget::remove_access_point(std::string path){ + auto widget = access_points[path]; + if (widget) + { + revealer_box.remove(*widget); + access_points.erase(path); + } +} + +void DeviceControlWidget::add_access_point(std::shared_ptr ap) +{ + if (!ap || ap->get_ssid()=="") + { + return; + } + auto path = ap->get_path(); + if (path == "/") + { + return; + } + access_points.emplace(path, new AccessPointWidget(path, ap)); + auto widget = access_points[path]; + auto click = Gtk::GestureClick::create(); + + click->signal_released().connect( + [this, path] (int, double, double) { + selected_access_point(path); + } + ); + widget->add_controller(click); + revealer_box.append(*access_points[path]); +} + +void DeviceControlWidget::selected_access_point(std::string path) +{ + auto wifi = std::dynamic_pointer_cast(network); + if (!wifi) + { + std::cerr << "Cannot select AP on non-wifi device" << std::endl; + } + if (path == "/") + { + return; + } + if (wifi->get_current_access_point_path() == path) + { + wifi->disconnect(); + } else + { + wifi->connect(path); + } +} + +NetworkControlWidget::NetworkControlWidget() +{ + add_css_class("network-control-center"); + set_orientation(Gtk::Orientation::VERTICAL); + network_manager = NetworkManager::getInstance(); + + network_manager->signal_device_added().connect( + sigc::mem_fun(*this, &NetworkControlWidget::add_device) + ); + + network_manager->signal_device_removed().connect( + sigc::mem_fun(*this, &NetworkControlWidget::remove_device) + ); + + /* Fill already existing devices */ + + for (auto &device : network_manager->get_all_devices()) + { + add_device(device.second); + } + top.append(global_networking); + top.append(wifi_networking); + top.append(mobile_networking); + append(top); + append(wire_box); + append(mobile_box); + append(wifi_box); + append(bt_box); + append(vpn_box); + + mobile_networking.set_halign(Gtk::Align::END); + wifi_networking.set_halign(Gtk::Align::END); + + global_networking.set_label("Networking"); + wifi_networking.set_label("Wifi"); + mobile_networking.set_label("Mobile"); + + signal_network = global_networking.signal_toggled().connect( + [this] () { + network_manager->networking_global_set(global_networking.get_active()); + } + ); + + signal_wifi = wifi_networking.signal_toggled().connect( + [this] () { + network_manager->wifi_global_set(wifi_networking.get_active()); + } + ); + + signal_mobile = mobile_networking.signal_toggled().connect( + [this] () { + network_manager->mobile_global_set(mobile_networking.get_active()); + } + ); + + /* Global killswitches from NM proper */ + auto global_cb = + [this] () { + auto [wifi_soft, wifi_hard] = network_manager->wifi_global_enabled(); + auto [mobile_soft, mobile_hard] = network_manager->mobile_global_enabled(); + auto global = network_manager->networking_global_enabled(); + if (!wifi_hard) + { + wifi_networking.set_label("Wifi ✈"); + signal_wifi.block(true); + wifi_networking.set_active(false); + signal_wifi.unblock(); + } else if(!wifi_soft) + { + wifi_networking.set_label("Wifi"); + signal_wifi.block(true); + wifi_networking.set_active(false); + signal_wifi.unblock(); + } else { + wifi_networking.set_label("Wifi"); + signal_wifi.block(true); + wifi_networking.set_active(true); + signal_wifi.unblock(); + } + if(!mobile_hard) + { + mobile_networking.set_label("Mobile ✈"); + signal_mobile.block(true); + mobile_networking.set_active(false); + signal_mobile.unblock(); + } else if(!mobile_soft) + { + mobile_networking.set_label("Mobile"); + signal_mobile.block(true); + mobile_networking.set_active(false); + signal_mobile.unblock(); + } else { + mobile_networking.set_label("Mobile"); + signal_mobile.block(true); + mobile_networking.set_active(true); + signal_mobile.unblock(); + } + signal_network.block(true); + global_networking.set_active(global); + signal_network.unblock(); + }; + + network_manager->signal_global_toggle().connect(global_cb); + global_cb(); + + for (auto &it : network_manager->get_all_vpns()) + { + add_vpn(it.second); + } + +} + +void NetworkControlWidget::add_vpn(std::shared_ptr config) +{ + auto widget = std::make_shared(config); + vpn_widgets.emplace(config->path, widget); + + auto click = Gtk::GestureClick::create(); + click->signal_released().connect( + [this, config] (int, double, double) { + auto primary = network_manager->get_primary_network(); + if (primary->has_vpn) + { + network_manager->deactivate_connection(primary->get_path()); + } else { + network_manager->activate_connection(config->path, "/", "/"); + } + } + ); + widget->add_controller(click); + vpn_box.append(*widget); +} + +void NetworkControlWidget::remove_vpn(std::string path) +{ + auto widget = vpn_widgets[path]; + vpn_box.remove(*widget); + vpn_widgets.erase(path); +} + +void NetworkControlWidget::add_device(std::shared_ptr network) +{ + /* GUI doesn't want our null-device */ + if (network->get_path() == "/") + { + return; + } + auto new_controller = std::make_shared(network); + widgets.emplace(network->get_path(), new_controller); + auto widget = widgets[network->get_path()]; + if (widget->type == "wifi") + { + wifi_box.append(*widget); + } else if (widget->type == "mobile") + { + mobile_box.append(*widget); + } else if (widget->type == "wired") + { + wire_box.append(*widget); + } else if (widget->type == "bt") + { + bt_box.append(*widget); + } else { + std::cout << "Unknown network type : " << widget->type << std::endl; + } + +} + +void NetworkControlWidget::remove_device(std::shared_ptr network) +{ + auto widget = widgets[network->get_path()]; + /* TODO Remove warnings by checking? */ + wifi_box.remove(*widget); + mobile_box.remove(*widget); + wire_box.remove(*widget); + vpn_box.remove(*widget); + bt_box.remove(*widget); + widgets.erase(network->get_path()); +} \ No newline at end of file diff --git a/src/util/network/network-widget.hpp b/src/util/network/network-widget.hpp new file mode 100644 index 00000000..d7a8e708 --- /dev/null +++ b/src/util/network/network-widget.hpp @@ -0,0 +1,65 @@ +#pragma once +#include +#include +#include "gtkmm.h" +#include "network/vpn.hpp" +#include "sigc++/connection.h" +#include "manager.hpp" +#include "wifi.hpp" + +class AccessPointWidget : public Gtk::Box +{ + private: + Gtk::Image image; + Gtk::Label label; + std::shared_ptr ap; + std::string path; + sigc::connection signal; + public: + AccessPointWidget(std::string path, std::shared_ptr ap); + ~AccessPointWidget(); +}; + +class DeviceControlWidget : public Gtk::Box +{ + private: + std::map> access_points; + std::shared_ptr network; + Gtk::Label label; + Gtk::Image image; + Gtk::Revealer revealer; + Gtk::Box revealer_box, topbox; + public: + DeviceControlWidget(std::shared_ptr network); + void add_access_point(std::shared_ptr ap); + void remove_access_point(std::string path); + void selected_access_point(std::string path); + std::string type; + +}; + +class VPNControlWidget : public Gtk::Box +{ + private: + std::shared_ptr config; + Gtk::Image image; + Gtk::Label label; + public: + VPNControlWidget(std::shared_ptr config); +}; + +class NetworkControlWidget : public Gtk::Box +{ + Gtk::Box wire_box, wifi_box, mobile_box, vpn_box, bt_box, top; + Gtk::CheckButton global_networking, wifi_networking, mobile_networking; + std::map > widgets; + std::map > vpn_widgets; + sigc::connection signal_network, signal_wifi, signal_mobile; + public: + NetworkControlWidget(); + std::shared_ptr network_manager; + void add_device(std::shared_ptr network); + void remove_device(std::shared_ptr network); + void add_vpn(std::shared_ptr config); + void remove_vpn(std::string path); +}; \ No newline at end of file diff --git a/src/util/network/network.cpp b/src/util/network/network.cpp new file mode 100644 index 00000000..b17db0be --- /dev/null +++ b/src/util/network/network.cpp @@ -0,0 +1,103 @@ +#include "network.hpp" +#include "manager.hpp" +type_signal_network_altered Network::signal_network_altered() { return network_altered; } + +Network::Network(std::string path, std::shared_ptr in_proxy): + network_path(path), device_proxy(in_proxy) +{ + /* Allow for nullnetwork and pseudo networks */ + if (in_proxy == nullptr) + { + return; + } + Glib::Variant val; + device_proxy->get_cached_property(val, "Interface"); + if(val.get().length() > 0) + { + interface = val.get(); + } + /* Any change of state */ + device_proxy->signal_signal().connect( + [this] (const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) { + if (signal == "StateChanged") + { + if (container.is_of_type(Glib::VariantType("(uuu)"))) + { + auto value = container.get_child(0); + auto value2= Glib::VariantBase::cast_dynamic>(value).get(); + last_state = value2; + network_altered.emit(); + } + } + }); + + device_proxy->signal_properties_changed().connect( + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { + for (auto &it : properties) + { + if (it.first == "ActiveConnection") + { + network_altered.emit(); + } + } + } + ); +} + +Network::~Network() +{ + +} + +std::string Network::get_friendly_name() +{ + return "Unknown Device"; +} + +std::string Network::get_interface() +{ + if (!device_proxy){ + return "/dev/null"; + } + Glib::Variant iface; + device_proxy->get_cached_property(iface, "Interface"); + return iface.get(); +} + +bool Network::show_spinner() +{ + return last_state == NM_DEVICE_STATE_PREPARE || + last_state == NM_DEVICE_STATE_CONFIG; + } + +std::string Network::get_path() +{ + return network_path; +} + +void Network::connect(std::string path) +{ + NetworkManager::getInstance()->activate_connection("/", network_path, path); +} +void Network::toggle() +{ + if (is_active()) + { + disconnect(); + + } else + { + connect("/"); + } +} +void Network::disconnect() +{ + device_proxy->call_sync("Disconnect"); +} + +bool Network::is_active() +{ + Glib::Variant val; + device_proxy->get_cached_property(val, "ActiveConnection"); + return val.get() != "/"; +} \ No newline at end of file diff --git a/src/util/network/network.hpp b/src/util/network/network.hpp new file mode 100644 index 00000000..b3d5c95f --- /dev/null +++ b/src/util/network/network.hpp @@ -0,0 +1,50 @@ +#pragma once +#include "glibmm/ustring.h" +#include "glibmm/variant.h" +#include +#include +#include +#include +#include +#define NM_DEVICE_STATE_UNKNOWN 0 +#define NM_DEVICE_STATE_UNMANAGED 10 +#define NM_DEVICE_STATE_UNAVAILABLE 20 +#define NM_DEVICE_STATE_DISCONNECTED 30 +#define NM_DEVICE_STATE_PREPARE 40 +#define NM_DEVICE_STATE_CONFIG 50 +#define NM_DEVICE_STATE_NEED_AUTH 60 +#define NM_DEVICE_STATE_IP_CONFIG 70 +#define NM_DEVICE_STATE_IP_CHECK 80 +#define NM_DEVICE_STATE_SECONDARIES 90 +#define NM_DEVICE_STATE_ACTIVATED 100 +#define NM_DEVICE_STATE_DEACTIVATING 110 +#define NM_DEVICE_STATE_FAILED 120 + +using type_signal_network_altered = sigc::signal; + +class Network { + protected: + type_signal_network_altered network_altered; + std::string network_path; + public: + type_signal_network_altered signal_network_altered(); + std::shared_ptr device_proxy; + std::string interface=""; + int last_state = 0; + virtual std::string get_name() = 0; + virtual std::string get_color_name() = 0; + Network(std::string path, std::shared_ptr in_proxy); + ~Network(); + virtual std::string get_friendly_name(); + virtual std::string get_interface(); + bool show_spinner(); + virtual std::string get_icon_name() = 0; + std::string get_icon_symbolic() { return get_icon_name() + "-symbolic"; }; + std::string get_path(); + void disconnect(); + void connect(std::string path_extra); + void toggle(); + bool is_active(); + Network(const Network &) = delete; + Network &operator = (const Network &) = delete; +}; \ No newline at end of file diff --git a/src/util/network/null.hpp b/src/util/network/null.hpp new file mode 100644 index 00000000..ef555b27 --- /dev/null +++ b/src/util/network/null.hpp @@ -0,0 +1,25 @@ +#pragma once +#include "network.hpp" + +class NullNetwork : public Network { + public: + NullNetwork():Network("/", nullptr) + { + + } + + std::string get_name() override + { + return "No connection"; + } + + std::string get_icon_name() override + { + return "network-offline"; + } + + std::string get_color_name() override + { + return "none"; + } +}; \ No newline at end of file diff --git a/src/util/network/vpn.hpp b/src/util/network/vpn.hpp new file mode 100644 index 00000000..d677a6f4 --- /dev/null +++ b/src/util/network/vpn.hpp @@ -0,0 +1,21 @@ +#pragma once +#include "giomm/dbusproxy.h" +#include "glibmm/variant.h" +#include "network.hpp" +#include + +class VpnConfig { + private: + std::shared_ptr vpn_proxy; + public: + std::string name; + std::string path; + + VpnConfig(std::string path, std::shared_ptr vpn_proxy, std::string name): + vpn_proxy(vpn_proxy), name(name),path(path) + { + + } + + +}; \ No newline at end of file diff --git a/src/util/network/wifi-ap.cpp b/src/util/network/wifi-ap.cpp new file mode 100644 index 00000000..37ec25a4 --- /dev/null +++ b/src/util/network/wifi-ap.cpp @@ -0,0 +1,79 @@ +#include "wifi-ap.hpp" +#include "network/network.hpp" +std::string AccessPoint::get_path() +{ + return ap_path; + +} +AccessPoint::AccessPoint(std::string path, std::shared_ptr access_point_proxy) : + ap_path(path), access_point_proxy(access_point_proxy) +{ + Glib::Variant strength_start; + access_point_proxy->get_cached_property(strength_start, "Strength"); + strength = strength_start.get(); + + Glib::Variant> ssid_start; + access_point_proxy->get_cached_property(ssid_start, "Ssid"); + auto ssid_bytes = ssid_start.get(); + ssid = std::string(ssid_bytes.begin(), ssid_bytes.end()); + + access_point_proxy->signal_properties_changed().connect( + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { + for (auto &it : properties) + { + if (it.first == "Strength") + { + auto value = Glib::VariantBase::cast_dynamic>(it.second).get(); + strength = value; + access_point_altered.emit(); + } else if (it.first == "Ssid") + { + auto value = Glib::VariantBase::cast_dynamic>>(it.second).get(); + ssid = std::string(value.begin(), value.end()); + access_point_altered.emit(); + } + } + } + ); + +} + +std::string AccessPoint::get_ssid(){ + return ssid; +} + +std::string AccessPoint::strength_string() +{ + if (strength >= 80) + { + return "excellent"; + } + + if (strength >= 55) + { + return "good"; + } + + if (strength >= 30) + { + return "ok"; + } + + if (strength >= 5) + { + return "weak"; + } + + return "none"; + +} + +std::string AccessPoint::get_icon_name() +{ + return "network-wireless-signal-"+strength_string(); +} + +type_signal_network_altered AccessPoint::signal_altered() +{ + return access_point_altered; +} \ No newline at end of file diff --git a/src/util/network/wifi-ap.hpp b/src/util/network/wifi-ap.hpp new file mode 100644 index 00000000..12923f1e --- /dev/null +++ b/src/util/network/wifi-ap.hpp @@ -0,0 +1,25 @@ +#pragma once +#include "giomm.h" +#include "giomm/dbusproxy.h" +#include "glibmm/variant.h" +#include "network.hpp" +#include "sigc++/connection.h" +#include +#include + +using type_signal_access_point_altered = sigc::signal; +class AccessPoint { + private: + std::string ap_path; + type_signal_access_point_altered access_point_altered; + unsigned char strength; + std::string ssid=""; + public: + std::string get_path(); + std::shared_ptr access_point_proxy; + AccessPoint(std::string path, std::shared_ptr access_point_proxy); + std::string get_ssid(); + std::string strength_string(); + std::string get_icon_name(); + type_signal_access_point_altered signal_altered(); +}; diff --git a/src/util/network/wifi.cpp b/src/util/network/wifi.cpp new file mode 100644 index 00000000..5bf04f5b --- /dev/null +++ b/src/util/network/wifi.cpp @@ -0,0 +1,152 @@ +#include "wifi.hpp" +#include "glibmm.h" +#include "glibmm/variant.h" +#include "network/manager.hpp" +#include "network/wifi-ap.hpp" +#include + +type_signal_access_point WifiNetwork::signal_add_access_point() +{ + return add_ap; +} +type_signal_access_point WifiNetwork::signal_remove_access_point() +{ + return remove_ap; +} + +std::map> WifiNetwork::get_access_points() +{ + return all_access_points; +} + +void WifiNetwork::add_access_point(std::string path) +{ + + auto ap_proxy =Gio::DBus::Proxy::create_sync(wifi_proxy->get_connection(), + "org.freedesktop.NetworkManager", + path, + "org.freedesktop.NetworkManager.AccessPoint"); + auto new_ap = std::make_shared(path, ap_proxy); + all_access_points[path] = new_ap; +} + +void WifiNetwork::remove_access_point(std::string path) +{ + all_access_points.erase(path); +} + +WifiNetwork::WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy): + Network(path, device_proxy), wifi_proxy(wifi_proxy) +{ + wifi_proxy->signal_signal().connect( + [this] (const Glib::ustring& source, const Glib::ustring& signal , const Glib::VariantContainerBase& value) { + if (signal == "AccessPointAdded") + { + auto val = Glib::VariantBase::cast_dynamic>(value.get_child()).get(); + add_access_point(val); + add_ap.emit(all_access_points[val]); + } else if (signal == "AccessPointRemoved") + { + auto val = Glib::VariantBase::cast_dynamic>(value.get_child()).get(); + remove_ap.emit(all_access_points[val]); + all_access_points.erase(val); + } + } + ); + + wifi_proxy->signal_properties_changed().connect( + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { + for (auto &it : properties) + { + if (it.first == "ActiveAccessPoint") + { + if (access_point_signal) + { + access_point_signal.disconnect(); + } + auto access_point = get_current_access_point(); + if (access_point) + { + /* Bubble signal upwards */ + access_point_signal = access_point->signal_altered().connect( + [this] () { + network_altered.emit(); + } + ); + } + network_altered.emit(); + + } + } + } + ); + /* Initial values */ + Glib::Variant> base; + wifi_proxy->get_cached_property(base, "AccessPoints"); + for (auto &it : base.get()) + { + add_access_point(it); + } + + auto access_point = get_current_access_point(); + if (access_point) + { + access_point_signal = access_point->signal_altered().connect( + [this]() { + network_altered.emit(); + } + ); + } +} + +std::string WifiNetwork::get_name() +{ + auto network = get_current_access_point(); + if (network) + { + return network->get_ssid(); + } + return "Wifi..."; +} + +std::string WifiNetwork::get_color_name() +{ + return ""; +} + +std::string WifiNetwork::get_icon_name() +{ + if (show_spinner()) + { + return "network-wireless-disconnected"; + } + auto ap = get_current_access_point(); + if (!ap){ + return "network-wireless-disconnected"; + } + return "network-wireless-signal-"+ap->strength_string(); +} + +std::string WifiNetwork::get_friendly_name() +{ + auto ap = get_current_access_point(); + if (ap) + { + return ap->get_ssid(); + } + return "Not connected"; +} + +std::shared_ptr WifiNetwork::get_current_access_point() +{ + auto access_point = all_access_points[get_current_access_point_path()]; + return access_point; +} + +std::string WifiNetwork::get_current_access_point_path() +{ + Glib::Variant ap_name; + wifi_proxy->get_cached_property(ap_name, "ActiveAccessPoint"); + return ap_name.get(); +} + diff --git a/src/util/network/wifi.hpp b/src/util/network/wifi.hpp new file mode 100644 index 00000000..7294648a --- /dev/null +++ b/src/util/network/wifi.hpp @@ -0,0 +1,38 @@ +#pragma once +#include "giomm.h" +#include "giomm/dbusproxy.h" +#include "glibmm/variant.h" +#include "network.hpp" +#include "sigc++/connection.h" +#include +#include +#include "wifi-ap.hpp" + + +using type_signal_access_point = sigc::signal)>; + +class WifiNetwork : public Network { + private: + sigc::connection access_point_signal; + std::map> all_access_points; + type_signal_access_point add_ap, remove_ap; + protected: + std::shared_ptr wifi_proxy; + public: + + type_signal_access_point signal_add_access_point(); + type_signal_access_point signal_remove_access_point(); + + std::map> get_access_points(); + + void add_access_point(std::string path); + void remove_access_point(std::string path); + + WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy); + std::string get_name() override; + std::string get_color_name() override; + std::string get_icon_name() override; + std::string get_friendly_name() override; + std::string get_current_access_point_path(); + std::shared_ptr get_current_access_point(); +}; \ No newline at end of file diff --git a/src/util/network/wired.cpp b/src/util/network/wired.cpp new file mode 100644 index 00000000..28aed6fa --- /dev/null +++ b/src/util/network/wired.cpp @@ -0,0 +1,27 @@ +#include "wired.hpp" +WiredNetwork::WiredNetwork(std::string path, std::shared_ptr proxy): + Network(path, proxy) +{ } + +std::string WiredNetwork::get_name() +{ + return "Wired"; +} + +std::string WiredNetwork::get_icon_name() +{ + if (is_active()){ + return "network-wired"; + } + return "network-wired-offline"; +} + +std::string WiredNetwork::get_color_name() +{ + return "excellent"; +} +std::string WiredNetwork::get_friendly_name() +{ + return "Ethernet"; +} + \ No newline at end of file diff --git a/src/util/network/wired.hpp b/src/util/network/wired.hpp new file mode 100644 index 00000000..e8a68af5 --- /dev/null +++ b/src/util/network/wired.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "network.hpp" +#include + +class WiredNetwork : public Network { + public: + WiredNetwork(std::string path, std::shared_ptr proxy); + std::string get_name() override; + std::string get_icon_name() override; + std::string get_color_name() override; + std::string get_friendly_name() override; +}; \ No newline at end of file From ac13828fd8ca6803cbeb5010e73ea74eed622149 Mon Sep 17 00:00:00 2001 From: trigg Date: Tue, 3 Feb 2026 01:59:07 +0000 Subject: [PATCH 02/17] 'undo me' left in code --- src/panel/widgets/network.cpp | 4 +--- src/panel/widgets/network.hpp | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index ae2ad551..2a5ddf74 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -33,7 +33,7 @@ void WayfireNetworkInfo::init(Gtk::Box *container) button->set_child(button_content); button->add_css_class("flat"); - //button->get_popover()->set_child(control); + button->get_popover()->set_child(control); button_content.set_valign(Gtk::Align::CENTER); button_content.append(icon); @@ -41,8 +41,6 @@ void WayfireNetworkInfo::init(Gtk::Box *container) button_content.set_spacing(6); icon.set_valign(Gtk::Align::CENTER); - window_undo_me.set_child(control); - window_undo_me.present(); signals.push_back(network_manager->signal_default_changed().connect( sigc::mem_fun(*this,&WayfireNetworkInfo::set_connection) diff --git a/src/panel/widgets/network.hpp b/src/panel/widgets/network.hpp index a79b0765..042690ef 100644 --- a/src/panel/widgets/network.hpp +++ b/src/panel/widgets/network.hpp @@ -27,7 +27,6 @@ class WayfireNetworkInfo : public WayfireWidget WfOption click_command_opt{"panel/network_onclick_command"}; NetworkControlWidget control; - Gtk::Window window_undo_me; public: WayfireNetworkInfo(); ~WayfireNetworkInfo(); From 1c6ea30eff24a5b51ef6e908a329d75b97003664 Mon Sep 17 00:00:00 2001 From: trigg Date: Tue, 3 Feb 2026 02:34:16 +0000 Subject: [PATCH 03/17] clean imports --- src/util/network/bluetooth.hpp | 1 - src/util/network/connection.hpp | 8 +++++--- src/util/network/manager.cpp | 14 ++++---------- src/util/network/manager.hpp | 5 ++--- src/util/network/modem.hpp | 8 +++++--- src/util/network/network-widget.cpp | 25 +++++++++++++------------ src/util/network/network-widget.hpp | 11 ++++++----- src/util/network/network.cpp | 1 + src/util/network/network.hpp | 6 ++---- src/util/network/vpn.hpp | 6 ++---- src/util/network/wifi-ap.cpp | 5 +++-- src/util/network/wifi-ap.hpp | 8 ++------ src/util/network/wifi.cpp | 10 +++++----- src/util/network/wifi.hpp | 10 +++++----- src/util/network/wired.hpp | 2 +- 15 files changed, 56 insertions(+), 64 deletions(-) diff --git a/src/util/network/bluetooth.hpp b/src/util/network/bluetooth.hpp index ad34bc58..f9e6d580 100644 --- a/src/util/network/bluetooth.hpp +++ b/src/util/network/bluetooth.hpp @@ -3,7 +3,6 @@ #include #include -#include "giomm/dbusproxy.h" #include "network.hpp" class BluetoothNetwork : public Network { diff --git a/src/util/network/connection.hpp b/src/util/network/connection.hpp index f53a253f..246c53ee 100644 --- a/src/util/network/connection.hpp +++ b/src/util/network/connection.hpp @@ -1,8 +1,10 @@ #pragma once -#include "giomm/dbusproxy.h" -#include "network.hpp" -#include "sigc++/connection.h" #include +#include +#include + +#include "network.hpp" + /* Information about an active connection */ class Connection : public Network { public: diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index c4c984fe..ceddbc9b 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -2,18 +2,12 @@ #include #include #include -#include #include "manager.hpp" -#include "giomm/dbusproxy.h" -#include "glib.h" -#include "glibmm/main.h" -#include "glibmm/ustring.h" -#include "glibmm/variant.h" -#include "network/bluetooth.hpp" -#include "network/connection.hpp" -#include "network/network.hpp" -#include "network/vpn.hpp" +#include "bluetooth.hpp" +#include "connection.hpp" +#include "network.hpp" +#include "vpn.hpp" #include "wifi.hpp" #include "modem.hpp" #include "wired.hpp" diff --git a/src/util/network/manager.hpp b/src/util/network/manager.hpp index 6ba08dba..6e813f3c 100644 --- a/src/util/network/manager.hpp +++ b/src/util/network/manager.hpp @@ -1,15 +1,14 @@ #pragma once #include #include +#include #include #include #include #include -#include "giomm/dbusconnection.h" -#include "giomm/dbusproxy.h" + #include "network.hpp" #include "connection.hpp" -#include "sigc++/connection.h" #include "vpn.hpp" using type_signal_network = sigc::signal)>; diff --git a/src/util/network/modem.hpp b/src/util/network/modem.hpp index 4b1b97fc..c6df8cb3 100644 --- a/src/util/network/modem.hpp +++ b/src/util/network/modem.hpp @@ -1,9 +1,11 @@ #pragma once -#include "giomm/dbusproxy.h" -#include "glibmm/variant.h" -#include "network.hpp" #include +#include #include +#include +#include + +#include "network.hpp" #define CAP_5G 16 #define CAP_4G 8 diff --git a/src/util/network/network-widget.cpp b/src/util/network/network-widget.cpp index ae2c8b9b..54b21151 100644 --- a/src/util/network/network-widget.cpp +++ b/src/util/network/network-widget.cpp @@ -1,16 +1,17 @@ -#include "network-widget.hpp" -#include "gtkmm/enums.h" -#include "gtkmm/gestureclick.h" -#include "network/bluetooth.hpp" -#include "network/manager.hpp" -#include "network/modem.hpp" -#include "network/network.hpp" -#include "network/vpn.hpp" -#include "network/wifi-ap.hpp" -#include "network/wifi.hpp" -#include "network/wired.hpp" -#include "sigc++/functors/mem_fun.h" +#include #include +#include + +#include "bluetooth.hpp" +#include "manager.hpp" +#include "modem.hpp" +#include "network.hpp" +#include "vpn.hpp" +#include "wifi-ap.hpp" +#include "wifi.hpp" +#include "wired.hpp" +#include "network-widget.hpp" + AccessPointWidget::AccessPointWidget(std::string path_in, std::shared_ptr ap_in): ap(ap_in),path(path_in) diff --git a/src/util/network/network-widget.hpp b/src/util/network/network-widget.hpp index d7a8e708..f728ab42 100644 --- a/src/util/network/network-widget.hpp +++ b/src/util/network/network-widget.hpp @@ -1,11 +1,12 @@ #pragma once -#include #include -#include "gtkmm.h" -#include "network/vpn.hpp" -#include "sigc++/connection.h" +#include +#include + #include "manager.hpp" -#include "wifi.hpp" +#include "wifi-ap.hpp" +#include "vpn.hpp" + class AccessPointWidget : public Gtk::Box { diff --git a/src/util/network/network.cpp b/src/util/network/network.cpp index b17db0be..81efd609 100644 --- a/src/util/network/network.cpp +++ b/src/util/network/network.cpp @@ -1,5 +1,6 @@ #include "network.hpp" #include "manager.hpp" + type_signal_network_altered Network::signal_network_altered() { return network_altered; } Network::Network(std::string path, std::shared_ptr in_proxy): diff --git a/src/util/network/network.hpp b/src/util/network/network.hpp index b3d5c95f..8b7a5d06 100644 --- a/src/util/network/network.hpp +++ b/src/util/network/network.hpp @@ -1,11 +1,9 @@ #pragma once -#include "glibmm/ustring.h" -#include "glibmm/variant.h" #include #include #include -#include -#include +#include + #define NM_DEVICE_STATE_UNKNOWN 0 #define NM_DEVICE_STATE_UNMANAGED 10 #define NM_DEVICE_STATE_UNAVAILABLE 20 diff --git a/src/util/network/vpn.hpp b/src/util/network/vpn.hpp index d677a6f4..9b2c068a 100644 --- a/src/util/network/vpn.hpp +++ b/src/util/network/vpn.hpp @@ -1,8 +1,6 @@ #pragma once -#include "giomm/dbusproxy.h" -#include "glibmm/variant.h" -#include "network.hpp" -#include +#include +#include class VpnConfig { private: diff --git a/src/util/network/wifi-ap.cpp b/src/util/network/wifi-ap.cpp index 37ec25a4..8e2ad7c2 100644 --- a/src/util/network/wifi-ap.cpp +++ b/src/util/network/wifi-ap.cpp @@ -1,5 +1,6 @@ #include "wifi-ap.hpp" -#include "network/network.hpp" +#include "network.hpp" + std::string AccessPoint::get_path() { return ap_path; @@ -70,7 +71,7 @@ std::string AccessPoint::strength_string() std::string AccessPoint::get_icon_name() { - return "network-wireless-signal-"+strength_string(); + return "network-wireless-signal-"+strength_string()+"-symbolic"; } type_signal_network_altered AccessPoint::signal_altered() diff --git a/src/util/network/wifi-ap.hpp b/src/util/network/wifi-ap.hpp index 12923f1e..e5e15410 100644 --- a/src/util/network/wifi-ap.hpp +++ b/src/util/network/wifi-ap.hpp @@ -1,11 +1,7 @@ #pragma once -#include "giomm.h" -#include "giomm/dbusproxy.h" -#include "glibmm/variant.h" -#include "network.hpp" -#include "sigc++/connection.h" +#include #include -#include + using type_signal_access_point_altered = sigc::signal; class AccessPoint { diff --git a/src/util/network/wifi.cpp b/src/util/network/wifi.cpp index 5bf04f5b..7d09cb9a 100644 --- a/src/util/network/wifi.cpp +++ b/src/util/network/wifi.cpp @@ -1,10 +1,10 @@ -#include "wifi.hpp" -#include "glibmm.h" -#include "glibmm/variant.h" -#include "network/manager.hpp" -#include "network/wifi-ap.hpp" +#include #include +#include "manager.hpp" +#include "wifi-ap.hpp" +#include "wifi.hpp" + type_signal_access_point WifiNetwork::signal_add_access_point() { return add_ap; diff --git a/src/util/network/wifi.hpp b/src/util/network/wifi.hpp index 7294648a..8a755e1f 100644 --- a/src/util/network/wifi.hpp +++ b/src/util/network/wifi.hpp @@ -1,11 +1,11 @@ #pragma once -#include "giomm.h" -#include "giomm/dbusproxy.h" -#include "glibmm/variant.h" -#include "network.hpp" -#include "sigc++/connection.h" #include #include +#include +#include +#include + +#include "network.hpp" #include "wifi-ap.hpp" diff --git a/src/util/network/wired.hpp b/src/util/network/wired.hpp index e8a68af5..fb454de5 100644 --- a/src/util/network/wired.hpp +++ b/src/util/network/wired.hpp @@ -1,6 +1,6 @@ #pragma once -#include "network.hpp" #include +#include "network.hpp" class WiredNetwork : public Network { public: From 6ab353b1685cf712dee9e6ed5acdc7fd4559e507 Mon Sep 17 00:00:00 2001 From: trigg Date: Tue, 3 Feb 2026 23:52:18 +0000 Subject: [PATCH 04/17] core: network manager survives service restart core: clean up references on teardowns --- src/panel/widgets/network.cpp | 5 +- src/util/meson.build | 1 + src/util/network/connection.hpp | 6 + src/util/network/manager.cpp | 118 ++++++++++++-- src/util/network/manager.hpp | 14 +- src/util/network/modem.cpp | 183 ++++++++++++++++++++++ src/util/network/modem.hpp | 190 ++--------------------- src/util/network/network-widget.cpp | 233 ++++++++++++++++++---------- src/util/network/network-widget.hpp | 13 +- src/util/network/network.cpp | 13 +- src/util/network/network.hpp | 2 + src/util/network/wifi-ap.cpp | 12 +- src/util/network/wifi-ap.hpp | 3 + src/util/network/wifi.cpp | 27 +++- src/util/network/wifi.hpp | 6 +- 15 files changed, 518 insertions(+), 308 deletions(-) create mode 100644 src/util/network/modem.cpp diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 2a5ddf74..0ade3dee 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -45,14 +45,11 @@ void WayfireNetworkInfo::init(Gtk::Box *container) signals.push_back(network_manager->signal_default_changed().connect( sigc::mem_fun(*this,&WayfireNetworkInfo::set_connection) )); + set_connection(network_manager->get_primary_network()); } void WayfireNetworkInfo::set_connection(std::shared_ptr network) { - if (network == nullptr) - { - return; - } status.remove_css_class("none"); status.remove_css_class("weak"); status.remove_css_class("bad"); diff --git a/src/util/meson.build b/src/util/meson.build index 2f1195c5..c1e636d6 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -14,6 +14,7 @@ util = static_library( 'network/network-widget.cpp', 'network/wifi-ap.cpp', 'network/network.cpp', + 'network/modem.cpp', ], dependencies: [wf_protos, gtklayershell, wayland_client, gtkmm, wfconfig, libinotify, json], ) diff --git a/src/util/network/connection.hpp b/src/util/network/connection.hpp index 246c53ee..a6a79fcc 100644 --- a/src/util/network/connection.hpp +++ b/src/util/network/connection.hpp @@ -12,6 +12,12 @@ class Connection : public Network { std::vector signals; std::shared_ptr connection_proxy, vpn_proxy; std::vector> devices; + + Connection(): + Network("/", nullptr), connection_proxy(nullptr), devices({}) + { + + } Connection(std::string path, std::shared_ptr connection_proxy, std::vector> devices): Network(path, nullptr), connection_proxy(connection_proxy), devices(devices) { diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index ceddbc9b..191b33ba 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -29,9 +29,79 @@ NetworkManager::NetworkManager() { + Gio::DBus::Proxy::create_for_bus(Gio::DBus::BusType::SYSTEM, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + [this] (const Glib::RefPtr & result) + { + // Got a dbus proxy + manager_proxy = Gio::DBus::Proxy::create_finish(result); + auto val = manager_proxy->call_sync("ListNames"); + Glib::Variant> list; + val.get_child(list, 0); + auto l2 = list.get(); + for (auto t : l2) + { + if (t == NM_DBUS_NAME) + { + connect_nm(); + } + } + + /* https://dbus.freedesktop.org/doc/dbus-java/api/org/freedesktop/DBus.NameOwnerChanged.html */ + dbus_signals.push_back(manager_proxy->signal_signal().connect( + [this] (const Glib::ustring & sender_name, + const Glib::ustring & signal_name, + const Glib::VariantContainerBase & params) + { + if (signal_name == "NameOwnerChanged") + { + Glib::Variant to, from, name; + params.get_child(name, 0); + params.get_child(from, 1); + params.get_child(to, 2); + if (name.get() == NM_DBUS_NAME) + { + if (from.get() == "") + { + connect_nm(); + } else if (to.get() == "") + { + lost_nm(); + } + } + } + })); + }); +} + +void NetworkManager::lost_nm() +{ + if (primary_signal) + primary_signal.disconnect(); + if (debounce) + debounce.disconnect(); + std::cout << "NetworkManager Lost" << std::endl; + connection = nullptr; + settings_proxy = nullptr; + nm_proxy = nullptr; + all_devices.clear(); + all_vpns.clear(); + primary_connection = "/"; + primary_connection_obj = std::make_shared(); + for (auto signal : nm_signals) + { + signal.disconnect(); + } + nm_stop.emit(); +} + +void NetworkManager::connect_nm() +{ + std::cout << "NetworkManager Found" << std::endl; all_devices.emplace("/", new NullNetwork()); - auto cancellable = Gio::Cancellable::create(); - connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::SYSTEM, cancellable); + connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::SYSTEM); if (!connection) { std::cerr << "Failed to connect to dbus" << std::endl; @@ -43,7 +113,11 @@ NetworkManager::NetworkManager() NM_DBUS_NAME, "/org/freedesktop/NetworkManager/Settings", "org.freedesktop.NetworkManager.Settings"); - + if (!settings_proxy) + { + std::cerr << "No NM Settings proxy" << std::endl; + return; + } auto ret1 = settings_proxy->call_sync("ListConnections").get_child(); Glib::Variant> ret = Glib::VariantBase::cast_dynamic>>(ret1); for (auto &it : ret.get()){ @@ -51,7 +125,7 @@ NetworkManager::NetworkManager() vpn_added.emit(it); } - settings_proxy->signal_signal().connect( + nm_signals.push_back(settings_proxy->signal_signal().connect( [this] (const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) { if (signal == "ConnectionRemoved") { @@ -65,7 +139,7 @@ NetworkManager::NetworkManager() vpn_added.emit(var); } } - ); + )); nm_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, @@ -78,10 +152,10 @@ NetworkManager::NetworkManager() return; } - signals.push_back(nm_proxy->signal_properties_changed().connect( + nm_signals.push_back(nm_proxy->signal_properties_changed().connect( sigc::mem_fun(*this, &NetworkManager::on_nm_properties_changed))); - signals.push_back(nm_proxy->signal_signal().connect( + nm_signals.push_back(nm_proxy->signal_signal().connect( sigc::mem_fun(*this, &NetworkManager::on_nm_signal))); /* Fill Initial List*/ @@ -118,8 +192,6 @@ void NetworkManager::check_add_vpn(std::string path) std::cerr << "INVALID TYPES "<< conname.get_type_string() << " " << contype.get_type_string()< async) @@ -130,12 +202,14 @@ void NetworkManager::get_all_devices_cb(std::shared_ptr async) add_network(val); } /* Now get the current connection */ - Glib::signal_idle().connect([this] () { + nm_signals.push_back(Glib::signal_idle().connect([this] () { Glib::Variant path_read; nm_proxy->get_cached_property(path_read, "PrimaryConnection"); changed_primary(path_read.get()); return G_SOURCE_REMOVE; - }); + })); + /* And emit a start event */ + nm_start.emit(); } void NetworkManager::add_network(std::string path){ @@ -301,14 +375,17 @@ void NetworkManager::deactivate_connection(std::string p1) manager->call_sync("DeactivateConnection", paths); } catch (...) { - /* Most likely no password*/ - /* TODO */ + } } /* Is Wifi Enabled, in software and in rfkill */ std::tuple NetworkManager::wifi_global_enabled() { + if (!nm_proxy) + { + return {false, false}; + } Glib::Variant wifisoft, wifihard; nm_proxy->get_cached_property(wifisoft, "WirelessEnabled"); nm_proxy->get_cached_property(wifihard, "WirelessHardwareEnabled"); @@ -317,6 +394,10 @@ std::tuple NetworkManager::wifi_global_enabled() /* Is Mobile Data Enabled, in software and in rfkill */ std::tuple NetworkManager::mobile_global_enabled() { + if (!nm_proxy) + { + return {false, false}; + } Glib::Variant modemsoft, modemhard; nm_proxy->get_cached_property(modemsoft, "WwanEnabled"); nm_proxy->get_cached_property(modemhard, "WwanHardwareEnabled"); @@ -325,6 +406,10 @@ std::tuple NetworkManager::mobile_global_enabled() /* Is Networking enabled */ bool NetworkManager::networking_global_enabled() { + if (!nm_proxy) + { + return false; + } Glib::Variant enabled; nm_proxy->get_cached_property(enabled, "NetworkingEnabled"); return enabled.get(); @@ -374,5 +459,10 @@ void NetworkManager::networking_global_set(bool value) NetworkManager::~NetworkManager() { - + lost_nm(); + /* Signals that outlast each NetworkManager start/stop but need to clear on widget reload */ + for (auto signal : dbus_signals) + { + signal.disconnect(); + } } \ No newline at end of file diff --git a/src/util/network/manager.hpp b/src/util/network/manager.hpp index 6e813f3c..2909126e 100644 --- a/src/util/network/manager.hpp +++ b/src/util/network/manager.hpp @@ -9,6 +9,7 @@ #include "network.hpp" #include "connection.hpp" +#include "network/null.hpp" #include "vpn.hpp" using type_signal_network = sigc::signal)>; @@ -21,19 +22,19 @@ class NetworkManager private: type_signal_network default_changed, device_added, device_removed; type_signal_device_list_changed device_list_changed; - type_signal_simple global_change; + type_signal_simple global_change, nm_start, nm_stop; type_signal_path vpn_added, vpn_removed; Glib::RefPtr connection; - Glib::RefPtr nm_proxy, settings_proxy; + Glib::RefPtr nm_proxy, settings_proxy, manager_proxy; - std::vector signals; + std::vector nm_signals, dbus_signals; sigc::connection debounce, primary_signal; std::string primary_connection = ""; - std::shared_ptr primary_connection_obj; + std::shared_ptr primary_connection_obj = std::make_shared(); std::map> all_devices; std::map> all_vpns; @@ -44,7 +45,8 @@ class NetworkManager void add_network(std::string path); void check_add_vpn(std::string path); void changed_primary(std::string path); - + void connect_nm(); + void lost_nm(); public: /* Emitted when the default connection or it's properties change */ @@ -59,6 +61,8 @@ class NetworkManager type_signal_simple signal_global_toggle() { return global_change; } type_signal_path signal_vpn_added() { return vpn_added; } type_signal_path signal_vpn_removed() { return vpn_removed; } + type_signal_simple signal_nm_start() { return nm_start; } + type_signal_simple signal_nm_stop() { return nm_stop; } std::shared_ptr get_nm_proxy() { return nm_proxy; } /* A list of current networks. */ diff --git a/src/util/network/modem.cpp b/src/util/network/modem.cpp new file mode 100644 index 00000000..e8862454 --- /dev/null +++ b/src/util/network/modem.cpp @@ -0,0 +1,183 @@ +#include "modem.hpp" +ModemNetwork::ModemNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr modem_proxy): + Network(path, device_proxy), modem_proxy(modem_proxy) +{ + Glib::Variant device_data; + modem_proxy->get_cached_property(device_data, "DeviceId"); + + find_mm_proxy(device_data.get()); +} + +void ModemNetwork::find_mm_proxy(std::string dev_id) +{ + auto mm_om_proxy = Gio::DBus::Proxy::create_sync(modem_proxy->get_connection(), + "org.freedesktop.ModemManager1", + "/org/freedesktop/ModemManager1", + "org.freedesktop.DBus.ObjectManager"); + + auto ret1 = mm_om_proxy->call_sync("GetManagedObjects").get_child(); + auto ret = Glib::VariantBase::cast_dynamic>>>>(ret1); + + for (auto &it : ret.get()) + { + std::string modem_path = it.first; + for (auto &next : it.second) + { + if (next.first == "org.freedesktop.ModemManager1.Modem") + { + for (auto &why : next.second) + { + if (why.first == "DeviceIdentifier") + { + auto devid = Glib::VariantBase::cast_dynamic>(why.second); + if (devid.get() == dev_id) + { + + mm_proxy = Gio::DBus::Proxy::create_sync(device_proxy->get_connection(), + "org.freedesktop.ModemManager1", + modem_path, + "org.freedeskop.ModemManager1.Modem"); + } + } + } + } + } + } + if (mm_proxy) + { + signals.push_back(mm_proxy->signal_properties_changed().connect( + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { + for (auto &it : properties) + { + if (it.first == "SignalQuality") + { + auto container = Glib::VariantBase::cast_dynamic(it.second); + Glib::Variant signal_data; + container.get_child(signal_data,0); + // "(ub)" => percent 0-100, 'is recent' + strength = signal_data.get(); + + } + if (it.first == "CurrentModes") + { + auto container = Glib::VariantBase::cast_dynamic(it.second); + Glib::Variant mode_data; + container.get_child(mode_data,1); + caps = mode_data.get(); + } + } + })); + } else + { + std::cerr << "Could not get extra modem details" << std::endl; + } + +} + +ModemNetwork::~ModemNetwork() +{ + for(auto signal : signals) + { + signal.disconnect(); + } +} + +std::string ModemNetwork::strength_string() +{ + if (strength >= 80) + { + return "excellent"; + } + + if (strength >= 55) + { + return "good"; + } + + if (strength >= 30) + { + return "ok"; + } + + if (strength >= 5) + { + return "weak"; + } + + return "none"; +} + +std::string ModemNetwork::get_name() +{ + if (!mm_proxy) + { + return "Misconfigured Mobile"; + } + /* TODO Get Carrier from MM */ + return "Mobile"; +} + +std::string ModemNetwork::get_signal_band() +{ + if (strength == 100) + { + return "100"; + } else if (strength >= 80) + { + return "80"; + } else if (strength >= 60) + { + return "60"; + } else if (strength >= 40) + { + return "40"; + } else if (strength >= 20) + { + return "20"; + } + return "0"; +} + +std::string ModemNetwork::get_connection_type_string() +{ + if (caps & CAP_5G) + { + return "5g"; + } else if (caps & CAP_4G) + { + return "lte"; + } else if (caps & CAP_3G) + { + return "hspa"; + } else if (caps & CAP_2G) + { + return "gprs"; + } else if (caps & CAP_CS) + { + return "edge"; + } + return "edge"; +} + +std::string ModemNetwork::get_icon_name() +{ + if (!mm_proxy) + { + return "network-mobile-off"; + } + if (!is_active()) + { + return "network-mobile-off"; + } + return "network-mobile-"+get_signal_band()+"-"+get_connection_type_string(); +} + +std::string ModemNetwork::get_color_name() +{ + return strength_string(); +} + +std::string ModemNetwork::get_friendly_name() +{ + return "Mobile Data"; +} \ No newline at end of file diff --git a/src/util/network/modem.hpp b/src/util/network/modem.hpp index c6df8cb3..947d4d76 100644 --- a/src/util/network/modem.hpp +++ b/src/util/network/modem.hpp @@ -6,6 +6,7 @@ #include #include "network.hpp" +#include "sigc++/connection.h" #define CAP_5G 16 #define CAP_4G 8 @@ -19,183 +20,14 @@ class ModemNetwork : public Network { int caps = 8; std::shared_ptr modem_proxy; std::shared_ptr mm_proxy; - ModemNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr modem_proxy): - Network(path, device_proxy), modem_proxy(modem_proxy) - { - Glib::Variant device_data; - modem_proxy->get_cached_property(device_data, "DeviceId"); - - find_mm_proxy(device_data.get()); - } - - void find_mm_proxy(std::string dev_id) - { - auto mm_om_proxy = Gio::DBus::Proxy::create_sync(modem_proxy->get_connection(), - "org.freedesktop.ModemManager1", - "/org/freedesktop/ModemManager1", - "org.freedesktop.DBus.ObjectManager"); - - auto ret1 = mm_om_proxy->call_sync("GetManagedObjects").get_child(); - auto ret = Glib::VariantBase::cast_dynamic>>>>(ret1); - - for (auto &it : ret.get()) - { - std::string modem_path = it.first; - for (auto &next : it.second) - { - if (next.first == "org.freedesktop.ModemManager1.Modem") - { - for (auto &why : next.second) - { - if (why.first == "DeviceIdentifier") - { - auto devid = Glib::VariantBase::cast_dynamic>(why.second); - if (devid.get() == dev_id) - { - - mm_proxy = Gio::DBus::Proxy::create_sync(device_proxy->get_connection(), - "org.freedesktop.ModemManager1", - modem_path, - "org.freedeskop.ModemManager1.Modem"); - } - } - } - } - } - } - if (mm_proxy) - { - mm_proxy->signal_properties_changed().connect( - [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { - for (auto &it : properties) - { - if (it.first == "SignalQuality") - { - auto container = Glib::VariantBase::cast_dynamic(it.second); - Glib::Variant signal_data; - container.get_child(signal_data,0); - // "(ub)" => percent 0-100, 'is recent' - strength = signal_data.get(); - - } - if (it.first == "CurrentModes") - { - auto container = Glib::VariantBase::cast_dynamic(it.second); - Glib::Variant mode_data; - container.get_child(mode_data,1); - caps = mode_data.get(); - } - } - }); - } else - { - std::cerr << "Could not get extra modem details" << std::endl; - } - - } - - ~ModemNetwork() - { - - } - - std::string strength_string() - { - if (strength >= 80) - { - return "excellent"; - } - - if (strength >= 55) - { - return "good"; - } - - if (strength >= 30) - { - return "ok"; - } - - if (strength >= 5) - { - return "weak"; - } - - return "none"; - } - - std::string get_name() - { - if (!mm_proxy) - { - return "Misconfigured Mobile"; - } - /* TODO Get Carrier from MM */ - return "Mobile"; - } - - std::string get_signal_band() - { - if (strength == 100) - { - return "100"; - } else if (strength >= 80) - { - return "80"; - } else if (strength >= 60) - { - return "60"; - } else if (strength >= 40) - { - return "40"; - } else if (strength >= 20) - { - return "20"; - } - return "0"; - } - - std::string get_connection_type_string() - { - if (caps & CAP_5G) - { - return "5g"; - } else if (caps & CAP_4G) - { - return "lte"; - } else if (caps & CAP_3G) - { - return "hspa"; - } else if (caps & CAP_2G) - { - return "gprs"; - } else if (caps & CAP_CS) - { - return "edge"; - } - return "edge"; - } - - std::string get_icon_name() - { - if (!mm_proxy) - { - return "network-mobile-off"; - } - if (!is_active()) - { - return "network-mobile-off"; - } - return "network-mobile-"+get_signal_band()+"-"+get_connection_type_string(); - } - - std::string get_color_name() - { - return strength_string(); - } - - std::string get_friendly_name() - { - return "Mobile Data"; - } + ModemNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr modem_proxy); + void find_mm_proxy(std::string dev_id); + ~ModemNetwork(); + std::string strength_string(); + std::string get_name(); + std::string get_signal_band(); + std::string get_connection_type_string(); + std::string get_icon_name(); + std::string get_color_name(); + std::string get_friendly_name(); }; \ No newline at end of file diff --git a/src/util/network/network-widget.cpp b/src/util/network/network-widget.cpp index 54b21151..951c9644 100644 --- a/src/util/network/network-widget.cpp +++ b/src/util/network/network-widget.cpp @@ -24,13 +24,16 @@ AccessPointWidget::AccessPointWidget(std::string path_in, std::shared_ptrget_ssid()); image.set_from_icon_name(ap->get_icon_name()); }; - signal = ap_in->signal_altered().connect(update_ap); + signals.push_back(ap_in->signal_altered().connect(update_ap)); update_ap(); } AccessPointWidget::~AccessPointWidget() { - signal.disconnect(); + for (auto signal : signals) + { + signal.disconnect(); + } } VPNControlWidget::VPNControlWidget(std::shared_ptr config): @@ -42,6 +45,14 @@ VPNControlWidget::VPNControlWidget(std::shared_ptr config): image.set_from_icon_name("network-vpn-symbolic"); } +VPNControlWidget::~VPNControlWidget() +{ + for (auto signal : signals) + { + signal.disconnect(); + } +} + DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): network(network) { @@ -68,17 +79,17 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): add_access_point(it.second); } - wifi->signal_add_access_point().connect( + signals.push_back(wifi->signal_add_access_point().connect( [this] (std::shared_ptr ap) { add_access_point(ap); } - ); + )); - wifi->signal_remove_access_point().connect( + signals.push_back(wifi->signal_remove_access_point().connect( [this] (std::shared_ptr ap) { remove_access_point(ap->get_path()); } - ); + )); auto wifi_cb = [this, wifi] () { @@ -92,7 +103,7 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): topbox.show(); } }; - network->signal_network_altered().connect(wifi_cb); + signals.push_back(network->signal_network_altered().connect(wifi_cb)); wifi_cb(); } else if (wired) { @@ -114,11 +125,11 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): /* Click toggles connection on/off */ auto click = Gtk::GestureClick::create(); - click->signal_released().connect( + signals.push_back(click->signal_released().connect( [network] (int, double, double) { network->toggle(); } - ); + )); label.add_controller(click); /* Set label and image based on friendly info */ @@ -133,7 +144,7 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): label.remove_css_class("active"); } }; - network->signal_network_altered().connect(network_change_cb); + signals.push_back(network->signal_network_altered().connect(network_change_cb)); network_change_cb(); } @@ -143,8 +154,8 @@ void DeviceControlWidget::remove_access_point(std::string path){ if (widget) { revealer_box.remove(*widget); - access_points.erase(path); } + access_points.erase(path); } void DeviceControlWidget::add_access_point(std::shared_ptr ap) @@ -158,16 +169,21 @@ void DeviceControlWidget::add_access_point(std::shared_ptr ap) { return; } - access_points.emplace(path, new AccessPointWidget(path, ap)); + auto success = access_points.emplace(path, new AccessPointWidget(path, ap)); + if (!success.second){ + std::cerr << "Unable to insert Access Point "<< path<< success.first->first << std::endl; + exit(1); + } auto widget = access_points[path]; auto click = Gtk::GestureClick::create(); - click->signal_released().connect( + auto sig = click->signal_released().connect( [this, path] (int, double, double) { selected_access_point(path); } ); widget->add_controller(click); + widget->signals.push_back(sig); revealer_box.append(*access_points[path]); } @@ -191,26 +207,39 @@ void DeviceControlWidget::selected_access_point(std::string path) } } +DeviceControlWidget::~DeviceControlWidget() +{ + access_points.clear(); + network = nullptr; + for (auto signal : signals) + { + signal.disconnect(); + } +} + NetworkControlWidget::NetworkControlWidget() { + append(network_manager_failed); + /* Default state is no NM found */ + network_manager_failed.set_label("Network Manager is not running"); + top.hide(); add_css_class("network-control-center"); set_orientation(Gtk::Orientation::VERTICAL); network_manager = NetworkManager::getInstance(); - network_manager->signal_device_added().connect( + signals.push_back(network_manager->signal_nm_start().connect( + sigc::mem_fun(*this, &NetworkControlWidget::nm_start) + )); + signals.push_back(network_manager->signal_nm_stop().connect( + sigc::mem_fun(*this, &NetworkControlWidget::nm_stop) + )); + signals.push_back(network_manager->signal_device_added().connect( sigc::mem_fun(*this, &NetworkControlWidget::add_device) - ); - - network_manager->signal_device_removed().connect( + )); + signals.push_back(network_manager->signal_device_removed().connect( sigc::mem_fun(*this, &NetworkControlWidget::remove_device) - ); - - /* Fill already existing devices */ + )); - for (auto &device : network_manager->get_all_devices()) - { - add_device(device.second); - } top.append(global_networking); top.append(wifi_networking); top.append(mobile_networking); @@ -228,79 +257,64 @@ NetworkControlWidget::NetworkControlWidget() wifi_networking.set_label("Wifi"); mobile_networking.set_label("Mobile"); + /* Connect to global widget cb */ signal_network = global_networking.signal_toggled().connect( [this] () { network_manager->networking_global_set(global_networking.get_active()); } ); - signal_wifi = wifi_networking.signal_toggled().connect( [this] () { network_manager->wifi_global_set(wifi_networking.get_active()); } ); - signal_mobile = mobile_networking.signal_toggled().connect( [this] () { network_manager->mobile_global_set(mobile_networking.get_active()); } ); - - /* Global killswitches from NM proper */ - auto global_cb = - [this] () { - auto [wifi_soft, wifi_hard] = network_manager->wifi_global_enabled(); - auto [mobile_soft, mobile_hard] = network_manager->mobile_global_enabled(); - auto global = network_manager->networking_global_enabled(); - if (!wifi_hard) - { - wifi_networking.set_label("Wifi ✈"); - signal_wifi.block(true); - wifi_networking.set_active(false); - signal_wifi.unblock(); - } else if(!wifi_soft) - { - wifi_networking.set_label("Wifi"); - signal_wifi.block(true); - wifi_networking.set_active(false); - signal_wifi.unblock(); - } else { - wifi_networking.set_label("Wifi"); - signal_wifi.block(true); - wifi_networking.set_active(true); - signal_wifi.unblock(); - } - if(!mobile_hard) - { - mobile_networking.set_label("Mobile ✈"); - signal_mobile.block(true); - mobile_networking.set_active(false); - signal_mobile.unblock(); - } else if(!mobile_soft) - { - mobile_networking.set_label("Mobile"); - signal_mobile.block(true); - mobile_networking.set_active(false); - signal_mobile.unblock(); - } else { - mobile_networking.set_label("Mobile"); - signal_mobile.block(true); - mobile_networking.set_active(true); - signal_mobile.unblock(); - } - signal_network.block(true); - global_networking.set_active(global); - signal_network.unblock(); - }; + /* Connect changes to global state in NM */ + signals.push_back(network_manager->signal_global_toggle().connect( + sigc::mem_fun(*this, &NetworkControlWidget::update_globals))); - network_manager->signal_global_toggle().connect(global_cb); - global_cb(); +} - for (auto &it : network_manager->get_all_vpns()) +void NetworkControlWidget::update_globals() +{ + auto [wifi_soft, wifi_hard] = network_manager->wifi_global_enabled(); + auto [mobile_soft, mobile_hard] = network_manager->mobile_global_enabled(); + auto global = network_manager->networking_global_enabled(); + signal_wifi.block(true); + signal_mobile.block(true); + signal_network.block(true); + if (!wifi_hard) { - add_vpn(it.second); + wifi_networking.set_label("Wifi ✈"); + wifi_networking.set_active(false); + } else if(!wifi_soft) + { + wifi_networking.set_label("Wifi"); + wifi_networking.set_active(false); + } else { + wifi_networking.set_label("Wifi"); + wifi_networking.set_active(true); } - + if(!mobile_hard) + { + mobile_networking.set_label("Mobile ✈"); + mobile_networking.set_active(false); + } else if(!mobile_soft) + { + mobile_networking.set_label("Mobile"); + mobile_networking.set_active(false); + } else { + mobile_networking.set_label("Mobile"); + mobile_networking.set_active(true); + } + global_networking.set_active(global); + signal_wifi.unblock(); + signal_mobile.unblock(); + signal_network.unblock(); } void NetworkControlWidget::add_vpn(std::shared_ptr config) @@ -309,7 +323,7 @@ void NetworkControlWidget::add_vpn(std::shared_ptr config) vpn_widgets.emplace(config->path, widget); auto click = Gtk::GestureClick::create(); - click->signal_released().connect( + auto sig = click->signal_released().connect( [this, config] (int, double, double) { auto primary = network_manager->get_primary_network(); if (primary->has_vpn) @@ -321,6 +335,7 @@ void NetworkControlWidget::add_vpn(std::shared_ptr config) } ); widget->add_controller(click); + widget->signals.push_back(sig); vpn_box.append(*widget); } @@ -356,17 +371,63 @@ void NetworkControlWidget::add_device(std::shared_ptr network) } else { std::cout << "Unknown network type : " << widget->type << std::endl; } - } void NetworkControlWidget::remove_device(std::shared_ptr network) { auto widget = widgets[network->get_path()]; - /* TODO Remove warnings by checking? */ - wifi_box.remove(*widget); - mobile_box.remove(*widget); - wire_box.remove(*widget); - vpn_box.remove(*widget); - bt_box.remove(*widget); + if (widget->type == "wifi") + { + wifi_box.remove(*widget); + } else if (widget->type == "mobile") + { + mobile_box.remove(*widget); + } else if (widget->type == "wired") + { + wire_box.remove(*widget); + } else if (widget->type == "bt") + { + bt_box.remove(*widget); + } else { + std::cout << "Unknown network type : " << widget->type << std::endl; + } widgets.erase(network->get_path()); +} + +void NetworkControlWidget::nm_start() +{ + network_manager_failed.hide(); + top.show(); + /* Fill already existing devices */ + for (auto &device : network_manager->get_all_devices()) + { + add_device(device.second); + } + for (auto &it : network_manager->get_all_vpns()) + { + add_vpn(it.second); + } + update_globals(); +} +void NetworkControlWidget::nm_stop() +{ + network_manager_failed.show(); + top.hide(); + widgets.clear(); + for (auto &it : vpn_widgets) + { + vpn_box.remove(*it.second); + } + vpn_widgets.clear(); +} + +NetworkControlWidget::~NetworkControlWidget() +{ + signal_network.disconnect(); + signal_mobile.disconnect(); + signal_wifi.disconnect(); + for (auto signal : signals) + { + signal.disconnect(); + } } \ No newline at end of file diff --git a/src/util/network/network-widget.hpp b/src/util/network/network-widget.hpp index f728ab42..dab1f8e2 100644 --- a/src/util/network/network-widget.hpp +++ b/src/util/network/network-widget.hpp @@ -15,8 +15,8 @@ class AccessPointWidget : public Gtk::Box Gtk::Label label; std::shared_ptr ap; std::string path; - sigc::connection signal; public: + std::vector signals; AccessPointWidget(std::string path, std::shared_ptr ap); ~AccessPointWidget(); }; @@ -30,8 +30,10 @@ class DeviceControlWidget : public Gtk::Box Gtk::Image image; Gtk::Revealer revealer; Gtk::Box revealer_box, topbox; + std::vector signals; public: DeviceControlWidget(std::shared_ptr network); + ~DeviceControlWidget(); void add_access_point(std::shared_ptr ap); void remove_access_point(std::string path); void selected_access_point(std::string path); @@ -46,21 +48,30 @@ class VPNControlWidget : public Gtk::Box Gtk::Image image; Gtk::Label label; public: + std::vector signals; + VPNControlWidget(std::shared_ptr config); + ~VPNControlWidget(); }; class NetworkControlWidget : public Gtk::Box { + Gtk::Label network_manager_failed; Gtk::Box wire_box, wifi_box, mobile_box, vpn_box, bt_box, top; Gtk::CheckButton global_networking, wifi_networking, mobile_networking; std::map > widgets; std::map > vpn_widgets; sigc::connection signal_network, signal_wifi, signal_mobile; + std::vector signals; public: NetworkControlWidget(); + ~NetworkControlWidget(); std::shared_ptr network_manager; + void update_globals(); void add_device(std::shared_ptr network); void remove_device(std::shared_ptr network); void add_vpn(std::shared_ptr config); void remove_vpn(std::string path); + void nm_start(); + void nm_stop(); }; \ No newline at end of file diff --git a/src/util/network/network.cpp b/src/util/network/network.cpp index 81efd609..deb5ade0 100644 --- a/src/util/network/network.cpp +++ b/src/util/network/network.cpp @@ -18,7 +18,7 @@ Network::Network(std::string path, std::shared_ptr in_proxy): interface = val.get(); } /* Any change of state */ - device_proxy->signal_signal().connect( + signals.push_back(device_proxy->signal_signal().connect( [this] (const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) { if (signal == "StateChanged") { @@ -30,9 +30,9 @@ Network::Network(std::string path, std::shared_ptr in_proxy): network_altered.emit(); } } - }); + })); - device_proxy->signal_properties_changed().connect( + signals.push_back(device_proxy->signal_properties_changed().connect( [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { for (auto &it : properties) { @@ -42,12 +42,15 @@ Network::Network(std::string path, std::shared_ptr in_proxy): } } } - ); + )); } Network::~Network() { - + for(auto signal : signals) + { + signal.disconnect(); + } } std::string Network::get_friendly_name() diff --git a/src/util/network/network.hpp b/src/util/network/network.hpp index 8b7a5d06..92ab5ca2 100644 --- a/src/util/network/network.hpp +++ b/src/util/network/network.hpp @@ -1,4 +1,5 @@ #pragma once +#include "sigc++/connection.h" #include #include #include @@ -24,6 +25,7 @@ class Network { protected: type_signal_network_altered network_altered; std::string network_path; + std::vector signals; public: type_signal_network_altered signal_network_altered(); std::shared_ptr device_proxy; diff --git a/src/util/network/wifi-ap.cpp b/src/util/network/wifi-ap.cpp index 8e2ad7c2..e087712a 100644 --- a/src/util/network/wifi-ap.cpp +++ b/src/util/network/wifi-ap.cpp @@ -18,7 +18,7 @@ AccessPoint::AccessPoint(std::string path, std::shared_ptr acc auto ssid_bytes = ssid_start.get(); ssid = std::string(ssid_bytes.begin(), ssid_bytes.end()); - access_point_proxy->signal_properties_changed().connect( + signals.push_back(access_point_proxy->signal_properties_changed().connect( [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { for (auto &it : properties) { @@ -35,7 +35,7 @@ AccessPoint::AccessPoint(std::string path, std::shared_ptr acc } } } - ); + )); } @@ -77,4 +77,12 @@ std::string AccessPoint::get_icon_name() type_signal_network_altered AccessPoint::signal_altered() { return access_point_altered; +} + +AccessPoint::~AccessPoint() +{ + for(auto signal : signals) + { + signal.disconnect(); + } } \ No newline at end of file diff --git a/src/util/network/wifi-ap.hpp b/src/util/network/wifi-ap.hpp index e5e15410..ab6ebded 100644 --- a/src/util/network/wifi-ap.hpp +++ b/src/util/network/wifi-ap.hpp @@ -1,4 +1,5 @@ #pragma once +#include "sigc++/connection.h" #include #include @@ -10,10 +11,12 @@ class AccessPoint { type_signal_access_point_altered access_point_altered; unsigned char strength; std::string ssid=""; + std::vector signals; public: std::string get_path(); std::shared_ptr access_point_proxy; AccessPoint(std::string path, std::shared_ptr access_point_proxy); + ~AccessPoint(); std::string get_ssid(); std::string strength_string(); std::string get_icon_name(); diff --git a/src/util/network/wifi.cpp b/src/util/network/wifi.cpp index 7d09cb9a..149aadcd 100644 --- a/src/util/network/wifi.cpp +++ b/src/util/network/wifi.cpp @@ -26,8 +26,7 @@ void WifiNetwork::add_access_point(std::string path) "org.freedesktop.NetworkManager", path, "org.freedesktop.NetworkManager.AccessPoint"); - auto new_ap = std::make_shared(path, ap_proxy); - all_access_points[path] = new_ap; + all_access_points.emplace(path, std::make_shared(path, ap_proxy)); } void WifiNetwork::remove_access_point(std::string path) @@ -38,7 +37,7 @@ void WifiNetwork::remove_access_point(std::string path) WifiNetwork::WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy): Network(path, device_proxy), wifi_proxy(wifi_proxy) { - wifi_proxy->signal_signal().connect( + signals.push_back(wifi_proxy->signal_signal().connect( [this] (const Glib::ustring& source, const Glib::ustring& signal , const Glib::VariantContainerBase& value) { if (signal == "AccessPointAdded") { @@ -52,9 +51,9 @@ WifiNetwork::WifiNetwork(std::string path, std::shared_ptr dev all_access_points.erase(val); } } - ); + )); - wifi_proxy->signal_properties_changed().connect( + signals.push_back(wifi_proxy->signal_properties_changed().connect( [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { for (auto &it : properties) { @@ -79,7 +78,7 @@ WifiNetwork::WifiNetwork(std::string path, std::shared_ptr dev } } } - ); + )); /* Initial values */ Glib::Variant> base; wifi_proxy->get_cached_property(base, "AccessPoints"); @@ -91,11 +90,11 @@ WifiNetwork::WifiNetwork(std::string path, std::shared_ptr dev auto access_point = get_current_access_point(); if (access_point) { - access_point_signal = access_point->signal_altered().connect( + signals.push_back(access_point_signal = access_point->signal_altered().connect( [this]() { network_altered.emit(); } - ); + )); } } @@ -150,3 +149,15 @@ std::string WifiNetwork::get_current_access_point_path() return ap_name.get(); } +WifiNetwork::~WifiNetwork() +{ + all_access_points.clear(); + if(access_point_signal) + { + access_point_signal.disconnect(); + } + for (auto signal : signals) + { + signal.disconnect(); + } +} \ No newline at end of file diff --git a/src/util/network/wifi.hpp b/src/util/network/wifi.hpp index 8a755e1f..d8cf7def 100644 --- a/src/util/network/wifi.hpp +++ b/src/util/network/wifi.hpp @@ -19,16 +19,14 @@ class WifiNetwork : public Network { protected: std::shared_ptr wifi_proxy; public: + WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy); + ~WifiNetwork(); type_signal_access_point signal_add_access_point(); type_signal_access_point signal_remove_access_point(); - std::map> get_access_points(); - void add_access_point(std::string path); void remove_access_point(std::string path); - - WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy); std::string get_name() override; std::string get_color_name() override; std::string get_icon_name() override; From 61b71e7898b8a02a136608802cc9dcba76acfe00 Mon Sep 17 00:00:00 2001 From: trigg Date: Wed, 4 Feb 2026 20:53:46 +0000 Subject: [PATCH 05/17] - watch for ModemManager appearing/disappearing --- src/panel/widgets/network.cpp | 11 ----------- src/panel/widgets/network.hpp | 1 - src/util/network/manager.cpp | 18 ++++++++++++++++++ src/util/network/manager.hpp | 6 +++--- src/util/network/network-widget.cpp | 17 +++++++++++++++++ src/util/network/network-widget.hpp | 2 ++ src/util/network/wifi.cpp | 1 - src/util/network/wifi.hpp | 1 - 8 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 0ade3dee..312b2d75 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -1,10 +1,7 @@ #include "network.hpp" -#include "glib.h" -#include "glibmm/main.h" #include "network/network.hpp" #include #include -#include #include #include @@ -13,14 +10,6 @@ WayfireNetworkInfo::WayfireNetworkInfo() } -void WayfireNetworkInfo::on_click() -{ - if ((std::string)click_command_opt != "default") - { - Glib::spawn_command_line_async((std::string)click_command_opt); - } -} - void WayfireNetworkInfo::init(Gtk::Box *container) { network_manager = NetworkManager::getInstance(); diff --git a/src/panel/widgets/network.hpp b/src/panel/widgets/network.hpp index 042690ef..d2983bae 100644 --- a/src/panel/widgets/network.hpp +++ b/src/panel/widgets/network.hpp @@ -31,6 +31,5 @@ class WayfireNetworkInfo : public WayfireWidget WayfireNetworkInfo(); ~WayfireNetworkInfo(); void init(Gtk::Box *container); - void on_click(); void set_connection(std::shared_ptr network); }; diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index 191b33ba..02e6ae69 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -13,6 +13,7 @@ #include "wired.hpp" #include "null.hpp" #define NM_DBUS_NAME "org.freedesktop.NetworkManager" +#define MM_DBUS_NAME "org.freedesktop.ModemManager1" #define ACTIVE_CONNECTION "PrimaryConnection" #define STRENGTH "Strength" @@ -70,6 +71,23 @@ NetworkManager::NetworkManager() { lost_nm(); } + } else if (name.get() == MM_DBUS_NAME) + { + if (from.get() == "") + { + mm_start.emit(); + } else if (to.get() == "") + { + for_each(all_devices.cbegin(), all_devices.cend(), + [this] (std::map>::const_reference it){ + if(std::dynamic_pointer_cast(it.second) != nullptr) + { + device_removed.emit(it.second); + all_devices.erase(it.first); + } + }); + mm_stop.emit(); + } } } })); diff --git a/src/util/network/manager.hpp b/src/util/network/manager.hpp index 2909126e..5f13b7bc 100644 --- a/src/util/network/manager.hpp +++ b/src/util/network/manager.hpp @@ -9,7 +9,6 @@ #include "network.hpp" #include "connection.hpp" -#include "network/null.hpp" #include "vpn.hpp" using type_signal_network = sigc::signal)>; @@ -22,7 +21,7 @@ class NetworkManager private: type_signal_network default_changed, device_added, device_removed; type_signal_device_list_changed device_list_changed; - type_signal_simple global_change, nm_start, nm_stop; + type_signal_simple global_change, nm_start, nm_stop, mm_start, mm_stop; type_signal_path vpn_added, vpn_removed; @@ -47,7 +46,6 @@ class NetworkManager void changed_primary(std::string path); void connect_nm(); void lost_nm(); - public: /* Emitted when the default connection or it's properties change */ type_signal_network signal_default_changed() { return default_changed; } @@ -63,6 +61,8 @@ class NetworkManager type_signal_path signal_vpn_removed() { return vpn_removed; } type_signal_simple signal_nm_start() { return nm_start; } type_signal_simple signal_nm_stop() { return nm_stop; } + type_signal_simple signal_mm_start() { return mm_start; } + type_signal_simple signal_mm_stop() { return mm_stop; } std::shared_ptr get_nm_proxy() { return nm_proxy; } /* A list of current networks. */ diff --git a/src/util/network/network-widget.cpp b/src/util/network/network-widget.cpp index 951c9644..4d69a716 100644 --- a/src/util/network/network-widget.cpp +++ b/src/util/network/network-widget.cpp @@ -233,6 +233,12 @@ NetworkControlWidget::NetworkControlWidget() signals.push_back(network_manager->signal_nm_stop().connect( sigc::mem_fun(*this, &NetworkControlWidget::nm_stop) )); + signals.push_back(network_manager->signal_mm_start().connect( + sigc::mem_fun(*this, &NetworkControlWidget::mm_start) + )); + signals.push_back(network_manager->signal_mm_stop().connect( + sigc::mem_fun(*this, &NetworkControlWidget::mm_stop) + )); signals.push_back(network_manager->signal_device_added().connect( sigc::mem_fun(*this, &NetworkControlWidget::add_device) )); @@ -256,6 +262,7 @@ NetworkControlWidget::NetworkControlWidget() global_networking.set_label("Networking"); wifi_networking.set_label("Wifi"); mobile_networking.set_label("Mobile"); + mobile_networking.hide(); /* Connect to global widget cb */ signal_network = global_networking.signal_toggled().connect( @@ -421,6 +428,16 @@ void NetworkControlWidget::nm_stop() vpn_widgets.clear(); } +void NetworkControlWidget::mm_start() +{ + mobile_networking.show(); +} + +void NetworkControlWidget::mm_stop() +{ + mobile_networking.hide(); +} + NetworkControlWidget::~NetworkControlWidget() { signal_network.disconnect(); diff --git a/src/util/network/network-widget.hpp b/src/util/network/network-widget.hpp index dab1f8e2..85bef8f9 100644 --- a/src/util/network/network-widget.hpp +++ b/src/util/network/network-widget.hpp @@ -74,4 +74,6 @@ class NetworkControlWidget : public Gtk::Box void remove_vpn(std::string path); void nm_start(); void nm_stop(); + void mm_start(); + void mm_stop(); }; \ No newline at end of file diff --git a/src/util/network/wifi.cpp b/src/util/network/wifi.cpp index 149aadcd..974963dd 100644 --- a/src/util/network/wifi.cpp +++ b/src/util/network/wifi.cpp @@ -1,7 +1,6 @@ #include #include -#include "manager.hpp" #include "wifi-ap.hpp" #include "wifi.hpp" diff --git a/src/util/network/wifi.hpp b/src/util/network/wifi.hpp index d8cf7def..45e63fb0 100644 --- a/src/util/network/wifi.hpp +++ b/src/util/network/wifi.hpp @@ -1,6 +1,5 @@ #pragma once #include -#include #include #include #include From 667ab0c73fb353467891928c6b6bc13158ce0efc Mon Sep 17 00:00:00 2001 From: trigg Date: Wed, 4 Feb 2026 21:08:30 +0000 Subject: [PATCH 06/17] - Set initial state of MM --- src/util/network/manager.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index 02e6ae69..158a7415 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -48,6 +48,10 @@ NetworkManager::NetworkManager() { connect_nm(); } + if (t == MM_DBUS_NAME) + { + mm_start.emit(); + } } /* https://dbus.freedesktop.org/doc/dbus-java/api/org/freedesktop/DBus.NameOwnerChanged.html */ From 67228421040f512635e237fa55d715b0547e2ea0 Mon Sep 17 00:00:00 2001 From: trigg Date: Wed, 4 Feb 2026 23:25:00 +0000 Subject: [PATCH 07/17] uncrust --- src/panel/widgets/network.cpp | 9 +- src/panel/widgets/network.hpp | 3 +- src/util/network/bluetooth.hpp | 16 +- src/util/network/connection.hpp | 44 +++-- src/util/network/manager.cpp | 200 ++++++++++++---------- src/util/network/manager.hpp | 105 +++++++++--- src/util/network/modem.cpp | 40 +++-- src/util/network/modem.hpp | 10 +- src/util/network/network-widget.cpp | 249 +++++++++++++++------------- src/util/network/network-widget.hpp | 21 ++- src/util/network/network.cpp | 61 ++++--- src/util/network/network.hpp | 16 +- src/util/network/null.hpp | 11 +- src/util/network/vpn.hpp | 16 +- src/util/network/wifi-ap.cpp | 43 ++--- src/util/network/wifi-ap.hpp | 6 +- src/util/network/wifi.cpp | 102 +++++++----- src/util/network/wifi.hpp | 10 +- src/util/network/wired.cpp | 10 +- src/util/network/wired.hpp | 5 +- 20 files changed, 565 insertions(+), 412 deletions(-) diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 312b2d75..4ecd21a8 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -6,9 +6,7 @@ #include WayfireNetworkInfo::WayfireNetworkInfo() -{ - -} +{} void WayfireNetworkInfo::init(Gtk::Box *container) { @@ -32,8 +30,7 @@ void WayfireNetworkInfo::init(Gtk::Box *container) icon.set_valign(Gtk::Align::CENTER); signals.push_back(network_manager->signal_default_changed().connect( - sigc::mem_fun(*this,&WayfireNetworkInfo::set_connection) - )); + sigc::mem_fun(*this, &WayfireNetworkInfo::set_connection))); set_connection(network_manager->get_primary_network()); } @@ -44,7 +41,7 @@ void WayfireNetworkInfo::set_connection(std::shared_ptr network) status.remove_css_class("bad"); status.remove_css_class("ok"); status.remove_css_class("excellent"); - + status.set_label(network->get_name()); icon.set_from_icon_name(network->get_icon_symbolic()); auto color = network->get_color_name(); diff --git a/src/panel/widgets/network.hpp b/src/panel/widgets/network.hpp index d2983bae..c7b85fae 100644 --- a/src/panel/widgets/network.hpp +++ b/src/panel/widgets/network.hpp @@ -25,8 +25,9 @@ class WayfireNetworkInfo : public WayfireWidget WfOption status_color_opt{"panel/network_status_use_color"}; WfOption status_font_opt{"panel/network_status_font"}; WfOption click_command_opt{"panel/network_onclick_command"}; - + NetworkControlWidget control; + public: WayfireNetworkInfo(); ~WayfireNetworkInfo(); diff --git a/src/util/network/bluetooth.hpp b/src/util/network/bluetooth.hpp index f9e6d580..36e06ba9 100644 --- a/src/util/network/bluetooth.hpp +++ b/src/util/network/bluetooth.hpp @@ -1,18 +1,17 @@ -#pragma once +#pragma once #include #include #include "network.hpp" -class BluetoothNetwork : public Network +class BluetoothNetwork : public Network { public: std::shared_ptr bluetooth_proxy; - BluetoothNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr bluetooth_proxy): + BluetoothNetwork(std::string path, std::shared_ptr device_proxy, + std::shared_ptr bluetooth_proxy) : Network(path, device_proxy), bluetooth_proxy(bluetooth_proxy) - { - - } + {} std::string get_name() override { @@ -21,10 +20,11 @@ class BluetoothNetwork : public Network std::string get_icon_name() override { - if(is_active()) + if (is_active()) { return "network-bluetooth-activated"; } + return "network-bluetooth-inactive"; } @@ -37,4 +37,4 @@ class BluetoothNetwork : public Network { return "Bluetooth"; } -}; \ No newline at end of file +}; diff --git a/src/util/network/connection.hpp b/src/util/network/connection.hpp index a6a79fcc..ddafcd7a 100644 --- a/src/util/network/connection.hpp +++ b/src/util/network/connection.hpp @@ -6,29 +6,30 @@ #include "network.hpp" /* Information about an active connection */ -class Connection : public Network { +class Connection : public Network +{ public: bool has_vpn; std::vector signals; std::shared_ptr connection_proxy, vpn_proxy; std::vector> devices; - Connection(): + Connection() : Network("/", nullptr), connection_proxy(nullptr), devices({}) - { + {} - } - Connection(std::string path, std::shared_ptr connection_proxy, std::vector> devices): + Connection(std::string path, std::shared_ptr connection_proxy, + std::vector> devices) : Network(path, nullptr), connection_proxy(connection_proxy), devices(devices) { /* Bubble up emits from any device here */ - for(auto &it : devices) + for (auto & it : devices) { signals.push_back(it->signal_network_altered().connect( - [this] () { - network_altered.emit(); - } - )); + [this] () + { + network_altered.emit(); + })); } Glib::Variant vpn_data; @@ -38,44 +39,51 @@ class Connection : public Network { ~Connection() { - for (auto signal : signals){ + for (auto signal : signals) + { signal.disconnect(); } } std::string get_name() { - if (devices.size() ==0) + if (devices.size() == 0) { return "No connection"; } + std::string secure = ""; if (has_vpn) { secure = " with VPN"; } - return devices[0]->get_name()+secure; + + return devices[0]->get_name() + secure; } - std::string get_icon_name(){ + std::string get_icon_name() + { if (devices.size() == 0) { return "network-disconnected"; } + std::string secure = ""; if (has_vpn) { secure = "-secure"; } - return devices[0]->get_icon_name()+secure; + + return devices[0]->get_icon_name() + secure; } - std::string get_color_name(){ + std::string get_color_name() + { if (devices.size() == 0) { return "none"; } + return devices[0]->get_color_name(); } - -}; \ No newline at end of file +}; diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index 158a7415..89f9bc4e 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -48,6 +48,7 @@ NetworkManager::NetworkManager() { connect_nm(); } + if (t == MM_DBUS_NAME) { mm_start.emit(); @@ -82,13 +83,14 @@ NetworkManager::NetworkManager() mm_start.emit(); } else if (to.get() == "") { - for_each(all_devices.cbegin(), all_devices.cend(), - [this] (std::map>::const_reference it){ - if(std::dynamic_pointer_cast(it.second) != nullptr) - { - device_removed.emit(it.second); - all_devices.erase(it.first); - } + for_each(all_devices.cbegin(), all_devices.cend(), + [this] (std::map>::const_reference it) + { + if (std::dynamic_pointer_cast(it.second) != nullptr) + { + device_removed.emit(it.second); + all_devices.erase(it.first); + } }); mm_stop.emit(); } @@ -101,29 +103,36 @@ NetworkManager::NetworkManager() void NetworkManager::lost_nm() { if (primary_signal) + { primary_signal.disconnect(); + } + if (debounce) + { debounce.disconnect(); + } + std::cout << "NetworkManager Lost" << std::endl; - connection = nullptr; + connection = nullptr; settings_proxy = nullptr; nm_proxy = nullptr; all_devices.clear(); all_vpns.clear(); - primary_connection = "/"; + primary_connection = "/"; primary_connection_obj = std::make_shared(); for (auto signal : nm_signals) { signal.disconnect(); } + nm_stop.emit(); } void NetworkManager::connect_nm() { std::cout << "NetworkManager Found" << std::endl; - all_devices.emplace("/", new NullNetwork()); - connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::SYSTEM); + all_devices.emplace("/", new NullNetwork()); + connection = Gio::DBus::Connection::get_sync(Gio::DBus::BusType::SYSTEM); if (!connection) { std::cerr << "Failed to connect to dbus" << std::endl; @@ -140,29 +149,34 @@ void NetworkManager::connect_nm() std::cerr << "No NM Settings proxy" << std::endl; return; } + auto ret1 = settings_proxy->call_sync("ListConnections").get_child(); - Glib::Variant> ret = Glib::VariantBase::cast_dynamic>>(ret1); - for (auto &it : ret.get()){ + Glib::Variant> ret = + Glib::VariantBase::cast_dynamic>>(ret1); + for (auto & it : ret.get()) + { check_add_vpn(it); vpn_added.emit(it); } nm_signals.push_back(settings_proxy->signal_signal().connect( - [this] (const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) { - if (signal == "ConnectionRemoved") - { - auto var = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); - all_vpns.erase(var); - vpn_removed.emit(var); - } else if (signal == "NewConnection") - { - auto var = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); - check_add_vpn(var); - vpn_added.emit(var); - } + [this] (const Glib::ustring& sender, const Glib::ustring& signal, + const Glib::VariantContainerBase& container) + { + if (signal == "ConnectionRemoved") + { + auto var = + Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + all_vpns.erase(var); + vpn_removed.emit(var); + } else if (signal == "NewConnection") + { + auto var = + Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + check_add_vpn(var); + vpn_added.emit(var); } - )); - + })); nm_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, NM_PATH, @@ -176,7 +190,7 @@ void NetworkManager::connect_nm() nm_signals.push_back(nm_proxy->signal_properties_changed().connect( sigc::mem_fun(*this, &NetworkManager::on_nm_properties_changed))); - + nm_signals.push_back(nm_proxy->signal_signal().connect( sigc::mem_fun(*this, &NetworkManager::on_nm_signal))); @@ -190,14 +204,14 @@ void NetworkManager::check_add_vpn(std::string path) auto proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, path, - "org.freedesktop.NetworkManager.Settings.Connection" - ); + "org.freedesktop.NetworkManager.Settings.Connection"); - auto values = Glib::VariantBase::cast_dynamic>>>(proxy->call_sync("GetSettings").get_child()); + auto values = Glib::VariantBase::cast_dynamic>>>(proxy->call_sync("GetSettings").get_child()); auto hash = values.get(); - if (hash.count("connection")==1 && hash["connection"].count("id")==1 && - hash["connection"].count("type")==1) + if ((hash.count("connection") == 1) && (hash["connection"].count("id") == 1) && + (hash["connection"].count("type") == 1)) { auto contype = hash["connection"]["type"]; auto conname = hash["connection"]["id"]; @@ -206,25 +220,30 @@ void NetworkManager::check_add_vpn(std::string path) { auto name = Glib::VariantBase::cast_dynamic>(conname).get(); auto contype_str = Glib::VariantBase::cast_dynamic>(contype).get(); - if(contype_str == "vpn") + if (contype_str == "vpn") { all_vpns[path] = std::make_shared(path, proxy, name); } - } else { - std::cerr << "INVALID TYPES "<< conname.get_type_string() << " " << contype.get_type_string()< async) { - auto list = Glib::VariantBase::cast_dynamic>> (nm_proxy->call_finish(async).get_child()).get(); - for (auto &val : list) + auto list = Glib::VariantBase::cast_dynamic>>(nm_proxy->call_finish( + async).get_child()).get(); + for (auto & val : list) { - add_network(val); + add_network(val); } + /* Now get the current connection */ - nm_signals.push_back(Glib::signal_idle().connect([this] () { + nm_signals.push_back(Glib::signal_idle().connect([this] () + { Glib::Variant path_read; nm_proxy->get_cached_property(path_read, "PrimaryConnection"); changed_primary(path_read.get()); @@ -234,12 +253,12 @@ void NetworkManager::get_all_devices_cb(std::shared_ptr async) nm_start.emit(); } -void NetworkManager::add_network(std::string path){ +void NetworkManager::add_network(std::string path) +{ Glib::RefPtr device_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, path, - "org.freedesktop.NetworkManager.Device" - ); + "org.freedesktop.NetworkManager.Device"); Glib::Variant type; device_proxy->get_cached_property(type, "DeviceType"); uint connection_type = type.get(); @@ -249,7 +268,7 @@ void NetworkManager::add_network(std::string path){ NM_DBUS_NAME, path, "org.freedesktop.NetworkManager.Device.Wireless"); - all_devices.emplace(path, new WifiNetwork(path, device_proxy, wifi_proxy)); + all_devices.emplace(path, new WifiNetwork(path, device_proxy, wifi_proxy)); device_added.emit(all_devices[path]); } else if (connection_type == MODEM_TYPE) { @@ -261,7 +280,7 @@ void NetworkManager::add_network(std::string path){ device_added.emit(all_devices[path]); } else if (connection_type == BLUETOOTH_TYPE) { - auto bluetooth_proxy =Gio::DBus::Proxy::create_sync(connection, + auto bluetooth_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, path, "org.freedesktop.NetworkManager.Devices.Bluetooth"); @@ -274,16 +293,18 @@ void NetworkManager::add_network(std::string path){ } } -void NetworkManager::on_nm_properties_changed(const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) +void NetworkManager::on_nm_properties_changed(const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated) { - for (auto &it : properties) + for (auto & it : properties) { if (it.first == "PrimaryConnection") { auto value = Glib::VariantBase::cast_dynamic>(it.second).get(); changed_primary(value); - } else if (it.first == "NetworkingEnabled" || it.first == "WirelessEnabled" || it.first == "WirelessHardwareEnabled" || - it.first == "WwanEnabled" || it.first == "WwanHardwareEnabled") + } else if ((it.first == "NetworkingEnabled") || (it.first == "WirelessEnabled") || + (it.first == "WirelessHardwareEnabled") || + (it.first == "WwanEnabled") || (it.first == "WwanHardwareEnabled")) { global_change.emit(); } @@ -298,45 +319,45 @@ void NetworkManager::changed_primary(std::string value) { primary_signal.disconnect(); } + primary_connection = value; auto network = get_connection(value); primary_connection_obj = network; /* Any change inside the primary connection also called default_changed */ primary_signal = network->signal_network_altered().connect( - [this, network] () { - default_changed.emit(network); - } - ); + [this, network] () + { + default_changed.emit(network); + }); /* Tell clients */ default_changed.emit(network); - } } - std::shared_ptr NetworkManager::get_connection(std::string path) { auto connection_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, path, - "org.freedesktop.NetworkManager.Connection.Active" - ); + "org.freedesktop.NetworkManager.Connection.Active"); std::vector> list; Glib::Variant> paths; connection_proxy->get_cached_property(paths, "Devices"); if (paths) { - for (auto &it : paths.get()) + for (auto & it : paths.get()) { list.push_back(all_devices[it]); } } + return std::make_shared(path, connection_proxy, list); } -void NetworkManager::on_nm_signal(const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) +void NetworkManager::on_nm_signal(const Glib::ustring& sender, const Glib::ustring& signal, + const Glib::VariantContainerBase& container) { if (signal == "DeviceAdded") { @@ -346,16 +367,19 @@ void NetworkManager::on_nm_signal(const Glib::ustring& sender, const Glib::ustri { auto val = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); all_devices.erase(val); - } else + } else { return; } + /* NM list changed, but let's not send instantly */ if (debounce) { debounce.disconnect(); } - debounce = Glib::signal_timeout().connect([this] () { + + debounce = Glib::signal_timeout().connect([this] () + { signal_device_list_changed().emit(all_devices); return G_SOURCE_REMOVE; }, 100); @@ -369,19 +393,21 @@ std::shared_ptr NetworkManager::get_primary_network() void NetworkManager::activate_connection(std::string p1, std::string p2, std::string p3) { auto manager = NetworkManager::getInstance()->get_nm_proxy(); - Glib::VariantStringBase path1,path2,path3; + Glib::VariantStringBase path1, path2, path3; Glib::VariantStringBase::create_object_path(path1, p1); Glib::VariantStringBase::create_object_path(path2, p2); Glib::VariantStringBase::create_object_path(path3, p3); auto paths = Glib::VariantContainerBase::create_tuple({path1, path2, path3}); - //auto data = Glib::VariantContainerBase::create_tuple(paths); + // auto data = Glib::VariantContainerBase::create_tuple(paths); try { manager->call_sync("ActivateConnection", paths); } catch (...) { - /* Most likely no password*/ - /* TODO */ + /* + * Most likely no password + * TODO + */ } } @@ -391,14 +417,12 @@ void NetworkManager::deactivate_connection(std::string p1) Glib::VariantStringBase path1; Glib::VariantStringBase::create_object_path(path1, p1); auto paths = Glib::VariantContainerBase::create_tuple({path1}); - //auto data = Glib::VariantContainerBase::create_tuple(paths); + // auto data = Glib::VariantContainerBase::create_tuple(paths); try { manager->call_sync("DeactivateConnection", paths); } catch (...) - { - - } + {} } /* Is Wifi Enabled, in software and in rfkill */ @@ -408,11 +432,13 @@ std::tuple NetworkManager::wifi_global_enabled() { return {false, false}; } + Glib::Variant wifisoft, wifihard; nm_proxy->get_cached_property(wifisoft, "WirelessEnabled"); nm_proxy->get_cached_property(wifihard, "WirelessHardwareEnabled"); return {wifisoft.get(), wifihard.get()}; } + /* Is Mobile Data Enabled, in software and in rfkill */ std::tuple NetworkManager::mobile_global_enabled() { @@ -420,11 +446,13 @@ std::tuple NetworkManager::mobile_global_enabled() { return {false, false}; } + Glib::Variant modemsoft, modemhard; nm_proxy->get_cached_property(modemsoft, "WwanEnabled"); nm_proxy->get_cached_property(modemhard, "WwanHardwareEnabled"); return {modemsoft.get(), modemhard.get()}; } + /* Is Networking enabled */ bool NetworkManager::networking_global_enabled() { @@ -432,6 +460,7 @@ bool NetworkManager::networking_global_enabled() { return false; } + Glib::Variant enabled; nm_proxy->get_cached_property(enabled, "NetworkingEnabled"); return enabled.get(); @@ -442,16 +471,14 @@ void NetworkManager::wifi_global_set(bool value) auto another_proxy = Gio::DBus::Proxy::create_sync(nm_proxy->get_connection(), NM_DBUS_NAME, NM_PATH, - DBUS_PROPERTIES_INTERFACE - ); + DBUS_PROPERTIES_INTERFACE); auto params = Glib::VariantContainerBase::create_tuple( - { - Glib::Variant::create(NM_INTERFACE), - Glib::Variant::create("WirelessEnabled"), - Glib::Variant::create(Glib::Variant::create(value)) - } - ); + { + Glib::Variant::create(NM_INTERFACE), + Glib::Variant::create("WirelessEnabled"), + Glib::Variant::create(Glib::Variant::create(value)) + }); another_proxy->call_sync("Set", params); } @@ -460,19 +487,18 @@ void NetworkManager::mobile_global_set(bool value) auto another_proxy = Gio::DBus::Proxy::create_sync(nm_proxy->get_connection(), NM_DBUS_NAME, NM_PATH, - DBUS_PROPERTIES_INTERFACE - ); + DBUS_PROPERTIES_INTERFACE); auto params = Glib::VariantContainerBase::create_tuple( - { - Glib::Variant::create(NM_INTERFACE), - Glib::Variant::create("WwanEnabled"), - - Glib::Variant::create(Glib::Variant::create(value)) - } - ); + { + Glib::Variant::create(NM_INTERFACE), + Glib::Variant::create("WwanEnabled"), + + Glib::Variant::create(Glib::Variant::create(value)) + }); another_proxy->call_sync("Set", params); } + void NetworkManager::networking_global_set(bool value) { auto params = Glib::VariantContainerBase::create_tuple(Glib::Variant::create(value)); @@ -487,4 +513,4 @@ NetworkManager::~NetworkManager() { signal.disconnect(); } -} \ No newline at end of file +} diff --git a/src/util/network/manager.hpp b/src/util/network/manager.hpp index 5f13b7bc..8efb61a4 100644 --- a/src/util/network/manager.hpp +++ b/src/util/network/manager.hpp @@ -12,18 +12,18 @@ #include "vpn.hpp" using type_signal_network = sigc::signal)>; -using type_signal_device_list_changed = sigc::signal>)>; +using type_signal_device_list_changed = sigc::signal>)>; using type_signal_simple = sigc::signal; -using type_signal_path = sigc::signal; +using type_signal_path = sigc::signal; -class NetworkManager +class NetworkManager { private: type_signal_network default_changed, device_added, device_removed; type_signal_device_list_changed device_list_changed; type_signal_simple global_change, nm_start, nm_stop, mm_start, mm_stop; type_signal_path vpn_added, vpn_removed; - + Glib::RefPtr connection; Glib::RefPtr nm_proxy, settings_proxy, manager_proxy; @@ -38,7 +38,8 @@ class NetworkManager std::map> all_devices; std::map> all_vpns; - void on_nm_properties_changed(const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated); + void on_nm_properties_changed(const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated); void on_nm_signal(const Glib::ustring&, const Glib::ustring&, const Glib::VariantContainerBase&); void get_all_devices_cb(std::shared_ptr); void add_network(std::string path); @@ -46,42 +47,100 @@ class NetworkManager void changed_primary(std::string path); void connect_nm(); void lost_nm(); + public: /* Emitted when the default connection or it's properties change */ - type_signal_network signal_default_changed() { return default_changed; } + type_signal_network signal_default_changed() + { + return default_changed; + } + /* Emitted when any network device is connected or disconnected */ - type_signal_device_list_changed signal_device_list_changed() { return device_list_changed; } + type_signal_device_list_changed signal_device_list_changed() + { + return device_list_changed; + } + /* Emitted when a networking device is added */ - type_signal_network signal_device_added() { return device_added; } + type_signal_network signal_device_added() + { + return device_added; + } + /* Emitted when a networking device is removed */ - type_signal_network signal_device_removed() { return device_removed; } + type_signal_network signal_device_removed() + { + return device_removed; + } + /* Emitted when any of the global enable toggles is changed */ - type_signal_simple signal_global_toggle() { return global_change; } - type_signal_path signal_vpn_added() { return vpn_added; } - type_signal_path signal_vpn_removed() { return vpn_removed; } - type_signal_simple signal_nm_start() { return nm_start; } - type_signal_simple signal_nm_stop() { return nm_stop; } - type_signal_simple signal_mm_start() { return mm_start; } - type_signal_simple signal_mm_stop() { return mm_stop; } - std::shared_ptr get_nm_proxy() { return nm_proxy; } + type_signal_simple signal_global_toggle() + { + return global_change; + } + + type_signal_path signal_vpn_added() + { + return vpn_added; + } + + type_signal_path signal_vpn_removed() + { + return vpn_removed; + } + + type_signal_simple signal_nm_start() + { + return nm_start; + } + + type_signal_simple signal_nm_stop() + { + return nm_stop; + } + + type_signal_simple signal_mm_start() + { + return mm_start; + } + + type_signal_simple signal_mm_stop() + { + return mm_stop; + } + + std::shared_ptr get_nm_proxy() + { + return nm_proxy; + } + /* A list of current networks. */ - std::map> get_all_vpns() {return all_vpns; } - std::map> get_all_devices() { return all_devices; } - + std::map> get_all_vpns() + { + return all_vpns; + } + + std::map> get_all_devices() + { + return all_devices; + } + /* TODO Consider allowing this to lose last reference */ static std::shared_ptr getInstance() { static std::shared_ptr instance; if (!instance) { - instance = std::make_shared(); + instance = std::make_shared(); } + return instance; } + NetworkManager(); ~NetworkManager(); - + std::shared_ptr get_primary_network(); std::shared_ptr get_connection(std::string path); void activate_connection(std::string connection_path, std::string device_path, std::string details_path); @@ -95,4 +154,4 @@ class NetworkManager void wifi_global_set(bool value); void mobile_global_set(bool value); void networking_global_set(bool value); -}; \ No newline at end of file +}; diff --git a/src/util/network/modem.cpp b/src/util/network/modem.cpp index e8862454..f2d85cce 100644 --- a/src/util/network/modem.cpp +++ b/src/util/network/modem.cpp @@ -1,5 +1,6 @@ #include "modem.hpp" -ModemNetwork::ModemNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr modem_proxy): +ModemNetwork::ModemNetwork(std::string path, std::shared_ptr device_proxy, + std::shared_ptr modem_proxy) : Network(path, device_proxy), modem_proxy(modem_proxy) { Glib::Variant device_data; @@ -14,25 +15,25 @@ void ModemNetwork::find_mm_proxy(std::string dev_id) "org.freedesktop.ModemManager1", "/org/freedesktop/ModemManager1", "org.freedesktop.DBus.ObjectManager"); - + auto ret1 = mm_om_proxy->call_sync("GetManagedObjects").get_child(); - auto ret = Glib::VariantBase::cast_dynamic>>>>(ret1); + auto ret = Glib::VariantBase::cast_dynamic>>>>(ret1); - for (auto &it : ret.get()) + for (auto & it : ret.get()) { std::string modem_path = it.first; - for (auto &next : it.second) + for (auto & next : it.second) { if (next.first == "org.freedesktop.ModemManager1.Modem") { - for (auto &why : next.second) + for (auto & why : next.second) { if (why.first == "DeviceIdentifier") { auto devid = Glib::VariantBase::cast_dynamic>(why.second); if (devid.get() == dev_id) { - mm_proxy = Gio::DBus::Proxy::create_sync(device_proxy->get_connection(), "org.freedesktop.ModemManager1", modem_path, @@ -43,26 +44,29 @@ void ModemNetwork::find_mm_proxy(std::string dev_id) } } } + if (mm_proxy) { signals.push_back(mm_proxy->signal_properties_changed().connect( - [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { - for (auto &it : properties) + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated) + { + for (auto & it : properties) { if (it.first == "SignalQuality") { auto container = Glib::VariantBase::cast_dynamic(it.second); Glib::Variant signal_data; - container.get_child(signal_data,0); + container.get_child(signal_data, 0); // "(ub)" => percent 0-100, 'is recent' strength = signal_data.get(); - } + if (it.first == "CurrentModes") { auto container = Glib::VariantBase::cast_dynamic(it.second); Glib::Variant mode_data; - container.get_child(mode_data,1); + container.get_child(mode_data, 1); caps = mode_data.get(); } } @@ -71,12 +75,11 @@ void ModemNetwork::find_mm_proxy(std::string dev_id) { std::cerr << "Could not get extra modem details" << std::endl; } - } ModemNetwork::~ModemNetwork() { - for(auto signal : signals) + for (auto signal : signals) { signal.disconnect(); } @@ -113,6 +116,7 @@ std::string ModemNetwork::get_name() { return "Misconfigured Mobile"; } + /* TODO Get Carrier from MM */ return "Mobile"; } @@ -135,6 +139,7 @@ std::string ModemNetwork::get_signal_band() { return "20"; } + return "0"; } @@ -156,6 +161,7 @@ std::string ModemNetwork::get_connection_type_string() { return "edge"; } + return "edge"; } @@ -165,11 +171,13 @@ std::string ModemNetwork::get_icon_name() { return "network-mobile-off"; } + if (!is_active()) { return "network-mobile-off"; } - return "network-mobile-"+get_signal_band()+"-"+get_connection_type_string(); + + return "network-mobile-" + get_signal_band() + "-" + get_connection_type_string(); } std::string ModemNetwork::get_color_name() @@ -180,4 +188,4 @@ std::string ModemNetwork::get_color_name() std::string ModemNetwork::get_friendly_name() { return "Mobile Data"; -} \ No newline at end of file +} diff --git a/src/util/network/modem.hpp b/src/util/network/modem.hpp index 947d4d76..fc7c3efb 100644 --- a/src/util/network/modem.hpp +++ b/src/util/network/modem.hpp @@ -14,13 +14,15 @@ #define CAP_2G 2 #define CAP_CS 1 -class ModemNetwork : public Network { +class ModemNetwork : public Network +{ public: - unsigned char strength=0; + unsigned char strength = 0; int caps = 8; std::shared_ptr modem_proxy; std::shared_ptr mm_proxy; - ModemNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr modem_proxy); + ModemNetwork(std::string path, std::shared_ptr device_proxy, + std::shared_ptr modem_proxy); void find_mm_proxy(std::string dev_id); ~ModemNetwork(); std::string strength_string(); @@ -30,4 +32,4 @@ class ModemNetwork : public Network { std::string get_icon_name(); std::string get_color_name(); std::string get_friendly_name(); -}; \ No newline at end of file +}; diff --git a/src/util/network/network-widget.cpp b/src/util/network/network-widget.cpp index 4d69a716..e546e550 100644 --- a/src/util/network/network-widget.cpp +++ b/src/util/network/network-widget.cpp @@ -13,17 +13,18 @@ #include "network-widget.hpp" -AccessPointWidget::AccessPointWidget(std::string path_in, std::shared_ptr ap_in): - ap(ap_in),path(path_in) +AccessPointWidget::AccessPointWidget(std::string path_in, std::shared_ptr ap_in) : + ap(ap_in), path(path_in) { add_css_class("access-point"); append(image); append(label); - auto update_ap = [this] () { - label.set_label(ap->get_ssid()); - image.set_from_icon_name(ap->get_icon_name()); - }; + auto update_ap = [this] () + { + label.set_label(ap->get_ssid()); + image.set_from_icon_name(ap->get_icon_name()); + }; signals.push_back(ap_in->signal_altered().connect(update_ap)); update_ap(); } @@ -36,8 +37,8 @@ AccessPointWidget::~AccessPointWidget() } } -VPNControlWidget::VPNControlWidget(std::shared_ptr config): - config(config) +VPNControlWidget::VPNControlWidget(std::shared_ptr config) : + config(config) { append(image); append(label); @@ -53,10 +54,9 @@ VPNControlWidget::~VPNControlWidget() } } -DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): +DeviceControlWidget::DeviceControlWidget(std::shared_ptr network) : network(network) { - add_css_class("device"); set_halign(Gtk::Align::FILL); set_orientation(Gtk::Orientation::VERTICAL); @@ -66,122 +66,129 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network): topbox.append(label); revealer.set_child(revealer_box); revealer_box.set_orientation(Gtk::Orientation::VERTICAL); - auto wifi = std::dynamic_pointer_cast(network); + auto wifi = std::dynamic_pointer_cast(network); auto mobile = std::dynamic_pointer_cast(network); - auto wired = std::dynamic_pointer_cast(network); - auto bt = std::dynamic_pointer_cast(network); - if(wifi) + auto wired = std::dynamic_pointer_cast(network); + auto bt = std::dynamic_pointer_cast(network); + if (wifi) { - type="wifi"; + type = "wifi"; /* TODO Sort*/ - for (auto &it : wifi->get_access_points()) + for (auto & it : wifi->get_access_points()) { add_access_point(it.second); } signals.push_back(wifi->signal_add_access_point().connect( - [this] (std::shared_ptr ap) { - add_access_point(ap); - } - )); + [this] (std::shared_ptr ap) + { + add_access_point(ap); + })); signals.push_back(wifi->signal_remove_access_point().connect( - [this] (std::shared_ptr ap) { - remove_access_point(ap->get_path()); + [this] (std::shared_ptr ap) + { + remove_access_point(ap->get_path()); + })); + + auto wifi_cb = + [this, wifi] () + { + if (wifi->get_current_access_point_path() == "/") + { + revealer.set_reveal_child(true); + topbox.hide(); + } else + { + revealer.set_reveal_child(false); + topbox.show(); } - )); - - auto wifi_cb = - [this, wifi] () { - if (wifi->get_current_access_point_path() == "/") - { - revealer.set_reveal_child(true); - topbox.hide(); - } else - { - revealer.set_reveal_child(false); - topbox.show(); - } - }; + }; signals.push_back(network->signal_network_altered().connect(wifi_cb)); wifi_cb(); } else if (wired) { - type="wired"; + type = "wired"; revealer.hide(); } else if (bt) { - type="bt"; + type = "bt"; revealer.hide(); } else if (mobile) { - type="mobile"; + type = "mobile"; revealer.hide(); } else { - type="broken"; + type = "broken"; revealer.hide(); } - + /* Click toggles connection on/off */ auto click = Gtk::GestureClick::create(); signals.push_back(click->signal_released().connect( - [network] (int, double, double) { - network->toggle(); - } - )); + [network] (int, double, double) + { + network->toggle(); + })); label.add_controller(click); /* Set label and image based on friendly info */ - auto network_change_cb = [this, network] () { - image.set_from_icon_name(network->get_icon_symbolic()); - label.set_label(network->get_name()); - if (network->is_active()) - { - label.add_css_class("active"); - } else - { - label.remove_css_class("active"); - } - }; + auto network_change_cb = [this, network] () + { + image.set_from_icon_name(network->get_icon_symbolic()); + label.set_label(network->get_name()); + if (network->is_active()) + { + label.add_css_class("active"); + } else + { + label.remove_css_class("active"); + } + }; signals.push_back(network->signal_network_altered().connect(network_change_cb)); network_change_cb(); - } -void DeviceControlWidget::remove_access_point(std::string path){ +void DeviceControlWidget::remove_access_point(std::string path) +{ auto widget = access_points[path]; if (widget) { revealer_box.remove(*widget); } + access_points.erase(path); } void DeviceControlWidget::add_access_point(std::shared_ptr ap) { - if (!ap || ap->get_ssid()=="") + if (!ap || (ap->get_ssid() == "")) { return; } + auto path = ap->get_path(); if (path == "/") { return; } - auto success = access_points.emplace(path, new AccessPointWidget(path, ap)); - if (!success.second){ - std::cerr << "Unable to insert Access Point "<< path<< success.first->first << std::endl; + + auto success = access_points.emplace(path, new AccessPointWidget(path, ap)); + if (!success.second) + { + std::cerr << "Unable to insert Access Point " << path << success.first->first << std::endl; exit(1); } + auto widget = access_points[path]; - auto click = Gtk::GestureClick::create(); - + auto click = Gtk::GestureClick::create(); + auto sig = click->signal_released().connect( - [this, path] (int, double, double) { - selected_access_point(path); - } - ); + [this, path] (int, double, double) + { + selected_access_point(path); + }); widget->add_controller(click); widget->signals.push_back(sig); revealer_box.append(*access_points[path]); @@ -194,16 +201,18 @@ void DeviceControlWidget::selected_access_point(std::string path) { std::cerr << "Cannot select AP on non-wifi device" << std::endl; } + if (path == "/") { return; } + if (wifi->get_current_access_point_path() == path) { wifi->disconnect(); - } else + } else { - wifi->connect(path); + wifi->connect(path); } } @@ -228,23 +237,17 @@ NetworkControlWidget::NetworkControlWidget() network_manager = NetworkManager::getInstance(); signals.push_back(network_manager->signal_nm_start().connect( - sigc::mem_fun(*this, &NetworkControlWidget::nm_start) - )); + sigc::mem_fun(*this, &NetworkControlWidget::nm_start))); signals.push_back(network_manager->signal_nm_stop().connect( - sigc::mem_fun(*this, &NetworkControlWidget::nm_stop) - )); + sigc::mem_fun(*this, &NetworkControlWidget::nm_stop))); signals.push_back(network_manager->signal_mm_start().connect( - sigc::mem_fun(*this, &NetworkControlWidget::mm_start) - )); + sigc::mem_fun(*this, &NetworkControlWidget::mm_start))); signals.push_back(network_manager->signal_mm_stop().connect( - sigc::mem_fun(*this, &NetworkControlWidget::mm_stop) - )); + sigc::mem_fun(*this, &NetworkControlWidget::mm_stop))); signals.push_back(network_manager->signal_device_added().connect( - sigc::mem_fun(*this, &NetworkControlWidget::add_device) - )); + sigc::mem_fun(*this, &NetworkControlWidget::add_device))); signals.push_back(network_manager->signal_device_removed().connect( - sigc::mem_fun(*this, &NetworkControlWidget::remove_device) - )); + sigc::mem_fun(*this, &NetworkControlWidget::remove_device))); top.append(global_networking); top.append(wifi_networking); @@ -266,29 +269,28 @@ NetworkControlWidget::NetworkControlWidget() /* Connect to global widget cb */ signal_network = global_networking.signal_toggled().connect( - [this] () { - network_manager->networking_global_set(global_networking.get_active()); - } - ); + [this] () + { + network_manager->networking_global_set(global_networking.get_active()); + }); signal_wifi = wifi_networking.signal_toggled().connect( - [this] () { - network_manager->wifi_global_set(wifi_networking.get_active()); - } - ); + [this] () + { + network_manager->wifi_global_set(wifi_networking.get_active()); + }); signal_mobile = mobile_networking.signal_toggled().connect( - [this] () { - network_manager->mobile_global_set(mobile_networking.get_active()); - } - ); + [this] () + { + network_manager->mobile_global_set(mobile_networking.get_active()); + }); /* Connect changes to global state in NM */ signals.push_back(network_manager->signal_global_toggle().connect( sigc::mem_fun(*this, &NetworkControlWidget::update_globals))); - } void NetworkControlWidget::update_globals() { - auto [wifi_soft, wifi_hard] = network_manager->wifi_global_enabled(); + auto [wifi_soft, wifi_hard] = network_manager->wifi_global_enabled(); auto [mobile_soft, mobile_hard] = network_manager->mobile_global_enabled(); auto global = network_manager->networking_global_enabled(); signal_wifi.block(true); @@ -298,26 +300,30 @@ void NetworkControlWidget::update_globals() { wifi_networking.set_label("Wifi ✈"); wifi_networking.set_active(false); - } else if(!wifi_soft) + } else if (!wifi_soft) { wifi_networking.set_label("Wifi"); wifi_networking.set_active(false); - } else { + } else + { wifi_networking.set_label("Wifi"); wifi_networking.set_active(true); } - if(!mobile_hard) + + if (!mobile_hard) { mobile_networking.set_label("Mobile ✈"); mobile_networking.set_active(false); - } else if(!mobile_soft) + } else if (!mobile_soft) { mobile_networking.set_label("Mobile"); mobile_networking.set_active(false); - } else { + } else + { mobile_networking.set_label("Mobile"); mobile_networking.set_active(true); } + global_networking.set_active(global); signal_wifi.unblock(); signal_mobile.unblock(); @@ -330,17 +336,18 @@ void NetworkControlWidget::add_vpn(std::shared_ptr config) vpn_widgets.emplace(config->path, widget); auto click = Gtk::GestureClick::create(); - auto sig = click->signal_released().connect( - [this, config] (int, double, double) { - auto primary = network_manager->get_primary_network(); - if (primary->has_vpn) - { - network_manager->deactivate_connection(primary->get_path()); - } else { - network_manager->activate_connection(config->path, "/", "/"); - } + auto sig = click->signal_released().connect( + [this, config] (int, double, double) + { + auto primary = network_manager->get_primary_network(); + if (primary->has_vpn) + { + network_manager->deactivate_connection(primary->get_path()); + } else + { + network_manager->activate_connection(config->path, "/", "/"); } - ); + }); widget->add_controller(click); widget->signals.push_back(sig); vpn_box.append(*widget); @@ -360,6 +367,7 @@ void NetworkControlWidget::add_device(std::shared_ptr network) { return; } + auto new_controller = std::make_shared(network); widgets.emplace(network->get_path(), new_controller); auto widget = widgets[network->get_path()]; @@ -375,7 +383,8 @@ void NetworkControlWidget::add_device(std::shared_ptr network) } else if (widget->type == "bt") { bt_box.append(*widget); - } else { + } else + { std::cout << "Unknown network type : " << widget->type << std::endl; } } @@ -395,9 +404,11 @@ void NetworkControlWidget::remove_device(std::shared_ptr network) } else if (widget->type == "bt") { bt_box.remove(*widget); - } else { + } else + { std::cout << "Unknown network type : " << widget->type << std::endl; } + widgets.erase(network->get_path()); } @@ -406,25 +417,29 @@ void NetworkControlWidget::nm_start() network_manager_failed.hide(); top.show(); /* Fill already existing devices */ - for (auto &device : network_manager->get_all_devices()) + for (auto & device : network_manager->get_all_devices()) { add_device(device.second); } - for (auto &it : network_manager->get_all_vpns()) + + for (auto & it : network_manager->get_all_vpns()) { add_vpn(it.second); } + update_globals(); } + void NetworkControlWidget::nm_stop() { network_manager_failed.show(); top.hide(); widgets.clear(); - for (auto &it : vpn_widgets) + for (auto & it : vpn_widgets) { vpn_box.remove(*it.second); } + vpn_widgets.clear(); } @@ -447,4 +462,4 @@ NetworkControlWidget::~NetworkControlWidget() { signal.disconnect(); } -} \ No newline at end of file +} diff --git a/src/util/network/network-widget.hpp b/src/util/network/network-widget.hpp index 85bef8f9..317f5649 100644 --- a/src/util/network/network-widget.hpp +++ b/src/util/network/network-widget.hpp @@ -15,6 +15,7 @@ class AccessPointWidget : public Gtk::Box Gtk::Label label; std::shared_ptr ap; std::string path; + public: std::vector signals; AccessPointWidget(std::string path, std::shared_ptr ap); @@ -31,6 +32,7 @@ class DeviceControlWidget : public Gtk::Box Gtk::Revealer revealer; Gtk::Box revealer_box, topbox; std::vector signals; + public: DeviceControlWidget(std::shared_ptr network); ~DeviceControlWidget(); @@ -38,7 +40,6 @@ class DeviceControlWidget : public Gtk::Box void remove_access_point(std::string path); void selected_access_point(std::string path); std::string type; - }; class VPNControlWidget : public Gtk::Box @@ -47,6 +48,7 @@ class VPNControlWidget : public Gtk::Box std::shared_ptr config; Gtk::Image image; Gtk::Label label; + public: std::vector signals; @@ -56,13 +58,14 @@ class VPNControlWidget : public Gtk::Box class NetworkControlWidget : public Gtk::Box { - Gtk::Label network_manager_failed; - Gtk::Box wire_box, wifi_box, mobile_box, vpn_box, bt_box, top; - Gtk::CheckButton global_networking, wifi_networking, mobile_networking; - std::map > widgets; - std::map > vpn_widgets; - sigc::connection signal_network, signal_wifi, signal_mobile; - std::vector signals; + Gtk::Label network_manager_failed; + Gtk::Box wire_box, wifi_box, mobile_box, vpn_box, bt_box, top; + Gtk::CheckButton global_networking, wifi_networking, mobile_networking; + std::map> widgets; + std::map> vpn_widgets; + sigc::connection signal_network, signal_wifi, signal_mobile; + std::vector signals; + public: NetworkControlWidget(); ~NetworkControlWidget(); @@ -76,4 +79,4 @@ class NetworkControlWidget : public Gtk::Box void nm_stop(); void mm_start(); void mm_stop(); -}; \ No newline at end of file +}; diff --git a/src/util/network/network.cpp b/src/util/network/network.cpp index deb5ade0..0da421dd 100644 --- a/src/util/network/network.cpp +++ b/src/util/network/network.cpp @@ -1,53 +1,61 @@ #include "network.hpp" #include "manager.hpp" -type_signal_network_altered Network::signal_network_altered() { return network_altered; } +type_signal_network_altered Network::signal_network_altered() +{ + return network_altered; +} -Network::Network(std::string path, std::shared_ptr in_proxy): +Network::Network(std::string path, std::shared_ptr in_proxy) : network_path(path), device_proxy(in_proxy) { /* Allow for nullnetwork and pseudo networks */ if (in_proxy == nullptr) { - return; + return; } + Glib::Variant val; device_proxy->get_cached_property(val, "Interface"); - if(val.get().length() > 0) + if (val.get().length() > 0) { - interface = val.get(); + interface = val.get(); } + /* Any change of state */ signals.push_back(device_proxy->signal_signal().connect( - [this] (const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) { + [this] (const Glib::ustring& sender, const Glib::ustring& signal, + const Glib::VariantContainerBase& container) + { if (signal == "StateChanged") { if (container.is_of_type(Glib::VariantType("(uuu)"))) - { - auto value = container.get_child(0); - auto value2= Glib::VariantBase::cast_dynamic>(value).get(); - last_state = value2; + { + auto value = container.get_child(0); + auto value2 = Glib::VariantBase::cast_dynamic>(value).get(); + last_state = value2; network_altered.emit(); } } })); signals.push_back(device_proxy->signal_properties_changed().connect( - [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { - for (auto &it : properties) + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated) + { + for (auto & it : properties) + { + if (it.first == "ActiveConnection") { - if (it.first == "ActiveConnection") - { - network_altered.emit(); - } + network_altered.emit(); } } - )); + })); } Network::~Network() { - for(auto signal : signals) + for (auto signal : signals) { signal.disconnect(); } @@ -60,9 +68,11 @@ std::string Network::get_friendly_name() std::string Network::get_interface() { - if (!device_proxy){ - return "/dev/null"; + if (!device_proxy) + { + return "/dev/null"; } + Glib::Variant iface; device_proxy->get_cached_property(iface, "Interface"); return iface.get(); @@ -71,10 +81,10 @@ std::string Network::get_interface() bool Network::show_spinner() { return last_state == NM_DEVICE_STATE_PREPARE || - last_state == NM_DEVICE_STATE_CONFIG; - } + last_state == NM_DEVICE_STATE_CONFIG; +} -std::string Network::get_path() +std::string Network::get_path() { return network_path; } @@ -83,17 +93,18 @@ void Network::connect(std::string path) { NetworkManager::getInstance()->activate_connection("/", network_path, path); } + void Network::toggle() { if (is_active()) { disconnect(); - } else { connect("/"); } } + void Network::disconnect() { device_proxy->call_sync("Disconnect"); @@ -104,4 +115,4 @@ bool Network::is_active() Glib::Variant val; device_proxy->get_cached_property(val, "ActiveConnection"); return val.get() != "/"; -} \ No newline at end of file +} diff --git a/src/util/network/network.hpp b/src/util/network/network.hpp index 92ab5ca2..9c37baa3 100644 --- a/src/util/network/network.hpp +++ b/src/util/network/network.hpp @@ -21,15 +21,17 @@ using type_signal_network_altered = sigc::signal; -class Network { +class Network +{ protected: type_signal_network_altered network_altered; std::string network_path; std::vector signals; + public: type_signal_network_altered signal_network_altered(); std::shared_ptr device_proxy; - std::string interface=""; + std::string interface = ""; int last_state = 0; virtual std::string get_name() = 0; virtual std::string get_color_name() = 0; @@ -39,12 +41,16 @@ class Network { virtual std::string get_interface(); bool show_spinner(); virtual std::string get_icon_name() = 0; - std::string get_icon_symbolic() { return get_icon_name() + "-symbolic"; }; + std::string get_icon_symbolic() + { + return get_icon_name() + "-symbolic"; + } + std::string get_path(); void disconnect(); void connect(std::string path_extra); void toggle(); bool is_active(); Network(const Network &) = delete; - Network &operator = (const Network &) = delete; -}; \ No newline at end of file + Network& operator =(const Network&) = delete; +}; diff --git a/src/util/network/null.hpp b/src/util/network/null.hpp index ef555b27..a7eaa892 100644 --- a/src/util/network/null.hpp +++ b/src/util/network/null.hpp @@ -1,12 +1,11 @@ #pragma once #include "network.hpp" -class NullNetwork : public Network { +class NullNetwork : public Network +{ public: - NullNetwork():Network("/", nullptr) - { - - } + NullNetwork() : Network("/", nullptr) + {} std::string get_name() override { @@ -22,4 +21,4 @@ class NullNetwork : public Network { { return "none"; } -}; \ No newline at end of file +}; diff --git a/src/util/network/vpn.hpp b/src/util/network/vpn.hpp index 9b2c068a..a4919bae 100644 --- a/src/util/network/vpn.hpp +++ b/src/util/network/vpn.hpp @@ -2,18 +2,16 @@ #include #include -class VpnConfig { +class VpnConfig +{ private: std::shared_ptr vpn_proxy; + public: std::string name; std::string path; - VpnConfig(std::string path, std::shared_ptr vpn_proxy, std::string name): - vpn_proxy(vpn_proxy), name(name),path(path) - { - - } - - -}; \ No newline at end of file + VpnConfig(std::string path, std::shared_ptr vpn_proxy, std::string name) : + vpn_proxy(vpn_proxy), name(name), path(path) + {} +}; diff --git a/src/util/network/wifi-ap.cpp b/src/util/network/wifi-ap.cpp index e087712a..25a1d5ed 100644 --- a/src/util/network/wifi-ap.cpp +++ b/src/util/network/wifi-ap.cpp @@ -4,8 +4,8 @@ std::string AccessPoint::get_path() { return ap_path; - } + AccessPoint::AccessPoint(std::string path, std::shared_ptr access_point_proxy) : ap_path(path), access_point_proxy(access_point_proxy) { @@ -19,27 +19,29 @@ AccessPoint::AccessPoint(std::string path, std::shared_ptr acc ssid = std::string(ssid_bytes.begin(), ssid_bytes.end()); signals.push_back(access_point_proxy->signal_properties_changed().connect( - [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { - for (auto &it : properties) + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated) + { + for (auto & it : properties) + { + if (it.first == "Strength") + { + auto value = Glib::VariantBase::cast_dynamic>(it.second).get(); + strength = value; + access_point_altered.emit(); + } else if (it.first == "Ssid") { - if (it.first == "Strength") - { - auto value = Glib::VariantBase::cast_dynamic>(it.second).get(); - strength = value; - access_point_altered.emit(); - } else if (it.first == "Ssid") - { - auto value = Glib::VariantBase::cast_dynamic>>(it.second).get(); - ssid = std::string(value.begin(), value.end()); - access_point_altered.emit(); - } + auto value = + Glib::VariantBase::cast_dynamic>>(it.second).get(); + ssid = std::string(value.begin(), value.end()); + access_point_altered.emit(); } } - )); - + })); } -std::string AccessPoint::get_ssid(){ +std::string AccessPoint::get_ssid() +{ return ssid; } @@ -66,12 +68,11 @@ std::string AccessPoint::strength_string() } return "none"; - } std::string AccessPoint::get_icon_name() { - return "network-wireless-signal-"+strength_string()+"-symbolic"; + return "network-wireless-signal-" + strength_string() + "-symbolic"; } type_signal_network_altered AccessPoint::signal_altered() @@ -81,8 +82,8 @@ type_signal_network_altered AccessPoint::signal_altered() AccessPoint::~AccessPoint() { - for(auto signal : signals) + for (auto signal : signals) { signal.disconnect(); } -} \ No newline at end of file +} diff --git a/src/util/network/wifi-ap.hpp b/src/util/network/wifi-ap.hpp index ab6ebded..aae8897c 100644 --- a/src/util/network/wifi-ap.hpp +++ b/src/util/network/wifi-ap.hpp @@ -5,13 +5,15 @@ using type_signal_access_point_altered = sigc::signal; -class AccessPoint { +class AccessPoint +{ private: std::string ap_path; type_signal_access_point_altered access_point_altered; unsigned char strength; - std::string ssid=""; + std::string ssid = ""; std::vector signals; + public: std::string get_path(); std::shared_ptr access_point_proxy; diff --git a/src/util/network/wifi.cpp b/src/util/network/wifi.cpp index 974963dd..20cdceac 100644 --- a/src/util/network/wifi.cpp +++ b/src/util/network/wifi.cpp @@ -6,10 +6,11 @@ type_signal_access_point WifiNetwork::signal_add_access_point() { - return add_ap; + return add_ap; } + type_signal_access_point WifiNetwork::signal_remove_access_point() -{ +{ return remove_ap; } @@ -20,8 +21,7 @@ std::map> WifiNetwork::get_access_poin void WifiNetwork::add_access_point(std::string path) { - - auto ap_proxy =Gio::DBus::Proxy::create_sync(wifi_proxy->get_connection(), + auto ap_proxy = Gio::DBus::Proxy::create_sync(wifi_proxy->get_connection(), "org.freedesktop.NetworkManager", path, "org.freedesktop.NetworkManager.AccessPoint"); @@ -33,55 +33,59 @@ void WifiNetwork::remove_access_point(std::string path) all_access_points.erase(path); } -WifiNetwork::WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy): +WifiNetwork::WifiNetwork(std::string path, std::shared_ptr device_proxy, + std::shared_ptr wifi_proxy) : Network(path, device_proxy), wifi_proxy(wifi_proxy) { signals.push_back(wifi_proxy->signal_signal().connect( - [this] (const Glib::ustring& source, const Glib::ustring& signal , const Glib::VariantContainerBase& value) { - if (signal == "AccessPointAdded") - { - auto val = Glib::VariantBase::cast_dynamic>(value.get_child()).get(); - add_access_point(val); - add_ap.emit(all_access_points[val]); - } else if (signal == "AccessPointRemoved") - { - auto val = Glib::VariantBase::cast_dynamic>(value.get_child()).get(); - remove_ap.emit(all_access_points[val]); - all_access_points.erase(val); - } + [this] (const Glib::ustring& source, const Glib::ustring& signal, + const Glib::VariantContainerBase& value) + { + if (signal == "AccessPointAdded") + { + auto val = Glib::VariantBase::cast_dynamic>(value.get_child()).get(); + add_access_point(val); + add_ap.emit(all_access_points[val]); + } else if (signal == "AccessPointRemoved") + { + auto val = Glib::VariantBase::cast_dynamic>(value.get_child()).get(); + remove_ap.emit(all_access_points[val]); + all_access_points.erase(val); } - )); + })); signals.push_back(wifi_proxy->signal_properties_changed().connect( - [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) { - for (auto &it : properties) + [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated) + { + for (auto & it : properties) + { + if (it.first == "ActiveAccessPoint") { - if (it.first == "ActiveAccessPoint") + if (access_point_signal) { - if (access_point_signal) - { - access_point_signal.disconnect(); - } - auto access_point = get_current_access_point(); - if (access_point) + access_point_signal.disconnect(); + } + + auto access_point = get_current_access_point(); + if (access_point) + { + /* Bubble signal upwards */ + access_point_signal = access_point->signal_altered().connect( + [this] () { - /* Bubble signal upwards */ - access_point_signal = access_point->signal_altered().connect( - [this] () { - network_altered.emit(); - } - ); - } - network_altered.emit(); - + network_altered.emit(); + }); } + + network_altered.emit(); } } - )); + })); /* Initial values */ Glib::Variant> base; wifi_proxy->get_cached_property(base, "AccessPoints"); - for (auto &it : base.get()) + for (auto & it : base.get()) { add_access_point(it); } @@ -90,10 +94,10 @@ WifiNetwork::WifiNetwork(std::string path, std::shared_ptr dev if (access_point) { signals.push_back(access_point_signal = access_point->signal_altered().connect( - [this]() { - network_altered.emit(); - } - )); + [this] () + { + network_altered.emit(); + })); } } @@ -104,6 +108,7 @@ std::string WifiNetwork::get_name() { return network->get_ssid(); } + return "Wifi..."; } @@ -118,11 +123,14 @@ std::string WifiNetwork::get_icon_name() { return "network-wireless-disconnected"; } + auto ap = get_current_access_point(); - if (!ap){ + if (!ap) + { return "network-wireless-disconnected"; } - return "network-wireless-signal-"+ap->strength_string(); + + return "network-wireless-signal-" + ap->strength_string(); } std::string WifiNetwork::get_friendly_name() @@ -132,6 +140,7 @@ std::string WifiNetwork::get_friendly_name() { return ap->get_ssid(); } + return "Not connected"; } @@ -151,12 +160,13 @@ std::string WifiNetwork::get_current_access_point_path() WifiNetwork::~WifiNetwork() { all_access_points.clear(); - if(access_point_signal) + if (access_point_signal) { access_point_signal.disconnect(); } + for (auto signal : signals) { signal.disconnect(); } -} \ No newline at end of file +} diff --git a/src/util/network/wifi.hpp b/src/util/network/wifi.hpp index 45e63fb0..93ced166 100644 --- a/src/util/network/wifi.hpp +++ b/src/util/network/wifi.hpp @@ -10,15 +10,19 @@ using type_signal_access_point = sigc::signal)>; -class WifiNetwork : public Network { +class WifiNetwork : public Network +{ private: sigc::connection access_point_signal; std::map> all_access_points; type_signal_access_point add_ap, remove_ap; + protected: std::shared_ptr wifi_proxy; + public: - WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy); + WifiNetwork(std::string path, std::shared_ptr device_proxy, + std::shared_ptr wifi_proxy); ~WifiNetwork(); type_signal_access_point signal_add_access_point(); @@ -32,4 +36,4 @@ class WifiNetwork : public Network { std::string get_friendly_name() override; std::string get_current_access_point_path(); std::shared_ptr get_current_access_point(); -}; \ No newline at end of file +}; diff --git a/src/util/network/wired.cpp b/src/util/network/wired.cpp index 28aed6fa..bf3a1d9b 100644 --- a/src/util/network/wired.cpp +++ b/src/util/network/wired.cpp @@ -1,7 +1,7 @@ #include "wired.hpp" -WiredNetwork::WiredNetwork(std::string path, std::shared_ptr proxy): +WiredNetwork::WiredNetwork(std::string path, std::shared_ptr proxy) : Network(path, proxy) -{ } +{} std::string WiredNetwork::get_name() { @@ -10,9 +10,11 @@ std::string WiredNetwork::get_name() std::string WiredNetwork::get_icon_name() { - if (is_active()){ + if (is_active()) + { return "network-wired"; } + return "network-wired-offline"; } @@ -20,8 +22,8 @@ std::string WiredNetwork::get_color_name() { return "excellent"; } + std::string WiredNetwork::get_friendly_name() { return "Ethernet"; } - \ No newline at end of file diff --git a/src/util/network/wired.hpp b/src/util/network/wired.hpp index fb454de5..adfa5538 100644 --- a/src/util/network/wired.hpp +++ b/src/util/network/wired.hpp @@ -2,11 +2,12 @@ #include #include "network.hpp" -class WiredNetwork : public Network { +class WiredNetwork : public Network +{ public: WiredNetwork(std::string path, std::shared_ptr proxy); std::string get_name() override; std::string get_icon_name() override; std::string get_color_name() override; std::string get_friendly_name() override; -}; \ No newline at end of file +}; From 5fd81ab002f1ddc5313d013d27faf941c9553a04 Mon Sep 17 00:00:00 2001 From: trigg Date: Wed, 4 Feb 2026 23:29:35 +0000 Subject: [PATCH 08/17] uncrust --- src/util/network/manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index 89f9bc4e..1004f6b2 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -227,7 +227,7 @@ void NetworkManager::check_add_vpn(std::string path) } else { std::cerr << "INVALID TYPES " << conname.get_type_string() << " " << contype.get_type_string() << - std::endl; + std::endl; } } } From 0e1067c223246bc9ff3fd749e402eb20324c8bd1 Mon Sep 17 00:00:00 2001 From: trigg Date: Thu, 5 Feb 2026 18:20:49 +0000 Subject: [PATCH 09/17] util: fixed up styling of network panel util: devices and connections can pass up multiple classes to describe their state in CSS util: split connection into hpp/cpp util: access points have 'has password' concept to see previously used APs util: modems use carrier name for device util: fixed initial modem strength util: each network type has to specify postfix for vpn icons util: wifi shows freq/band, PSK state util: sort wifi widgets by signal strength util: wifi AP name is added to class list to allow custom rules for any name util: wifi classes for band, has password, has psk util: connecting to an unknown wifi now prompts for password Co-authored-by: altrgeek --- data/css/default.css | 40 +++++- src/panel/widgets/network.cpp | 24 ++-- src/util/meson.build | 14 +- src/util/network/bluetooth.hpp | 4 +- src/util/network/connection.cpp | 89 ++++++++++++ src/util/network/connection.hpp | 78 +---------- src/util/network/manager.cpp | 207 +++++++++++++++++++++++++++- src/util/network/manager.hpp | 18 +++ src/util/network/modem.cpp | 36 ++++- src/util/network/modem.hpp | 10 +- src/util/network/network-widget.cpp | 107 +++++++++++++- src/util/network/network-widget.hpp | 8 +- src/util/network/network.hpp | 7 +- src/util/network/null.hpp | 4 +- src/util/network/settings.cpp | 50 +++++++ src/util/network/settings.hpp | 17 +++ src/util/network/wifi-ap.cpp | 122 ++++++++++++++++ src/util/network/wifi-ap.hpp | 15 ++ src/util/network/wifi.cpp | 30 +++- src/util/network/wifi.hpp | 5 +- src/util/network/wired.cpp | 10 +- src/util/network/wired.hpp | 3 +- 22 files changed, 779 insertions(+), 119 deletions(-) create mode 100644 src/util/network/connection.cpp create mode 100644 src/util/network/settings.cpp create mode 100644 src/util/network/settings.hpp diff --git a/data/css/default.css b/data/css/default.css index eed40763..33649e53 100644 --- a/data/css/default.css +++ b/data/css/default.css @@ -72,23 +72,28 @@ border-radius: 3px; color: #41A6B5; } -.excellent { +.excellent>label +{ color: #00ff00; } -.good { +.good>label +{ color: #88ff00; } -.ok { +.ok>label +{ color: #ffff00; } -.weak { +.weak>label +{ color: #ff8800; } -.none { +.none>label +{ color: #ff0000; } @@ -146,6 +151,31 @@ animation-fill-mode: forwards; } + +.network-control-center image.access-point { + -gtk-icon-size:40px; +} + +.network-control-center .access-point.secure .security { + -gtk-icon-size:20px; + color:red; +} + +.network-control-center .access-point.secure.has-password .security { + color:green; +} + +.network-control-center .access-point.has-password{ + font-weight: bold; + background: #8f83; +} + + +.network-control-center .access-point .band { + font-size: 1em; + font-weight: bolder; +} + @keyframes embiggen { to { -gtk-icon-size: 64px; diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 4ecd21a8..2ed0e5ae 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -36,19 +36,23 @@ void WayfireNetworkInfo::init(Gtk::Box *container) void WayfireNetworkInfo::set_connection(std::shared_ptr network) { - status.remove_css_class("none"); - status.remove_css_class("weak"); - status.remove_css_class("bad"); - status.remove_css_class("ok"); - status.remove_css_class("excellent"); + for (auto clas : button_content.get_css_classes()) + { + if ((clas == "flat") || (clas == "network") || (clas == "widget-icon")) + { + continue; + } - status.set_label(network->get_name()); - icon.set_from_icon_name(network->get_icon_symbolic()); - auto color = network->get_color_name(); - if (color != "") + button_content.remove_css_class(clas); + } + + for (auto clas : network->get_css_classes()) { - status.add_css_class(color); + button_content.add_css_class(clas); } + + status.set_label(network->get_name()); + icon.set_from_icon_name(network->get_icon_symbolic()); } WayfireNetworkInfo::~WayfireNetworkInfo() diff --git a/src/util/meson.build b/src/util/meson.build index c1e636d6..d835637f 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -15,9 +15,19 @@ util = static_library( 'network/wifi-ap.cpp', 'network/network.cpp', 'network/modem.cpp', + 'network/settings.cpp', + 'network/connection.cpp', + ], + dependencies: [ + wf_protos, + gtklayershell, + wayland_client, + gtkmm, + wfconfig, + libinotify, + json, ], - dependencies: [wf_protos, gtklayershell, wayland_client, gtkmm, wfconfig, libinotify, json], ) util_includes = include_directories('.') -libutil = declare_dependency(link_with: util, include_directories: util_includes) +libutil = declare_dependency(link_with: util, include_directories: util_includes) \ No newline at end of file diff --git a/src/util/network/bluetooth.hpp b/src/util/network/bluetooth.hpp index 36e06ba9..e0e54dfb 100644 --- a/src/util/network/bluetooth.hpp +++ b/src/util/network/bluetooth.hpp @@ -28,9 +28,9 @@ class BluetoothNetwork : public Network return "network-bluetooth-inactive"; } - std::string get_color_name() override + std::vector get_css_classes() override { - return ""; + return {}; } std::string get_friendly_name() override diff --git a/src/util/network/connection.cpp b/src/util/network/connection.cpp new file mode 100644 index 00000000..0b3c5c15 --- /dev/null +++ b/src/util/network/connection.cpp @@ -0,0 +1,89 @@ +#include "connection.hpp" +#include "network/manager.hpp" + +Connection::Connection() : + Network("/", nullptr), connection_proxy(nullptr), devices({}) +{} + +Connection::Connection(std::string path, std::shared_ptr connection_proxy, + std::vector> devices) : + Network(path, nullptr), connection_proxy(connection_proxy), devices(devices) +{ + /* Bubble up emits from any device here */ + for (auto & it : devices) + { + signals.push_back(it->signal_network_altered().connect( + [this] () + { + network_altered.emit(); + })); + } + + Glib::Variant vpn_data; + connection_proxy->get_cached_property(vpn_data, "Vpn"); + has_vpn = vpn_data.get(); + + if (has_vpn) + { + Glib::Variant vpn_path_start; + connection_proxy->get_cached_property(vpn_path_start, "Connection"); + vpn_path = vpn_path_start.get(); + } +} + +Connection::~Connection() +{ + for (auto signal : signals) + { + signal.disconnect(); + } +} + +std::string Connection::get_name() +{ + if (devices.size() == 0) + { + return "No connection"; + } + + std::string secure = ""; + if (has_vpn) + { + auto settings = NetworkManager::getInstance()->get_vpn(vpn_path); + if (settings) + { + secure = " with " + settings->name; + } else + { + secure = " with VPN"; + } + } + + return devices[0]->get_name() + secure; +} + +std::string Connection::get_icon_name() +{ + if (devices.size() == 0) + { + return "network-disconnected"; + } + + std::string secure = ""; + if (has_vpn) + { + secure = devices[0]->get_secure_variant(); + } + + return devices[0]->get_icon_name() + secure; +} + +std::vector Connection::get_css_classes() +{ + if (devices.size() == 0) + { + return {"none"}; + } + + return devices[0]->get_css_classes(); +} diff --git a/src/util/network/connection.hpp b/src/util/network/connection.hpp index ddafcd7a..b42d72f3 100644 --- a/src/util/network/connection.hpp +++ b/src/util/network/connection.hpp @@ -13,77 +13,13 @@ class Connection : public Network std::vector signals; std::shared_ptr connection_proxy, vpn_proxy; std::vector> devices; + std::string vpn_path = ""; - Connection() : - Network("/", nullptr), connection_proxy(nullptr), devices({}) - {} - + Connection(); Connection(std::string path, std::shared_ptr connection_proxy, - std::vector> devices) : - Network(path, nullptr), connection_proxy(connection_proxy), devices(devices) - { - /* Bubble up emits from any device here */ - for (auto & it : devices) - { - signals.push_back(it->signal_network_altered().connect( - [this] () - { - network_altered.emit(); - })); - } - - Glib::Variant vpn_data; - connection_proxy->get_cached_property(vpn_data, "Vpn"); - has_vpn = vpn_data.get(); - } - - ~Connection() - { - for (auto signal : signals) - { - signal.disconnect(); - } - } - - std::string get_name() - { - if (devices.size() == 0) - { - return "No connection"; - } - - std::string secure = ""; - if (has_vpn) - { - secure = " with VPN"; - } - - return devices[0]->get_name() + secure; - } - - std::string get_icon_name() - { - if (devices.size() == 0) - { - return "network-disconnected"; - } - - std::string secure = ""; - if (has_vpn) - { - secure = "-secure"; - } - - return devices[0]->get_icon_name() + secure; - } - - std::string get_color_name() - { - if (devices.size() == 0) - { - return "none"; - } - - return devices[0]->get_color_name(); - } + std::vector> devices); + ~Connection(); + std::string get_name(); + std::string get_icon_name(); + std::vector get_css_classes(); }; diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index 1004f6b2..45ffc44b 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -2,11 +2,15 @@ #include #include #include +#include #include "manager.hpp" #include "bluetooth.hpp" #include "connection.hpp" +#include "gtkmm/enums.h" #include "network.hpp" +#include "network/settings.hpp" +#include "sigc++/functors/mem_fun.h" #include "vpn.hpp" #include "wifi.hpp" #include "modem.hpp" @@ -30,6 +34,13 @@ NetworkManager::NetworkManager() { + popup_window.set_child(popup_box); + popup_box.append(popup_label); + popup_box.append(popup_entry); + popup_box.set_orientation(Gtk::Orientation::VERTICAL); + popup_entry.set_visibility(false); + popup_entry.signal_activate().connect( + sigc::mem_fun(*this, &NetworkManager::submit_password)); Gio::DBus::Proxy::create_for_bus(Gio::DBus::BusType::SYSTEM, "org.freedesktop.DBus", "/org/freedesktop/DBus", @@ -100,6 +111,61 @@ NetworkManager::NetworkManager() }); } +void NetworkManager::setting_added(std::string path) +{ + auto proxy = Gio::DBus::Proxy::create_sync( + connection, + NM_DBUS_NAME, + path, + "org.freedesktop.NetworkManager.Settings.Connection"); + + all_settings.emplace(path, + new NetworkSettings(path, proxy)); + auto setting = all_settings[path]; + + if (setting->get_ssid() != "") + { + for (auto & device : all_devices) + { + auto wifi = std::dynamic_pointer_cast(device.second); + if (wifi) + { + for (auto & ap : wifi->all_access_points) + { + if (ap.second && (ap.second->get_ssid() == setting->get_ssid())) + { + ap.second->set_has_saved_password(true); + } + } + } + } + } +} + +void NetworkManager::setting_removed(std::string path) +{ + auto setting = all_settings[path]; + if (setting) + { + for (auto & device : all_devices) + { + auto wifi = std::dynamic_pointer_cast(device.second); + if (wifi) + { + for (auto & ap : wifi->all_access_points) + { + if (ap.second->get_ssid() == setting->get_ssid()) + { + ap.second->set_has_saved_password(false); + } + } + } + } + } + + all_settings.erase(path); +} + void NetworkManager::lost_nm() { if (primary_signal) @@ -155,6 +221,7 @@ void NetworkManager::connect_nm() Glib::VariantBase::cast_dynamic>>(ret1); for (auto & it : ret.get()) { + setting_added(it); check_add_vpn(it); vpn_added.emit(it); } @@ -167,12 +234,14 @@ void NetworkManager::connect_nm() { auto var = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + all_settings.erase(var); all_vpns.erase(var); vpn_removed.emit(var); } else if (signal == "NewConnection") { auto var = Glib::VariantBase::cast_dynamic>(container.get_child()).get(); + setting_added(var); check_add_vpn(var); vpn_added.emit(var); } @@ -404,10 +473,21 @@ void NetworkManager::activate_connection(std::string p1, std::string p2, std::st manager->call_sync("ActivateConnection", paths); } catch (...) { - /* - * Most likely no password - * TODO - */ + /* It's most likely a WIFI AP with no password set. Let's ask */ + std::cout << p2 << std::endl; + if (p2.find("/Devices/") != std::string::npos) + { + auto device = std::dynamic_pointer_cast(all_devices[p2]); + if (device) + { + popup_cache_p2 = p2; + popup_cache_p3 = p3; + auto ap = device->get_access_points()[p3]; + popup_label.set_label("Preshared Key required for Access Point '" + ap->get_ssid() + "'"); + popup_window.present(); + popup_window.get_focus(); + } + } } } @@ -499,6 +579,125 @@ void NetworkManager::mobile_global_set(bool value) another_proxy->call_sync("Set", params); } +std::shared_ptr NetworkManager::get_setting_for_ssid(std::string ssid) +{ + if (ssid == "") + { + return nullptr; + } + + for (auto setting : all_settings) + { + if (setting.second->get_ssid() == ssid) + { + return setting.second; + } + } + + return nullptr; +} + +std::shared_ptr NetworkManager::get_vpn(std::string path) +{ + return all_vpns[path]; +} + +void NetworkManager::submit_password() +{ + auto password = popup_entry.get_text(); + if (password.length() == 0) + { + return; + } + + popup_entry.set_text(""); + auto wifi = std::dynamic_pointer_cast(all_devices[popup_cache_p2]); + if (!wifi) + { + return; + } + + auto ap = wifi->get_access_points()[popup_cache_p3]; + if (!ap) + { + return; + } + + auto ssid = ap->get_ssid(); + if (ssid.length() == 0) + { + return; + } + + popup_window.hide(); + + // --- Build settings using glibmm (correct types) --- + + // SSID as byte array 'ay' + std::vector ssid_bytes(ssid.begin(), ssid.end()); + auto ssid_variant = Glib::Variant>::create(ssid_bytes); + + // UUID + gchar *uuid_c = g_uuid_string_random(); + Glib::ustring uuid(uuid_c); + g_free(uuid_c); + + // ----- connection (a{sv}) + std::map connection_map; + connection_map["type"] = + Glib::Variant::create("802-11-wireless"); + connection_map["id"] = Glib::Variant::create(ssid); + connection_map["uuid"] = Glib::Variant::create(uuid); + + // ----- 802-11-wireless (a{sv}) + std::map wifi_map; + wifi_map["ssid"] = ssid_variant; + wifi_map["mode"] = Glib::Variant::create("infrastructure"); + + // ----- 802-11-wireless-security (a{sv}) + std::map sec_map; + bool use_security = !password.empty(); + if (use_security) + { + sec_map["key-mgmt"] = Glib::Variant::create("wpa-psk"); + sec_map["psk"] = Glib::Variant::create(password); + } + + // ------------------------ + // TOP-LEVEL SETTINGS (a{sa{sv}}) + // ------------------------ + std::map> + settings_map; + + settings_map["connection"] = connection_map; + settings_map["802-11-wireless"] = wifi_map; + if (use_security) + { + settings_map["802-11-wireless-security"] = sec_map; + } + + auto settings = Glib::Variant< + std::map>>:: + create(settings_map); + // ------------------------ + // Object paths (o) + // ------------------------ + auto device_path = + Glib::Variant::create(popup_cache_p2); + // Access point path is "/" → NM autoselects AP matching SSID + auto ap_path = Glib::Variant::create("/"); + // ------------------------ + // FINAL TUPLE (a{sa{sv}}, o, o) + // ------------------------ + std::vector args_vec = {settings, device_path, ap_path}; + auto args = Glib::VariantContainerBase::create_tuple(args_vec); + + // ------------------------ + // CALL NetworkManager + // ------------------------ + nm_proxy->call_sync("AddAndActivateConnection", args); +} + void NetworkManager::networking_global_set(bool value) { auto params = Glib::VariantContainerBase::create_tuple(Glib::Variant::create(value)); diff --git a/src/util/network/manager.hpp b/src/util/network/manager.hpp index 8efb61a4..f286e485 100644 --- a/src/util/network/manager.hpp +++ b/src/util/network/manager.hpp @@ -6,10 +6,12 @@ #include #include #include +#include #include "network.hpp" #include "connection.hpp" #include "vpn.hpp" +#include "settings.hpp" using type_signal_network = sigc::signal)>; using type_signal_device_list_changed = sigc::signal>)>; @@ -37,6 +39,7 @@ class NetworkManager std::map> all_devices; std::map> all_vpns; + std::map> all_settings; void on_nm_properties_changed(const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated); @@ -48,6 +51,16 @@ class NetworkManager void connect_nm(); void lost_nm(); + void setting_added(std::string path); + void setting_removed(std::string path); + + Gtk::Window popup_window; + Gtk::Box popup_box; + Gtk::Label popup_label; + Gtk::Entry popup_entry; + + std::string popup_cache_p2 = "", popup_cache_p3 = ""; + public: /* Emitted when the default connection or it's properties change */ type_signal_network signal_default_changed() @@ -151,7 +164,12 @@ class NetworkManager std::tuple mobile_global_enabled(); bool networking_global_enabled(); + std::shared_ptr get_vpn(std::string path); + void wifi_global_set(bool value); void mobile_global_set(bool value); void networking_global_set(bool value); + void submit_password(); + + std::shared_ptr get_setting_for_ssid(std::string ssid); }; diff --git a/src/util/network/modem.cpp b/src/util/network/modem.cpp index f2d85cce..2a2d7d2b 100644 --- a/src/util/network/modem.cpp +++ b/src/util/network/modem.cpp @@ -1,4 +1,7 @@ #include "modem.hpp" +#include "giomm/dbusproxy.h" +#include "glibmm/variant.h" +#include ModemNetwork::ModemNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr modem_proxy) : Network(path, device_proxy), modem_proxy(modem_proxy) @@ -37,7 +40,12 @@ void ModemNetwork::find_mm_proxy(std::string dev_id) mm_proxy = Gio::DBus::Proxy::create_sync(device_proxy->get_connection(), "org.freedesktop.ModemManager1", modem_path, - "org.freedeskop.ModemManager1.Modem"); + "org.freedesktop.ModemManager1.Modem"); + + modem_3gpp_proxy = Gio::DBus::Proxy::create_sync(device_proxy->get_connection(), + "org.freedesktop.ModemManager1", + modem_path, + "org.freedesktop.ModemManager1.Modem.Modem3gpp"); } } } @@ -47,6 +55,15 @@ void ModemNetwork::find_mm_proxy(std::string dev_id) if (mm_proxy) { + /* Get initial values */ + + Glib::VariantBase signal_pair; + mm_proxy->get_cached_property(signal_pair, "SignalQuality"); + + auto [a, b] = + Glib::VariantBase::cast_dynamic>>(signal_pair).get(); + strength = a; + signals.push_back(mm_proxy->signal_properties_changed().connect( [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) @@ -117,7 +134,13 @@ std::string ModemNetwork::get_name() return "Misconfigured Mobile"; } - /* TODO Get Carrier from MM */ + if (modem_3gpp_proxy) + { + Glib::Variant carrier; + modem_3gpp_proxy->get_cached_property(carrier, "OperatorName"); + return carrier.get(); + } + return "Mobile"; } @@ -180,9 +203,14 @@ std::string ModemNetwork::get_icon_name() return "network-mobile-" + get_signal_band() + "-" + get_connection_type_string(); } -std::string ModemNetwork::get_color_name() +std::string ModemNetwork::get_secure_variant() +{ + return "-locked"; +} + +std::vector ModemNetwork::get_css_classes() { - return strength_string(); + return {"modem", get_connection_type_string(), strength_string(), "carrier-" + get_name()}; } std::string ModemNetwork::get_friendly_name() diff --git a/src/util/network/modem.hpp b/src/util/network/modem.hpp index fc7c3efb..64e6354d 100644 --- a/src/util/network/modem.hpp +++ b/src/util/network/modem.hpp @@ -19,6 +19,7 @@ class ModemNetwork : public Network public: unsigned char strength = 0; int caps = 8; + std::shared_ptr modem_3gpp_proxy; std::shared_ptr modem_proxy; std::shared_ptr mm_proxy; ModemNetwork(std::string path, std::shared_ptr device_proxy, @@ -26,10 +27,11 @@ class ModemNetwork : public Network void find_mm_proxy(std::string dev_id); ~ModemNetwork(); std::string strength_string(); - std::string get_name(); + std::string get_name() override; std::string get_signal_band(); std::string get_connection_type_string(); - std::string get_icon_name(); - std::string get_color_name(); - std::string get_friendly_name(); + std::string get_icon_name() override; + std::string get_friendly_name() override; + std::string get_secure_variant() override; + std::vector get_css_classes() override; }; diff --git a/src/util/network/network-widget.cpp b/src/util/network/network-widget.cpp index e546e550..b7aae4a9 100644 --- a/src/util/network/network-widget.cpp +++ b/src/util/network/network-widget.cpp @@ -1,8 +1,11 @@ #include #include #include +#include #include "bluetooth.hpp" +#include "gtk/gtk.h" +#include "gtkmm/enums.h" #include "manager.hpp" #include "modem.hpp" #include "network.hpp" @@ -17,14 +20,44 @@ AccessPointWidget::AccessPointWidget(std::string path_in, std::shared_ptrget_ssid()); - image.set_from_icon_name(ap->get_icon_name()); + wifi.set_from_icon_name(ap->get_icon_name()); + security.set_from_icon_name(ap->get_security_icon_name()); + band.set_label(ap->get_band_name()); + auto classes = get_css_classes(); + for (auto css_class : classes) + { + remove_css_class(css_class); + } + + for (auto css_class : ap->get_css_classes()) + { + add_css_class(css_class); + } }; + + band.set_halign(Gtk::Align::END); + band.add_css_class("band"); + band.set_justify(Gtk::Justification::RIGHT); + security.set_halign(Gtk::Align::END); + security.set_valign(Gtk::Align::END); + security.add_css_class("security"); + + signals.push_back(ap_in->signal_altered().connect(update_ap)); update_ap(); } @@ -37,6 +70,11 @@ AccessPointWidget::~AccessPointWidget() } } +std::shared_ptr AccessPointWidget::get_ap() +{ + return ap; +} + VPNControlWidget::VPNControlWidget(std::shared_ptr config) : config(config) { @@ -73,22 +111,26 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network) : if (wifi) { type = "wifi"; - /* TODO Sort*/ for (auto & it : wifi->get_access_points()) { add_access_point(it.second); } + sort_access_points(); + + signals.push_back(wifi->signal_add_access_point().connect( [this] (std::shared_ptr ap) { add_access_point(ap); + sort_access_points(); })); signals.push_back(wifi->signal_remove_access_point().connect( [this] (std::shared_ptr ap) { remove_access_point(ap->get_path()); + sort_access_points(); })); auto wifi_cb = @@ -96,6 +138,7 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network) : { if (wifi->get_current_access_point_path() == "/") { + sort_access_points(); revealer.set_reveal_child(true); topbox.hide(); } else @@ -131,7 +174,7 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network) : { network->toggle(); })); - label.add_controller(click); + topbox.add_controller(click); /* Set label and image based on friendly info */ auto network_change_cb = [this, network] () @@ -145,6 +188,17 @@ DeviceControlWidget::DeviceControlWidget(std::shared_ptr network) : { label.remove_css_class("active"); } + + auto classes = get_css_classes(); + for (auto css_class : classes) + { + remove_css_class(css_class); + } + + for (auto css_class : network->get_css_classes()) + { + add_css_class(css_class); + } }; signals.push_back(network->signal_network_altered().connect(network_change_cb)); network_change_cb(); @@ -159,6 +213,8 @@ void DeviceControlWidget::remove_access_point(std::string path) } access_points.erase(path); + + sort_access_points(); } void DeviceControlWidget::add_access_point(std::shared_ptr ap) @@ -192,6 +248,8 @@ void DeviceControlWidget::add_access_point(std::shared_ptr ap) widget->add_controller(click); widget->signals.push_back(sig); revealer_box.append(*access_points[path]); + + sort_access_points(); } void DeviceControlWidget::selected_access_point(std::string path) @@ -226,6 +284,47 @@ DeviceControlWidget::~DeviceControlWidget() } } +bool sort_compare(std::pair> a, + std::pair> b) +{ + auto a_ap = a.second->get_ap(); + auto b_ap = b.second->get_ap(); + + /*if (!a_ap->has_saved_password && b_ap->has_saved_password) + * { + * return true; + * }*/ + + return a_ap->get_strength() > b_ap->get_strength(); +} + +void DeviceControlWidget::sort_access_points() +{ + std::vector>> sorting; + for (auto & it : access_points) + { + sorting.push_back(it); + } + + sort(sorting.begin(), sorting.end(), sort_compare); + + std::shared_ptr prev = nullptr; + for (auto & it : sorting) + { + if (!prev) + { + /* Work around not being allowed to pass NULL in gtkmm */ + gtk_box_reorder_child_after((GtkBox*)revealer_box.gobj(), (GtkWidget*)it.second->gobj(), NULL); + } else + { + revealer_box.reorder_child_after(*it.second, *prev); + } + + prev = it.second; + } +} + NetworkControlWidget::NetworkControlWidget() { append(network_manager_failed); diff --git a/src/util/network/network-widget.hpp b/src/util/network/network-widget.hpp index 317f5649..a28441af 100644 --- a/src/util/network/network-widget.hpp +++ b/src/util/network/network-widget.hpp @@ -3,6 +3,7 @@ #include #include +#include "gtkmm/overlay.h" #include "manager.hpp" #include "wifi-ap.hpp" #include "vpn.hpp" @@ -11,8 +12,9 @@ class AccessPointWidget : public Gtk::Box { private: - Gtk::Image image; - Gtk::Label label; + Gtk::Overlay overlay; + Gtk::Image wifi, security; + Gtk::Label label, band; std::shared_ptr ap; std::string path; @@ -20,6 +22,7 @@ class AccessPointWidget : public Gtk::Box std::vector signals; AccessPointWidget(std::string path, std::shared_ptr ap); ~AccessPointWidget(); + std::shared_ptr get_ap(); }; class DeviceControlWidget : public Gtk::Box @@ -39,6 +42,7 @@ class DeviceControlWidget : public Gtk::Box void add_access_point(std::shared_ptr ap); void remove_access_point(std::string path); void selected_access_point(std::string path); + void sort_access_points(); std::string type; }; diff --git a/src/util/network/network.hpp b/src/util/network/network.hpp index 9c37baa3..b4ad8749 100644 --- a/src/util/network/network.hpp +++ b/src/util/network/network.hpp @@ -34,7 +34,7 @@ class Network std::string interface = ""; int last_state = 0; virtual std::string get_name() = 0; - virtual std::string get_color_name() = 0; + virtual std::vector get_css_classes() = 0; Network(std::string path, std::shared_ptr in_proxy); ~Network(); virtual std::string get_friendly_name(); @@ -46,6 +46,11 @@ class Network return get_icon_name() + "-symbolic"; } + virtual std::string get_secure_variant() + { + return ""; + } + std::string get_path(); void disconnect(); void connect(std::string path_extra); diff --git a/src/util/network/null.hpp b/src/util/network/null.hpp index a7eaa892..eb4acda0 100644 --- a/src/util/network/null.hpp +++ b/src/util/network/null.hpp @@ -17,8 +17,8 @@ class NullNetwork : public Network return "network-offline"; } - std::string get_color_name() override + std::vector get_css_classes() override { - return "none"; + return {"none"}; } }; diff --git a/src/util/network/settings.cpp b/src/util/network/settings.cpp new file mode 100644 index 00000000..514a71a0 --- /dev/null +++ b/src/util/network/settings.cpp @@ -0,0 +1,50 @@ +#include "settings.hpp" +#include "glibmm/variant.h" +#include "sigc++/functors/mem_fun.h" +#include "giomm/dbusproxy.h" +#include + +NetworkSettings::NetworkSettings(std::string path, std::shared_ptr proxy) : + proxy(proxy) +{ + proxy->signal_signal().connect( + sigc::mem_fun(*this, &NetworkSettings::signal)); + read_contents(); +} + +void NetworkSettings::signal(const Glib::ustring& name, const Glib::ustring& signal, + const Glib::VariantContainerBase& variants) +{ + if (signal == "Updates") + { + read_contents(); + } +} + +void NetworkSettings::read_contents() +{ + auto contents = Glib::VariantBase::cast_dynamic>>>(proxy->call_sync("GetSettings").get_child()).get(); + + setting_name = + Glib::VariantBase::cast_dynamic>(contents["connection"]["id"]).get(); + + if (contents.count("802-11-wireless") == 1) + { + auto ssid_bytes = + Glib::VariantBase::cast_dynamic>>(contents[ + "802-11-wireless"][ + "ssid"]).get(); + ssid = std::string(ssid_bytes.begin(), ssid_bytes.end()); + } +} + +std::string NetworkSettings::get_ssid() +{ + return ssid; +} + +std::string NetworkSettings::get_name() +{ + return setting_name; +} diff --git a/src/util/network/settings.hpp b/src/util/network/settings.hpp new file mode 100644 index 00000000..f82b87ea --- /dev/null +++ b/src/util/network/settings.hpp @@ -0,0 +1,17 @@ +#pragma once +#include +class NetworkSettings +{ + private: + std::shared_ptr proxy; + std::string setting_name = ""; + std::string ssid = ""; + + public: + NetworkSettings(std::string path, std::shared_ptr proxy); + void signal(const Glib::ustring&, const Glib::ustring&, const Glib::VariantContainerBase&); + void read_contents(); + + std::string get_ssid(); + std::string get_name(); +}; diff --git a/src/util/network/wifi-ap.cpp b/src/util/network/wifi-ap.cpp index 25a1d5ed..deef6b1d 100644 --- a/src/util/network/wifi-ap.cpp +++ b/src/util/network/wifi-ap.cpp @@ -1,5 +1,7 @@ #include "wifi-ap.hpp" +#include "glibmm/variant.h" #include "network.hpp" +#include std::string AccessPoint::get_path() { @@ -18,6 +20,14 @@ AccessPoint::AccessPoint(std::string path, std::shared_ptr acc auto ssid_bytes = ssid_start.get(); ssid = std::string(ssid_bytes.begin(), ssid_bytes.end()); + Glib::Variant security_flags_start; + access_point_proxy->get_cached_property(security_flags_start, "RsnFlags"); + security_flags = security_flags_start.get(); + + Glib::Variant freq_start; + access_point_proxy->get_cached_property(freq_start, "Frequency"); + freq = freq_start.get(); + signals.push_back(access_point_proxy->signal_properties_changed().connect( [this] (const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated) @@ -35,6 +45,18 @@ AccessPoint::AccessPoint(std::string path, std::shared_ptr acc Glib::VariantBase::cast_dynamic>>(it.second).get(); ssid = std::string(value.begin(), value.end()); access_point_altered.emit(); + } else if (it.first == "RsnFlags") + { + auto value = + Glib::VariantBase::cast_dynamic>(it.second).get(); + security_flags = value; + access_point_altered.emit(); + } else if (it.first == "Frequency") + { + auto value = + Glib::VariantBase::cast_dynamic>(it.second).get(); + freq = value; + access_point_altered.emit(); } } })); @@ -87,3 +109,103 @@ AccessPoint::~AccessPoint() signal.disconnect(); } } + +std::string AccessPoint::get_security_icon_name() +{ + if (security_flags | NM_SOME_WPA_SECURITY) + { + return "channel-secure-symbolic"; + } + + return "channel-insecure-symbolic"; +} + +std::string AccessPoint::get_band_name() +{ + if ((freq > 800) && (freq < 1000)) + { + return "900Mhz"; + } else if ((freq > 2000) && (freq < 3000)) + { + return "2.4 Ghz"; + } else if ((freq >= 5000) && (freq < 6000)) + { + return "5 Ghz"; + } else if ((freq >= 6000) && (freq < 7000)) + { + return "6 Ghz"; + } else if ((freq >= 40000) && (freq < 50000)) + { + return "45 Ghz"; + } else if ((freq >= 57000) && (freq < 74000)) + { + return "60 Ghz"; + } + + return "???"; +} + +std::vector AccessPoint::get_css_classes() +{ + /* Set a bunch of AP-specific info here + * This allows theme makers to put much more detail in */ + std::vector classlist; + classlist.push_back("access-point"); + if ((freq > 800) && (freq < 1000)) + { + classlist.push_back("f900mhz"); + } else if ((freq > 2000) && (freq < 3000)) + { + classlist.push_back("f2-4ghz"); + } else if ((freq >= 5000) && (freq < 6000)) + { + classlist.push_back("f5ghz"); + } else if ((freq >= 6000) && (freq < 7000)) + { + classlist.push_back("f6ghz"); + } else if ((freq >= 40000) && (freq < 50000)) + { + classlist.push_back("f45ghz"); + } else if ((freq >= 57000) && (freq < 74000)) + { + classlist.push_back("f60ghz"); + } + + classlist.push_back(strength_string()); + + if (ssid.length() > 0) + { + classlist.push_back("ap-" + ssid); + } + + if (security_flags | NM_SOME_WPA_SECURITY) + { + classlist.push_back("secure"); + } else + { + classlist.push_back("insecure"); + } + + if (saved_password) + { + classlist.push_back("has-password"); + } + + return classlist; +} + +unsigned char AccessPoint::get_strength() +{ + return strength; +} + +void AccessPoint::set_has_saved_password(bool new_val) +{ + saved_password = new_val; + access_point_altered.emit(); +} + +bool AccessPoint::has_saved_password() +{ + return saved_password; +} diff --git a/src/util/network/wifi-ap.hpp b/src/util/network/wifi-ap.hpp index aae8897c..e53ffe78 100644 --- a/src/util/network/wifi-ap.hpp +++ b/src/util/network/wifi-ap.hpp @@ -1,8 +1,13 @@ #pragma once +#include "network/network.hpp" +#include "network/settings.hpp" #include "sigc++/connection.h" #include #include +/* 256 + 512, Has *some* kind of password security */ +#define NM_SOME_WPA_SECURITY 0x300 + using type_signal_access_point_altered = sigc::signal; class AccessPoint @@ -11,10 +16,14 @@ class AccessPoint std::string ap_path; type_signal_access_point_altered access_point_altered; unsigned char strength; + unsigned int security_flags; + unsigned int freq; std::string ssid = ""; std::vector signals; + bool saved_password; public: + std::string get_path(); std::shared_ptr access_point_proxy; AccessPoint(std::string path, std::shared_ptr access_point_proxy); @@ -22,5 +31,11 @@ class AccessPoint std::string get_ssid(); std::string strength_string(); std::string get_icon_name(); + std::string get_security_icon_name(); + std::string get_band_name(); + std::vector get_css_classes(); type_signal_access_point_altered signal_altered(); + unsigned char get_strength(); + bool has_saved_password(); + void set_has_saved_password(bool); }; diff --git a/src/util/network/wifi.cpp b/src/util/network/wifi.cpp index 20cdceac..846ed781 100644 --- a/src/util/network/wifi.cpp +++ b/src/util/network/wifi.cpp @@ -1,8 +1,9 @@ #include #include - +#include #include "wifi-ap.hpp" #include "wifi.hpp" +#include "manager.hpp" type_signal_access_point WifiNetwork::signal_add_access_point() { @@ -26,6 +27,16 @@ void WifiNetwork::add_access_point(std::string path) path, "org.freedesktop.NetworkManager.AccessPoint"); all_access_points.emplace(path, std::make_shared(path, ap_proxy)); + auto ap = all_access_points[path]; + + auto setting = NetworkManager::getInstance()->get_setting_for_ssid(ap->get_ssid()); + if (setting) + { + ap->set_has_saved_password(true); + } else + { + ap->set_has_saved_password(false); + } } void WifiNetwork::remove_access_point(std::string path) @@ -112,9 +123,17 @@ std::string WifiNetwork::get_name() return "Wifi..."; } -std::string WifiNetwork::get_color_name() +std::vector WifiNetwork::get_css_classes() { - return ""; + std::vector list = {"wifi"}; + auto ap = get_current_access_point(); + if (ap) + { + auto aplist = ap->get_css_classes(); + list.insert(list.end(), aplist.begin(), aplist.end()); + } + + return list; } std::string WifiNetwork::get_icon_name() @@ -170,3 +189,8 @@ WifiNetwork::~WifiNetwork() signal.disconnect(); } } + +std::string WifiNetwork::get_secure_variant() +{ + return "-secure"; +} diff --git a/src/util/network/wifi.hpp b/src/util/network/wifi.hpp index 93ced166..9fed88d4 100644 --- a/src/util/network/wifi.hpp +++ b/src/util/network/wifi.hpp @@ -14,13 +14,13 @@ class WifiNetwork : public Network { private: sigc::connection access_point_signal; - std::map> all_access_points; type_signal_access_point add_ap, remove_ap; protected: std::shared_ptr wifi_proxy; public: + std::map> all_access_points; WifiNetwork(std::string path, std::shared_ptr device_proxy, std::shared_ptr wifi_proxy); ~WifiNetwork(); @@ -31,9 +31,10 @@ class WifiNetwork : public Network void add_access_point(std::string path); void remove_access_point(std::string path); std::string get_name() override; - std::string get_color_name() override; + std::vector get_css_classes() override; std::string get_icon_name() override; std::string get_friendly_name() override; + std::string get_secure_variant() override; std::string get_current_access_point_path(); std::shared_ptr get_current_access_point(); }; diff --git a/src/util/network/wired.cpp b/src/util/network/wired.cpp index bf3a1d9b..93df96fc 100644 --- a/src/util/network/wired.cpp +++ b/src/util/network/wired.cpp @@ -1,4 +1,5 @@ #include "wired.hpp" +#include WiredNetwork::WiredNetwork(std::string path, std::shared_ptr proxy) : Network(path, proxy) {} @@ -18,12 +19,17 @@ std::string WiredNetwork::get_icon_name() return "network-wired-offline"; } -std::string WiredNetwork::get_color_name() +std::vector WiredNetwork::get_css_classes() { - return "excellent"; + return {"ethernet", "good"}; } std::string WiredNetwork::get_friendly_name() { return "Ethernet"; } + +std::string WiredNetwork::get_secure_variant() +{ + return "-secure"; +} diff --git a/src/util/network/wired.hpp b/src/util/network/wired.hpp index adfa5538..81f1e256 100644 --- a/src/util/network/wired.hpp +++ b/src/util/network/wired.hpp @@ -8,6 +8,7 @@ class WiredNetwork : public Network WiredNetwork(std::string path, std::shared_ptr proxy); std::string get_name() override; std::string get_icon_name() override; - std::string get_color_name() override; std::string get_friendly_name() override; + std::vector get_css_classes() override; + std::string get_secure_variant() override; }; From dc15d066e54de353ce43c3752a7e0d9b2671506e Mon Sep 17 00:00:00 2001 From: trigg Date: Thu, 5 Feb 2026 20:23:01 +0000 Subject: [PATCH 10/17] util: bluetooth implemented --- src/util/network/bluetooth.hpp | 11 +++++++++-- src/util/network/manager.cpp | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/util/network/bluetooth.hpp b/src/util/network/bluetooth.hpp index e0e54dfb..b0bf2ecc 100644 --- a/src/util/network/bluetooth.hpp +++ b/src/util/network/bluetooth.hpp @@ -15,7 +15,14 @@ class BluetoothNetwork : public Network std::string get_name() override { - return ""; + if (bluetooth_proxy) + { + Glib::Variant name; + bluetooth_proxy->get_cached_property(name, "Name"); + return name.get(); + } + + return "Bluetooth"; } std::string get_icon_name() override @@ -30,7 +37,7 @@ class BluetoothNetwork : public Network std::vector get_css_classes() override { - return {}; + return {"bluetooth"}; } std::string get_friendly_name() override diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index 45ffc44b..57b92232 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -352,7 +352,7 @@ void NetworkManager::add_network(std::string path) auto bluetooth_proxy = Gio::DBus::Proxy::create_sync(connection, NM_DBUS_NAME, path, - "org.freedesktop.NetworkManager.Devices.Bluetooth"); + "org.freedesktop.NetworkManager.Device.Bluetooth"); all_devices.emplace(path, new BluetoothNetwork(path, device_proxy, bluetooth_proxy)); device_added.emit(all_devices[path]); } else if (connection_type == ETHERNET_TYPE) From 329d650d83bf934dc8808f70cb6764be6d307d6a Mon Sep 17 00:00:00 2001 From: trigg Date: Thu, 5 Feb 2026 20:34:52 +0000 Subject: [PATCH 11/17] util: bluetooth themeing --- data/css/default.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/css/default.css b/data/css/default.css index 33649e53..a2e8ebf9 100644 --- a/data/css/default.css +++ b/data/css/default.css @@ -96,6 +96,10 @@ { color: #ff0000; } +.bluetooth>label +{ + color: #8888ff; +} .wf-dock, .wf-dock .out-box { From 9f0cd875794ce98a210d43691667c7b1f82e0101 Mon Sep 17 00:00:00 2001 From: trigg Date: Thu, 5 Feb 2026 20:53:27 +0000 Subject: [PATCH 12/17] panel: option to have icon-only for network --- metadata/panel.xml | 4 ++++ src/panel/widgets/network.cpp | 11 +++++++++++ src/panel/widgets/network.hpp | 1 + 3 files changed, 16 insertions(+) diff --git a/metadata/panel.xml b/metadata/panel.xml index b59900e7..451e9f96 100644 --- a/metadata/panel.xml +++ b/metadata/panel.xml @@ -165,6 +165,10 @@ <_short>On Click Command default + <_short>Menu diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 2ed0e5ae..3d9b1f90 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -29,6 +29,17 @@ void WayfireNetworkInfo::init(Gtk::Box *container) icon.set_valign(Gtk::Align::CENTER); + no_label.set_callback([this] () + { + if (no_label) + { + status.hide(); + } else + { + status.show(); + } + }); + signals.push_back(network_manager->signal_default_changed().connect( sigc::mem_fun(*this, &WayfireNetworkInfo::set_connection))); set_connection(network_manager->get_primary_network()); diff --git a/src/panel/widgets/network.hpp b/src/panel/widgets/network.hpp index c7b85fae..2d9c6973 100644 --- a/src/panel/widgets/network.hpp +++ b/src/panel/widgets/network.hpp @@ -25,6 +25,7 @@ class WayfireNetworkInfo : public WayfireWidget WfOption status_color_opt{"panel/network_status_use_color"}; WfOption status_font_opt{"panel/network_status_font"}; WfOption click_command_opt{"panel/network_onclick_command"}; + WfOption no_label{"panel/network_no_label"}; NetworkControlWidget control; From 689d1f840f9062637896c01c0f609b7e7c577222 Mon Sep 17 00:00:00 2001 From: trigg Date: Thu, 5 Feb 2026 21:16:32 +0000 Subject: [PATCH 13/17] panel: network reintroduce alternative actions --- src/panel/widgets/network.cpp | 39 +++++++++++++++++++++++++++++++++++ src/panel/widgets/network.hpp | 1 + 2 files changed, 40 insertions(+) diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 3d9b1f90..52397559 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -1,4 +1,7 @@ #include "network.hpp" +#include "gtkmm/gesture.h" +#include "gtkmm/gestureclick.h" +#include "gtkmm/gesturelongpress.h" #include "network/network.hpp" #include #include @@ -40,6 +43,30 @@ void WayfireNetworkInfo::init(Gtk::Box *container) } }); + auto click = Gtk::GestureClick::create(); + click->set_button(3); + signals.push_back(click->signal_released().connect( + [this] (int, double, double) + { + on_click(); + })); + signals.push_back(click->signal_pressed().connect( + [click] (int, double, double) + { + click->set_state(Gtk::EventSequenceState::CLAIMED); + })); + + auto touch = Gtk::GestureLongPress::create(); + touch->set_touch_only(true); + signals.push_back(touch->signal_pressed().connect( + [this] (double, double) + { + on_click(); + })); + + button->add_controller(touch); + button->add_controller(click); + signals.push_back(network_manager->signal_default_changed().connect( sigc::mem_fun(*this, &WayfireNetworkInfo::set_connection))); set_connection(network_manager->get_primary_network()); @@ -66,6 +93,18 @@ void WayfireNetworkInfo::set_connection(std::shared_ptr network) icon.set_from_icon_name(network->get_icon_symbolic()); } +void WayfireNetworkInfo::on_click() +{ + if ((std::string)click_command_opt != "default") + { + Glib::spawn_command_line_async((std::string)click_command_opt); + } else + { + std::string command = "env XDG_CURRENT_DESKTOP=GNOME gnome-control-center"; + Glib::spawn_command_line_async(command); + } +} + WayfireNetworkInfo::~WayfireNetworkInfo() { for (auto signal : signals) diff --git a/src/panel/widgets/network.hpp b/src/panel/widgets/network.hpp index 2d9c6973..271ac444 100644 --- a/src/panel/widgets/network.hpp +++ b/src/panel/widgets/network.hpp @@ -15,6 +15,7 @@ class WayfireNetworkInfo : public WayfireWidget { + void on_click(); std::vector signals; std::shared_ptr network_manager; std::unique_ptr button; From f33bc931764b3b0d52e44065dfedb8bd1c46594c Mon Sep 17 00:00:00 2001 From: trigg Date: Thu, 5 Feb 2026 22:20:33 +0000 Subject: [PATCH 14/17] dock: optional network control --- data/css/default.css | 23 +++++++++++++++-------- metadata/dock.xml | 4 ++++ src/dock/dock.cpp | 35 +++++++++++++++++++++++++++++++++++ src/dock/dock.hpp | 1 + 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/data/css/default.css b/data/css/default.css index a2e8ebf9..3dfa00cf 100644 --- a/data/css/default.css +++ b/data/css/default.css @@ -102,7 +102,7 @@ } .wf-dock, -.wf-dock .out-box { +.wf-dock>.out-box { background: transparent; } @@ -113,18 +113,18 @@ border-radius: 1em; } -.wf-dock button { +.wf-dock button.toplevel-icon { background: transparent; padding-left: 0rem; padding-right: 0rem; } -.wf-dock button.activated { +.wf-dock .box button.activated { border-bottom: 3px solid white; margin-bottom: 5px; } -.wf-dock image { +.wf-dock .box image { background: transparent; padding-left: 0rem; padding-right: 0rem; @@ -132,7 +132,7 @@ -gtk-icon-transform: scale(0.7); } -.wf-dock image:hover { +.wf-dock .box image:hover { background: transparent; padding-left: 0rem; padding-right: 0rem; @@ -140,14 +140,14 @@ -gtk-icon-transform: scale(1.0); } -.wf-dock image { +.wf-dock .box image.toplevel-icon { animation-name: embiggen; animation-duration: 1000ms; animation-timing-function: linear; animation-iteration-count: 1; } -.wf-dock .closing image { +.wf-dock .box .closing image.toplevel-icon { animation-name: kromulent; animation-duration: 1000ms; animation-timing-function: linear; @@ -155,9 +155,16 @@ animation-fill-mode: forwards; } +.wf-dock .network .image-button{ + -gtk-icon-size:64px; +} + +.wf-dock .network-control-center { + -gtk-icon-size: 48px; +} .network-control-center image.access-point { - -gtk-icon-size:40px; + -gtk-icon-size: 40px; } .network-control-center .access-point.secure .security { diff --git a/metadata/dock.xml b/metadata/dock.xml index 3451c111..43aee187 100644 --- a/metadata/dock.xml +++ b/metadata/dock.xml @@ -45,5 +45,9 @@ <_long>Keep all window icons for up to 2 seconds to allow CSS animations. true + diff --git a/src/dock/dock.cpp b/src/dock/dock.cpp index 763cbfdb..8710ca95 100644 --- a/src/dock/dock.cpp +++ b/src/dock/dock.cpp @@ -4,12 +4,17 @@ #include #include +#include #include #include #include #include "dock.hpp" #include "../util/gtk-utils.hpp" +#include "gtkmm/menubutton.h" +#include "network/manager.hpp" +#include "network/network-widget.hpp" +#include "network/network.hpp" #include @@ -20,13 +25,18 @@ class WfDock::impl wl_surface *_wl_surface; Gtk::Box out_box; Gtk::Box box; + std::unique_ptr network_image; + std::unique_ptr network_control; WfOption css_path{"dock/css_path"}; WfOption dock_height{"dock/dock_height"}; + WfOption network{"dock/show_network_status"}; public: impl(WayfireOutput *output) { + network_image = std::make_unique("dock"); + this->output = output; window = std::unique_ptr( new WayfireAutohidingWindow(output, "dock")); @@ -55,6 +65,31 @@ class WfDock::impl } } + if (network) + { + add_child(*network_image); + network_control = std::make_unique(); + network_image->get_popover()->set_child(*network_control); + network_image->set_has_frame(false); + NetworkManager::getInstance()->signal_default_changed().connect( + [this] (std::shared_ptr network) + { + network_image->set_icon_name(network->get_icon_name()); + for (auto clas : network_image->get_css_classes()) + { + network_image->remove_css_class(clas); + } + + for (auto clas : network->get_css_classes()) + { + network_image->add_css_class(clas); + } + + network_image->add_css_class("network"); + network_image->add_css_class("flat"); + }); + } + window->present(); _wl_surface = gdk_wayland_surface_get_wl_surface( window->get_surface()->gobj()); diff --git a/src/dock/dock.hpp b/src/dock/dock.hpp index d4db695c..6b1d93c5 100644 --- a/src/dock/dock.hpp +++ b/src/dock/dock.hpp @@ -5,6 +5,7 @@ #include #include +#include "network/manager.hpp" #include "wf-shell-app.hpp" class WfDock From 679a73b7cbc34611d30a094d27dc2305262f16e9 Mon Sep 17 00:00:00 2001 From: trigg Date: Fri, 6 Feb 2026 10:04:40 +0000 Subject: [PATCH 15/17] dock: add network name as tooltip --- src/dock/dock.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dock/dock.cpp b/src/dock/dock.cpp index 8710ca95..b4be4433 100644 --- a/src/dock/dock.cpp +++ b/src/dock/dock.cpp @@ -85,6 +85,8 @@ class WfDock::impl network_image->add_css_class(clas); } + network_image->set_tooltip_text(network->get_name()); + network_image->add_css_class("network"); network_image->add_css_class("flat"); }); From 41bf77a76377a2c661833d2b2741443afa903387 Mon Sep 17 00:00:00 2001 From: trigg Date: Sat, 7 Feb 2026 09:46:06 +0000 Subject: [PATCH 16/17] util: use weak_ptr for network manager --- src/dock/dock.cpp | 5 +++-- src/dock/dock.hpp | 1 + src/panel/panel.cpp | 2 ++ src/util/network/manager.cpp | 21 ++++++++++----------- src/util/network/manager.hpp | 19 +++++++++++++------ 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/dock/dock.cpp b/src/dock/dock.cpp index b4be4433..9c0a695c 100644 --- a/src/dock/dock.cpp +++ b/src/dock/dock.cpp @@ -11,7 +11,6 @@ #include "dock.hpp" #include "../util/gtk-utils.hpp" -#include "gtkmm/menubutton.h" #include "network/manager.hpp" #include "network/network-widget.hpp" #include "network/network.hpp" @@ -27,6 +26,7 @@ class WfDock::impl Gtk::Box box; std::unique_ptr network_image; std::unique_ptr network_control; + std::shared_ptr network_manager; WfOption css_path{"dock/css_path"}; WfOption dock_height{"dock/dock_height"}; @@ -67,11 +67,12 @@ class WfDock::impl if (network) { + network_manager = NetworkManager::getInstance(); add_child(*network_image); network_control = std::make_unique(); network_image->get_popover()->set_child(*network_control); network_image->set_has_frame(false); - NetworkManager::getInstance()->signal_default_changed().connect( + network_manager->signal_default_changed().connect( [this] (std::shared_ptr network) { network_image->set_icon_name(network->get_icon_name()); diff --git a/src/dock/dock.hpp b/src/dock/dock.hpp index 6b1d93c5..ea5b449c 100644 --- a/src/dock/dock.hpp +++ b/src/dock/dock.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index 0864fb1f..852e65e3 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -14,6 +14,7 @@ #include #include "panel.hpp" +#include "network/manager.hpp" #include "widgets/battery.hpp" #include "widgets/command-output.hpp" #include "widgets/language.hpp" @@ -243,6 +244,7 @@ class WayfirePanel::impl { const auto lock_sn_watcher = Watcher::Instance(); const auto lock_notification_daemon = Daemon::Instance(); + const auto lock_network_manager = NetworkManager::getInstanceIfExists(); for (auto child : box.get_children()) { box.remove(*child); diff --git a/src/util/network/manager.cpp b/src/util/network/manager.cpp index 57b92232..8a9ac238 100644 --- a/src/util/network/manager.cpp +++ b/src/util/network/manager.cpp @@ -39,8 +39,8 @@ NetworkManager::NetworkManager() popup_box.append(popup_entry); popup_box.set_orientation(Gtk::Orientation::VERTICAL); popup_entry.set_visibility(false); - popup_entry.signal_activate().connect( - sigc::mem_fun(*this, &NetworkManager::submit_password)); + our_signals.push_back(popup_entry.signal_activate().connect( + sigc::mem_fun(*this, &NetworkManager::submit_password))); Gio::DBus::Proxy::create_for_bus(Gio::DBus::BusType::SYSTEM, "org.freedesktop.DBus", "/org/freedesktop/DBus", @@ -67,7 +67,7 @@ NetworkManager::NetworkManager() } /* https://dbus.freedesktop.org/doc/dbus-java/api/org/freedesktop/DBus.NameOwnerChanged.html */ - dbus_signals.push_back(manager_proxy->signal_signal().connect( + our_signals.push_back(manager_proxy->signal_signal().connect( [this] (const Glib::ustring & sender_name, const Glib::ustring & signal_name, const Glib::VariantContainerBase & params) @@ -186,7 +186,7 @@ void NetworkManager::lost_nm() all_vpns.clear(); primary_connection = "/"; primary_connection_obj = std::make_shared(); - for (auto signal : nm_signals) + for (auto signal : nm_dbus_signals) { signal.disconnect(); } @@ -226,7 +226,7 @@ void NetworkManager::connect_nm() vpn_added.emit(it); } - nm_signals.push_back(settings_proxy->signal_signal().connect( + nm_dbus_signals.push_back(settings_proxy->signal_signal().connect( [this] (const Glib::ustring& sender, const Glib::ustring& signal, const Glib::VariantContainerBase& container) { @@ -257,10 +257,10 @@ void NetworkManager::connect_nm() return; } - nm_signals.push_back(nm_proxy->signal_properties_changed().connect( + nm_dbus_signals.push_back(nm_proxy->signal_properties_changed().connect( sigc::mem_fun(*this, &NetworkManager::on_nm_properties_changed))); - nm_signals.push_back(nm_proxy->signal_signal().connect( + nm_dbus_signals.push_back(nm_proxy->signal_signal().connect( sigc::mem_fun(*this, &NetworkManager::on_nm_signal))); /* Fill Initial List*/ @@ -311,7 +311,7 @@ void NetworkManager::get_all_devices_cb(std::shared_ptr async) } /* Now get the current connection */ - nm_signals.push_back(Glib::signal_idle().connect([this] () + nm_dbus_signals.push_back(Glib::signal_idle().connect([this] () { Glib::Variant path_read; nm_proxy->get_cached_property(path_read, "PrimaryConnection"); @@ -461,7 +461,6 @@ std::shared_ptr NetworkManager::get_primary_network() void NetworkManager::activate_connection(std::string p1, std::string p2, std::string p3) { - auto manager = NetworkManager::getInstance()->get_nm_proxy(); Glib::VariantStringBase path1, path2, path3; Glib::VariantStringBase::create_object_path(path1, p1); Glib::VariantStringBase::create_object_path(path2, p2); @@ -470,7 +469,7 @@ void NetworkManager::activate_connection(std::string p1, std::string p2, std::st // auto data = Glib::VariantContainerBase::create_tuple(paths); try { - manager->call_sync("ActivateConnection", paths); + nm_proxy->call_sync("ActivateConnection", paths); } catch (...) { /* It's most likely a WIFI AP with no password set. Let's ask */ @@ -708,7 +707,7 @@ NetworkManager::~NetworkManager() { lost_nm(); /* Signals that outlast each NetworkManager start/stop but need to clear on widget reload */ - for (auto signal : dbus_signals) + for (auto signal : our_signals) { signal.disconnect(); } diff --git a/src/util/network/manager.hpp b/src/util/network/manager.hpp index f286e485..17e4c21b 100644 --- a/src/util/network/manager.hpp +++ b/src/util/network/manager.hpp @@ -30,7 +30,8 @@ class NetworkManager Glib::RefPtr connection; Glib::RefPtr nm_proxy, settings_proxy, manager_proxy; - std::vector nm_signals, dbus_signals; + /* Connections that must be severed after NM Dbus is lost, and this NM is deconstructed*/ + std::vector nm_dbus_signals, our_signals; sigc::connection debounce, primary_signal; std::string primary_connection = ""; @@ -60,6 +61,7 @@ class NetworkManager Gtk::Entry popup_entry; std::string popup_cache_p2 = "", popup_cache_p3 = ""; + inline static std::weak_ptr instance; public: /* Emitted when the default connection or it's properties change */ @@ -139,16 +141,21 @@ class NetworkManager return all_devices; } - /* TODO Consider allowing this to lose last reference */ static std::shared_ptr getInstance() { - static std::shared_ptr instance; - if (!instance) + if (instance.expired()) { - instance = std::make_shared(); + auto instance_now = std::make_shared(); + instance = instance_now; + return instance_now; } - return instance; + return instance.lock(); + } + + static std::shared_ptr getInstanceIfExists() + { + return instance.lock(); } NetworkManager(); From f653367d37ef4a83e574b8eb0e2380b3a20874ec Mon Sep 17 00:00:00 2001 From: trigg Date: Sat, 7 Feb 2026 09:47:20 +0000 Subject: [PATCH 17/17] panel: hide network label on start if needed --- src/panel/widgets/network.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/panel/widgets/network.cpp b/src/panel/widgets/network.cpp index 52397559..a74fa7dc 100644 --- a/src/panel/widgets/network.cpp +++ b/src/panel/widgets/network.cpp @@ -32,7 +32,7 @@ void WayfireNetworkInfo::init(Gtk::Box *container) icon.set_valign(Gtk::Align::CENTER); - no_label.set_callback([this] () + auto show_hide_label = [this] () { if (no_label) { @@ -41,7 +41,9 @@ void WayfireNetworkInfo::init(Gtk::Box *container) { status.show(); } - }); + }; + no_label.set_callback(show_hide_label); + show_hide_label(); auto click = Gtk::GestureClick::create(); click->set_button(3);