From 83fad6307903644c0c6588001220aafb1da95cbe Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Sun, 3 Dec 2023 22:56:36 +0100 Subject: data/*: Add AccountsService files --- ....ayatana.indicator.display.AccountsService.rules | 7 +++++++ data/CMakeLists.txt | 19 +++++++++++++++++++ ...ayatana.indicator.display.AccountsService.policy | 21 +++++++++++++++++++++ ...rg.ayatana.indicator.display.AccountsService.xml | 17 +++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 data/50-org.ayatana.indicator.display.AccountsService.rules create mode 100644 data/org.ayatana.indicator.display.AccountsService.policy create mode 100644 data/org.ayatana.indicator.display.AccountsService.xml diff --git a/data/50-org.ayatana.indicator.display.AccountsService.rules b/data/50-org.ayatana.indicator.display.AccountsService.rules new file mode 100644 index 0000000..d3126f3 --- /dev/null +++ b/data/50-org.ayatana.indicator.display.AccountsService.rules @@ -0,0 +1,7 @@ +// Allow LightDM to set AccountsService fields +polkit.addRule (function (action, subject) { + if (action.id == "org.ayatana.indicator.display.AccountsService.ModifyAnyUser" && subject.user == "lightdm") + { + return polkit.Result.YES; + } +}); diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 38ba788..451c9e8 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -64,3 +64,22 @@ install (FILES "${AYATANA_INDICATOR_FILE}" # ayatana-indicator-display-brightness-high install (DIRECTORY "icons/" DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/icons/hicolor/scalable/status" FILES_MATCHING PATTERN "*.svg") + +if (ENABLE_COLOR_TEMP) + + # org.ayatana.indicator.display.AccountsService.xml + + install (FILES org.ayatana.indicator.display.AccountsService.xml DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/dbus-1/interfaces") + install (DIRECTORY DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/accountsservice/interfaces/") + install (CODE "message(STATUS \"Symlinking: \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_DATADIR}/accountsservice/interfaces/org.ayatana.indicator.display.AccountsService.xml\")") + install (CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ../../dbus-1/interfaces/org.ayatana.indicator.display.AccountsService.xml \$ENV{DESTDIR}${CMAKE_INSTALL_FULL_DATADIR}/accountsservice/interfaces/org.ayatana.indicator.display.AccountsService.xml)") + + # org.ayatana.indicator.display.AccountsService.policy + + install (FILES org.ayatana.indicator.display.AccountsService.policy DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/polkit-1/actions") + + # 50-org.ayatana.indicator.display.AccountsService.rules + + install (FILES 50-org.ayatana.indicator.display.AccountsService.rules DESTINATION "${CMAKE_INSTALL_FULL_DATADIR}/polkit-1/rules.d") + +endif () diff --git a/data/org.ayatana.indicator.display.AccountsService.policy b/data/org.ayatana.indicator.display.AccountsService.policy new file mode 100644 index 0000000..a2bff7a --- /dev/null +++ b/data/org.ayatana.indicator.display.AccountsService.policy @@ -0,0 +1,21 @@ + + + + Set properties of own user + Authentication is required to set one's own indicator display properties. + + yes + yes + yes + + + + Set properties of any user + Authentication is required to set another user's indicator display properties. + + no + no + no + + + diff --git a/data/org.ayatana.indicator.display.AccountsService.xml b/data/org.ayatana.indicator.display.AccountsService.xml new file mode 100644 index 0000000..9e41ef2 --- /dev/null +++ b/data/org.ayatana.indicator.display.AccountsService.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 50448a83b1ec2ed840e94dfc09f87ec6f275c028 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Sun, 3 Dec 2023 23:07:06 +0100 Subject: src/service.cpp: Fix build with ENABLE_COLOR_TEMP off --- src/service.cpp | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/src/service.cpp b/src/service.cpp index 6221962..0b61eec 100644 --- a/src/service.cpp +++ b/src/service.cpp @@ -59,11 +59,13 @@ public: Impl() { - const char *sUser = g_get_user_name(); - this->bGreeter = g_str_equal (sUser, "lightdm"); - GSettingsSchemaSource *pSource = g_settings_schema_source_get_default(); +#ifdef COLOR_TEMP_ENABLED const gchar *sTest = g_getenv ("TEST_NAME"); this->bTest = (sTest != NULL && g_str_equal (sTest, "rotation-lock-test")); +#endif + const char *sUserName = g_get_user_name(); + this->bGreeter = g_str_equal (sUserName, "lightdm"); + GSettingsSchemaSource *pSource = g_settings_schema_source_get_default(); if (pSource != NULL) { @@ -96,6 +98,8 @@ public: g_error("No schema could be found"); } +#ifdef COLOR_TEMP_ENABLED + if (!this->bGreeter) { const gchar *sSchema = NULL; @@ -190,6 +194,7 @@ public: g_error("No %s schema could be found", sSchema); } } +#endif } } @@ -235,15 +240,12 @@ public: ~Impl() { +#ifdef COLOR_TEMP_ENABLED if (nCallback) { g_source_remove (nCallback); } - g_signal_handlers_disconnect_by_data(m_settings, this); - g_clear_object(&m_action_group); - g_clear_object(&m_settings); - if (sLastTheme) { g_free (sLastTheme); @@ -268,6 +270,11 @@ public: { g_clear_object (&pColorSchemeSettings); } +#endif + + g_signal_handlers_disconnect_by_data(m_settings, this); + g_clear_object(&m_action_group); + g_clear_object(&m_settings); } GSimpleActionGroup* action_group() const @@ -683,7 +690,9 @@ private: if (ayatana_common_utils_is_lomiri() == FALSE) { pVariantType = g_variant_type_new ("d"); - action = g_simple_action_new_stateful ("color-temp", pVariantType, g_variant_new_double (0)); + guint nTemperature = 0; + g_settings_get (this->m_settings, "color-temp", "q", &nTemperature); + action = g_simple_action_new_stateful ("color-temp", pVariantType, g_variant_new_double (nTemperature)); g_variant_type_free (pVariantType); g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action)); g_signal_connect (m_settings, "changed::color-temp", G_CALLBACK (onColorTempSettings), this); @@ -691,7 +700,11 @@ private: g_object_unref(G_OBJECT (action)); pVariantType = g_variant_type_new ("s"); - action = g_simple_action_new_stateful ("profile", pVariantType, g_variant_new_string ("0")); + guint nProfile = 0; + g_settings_get (this->m_settings, "color-temp-profile", "q", &nProfile); + gchar *sProfile = g_strdup_printf ("%i", nProfile); + action = g_simple_action_new_stateful ("profile", pVariantType, g_variant_new_string (sProfile)); + g_free (sProfile); g_variant_type_free (pVariantType); g_settings_bind_with_mapping (this->m_settings, "color-temp-profile", action, "state", G_SETTINGS_BIND_DEFAULT, settingsIntToActionStateString, actionStateStringToSettingsInt, NULL, NULL); g_action_map_add_action(G_ACTION_MAP(group), G_ACTION(action)); @@ -699,7 +712,8 @@ private: g_signal_connect_swapped (m_settings, "changed::color-temp-profile", G_CALLBACK (updateColor), this); pVariantType = g_variant_type_new("d"); - action = g_simple_action_new_stateful ("brightness", pVariantType, g_variant_new_double (0)); + gdouble fBrightness = g_settings_get_double (this->m_settings, "brightness"); + action = g_simple_action_new_stateful ("brightness", pVariantType, g_variant_new_double (fBrightness)); g_variant_type_free(pVariantType); g_settings_bind_with_mapping (m_settings, "brightness", action, "state", G_SETTINGS_BIND_DEFAULT, settings_to_action_state, action_state_to_settings, NULL, NULL); g_action_map_add_action (G_ACTION_MAP (group), G_ACTION (action)); @@ -921,6 +935,7 @@ private: std::shared_ptr m_phone; std::shared_ptr m_desktop; std::shared_ptr m_icon; + gboolean bGreeter; #ifdef COLOR_TEMP_ENABLED gdouble fLatitude = 0.0; gdouble fLongitude = 0.0; @@ -935,7 +950,6 @@ private: GSettings *pMetacitySettings = NULL; GSettings *pColorSchemeSettings = NULL; gboolean bTest; - gboolean bGreeter; #endif }; -- cgit v1.2.3 From aef2ed6874d249a35ee666b433daff070a7b7765 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Mon, 4 Dec 2023 08:33:00 +0100 Subject: Whitespace fix --- src/service.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/service.cpp b/src/service.cpp index 0b61eec..03872d2 100644 --- a/src/service.cpp +++ b/src/service.cpp @@ -23,7 +23,7 @@ #include #ifdef COLOR_TEMP_ENABLED -#include + #include #endif extern "C" -- cgit v1.2.3 From 92416feefc2ff70e30f0378c263fcebc9d9a127d Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Sun, 3 Dec 2023 23:10:15 +0100 Subject: src/service.cpp: Add AccountsService support --- src/service.cpp | 227 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 212 insertions(+), 15 deletions(-) diff --git a/src/service.cpp b/src/service.cpp index 03872d2..f3fd33b 100644 --- a/src/service.cpp +++ b/src/service.cpp @@ -31,26 +31,31 @@ extern "C" #include #ifdef COLOR_TEMP_ENABLED - #include "solar.h" + #include + #include + #include "solar.h" #endif } #ifdef COLOR_TEMP_ENABLED -typedef struct -{ - guint nTempLow; - guint nTempHigh; - const gchar *sName; -} TempProfile; + #define GREETER_BUS_NAME "org.ayatana.greeter" + #define GREETER_BUS_PATH "/org/ayatana/greeter" -TempProfile m_lTempProfiles[] = -{ - {0, 0, N_("Manual")}, - {4500, 6500, N_("Adaptive (Colder)")}, - {3627, 4913, N_("Adaptive")}, - {3058, 4913, N_("Adaptive (Warmer)")}, - {0, 0, NULL} -}; + typedef struct + { + guint nTempLow; + guint nTempHigh; + const gchar *sName; + } TempProfile; + + TempProfile m_lTempProfiles[] = + { + {0, 0, N_("Manual")}, + {4500, 6500, N_("Adaptive (Colder)")}, + {3627, 4913, N_("Adaptive")}, + {3058, 4913, N_("Adaptive (Warmer)")}, + {0, 0, NULL} + }; #endif class DisplayIndicator::Impl @@ -99,6 +104,7 @@ public: } #ifdef COLOR_TEMP_ENABLED + this->pAccountsServiceConnection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); if (!this->bGreeter) { @@ -194,10 +200,23 @@ public: g_error("No %s schema could be found", sSchema); } } + else + { + this->pConnection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + this->nGreeterSubscription = g_dbus_connection_signal_subscribe (this->pConnection, NULL, GREETER_BUS_NAME, "UserChanged", GREETER_BUS_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE, onUserChanged, this, NULL); + loadManager (this); + } #endif } } +#ifdef COLOR_TEMP_ENABLED + if (!this->bGreeter) + { + gint nUid = geteuid (); + getAccountsService (this, nUid); + } +#endif m_action_group = create_action_group(); // build the icon @@ -241,6 +260,21 @@ public: ~Impl() { #ifdef COLOR_TEMP_ENABLED + if (this->nGreeterSubscription) + { + g_dbus_connection_signal_unsubscribe (this->pConnection, this->nGreeterSubscription); + } + + if (this->lUsers) + { + g_slist_free (this->lUsers); + } + + if (this->pConnection) + { + g_object_unref (this->pConnection); + } + if (nCallback) { g_source_remove (nCallback); @@ -270,6 +304,11 @@ public: { g_clear_object (&pColorSchemeSettings); } + + if (this->pAccountsServiceConnection) + { + g_object_unref (this->pAccountsServiceConnection); + } #endif g_signal_handlers_disconnect_by_data(m_settings, this); @@ -293,9 +332,130 @@ public: private: #ifdef COLOR_TEMP_ENABLED + static void onUserChanged (GDBusConnection *pConnection, const gchar *sSender, const gchar *sPath, const gchar *sInterface, const gchar *sSignal, GVariant *pParameters, gpointer pUserData) + { + DisplayIndicator::Impl *pImpl = (DisplayIndicator::Impl*) pUserData; + g_variant_get (pParameters, "(s)", &pImpl->sUser); + loadManager (pImpl); + } + + static void getAccountsService (DisplayIndicator::Impl *pImpl, gint nUid) + { + pImpl->bReadingAccountsService = TRUE; + gchar *sPath = g_strdup_printf ("/org/freedesktop/Accounts/User%i", nUid); + GDBusProxy *pProxy = g_dbus_proxy_new_sync (pImpl->pAccountsServiceConnection, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.Accounts", sPath, "org.freedesktop.DBus.Properties", NULL, NULL); + g_free (sPath); + + if (pProxy) + { + const gchar *lProperties[] = {"brightness", "color-temp", "color-temp-profile"}; + + for (gint nIndex = 0; nIndex < 3; nIndex++) + { + GVariant *pParams = g_variant_new ("(ss)", "org.ayatana.indicator.display.AccountsService", lProperties[nIndex]); + GVariant *pValue = g_dbus_proxy_call_sync (pProxy, "Get", pParams, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL); + + if (pValue) + { + GVariant *pChild0 = g_variant_get_child_value (pValue, 0); + g_variant_unref (pValue); + GVariant *pChild1 = g_variant_get_child_value (pChild0, 0); + g_variant_unref (pChild0); + g_settings_set_value (pImpl->m_settings, lProperties[nIndex], pChild1); + g_variant_unref (pChild1); + } + } + } + + pImpl->bReadingAccountsService = FALSE; + } + + static void onUserLoaded (DisplayIndicator::Impl *pImpl, ActUser *pUser) + { + g_signal_handlers_disconnect_by_func (G_OBJECT (pUser), (gpointer) G_CALLBACK (onUserLoaded), pImpl); + + if (!pImpl->sUser) + { + GError *pError = NULL; + GVariant *pGreeterUser = g_dbus_connection_call_sync (pImpl->pConnection, GREETER_BUS_NAME, GREETER_BUS_PATH, GREETER_BUS_NAME, "GetUser", NULL, G_VARIANT_TYPE ("(s)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &pError); + + if (pError) + { + g_debug ("Failed calling GetUser, the greeter may not be ready yet: %s", pError->message); + g_error_free (pError); + + return; + } + + g_variant_get (pGreeterUser, "(s)", &pImpl->sUser); + } + + gboolean bPrefix = g_str_has_prefix (pImpl->sUser, "*"); + + if (!bPrefix) + { + const gchar *sUserName = act_user_get_user_name (pUser); + gboolean bSame = g_str_equal (pImpl->sUser, sUserName); + + if (bSame) + { + gint nUid = act_user_get_uid (pUser); + getAccountsService (pImpl, nUid); + updateColor (pImpl); + } + } + } + + static void onManagerLoaded (DisplayIndicator::Impl *pImpl) + { + ActUserManager *pManager = act_user_manager_get_default (); + + if (!pImpl->lUsers) + { + pImpl->lUsers = act_user_manager_list_users (pManager); + } + + for (GSList *lUser = pImpl->lUsers; lUser; lUser = lUser->next) + { + ActUser *pUser = static_cast(lUser->data); + gboolean bLoaded = act_user_is_loaded (pUser); + + if (bLoaded) + { + onUserLoaded (pImpl, pUser); + } + else + { + g_signal_connect_swapped (pUser, "notify::is-loaded", G_CALLBACK (onUserLoaded), pImpl); + } + } + } + + static void loadManager (DisplayIndicator::Impl *pImpl) + { + ActUserManager *pManager = act_user_manager_get_default (); + gboolean bLoaded = FALSE; + g_object_get (pManager, "is-loaded", &bLoaded, NULL); + + if (bLoaded) + { + onManagerLoaded (pImpl); + } + else + { + g_signal_connect_swapped (pManager, "notify::is-loaded", G_CALLBACK (onManagerLoaded), pImpl); + } + } + static gboolean updateColor (gpointer pData) { DisplayIndicator::Impl *pImpl = (DisplayIndicator::Impl*) pData; + + if (pImpl->bReadingAccountsService) + { + return G_SOURCE_CONTINUE; + } + guint nProfile = 0; g_settings_get (pImpl->m_settings, "color-temp-profile", "q", &nProfile); gdouble fBrightness = g_settings_get_double (pImpl->m_settings, "brightness"); @@ -390,6 +550,37 @@ private: pImpl->fLastBrightness = fBrightness; pImpl->nLasColorTemp = nTemperature; g_free (sCommand); + gint nUid = 0; + + if (!pImpl->bGreeter) + { + nUid = geteuid (); + } + else if (pImpl->sUser) + { + const struct passwd *pPasswd = getpwnam (pImpl->sUser); + + if (pPasswd) + { + nUid = pPasswd->pw_uid; + } + } + + if (nUid) + { + gchar *sPath = g_strdup_printf ("/org/freedesktop/Accounts/User%i", nUid); + GDBusProxy *pProxy = g_dbus_proxy_new_sync (pImpl->pAccountsServiceConnection, G_DBUS_PROXY_FLAGS_NONE, NULL, "org.freedesktop.Accounts", sPath, "org.freedesktop.DBus.Properties", NULL, NULL); + g_free (sPath); + GVariant *pBrightnessValue = g_variant_new ("d", pImpl->fLastBrightness); + GVariant *pBrightnessParams = g_variant_new ("(ssv)", "org.ayatana.indicator.display.AccountsService", "brightness", pBrightnessValue); + g_dbus_proxy_call (pProxy, "Set", pBrightnessParams, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + GVariant *pColorTempValue = g_variant_new ("q", pImpl->nLasColorTemp); + GVariant *pColorTempParams = g_variant_new ("(ssv)", "org.ayatana.indicator.display.AccountsService", "color-temp", pColorTempValue); + g_dbus_proxy_call (pProxy, "Set", pColorTempParams, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + GVariant *pProfileValue = g_variant_new ("q", nProfile); + GVariant *pProfileParams = g_variant_new ("(ssv)", "org.ayatana.indicator.display.AccountsService", "color-temp-profile", pProfileValue); + g_dbus_proxy_call (pProxy, "Set", pProfileParams, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + } } if (!pImpl->bGreeter) @@ -950,6 +1141,12 @@ private: GSettings *pMetacitySettings = NULL; GSettings *pColorSchemeSettings = NULL; gboolean bTest; + guint nGreeterSubscription; + GDBusConnection *pConnection; + gchar *sUser = NULL; + GSList *lUsers = NULL; + gboolean bReadingAccountsService = FALSE; + GDBusConnection *pAccountsServiceConnection = NULL; #endif }; -- cgit v1.2.3 From 0638d3d13063030e6c259ded3a9041b49269a45d Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Sun, 3 Dec 2023 23:11:35 +0100 Subject: CMakeLists.txt: Add accountsservice dependency --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7010e20..0292fef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,7 +75,7 @@ if (ENABLE_LOMIRI_FEATURES) endif () if (ENABLE_COLOR_TEMP) - list (APPEND SERVICE_DEPS libgeoclue-2.0) + list (APPEND SERVICE_DEPS libgeoclue-2.0 accountsservice) add_definitions (-DCOLOR_TEMP_ENABLED) endif () -- cgit v1.2.3 From 405c7fddc7a95ecde7f1221babd54350276e15cf Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Sun, 3 Dec 2023 23:15:02 +0100 Subject: .build.yml: Add accountsservice dependency --- .build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.build.yml b/.build.yml index f65c396..8c6db80 100644 --- a/.build.yml +++ b/.build.yml @@ -16,6 +16,7 @@ requires: - systemd - geoclue - gnome-desktop + - accountsservice # - libayatana-common (AUR) # - xsct (AUR) @@ -49,6 +50,7 @@ requires: - systemd - libgeoclue-2-dev - gsettings-desktop-schemas + - libaccountsservice-dev # For xsct - libx11-dev - libxrandr-dev @@ -82,6 +84,7 @@ requires: - gsettings-ubuntu-schemas - libgeoclue-2-dev - gsettings-desktop-schemas + - libaccountsservice-dev # For xsct - libx11-dev - libxrandr-dev @@ -115,6 +118,7 @@ requires: - gsettings-ubuntu-schemas - libgeoclue-2-dev - gsettings-desktop-schemas + - libaccountsservice-dev # For xsct - libx11-dev - libxrandr-dev -- cgit v1.2.3 From 86d64f3b4ec4ce7b0fb115093f646ffcdde7b88b Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Sun, 3 Dec 2023 23:18:51 +0100 Subject: debian/control: Add libaccountsservice-dev dependency --- debian/control | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/control b/debian/control index 2bf8004..b4da897 100644 --- a/debian/control +++ b/debian/control @@ -12,6 +12,7 @@ Build-Depends: cmake, libgudev-1.0-dev, libproperties-cpp-dev, libgeoclue-2-dev, + libaccountsservice-dev, # for coverage reports gcovr, lcov, -- cgit v1.2.3 From 8fec9b6fafe17c0182d3dda6157acf772898d518 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Sun, 3 Dec 2023 23:21:44 +0100 Subject: INSTALL.md: Update build dependencies --- INSTALL.md | 1 + 1 file changed, 1 insertion(+) diff --git a/INSTALL.md b/INSTALL.md index 8a11f7a..eaec47a 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -10,6 +10,7 @@ - gudev-1.0 - properties-cpp - libgeoclue-2.0 + - accountsservice - gtest (>= 1.6.0) - **For testing** - qt5-base5 - **For testing** - libqtdbusmock1 - **For testing** -- cgit v1.2.3