~noskcaj/ubuntu/vivid/xfce4-panel/4.11.2

« back to all changes in this revision

Viewing changes to plugins/clock/clock.c

  • Committer: Package Import Robot
  • Author(s): Unit 193, Unit 193, Lionel Le Folgoc
  • Date: 2014-02-12 15:41:39 UTC
  • mfrom: (1.1.36)
  • Revision ID: package-import@ubuntu.com-20140212154139-j4cm4hlso68qadjw
Tags: 4.11.0~0.git20140209.86a1b73-0ubuntu1
[ Unit 193 ]
* New git snapshot. (LP: #1238997)
* debian/patches:
  - 02_potfiles-fix-ftbfs.patch: added, add missing files to po/POTFILES.in.
* debian/control: add b-dep on newer garcon.

[ Lionel Le Folgoc ]
* debian/patches:
  - xubuntu_add-calendar-popup-to-clock-plugin.patch: dropped, included.
  - series: refreshed.
* debian/xfce4-panel.install: include both (gtk2 and gtk3) wrappers.
* debian/rules: pass --enable-gtk3 --disable-silent-rules to configure script.
* debian/control: add b-dep on libgtk-3-dev.
* debian/xfce4-panel.shlibs: updated for the gtk3 library.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
#include <config.h>
22
22
#endif
23
23
 
24
 
#ifdef HAVE_TIME_H
25
 
#include <time.h>
26
 
#endif
27
24
#ifdef HAVE_MATH_H
28
25
#include <math.h>
29
26
#endif
30
27
 
 
28
#include <gdk/gdkkeysyms.h>
31
29
#include <gtk/gtk.h>
32
30
#include <exo/exo.h>
33
31
#include <libxfce4ui/libxfce4ui.h>
37
35
#include <common/panel-utils.h>
38
36
 
39
37
#include "clock.h"
 
38
#include "clock-time.h"
40
39
#include "clock-analog.h"
41
40
#include "clock-binary.h"
42
41
#include "clock-digital.h"
46
45
 
47
46
#define DEFAULT_TOOLTIP_FORMAT "%A %d %B %Y"
48
47
 
 
48
/* Please adjust the following command to match your distribution */
 
49
/* e.g. "time-admin" */
 
50
#define DEFAULT_TIME_CONFIG_TOOL "time-admin"
 
51
 
 
52
/* Use the posix directory for the names. If people want a time based on posix or
 
53
 * right time, they can prepend that manually in the entry */
 
54
#define ZONEINFO_DIR "/usr/share/zoneinfo/posix/"
 
55
 
49
56
 
50
57
 
51
58
static void     clock_plugin_get_property              (GObject               *object,
57
64
                                                        const GValue          *value,
58
65
                                                        GParamSpec            *pspec);
59
66
static gboolean clock_plugin_leave_notify_event        (GtkWidget             *widget,
60
 
                                                        GdkEventCrossing      *event);
 
67
                                                        GdkEventCrossing      *event,
 
68
                                                        ClockPlugin           *plugin);
61
69
static gboolean clock_plugin_enter_notify_event        (GtkWidget             *widget,
62
 
                                                        GdkEventCrossing      *event);
 
70
                                                        GdkEventCrossing      *event,
 
71
                                                        ClockPlugin           *plugin);
63
72
static gboolean clock_plugin_button_press_event        (GtkWidget             *widget,
64
 
                                                        GdkEventButton        *event);
 
73
                                                        GdkEventButton        *event,
 
74
                                                        ClockPlugin           *plugin);
65
75
static void     clock_plugin_construct                 (XfcePanelPlugin       *panel_plugin);
66
76
static void     clock_plugin_free_data                 (XfcePanelPlugin       *panel_plugin);
67
77
static gboolean clock_plugin_size_changed              (XfcePanelPlugin       *panel_plugin,
73
83
                                                        XfceScreenPosition     position);
74
84
static void     clock_plugin_configure_plugin          (XfcePanelPlugin       *panel_plugin);
75
85
static void     clock_plugin_set_mode                  (ClockPlugin           *plugin);
76
 
static void     clock_plugin_reposition_calendar       (ClockPlugin          *plugin);
77
 
static void     clock_plugin_popup_calendar            (ClockPlugin           *plugin);
 
86
static void     clock_plugin_reposition_calendar       (ClockPlugin           *plugin);
 
87
static gboolean clock_plugin_pointer_grab              (ClockPlugin           *plugin,
 
88
                                                        GtkWidget             *widget,
 
89
                                                        gboolean               keep);
 
90
static void     clock_plugin_pointer_ungrab            (ClockPlugin           *plugin,
 
91
                                                        GtkWidget             *widget);
 
92
static gboolean clock_plugin_calendar_pointed          (GtkWidget             *calendar_window,
 
93
                                                        gdouble                x_root,
 
94
                                                        gdouble                y_root);
 
95
static gboolean clock_plugin_calendar_button_press_event (GtkWidget           *calendar_window,
 
96
                                                          GdkEventButton      *event,
 
97
                                                          ClockPlugin         *plugin);
 
98
static gboolean clock_plugin_calendar_key_press_event  (GtkWidget             *calendar_window,
 
99
                                                        GdkEventKey           *event,
 
100
                                                        ClockPlugin           *plugin);
 
101
static void     clock_plugin_popup_calendar            (ClockPlugin           *plugin,
 
102
                                                        gboolean               modal);
78
103
static void     clock_plugin_hide_calendar             (ClockPlugin           *plugin);
79
104
static gboolean clock_plugin_tooltip                   (gpointer               user_data);
80
 
static gboolean clock_plugin_timeout_running           (gpointer               user_data);
81
 
static void     clock_plugin_timeout_destroyed         (gpointer               user_data);
82
 
static gboolean clock_plugin_timeout_sync              (gpointer               user_data);
83
105
 
84
106
 
85
107
 
87
109
{
88
110
  PROP_0,
89
111
  PROP_MODE,
90
 
  PROP_SHOW_FRAME,
91
112
  PROP_TOOLTIP_FORMAT,
92
113
  PROP_COMMAND,
93
 
  PROP_ROTATE_VERTICALLY
 
114
  PROP_ROTATE_VERTICALLY,
 
115
  PROP_TIME_CONFIG_TOOL
94
116
};
95
117
 
96
118
typedef enum
118
140
  XfcePanelPlugin __parent__;
119
141
 
120
142
  GtkWidget          *clock;
121
 
  GtkWidget          *frame;
 
143
  GtkWidget          *button;
