~noskcaj/ubuntu/saucy/xfce4-power-manager/systemd

« back to all changes in this revision

Viewing changes to .pc/03_fix-insert-battery.patch/src/xfpm-battery.c

  • Committer: Package Import Robot
  • Author(s): Jackson Doak
  • Date: 2013-08-13 06:56:35 UTC
  • mfrom: (6.2.13 sid)
  • Revision ID: package-import@ubuntu.com-20130813065635-gu2mh06aw8n2id6w
Tags: 1.2.0-2ubuntu1
* Merged from debian unstable. Remaining changes:
  - 06_fix-suspend-auth-check.patch: added, correctly check for suspend
    permissions before disabling the corresponding drop-down menu item.
    lp #929537
  - 08_show_preferences_lxde.patch: Hide settings menu only on desktop
    environment which have another power manager.
  - xubuntu_fix-status-icon-other-devices.patch: fix broken status icons
    for other devices (phone, wireless kbd, mouse, etc.).
  - Switch to using logind for session tracking. Depend on systemd-services
  instead of consolekit recommends, and add libsystemd-login-dev build
  dependency.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * * Copyright (C) 2009-2011 Ali <aliov@xfce.org>
 
3
 *
 
4
 * Licensed under the GNU General Public License Version 2
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <string.h>
 
28
 
 
29
#include <gtk/gtk.h>
 
30
 
 
31
#include <libxfce4util/libxfce4util.h>
 
32
 
 
33
#include "xfpm-battery.h"
 
34
#include "xfpm-dbus.h"
 
35
#include "xfpm-icons.h"
 
36
#include "xfpm-xfconf.h"
 
37
#include "xfpm-notify.h"
 
38
#include "xfpm-config.h"
 
39
#include "xfpm-button.h"
 
40
#include "xfpm-enum-glib.h"
 
41
#include "xfpm-enum-types.h"
 
42
#include "xfpm-debug.h"
 
43
#include "xfpm-power-common.h"
 
44
#include "xfpm-common.h"
 
45
 
 
46
static void xfpm_battery_finalize   (GObject *object);
 
47
 
 
48
#define XFPM_BATTERY_GET_PRIVATE(o) \
 
49
(G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_BATTERY, XfpmBatteryPrivate))
 
50
 
 
51
struct XfpmBatteryPrivate
 
52
{
 
53
    XfpmXfconf             *conf;
 
54
    XfpmNotify             *notify;
 
55
    XfpmButton             *button;
 
56
    DBusGProxy             *proxy;
 
57
    DBusGProxy             *proxy_prop;
 
58
    
 
59
    gchar                  *icon_prefix;
 
60
    
 
61
    XfpmBatteryCharge       charge;
 
62
    XfpmDeviceState         state;
 
63
    XfpmDeviceType          type;
 
64
    gboolean                ac_online;
 
65
    gboolean                present;
 
66
    guint                   percentage;
 
67
    gint64                  time_to_full;
 
68
    gint64                  time_to_empty;
 
69
 
 
70
    const gchar            *battery_name;
 
71
    
 
72
    gulong                  sig;
 
73
    gulong                  sig_bt;
 
74
    
 
75
    guint                   notify_idle;
 
76
};
 
77
 
 
78
enum
 
79
{
 
80
    PROP_0,
 
81
    PROP_AC_ONLINE,
 
82
    PROP_CHARGE_STATUS,
 
83
    PROP_DEVICE_TYPE
 
84
};
 
85
    
 
86
enum
 
87
{
 
88
    BATTERY_CHARGE_CHANGED,
 
89
    LAST_SIGNAL
 
90
};
 
91
 
 
92
static guint signals [LAST_SIGNAL] = { 0 };
 
93
 
 
94
G_DEFINE_TYPE (XfpmBattery, xfpm_battery, GTK_TYPE_STATUS_ICON)
 
95
 
 
96
static const gchar * G_GNUC_CONST
 
97
xfpm_battery_get_icon_index (XfpmDeviceType type, guint percent)
 
98
{
 
99
    if (percent < 10) 
 
100
    {
 
101
        return "000";
 
102
    } 
 
103
    else if (percent < 30) 
 
104
    {
 
105
        return ( (type == XFPM_DEVICE_TYPE_BATTERY || type == XFPM_DEVICE_TYPE_UPS) ? "020" : "030");
 
106
    } 
 
107
    else if (percent < 50) 
 
108
    {
 
109
        return ( (type == XFPM_DEVICE_TYPE_BATTERY || type == XFPM_DEVICE_TYPE_UPS ) ? "040" : "030");
 
110
    } 
 
111
    else if (percent < 70) 
 
112
    {
 
113
        return "060";
 
114
    } 
 
115
    else if (percent < 90) 
 
116
    {
 
117
        return ((type == XFPM_DEVICE_TYPE_BATTERY || type == XFPM_DEVICE_TYPE_UPS) ? "080" : "060");
 
118
    }
 
119
    
 
120
    return "100";
 
121
}
 
