diff options
Diffstat (limited to 'applets/clock/clock.c')
| -rw-r--r-- | applets/clock/clock.c | 535 |
1 files changed, 399 insertions, 136 deletions
diff --git a/applets/clock/clock.c b/applets/clock/clock.c index 8b427d2e..2e26b39f 100644 --- a/applets/clock/clock.c +++ b/applets/clock/clock.c @@ -51,10 +51,20 @@ #include <gdk/gdkkeysyms.h> #include <gio/gio.h> +#if defined (CLOCK_INPROCESS) && defined (HAVE_WAYLAND) +#include <gdk/gdkwayland.h> +#include <gtk-layer-shell/gtk-layer-shell.h> +#endif + #ifdef HAVE_X11 #include <gdk/gdkx.h> #endif +#ifndef HAVE_X11 +#include <gdk/gdkwayland.h> +#define GDK_IS_X11_DISPLAY(object) !(G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_WAYLAND_DISPLAY)) +#endif + #include <libmateweather/mateweather-prefs.h> #include <libmateweather/location-entry.h> #include <libmateweather/timezone-menu.h> @@ -84,6 +94,18 @@ #define KEY_CITIES "cities" #define KEY_TEMPERATURE_UNIT "temperature-unit" #define KEY_SPEED_UNIT "speed-unit" +#define KEY_SHOW_CALENDAR_EVENTS "show-calendar-events" +#define KEY_SHOW_TASKS "show-tasks" + +/* 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)))) @@ -112,6 +134,7 @@ struct _ClockData { GtkWidget *props; GtkWidget *calendar_popup; + gboolean calendar_popup_destroying; GtkWidget *clock_vbox; GtkSizeGroup *clock_group; @@ -186,6 +209,12 @@ struct _ClockData { GSettings *settings; const gchar *weather_icon_name; + + GDBusProxy *system_manager_proxy; + +#ifdef HAVE_EDS + CalendarClient *calendar_client; +#endif }; /* Used to count the number of clock instances. It's there to know when we @@ -441,7 +470,7 @@ get_updated_timeformat (ClockData *cd) /* Translators: This is a strftime format string. * It is used to display the time in 12-hours format (eg, like * in the US: 8:10 am). The %p expands to am/pm. */ - time_format = cd->showseconds ? _("%l:%M:%S %p") : _("%l:%M %p"); + time_format = cd->showseconds ? _("%_I:%M:%S %p") : _("%_I:%M %p"); else /* Translators: This is a strftime format string. * It is used to display the time in 24-hours format (eg, like @@ -747,6 +776,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); @@ -765,9 +800,12 @@ destroy_clock (GtkWidget * widget, ClockData *cd) gtk_widget_destroy (cd->props); cd->props = NULL; - if (cd->calendar_popup) + if (cd->calendar_popup && !cd->calendar_popup_destroying) { + cd->calendar_popup_destroying = TRUE; gtk_widget_destroy (cd->calendar_popup); + } cd->calendar_popup = NULL; + cd->calendar_popup_destroying = FALSE; g_free (cd->timeformat); @@ -794,6 +832,13 @@ destroy_clock (GtkWidget * widget, ClockData *cd) cd->builder = NULL; } +#ifdef HAVE_EDS + if (cd->calendar_client) { + g_object_unref (cd->calendar_client); + cd->calendar_client = NULL; + } +#endif + g_free (cd); } @@ -834,13 +879,31 @@ create_calendar (ClockData *cd) { GtkWidget *window; char *prefs_path; + char *fallback_path = NULL; prefs_path = mate_panel_applet_get_preferences_path (MATE_PANEL_APPLET (cd->applet)); + + /* Provide a fallback preferences path in case the applet doesn't + * provide one. This happens when running outside the actual panel, + * like in mate-panel-test-applets */ + if (!prefs_path || !prefs_path[0]) { + fallback_path = g_strdup ("/org/mate/panel/applets/clock/"); + g_free (prefs_path); + prefs_path = fallback_path; + } + window = calendar_window_new (&cd->current_time, prefs_path, - cd->orient == MATE_PANEL_APPLET_ORIENT_UP); + cd->orient == MATE_PANEL_APPLET_ORIENT_UP, + cd->settings); g_free (prefs_path); +#ifdef HAVE_EDS + if (cd->calendar_client) { + calendar_window_set_client (CALENDAR_WINDOW (window), cd->calendar_client); + } +#endif + calendar_window_set_show_weeks (CALENDAR_WINDOW (window), cd->showweek); @@ -870,105 +933,204 @@ create_calendar (ClockData *cd) static void position_calendar_popup (ClockData *cd) { -#ifdef HAVE_X11 - GtkRequisition req; - GtkAllocation allocation; - GdkDisplay *display; - GdkScreen *screen; - GdkRectangle monitor; - GdkGravity gravity = GDK_GRAVITY_NORTH_WEST; - int button_w, button_h; - int x, y; - int w, h; - int i, n; - gboolean found_monitor = FALSE; - - if (!GDK_IS_X11_DISPLAY (gdk_display_get_default ())) - return; +#if defined(HAVE_X11) && defined(GDK_WINDOWING_X11) + if (GDK_IS_X11_DISPLAY (gdk_display_get_default ())) + { + GtkRequisition req; + GtkAllocation allocation; + GdkDisplay *display; + GdkScreen *screen; + GdkRectangle monitor; + GdkGravity gravity = GDK_GRAVITY_NORTH_WEST; + int button_w, button_h; + int x, y; + int w, h; + int i, n; + gboolean found_monitor = FALSE; + + + /* Get root origin of the toggle button, and position above that. */ + gdk_window_get_origin (gtk_widget_get_window (cd->panel_button), + &x, &y); + + gtk_window_get_size (GTK_WINDOW (cd->calendar_popup), &w, &h); + gtk_widget_get_preferred_size (cd->calendar_popup, &req, NULL); + w = req.width; + h = req.height; + + gtk_widget_get_allocation (cd->panel_button, &allocation); + button_w = allocation.width; + button_h = allocation.height; + + screen = gtk_widget_get_screen (GTK_WIDGET (cd->calendar_popup)); + display = gtk_widget_get_display (GTK_WIDGET (cd->calendar_popup)); + + n = gdk_display_get_n_monitors (display); + for (i = 0; i < n; i++) { + gdk_monitor_get_geometry (gdk_display_get_monitor (display, i), &monitor); + if (x >= monitor.x && x <= monitor.x + monitor.width && + y >= monitor.y && y <= monitor.y + monitor.height) { + found_monitor = TRUE; + break; + } + } - /* Get root origin of the toggle button, and position above that. */ - gdk_window_get_origin (gtk_widget_get_window (cd->panel_button), - &x, &y); + if (!found_monitor) { + /* eek, we should be on one of those xinerama + monitors */ + monitor.x = 0; + monitor.y = 0; + monitor.width = WidthOfScreen (gdk_x11_screen_get_xscreen (screen)); + monitor.height = HeightOfScreen (gdk_x11_screen_get_xscreen (screen)); + } - gtk_window_get_size (GTK_WINDOW (cd->calendar_popup), &w, &h); - gtk_widget_get_preferred_size (cd->calendar_popup, &req, NULL); - w = req.width; - h = req.height; + /* Based on panel orientation, position the popup. + * Ignore window gravity since the window is undecorated. + * The orientations are all named backward from what + * I expected. + */ + switch (cd->orient) { + case MATE_PANEL_APPLET_ORIENT_RIGHT: + x += button_w; + if ((y + h) > monitor.y + monitor.height) + y -= (y + h) - (monitor.y + monitor.height); + + if ((y + h) > (monitor.height / 2)) + gravity = GDK_GRAVITY_SOUTH_WEST; + else + gravity = GDK_GRAVITY_NORTH_WEST; - gtk_widget_get_allocation (cd->panel_button, &allocation); - button_w = allocation.width; - button_h = allocation.height; - - screen = gtk_window_get_screen (GTK_WINDOW (cd->calendar_popup)); - display = gdk_screen_get_display (screen); - - n = gdk_display_get_n_monitors (display); - for (i = 0; i < n; i++) { - gdk_monitor_get_geometry (gdk_display_get_monitor (display, i), &monitor); - if (x >= monitor.x && x <= monitor.x + monitor.width && - y >= monitor.y && y <= monitor.y + monitor.height) { - found_monitor = TRUE; break; - } - } + case MATE_PANEL_APPLET_ORIENT_LEFT: + x -= w; + if ((y + h) > monitor.y + monitor.height) + y -= (y + h) - (monitor.y + monitor.height); - if (!found_monitor) { - /* eek, we should be on one of those xinerama - monitors */ - monitor.x = 0; - monitor.y = 0; - monitor.width = WidthOfScreen (gdk_x11_screen_get_xscreen (screen)); - monitor.height = HeightOfScreen (gdk_x11_screen_get_xscreen (screen)); - } + if ((y + h) > (monitor.height / 2)) + gravity = GDK_GRAVITY_SOUTH_EAST; + else + gravity = GDK_GRAVITY_NORTH_EAST; - /* Based on panel orientation, position the popup. - * Ignore window gravity since the window is undecorated. - * The orientations are all named backward from what - * I expected. - */ - switch (cd->orient) { - case MATE_PANEL_APPLET_ORIENT_RIGHT: - x += button_w; - if ((y + h) > monitor.y + monitor.height) - y -= (y + h) - (monitor.y + monitor.height); + break; + case MATE_PANEL_APPLET_ORIENT_DOWN: + y += button_h; + if ((x + w) > monitor.x + monitor.width) + x -= (x + w) - (monitor.x + monitor.width); - if ((y + h) > (monitor.height / 2)) - gravity = GDK_GRAVITY_SOUTH_WEST; - else gravity = GDK_GRAVITY_NORTH_WEST; - break; - case MATE_PANEL_APPLET_ORIENT_LEFT: - x -= w; - if ((y + h) > monitor.y + monitor.height) - y -= (y + h) - (monitor.y + monitor.height); + break; + case MATE_PANEL_APPLET_ORIENT_UP: + y -= h; + if ((x + w) > monitor.x + monitor.width) + x -= (x + w) - (monitor.x + monitor.width); - if ((y + h) > (monitor.height / 2)) - gravity = GDK_GRAVITY_SOUTH_EAST; - else - gravity = GDK_GRAVITY_NORTH_EAST; + gravity = GDK_GRAVITY_SOUTH_WEST; - break; - case MATE_PANEL_APPLET_ORIENT_DOWN: - y += button_h; - if ((x + w) > monitor.x + monitor.width) - x -= (x + w) - (monitor.x + monitor.width); + break; + } - gravity = GDK_GRAVITY_NORTH_WEST; + gtk_window_move (GTK_WINDOW (cd->calendar_popup), x, y); + gtk_window_set_gravity (GTK_WINDOW (cd->calendar_popup), gravity); + } +#endif - break; - case MATE_PANEL_APPLET_ORIENT_UP: - y -= h; - if ((x + w) > monitor.x + monitor.width) - x -= (x + w) - (monitor.x + monitor.width); + /*Only build wayland support when building in process*/ +#if defined(CLOCK_INPROCESS) && defined(HAVE_WAYLAND) && defined(GDK_WINDOWING_WAYLAND) + if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ())) + { + GtkWindow *window; + GdkWindow *panelwin; + GtkWidget *toplevel; + int x, y, w, h, panel_w, panel_h; + + /*Get the calendar window dimensions*/ + window = (GTK_WINDOW (cd->calendar_popup)); + gtk_window_get_size (window, &w, &h); + /*Find the position of the applet*/ + gdk_window_get_origin (gtk_widget_get_window (cd->panel_button), + &x, &y); + + /*Get the panel dimensions*/ + toplevel = gtk_widget_get_toplevel (cd->applet); + panelwin = gtk_widget_get_window (toplevel); + gdk_window_get_geometry (panelwin, NULL, NULL, &panel_w, &panel_h); + + /*Set up GTK Layer Shell*/ + gtk_layer_init_for_window (window); + gtk_layer_set_layer (window, GTK_LAYER_SHELL_LAYER_TOP); + + switch (cd->orient) { + case MATE_PANEL_APPLET_ORIENT_RIGHT: + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_LEFT, 0); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_RIGHT, FALSE); + if (y < (panel_h - h)) + { + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_BOTTOM, FALSE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_TOP, y); + } + else + { + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_TOP, FALSE); + } + break; - gravity = GDK_GRAVITY_SOUTH_WEST; + case MATE_PANEL_APPLET_ORIENT_LEFT: + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_RIGHT, 0); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_LEFT, FALSE); + if (y < (panel_h - h)) + { + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_BOTTOM, FALSE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_TOP, y); + } + else + { + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_TOP, FALSE); + } + break; - break; - } + case MATE_PANEL_APPLET_ORIENT_DOWN: + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_TOP, TRUE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_TOP, 0); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_BOTTOM, FALSE); + if (x < (panel_w - w)) + { + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_RIGHT, FALSE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_LEFT, x); + } + else + { + gtk_layer_set_anchor(window, GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_LEFT, FALSE); + } + break; - gtk_window_move (GTK_WINDOW (cd->calendar_popup), x, y); - gtk_window_set_gravity (GTK_WINDOW (cd->calendar_popup), gravity); + case MATE_PANEL_APPLET_ORIENT_UP: + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_BOTTOM, TRUE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_BOTTOM, 0); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_TOP, FALSE); + if (x < (panel_w - w)) + { + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_LEFT, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_RIGHT, FALSE); + gtk_layer_set_margin (window, GTK_LAYER_SHELL_EDGE_LEFT, x); + } + else + { + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_RIGHT, TRUE); + gtk_layer_set_anchor (window, GTK_LAYER_SHELL_EDGE_LEFT, FALSE); + } + break; + } + return; + } #endif } @@ -1065,35 +1227,17 @@ sort_locations_by_time (gconstpointer a, gconstpointer b) clock_location_localtime (loc_a, &tm_a); clock_location_localtime (loc_b, &tm_b); - ret = (tm_a.tm_year == tm_b.tm_year) ? 0 : 1; - if (ret) { - return (tm_a.tm_year < tm_b.tm_year) ? -1 : 1; - } - - ret = (tm_a.tm_mon == tm_b.tm_mon) ? 0 : 1; - if (ret) { - return (tm_a.tm_mon < tm_b.tm_mon) ? -1 : 1; - } - - ret = (tm_a.tm_mday == tm_b.tm_mday) ? 0 : 1; - if (ret) { - return (tm_a.tm_mday < tm_b.tm_mday) ? -1 : 1; - } - - ret = (tm_a.tm_hour == tm_b.tm_hour) ? 0 : 1; - if (ret) { - return (tm_a.tm_hour < tm_b.tm_hour) ? -1 : 1; - } - - ret = (tm_a.tm_min == tm_b.tm_min) ? 0 : 1; - if (ret) { - return (tm_a.tm_min < tm_b.tm_min) ? -1 : 1; - } - - ret = (tm_a.tm_sec == tm_b.tm_sec) ? 0 : 1; - if (ret) { - return (tm_a.tm_sec < tm_b.tm_sec) ? -1 : 1; - } + ret = tm_a.tm_year - tm_b.tm_year; + if (! ret) + ret = tm_a.tm_mon - tm_b.tm_mon; + if (! ret) + ret = tm_a.tm_mday - tm_b.tm_mday; + if (! ret) + ret = tm_a.tm_hour - tm_b.tm_hour; + if (! ret) + ret = tm_a.tm_min - tm_b.tm_min; + if (! ret) + ret = tm_a.tm_sec - tm_b.tm_sec; return ret; } @@ -1144,6 +1288,7 @@ location_tile_need_clock_format_cb(ClockLocationTile *tile, gpointer data) static void create_cities_section (ClockData *cd) { + GtkWidget *cities_box; GSList *node; GSList *cities; GSList *l; @@ -1157,8 +1302,16 @@ create_cities_section (ClockData *cd) g_slist_free (cd->location_tiles); cd->location_tiles = NULL; - cd->cities_section = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); - gtk_container_set_border_width (GTK_CONTAINER (cd->cities_section), 0); + cd->cities_section = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (cd->cities_section), + GTK_POLICY_NEVER, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (cd->cities_section), + GTK_SHADOW_NONE); + gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (cd->cities_section), + TRUE); + + cities_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); cities = cd->locations; if (g_slist_length (cities) == 0) { @@ -1180,7 +1333,7 @@ create_cities_section (ClockData *cd) g_signal_connect (city, "need-clock-format", G_CALLBACK (location_tile_need_clock_format_cb), cd); - gtk_box_pack_start (GTK_BOX (cd->cities_section), + gtk_box_pack_start (GTK_BOX (cities_box), GTK_WIDGET (city), FALSE, FALSE, 0); @@ -1191,6 +1344,8 @@ create_cities_section (ClockData *cd) g_slist_free (node); + gtk_container_add (GTK_CONTAINER (cd->cities_section), cities_box); + gtk_box_pack_end (GTK_BOX (cd->clock_vbox), cd->cities_section, FALSE, FALSE, 0); @@ -1234,9 +1389,11 @@ static void update_calendar_popup (ClockData *cd) { if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cd->panel_button))) { - if (cd->calendar_popup) { + if (cd->calendar_popup && !cd->calendar_popup_destroying) { + cd->calendar_popup_destroying = TRUE; gtk_widget_destroy (cd->calendar_popup); cd->calendar_popup = NULL; + cd->calendar_popup_destroying = FALSE; cd->cities_section = NULL; cd->map_widget = NULL; cd->clock_vbox = NULL; @@ -1249,7 +1406,7 @@ update_calendar_popup (ClockData *cd) return; } - if (!cd->calendar_popup) { + if (!cd->calendar_popup && !cd->calendar_popup_destroying) { cd->calendar_popup = create_calendar (cd); g_object_add_weak_pointer (G_OBJECT (cd->calendar_popup), (gpointer *) &cd->calendar_popup); @@ -2115,9 +2272,6 @@ location_set_current_cb (ClockLocation *loc, static void locations_changed (ClockData *cd) { - GSList *l; - glong id; - if (!cd->locations) { if (cd->weather_obox) gtk_widget_hide (cd->weather_obox); @@ -2132,8 +2286,9 @@ locations_changed (ClockData *cd) gtk_widget_show (cd->weather_obox); } - for (l = cd->locations; l; l = l->next) { + for (GSList *l = cd->locations; l; l = l->next) { ClockLocation *loc = l->data; + glong id; id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (loc), "weather-updated")); if (id == 0) { @@ -2393,18 +2548,8 @@ show_week_changed (GSettings *settings, static void setup_gsettings (ClockData *cd) { - gint format; - gchar *custom_format; - cd->settings = mate_panel_applet_settings_new (MATE_PANEL_APPLET (cd->applet), CLOCK_SCHEMA); - /* hack to allow users to set custom format in dconf-editor */ - format = g_settings_get_enum (cd->settings, KEY_FORMAT); - custom_format = g_settings_get_string (cd->settings, KEY_CUSTOM_FORMAT); - g_settings_set_enum (cd->settings, KEY_FORMAT, format); - g_settings_set_string (cd->settings, KEY_CUSTOM_FORMAT, custom_format); - g_free (custom_format); - g_signal_connect (cd->settings, "changed::" KEY_FORMAT, G_CALLBACK (format_changed), cd); g_signal_connect (cd->settings, "changed::" KEY_SHOW_SECONDS, G_CALLBACK (show_seconds_changed), cd); g_signal_connect (cd->settings, "changed::" KEY_SHOW_DATE, G_CALLBACK (show_date_changed), cd); @@ -2420,7 +2565,6 @@ setup_gsettings (ClockData *cd) static GSList * parse_gsettings_cities (ClockData *cd, gchar **values) { - gint i; LocationParserData data; GMarkupParseContext *context; @@ -2430,7 +2574,7 @@ parse_gsettings_cities (ClockData *cd, gchar **values) context = g_markup_parse_context_new (&location_parser, 0, &data, NULL); if (values) { - for (i = 0; values[i]; i++) { + for (gint i = 0; values[i]; i++) { g_markup_parse_context_parse (context, values[i], strlen(values[i]), NULL); } } @@ -2478,6 +2622,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) +{ + if (g_strcmp0 (signal_name, "PrepareForSleep") == 0) + { + GVariant *variant; + gboolean active; + + 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 +2775,16 @@ 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); + +#ifdef HAVE_EDS + /* Initialize persistent calendar client */ + cd->calendar_client = calendar_client_new (cd->settings); +#endif + return TRUE; } @@ -3100,6 +3334,35 @@ fill_prefs_window (ClockData *cd) g_settings_bind (cd->settings, KEY_SHOW_TEMPERATURE, widget, "active", G_SETTINGS_BIND_DEFAULT); +#ifdef HAVE_EDS + /* Set the EDS calendar event checkboxes */ + widget = _clock_get_widget (cd, "show_calendar_events_check"); + if (widget) { + /* Bind to gsettings - this should sync with calendar window automatically */ + g_settings_bind (cd->settings, KEY_SHOW_CALENDAR_EVENTS, widget, "active", + G_SETTINGS_BIND_DEFAULT); + } else { + g_warning ("Could not find show_calendar_events_check widget in preferences"); + } + + /* Set the EDS tasks checkboxes */ + widget = _clock_get_widget (cd, "show_tasks_check"); + if (widget) { + /* Bind to gsettings - this should sync with calendar window automatically */ + g_settings_bind (cd->settings, KEY_SHOW_TASKS, widget, "active", + G_SETTINGS_BIND_DEFAULT); + } else { + g_warning ("Could not find show_tasks_check widget in preferences"); + } + +#else + /* Hide the Calendar tab if EDS is not available */ + widget = _clock_get_widget (cd, "vbox-calendar"); + gtk_widget_hide (widget); + widget = _clock_get_widget (cd, "label-calendar-tab"); + gtk_widget_hide (widget); +#endif + /* Fill the Cities list */ widget = _clock_get_widget (cd, "cities_list"); |