122
144
 
123
145
  GtkWidget          *calendar_window;
124
146
  GtkWidget          *calendar;
125
147
 
126
 
  guint               show_frame : 1;
127
148
  gchar              *command;
128
149
  ClockPluginMode     mode;
129
150
  guint               rotate_vertically : 1;
130
151
 
131
152
  gchar              *tooltip_format;
132
 
  ClockPluginTimeout *tooltip_timeout;
133
 
};
134
 
 
135
 
struct _ClockPluginTimeout
136
 
{
137
 
  guint       interval;
138
 
  GSourceFunc function;
139
 
  gpointer    data;
140
 
  guint       timeout_id;
141
 
  guint       restart : 1;
 
153
  ClockTimeTimeout   *tooltip_timeout;
 
154
 
 
155
  GdkGrabStatus       grab_pointer;
 
156
  GdkGrabStatus       grab_keyboard;
 
157
 
 
158
  gchar              *time_config_tool;
 
159
  ClockTime          *time;
142
160
};
143
161
 
144
162
typedef struct
145
163
{
146
164
  ClockPlugin *plugin;
147
165
  GtkBuilder  *builder;
 
166
  guint        zonecompletion_idle;
148
167
}
149
168
ClockPluginDialog;
150
169
 
177
196
 
178
197
/* define the plugin */
179
198
XFCE_PANEL_DEFINE_PLUGIN (ClockPlugin, clock_plugin,
 
199
  clock_time_register_type,
180
200
  xfce_clock_analog_register_type,
181
201
  xfce_clock_binary_register_type,
182
202
  xfce_clock_digital_register_type,
189
209
clock_plugin_class_init (ClockPluginClass *klass)
190
210
{
191
211
  GObjectClass         *gobject_class;
192
 
  GtkWidgetClass       *widget_class;
193
212
  XfcePanelPluginClass *plugin_class;
194
213
 
195
214
  gobject_class = G_OBJECT_CLASS (klass);
196
215
  gobject_class->set_property = clock_plugin_set_property;
197
216
  gobject_class->get_property = clock_plugin_get_property;
198
217
 
199
 
  widget_class = GTK_WIDGET_CLASS (klass);
200
 
  widget_class->leave_notify_event = clock_plugin_leave_notify_event;
201
 
  widget_class->enter_notify_event = clock_plugin_enter_notify_event;
202
 
  widget_class->button_press_event = clock_plugin_button_press_event;
203
 
 
204
218
  plugin_class = XFCE_PANEL_PLUGIN_CLASS (klass);
205
219
  plugin_class->construct = clock_plugin_construct;
206
220
  plugin_class->free_data = clock_plugin_free_data;
219
233
                                                      EXO_PARAM_READWRITE));
220
234
 
221
235
  g_object_class_install_property (gobject_class,
222
 
                                   PROP_SHOW_FRAME,
223
 
                                   g_param_spec_boolean ("show-frame",
224
 
                                                         NULL, NULL,
225
 
                                                         TRUE,
226
 
                                                         EXO_PARAM_READWRITE));
227
 
 
228
 
  g_object_class_install_property (gobject_class,
229
236
                                   PROP_TOOLTIP_FORMAT,
230
237
                                   g_param_spec_string ("tooltip-format",
231
238
                                                        NULL, NULL,
244
251
                                   g_param_spec_string ("command",
245
252
                                                        NULL, NULL, NULL,
246
253
                                                        EXO_PARAM_READWRITE));
 
254
 
 
255
  g_object_class_install_property (gobject_class,
 
256
                                   PROP_TIME_CONFIG_TOOL,
 
257
                                   g_param_spec_string ("time-config-tool",
 
258
                                                        NULL, NULL,
 
259
                                                        DEFAULT_TIME_CONFIG_TOOL,
 
260
                                                        EXO_PARAM_READWRITE));
247
261
}
248
262
 
249
263
 
253
267
{
254
268
  plugin->mode = CLOCK_PLUGIN_MODE_DEFAULT;
255
269
  plugin->clock = NULL;
256
 
  plugin->show_frame = TRUE;
257
270
  plugin->tooltip_format = g_strdup (DEFAULT_TOOLTIP_FORMAT);
258
271
  plugin->tooltip_timeout = NULL;
259
272
  plugin->command = NULL;
 
273
  plugin->time_config_tool = g_strdup (DEFAULT_TIME_CONFIG_TOOL);
260
274
  plugin->rotate_vertically = TRUE;
 
275
  plugin->time = clock_time_new ();
261
276
 
262
 
  plugin->frame = gtk_frame_new (NULL);
263
 
  gtk_container_add (GTK_CONTAINER (plugin), plugin->frame);
264
 
  gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame), GTK_SHADOW_ETCHED_IN);
265
 
  gtk_widget_show (plugin->frame);
 
277
  plugin->button = xfce_panel_create_toggle_button ();
 
278
  /* xfce_panel_plugin_add_action_widget (XFCE_PANEL_PLUGIN (plugin), plugin->button); */
 
279
  gtk_container_add (GTK_CONTAINER (plugin), plugin->button);
 
280
  gtk_widget_set_name (plugin->button, "clock-button");
 
281
  gtk_button_set_relief (GTK_BUTTON (plugin->button), GTK_RELIEF_NONE);
 
282
  /* Have to handle all events in the button object rather than the plugin.
 
283
   * Otherwise, default handlers will block the events. */
 
284
  g_signal_connect (G_OBJECT (plugin->button), "button-press-event",
 
285
                    G_CALLBACK (clock_plugin_button_press_event), plugin);
 
286
  g_signal_connect (G_OBJECT (plugin->button), "enter-notify-event",
 
287
                    G_CALLBACK (clock_plugin_enter_notify_event), plugin);
 
288
  g_signal_connect (G_OBJECT (plugin->button), "leave-notify-event",
 
289
                    G_CALLBACK (clock_plugin_leave_notify_event), plugin);
 
290
  gtk_widget_show (plugin->button);
266
291
}
267
292
 
268
293
 
281
306
      g_value_set_uint (value, plugin->mode);
282
307
      break;
283
308
 
284
 
    case PROP_SHOW_FRAME:
285
 
      g_value_set_boolean (value, plugin->show_frame);
286
 
      break;
287
 
 
288
309
    case PROP_TOOLTIP_FORMAT:
289
310
      g_value_set_string (value, plugin->tooltip_format);
290
311
      break;
293
314
      g_value_set_string (value, plugin->command);
294
315
      break;