122
 
 
123
static void
 
124
xfpm_battery_refresh_visible (XfpmBattery *battery)
 
125
{
 
126
    XfpmShowIcon show_icon;
 
127
    gboolean visible = TRUE;
 
128
    
 
129
    g_object_get (G_OBJECT (battery->priv->conf),
 
130
                  SHOW_TRAY_ICON_CFG, &show_icon,
 
131
                  NULL);
 
132
                  
 
133
    if ( show_icon == SHOW_ICON_ALWAYS )
 
134
        visible = TRUE;
 
135
    else if ( show_icon == NEVER_SHOW_ICON )
 
136
        visible = FALSE;
 
137
    else if ( show_icon == SHOW_ICON_WHEN_BATTERY_PRESENT )
 
138
    {
 
139
        if ( battery->priv->present )
 
140
            visible = TRUE;
 
141
        else visible = FALSE;
 
142
    }
 
143
    else if ( show_icon == SHOW_ICON_WHEN_BATTERY_CHARGING_DISCHARGING )
 
144
    {
 
145
        if ( battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
 
146
            visible = FALSE;
 
147
        else visible = TRUE;
 
148
    }
 
149
 
 
150
    XFPM_DEBUG_ENUM (show_icon, XFPM_TYPE_SHOW_ICON, "visible=%s", xfpm_bool_to_string (visible));
 
151
                          
 
152
    gtk_status_icon_set_visible (GTK_STATUS_ICON (battery), visible);
 
153
}
 
154
 
 
155
 
 
156
/*
 
157
 * Taken from gpm
 
158
 */
 
159
static gchar *
 
160
xfpm_battery_get_time_string (guint seconds)
 
161
{
 
162
    char* timestring = NULL;
 
163
    gint  hours;
 
164
    gint  minutes;
 
165
 
 
166
    /* Add 0.5 to do rounding */
 
167
    minutes = (int) ( ( seconds / 60.0 ) + 0.5 );
 
168
 
 
169
    if (minutes == 0) 
 
170
    {
 
171
        timestring = g_strdup (_("Unknown time"));
 
172
        return timestring;
 
173
    }
 
174
 
 
175
    if (minutes < 60) 
 
176
    {
 
177
        timestring = g_strdup_printf (ngettext ("%i minute",
 
178
                                      "%i minutes",
 
179
                                      minutes), minutes);
 
180
        return timestring;
 
181
    }
 
182
 
 
183
    hours = minutes / 60;
 
184
    minutes = minutes % 60;
 
185
 
 
186
    if (minutes == 0)
 
187
        timestring = g_strdup_printf (ngettext (
 
188
                            "%i hour",
 
189
                            "%i hours",
 
190
                            hours), hours);
 
191
    else
 
192
        /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
 
193
         * Swap order with "%2$s %2$i %1$s %1$i if needed */
 
194
        timestring = g_strdup_printf (_("%i %s %i %s"),
 
195
                            hours, ngettext ("hour", "hours", hours),
 
196
                            minutes, ngettext ("minute", "minutes", minutes));
 
197
    return timestring;
 
198
}
 
199
 
 
200
static gchar *
 
201
xfpm_battery_get_message_from_battery_state (XfpmBattery *battery)
 
202
{
 
203
    gchar *msg  = NULL;
 
204
    
 
205
    
 
206
    if (battery->priv->type == XFPM_DEVICE_TYPE_BATTERY || battery->priv->type == XFPM_DEVICE_TYPE_UPS)
 
207
    {
 
208
        switch (battery->priv->state)
 
209
        {
 
210
            case XFPM_DEVICE_STATE_FULLY_CHARGED:
 
211
                msg = g_strdup_printf (_("Your %s is fully charged"), battery->priv->battery_name);
 
212
                break;
 
213
            case XFPM_DEVICE_STATE_CHARGING:
 
214
                msg = g_strdup_printf (_("Your %s is charging"), battery->priv->battery_name);
 
215
                
 
216
                if ( battery->priv->time_to_full != 0 )
 
217
                {
 
218
                    gchar *tmp, *est_time_str;
 
219
                    tmp = g_strdup (msg);
 
220
                    g_free (msg);
 
221
                    
 
222
                    est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_full);
 
223
                    
 
224
                    msg = g_strdup_printf (_("%s (%i%%)\n%s until is fully charged."), tmp, battery->priv->percentage, est_time_str);
 
225
                    g_free (est_time_str);
 
226
                    g_free (tmp);
 
227
                }
 
228
 
 
229
                break;
 
230
            case XFPM_DEVICE_STATE_DISCHARGING:
 
231
                if (battery->priv->ac_online)
 
232
                    msg =  g_strdup_printf (_("Your %s is discharging"), battery->priv->battery_name);
 
233
                else
 
234
                    msg =  g_strdup_printf (_("System is running on %s power"), battery->priv->battery_name);
 
235
                    
 
236
                    if ( battery->priv->time_to_empty != 0 )
 
237
                    {
 
238
                        gchar *tmp, *est_time_str;
 
239
                        tmp = g_strdup (msg);
 
240
                        g_free (msg);
 
241
                        
 
242
                        est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_empty);
 
243
                        
 
244
                        msg = g_strdup_printf (_("%s (%i%%)\nEstimated time left is %s."), tmp, battery->priv->percentage, est_time_str);
 
245
                        g_free (tmp);
 
246
                        g_free (est_time_str);
 
247
                    }
 
248
                break;
 
249
            case XFPM_DEVICE_STATE_EMPTY:
 
250
                msg = g_strdup_printf (_("Your %s is empty"), battery->priv->battery_name);
 
251
                break;
 
252
            default:
 
253
                break;
 
254
        }
 
255
        
 
256
    }
 
