From c80d5eb29fd339c1322110d36b5a9d066056a14e Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Mon, 6 Mar 2023 22:58:52 +0100 Subject: Show battery level for all devices (including bluetooth) fixes https://gitlab.com/ubports/development/core/packaging/ayatana-indicators/ayatana-indicator-bluetooth/-/issues/3 --- src/device.c | 69 +++++++++++++++++++++++++- src/device.h | 18 ++++++- src/service.c | 153 +++++++++++++++++++++++----------------------------------- 3 files changed, 145 insertions(+), 95 deletions(-) (limited to 'src') diff --git a/src/device.c b/src/device.c index bfa31ea..a1c4d14 100644 --- a/src/device.c +++ b/src/device.c @@ -3,7 +3,7 @@ A simple Device structure used internally by indicator-power Copyright 2012 Canonical Ltd. -Copyright 2021-2022 Robert Tari +Copyright 2021-2023 Robert Tari Authors: Charles Kerr @@ -388,6 +388,22 @@ device_kind_to_string (UpDeviceKind kind) case UP_DEVICE_KIND_TABLET: return "tablet"; case UP_DEVICE_KIND_COMPUTER: return "computer"; case UP_DEVICE_KIND_GAMING_INPUT: return "gaming-input"; + case UP_DEVICE_KIND_PEN: return "pen"; + case UP_DEVICE_KIND_TOUCHPAD: return "touchpad"; + case UP_DEVICE_KIND_MODEM: return "modem"; + case UP_DEVICE_KIND_NETWORK: return "network"; + case UP_DEVICE_KIND_HEADSET: return "headset"; + case UP_DEVICE_KIND_SPEAKERS: return "speakers"; + case UP_DEVICE_KIND_HEADPHONES: return "headphones"; + case UP_DEVICE_KIND_VIDEO: return "video"; + case UP_DEVICE_KIND_OTHER_AUDIO: return "audio-device"; + case UP_DEVICE_KIND_REMOTE_CONTROL: return "remote-control"; + case UP_DEVICE_KIND_PRINTER: return "printer"; + case UP_DEVICE_KIND_SCANNER: return "scanner"; + case UP_DEVICE_KIND_CAMERA: return "camera"; + case UP_DEVICE_KIND_WEARABLE: return "wearable"; + case UP_DEVICE_KIND_TOY: return "toy"; + case UP_DEVICE_KIND_BLUETOOTH_GENERIC: return "bluetooth-generic"; default: return "unknown"; } } @@ -624,6 +640,57 @@ device_kind_to_localised_string (UpDeviceKind kind) /* TRANSLATORS: game controller/joystick with internal batteries */ text = _("Gaming input"); break; + case UP_DEVICE_KIND_PEN: + /* TRANSLATORS: graphic tablet pen with internal battery */ + text = _("Pen"); + break; + case UP_DEVICE_KIND_TOUCHPAD: + text = _("Touchpad"); + break; + case UP_DEVICE_KIND_MODEM: + text = _("Modem"); + break; + case UP_DEVICE_KIND_NETWORK: + text = _("Network device"); + break; + case UP_DEVICE_KIND_HEADSET: + text = _("Headset"); + break; + case UP_DEVICE_KIND_SPEAKERS: + /* TRANSLATORS: loudspeakers with internal batteries */ + text = _("Speakers"); + break; + case UP_DEVICE_KIND_HEADPHONES: + text = _("Headphones"); + break; + case UP_DEVICE_KIND_VIDEO: + text = _("Video device"); + break; + case UP_DEVICE_KIND_OTHER_AUDIO: + text = _("Audio device"); + break; + case UP_DEVICE_KIND_REMOTE_CONTROL: + /* TRANSLATORS: remote control device with internal battery */ + text = _("Remote control"); + break; + case UP_DEVICE_KIND_PRINTER: + text = _("Printer"); + break; + case UP_DEVICE_KIND_SCANNER: + text = _("Scanner"); + break; + case UP_DEVICE_KIND_CAMERA: + text = _("Camera"); + break; + case UP_DEVICE_KIND_WEARABLE: + text = _("Wearable"); + break; + case UP_DEVICE_KIND_TOY: + text = _("Toy"); + break; + case UP_DEVICE_KIND_BLUETOOTH_GENERIC: + text = _("Bluetooth device"); + break; case UP_DEVICE_KIND_UNKNOWN: /* TRANSLATORS: unknown device */ text = _("Unknown"); diff --git a/src/device.h b/src/device.h index 15c64f3..fa41fe0 100644 --- a/src/device.h +++ b/src/device.h @@ -3,7 +3,7 @@ A simple Device structure used internally by indicator-power Copyright 2012 Canonical Ltd. -Copyright 2022 Robert Tari +Copyright 2022-2023 Robert Tari Authors: Charles Kerr @@ -63,6 +63,22 @@ typedef enum UP_DEVICE_KIND_TABLET, UP_DEVICE_KIND_COMPUTER, UP_DEVICE_KIND_GAMING_INPUT, + UP_DEVICE_KIND_PEN, + UP_DEVICE_KIND_TOUCHPAD, + UP_DEVICE_KIND_MODEM, + UP_DEVICE_KIND_NETWORK, + UP_DEVICE_KIND_HEADSET, + UP_DEVICE_KIND_SPEAKERS, + UP_DEVICE_KIND_HEADPHONES, + UP_DEVICE_KIND_VIDEO, + UP_DEVICE_KIND_OTHER_AUDIO, + UP_DEVICE_KIND_REMOTE_CONTROL, + UP_DEVICE_KIND_PRINTER, + UP_DEVICE_KIND_SCANNER, + UP_DEVICE_KIND_CAMERA, + UP_DEVICE_KIND_WEARABLE, + UP_DEVICE_KIND_TOY, + UP_DEVICE_KIND_BLUETOOTH_GENERIC, UP_DEVICE_KIND_LAST } UpDeviceKind; diff --git a/src/service.c b/src/service.c index f9122ba..3914e3f 100644 --- a/src/service.c +++ b/src/service.c @@ -353,21 +353,6 @@ calculate_device_state_action_state (IndicatorPowerService * self) return g_variant_new_string(device_state_to_string(device_state)); } -static GVariant* -calculate_battery_level_action_state (IndicatorPowerService * self) -{ - const priv_t * const p = self->priv; - guint32 battery_level; - - if (p->primary_device == NULL) - battery_level = 0; - else - battery_level = (guint32)(indicator_power_device_get_percentage (p->primary_device) + 0.5); - - return g_variant_new_uint32 (battery_level); -} - - /*** **** **** HEADER SECTION @@ -515,81 +500,72 @@ create_header_state (IndicatorPowerService * self) **** ***/ -static void -append_device_to_menu (GMenu * menu, const IndicatorPowerDevice * device, int profile) +static GMenuModel * +create_devices_section (IndicatorPowerService * self, int profile) { - const UpDeviceKind kind = indicator_power_device_get_kind (device); + GMenu * menu = g_menu_new (); - if (kind != UP_DEVICE_KIND_LINE_POWER) - { - char * label; - GMenuItem * item; - GIcon * icon; - - label = indicator_power_device_get_readable_text (device); - item = g_menu_item_new (label, NULL); - g_free (label); - - g_menu_item_set_attribute (item, "x-ayatana-type", "s", "org.ayatana.indicator.basic"); - - if ((icon = indicator_power_device_get_gicon (device, FALSE))) - { - GVariant * serialized_icon = g_icon_serialize (icon); - - if (serialized_icon != NULL) - { - g_menu_item_set_attribute_value (item, - G_MENU_ATTRIBUTE_ICON, - serialized_icon); - g_variant_unref (serialized_icon); - } - - g_object_unref (icon); - } - - if (profile == PROFILE_DESKTOP) - { - g_menu_item_set_action_and_target(item, "indicator.activate-statistics", "s", - indicator_power_device_get_object_path (device)); - } - - g_menu_append_item (menu, item); - g_object_unref (item); - } -} + if (self->priv->primary_device != NULL) + { + GMenuItem * item = g_menu_item_new (_("Charge level"), NULL); + g_menu_item_set_attribute (item, "x-ayatana-type", "s", "org.ayatana.indicator.progress"); + guint16 battery_level = (guint16)(indicator_power_device_get_percentage (self->priv->primary_device) + 0.5); + g_menu_item_set_attribute (item, "x-ayatana-progress", "q", battery_level); + g_menu_append_item (menu, item); + g_object_unref (item); + } + GList * l; -static GMenuModel * -create_desktop_devices_section (IndicatorPowerService * self, int profile) -{ - GList * l; - GMenu * menu = g_menu_new (); + for (l=self->priv->devices; l!=NULL; l=l->next) + { + IndicatorPowerDevice *device = l->data; + const UpDeviceKind kind = indicator_power_device_get_kind (device); + + if (kind != UP_DEVICE_KIND_LINE_POWER) + { + if (device == self->priv->primary_device) + { + continue; + } - for (l=self->priv->devices; l!=NULL; l=l->next) - append_device_to_menu (menu, l->data, profile); + char * label = indicator_power_device_get_readable_text (device); + GMenuItem * item = g_menu_item_new (label, NULL); + g_free (label); + g_menu_item_set_attribute (item, "x-ayatana-type", "s", "org.ayatana.indicator.progress"); + guint16 battery_level = (guint16)(indicator_power_device_get_percentage (device) + 0.5); + g_menu_item_set_attribute (item, "x-ayatana-progress", "q", battery_level); - return G_MENU_MODEL (menu); -} + if (profile != PROFILE_PHONE) + { + GIcon * icon = indicator_power_device_get_gicon (device, FALSE); -/* https://wiki.ubuntu.com/Power#Phone - * The spec also discusses including an item for any connected bluetooth - * headset, but bluez doesn't appear to support Battery Level at this time */ -static GMenuModel * -create_phone_devices_section (IndicatorPowerService * self G_GNUC_UNUSED) -{ - GMenu * menu; - GMenuItem *item; + if (icon) + { + GVariant * serialized_icon = g_icon_serialize (icon); - menu = g_menu_new (); + if (serialized_icon != NULL) + { + g_menu_item_set_attribute_value (item, G_MENU_ATTRIBUTE_ICON, serialized_icon); + g_variant_unref (serialized_icon); + } - item = g_menu_item_new (_("Charge level"), "indicator.battery-level"); - g_menu_item_set_attribute (item, "x-ayatana-type", "s", "org.ayatana.indicator.progress"); - g_menu_append_item (menu, item); - g_object_unref (item); + g_object_unref (icon); + } - return G_MENU_MODEL (menu); -} + if (profile == PROFILE_DESKTOP) + { + g_menu_item_set_action_and_target(item, "indicator.activate-statistics", "s", indicator_power_device_get_object_path (device)); + } + } + + g_menu_append_item (menu, item); + g_object_unref (item); + } + } + return G_MENU_MODEL (menu); +} /*** **** @@ -738,8 +714,8 @@ rebuild_now (IndicatorPowerService * self, guint sections) if (sections & SECTION_DEVICES) { - rebuild_section (desktop->submenu, 0, create_desktop_devices_section (self, PROFILE_DESKTOP)); - rebuild_section (greeter->submenu, 0, create_desktop_devices_section (self, PROFILE_DESKTOP_GREETER)); + rebuild_section (desktop->submenu, 0, create_devices_section (self, PROFILE_DESKTOP)); + rebuild_section (greeter->submenu, 0, create_devices_section (self, PROFILE_DESKTOP_GREETER)); } if (sections & SECTION_SETTINGS) @@ -773,17 +749,17 @@ create_menu (IndicatorPowerService * self, int profile) switch (profile) { case PROFILE_PHONE: - sections[n++] = create_phone_devices_section (self); + sections[n++] = create_devices_section (self, PROFILE_PHONE); sections[n++] = create_phone_settings_section (self); break; case PROFILE_DESKTOP: - sections[n++] = create_desktop_devices_section (self, PROFILE_DESKTOP); + sections[n++] = create_devices_section (self, PROFILE_DESKTOP); sections[n++] = create_desktop_settings_section (self); break; case PROFILE_DESKTOP_GREETER: - sections[n++] = create_desktop_devices_section (self, PROFILE_DESKTOP_GREETER); + sections[n++] = create_devices_section (self, PROFILE_DESKTOP_GREETER); break; } @@ -912,12 +888,6 @@ init_gactions (IndicatorPowerService * self) g_action_map_add_action (G_ACTION_MAP(p->actions), G_ACTION(a)); p->header_action = a; - /* add the power-level action */ - a = g_simple_action_new_stateful ("battery-level", NULL, calculate_battery_level_action_state(self)); - g_simple_action_set_enabled (a, FALSE); - g_action_map_add_action (G_ACTION_MAP(p->actions), G_ACTION(a)); - p->battery_level_action = a; - /* add the charge state action */ a = g_simple_action_new_stateful ("device-state", NULL, calculate_device_state_action_state(self)); g_simple_action_set_enabled (a, FALSE); @@ -1089,9 +1059,6 @@ on_devices_changed (IndicatorPowerService * self) else indicator_power_notifier_set_battery (p->notifier, NULL); - /* update the battery-level action's state */ - g_simple_action_set_state (p->battery_level_action, calculate_battery_level_action_state(self)); - /* update the device-state action's state */ g_simple_action_set_state (p->device_state_action, calculate_device_state_action_state(self)); -- cgit v1.2.3