295
316
 
 
317
    case PROP_TIME_CONFIG_TOOL:
 
318
      g_value_set_string (value, plugin->time_config_tool);
 
319
      break;
 
320
 
296
321
    case PROP_ROTATE_VERTICALLY:
297
322
      g_value_set_boolean (value, plugin->rotate_vertically);
298
323
      break;
312
337
                           GParamSpec   *pspec)
313
338
{
314
339
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (object);
315
 
  gboolean     show_frame;
316
340
  gboolean     rotate_vertically;
317
341
 
318
342
  switch (prop_id)
325
349
        }
326
350
      break;
327
351
 
328
 
    case PROP_SHOW_FRAME:
329
 
      show_frame = g_value_get_boolean (value);
330
 
      if (plugin->show_frame != show_frame)
331
 
        {
332
 
          plugin->show_frame = show_frame;
333
 
          gtk_frame_set_shadow_type (GTK_FRAME (plugin->frame),
334
 
              show_frame ? GTK_SHADOW_ETCHED_IN : GTK_SHADOW_NONE);
335
 
        }
336
 
      break;
337
 
 
338
352
    case PROP_TOOLTIP_FORMAT:
339
353
      g_free (plugin->tooltip_format);
340
354
      plugin->tooltip_format = g_value_dup_string (value);
350
364
      clock_plugin_hide_calendar (plugin);
351
365
      break;
352
366
 
 
367
    case PROP_TIME_CONFIG_TOOL:
 
368
      g_free (plugin->time_config_tool);
 
369
      plugin->time_config_tool = g_value_dup_string (value);
 
370
      break;
 
371
 
353
372
    case PROP_ROTATE_VERTICALLY:
354
373
      rotate_vertically = g_value_get_boolean (value);
355
374
      if (plugin->rotate_vertically != rotate_vertically)
369
388
 
370
389
static gboolean
371
390
clock_plugin_leave_notify_event (GtkWidget        *widget,
372
 
                                 GdkEventCrossing *event)
 
391
                                 GdkEventCrossing *event,
 
392
                                 ClockPlugin      *plugin)
373
393
{
374
 
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
375
 
 
376
394
  /* stop a running tooltip timeout when we leave the widget */
377
395
  if (plugin->tooltip_timeout != NULL)
378
396
    {
379
 
      clock_plugin_timeout_free (plugin->tooltip_timeout);
 
397
      clock_time_timeout_free (plugin->tooltip_timeout);
380
398
      plugin->tooltip_timeout = NULL;
381
399
    }
382
400
 
387
405
 
388
406
static gboolean
389
407
clock_plugin_enter_notify_event (GtkWidget        *widget,
390
 
                                 GdkEventCrossing *event)
 
408
                                 GdkEventCrossing *event,
 
409
                                 ClockPlugin      *plugin)
391
410
{
392
 
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
393
411
  guint        interval;
394
412
 
395
413
  /* start the tooltip timeout if needed */
396
414
  if (plugin->tooltip_timeout == NULL)
397
415
    {
398
 
      interval = clock_plugin_interval_from_format (plugin->tooltip_format);
399
 
      plugin->tooltip_timeout = clock_plugin_timeout_new (interval, clock_plugin_tooltip, plugin);
 
416
      interval = clock_time_interval_from_format (plugin->tooltip_format);
 
417
      plugin->tooltip_timeout = clock_time_timeout_new (interval, plugin->time,
 
418
                                                        G_CALLBACK (clock_plugin_tooltip), plugin);
400
419
    }
401
420
 
402
421
  return FALSE;
406
425
 
407
426
static gboolean
408
427
clock_plugin_button_press_event (GtkWidget      *widget,
409
 
                                 GdkEventButton *event)
 
428
                                 GdkEventButton *event,
 
429
                                 ClockPlugin    *plugin)
410
430
{
411
 
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (widget);
412
431
  GError      *error = NULL;
413
432
 
414
 
  if (event->button == 1)
 
433
  if (event->button == 1 || event->button == 2)
415
434
    {
416
435
      if (event->type == GDK_BUTTON_PRESS &&
417
436
          exo_str_is_empty (plugin->command))
419
438
          /* toggle calendar window visibility */
420
439
          if (plugin->calendar_window == NULL
421
440
              || !gtk_widget_get_visible (GTK_WIDGET (plugin->calendar_window)))
422
 
            clock_plugin_popup_calendar (plugin);
 
441
            clock_plugin_popup_calendar
 
442
              (plugin, event->button == 1 && !(event->state & GDK_CONTROL_MASK));
423
443
          else
424
444
            clock_plugin_hide_calendar (plugin);
425
445
 
440
460
 
441
461
          return TRUE;
442
462
        }
 
463
      return TRUE;
443
464
    }
444
465
 
445
 
  return (*GTK_WIDGET_CLASS (clock_plugin_parent_class)->button_press_event) (widget, event);
 
466
  /* bypass GTK_TOGGLE_BUTTON's handler and go directly to the plugin's one */
 
467
  return (*GTK_WIDGET_CLASS (clock_plugin_parent_class)->button_press_event) (GTK_WIDGET (plugin), event);
446
468
}
447
469
 
448
470
 
454
476
  const PanelProperty  properties[] =
455
477
  {
456
478
    { "mode", G_TYPE_UINT },
457
 
    { "show-frame", G_TYPE_BOOLEAN },
458
479
    { "tooltip-format", G_TYPE_STRING },
459
480
    { "command", G_TYPE_STRING },
460
481
    { "rotate-vertically", G_TYPE_BOOLEAN },
 
482
    { "time-config-tool", G_TYPE_STRING },
461
483
    { NULL }
462
484
  };
463
485
 
 
486
  const PanelProperty  time_properties[] =
 
487
    {
 
488
      { "timezone", G_TYPE_STRING },
 
489
      { NULL }
 
490
    };
 
491
 
464
492
  /* show configure */
465
493
  xfce_panel_plugin_menu_show_configure (panel_plugin);
466
494
 
469
497
                         xfce_panel_plugin_get_property_base (panel_plugin),
470
498
                         properties, FALSE);
471
499
 
 
500
  panel_properties_bind (NULL, G_OBJECT (plugin->time),
 
501
                         xfce_panel_plugin_get_property_base (panel_plugin),
 
502
                         time_properties, FALSE);
 
503
 
472
504
  /* make sure a mode is set */
473
505
  if (plugin->mode == CLOCK_PLUGIN_MODE_DEFAULT)
474
506
    clock_plugin_set_mode (plugin);