257
    else if (battery->priv->type >= XFPM_DEVICE_TYPE_MONITOR)
 
258
    {
 
259
        switch (battery->priv->state)
 
260
        {
 
261
            case XFPM_DEVICE_STATE_FULLY_CHARGED:
 
262
                msg = g_strdup_printf (_("Your %s is fully charged"), battery->priv->battery_name);
 
263
                break;
 
264
            case XFPM_DEVICE_STATE_CHARGING:
 
265
                msg = g_strdup_printf (_("Your %s is charging"), battery->priv->battery_name);
 
266
                break;
 
267
            case XFPM_DEVICE_STATE_DISCHARGING:
 
268
                msg =  g_strdup_printf (_("Your %s is discharging"), battery->priv->battery_name);
 
269
                break;
 
270
            case XFPM_DEVICE_STATE_EMPTY:
 
271
                msg = g_strdup_printf (_("Your %s is empty"), battery->priv->battery_name);
 
272
                break;
 
273
            default:
 
274
                break;
 
275
        }
 
276
    }
 
277
    
 
278
    return msg;
 
279
}
 
280
 
 
281
static void
 
282
xfpm_battery_refresh_icon (XfpmBattery *battery)
 
283
{
 
284
    gchar icon_name[128];
 
285
    
 
286
    XFPM_DEBUG ("Battery state %d", battery->priv->state);
 
287
    
 
288
    if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY || 
 
289
         battery->priv->type == XFPM_DEVICE_TYPE_UPS )
 
290
    {
 
291
        if (!battery->priv->present)
 
292
        {
 
293
            g_snprintf (icon_name, 128, "%s%s", battery->priv->icon_prefix, "missing");
 
294
        }
 
295
        else if (battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
 
296
        {
 
297
            g_snprintf (icon_name, 128, "%s%s", battery->priv->icon_prefix, battery->priv->ac_online ? "charged" : "100");
 
298
        }
 
299
        else if ( battery->priv->state == XFPM_DEVICE_STATE_CHARGING || 
 
300
                  battery->priv->state == XFPM_DEVICE_STATE_PENDING_CHARGING)
 
301
        {
 
302
            g_snprintf (icon_name, 128, "%s%s-%s", 
 
303
                        battery->priv->icon_prefix, 
 
304
                        xfpm_battery_get_icon_index (battery->priv->type, battery->priv->percentage),
 
305
                        "charging");
 
306
        }
 
307
        else if ( battery->priv->state == XFPM_DEVICE_STATE_DISCHARGING ||
 
308
                  battery->priv->state == XFPM_DEVICE_STATE_PENDING_DISCHARGING)
 
309
        {
 
310
            g_snprintf (icon_name, 128, "%s%s", 
 
311
                        battery->priv->icon_prefix, 
 
312
                        xfpm_battery_get_icon_index (battery->priv->type, battery->priv->percentage));
 
313
        }
 
314
        else if ( battery->priv->state == XFPM_DEVICE_STATE_EMPTY)
 
315
        {
 
316
            g_snprintf (icon_name, 128, "%s%s", battery->priv->icon_prefix, battery->priv->ac_online ? "000-charging" : "000");
 
317
        }
 
318
    }
 
319
    else
 
320
    {
 
321
        if ( !battery->priv->present || battery->priv->state == XFPM_DEVICE_STATE_EMPTY )
 
322
        {
 
323
            g_snprintf (icon_name, 128, "%s-000", battery->priv->icon_prefix);
 
324
        }
 
325
        else if ( battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
 
326
        {
 
327
            g_snprintf (icon_name, 128, "%s-100", battery->priv->icon_prefix);
 
328
        }
 
329
        else if ( battery->priv->state == XFPM_DEVICE_STATE_DISCHARGING )
 
330
        {
 
331
            g_snprintf (icon_name, 128, "%s-%s", 
 
332
                        battery->priv->icon_prefix, 
 
333
                        xfpm_battery_get_icon_index (battery->priv->type, battery->priv->percentage));
 
334
        }
 
335
    }
 
336
    
 
337
    gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (battery), icon_name);
 
338
}
 
339
 
 
340
static void
 
