aboutsummaryrefslogtreecommitdiff
path: root/src/service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service.c')
-rw-r--r--src/service.c178
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;