482
514
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
483
515
 
484
516
  if (plugin->tooltip_timeout != NULL)
485
 
    clock_plugin_timeout_free (plugin->tooltip_timeout);
 
517
    clock_time_timeout_free (plugin->tooltip_timeout);
486
518
 
487
519
  if (plugin->calendar_window != NULL)
488
520
    gtk_widget_destroy (plugin->calendar_window);
489
521
 
 
522
  g_object_unref (G_OBJECT (plugin->time));
 
523
 
490
524
  g_free (plugin->tooltip_format);
 
525
  g_free (plugin->time_config_tool);
491
526
  g_free (plugin->command);
492
527
}
493
528
 
500
535
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (panel_plugin);
501
536
  gdouble      ratio;
502
537
  gint         ratio_size;
503
 
  gint         border = 0;
504
538
  gint         offset;
505
539
 
506
540
  if (plugin->clock == NULL)
507
541
    return TRUE;
508
542
 
509
 
  /* set the frame border */
510
 
  if (plugin->show_frame && size > 26)
511
 
    border = 1;
512
 
  gtk_container_set_border_width (GTK_CONTAINER (plugin->frame), border);
513
 
 
514
543
  /* get the width:height ratio */
515
544
  g_object_get (G_OBJECT (plugin->clock), "size-ratio", &ratio, NULL);
516
545
  if (ratio > 0)
517
546
    {
518
 
      offset = MAX (plugin->frame->style->xthickness, plugin->frame->style->ythickness) + border;
519
 
      offset *= 2;
520
 
      ratio_size = size - offset;
 
547
      ratio_size = size;
 
548
      offset = 0;
521
549
    }
522
550
  else
523
551
    {
730
758
 
731
759
 
732
760
static void
733
 
clock_plugin_configure_plugin_chooser_fill (GtkComboBox *combo,
 
761
clock_plugin_configure_plugin_chooser_fill (ClockPlugin *plugin,
 
762
                                            GtkComboBox *combo,
734
763
                                            GtkEntry    *entry,
735
764
                                            const gchar *formats[])
736
765
{
737
766
  guint         i;
738
767
  GtkListStore *store;
739
768
  gchar        *preview;
740
 
  struct tm     now;
741
769
  GtkTreeIter   iter;
742
770
  const gchar  *active_format;
743
771
  gboolean      has_active = FALSE;
744
772
 
 
773
  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
745
774
  panel_return_if_fail (GTK_IS_COMBO_BOX (combo));
746
775
  panel_return_if_fail (GTK_IS_ENTRY (entry));
747
776
 
751
780
  store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING);
752
781
  gtk_combo_box_set_model (combo, GTK_TREE_MODEL (store));
753
782
 
754
 
  clock_plugin_get_localtime (&now);
755
 
 
756
783
  active_format = gtk_entry_get_text (entry);
757
784
 
758
785
  for (i = 0; formats[i] != NULL; i++)
759
786
    {
760
 
      preview = clock_plugin_strdup_strftime (_(formats[i]), &now);
 
787
      preview = clock_time_strdup_strftime (plugin->time, _(formats[i]));
761
788
      gtk_list_store_insert_with_values (store, &iter, i,
762
789
                                         COLUMN_FORMAT, _(formats[i]),
763
790
                                         COLUMN_TEXT, preview, -1);
795
822
static void
796
823
clock_plugin_configure_plugin_free (gpointer user_data)
797
824
{
798
 
  g_slice_free (ClockPluginDialog, user_data);
 
825
  ClockPluginDialog *dialog = user_data;
 
826
 
 
827
  if (dialog->zonecompletion_idle != 0)
 
828
    g_source_remove (dialog->zonecompletion_idle);
 
829
 
 
830
  g_slice_free (ClockPluginDialog, dialog);
 
831
}
 
832
 
 
833
 
 
834
 
 
835
static void
 
836
clock_plugin_configure_config_tool_changed (ClockPluginDialog *dialog)
 
837
{
 
838
  GObject *object;
 
839
  gchar   *path;
 
840
 
 
841
  panel_return_if_fail (GTK_IS_BUILDER (dialog->builder));
 
842
  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (dialog->plugin));
 
843
 
 
844
  object = gtk_builder_get_object (dialog->builder, "run-time-config-tool");
 
845
  panel_return_if_fail (GTK_IS_BUTTON (object));
 
846
  path = g_find_program_in_path (dialog->plugin->time_config_tool);
 
847
  gtk_widget_set_visible (GTK_WIDGET (object), path != NULL);
 
848
  g_free (path);
 
849
}
 
850
 
 
851
 
 
852
 
 
853
static void
 
854
clock_plugin_configure_run_config_tool (GtkWidget   *button,
 
855
                                        ClockPlugin *plugin)
 
856
{
 
857
  GError *error = NULL;
 
858
 
 
859
  panel_return_if_fail (XFCE_IS_CLOCK_PLUGIN (plugin));
 
860
 
 
861
  if (!xfce_spawn_command_line_on_screen (gtk_widget_get_screen (button),
 
862
                                          plugin->time_config_tool,
 
863
                                          FALSE, FALSE, &error))
 
864
    {
 
865
      xfce_dialog_show_error (NULL, error, _("Failed to execute command \"%s\"."), plugin->time_config_tool);
 
866
      g_error_free (error);
 
867
    }
 
868
}
 
869
 
 
870
 
 
871
 
 
872
static void
 
873
clock_plugin_configure_zoneinfo_model_insert (GtkListStore *store,
 
874
                                              const gchar  *parent)
 
875
{
 
876
  gchar       *filename;
 
877
  GtkTreeIter  iter;
 
878
  GDir        *dir;
 
879
  const gchar *name;
 
880
  gsize        dirlen = strlen (ZONEINFO_DIR);
 
881
 
 
882
  panel_return_if_fail (GTK_IS_LIST_STORE (store));
 
883
 
 
884
  dir = g_dir_open (parent, 0, NULL);
 
885
  if (dir == NULL)
 
886
    return;
 
887
 
 
888
  for (;;)
 
889
    {
 
890
      name = g_dir_read_name (dir);
 
891
      if (name == NULL)
 
892
        break;
 
893
 
 
894
      filename = g_build_filename (parent, name, NULL);
 
895
 
 
896
      if (g_file_test (filename, G_FILE_TEST_IS_DIR))
 
897
        {
 
898
          clock_plugin_configure_zoneinfo_model_insert (store, filename);
 
899
        }
 
900
      else
 
901
        {
 
902
          gtk_list_store_append (store, &iter);
 
903
          gtk_list_store_set (store, &iter, 0, filename + dirlen, -1);
 
904
        }
 
905
 
 
906
      g_free (filename);
 
907
    }
 
908
 
 
909
  g_dir_close (dir);
 
910
}
 
911
 
 
912
 
 
913
 
 
914
static gboolean
 
915
clock_plugin_configure_zoneinfo_model (gpointer data)
 
916
{
 
917
  ClockPluginDialog  *dialog = data;
 
918
  GtkEntryCompletion *completion;
 
919
  GtkListStore       *store;
 
920
  GObject            *object;
 
921
 
 
922
  GDK_THREADS_ENTER ();
 
923
 
 
924
  dialog->zonecompletion_idle = 0;
 
925
 
 
926
  object = gtk_builder_get_object (dialog->builder, "timezone-name");
 
927
  panel_return_val_if_fail (GTK_IS_ENTRY (object), FALSE);
 
928
 
 
929
  /* build timezone model */
 
930
  store = gtk_list_store_new (1, G_TYPE_STRING);
 
931
  clock_plugin_configure_zoneinfo_model_insert (store, ZONEINFO_DIR);
 
932
  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 0, GTK_SORT_ASCENDING);
 
933
 
 
934
  completion = gtk_entry_completion_new ();
 
935
  gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (store));
 
936
  g_object_unref (G_OBJECT (store));
 
937
 
 
938
  gtk_entry_set_completion (GTK_ENTRY (object), completion);
 
939
  gtk_entry_completion_set_popup_single_match (completion, TRUE);
 
940
  gtk_entry_completion_set_text_column (completion, 0);
 
941
 
 
942
  g_object_unref (G_OBJECT (completion));
 
943
 
 
944
  GDK_THREADS_LEAVE ();
 
945
 
 
946
  return FALSE;
799
947
}
800
948
 