341
xfpm_battery_notify (XfpmBattery *battery)
 
342
{
 
343
    gchar *message = NULL;
 
344
    
 
345
    message = xfpm_battery_get_message_from_battery_state (battery);
 
346
    
 
347
    if ( !message )
 
348
        return;
 
349
        
 
350
    xfpm_notify_show_notification (battery->priv->notify, 
 
351
                                   _("Power Manager"), 
 
352
                                   message, 
 
353
                                   gtk_status_icon_get_icon_name (GTK_STATUS_ICON (battery)),
 
354
                                   8000,
 
355
                                   FALSE,
 
356
                                   XFPM_NOTIFY_NORMAL,
 
357
                                   GTK_STATUS_ICON (battery));
 
358
    
 
359
    g_free (message);
 
360
}
 
361
 
 
362
static gboolean
 
363
xfpm_battery_notify_idle (gpointer data)
 
364
{
 
365
    XfpmBattery *battery = XFPM_BATTERY (data);
 
366
    
 
367
    xfpm_battery_notify (battery);
 
368
    battery->priv->notify_idle = 0;
 
369
    
 
370
    return FALSE;
 
371
}
 
372
 
 
373
static void
 
374
xfpm_battery_notify_state (XfpmBattery *battery)
 
375
{
 
376
    gboolean notify;
 
377
    static gboolean starting_up = TRUE;
 
378
    
 
379
    if ( !gtk_status_icon_get_visible (GTK_STATUS_ICON (battery)) )
 
380
        return;
 
381
    
 
382
    if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY ||
 
383
         battery->priv->type == XFPM_DEVICE_TYPE_UPS )
 
384
    {
 
385
        if ( starting_up )
 
386
        {
 
387
            starting_up = FALSE;
 
388
            return;
 
389
        }
 
390
    
 
391
        g_object_get (G_OBJECT (battery->priv->conf),
 
392
                      GENERAL_NOTIFICATION_CFG, &notify,
 
393
                      NULL);
 
394
                      
 
395
        if ( notify )
 
396
        {
 
397
            if (battery->priv->notify_idle == 0)
 
398
                battery->priv->notify_idle = g_idle_add (xfpm_battery_notify_idle, battery);
 
399
        }
 
400
    }
 
401
}
 
402
 
 
403
/*
 
404
 * Refresh tooltip function for UPS and battery device only.
 
405
 */
 
406
static void
 
407
xfpm_battery_set_tooltip_primary (XfpmBattery *battery, GtkTooltip *tooltip)
 
408
{
 
409
    gchar *tip;
 
410
    gchar *est_time_str = NULL;
 
411
    gchar *power_status = NULL;
 
412
    
 
413
    power_status = g_strdup_printf (battery->priv->ac_online ? _("Adaptor is online") : _("System is running on battery power"));
 
414
    
 
415
    if ( battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
 
416
    {
 
417
        if ( battery->priv->time_to_empty > 0 )
 
418
        {
 
419
            est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_empty);
 
420
            tip = g_strdup_printf (_("%s\nYour %s is fully charged (%i%%).\nProvides %s runtime"), 
 
421
                                   power_status,
 
422
                                   battery->priv->battery_name, 
 
423
                                   battery->priv->percentage,
 
424
                                   est_time_str);
 
425
            g_free (est_time_str);
 
426
        }
 
427
        else
 
428
        {
 
429
            tip = g_strdup_printf (_("%s\nYour %s is fully charged (%i%%)."), 
 
430
                                   power_status,
 
431
                                   battery->priv->battery_name,
 
432
                                   battery->priv->percentage);
 
433
        }
 
434
    }
 
435
    else if ( battery->priv->state == XFPM_DEVICE_STATE_CHARGING )
 
436
    {
 
437
        if ( battery->priv->time_to_full != 0 )
 
438
        {
 
439
            est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_full);
 
440
            tip = g_strdup_printf (_("%s\nYour %s is charging (%i%%)\n%s until is fully charged."), 
 
441
                                   power_status,
 
442
                                   battery->priv->battery_name, 
 
443
                                   battery->priv->percentage, 
 
444
                                   est_time_str);
 
445
            g_free (est_time_str);
 
446
        }
 
447
        else
 
448
        {
 
449
            tip = g_strdup_printf (_("%s\nYour %s is charging (%i%%)."),
 
450
                                   power_status,
 
451
                                   battery->priv->battery_name,
 
452
                                   battery->priv->percentage);
 
453
        }
 
454
    }
 
455
    else if ( battery->priv->state == XFPM_DEVICE_STATE_DISCHARGING )
 
456
    {
 
457
        if ( battery->priv->time_to_empty != 0 )
 
458
        {
 
459
            est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_empty);
 
460
            tip = g_strdup_printf (_("%s\nYour %s is discharging (%i%%)\nEstimated time left is %s."), 
 
461
                                   power_status,
 
462
                                   battery->priv->battery_name, 
 
463
                                   battery->priv->percentage, 
 
464
                                   est_time_str);
 
465
            g_free (est_time_str);
 
466
        }
 
