diff --git a/metadata/panel.xml b/metadata/panel.xml index 92289222..66b399e3 100644 --- a/metadata/panel.xml +++ b/metadata/panel.xml @@ -242,6 +242,18 @@ default + + <_short>Power profiles + + <_short>Battery Icon Size + 0 + 0 + + + <_short>Battery Font + default + + <_short>Network diff --git a/src/panel/meson.build b/src/panel/meson.build index d569ea74..06390da5 100644 --- a/src/panel/meson.build +++ b/src/panel/meson.build @@ -1,5 +1,6 @@ widget_sources = [ 'widgets/battery.cpp', + 'widgets/power-profiles.cpp', 'widgets/menu/menu.cpp', 'widgets/menu/layout.cpp', 'widgets/menu/logout.cpp', @@ -88,4 +89,4 @@ executable( ['panel.cpp', version_h] + widget_sources, dependencies: deps, install: true, -) \ No newline at end of file +) diff --git a/src/panel/panel.cpp b/src/panel/panel.cpp index f85d09ca..e1a077d0 100644 --- a/src/panel/panel.cpp +++ b/src/panel/panel.cpp @@ -16,6 +16,7 @@ #include "network/manager.hpp" #include "widgets/battery.hpp" +#include "widgets/power-profiles.hpp" #include "widgets/command-output.hpp" #include "widgets/language.hpp" #include "widgets/menu/menu.hpp" @@ -232,6 +233,11 @@ class WayfirePanel::impl return Widget(new WayfireBatteryInfo()); } + if (name == "power-profiles") + { + return Widget(new WayfirePowerProfiles()); + } + if (name == "volume") { #ifdef HAVE_PULSE @@ -632,6 +638,7 @@ void WayfirePanelApp::on_activate() {"panel/menu_category_icon_size", ".app-category .default-icon"}, {"panel/launchers_size", ".launcher.widget-icon"}, {"panel/battery_icon_size", ".battery image.widget-icon"}, + {"panel/power_profiles_icon_size", ".power-profiles image.widget-icon"}, {"panel/network_icon_size", ".network .widget-icon"}, {"panel/volume_icon_size", ".volume .widget-icon"}, {"panel/mixer_icon_size", ".mixer .widget-icon"}, @@ -654,6 +661,7 @@ void WayfirePanelApp::on_activate() new CssFromConfigBool("panel/network_icon_invert_color", ".network-icon{filter:invert(100%);}", ""); new CssFromConfigFont("panel/battery_font", ".battery {", "}"); + new CssFromConfigFont("panel/power_profiles_font", ".power_profiles {", "}"); new CssFromConfigFont("panel/clock_font", ".clock {", "}"); new CssFromConfigFont("panel/weather_font", ".weather {", "}"); } diff --git a/src/panel/widgets/battery.cpp b/src/panel/widgets/battery.cpp index dd230e9f..6858bbff 100644 --- a/src/panel/widgets/battery.cpp +++ b/src/panel/widgets/battery.cpp @@ -2,8 +2,6 @@ #include #include "battery.hpp" -#define POWER_PROFILE_PATH "/org/freedesktop/UPower/PowerProfiles" -#define POWER_PROFILE_NAME "org.freedesktop.UPower.PowerProfiles" #define UPOWER_NAME "org.freedesktop.UPower" #define DISPLAY_DEVICE "/org/freedesktop/UPower/devices/DisplayDevice" @@ -15,10 +13,6 @@ #define TIMETOEMPTY "TimeToEmpty" #define SHOULD_DISPLAY "IsPresent" -#define DEGRADED "PerformanceDegraded" -#define PROFILES "Profiles" -#define ACTIVE_PROFILE "ActiveProfile" - static std::string get_device_type_description(uint32_t type) { if (type == 2) @@ -77,12 +71,6 @@ void WayfireBatteryInfo::on_properties_changed( void WayfireBatteryInfo::update_icon() { - if (!feat_bat && feat_modes) - { - icon.set_from_icon_name("power-profile-" + power_mode); - return; - } - Glib::Variant icon_name; display_device->get_cached_property(icon_name, ICON); icon.set_from_icon_name(icon_name.get()); @@ -150,14 +138,14 @@ void WayfireBatteryInfo::update_details() description += ", " + uint_to_time(time_to_empty.get()) + " remaining"; } - box->set_tooltip_text( + box.set_tooltip_text( get_device_type_description(type.get()) + description); if (status_opt.value() == BATTERY_STATUS_PERCENT) { label.set_text(percentage_string); overlay.remove_overlay(label); - box->set_child(label); + box.append(label); } else if (status_opt.value() == BATTERY_STATUS_FULL) { label.set_text(description); @@ -167,14 +155,14 @@ void WayfireBatteryInfo::update_details() overlay.remove_overlay(label); } - box->set_child(label); + box.append(label); } else if (status_opt.value() == BATTERY_STATUS_OVERLAY) { label.set_text(percentage_string); - auto children = box->get_children(); + auto children = box.get_children(); if (std::count(children.begin(), children.end(), &label)) { - box->remove(label); + box.remove(label); } overlay.add_overlay(label); @@ -195,46 +183,6 @@ void WayfireBatteryInfo::update_state() "\n\tWayfireBatteryInfo::update_state()" << std::endl; } -bool WayfireBatteryInfo::setup_dbus_power_modes() -{ - 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; - } - - powerprofile_proxy = Gio::DBus::Proxy::create_sync(connection, POWER_PROFILE_NAME, - POWER_PROFILE_PATH, - POWER_PROFILE_NAME); - if (!powerprofile_proxy) - { - std::cout << "Unable to conect to Power Profiles. Continuing" << std::endl; - } else - { - powerprofile_proxy->signal_properties_changed().connect( - sigc::mem_fun(*this, &WayfireBatteryInfo::on_upower_properties_changed)); - Glib::Variant current_profile; - Glib::Variant>> profiles; - powerprofile_proxy->get_cached_property(current_profile, ACTIVE_PROFILE); - powerprofile_proxy->get_cached_property(profiles, PROFILES); - - if (profiles && current_profile) - { - setup_profiles(profiles.get()); - set_current_profile(current_profile.get()); - return true; - } else - { - std::cout << "Unable to conect to Power Profiles. Continuing" << std::endl; - return false; - } - } - - return false; -} - bool WayfireBatteryInfo::setup_dbus_battery() { auto cancellable = Gio::Cancellable::create(); @@ -278,19 +226,14 @@ bool WayfireBatteryInfo::setup_dbus_battery() void WayfireBatteryInfo::update_layout() { - if (!box) - { - return; - } - WfOption panel_position{"panel/position"}; if (panel_position.value() == PANEL_POSITION_LEFT or panel_position.value() == PANEL_POSITION_RIGHT) { - box->set_orientation(Gtk::Orientation::VERTICAL); + box.set_orientation(Gtk::Orientation::VERTICAL); } else { - box->set_orientation(Gtk::Orientation::HORIZONTAL); + box.set_orientation(Gtk::Orientation::HORIZONTAL); } } @@ -299,73 +242,23 @@ void WayfireBatteryInfo::handle_config_reload() update_layout(); } -// TODO: simplify config loading - void WayfireBatteryInfo::init(Gtk::Box *container) { - profiles_menu = Gio::Menu::create(); - state_action = Gio::SimpleAction::create_radio_string("set_profile", ""); - - // the two features are battery displaying and power modes - feat_bat = setup_dbus_battery(); - feat_modes = setup_dbus_power_modes(); - - // ignore if we can’t do either - if (!feat_bat && !feat_modes) + if (!setup_dbus_battery()) { return; } - box = std::make_unique("panel", "battery"); - - box->set_child(overlay); + box.append(overlay); overlay.set_child(icon); icon.add_css_class("widget-icon"); - if (feat_bat) - { - status_opt.set_callback([=] () { update_details(); }); - update_details(); - } + status_opt.set_callback([=] () { update_details(); }); + update_details(); update_icon(); - if (feat_modes) - { - auto actions = Gio::SimpleActionGroup::create(); - - state_action->signal_activate().connect([=] (Glib::VariantBase vb) - { - // User has requested a change of state. Don't change the UI choice, - // let the dbus roundtrip happen to be sure. - if (vb.is_of_type(Glib::VariantType("s"))) - { - // Couldn't seem to make proxy send property back, so this will have to do - Glib::VariantContainerBase params = Glib::Variant>::create({POWER_PROFILE_NAME, ACTIVE_PROFILE, vb}); - - connection->call_sync( - POWER_PROFILE_PATH, - "org.freedesktop.DBus.Properties", - "Set", - params, - NULL, - POWER_PROFILE_NAME, - -1, - Gio::DBus::CallFlags::NONE, - {}); - } - }); - - actions->add_action(state_action); - - box->open_on(1); - box->insert_action_group("actions", actions); - box->set_spacing(5); - box->set_menu_model(profiles_menu); - } - - container->append(*box); + container->append(box); icon.property_scale_factor().signal_changed() .connect(sigc::mem_fun(*this, &WayfireBatteryInfo::update_icon)); @@ -373,65 +266,7 @@ void WayfireBatteryInfo::init(Gtk::Box *container) update_layout(); } -void WayfireBatteryInfo::on_upower_properties_changed( - const Gio::DBus::Proxy::MapChangedProperties& properties, - const std::vector& invalidated) -{ - for (auto& prop : properties) - { - if (prop.first == ACTIVE_PROFILE) - { - if (prop.second.is_of_type(Glib::VariantType("s"))) - { - auto value_string = - Glib::VariantBase::cast_dynamic>(prop.second).get(); - set_current_profile(value_string); - } - } else if (prop.first == PROFILES) - { - // I've been unable to find a way to change possible profiles on the fly, so cannot confirm this - // works at all. - auto value = Glib::VariantBase::cast_dynamic>>>(prop.second); - setup_profiles(value.get()); - } - - // TODO Consider watching for "Performance Degraded" events too, but we currently have no way to - // output this additional information - } -} - -void WayfireBatteryInfo::set_current_profile(Glib::ustring profile) -{ - power_mode = profile; - state_action->set_state(Glib::Variant::create(profile)); - update_icon(); -} - -void WayfireBatteryInfo::setup_profiles(std::vector> profiles) -{ - profiles_menu->remove_all(); - for (auto profile : profiles) - { - if (profile.count("Profile") == 1) - { - Glib::VariantBase value = profile.at("Profile"); - if (value.is_of_type(Glib::VariantType("s"))) - { - auto value_string = - Glib::VariantBase::cast_dynamic>(value).get(); - auto item = Gio::MenuItem::create(value_string, "noactionyet"); - - item->set_action_and_target("actions.set_profile", - Glib::Variant::create(value_string)); - profiles_menu->append_item(item); - } - } - } -} - WayfireBatteryInfo::~WayfireBatteryInfo() { - btn_sig.disconnect(); disp_dev_sig.disconnect(); } diff --git a/src/panel/widgets/battery.hpp b/src/panel/widgets/battery.hpp index df85e4a8..34b8d947 100644 --- a/src/panel/widgets/battery.hpp +++ b/src/panel/widgets/battery.hpp @@ -8,12 +8,10 @@ #include #include -#include #include #include "widget.hpp" -#include "wf-popover.hpp" using DBusConnection = Glib::RefPtr; using DBusProxy = Glib::RefPtr; @@ -28,21 +26,18 @@ class WayfireBatteryInfo : public WayfireWidget { WfOption status_opt{"panel/battery_status"}; - sigc::connection btn_sig, disp_dev_sig; + sigc::connection disp_dev_sig; Gtk::Label label; - std::unique_ptr box; + Gtk::Box box; Gtk::Overlay overlay; - std::shared_ptr profiles_menu; Gtk::Image icon; DBusConnection connection; - DBusProxy upower_proxy, powerprofile_proxy, display_device; - std::string power_mode = ""; + DBusProxy upower_proxy, display_device; - bool feat_bat, feat_modes; // the available features when running + bool feat_bat; bool setup_dbus_battery(); - bool setup_dbus_power_modes(); void update_icon(); void update_details(); @@ -55,15 +50,6 @@ class WayfireBatteryInfo : public WayfireWidget const Gio::DBus::Proxy::MapChangedProperties& properties, const std::vector& invalidated); - void on_upower_properties_changed( - const Gio::DBus::Proxy::MapChangedProperties& properties, - const std::vector& invalidated); - - void set_current_profile(Glib::ustring profile); - void setup_profiles(std::vector> profiles); - - std::shared_ptr state_action; - public: virtual void init(Gtk::Box *container); virtual ~WayfireBatteryInfo(); diff --git a/src/panel/widgets/power-profiles.cpp b/src/panel/widgets/power-profiles.cpp new file mode 100644 index 00000000..843670e7 --- /dev/null +++ b/src/panel/widgets/power-profiles.cpp @@ -0,0 +1,157 @@ +#include +#include + +#include "power-profiles.hpp" + +#define POWER_PROFILE_PATH "/org/freedesktop/UPower/PowerProfiles" +#define POWER_PROFILE_NAME "org.freedesktop.UPower.PowerProfiles" + +#define PROFILES "Profiles" +#define ACTIVE_PROFILE "ActiveProfile" + +void WayfirePowerProfiles::update_icon() +{ + icon.set_from_icon_name("power-profile-" + power_mode); +} + +void WayfirePowerProfiles::set_current_profile(Glib::ustring profile) +{ + power_mode = profile; + state_action->set_state(Glib::Variant::create(profile)); + update_icon(); +} + +void WayfirePowerProfiles::setup_profiles(std::vector> profiles) +{ + profiles_menu->remove_all(); + for (auto profile : profiles) + { + if (profile.count("Profile") == 1) + { + Glib::VariantBase value = profile.at("Profile"); + if (value.is_of_type(Glib::VariantType("s"))) + { + auto value_string = + Glib::VariantBase::cast_dynamic>(value).get(); + auto item = Gio::MenuItem::create(value_string, "noactionyet"); + + item->set_action_and_target("actions.set_profile", + Glib::Variant::create(value_string)); + profiles_menu->append_item(item); + } + } + } +} + +void WayfirePowerProfiles::on_properties_changed( + const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated) +{ + for (auto& prop : properties) + { + if (prop.first == ACTIVE_PROFILE) + { + if (prop.second.is_of_type(Glib::VariantType("s"))) + { + auto value_string = + Glib::VariantBase::cast_dynamic>(prop.second).get(); + set_current_profile(value_string); + } + } else if (prop.first == PROFILES) + { + auto value = Glib::VariantBase::cast_dynamic>>>(prop.second); + setup_profiles(value.get()); + } + } +} + +bool WayfirePowerProfiles::setup_dbus_power_modes() +{ + 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; + } + + powerprofile_proxy = Gio::DBus::Proxy::create_sync(connection, POWER_PROFILE_NAME, + POWER_PROFILE_PATH, + POWER_PROFILE_NAME); + if (!powerprofile_proxy) + { + std::cout << "Unable to conect to Power Profiles. Continuing" << std::endl; + return false; + } + + powerprofile_proxy->signal_properties_changed().connect( + sigc::mem_fun(*this, &WayfirePowerProfiles::on_properties_changed)); + + Glib::Variant current_profile; + Glib::Variant>> profiles; + powerprofile_proxy->get_cached_property(current_profile, ACTIVE_PROFILE); + powerprofile_proxy->get_cached_property(profiles, PROFILES); + + if (profiles && current_profile) + { + setup_profiles(profiles.get()); + set_current_profile(current_profile.get()); + return true; + } + + std::cout << "Unable to conect to Power Profiles. Continuing" << std::endl; + return false; +} + +void WayfirePowerProfiles::init(Gtk::Box *container) +{ + profiles_menu = Gio::Menu::create(); + state_action = Gio::SimpleAction::create_radio_string("set_profile", ""); + + if (!setup_dbus_power_modes()) + { + return; + } + + box = std::make_unique("panel", "power-profiles"); + + box->set_child(icon); + icon.add_css_class("widget-icon"); + + auto actions = Gio::SimpleActionGroup::create(); + + state_action->signal_activate().connect([=] (Glib::VariantBase vb) + { + if (vb.is_of_type(Glib::VariantType("s"))) + { + Glib::VariantContainerBase params = Glib::Variant>::create({POWER_PROFILE_NAME, ACTIVE_PROFILE, vb}); + + connection->call_sync( + POWER_PROFILE_PATH, + "org.freedesktop.DBus.Properties", + "Set", + params, + NULL, + POWER_PROFILE_NAME, + -1, + Gio::DBus::CallFlags::NONE, + {}); + } + }); + + actions->add_action(state_action); + + box->open_on(1); + box->insert_action_group("actions", actions); + box->set_spacing(5); + box->set_menu_model(profiles_menu); + + container->append(*box); + + icon.property_scale_factor().signal_changed() + .connect(sigc::mem_fun(*this, &WayfirePowerProfiles::update_icon)); + + update_icon(); +} diff --git a/src/panel/widgets/power-profiles.hpp b/src/panel/widgets/power-profiles.hpp new file mode 100644 index 00000000..225a6318 --- /dev/null +++ b/src/panel/widgets/power-profiles.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include + +#include +#include +#include + +#include "widget.hpp" +#include "wf-popover.hpp" + +using DBusConnection = Glib::RefPtr; +using DBusProxy = Glib::RefPtr; + +class WayfirePowerProfiles : public WayfireWidget +{ + Gtk::Image icon; + std::unique_ptr box; + std::shared_ptr profiles_menu; + std::shared_ptr state_action; + + DBusConnection connection; + DBusProxy powerprofile_proxy; + std::string power_mode = ""; + + bool setup_dbus_power_modes(); + + void update_icon(); + void set_current_profile(Glib::ustring profile); + void setup_profiles(std::vector> profiles); + + void on_properties_changed( + const Gio::DBus::Proxy::MapChangedProperties& properties, + const std::vector& invalidated); + + public: + virtual void init(Gtk::Box *container); + virtual ~WayfirePowerProfiles() = default; +}; diff --git a/src/util/meson.build b/src/util/meson.build index 30611837..b02f324b 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -33,17 +33,17 @@ util = static_library( ) git_command = [ - 'sh', - '-c', 'printf "@0@ version @1@-%s (%s) branch %s gtk @2@" "$(git rev-parse --short HEAD)" "$(git log -1 --format=%as)" "$(git rev-parse --abbrev-ref HEAD)"'.format(meson.project_name(), meson.project_version(), gtkmm.version()), + 'sh', + '-c', 'printf "@0@ version @1@-%s (%s) branch %s gtk @2@" "$(git rev-parse --short HEAD)" "$(git log -1 --format=%as)" "$(git rev-parse --abbrev-ref HEAD)"'.format(meson.project_name(), meson.project_version(), gtkmm.version()), ] fallback_string = '@0@ version @1@-unknown-commit (unknown-date) branch unknown-branch gtk @2@'.format(meson.project_name(), meson.project_version(), gtkmm.version()) version_h = vcs_tag( - input: 'version.h.in', - output: 'version.h', - command: git_command, - fallback: fallback_string, + input: 'version.h.in', + output: 'version.h', + command: git_command, + fallback: fallback_string, ) util_includes = include_directories('.')