801
949
 
823
971
  dialog->plugin = plugin;
824
972
  dialog->builder = builder;
825
973
 
 
974
  object = gtk_builder_get_object (builder, "run-time-config-tool");
 
975
  panel_return_if_fail (GTK_IS_BUTTON (object));
 
976
  g_signal_connect_swapped (G_OBJECT (plugin), "notify::time-config-tool",
 
977
                            G_CALLBACK (clock_plugin_configure_config_tool_changed),
 
978
                            dialog);
 
979
  clock_plugin_configure_config_tool_changed (dialog);
 
980
  g_signal_connect (G_OBJECT (object), "clicked",
 
981
      G_CALLBACK (clock_plugin_configure_run_config_tool), plugin);
 
982
 
 
983
  object = gtk_builder_get_object (builder, "timezone-name");
 
984
  panel_return_if_fail (GTK_IS_ENTRY (object));
 
985
  exo_mutual_binding_new (G_OBJECT (plugin->time), "timezone",
 
986
                          G_OBJECT (object), "text");
 
987
 
 
988
  /* idle add the zone completion */
 
989
  dialog->zonecompletion_idle = g_idle_add (clock_plugin_configure_zoneinfo_model, dialog);
 
990
 
826
991
  object = gtk_builder_get_object (builder, "mode");