467
        else
 
468
        {
 
469
            tip = g_strdup_printf (_("%s\nYour %s is discharging (%i%%)."),
 
470
                                   power_status,
 
471
                                   battery->priv->battery_name,
 
472
                                   battery->priv->percentage);
 
473
        }
 
474
        
 
475
    }
 
476
    else if ( battery->priv->state == XFPM_DEVICE_STATE_PENDING_CHARGING )
 
477
    {
 
478
        tip = g_strdup_printf (_("%s\n%s waiting to discharge (%i%%)."), power_status, battery->priv->battery_name, battery->priv->percentage);
 
479
    }
 
480
    else if ( battery->priv->state == XFPM_DEVICE_STATE_PENDING_DISCHARGING )
 
481
    {
 
482
        tip = g_strdup_printf (_("%s\n%s waiting to charge (%i%%)."), power_status, battery->priv->battery_name, battery->priv->percentage);
 
483
    }
 
484
    else if ( battery->priv->state == XFPM_DEVICE_STATE_EMPTY )
 
485
    {
 
486
        tip = g_strdup_printf (_("%s\nYour %s is empty"), power_status, battery->priv->battery_name);
 
487
    }
 
488
    
 
489
    gtk_tooltip_set_text (tooltip, tip);
 
490
    g_free (power_status);
 
491
    g_free (tip);
 
492
}
 
493
 
 
494
static void
 
495
xfpm_battery_check_charge (XfpmBattery *battery)
 
496
{
 
497
    XfpmBatteryCharge charge;
 
498
    guint critical_level, low_level;
 
499
    
 
500
    g_object_get (G_OBJECT (battery->priv->conf),
 
501
                  CRITICAL_POWER_LEVEL, &critical_level,
 
502
                  NULL);
 
503
                  
 
504
    low_level = critical_level + 10;
 
505
    
 
506
    if ( battery->priv->percentage > low_level )
 
507
        charge = XFPM_BATTERY_CHARGE_OK;
 
508
    else if ( battery->priv->percentage <= low_level && battery->priv->percentage > critical_level )
 
509
        charge = XFPM_BATTERY_CHARGE_LOW;
 
510
    else if ( battery->priv->percentage <= critical_level )
 
511
        charge = XFPM_BATTERY_CHARGE_CRITICAL;
 
512
        
 
513
    if ( charge != battery->priv->charge)
 
514
    {
 
515
        battery->priv->charge = charge;
 
516
        /*
 
517
         * only emit signal when when battery charge changes from ok->low->critical
 
518
         * and not the other way round.
 
519
         */
 
520
        if ( battery->priv->charge != XFPM_BATTERY_CHARGE_CRITICAL || charge != XFPM_BATTERY_CHARGE_LOW )
 
521
            g_signal_emit (G_OBJECT (battery), signals [BATTERY_CHARGE_CHANGED], 0);
 
522
    }
 
523
}
 
524
 
 
525
static void
 
526
xfpm_battery_refresh (XfpmBattery *battery, GHashTable *props)
 
527
{
 
528
    GValue *value;
 
529
    guint state;
 
530
    
 
531
    value = g_hash_table_lookup (props, "IsPresent");
 
532
    
 
533
    if ( value == NULL )
 
534
    {
 
535
        g_warning ("No 'IsPresent' property found");
 
536
        goto out;
 
537
    }
 
538
    
 
539
    battery->priv->present = g_value_get_boolean (value);
 
540
    
 
541
    value = g_hash_table_lookup (props, "State");
 
542
    
 
543
    if ( value == NULL )
 
544
    {
 
545
        g_warning ("No 'State' property found");
 
546
    }
 
547
    
 
548
    state = g_value_get_uint (value);
 
549
    if ( state != battery->priv->state )
 
550
    {
 
551
        battery->priv->state = state;
 
552
        xfpm_battery_refresh_visible (battery);
 
553
        xfpm_battery_notify_state (battery);
 
554
    }
 
555
    
 
556
    value = g_hash_table_lookup (props, "Percentage");
 
557
    
 
558
    if ( value == NULL )
 
559
    {
 
560
        g_warning ("No 'Percentage' property found on battery device");
 
561
        goto out;
 
562
    }
 
563
    
 
564
    battery->priv->percentage = (guint) g_value_get_double (value);
 
565
    
 
566
    xfpm_battery_check_charge (battery);
 
567
    
 
568
    xfpm_battery_refresh_icon (battery);
 
569
    
 
570
    if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY ||
 
571
         battery->priv->type == XFPM_DEVICE_TYPE_UPS )
 
