diff options
Diffstat (limited to 'src/service.c')
-rw-r--r-- | src/service.c | 178 |
1 files changed, 169 insertions, 9 deletions
diff --git a/src/service.c b/src/service.c index 1a4e24a..00efe9b 100644 --- a/src/service.c +++ b/src/service.c @@ -27,6 +27,7 @@ #include "device.h" #include "device-provider.h" #include "ib-brightness-control.h" +#include "ib-brightness-powerd-control.h" #include "service.h" #define BUS_NAME "com.canonical.indicator.power" @@ -104,6 +105,7 @@ struct _IndicatorPowerServicePrivate GSettings * settings; IbBrightnessControl * brightness_control; + IbBrightnessPowerdControl * brightness_powerd_control; guint own_id; guint actions_export_id; @@ -459,7 +461,16 @@ create_phone_devices_section (IndicatorPowerService * self G_GNUC_UNUSED) static void get_brightness_range (IndicatorPowerService * self, gint * low, gint * high) { - const int max = ib_brightness_control_get_max_value (self->priv->brightness_control); + priv_t * p = self->priv; + int max = 0; + if (p->brightness_control) + { + max = ib_brightness_control_get_max_value (self->priv->brightness_control); + } + else if (p->brightness_powerd_control) + { + max = ib_brightness_powerd_control_get_max_value (self->priv->brightness_powerd_control); + } *low = max * 0.05; /* 5% minimum -- don't let the screen go completely dark */ *high = max; } @@ -502,7 +513,15 @@ static GVariant * action_state_for_brightness (IndicatorPowerService * self) { priv_t * p = self->priv; - const gint brightness = ib_brightness_control_get_value (p->brightness_control); + gint brightness = 0; + if (p->brightness_control) + { + brightness = ib_brightness_control_get_value (p->brightness_control); + } + else if (p->brightness_powerd_control) + { + brightness = ib_brightness_powerd_control_get_value (p->brightness_powerd_control); + } return g_variant_new_double (brightness_to_percentage (self, brightness)); } @@ -521,7 +540,16 @@ on_brightness_change_requested (GSimpleAction * action G_GNUC_UNUSED, IndicatorPowerService * self = INDICATOR_POWER_SERVICE (gself); const gdouble percentage = g_variant_get_double (parameter); const int brightness = percentage_to_brightness (self, percentage); - ib_brightness_control_set_value (self->priv->brightness_control, brightness); + + if (self->priv->brightness_control) + { + ib_brightness_control_set_value (self->priv->brightness_control, brightness); + } + else if (self->priv->brightness_powerd_control) + { + ib_brightness_powerd_control_set_value (self->priv->brightness_powerd_control, brightness); + } + update_brightness_action_state (self); } @@ -1018,7 +1046,9 @@ my_dispose (GObject * o) g_clear_object (&p->conn); + // g_clear_pointer has NULL check inside. g_clear_pointer (&p->brightness_control, ib_brightness_control_free); + g_clear_pointer (&p->brightness_powerd_control, ib_brightness_powerd_control_free); indicator_power_service_set_device_provider (self, NULL); @@ -1032,6 +1062,8 @@ my_dispose (GObject * o) static void indicator_power_service_init (IndicatorPowerService * self) { + GDBusProxy *powerd_proxy; + brightness_params_t powerd_brightness_params; priv_t * p = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_TYPE_POWER_SERVICE, IndicatorPowerServicePrivate); @@ -1041,7 +1073,15 @@ indicator_power_service_init (IndicatorPowerService * self) p->settings = g_settings_new ("com.canonical.indicator.power"); - p->brightness_control = ib_brightness_control_new (); + powerd_proxy = powerd_get_proxy(&powerd_brightness_params); + if (powerd_proxy != NULL) + { + p->brightness_powerd_control = ib_brightness_powerd_control_new(powerd_proxy, powerd_brightness_params); + } + else + { + p->brightness_control = ib_brightness_control_new (); + } init_gactions (self); @@ -1137,6 +1177,129 @@ indicator_power_service_set_device_provider (IndicatorPowerService * self, } } +/* If a device has multiple batteries and uses only one of them at a time, + they should be presented as separate items inside the battery menu, + but everywhere else they should be aggregated (bug 880881). + Their percentages should be averaged. If any are discharging, + the aggregated time remaining should be the maximum of the times + for all those that are discharging, plus the sum of the times + for all those that are idle. Otherwise, the aggregated time remaining + should be the the maximum of the times for all those that are charging. */ +static IndicatorPowerDevice * +create_totalled_battery_device (const GList * devices) +{ + const GList * l; + guint n_charged = 0; + guint n_charging = 0; + guint n_discharging = 0; + guint n_batteries = 0; + double sum_percent = 0; + time_t max_discharge_time = 0; + time_t max_charge_time = 0; + time_t sum_charged_time = 0; + IndicatorPowerDevice * device = NULL; + + for (l=devices; l!=NULL; l=l->next) + { + const IndicatorPowerDevice * device = INDICATOR_POWER_DEVICE(l->data); + + if (indicator_power_device_get_kind(device) == UP_DEVICE_KIND_BATTERY) + { + const double percent = indicator_power_device_get_percentage (device); + const time_t t = indicator_power_device_get_time (device); + const UpDeviceState state = indicator_power_device_get_state (device); + + ++n_batteries; + + if (percent > 0.01) + sum_percent += percent; + + if (state == UP_DEVICE_STATE_CHARGING) + { + ++n_charging; + max_charge_time = MAX(max_charge_time, t); + } + else if (state == UP_DEVICE_STATE_DISCHARGING) + { + ++n_discharging; + max_discharge_time = MAX(max_discharge_time, t); + } + else if (state == UP_DEVICE_STATE_FULLY_CHARGED) + { + ++n_charged; + sum_charged_time += t; + } + } + } + + if (n_batteries > 1) + { + const double percent = sum_percent / n_batteries; + UpDeviceState state; + time_t time_left; + + if (n_discharging > 0) + { + state = UP_DEVICE_STATE_DISCHARGING; + time_left = max_discharge_time + sum_charged_time; + } + else if (n_charging > 0) + { + state = UP_DEVICE_STATE_CHARGING; + time_left = max_charge_time; + } + else if (n_charged > 0) + { + state = UP_DEVICE_STATE_FULLY_CHARGED; + time_left = 0; + } + else + { + state = UP_DEVICE_STATE_UNKNOWN; + time_left = 0; + } + + device = indicator_power_device_new (NULL, + UP_DEVICE_KIND_BATTERY, + percent, + state, + time_left); + } + + return device; +} + +/** + * If there are multiple UP_DEVICE_KIND_BATTERY devices in the list, + * they're merged into a new 'totalled' device representing the sum of them. + * + * Returns: (element-type IndicatorPowerDevice)(transfer full): a list of devices + */ +static GList* +merge_batteries_together (GList * devices) +{ + GList * ret; + IndicatorPowerDevice * merged_device; + + if ((merged_device = create_totalled_battery_device (devices))) + { + GList * l; + + ret = g_list_append (NULL, merged_device); + + for (l=devices; l!=NULL; l=l->next) + if (indicator_power_device_get_kind(INDICATOR_POWER_DEVICE(l->data)) != UP_DEVICE_KIND_BATTERY) + ret = g_list_append (ret, g_object_ref(l->data)); + } + else /* not enough batteries to merge */ + { + ret = g_list_copy (devices); + g_list_foreach (ret, (GFunc)g_object_ref, NULL); + } + + return ret; +} + IndicatorPowerDevice * indicator_power_service_choose_primary_device (GList * devices) { @@ -1144,13 +1307,10 @@ indicator_power_service_choose_primary_device (GList * devices) if (devices != NULL) { - GList * tmp; - - tmp = g_list_copy (devices); + GList * tmp = merge_batteries_together (devices); tmp = g_list_sort (tmp, device_compare_func); primary = g_object_ref (tmp->data); - - g_list_free (tmp); + g_list_free_full (tmp, (GDestroyNotify)g_object_unref); } return primary; |