827
992
  g_signal_connect_data (G_OBJECT (object), "changed",
828
993
      G_CALLBACK (clock_plugin_configure_plugin_mode_changed), dialog,
830
995
  exo_mutual_binding_new (G_OBJECT (plugin), "mode",
831
996
                          G_OBJECT (object), "active");
832
997
 
833
 
  object = gtk_builder_get_object (builder, "show-frame");
834
 
  exo_mutual_binding_new (G_OBJECT (plugin), "show-frame",
835
 
                          G_OBJECT (object), "active");
836
 
 
837
998
  object = gtk_builder_get_object (builder, "tooltip-format");
838
999
  exo_mutual_binding_new (G_OBJECT (plugin), "tooltip-format",
839
1000
                          G_OBJECT (object), "text");
840
1001
  combo = gtk_builder_get_object (builder, "tooltip-chooser");
841
 
  clock_plugin_configure_plugin_chooser_fill (GTK_COMBO_BOX (combo),
 
1002
  clock_plugin_configure_plugin_chooser_fill (plugin,
 
1003
                                              GTK_COMBO_BOX (combo),
842
1004
                                              GTK_ENTRY (object),
843
1005
                                              tooltip_formats);
844
1006
 
845
1007
  object = gtk_builder_get_object (builder, "digital-format");
846
1008
  combo = gtk_builder_get_object (builder, "digital-chooser");
847
 
  clock_plugin_configure_plugin_chooser_fill (GTK_COMBO_BOX (combo),
 
1009
  clock_plugin_configure_plugin_chooser_fill (plugin,
 
1010
                                              GTK_COMBO_BOX (combo),
848
1011
                                              GTK_ENTRY (object),
849
1012
                                              digital_formats);
850
1013
 
894
1057
 
895
1058
  /* create a new clock */
896
1059
  if (plugin->mode == CLOCK_PLUGIN_MODE_ANALOG)
897
 
    plugin->clock = xfce_clock_analog_new ();
 
1060
    plugin->clock = xfce_clock_analog_new (plugin->time);
898
1061
  else if (plugin->mode == CLOCK_PLUGIN_MODE_BINARY)
899
 
    plugin->clock = xfce_clock_binary_new ();
 
1062
    plugin->clock = xfce_clock_binary_new (plugin->time);
900
1063
  else if (plugin->mode == CLOCK_PLUGIN_MODE_DIGITAL)
901
 
    plugin->clock = xfce_clock_digital_new ();
 
1064
    plugin->clock = xfce_clock_digital_new (plugin->time);
902
1065
  else if (plugin->mode == CLOCK_PLUGIN_MODE_FUZZY)
903
 
    plugin->clock = xfce_clock_fuzzy_new ();
 
1066
    plugin->clock = xfce_clock_fuzzy_new (plugin->time);
904
1067
  else
905
 
    plugin->clock = xfce_clock_lcd_new ();
 
1068
    plugin->clock = xfce_clock_lcd_new (plugin->time);
 
1069
 
906
1070
 
907
1071
  if (plugin->rotate_vertically)
908
1072
    {
924
1088
                         xfce_panel_plugin_get_property_base (XFCE_PANEL_PLUGIN (plugin)),
925
1089
                         properties[plugin->mode], FALSE);
926
1090
 
927
 
  gtk_container_add (GTK_CONTAINER (plugin->frame), plugin->clock);
 
1091
  gtk_container_add (GTK_CONTAINER (plugin->button), plugin->clock);
928
1092
 
929
1093
  gtk_widget_show (plugin->clock);
930
1094
}
948
1112
clock_plugin_calendar_show_event (GtkWidget   *calendar_window,
949
1113
                                  ClockPlugin *plugin)
950
1114
{
951
 
  struct tm tm;
 
1115
  GDateTime *time;
952
1116
 
953
1117
  panel_return_if_fail (XFCE_IS_PANEL_PLUGIN (plugin));
954
1118
 
955
1119
  clock_plugin_reposition_calendar (plugin);
956
1120
 
957
 
  clock_plugin_get_localtime (&tm);
958
 
  gtk_calendar_select_month (GTK_CALENDAR (plugin->calendar), tm.tm_mon,
959
 
                             1900 + tm.tm_year);
960
 
  gtk_calendar_select_day (GTK_CALENDAR (plugin->calendar), tm.tm_mday);
961
 
}
962
 
 
963
 
 
964
 
 
965
 
static void
966
 
clock_plugin_popup_calendar (ClockPlugin *plugin)
967
 
{
968
 
  GtkWidget *calendar_frame;
969
 
 
 
1121
  time = clock_time_get_time (plugin->time);
 
1122
  gtk_calendar_select_month (GTK_CALENDAR (plugin->calendar), g_date_time_get_month (time) - 1,
 
1123
                             g_date_time_get_year (time));
 
1124
  gtk_calendar_select_day (GTK_CALENDAR (plugin->calendar), g_date_time_get_day_of_month (time));
 
1125
  g_date_time_unref (time);
 
1126
}
 
1127
 
 
1128
 
 
1129
 
 
1130
static void
 
1131
clock_plugin_pointer_ungrab (ClockPlugin *plugin,
 
1132
                             GtkWidget   *widget)
 
1133
{
 
1134
  if (plugin->grab_pointer == GDK_GRAB_SUCCESS)
 
1135
    gdk_pointer_ungrab (GDK_CURRENT_TIME);
 
1136
  if (plugin->grab_keyboard == GDK_GRAB_SUCCESS)
 
1137
    gdk_keyboard_ungrab (GDK_CURRENT_TIME);
 
1138
}
 
1139
 
 
1140
 
 
1141
 
 
1142
static gboolean
 
1143
clock_plugin_pointer_grab (ClockPlugin *plugin,
 
1144
                           GtkWidget   *widget,
 
1145
                           gboolean     keep)
 
1146
{
 
1147
  GdkWindow     *window;
 
1148
  gboolean       grab_succeed = FALSE;
 
1149
  guint          i;
 
1150
  GdkEventMask   pointer_mask = GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
 
1151
                                | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK
 
1152
                                | GDK_POINTER_MOTION_MASK;
 
1153
 
 
1154
  window = widget->window;
 
1155
 
 
1156
  /* don't try to get the grab for longer then 1/4 second */
 
1157
  for (i = 0; i < (G_USEC_PER_SEC / 100 / 4); i++)
 
1158
    {
 
1159
      plugin->grab_keyboard = gdk_keyboard_grab (window, TRUE, GDK_CURRENT_TIME);
 
1160
      if (plugin->grab_keyboard == GDK_GRAB_SUCCESS)
 
1161
        {
 
1162
          plugin->grab_pointer = gdk_pointer_grab (window, TRUE, pointer_mask,
 
1163
                                                   NULL, NULL, GDK_CURRENT_TIME);
 
1164
          if (plugin->grab_pointer == GDK_GRAB_SUCCESS)
 
1165
            {
 
1166
              grab_succeed = TRUE;
 
1167
              break;
 
1168
            }
 
1169
        }
 
1170
 
 
1171
      g_usleep (100);
 
1172
    }
 
1173
 
 
1174
  /* release the grab */
 
1175
  if (!keep)
 
1176
    clock_plugin_pointer_ungrab (plugin, widget);
 
1177
 
 
1178
  if (!grab_succeed)
 
1179
    {
 
1180
      clock_plugin_pointer_ungrab (plugin, widget);
 
1181
      g_printerr (PACKAGE_NAME ": Unable to get keyboard and mouse "
 
1182
                  "grab. Popup failed.\n");
 
1183
    }
 
1184
 
 
1185
  return grab_succeed;
 
1186
}
 
1187
 
 
1188
 
 
1189
 
 
1190
static gboolean
 
1191
clock_plugin_calendar_pointed (GtkWidget *calendar_window,
 
1192
                               gdouble    x_root,
 
1193
                               gdouble    y_root)
 
1194
{
 
1195
  gint          window_x, window_y;
 
1196
 
 
1197
  if (gtk_widget_get_mapped (calendar_window))
 
1198
    {
 
1199
      gdk_window_get_position (calendar_window->window, &window_x, &window_y);
 
1200
 
 
1201
      if (x_root >= window_x && x_root < window_x + calendar_window->allocation.width &&
 
1202
          y_root >= window_y && y_root < window_y + calendar_window->allocation.height)
 
1203
        return TRUE;
 
1204
    }
 
1205
 
 
1206
  return FALSE;
 
1207
}
 
1208
 
 
1209
 
 
1210
 
 
1211
static gboolean
 
1212
clock_plugin_calendar_button_press_event (GtkWidget      *calendar_window,
 
1213
                                          GdkEventButton *event,
 
1214
                                          ClockPlugin    *plugin)
 
1215
{
 
1216
  if (event->type == GDK_BUTTON_PRESS &&
 
1217
      !clock_plugin_calendar_pointed (calendar_window, event->x_root, event->y_root))
 
1218
    {
 
1219
      clock_plugin_hide_calendar (plugin);
 
1220
      return TRUE;
 
1221
    }
 
1222
 
 
1223
  return FALSE;
 
1224
}
 
1225
 
 
1226
 
 
1227
 
 
1228
static gboolean
 
1229
clock_plugin_calendar_key_press_event (GtkWidget      *calendar_window,
 
1230
                                       GdkEventKey    *event,
 
1231
                                       ClockPlugin    *plugin)
 
1232
{
 
1233
  if (event->type == GDK_KEY_PRESS && event->keyval == GDK_KEY_Escape)
 
1234
    {
 
1235
      clock_plugin_hide_calendar (plugin);
 
1236
      return TRUE;
 
1237
    }
 
1238
 
 
1239
  return FALSE;
 
1240
}
 
1241
 
 
1242
 
 
1243
 
 
1244
static void
 
1245
clock_plugin_popup_calendar (ClockPlugin *plugin,
 
1246
                             gboolean     modal)
 
1247
{
970
1248
  if (plugin->calendar_window == NULL)
971
1249
    {
972
1250
      plugin->calendar_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
979
1257
      gtk_window_set_keep_above (GTK_WINDOW (plugin->calendar_window), TRUE);
980
1258
      gtk_window_stick (GTK_WINDOW (plugin->calendar_window));
981
1259
 
982
 
      calendar_frame = gtk_frame_new (NULL);
983
 
      gtk_frame_set_shadow_type (GTK_FRAME (calendar_frame), GTK_SHADOW_OUT);
984
 
      gtk_container_add (GTK_CONTAINER (plugin->calendar_window), calendar_frame);
985
 
      gtk_widget_show (calendar_frame);
986
 
 
987
1260
      plugin->calendar = gtk_calendar_new ();
988
1261
      gtk_calendar_set_display_options (GTK_CALENDAR (plugin->calendar),
989
1262
                                        GTK_CALENDAR_SHOW_HEADING
991
1264
                                        | GTK_CALENDAR_SHOW_WEEK_NUMBERS);
992
1265
      g_signal_connect (G_OBJECT (plugin->calendar_window), "show",
993
1266
                        G_CALLBACK (clock_plugin_calendar_show_event), plugin);
994
 
      gtk_container_add (GTK_CONTAINER (calendar_frame), plugin->calendar);
 
1267
      g_signal_connect (G_OBJECT (plugin->calendar_window), "button-press-event",
 
1268
                        G_CALLBACK (clock_plugin_calendar_button_press_event), plugin);
 
1269
      g_signal_connect (G_OBJECT (plugin->calendar_window), "key-press-event",
 
1270
                        G_CALLBACK (clock_plugin_calendar_key_press_event), plugin);
 
1271
      gtk_container_add (GTK_CONTAINER (plugin->calendar_window), plugin->calendar);
995
1272
      gtk_widget_show (plugin->calendar);
996
1273
    }
997
1274
 
 
1275
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), TRUE);
998
1276
  gtk_widget_show (GTK_WIDGET (plugin->calendar_window));
999
1277
  xfce_panel_plugin_block_autohide (XFCE_PANEL_PLUGIN (plugin), TRUE);
 
1278
  if (modal)
 
1279
    clock_plugin_pointer_grab (plugin, GTK_WIDGET (plugin->calendar_window), TRUE);
1000
1280
}
1001
1281
 