572
    {
 
573
        value = g_hash_table_lookup (props, "TimeToEmpty");
 
574
        
 
575
        if ( value == NULL )
 
576
        {
 
577
            g_warning ("No 'TimeToEmpty' property found on battery device");
 
578
            goto out;
 
579
        }
 
580
        
 
581
        battery->priv->time_to_empty = g_value_get_int64 (value);
 
582
        
 
583
        value = g_hash_table_lookup (props, "TimeToFull");
 
584
        
 
585
        if ( value == NULL )
 
586
        {
 
587
            g_warning ("No 'TimeToFull' property found on battery device");
 
588
            goto out;
 
589
        }
 
590
        
 
591
        battery->priv->time_to_full = g_value_get_int64 (value);
 
592
    }
 
593
    
 
594
    out:
 
595
        g_hash_table_destroy (props);
 
596
}
 
597
 
 
598
static void
 
599
xfpm_battery_button_pressed_cb (XfpmButton *button, XfpmButtonKey type, XfpmBattery *battery)
 
600
{
 
601
    if (type == BUTTON_BATTERY)
 
602
        xfpm_battery_notify (battery);
 
603
}
 
604
 
 
605
static void
 
606
xfpm_battery_changed_cb (DBusGProxy *proxy, XfpmBattery *battery)
 
607
{
 
608
    GHashTable *props;
 
609
    
 
610
    props = xfpm_power_get_interface_properties (battery->priv->proxy_prop, 
 
611
                                                 UPOWER_IFACE_DEVICE);
 
612
    
 
613
    if ( props )
 
614
        xfpm_battery_refresh (battery, props);
 
615
}
 
616
 
 
617
static gboolean
 
618
xfpm_battery_query_tooltip (GtkStatusIcon *icon, 
 
619
                            gint x,
 
620
                            gint y,
 
621
                            gboolean keyboard_mode,
 
622
                            GtkTooltip *tooltip)
 
623
{
 
624
    XfpmBattery *battery;
 
625
    
 
626
    battery = XFPM_BATTERY (icon);
 
627
 
 
628
    if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY ||
 
629
         battery->priv->type == XFPM_DEVICE_TYPE_UPS )
 
630
    {
 
631
        xfpm_battery_set_tooltip_primary (battery, tooltip);
 
632
        return TRUE;
 
633
    }
 
634
    
 
635
    return FALSE;
 
636
}
 
637
 
 
638
static void
 
639
xfpm_battery_tray_icon_settings_changed (GObject *obj, GParamSpec *spec, XfpmBattery *battery)
 
640
{
 
641
    xfpm_battery_refresh_visible (battery);
 
642
}
 
643
 
 
644
static void xfpm_battery_get_property (GObject *object,
 
645
                                       guint prop_id,
 
646
                                       GValue *value,
 
647
                                       GParamSpec *pspec)
 
648
{
 
649
    XfpmBattery *battery;
 
650
    
 
651
    battery = XFPM_BATTERY (object);
 
652
    
 
653
    switch (prop_id)
 
654
    {
 
655
        case PROP_AC_ONLINE:
 
656
            g_value_set_boolean (value, battery->priv->ac_online);
 
657
            break;
 
658
        case PROP_DEVICE_TYPE:
 
659
            g_value_set_enum (value, battery->priv->type);
 
660
            break;
 
661
        case PROP_CHARGE_STATUS:
 
662
            g_value_set_enum (value, battery->priv->charge);
 
663
            break;
 
664
        default:
 
665
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
666
            break;
 
667
    }
 
668
}
 
669
 
 
670
static void xfpm_battery_set_property (GObject *object,
 
671
                                       guint prop_id,
 
672
                                       const GValue *value,
 
673
                                       GParamSpec *pspec)
 
674
{
 
675
    XfpmBattery *battery;
 
676
    
 
677
    battery = XFPM_BATTERY (object);
 
678
    
 
679
    switch (prop_id)
 
680
    {
 
681
        case PROP_AC_ONLINE:
 
682
            battery->priv->ac_online = g_value_get_boolean (value);
 
683
            xfpm_battery_refresh_icon (battery);
 
684
            break;
 
685
        default:
 
686
            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
687
            break;
 
688
    }
 
689
}
 
690
 
 
691
 
 
692
static void
 
693
xfpm_battery_class_init (XfpmBatteryClass *klass)
 
