diff options
Diffstat (limited to 'src/notifier.c')
-rw-r--r-- | src/notifier.c | 260 |
1 files changed, 116 insertions, 144 deletions
diff --git a/src/notifier.c b/src/notifier.c index 897154a..d32008f 100644 --- a/src/notifier.c +++ b/src/notifier.c @@ -19,10 +19,7 @@ #include "dbus-battery-info.h" #include "dbus-shared.h" -#include "device.h" -#include "device-provider.h" #include "notifier.h" -#include "service.h" #include <libnotify/notify.h> @@ -33,40 +30,44 @@ G_DEFINE_TYPE(IndicatorPowerNotifier, indicator_power_notifier, G_TYPE_OBJECT) +/** +*** GObject Properties +**/ + enum { PROP_0, - PROP_DEVICE_PROVIDER, + PROP_BATTERY, PROP_IS_WARNING, PROP_POWER_LEVEL, LAST_PROP }; -#define DEVICE_PROVIDER_NAME "device-provider" +#define BATTERY_NAME "battery" #define IS_WARNING_NAME "is-warning" #define POWER_LEVEL_NAME "power-level" static GParamSpec * properties[LAST_PROP]; -static int n_notifiers = 0; +/** +*** +**/ -typedef enum -{ - POWER_LEVEL_OK, - POWER_LEVEL_LOW, - POWER_LEVEL_VERY_LOW, - POWER_LEVEL_CRITICAL -} -PowerLevel; +static int n_notifiers = 0; struct _IndicatorPowerNotifierPrivate { IndicatorPowerDeviceProvider * device_provider; + /* The battery we're currently watching. + This may be a physical battery or it may be a "merged" battery + synthesized from multiple batteries present on the device. + See indicator_power_service_choose_primary_device() */ IndicatorPowerDevice * battery; + PowerLevel power_level; + NotifyNotification* notify_notification; gboolean is_warning; - PowerLevel power_level; DbusBattery * dbus_battery; GBinding * is_warning_binding; @@ -77,41 +78,7 @@ struct _IndicatorPowerNotifierPrivate typedef IndicatorPowerNotifierPrivate priv_t; /*** -**** -***/ - -/* implemented here rather than my_set_property() to guard from public use - because this is a read-only property */ -static void -set_is_warning_property (IndicatorPowerNotifier * self, gboolean is_warning) -{ - priv_t * p = self->priv; - - if (p->is_warning != is_warning) - { - p->is_warning = is_warning; - - g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_IS_WARNING]); - } -} - -/* implemented here rather than my_set_property() to guard from public use - because this is a read-only property */ -static void -set_power_level_property (IndicatorPowerNotifier * self, PowerLevel power_level) -{ - priv_t * p = self->priv; - - if (p->power_level != power_level) - { - p->power_level = power_level; - - g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_POWER_LEVEL]); - } -} - -/*** -**** +**** Notifications ***/ static void @@ -135,30 +102,38 @@ on_notification_clicked(NotifyNotification * notify_notification G_GNUC_UNUSED, char * action G_GNUC_UNUSED, gpointer gself G_GNUC_UNUSED) { - /* no-op */ + /* no-op because notify_notification_add_action() doesn't like a NULL cb */ } static void -notification_show(IndicatorPowerNotifier * self, - IndicatorPowerDevice * device) - +notification_show(IndicatorPowerNotifier * self) { - priv_t * p = self->priv; + priv_t * p; + IndicatorPowerDevice * battery; char * body; NotifyNotification * nn; - // if there's already a notification, tear it down notification_clear (self); - // create the notification - body = g_strdup_printf(_("%d%% charge remaining"), (int)indicator_power_device_get_percentage(device)); - p->notify_notification = nn = notify_notification_new(_("Battery Low"), body, NULL); - notify_notification_set_hint(nn, "x-canonical-snap-decisions", g_variant_new_boolean(TRUE)); - notify_notification_set_hint(nn, "x-canonical-private-button-tint", g_variant_new_boolean(TRUE)); - notify_notification_add_action(nn, "OK", _("OK"), on_notification_clicked, self, NULL); + p = self->priv; + battery = p->battery; + g_return_if_fail (battery != NULL); + + /* create the notification */ + body = g_strdup_printf(_("%d%% charge remaining"), + (int)indicator_power_device_get_percentage(battery)); + p->notify_notification = nn = notify_notification_new(_("Battery Low"), + body, + NULL); + notify_notification_set_hint(nn, "x-canonical-snap-decisions", + g_variant_new_boolean(TRUE)); + notify_notification_set_hint(nn, "x-canonical-private-button-tint", + g_variant_new_boolean(TRUE)); + notify_notification_add_action(nn, "OK", _("OK"), + on_notification_clicked, self, NULL); g_signal_connect_swapped(nn, "closed", G_CALLBACK(notification_clear), self); - // show the notification + /* show the notification */ GError* error = NULL; notify_notification_show(nn, &error); if (error != NULL) @@ -174,12 +149,16 @@ notification_show(IndicatorPowerNotifier * self, g_free (body); } +/*** +**** +***/ + static PowerLevel get_power_level (const IndicatorPowerDevice * device) { static const double percent_critical = 2.0; static const double percent_very_low = 5.0; - static const double percent_low = 48.0; + static const double percent_low = 10.0; const gdouble p = indicator_power_device_get_percentage(device); PowerLevel ret; @@ -195,50 +174,6 @@ get_power_level (const IndicatorPowerDevice * device) return ret; } -static void -on_devices_changed(IndicatorPowerNotifier * self) -{ - priv_t * p = self->priv; - GList * devices; - IndicatorPowerDevice * primary; - - /* find the primary battery */ - devices = indicator_power_device_provider_get_devices (p->device_provider); - primary = indicator_power_service_choose_primary_device (devices); - g_clear_object (&p->battery); - if ((primary != NULL) && (indicator_power_device_get_kind (primary) == UP_DEVICE_KIND_BATTERY)) - p->battery = g_object_ref (primary); - g_clear_object(&primary); - g_list_free_full (devices, (GDestroyNotify)g_object_unref); - - /* update our state based on the new primary device */ - if (p->battery == NULL) - { - /* if there's no primary battery, put everything in standby mode */ - set_power_level_property (self, POWER_LEVEL_OK); - notification_clear(self); - } - else - { - const PowerLevel power_level = get_power_level (p->battery); - - if (p->power_level != power_level) - { - set_power_level_property (self, power_level); - - /* maybe update the notifications */ - if ((power_level == POWER_LEVEL_OK) || - (indicator_power_device_get_state(p->battery) != UP_DEVICE_STATE_DISCHARGING)) - { - notification_clear (self); - } - else - { - notification_show (self, p->battery); - } - } - } -} /*** **** GObject virtual functions @@ -255,8 +190,8 @@ my_get_property (GObject * o, switch (property_id) { - case PROP_DEVICE_PROVIDER: - g_value_set_object (value, p->device_provider); + case PROP_BATTERY: + g_value_set_object (value, p->battery); break; case PROP_POWER_LEVEL: @@ -282,8 +217,8 @@ my_set_property (GObject * o, switch (property_id) { - case PROP_DEVICE_PROVIDER: - indicator_power_notifier_set_device_provider (self, g_value_get_object (value)); + case PROP_BATTERY: + indicator_power_notifier_set_battery (self, g_value_get_object(value)); break; default: @@ -291,17 +226,43 @@ my_set_property (GObject * o, } } +/* read-only property, so not implemented in my_set_property() */ +static void +set_is_warning_property (IndicatorPowerNotifier * self, gboolean is_warning) +{ + priv_t * p = self->priv; + + if (p->is_warning != is_warning) + { + p->is_warning = is_warning; + + g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_IS_WARNING]); + } +} + +/* read-only property, so not implemented in my_set_property() */ +static void +set_power_level_property (IndicatorPowerNotifier * self, PowerLevel power_level) +{ + priv_t * p = self->priv; + + if (p->power_level != power_level) + { + p->power_level = power_level; + + g_object_notify_by_pspec (G_OBJECT(self), properties[PROP_POWER_LEVEL]); + } +} + static void my_dispose (GObject * o) { IndicatorPowerNotifier * self = INDICATOR_POWER_NOTIFIER(o); priv_t * p = self->priv; -g_message ("%s %s dispose %p", G_STRLOC, G_STRFUNC, (void*)o); - - indicator_power_notifier_set_bus(self, NULL); - notification_clear(self); - indicator_power_notifier_set_device_provider (self, NULL); + indicator_power_notifier_set_bus (self, NULL); + notification_clear (self); + indicator_power_notifier_set_device (self, NULL); g_clear_pointer (&p->power_level_binding, g_binding_unbind); g_clear_pointer (&p->is_warning_binding, g_binding_unbind); g_clear_object (&p->dbus_battery); @@ -310,9 +271,8 @@ g_message ("%s %s dispose %p", G_STRLOC, G_STRFUNC, (void*)o); } static void -my_finalize (GObject * o) +my_finalize (GObject * o G_GNUC_UNUSED) { -g_message ("%s %s finalize %p", G_STRLOC, G_STRFUNC, (void*)o); if (!--n_notifiers) notify_uninit(); } @@ -328,12 +288,9 @@ indicator_power_notifier_init (IndicatorPowerNotifier * self) INDICATOR_TYPE_POWER_NOTIFIER, IndicatorPowerNotifierPrivate); self->priv = p; -g_message ("%s %s init %p", G_STRLOC, G_STRFUNC, (void*)self); p->dbus_battery = dbus_battery_skeleton_new (); - /* FIXME: own the busname and export the skeleton */ - p->is_warning_binding = g_object_bind_property (self, IS_WARNING_NAME, p->dbus_battery, @@ -364,17 +321,17 @@ indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass) properties[PROP_0] = NULL; - properties[PROP_DEVICE_PROVIDER] = g_param_spec_object ( - DEVICE_PROVIDER_NAME, - "Device Provider", - "Source for power devices", + properties[PROP_BATTERY] = g_param_spec_object ( + BATTERY_NAME, + "Battery", + "The current battery", G_TYPE_OBJECT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); properties[PROP_POWER_LEVEL] = g_param_spec_int ( POWER_LEVEL_NAME, "Power Level", - "Power Level of the batteries", + "The battery's power level", POWER_LEVEL_OK, POWER_LEVEL_CRITICAL, POWER_LEVEL_OK, @@ -397,50 +354,65 @@ indicator_power_notifier_class_init (IndicatorPowerNotifierClass * klass) IndicatorPowerNotifier * indicator_power_notifier_new (IndicatorPowerDeviceProvider * device_provider) { - GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, - DEVICE_PROVIDER_NAME, device_provider, - NULL); + GObject * o = g_object_new (INDICATOR_TYPE_POWER_NOTIFIER, NULL); return INDICATOR_POWER_NOTIFIER (o); } void -indicator_power_notifier_set_device_provider(IndicatorPowerNotifier * self, - IndicatorPowerDeviceProvider * dp) +indicator_power_notifier_set_battery (IndicatorPowerNotifier * self, + IndicatorPowerDevice * battery) { priv_t * p; g_return_if_fail(INDICATOR_IS_POWER_NOTIFIER(self)); - g_return_if_fail(!dp || INDICATOR_IS_POWER_DEVICE_PROVIDER(dp)); - p = self->priv; + g_return_if_fail((battery == NULL) || INDICATOR_IS_POWER_DEVICE(battery)); + g_return_if_fail((battery == NULL) || (indicator_power_device_get_kind(battery) == UP_DEVICE_KIND_BATTERY)); - if (p->device_provider != NULL) + if (p->battery != NULL) { - g_signal_handlers_disconnect_by_data(p->device_provider, self); - g_clear_object(&p->device_provider); - g_clear_object(&p->battery); + g_clear_object (&p->battery); + set_power_level_property (self, POWER_LEVEL_OK); + notification_clear (self); } - if (dp != NULL) + if (battery != NULL) { - p->device_provider = g_object_ref(dp); + const PowerLevel power_level = get_power_level (battery); - g_signal_connect_swapped(p->device_provider, "devices-changed", - G_CALLBACK(on_devices_changed), self); + p->battery = g_object_ref(battery); - on_devices_changed(self); + if (p->power_level != power_level) + { + set_power_level_property (self, power_level); + + if ((power_level == POWER_LEVEL_OK) || + (indicator_power_device_get_state(battery) != UP_DEVICE_STATE_DISCHARGING)) + { + notification_clear (self); + } + else + { + notification_show (self); + } + } } } void indicator_power_notifier_set_bus (IndicatorPowerNotifier * self, - GDBusConnection * bus) + GDBusConnection * bus) { priv_t * p; g_return_if_fail(INDICATOR_IS_POWER_NOTIFIER(self)); + g_return_if_fail((bus == NULL) || G_IS_DBUS_CONNECTION(bus)); + p = self->priv; + if (p->bus == bus) + return; + if (p->bus != NULL) { if (p->dbus_battery != NULL) |