1002
1282
 
1004
1284
static void
1005
1285
clock_plugin_hide_calendar (ClockPlugin *plugin)
1006
1286
{
1007
 
  panel_return_if_fail (plugin->calendar_window != NULL);
 
1287
  /* calendar_window is initialized on the first call to clock_plugin_popup_calendar () */
 
1288
  if (plugin->calendar_window == NULL)
 
1289
    return;
1008
1290
 
 
1291
  clock_plugin_pointer_ungrab (plugin, GTK_WIDGET (plugin->calendar_window));
1009
1292
  gtk_widget_hide (GTK_WIDGET (plugin->calendar_window));
1010
1293
  xfce_panel_plugin_block_autohide (XFCE_PANEL_PLUGIN (plugin), FALSE);
 
1294
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (plugin->button), FALSE);
1011
1295
}
1012
1296
 
1013
1297
 
1017
1301
{
1018
1302
  ClockPlugin *plugin = XFCE_CLOCK_PLUGIN (user_data);
1019
1303
  gchar       *string;
1020
 
  struct tm    tm;
1021
 
 
1022
 
  /* get the local time */
1023
 
  clock_plugin_get_localtime (&tm);
1024
1304
 
1025
1305
  /* set the tooltip */
1026
 
  string = clock_plugin_strdup_strftime (plugin->tooltip_format, &tm);
 
1306
  string = clock_time_strdup_strftime (plugin->time, plugin->tooltip_format);
1027
1307
  gtk_widget_set_tooltip_markup (GTK_WIDGET (plugin), string);
1028
1308
  g_free (string);
1029
1309
 
1033
1313
  /* keep the timeout running */
1034
1314
  return TRUE;
1035
1315
}
1036
 
 
1037
 
 
1038
 
 
1039
 
static gboolean
1040
 
clock_plugin_timeout_running (gpointer user_data)
1041
 
{
1042
 
  ClockPluginTimeout *timeout = user_data;
1043
 
  gboolean            result;
1044
 
  struct tm           tm;
1045
 
 
1046
 
  GDK_THREADS_ENTER ();
1047
 
  result = (timeout->function) (timeout->data);
1048
 
  GDK_THREADS_LEAVE ();
1049
 
 
1050
 
  /* check if the timeout still runs in time if updating once a minute */
1051
 
  if (result && timeout->interval == CLOCK_INTERVAL_MINUTE)
1052
 
    {
1053
 
      /* sync again when we don't run on time */
1054
 
      clock_plugin_get_localtime (&tm);
1055
 
      timeout->restart = tm.tm_sec != 0;
1056
 
    }
1057
 
 
1058
 
  return result && !timeout->restart;
1059
 
}
1060
 
 
1061
 
 
1062
 
 
1063
 
static void
1064
 
clock_plugin_timeout_destroyed (gpointer user_data)
1065
 
{
1066
 
  ClockPluginTimeout *timeout = user_data;
1067
 
 
1068
 
  timeout->timeout_id = 0;
1069
 
 
1070
 
  if (G_UNLIKELY (timeout->restart))
1071
 
    clock_plugin_timeout_set_interval (timeout, timeout->interval);
1072
 
}
1073
 
 
1074
 
 
1075
 
 
1076
 
static gboolean
1077
 
clock_plugin_timeout_sync (gpointer user_data)
1078
 
{
1079
 
  ClockPluginTimeout *timeout = user_data;
1080
 
 
1081
 
  /* run the user function */
1082
 
  if ((timeout->function) (timeout->data))
1083
 
    {
1084
 
      /* start the real timeout */
1085
 
      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, timeout->interval,
1086
 
                                                        clock_plugin_timeout_running, timeout,
1087
 
                                                        clock_plugin_timeout_destroyed);
1088
 
    }
1089
 
  else
1090
 
    {
1091
 
      timeout->timeout_id = 0;
1092
 
    }
1093
 
 
1094
 
  /* stop the sync timeout */
1095
 
  return FALSE;