694
{
 
695
    GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
696
    GtkStatusIconClass *status_icon_class = GTK_STATUS_ICON_CLASS (klass);
 
697
 
 
698
    object_class->finalize = xfpm_battery_finalize;
 
699
    object_class->get_property = xfpm_battery_get_property;
 
700
    object_class->set_property = xfpm_battery_set_property;
 
701
 
 
702
    status_icon_class->query_tooltip = xfpm_battery_query_tooltip;
 
703
    
 
704
    signals [BATTERY_CHARGE_CHANGED] = 
 
705
        g_signal_new ("battery-charge-changed",
 
706
                      XFPM_TYPE_BATTERY,
 
707
                      G_SIGNAL_RUN_LAST,
 
708
                      G_STRUCT_OFFSET(XfpmBatteryClass, battery_charge_changed),
 
709
                      NULL, NULL,
 
710
                      g_cclosure_marshal_VOID__VOID,
 
711
                      G_TYPE_NONE, 0, G_TYPE_NONE);
 
712
    
 
713
    g_object_class_install_property (object_class,
 
714
                                     PROP_AC_ONLINE,
 
715
                                     g_param_spec_boolean("ac-online",
 
716
                                                          NULL, NULL,
 
717
                                                          FALSE,
 
718
                                                          G_PARAM_READWRITE));
 
719
 
 
720
    g_object_class_install_property (object_class,
 
721
                                     PROP_DEVICE_TYPE,
 
722
                                     g_param_spec_enum ("device-type",
 
723
                                                        NULL, NULL,
 
724
                                                        XFPM_TYPE_DEVICE_TYPE,
 
725
                                                        XFPM_DEVICE_TYPE_UNKNOWN,
 
726
                                                        G_PARAM_READABLE));
 
727
 
 
728
    g_object_class_install_property (object_class,
 
729
                                     PROP_CHARGE_STATUS,
 
730
                                     g_param_spec_enum ("charge-status",
 
731
                                                        NULL, NULL,
 
732
                                                        XFPM_TYPE_BATTERY_CHARGE,
 
733
                                                        XFPM_BATTERY_CHARGE_UNKNOWN,
 
734
                                                        G_PARAM_READABLE));
 
735
 
 
736
    g_type_class_add_private (klass, sizeof (XfpmBatteryPrivate));
 
737
}
 
738
 
 
739
static void
 
740
xfpm_battery_init (XfpmBattery *battery)
 
741
{
 
742
    battery->priv = XFPM_BATTERY_GET_PRIVATE (battery);
 
743
    
 
744
    battery->priv->conf          = xfpm_xfconf_new ();
 
745
    battery->priv->notify        = xfpm_notify_new ();
 
746
    battery->priv->proxy_prop    = NULL;
 
747
    battery->priv->state         = XFPM_DEVICE_STATE_UNKNOWN;
 
748
    battery->priv->type          = XFPM_DEVICE_TYPE_UNKNOWN;
 
749
    battery->priv->charge        = XFPM_BATTERY_CHARGE_UNKNOWN;
 
750
    battery->priv->icon_prefix   = NULL;
 
751
    battery->priv->time_to_full  = 0;
 
752
    battery->priv->time_to_empty = 0;
 
753
    battery->priv->button        = xfpm_button_new ();
 
754
    battery->priv->ac_online     = TRUE;
 
755
    
 
756
    battery->priv->sig = g_signal_connect (G_OBJECT (battery->priv->conf), "notify::" SHOW_TRAY_ICON_CFG,
 
757
                                           G_CALLBACK (xfpm_battery_tray_icon_settings_changed), battery);
 
758
                                           
 
759
    
 
760
    battery->priv->sig_bt = g_signal_connect (G_OBJECT (battery->priv->button), "button-pressed",
 
761
                                           G_CALLBACK (xfpm_battery_button_pressed_cb), battery);
 
762
}
 
763
 
 
764
static void
 
765
xfpm_battery_finalize (GObject *object)
 
766
{
 
767
    XfpmBattery *battery;
 
768
 
 
769
    battery = XFPM_BATTERY (object);
 
770
    
 
771
    g_free (battery->priv->icon_prefix);
 
772
 
 
773
    if (battery->priv->notify_idle != 0)
 
774
        g_source_remove (battery->priv->notify_idle);
 
775
 
 
776
    dbus_g_proxy_disconnect_signal (battery->priv->proxy, "Changed",
 
777
                                    G_CALLBACK (xfpm_battery_changed_cb), battery);
 
778
                                    
 
779
    if ( g_signal_handler_is_connected (battery->priv->conf, battery->priv->sig ) )
 
780
        g_signal_handler_disconnect (G_OBJECT (battery->priv->conf), battery->priv->sig);
 
781
        
 
782
     if ( g_signal_handler_is_connected (battery->priv->button, battery->priv->sig_bt ) )
 
783
        g_signal_handler_disconnect (G_OBJECT (battery->priv->button), battery->priv->sig_bt);
 
784
                                    
 
785
    g_object_unref (battery->priv->proxy);
 
786
    g_object_unref (battery->priv->proxy_prop);
 
787
    g_object_unref (battery->priv->conf);
 
788
    g_object_unref (battery->priv->notify);
 
789
    g_object_unref (battery->priv->button);
 
790
 
 
791
    G_OBJECT_CLASS (xfpm_battery_parent_class)->finalize (object);
 
792
}
 
793
 
 
794
static gchar *
 
795
xfpm_battery_get_icon_prefix_device_enum_type (XfpmDeviceType type)
 
