summaryrefslogtreecommitdiff
path: root/applets/clock/clock.c
diff options
context:
space:
mode:
authorGordon Norman Squash <[email protected]>2023-03-17 21:06:33 -0400
committerLuke from DC <[email protected]>2023-03-27 03:16:17 +0000
commit061193aca2309da9caeecf228857631a40739d9a (patch)
tree5a8bdaaca618d03128ea8784c746fd82c7db2256 /applets/clock/clock.c
parente504576092e499bdc5ecb14fc8b99db74ee9382d (diff)
downloadmate-panel-061193aca2309da9caeecf228857631a40739d9a.tar.bz2
mate-panel-061193aca2309da9caeecf228857631a40739d9a.tar.xz
Clock Applet: Update date/time and weather after resume from sleep mode
Before this commit, the Clock Applet was unaware of when the system resumed from sleep mode (e.g. suspend or hibernate). This meant that, if the user suspended the system and then woke it up some time later, the clock might not show the real current time, but instead would continue to show the time at which the system was suspended for up to a minute after the system woke up. This could be confusing to the user if they peered up at the clock immediately after, say, opening their laptop lid. This commit connects to ConsoleKit or (if available) systemd-logind via D-Bus, and listens for a signal that indicates when the system wakes up from sleep mode. When the system does wake up, the Clock Applet updates the date/time immediately, and also updates all the weather/temperature readings if possible. Note that if logind is missing, ConsoleKit2 is required for this feature to work; the original ConsoleKit lacked the signal required to implement this feature. This should not be a problem since it is unlikely that anyone would even consider using the original ConsoleKit in this day and age.
Diffstat (limited to 'applets/clock/clock.c')
-rw-r--r--applets/clock/clock.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/applets/clock/clock.c b/applets/clock/clock.c
index 8b427d2e..0ee49628 100644
--- a/applets/clock/clock.c
+++ b/applets/clock/clock.c
@@ -85,6 +85,16 @@
#define KEY_TEMPERATURE_UNIT "temperature-unit"
#define KEY_SPEED_UNIT "speed-unit"
+/* For watching for when the system resumes from sleep mode (e.g. suspend)
+ * and updating the clock as soon as that happens. */
+#define LOGIND_RUNNING() (access("/run/systemd/seats/", F_OK) >= 0)
+#define SYSTEMD_LOGIND_SERVICE "org.freedesktop.login1"
+#define SYSTEMD_LOGIND_PATH "/org/freedesktop/login1"
+#define SYSTEMD_LOGIND_INTERFACE "org.freedesktop.login1.Manager"
+#define CK_SERVICE "org.freedesktop.ConsoleKit"
+#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+
#define _clock_get_widget(x,y) (GTK_WIDGET (gtk_builder_get_object ((x)->builder, (y))))
enum {
@@ -186,6 +196,8 @@ struct _ClockData {
GSettings *settings;
const gchar *weather_icon_name;
+
+ GDBusProxy *system_manager_proxy;
};
/* Used to count the number of clock instances. It's there to know when we
@@ -747,6 +759,12 @@ free_locations (ClockData *cd)
static void
destroy_clock (GtkWidget * widget, ClockData *cd)
{
+ if (cd->system_manager_proxy)
+ {
+ g_signal_handlers_disconnect_by_data (cd->system_manager_proxy, cd);
+ g_object_unref (cd->system_manager_proxy);
+ }
+
if (cd->settings)
g_signal_handlers_disconnect_by_data( cd->settings, cd);
@@ -2478,6 +2496,86 @@ load_gsettings (ClockData *cd)
set_locations (cd, cities);
}
+/* When the system manager (ConsoleKit or systemd-logind) reports that
+ * the system has just resumed from sleep mode (e.g. suspend/hibernate),
+ * update the clock and the weather/temperature readings. That way, if
+ * the user suspended the system for an hour and then wakes the system up,
+ * the user will immediately see the current time and (if possible)
+ * updated weather data. Without this extra code, the user would most
+ * likely wake the system up and see the weather from an hour ago, and if
+ * the clock is set to not display seconds (only minutes), the clock may
+ * show an inaccurate time for up to a minute after resume.
+ */
+static void
+system_manager_signal_cb (GDBusProxy *proxy,
+ gchar *sender_name,
+ gchar *signal_name,
+ GVariant *parameters,
+ ClockData *cd)
+{
+ GVariant *variant;
+ gboolean active;
+
+ if (g_strcmp0 (signal_name, "PrepareForSleep") == 0)
+ {
+ variant = g_variant_get_child_value (parameters, 0);
+ active = g_variant_get_boolean (variant);
+ g_variant_unref (variant);
+
+ /* The PrepareForSleep signal is emitted by ConsoleKit2 and
+ * logind, both before sleep mode is entered, and
+ * immediately after the system has resumed from sleep mode.
+ * Listeners of this signal distinguish between the two
+ * states by checking the parameter to this signal. If the
+ * parameter is TRUE, the system is about to enter sleep
+ * mode; if FALSE, the system has resumed from sleep mode.
+ * We only care about updating the clock after resumption,
+ * so test if the parameter is FALSE.
+ */
+ if (active == FALSE)
+ {
+ update_clock (cd);
+ update_weather_locations (cd);
+ }
+ }
+}
+
+static void
+setup_monitor_for_resume (ClockData *cd)
+{
+ gboolean logind_running;
+ const char * service;
+ const char * path;
+ const char * interface;
+
+ /* If logind is running, connect to logind; otherwise use ConsoleKit.
+ */
+ logind_running = LOGIND_RUNNING ();
+ if (logind_running) {
+ service = SYSTEMD_LOGIND_SERVICE;
+ path = SYSTEMD_LOGIND_PATH;
+ interface = SYSTEMD_LOGIND_INTERFACE;
+ } else {
+ service = CK_SERVICE;
+ path = CK_MANAGER_PATH;
+ interface = CK_MANAGER_INTERFACE;
+ }
+
+ cd->system_manager_proxy = g_dbus_proxy_new_for_bus_sync
+ (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ NULL,
+ service, path, interface,
+ NULL, NULL);
+
+ if (cd->system_manager_proxy != NULL) {
+ g_signal_connect (cd->system_manager_proxy,
+ "g-signal",
+ G_CALLBACK (system_manager_signal_cb),
+ cd);
+ }
+}
+
static gboolean
fill_clock_applet (MatePanelApplet *applet)
{
@@ -2551,6 +2649,11 @@ fill_clock_applet (MatePanelApplet *applet)
G_CALLBACK (weather_icon_updated_cb),
cd);
+ /* If ConsoleKit or systemd-logind is available, set up to update
+ * the clock if/when the system resumes from sleep (e.g. suspend/
+ * hibernate). */
+ setup_monitor_for_resume (cd);
+
return TRUE;
}