1096
 
}
1097
 
 
1098
 
 
1099
 
 
1100
 
ClockPluginTimeout *
1101
 
clock_plugin_timeout_new (guint       interval,
1102
 
                          GSourceFunc function,
1103
 
                          gpointer    data)
1104
 
{
1105
 
  ClockPluginTimeout *timeout;
1106
 
 
1107
 
  panel_return_val_if_fail (interval > 0, NULL);
1108
 
  panel_return_val_if_fail (function != NULL, NULL);
1109
 
 
1110
 
  timeout = g_slice_new0 (ClockPluginTimeout);
1111
 
  timeout->interval = 0;
1112
 
  timeout->function = function;
1113
 
  timeout->data = data;
1114
 
  timeout->timeout_id = 0;
1115
 
  timeout->restart = FALSE;
1116
 
 
1117
 
  clock_plugin_timeout_set_interval (timeout, interval);
1118
 
 
1119
 
  return timeout;
1120
 
}
1121
 
 
1122
 
 
1123
 
 
1124
 
void
1125
 
clock_plugin_timeout_set_interval (ClockPluginTimeout *timeout,
1126
 
                                   guint               interval)
1127
 
{
1128
 
  struct tm tm;
1129
 
  guint     next_interval;
1130
 
  gboolean  restart = timeout->restart;
1131
 
 
1132
 
  panel_return_if_fail (timeout != NULL);
1133
 
  panel_return_if_fail (interval > 0);
1134
 
 
1135
 
  /* leave if nothing changed and we're not restarting */
1136
 
  if (!restart && timeout->interval == interval)
1137
 
    return;
1138
 
  timeout->interval = interval;
1139
 
  timeout->restart = FALSE;
1140
 
 
1141
 
  /* stop running timeout */
1142
 
  if (G_LIKELY (timeout->timeout_id != 0))
1143
 
    g_source_remove (timeout->timeout_id);
1144
 
  timeout->timeout_id = 0;
1145
 
 
1146
 
  /* run function when not restarting, leave if it returns false */
1147
 
  if (!restart && !(timeout->function) (timeout->data))
1148
 
    return;
1149
 
 
1150
 
  /* get the seconds to the next internal */
1151
 
  if (interval == CLOCK_INTERVAL_MINUTE)
1152
 
    {
1153
 
      clock_plugin_get_localtime (&tm);
1154
 
      next_interval = 60 - tm.tm_sec;
1155
 
    }
1156
 
  else
1157
 
    {
1158
 
      next_interval = 0;
1159
 
    }
1160
 
 
1161
 
  if (next_interval > 0)
1162
 
    {
1163
 
      /* start the sync timeout */
1164
 
      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, next_interval,
1165
 
                                                        clock_plugin_timeout_sync,
1166
 
                                                        timeout, NULL);
1167
 
    }
1168
 
  else
1169
 
    {
1170
 
      /* directly start running the normal timeout */
1171
 
      timeout->timeout_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, interval,
1172
 
                                                        clock_plugin_timeout_running, timeout,
1173
 
                                                        clock_plugin_timeout_destroyed);
1174
 
    }
1175
 
}
1176
 
 
1177
 
 
1178
 
 
1179
 
void
1180
 
clock_plugin_timeout_free (ClockPluginTimeout *timeout)
1181
 
{
1182
 
  panel_return_if_fail (timeout != NULL);
1183
 
 
1184
 
  timeout->restart = FALSE;
1185
 
  if (G_LIKELY (timeout->timeout_id != 0))
1186
 
    g_source_remove (timeout->timeout_id);
1187
 
  g_slice_free (ClockPluginTimeout, timeout);
1188
 
}
1189
 
 
1190
 
 
1191
 
 
1192
 
void
1193
 
clock_plugin_get_localtime (struct tm *tm)
1194
 
{
1195
 
  time_t now = time (NULL);
1196
 
 
1197
 
#ifndef HAVE_LOCALTIME_R
1198
 
  struct tm *tmbuf;
1199
 
 
1200
 
  tmbuf = localtime (&now);
1201
 
  *tm = *tmbuf;
1202
 
#else
1203
 
  localtime_r (&now, tm);
1204
 
#endif
1205
 
}
1206
 
 
1207
 
 
1208
 
 
1209
 
gchar *
1210
 
clock_plugin_strdup_strftime (const gchar     *format,
1211
 
                              const struct tm *tm)
1212
 
{
1213
 
  gchar *converted, *result;
1214
 
  gsize  length;
1215
 
  gchar  buffer[1024];
1216
 
 
1217
 
  /* leave when format is null */
1218
 
  if (G_UNLIKELY (exo_str_is_empty (format)))
1219
 
    return NULL;
1220
 
 
1221
 
  /* convert to locale, because that's what strftime uses */
1222
 
  converted = g_locale_from_utf8 (format, -1, NULL, NULL, NULL);
1223
 
  if (G_UNLIKELY (converted == NULL))
1224
 
    return NULL;
1225
 
 
1226
 
  /* parse the time string */
1227
 
  length = strftime (buffer, sizeof (buffer), converted, tm);
1228
 
  if (G_UNLIKELY (length == 0))
1229
 
    buffer[0] = '\0';
1230
 
 
1231
 
  /* convert the string back to utf-8 */
1232
 
  result = g_locale_to_utf8 (buffer, -1, NULL, NULL, NULL);
1233
 
 
1234
 
  /* cleanup */
1235
 
  g_free (converted);
1236
 
 
1237
 
  return result;
1238
 
}
1239
 
 
1240
 
 
1241
 
 
1242
 
guint
1243
 
clock_plugin_interval_from_format (const gchar *format)
1244
 
{
1245
 
  const gchar *p;
1246
 
 
1247
 
  if (G_UNLIKELY (exo_str_is_empty (format)))
1248
 
      return CLOCK_INTERVAL_MINUTE;
1249
 
 
1250
 
  for (p = format; *p != '\0'; ++p)
1251
 
    {
1252
 
      if (p[0] == '%' && p[1] != '\0')
1253
 
        {
1254
 
          switch (*++p)
1255
 
            {
1256
 
            case 'c':
1257
 
            case 'N':
1258
 
            case 'r':
1259
 
            case 's':
1260
 
            case 'S':
1261
 
            case 'T':
1262
 
            case 'X':
1263
 
              return CLOCK_INTERVAL_SECOND;
1264
 
            }
1265
 
        }
1266
 
    }
1267
 
 
1268
 
  return CLOCK_INTERVAL_MINUTE;
1269
 
}