796
{
 
797
    if ( type == XFPM_DEVICE_TYPE_BATTERY )
 
798
    {
 
799
        return g_strdup (XFPM_PRIMARY_ICON_PREFIX);
 
800
    }
 
801
    else if ( type == XFPM_DEVICE_TYPE_UPS ) 
 
802
    {
 
803
        return g_strdup (XFPM_UPS_ICON_PREFIX);
 
804
    }
 
805
    else if ( type == XFPM_DEVICE_TYPE_MOUSE ) 
 
806
    {
 
807
        return g_strdup (XFPM_MOUSE_ICON_PREFIX);
 
808
    }
 
809
    else if ( type == XFPM_DEVICE_TYPE_KBD ) 
 
810
    {
 
811
        return g_strdup (XFPM_KBD_ICON_PREFIX);
 
812
    }
 
813
    else if ( type == XFPM_DEVICE_TYPE_PHONE ) 
 
814
    {
 
815
        return g_strdup (XFPM_PHONE_ICON_PREFIX);
 
816
    }
 
817
    
 
818
    return g_strdup (XFPM_PRIMARY_ICON_PREFIX);
 
819
}
 
820
 
 
821
static const gchar *
 
822
xfpm_battery_get_name (XfpmDeviceType type)
 
823
{
 
824
    const gchar *name = NULL;
 
825
    
 
826
    switch (type)
 
827
    {
 
828
        case XFPM_DEVICE_TYPE_BATTERY:
 
829
            name = _("battery");
 
830
            break;
 
831
        case XFPM_DEVICE_TYPE_UPS:
 
832
            name = _("UPS");
 
833
            break;
 
834
        case XFPM_DEVICE_TYPE_MONITOR:
 
835
            name = _("monitor battery");
 
836
            break;
 
837
        case XFPM_DEVICE_TYPE_MOUSE:
 
838
            name = _("mouse battery");
 
839
            break;
 
840
        case XFPM_DEVICE_TYPE_KBD:
 
841
            name = _("keyboard battery");
 
842
            break;
 
843
        case XFPM_DEVICE_TYPE_PDA:
 
844
            name = _("PDA battery");
 
845
            break;
 
846
        case XFPM_DEVICE_TYPE_PHONE:
 
847
            name = _("Phone battery");
 
848
            break;
 
849
        default:
 
850
            name = _("Unknown");
 
851
            break;
 
852
    }
 
853
    
 
854
    return name;
 
855
}
 
856
 
 
857
GtkStatusIcon *
 
858
xfpm_battery_new (void)
 
859
{
 
860
    XfpmBattery *battery = NULL;
 
861
    
 
862
    battery = g_object_new (XFPM_TYPE_BATTERY, NULL);
 
863
    
 
864
    return GTK_STATUS_ICON (battery);
 
865
}
 
866
 
 
867
void xfpm_battery_monitor_device (XfpmBattery *battery,
 
868
                                  DBusGProxy *proxy,
 
869
                                  DBusGProxy *proxy_prop,
 
870
                                  XfpmDeviceType device_type)
 
871
{
 
872
    battery->priv->type = device_type;
 
873
    battery->priv->proxy_prop = proxy_prop;
 
874
    battery->priv->proxy = proxy;
 
875
    battery->priv->icon_prefix = xfpm_battery_get_icon_prefix_device_enum_type (device_type);
 
876
    battery->priv->battery_name = xfpm_battery_get_name (device_type);
 
877
    
 
878
    
 
879
    dbus_g_proxy_add_signal (proxy, "Changed", G_TYPE_INVALID);
 
880
    dbus_g_proxy_connect_signal (proxy, "Changed",
 
881
                                 G_CALLBACK (xfpm_battery_changed_cb), battery, NULL);
 
882
 
 
883
    g_object_set (G_OBJECT (battery),
 
884
                  "has-tooltip", TRUE,
 
885
                  NULL);
 
886
 
 
887
    xfpm_battery_changed_cb (proxy, battery);
 
888
}
 
889
 
 
890
XfpmDeviceType xfpm_battery_get_device_type (XfpmBattery *battery)
 
891
{
 
892
    g_return_val_if_fail (XFPM_IS_BATTERY (battery), XFPM_DEVICE_TYPE_UNKNOWN );
 
893
    
 
894
    return battery->priv->type;
 
895
}
 
896
 
 
897
XfpmBatteryCharge xfpm_battery_get_charge (XfpmBattery *battery)
 
898
{
 
899
    g_return_val_if_fail (XFPM_IS_BATTERY (battery), XFPM_BATTERY_CHARGE_UNKNOWN);
 
900
    
 
901
    return battery->priv->charge;
 
902
}
 
903
 
 
904
const gchar *xfpm_battery_get_battery_name (XfpmBattery *battery)
 
905
{
 
906
    g_return_val_if_fail (XFPM_IS_BATTERY (battery), NULL);
 
907
    
 
908
    return battery->priv->battery_name;
 
909
}
 
910
 
 
911
gchar *xfpm_battery_get_time_left (XfpmBattery *battery)
 
912
{
 
913
    g_return_val_if_fail (XFPM_IS_BATTERY (battery), NULL);
 
914
    
 
915
    return xfpm_battery_get_time_string (battery->priv->time_to_empty);
 
916
}