Merge lp:~noskcaj/ubuntu/saucy/xfce4-power-manager/1.2.0-2ubuntu1 into lp:ubuntu/saucy/xfce4-power-manager

Proposed by Jackson Doak
Status: Needs review
Proposed branch: lp:~noskcaj/ubuntu/saucy/xfce4-power-manager/1.2.0-2ubuntu1
Merge into: lp:ubuntu/saucy/xfce4-power-manager
Diff against target: 12657 lines (+6506/-4889)
29 files modified
.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/po/POTFILES.in (+19/-0)
.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/Makefile.am (+211/-0)
.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.c (+1078/-0)
.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.h (+71/-0)
.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-backlight.c (+478/-0)
.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-notify.c (+409/-0)
.pc/03_fix-insert-battery.patch/src/xfpm-battery.c (+916/-0)
.pc/03_fix-insert-battery.patch/src/xfpm-power.c (+1755/-0)
.pc/06_fix-suspend-auth-check.patch/src/xfpm-power.c (+1/-0)
.pc/09_fix_insert_battery.patch/src/xfpm-battery.c (+0/-916)
.pc/09_fix_insert_battery.patch/src/xfpm-power.c (+0/-1755)
.pc/applied-patches (+2/-1)
debian/changelog (+35/-0)
debian/control (+4/-2)
debian/patches/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch (+1423/-0)
debian/patches/02_translations-fix-invalid-format-strings.patch (+18/-12)
debian/patches/03_fix-insert-battery.patch (+44/-0)
debian/patches/06_fix-suspend-auth-check.patch (+5/-3)
debian/patches/08_show_preferences_lxde.patch (+2/-2)
debian/patches/series (+3/-1)
debian/patches/xubuntu_fix-status-icon-other-devices.patch (+5/-3)
debian/rules (+5/-1)
po/POTFILES.in (+1/-0)
po/ast.po (+0/-927)
src/Makefile.am (+1/-3)
src/gsd-media-keys-window.c (+0/-1078)
src/gsd-media-keys-window.h (+0/-71)
src/xfpm-backlight.c (+19/-113)
src/xfpm-notify.c (+1/-1)
To merge this branch: bzr merge lp:~noskcaj/ubuntu/saucy/xfce4-power-manager/1.2.0-2ubuntu1
Reviewer Review Type Date Requested Status
Daniel Holbach (community) Approve
Review via email: mp+179809@code.launchpad.net

Description of the change

* 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.

To post a comment you must log in.
Revision history for this message
Daniel Holbach (dholbach) wrote :

Good work. Uploaded.

review: Approve

Unmerged revisions

34. By Jackson Doak

* 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.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch'
2=== added file '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/.timestamp'
3=== added directory '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/po'
4=== added file '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/po/POTFILES.in'
5--- .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/po/POTFILES.in 1970-01-01 00:00:00 +0000
6+++ .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/po/POTFILES.in 2013-08-12 21:07:54 +0000
7@@ -0,0 +1,19 @@
8+[encoding: UTF-8]
9+[type: gettext/glade]data/interfaces/xfpm-settings.ui
10+settings/xfpm-settings.c
11+settings/xfpm-settings-main.c
12+settings/xfce4-power-manager-settings.desktop.in
13+common/xfpm-common.c
14+src/xfpm-power.c
15+src/xfpm-power-common.c
16+src/xfpm-battery.c
17+src/xfpm-battery.c
18+src/xfpm-main.c
19+src/xfpm-network-manager.c
20+src/xfpm-dpms.c
21+src/xfpm-inhibit.c
22+src/xfpm-power-info.c
23+src/xfce4-power-manager.desktop.in
24+src/org.xfce.power.policy.in2
25+panel-plugins/brightness/brightness-button.c
26+panel-plugins/brightness/xfce4-brightness-plugin.desktop.in.in
27
28=== added directory '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src'
29=== added file '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/Makefile.am'
30--- .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/Makefile.am 1970-01-01 00:00:00 +0000
31+++ .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/Makefile.am 2013-08-12 21:07:54 +0000
32@@ -0,0 +1,211 @@
33+bin_PROGRAMS = xfce4-power-manager \
34+ xfce4-power-information
35+
36+xfce4_power_manager_SOURCES = \
37+ $(BUILT_SOURCES) \
38+ xfpm-enum.h \
39+ xfpm-enum-glib.h \
40+ xfpm-main.c \
41+ xfpm-manager.c \
42+ xfpm-manager.h \
43+ xfpm-power.c \
44+ xfpm-power.h \
45+ xfpm-power-common.c \
46+ xfpm-power-common.h \
47+ xfpm-battery.c \
48+ xfpm-battery.h \
49+ xfpm-xfconf.c \
50+ xfpm-xfconf.h \
51+ xfpm-disks.c \
52+ xfpm-disks.h \
53+ xfpm-console-kit.c \
54+ xfpm-console-kit.h \
55+ egg-idletime.c \
56+ egg-idletime.h \
57+ xfpm-backlight.c \
58+ xfpm-backlight.h \
59+ xfpm-dpms.c \
60+ xfpm-dpms.h \
61+ xfpm-button.c \
62+ xfpm-button.h \
63+ xfpm-network-manager.c \
64+ xfpm-network-manager.h \
65+ xfpm-inhibit.c \
66+ xfpm-inhibit.h \
67+ xfpm-notify.c \
68+ xfpm-notify.h \
69+ xfpm-polkit.c \
70+ xfpm-polkit.h \
71+ xfpm-errors.c \
72+ xfpm-errors.h \
73+ gsd-media-keys-window.c \
74+ gsd-media-keys-window.h
75+
76+xfce4_power_manager_CFLAGS = \
77+ -I$(top_srcdir) \
78+ -I$(top_srcdir)/common \
79+ -I$(top_srcdir)/libdbus \
80+ -DLOCALEDIR=\"$(localedir)\" \
81+ -DG_LOG_DOMAIN=\"xfce4-power-manager\" \
82+ -DSYSCONFDIR=\"$(sysconfdir)\" \
83+ $(GOBJECT_CFLAGS) \
84+ $(GTHREAD_CFLAGS) \
85+ $(DBUS_GLIB_CFLAGS) \
86+ $(LIBXFCE4UI_CFLAGS) \
87+ $(XFCONF_CFLAGS) \
88+ $(LIBNOTIFY_CFLAGS) \
89+ $(XRANDR_CFLAGS) \
90+ $(DPMS_CFLAGS) \
91+ $(PLATFORM_CPPFLAGS) \
92+ $(PLATFORM_CFLAGS)
93+
94+xfce4_power_manager_LDFLAGS = \
95+ -no-undefined \
96+ $(PLATFORM_LDFLAGS)
97+
98+xfce4_power_manager_LDADD = \
99+ $(top_builddir)/common/libxfpmcommon.la \
100+ $(top_builddir)/libdbus/libxfpmdbus.la \
101+ $(GOBJECT_LIBS) \
102+ $(GTHREAD_LIBS) \
103+ $(DBUS_GLIB_LIBS) \
104+ $(LIBXFCE4UI_LIBS) \
105+ $(XFCONF_LIBS) \
106+ $(LIBNOTIFY_LIBS) \
107+ $(XRANDR_LIBS) \
108+ $(DPMS_LIBS)
109+
110+xfce4_power_information_SOURCES = \
111+ xfpm-power-info.c \
112+ xfpm-power-common.c \
113+ xfpm-power-common.h
114+
115+xfce4_power_information_CFLAGS = \
116+ -I$(top_srcdir) \
117+ -I$(top_srcdir)/common \
118+ -I$(top_srcdir)/libdbus \
119+ -DLOCALEDIR=\"$(localedir)\" \
120+ -DG_LOG_DOMAIN=\"xfce4-power-information\"\
121+ $(GOBJECT_CFLAGS) \
122+ $(DBUS_GLIB_CFLAGS) \
123+ $(LIBXFCE4UI_CFLAGS) \
124+ $(PLATFORM_CPPFLAGS) \
125+ $(PLATFORM_CFLAGS)
126+
127+xfce4_power_information_LDFLAGS = \
128+ -no-undefined \
129+ $(PLATFORM_LDFLAGS)
130+
131+xfce4_power_information_LDADD = \
132+ $(GOBJECT_LIBS) \
133+ $(DBUS_GLIB_LIBS) \
134+ $(LIBXFCE4UI_LIBS) \
135+ $(top_builddir)/libdbus/libxfpmdbus.la
136+
137+if ENABLE_POLKIT
138+
139+sbin_PROGRAMS = xfpm-power-backlight-helper
140+
141+xfpm_power_backlight_helper_SOURCES = \
142+ xfpm-backlight-helper.c
143+
144+xfpm_power_backlight_helper_LDADD = \
145+ $(GLIB_LIBS) \
146+ -lm
147+
148+xfpm_power_backlight_helper_CFLAGS = \
149+ $(GLIB_CFLAGS) \
150+ $(PLATFORM_CPPFLAGS) \
151+ $(PLATFORM_CFLAGS)
152+
153+polkit_policydir = $(datadir)/polkit-1/actions
154+polkit_policy_DATA = \
155+ org.xfce.power.policy
156+
157+# You will need a recent intltool or the patch from this bug
158+# http://bugzilla.gnome.org/show_bug.cgi?id=462312
159+@INTLTOOL_POLICY_RULE@
160+
161+.in2.in:
162+ sed "s|[@]sbindir@|${sbindir}|" $< > $@
163+
164+endif
165+
166+manpagedir = $(mandir)/man1
167+
168+manpage_DATA = xfce4-power-manager.1
169+
170+xfpm_glib_headers = \
171+ $(srcdir)/xfpm-enum-glib.h
172+
173+BUILT_SOURCES = \
174+ xfce-power-manager-dbus-server.h \
175+ xfce-power-manager-dbus-client.h \
176+ xfpm-enum-types.c \
177+ xfpm-enum-types.h \
178+ xfpm-marshal.c \
179+ xfpm-marshal.h \
180+ org.freedesktop.PowerManagement.h \
181+ org.freedesktop.PowerManagement.Inhibit.h
182+
183+if MAINTAINER_MODE
184+
185+xfpm-enum-types.h: $(xfpm_glib_headers)
186+ ( cd $(srcdir) && glib-mkenums \
187+ --fhead "#ifndef _XFPM_ENUM_TYPES_H\n#define _XFPM_ENUM_TYPES_H\n#include <glib-object.h>\nG_BEGIN_DECLS\n" \
188+ --fprod "/* enumerations from \"@filename@\" */\n" \
189+ --vhead "GType @enum_name@_get_type (void);\n#define XFPM_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
190+ --ftail "G_END_DECLS\n\n#endif /* _XFPM_ENUM_TYPES_H__ */" \
191+ $(xfpm_glib_headers) ) >> xgen \
192+ && (cmp -s xgen xfpm-enum-types.h || cp xgen xfpm-enum-types.h ) \
193+ && rm -f xgen xgen~
194+
195+xfpm-enum-types.c: xfpm-enum-types.h
196+ ( cd $(srcdir) && glib-mkenums \
197+ --fhead "#include <xfpm-enum-types.h>\n" \
198+ --fhead "#include \"xfpm-enum-glib.h\"\n\n" \
199+ --fprod "\n/* enumerations from \"@filename@\" */\n" \
200+ --vhead "GType\n@enum_name@_get_type (void)\n{\n\tstatic GType type = 0;\n\tif (type == 0) {\n\tstatic const G@Type@Value values[] = {"\
201+ --vprod "\t{ @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
202+ --vtail "\t{ 0, NULL, NULL }\n\t};\n\ttype = g_@type@_register_static (\"@EnumName@\", values);\n }\n\treturn type;\n}\n" \
203+ $(xfpm_glib_headers) ) > xgen \
204+ && cp xgen xfpm-enum-types.c \
205+ && rm -f xgen xgen~
206+
207+xfpm-marshal.c: xfpm-marshal.list
208+ echo "#include \"xfpm-marshal.h\"" > $@ && \
209+ glib-genmarshal $< --prefix=_xfpm_marshal --body >> $@
210+
211+xfpm-marshal.h: xfpm-marshal.list
212+ glib-genmarshal $< --prefix=_xfpm_marshal --header > $@
213+
214+xfce-power-manager-dbus-server.h: $(srcdir)/org.xfce.Power.Manager.xml
215+ dbus-binding-tool --mode=glib-server --prefix=xfpm_manager $< >$@
216+
217+xfce-power-manager-dbus-client.h: $(srcdir)/org.xfce.Power.Manager.xml
218+ dbus-binding-tool --mode=glib-client --prefix=xfpm_manager $< >$@
219+
220+org.freedesktop.PowerManagement.h: $(srcdir)/org.freedesktop.PowerManagement.xml
221+ dbus-binding-tool --mode=glib-server --prefix=xfpm_power $< >$@
222+
223+org.freedesktop.PowerManagement.Inhibit.h: $(srcdir)/org.freedesktop.PowerManagement.Inhibit.xml
224+ dbus-binding-tool --mode=glib-server --prefix=xfpm_inhibit $< >$@
225+
226+endif
227+
228+@INTLTOOL_DESKTOP_RULE@
229+autostartdir = $(sysconfdir)/xdg/autostart
230+autostart_in_files = xfce4-power-manager.desktop.in
231+autostart_DATA = $(autostart_in_files:.desktop.in=.desktop)
232+
233+EXTRA_DIST = \
234+ xfpm-marshal.list \
235+ $(autostart_in_files) \
236+ org.xfce.power.policy.in2 \
237+ $(manpage_DATA)
238+
239+DISTCLEANFILES = \
240+ $(BUILT_SOURCES) \
241+ xfce4-power-manager.desktop \
242+ org.xfce.power.policy \
243+ org.xfce.power.policy.in
244
245=== added file '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.c'
246--- .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.c 1970-01-01 00:00:00 +0000
247+++ .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.c 2013-08-12 21:07:54 +0000
248@@ -0,0 +1,1078 @@
249+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
250+ *
251+ * Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu>
252+ *
253+ * This program is free software; you can redistribute it and/or modify
254+ * it under the terms of the GNU General Public License as published by
255+ * the Free Software Foundation; either version 2 of the License, or
256+ * (at your option) any later version.
257+ *
258+ * This program is distributed in the hope that it will be useful,
259+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
260+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
261+ * GNU General Public License for more details.
262+ *
263+ * You should have received a copy of the GNU General Public License
264+ * along with this program; if not, write to the Free Software
265+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
266+ *
267+ */
268+
269+#include "config.h"
270+
271+#include <stdlib.h>
272+#include <string.h>
273+#include <math.h>
274+#include <glib.h>
275+#include <glib/gi18n.h>
276+#include <gtk/gtk.h>
277+
278+#include "gsd-media-keys-window.h"
279+
280+#include "data/interfaces/acme_ui.h"
281+
282+#define DIALOG_TIMEOUT 2000 /* dialog timeout in ms */
283+#define DIALOG_FADE_TIMEOUT 1500 /* timeout before fade starts */
284+#define FADE_TIMEOUT 10 /* timeout in ms between each frame of the fade */
285+
286+#define BG_ALPHA 0.75
287+#define FG_ALPHA 1.00
288+
289+#define GSD_MEDIA_KEYS_WINDOW_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MEDIA_KEYS_WINDOW, GsdMediaKeysWindowPrivate))
290+
291+struct GsdMediaKeysWindowPrivate
292+{
293+ guint is_composited : 1;
294+ guint hide_timeout_id;
295+ guint fade_timeout_id;
296+ double fade_out_alpha;
297+ GsdMediaKeysWindowAction action;
298+ char *icon_name;
299+ gboolean show_level;
300+
301+ guint volume_muted : 1;
302+ int volume_level;
303+
304+ GtkImage *image;
305+ GtkWidget *progress;
306+};
307+
308+G_DEFINE_TYPE (GsdMediaKeysWindow, gsd_media_keys_window, GTK_TYPE_WINDOW)
309+
310+static gboolean
311+fade_timeout (GsdMediaKeysWindow *window)
312+{
313+ if (window->priv->fade_out_alpha <= 0.0) {
314+ gtk_widget_hide (GTK_WIDGET (window));
315+
316+ /* Reset it for the next time */
317+ window->priv->fade_out_alpha = 1.0;
318+ window->priv->fade_timeout_id = 0;
319+
320+ return FALSE;
321+ } else {
322+ GdkRectangle rect;
323+ GtkWidget *win = GTK_WIDGET (window);
324+ GtkAllocation allocation;
325+
326+ window->priv->fade_out_alpha -= 0.10;
327+
328+ rect.x = 0;
329+ rect.y = 0;
330+ gtk_widget_get_allocation (win, &allocation);
331+ rect.width = allocation.width;
332+ rect.height = allocation.height;
333+
334+ gtk_widget_realize (win);
335+ gdk_window_invalidate_rect (gtk_widget_get_window (win), &rect, FALSE);
336+ }
337+
338+ return TRUE;
339+}
340+
341+static gboolean
342+hide_timeout (GsdMediaKeysWindow *window)
343+{
344+ if (window->priv->is_composited) {
345+ window->priv->hide_timeout_id = 0;
346+ window->priv->fade_timeout_id = g_timeout_add (FADE_TIMEOUT,
347+ (GSourceFunc) fade_timeout,
348+ window);
349+ } else {
350+ gtk_widget_hide (GTK_WIDGET (window));
351+ }
352+
353+ return FALSE;
354+}
355+
356+static void
357+remove_hide_timeout (GsdMediaKeysWindow *window)
358+{
359+ if (window->priv->hide_timeout_id != 0) {
360+ g_source_remove (window->priv->hide_timeout_id);
361+ window->priv->hide_timeout_id = 0;
362+ }
363+
364+ if (window->priv->fade_timeout_id != 0) {
365+ g_source_remove (window->priv->fade_timeout_id);
366+ window->priv->fade_timeout_id = 0;
367+ window->priv->fade_out_alpha = 1.0;
368+ }
369+}
370+
371+static void
372+add_hide_timeout (GsdMediaKeysWindow *window)
373+{
374+ int timeout;
375+
376+ if (window->priv->is_composited) {
377+ timeout = DIALOG_FADE_TIMEOUT;
378+ } else {
379+ timeout = DIALOG_TIMEOUT;
380+ }
381+ window->priv->hide_timeout_id = g_timeout_add (timeout,
382+ (GSourceFunc) hide_timeout,
383+ window);
384+}
385+
386+static void
387+update_window (GsdMediaKeysWindow *window)
388+{
389+ remove_hide_timeout (window);
390+ add_hide_timeout (window);
391+
392+ if (window->priv->is_composited) {
393+ gtk_widget_queue_draw (GTK_WIDGET (window));
394+ }
395+}
396+
397+static void
398+volume_controls_set_visible (GsdMediaKeysWindow *window,
399+ gboolean visible)
400+{
401+ if (window->priv->progress == NULL)
402+ return;
403+
404+ if (visible) {
405+ gtk_widget_show (window->priv->progress);
406+ } else {
407+ gtk_widget_hide (window->priv->progress);
408+ }
409+}
410+
411+static void
412+window_set_icon_name (GsdMediaKeysWindow *window,
413+ const char *name)
414+{
415+ if (window->priv->image == NULL)
416+ return;
417+
418+ gtk_image_set_from_icon_name (window->priv->image,
419+ name, GTK_ICON_SIZE_DIALOG);
420+}
421+
422+static void
423+action_changed (GsdMediaKeysWindow *window)
424+{
425+ if (! window->priv->is_composited) {
426+ switch (window->priv->action) {
427+ case GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME:
428+ volume_controls_set_visible (window, TRUE);
429+
430+ if (window->priv->volume_muted) {
431+ window_set_icon_name (window, "audio-volume-muted");
432+ } else {
433+ window_set_icon_name (window, "audio-volume-high");
434+ }
435+
436+ break;
437+ case GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM:
438+ volume_controls_set_visible (window, window->priv->show_level);
439+ window_set_icon_name (window, window->priv->icon_name);
440+ break;
441+ default:
442+ g_assert_not_reached ();
443+ break;
444+ }
445+ }
446+
447+ update_window (window);
448+}
449+
450+static void
451+volume_level_changed (GsdMediaKeysWindow *window)
452+{
453+ update_window (window);
454+
455+ if (!window->priv->is_composited && window->priv->progress != NULL) {
456+ double fraction;
457+
458+ fraction = (double) window->priv->volume_level / 100.0;
459+
460+ gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (window->priv->progress),
461+ fraction);
462+ }
463+}
464+
465+static void
466+volume_muted_changed (GsdMediaKeysWindow *window)
467+{
468+ update_window (window);
469+
470+ if (! window->priv->is_composited) {
471+ if (window->priv->volume_muted) {
472+ window_set_icon_name (window, "audio-volume-muted");
473+ } else {
474+ window_set_icon_name (window, "audio-volume-high");
475+ }
476+ }
477+}
478+
479+void
480+gsd_media_keys_window_set_action (GsdMediaKeysWindow *window,
481+ GsdMediaKeysWindowAction action)
482+{
483+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
484+ g_return_if_fail (action == GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME);
485+
486+ if (window->priv->action != action) {
487+ window->priv->action = action;
488+ action_changed (window);
489+ } else {
490+ update_window (window);
491+ }
492+}
493+
494+void
495+gsd_media_keys_window_set_action_custom (GsdMediaKeysWindow *window,
496+ const char *icon_name,
497+ gboolean show_level)
498+{
499+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
500+ g_return_if_fail (icon_name != NULL);
501+
502+ if (window->priv->action != GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM ||
503+ g_strcmp0 (window->priv->icon_name, icon_name) != 0 ||
504+ window->priv->show_level != show_level) {
505+ window->priv->action = GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM;
506+ g_free (window->priv->icon_name);
507+ window->priv->icon_name = g_strdup (icon_name);
508+ window->priv->show_level = show_level;
509+ action_changed (window);
510+ } else {
511+ update_window (window);
512+ }
513+}
514+
515+void
516+gsd_media_keys_window_set_volume_muted (GsdMediaKeysWindow *window,
517+ gboolean muted)
518+{
519+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
520+
521+ if (window->priv->volume_muted != muted) {
522+ window->priv->volume_muted = muted;
523+ volume_muted_changed (window);
524+ }
525+}
526+
527+void
528+gsd_media_keys_window_set_volume_level (GsdMediaKeysWindow *window,
529+ int level)
530+{
531+ g_return_if_fail (GSD_IS_MEDIA_KEYS_WINDOW (window));
532+
533+ if (window->priv->volume_level != level) {
534+ window->priv->volume_level = level;
535+ volume_level_changed (window);
536+ }
537+}
538+
539+static void
540+rounded_rectangle (cairo_t* cr,
541+ gdouble aspect,
542+ gdouble x,
543+ gdouble y,
544+ gdouble corner_radius,
545+ gdouble width,
546+ gdouble height)
547+{
548+ gdouble radius = corner_radius / aspect;
549+
550+ cairo_move_to (cr, x + radius, y);
551+
552+ cairo_line_to (cr,
553+ x + width - radius,
554+ y);
555+ cairo_arc (cr,
556+ x + width - radius,
557+ y + radius,
558+ radius,
559+ -90.0f * G_PI / 180.0f,
560+ 0.0f * G_PI / 180.0f);
561+ cairo_line_to (cr,
562+ x + width,
563+ y + height - radius);
564+ cairo_arc (cr,
565+ x + width - radius,
566+ y + height - radius,
567+ radius,
568+ 0.0f * G_PI / 180.0f,
569+ 90.0f * G_PI / 180.0f);
570+ cairo_line_to (cr,
571+ x + radius,
572+ y + height);
573+ cairo_arc (cr,
574+ x + radius,
575+ y + height - radius,
576+ radius,
577+ 90.0f * G_PI / 180.0f,
578+ 180.0f * G_PI / 180.0f);
579+ cairo_line_to (cr,
580+ x,
581+ y + radius);
582+ cairo_arc (cr,
583+ x + radius,
584+ y + radius,
585+ radius,
586+ 180.0f * G_PI / 180.0f,
587+ 270.0f * G_PI / 180.0f);
588+ cairo_close_path (cr);
589+}
590+
591+static GdkPixbuf *
592+load_pixbuf (GsdMediaKeysWindow *window,
593+ const char *name,
594+ int icon_size)
595+{
596+ GtkIconTheme *theme;
597+ GdkPixbuf *pixbuf;
598+
599+ if (window != NULL && gtk_widget_has_screen (GTK_WIDGET (window))) {
600+ theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (window)));
601+ } else {
602+ theme = gtk_icon_theme_get_default ();
603+ }
604+
605+ pixbuf = gtk_icon_theme_load_icon (theme,
606+ name,
607+ icon_size,
608+ GTK_ICON_LOOKUP_FORCE_SVG,
609+ NULL);
610+
611+ /* make sure the pixbuf is close to the requested size
612+ * this is necessary because GTK_ICON_LOOKUP_FORCE_SVG
613+ * seems to be broken */
614+ if (pixbuf != NULL) {
615+ int width;
616+
617+ width = gdk_pixbuf_get_width (pixbuf);
618+ if (width < (float)icon_size * 0.75) {
619+ g_object_unref (pixbuf);
620+ pixbuf = NULL;
621+ }
622+ }
623+
624+ return pixbuf;
625+}
626+
627+static void
628+draw_eject (cairo_t *cr,
629+ double _x0,
630+ double _y0,
631+ double width,
632+ double height)
633+{
634+ int box_height;
635+ int tri_height;
636+ int separation;
637+
638+ box_height = height * 0.2;
639+ separation = box_height / 3;
640+ tri_height = height - box_height - separation;
641+
642+ cairo_rectangle (cr, _x0, _y0 + height - box_height, width, box_height);
643+
644+ cairo_move_to (cr, _x0, _y0 + tri_height);
645+ cairo_rel_line_to (cr, width, 0);
646+ cairo_rel_line_to (cr, -width / 2, -tri_height);
647+ cairo_rel_line_to (cr, -width / 2, tri_height);
648+ cairo_close_path (cr);
649+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, FG_ALPHA);
650+ cairo_fill_preserve (cr);
651+
652+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, FG_ALPHA / 2);
653+ cairo_set_line_width (cr, 2);
654+ cairo_stroke (cr);
655+}
656+
657+static void
658+draw_waves (cairo_t *cr,
659+ double cx,
660+ double cy,
661+ double max_radius,
662+ int volume_level)
663+{
664+ const int n_waves = 3;
665+ int last_wave;
666+ int i;
667+
668+ last_wave = n_waves * volume_level / 100;
669+
670+ for (i = 0; i < n_waves; i++) {
671+ double angle1;
672+ double angle2;
673+ double radius;
674+ double alpha;
675+
676+ angle1 = -M_PI / 4;
677+ angle2 = M_PI / 4;
678+
679+ if (i < last_wave)
680+ alpha = 1.0;
681+ else if (i > last_wave)
682+ alpha = 0.1;
683+ else alpha = 0.1 + 0.9 * (n_waves * volume_level % 100) / 100.0;
684+
685+ radius = (i + 1) * (max_radius / n_waves);
686+ cairo_arc (cr, cx, cy, radius, angle1, angle2);
687+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, alpha / 2);
688+ cairo_set_line_width (cr, 14);
689+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
690+ cairo_stroke_preserve (cr);
691+
692+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha);
693+ cairo_set_line_width (cr, 10);
694+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
695+ cairo_stroke (cr);
696+ }
697+}
698+
699+static void
700+draw_cross (cairo_t *cr,
701+ double cx,
702+ double cy,
703+ double size)
704+{
705+ cairo_move_to (cr, cx, cy - size/2.0);
706+ cairo_rel_line_to (cr, size, size);
707+
708+ cairo_move_to (cr, cx, cy + size/2.0);
709+ cairo_rel_line_to (cr, size, -size);
710+
711+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, FG_ALPHA / 2);
712+ cairo_set_line_width (cr, 14);
713+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
714+ cairo_stroke_preserve (cr);
715+
716+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, FG_ALPHA);
717+ cairo_set_line_width (cr, 10);
718+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
719+ cairo_stroke (cr);
720+}
721+
722+static void
723+draw_speaker (cairo_t *cr,
724+ double cx,
725+ double cy,
726+ double width,
727+ double height)
728+{
729+ double box_width;
730+ double box_height;
731+ double _x0;
732+ double _y0;
733+
734+ box_width = width / 3;
735+ box_height = height / 3;
736+
737+ _x0 = cx - (width / 2) + box_width;
738+ _y0 = cy - box_height / 2;
739+
740+ cairo_move_to (cr, _x0, _y0);
741+ cairo_rel_line_to (cr, - box_width, 0);
742+ cairo_rel_line_to (cr, 0, box_height);
743+ cairo_rel_line_to (cr, box_width, 0);
744+
745+ cairo_line_to (cr, cx + box_width, cy + height / 2);
746+ cairo_rel_line_to (cr, 0, -height);
747+ cairo_line_to (cr, _x0, _y0);
748+ cairo_close_path (cr);
749+
750+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, FG_ALPHA);
751+ cairo_fill_preserve (cr);
752+
753+ cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, FG_ALPHA / 2);
754+ cairo_set_line_width (cr, 2);
755+ cairo_stroke (cr);
756+}
757+
758+static gboolean
759+render_speaker (GsdMediaKeysWindow *window,
760+ cairo_t *cr,
761+ double _x0,
762+ double _y0,
763+ double width,
764+ double height)
765+{
766+ GdkPixbuf *pixbuf;
767+ int icon_size;
768+ int n;
769+ static const char *icon_names[] = {
770+ "audio-volume-muted",
771+ "audio-volume-low",
772+ "audio-volume-medium",
773+ "audio-volume-high",
774+ NULL
775+ };
776+
777+ if (window->priv->volume_muted) {
778+ n = 0;
779+ } else {
780+ /* select image */
781+ n = 3 * window->priv->volume_level / 100 + 1;
782+ if (n < 1) {
783+ n = 1;
784+ } else if (n > 3) {
785+ n = 3;
786+ }
787+ }
788+
789+ icon_size = (int)width;
790+
791+ pixbuf = load_pixbuf (window, icon_names[n], icon_size);
792+
793+ if (pixbuf == NULL) {
794+ return FALSE;
795+ }
796+
797+ gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0);
798+ cairo_paint_with_alpha (cr, FG_ALPHA);
799+
800+ g_object_unref (pixbuf);
801+
802+ return TRUE;
803+}
804+
805+static void
806+color_reverse (const GdkColor *a,
807+ GdkColor *b)
808+{
809+ gdouble red;
810+ gdouble green;
811+ gdouble blue;
812+ gdouble h;
813+ gdouble s;
814+ gdouble v;
815+
816+ red = (gdouble) a->red / 65535.0;
817+ green = (gdouble) a->green / 65535.0;
818+ blue = (gdouble) a->blue / 65535.0;
819+
820+ gtk_rgb_to_hsv (red, green, blue, &h, &s, &v);
821+
822+ v = 0.5 + (0.5 - v);
823+ if (v > 1.0)
824+ v = 1.0;
825+ else if (v < 0.0)
826+ v = 0.0;
827+
828+ gtk_hsv_to_rgb (h, s, v, &red, &green, &blue);
829+
830+ b->red = red * 65535.0;
831+ b->green = green * 65535.0;
832+ b->blue = blue * 65535.0;
833+}
834+
835+static void
836+draw_volume_boxes (GsdMediaKeysWindow *window,
837+ cairo_t *cr,
838+ double percentage,
839+ double _x0,
840+ double _y0,
841+ double width,
842+ double height)
843+{
844+ gdouble x1;
845+ GdkColor color;
846+ double r, g, b;
847+ GtkStyle *style;
848+
849+ _x0 += 0.5;
850+ _y0 += 0.5;
851+ height = round (height) - 1;
852+ width = round (width) - 1;
853+ x1 = round ((width - 1) * percentage);
854+ style = gtk_widget_get_style (GTK_WIDGET (window));
855+
856+ /* bar background */
857+ color_reverse (&style->dark[GTK_STATE_NORMAL], &color);
858+ r = (float)color.red / 65535.0;
859+ g = (float)color.green / 65535.0;
860+ b = (float)color.blue / 65535.0;
861+ rounded_rectangle (cr, 1.0, _x0, _y0, height / 6, width, height);
862+ cairo_set_source_rgba (cr, r, g, b, FG_ALPHA / 2);
863+ cairo_fill_preserve (cr);
864+
865+ /* bar border */
866+ color_reverse (&style->light[GTK_STATE_NORMAL], &color);
867+ r = (float)color.red / 65535.0;
868+ g = (float)color.green / 65535.0;
869+ b = (float)color.blue / 65535.0;
870+ cairo_set_source_rgba (cr, r, g, b, FG_ALPHA / 2);
871+ cairo_set_line_width (cr, 1);
872+ cairo_stroke (cr);
873+
874+ /* bar progress */
875+ if (percentage < 0.01)
876+ return;
877+ color = style->bg[GTK_STATE_NORMAL];
878+ r = (float)color.red / 65535.0;
879+ g = (float)color.green / 65535.0;
880+ b = (float)color.blue / 65535.0;
881+ rounded_rectangle (cr, 1.0, _x0 + 0.5, _y0 + 0.5, height / 6 - 0.5, x1, height - 1);
882+ cairo_set_source_rgba (cr, r, g, b, FG_ALPHA);
883+ cairo_fill (cr);
884+}
885+
886+static void
887+draw_action_volume (GsdMediaKeysWindow *window,
888+ cairo_t *cr)
889+{
890+ int window_width;
891+ int window_height;
892+ double icon_box_width;
893+ double icon_box_height;
894+ double icon_box_x0;
895+ double icon_box_y0;
896+ double volume_box_x0;
897+ double volume_box_y0;
898+ double volume_box_width;
899+ double volume_box_height;
900+ gboolean res;
901+
902+ gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height);
903+
904+ icon_box_width = round (window_width * 0.65);
905+ icon_box_height = round (window_height * 0.65);
906+ volume_box_width = icon_box_width;
907+ volume_box_height = round (window_height * 0.05);
908+
909+ icon_box_x0 = (window_width - icon_box_width) / 2;
910+ icon_box_y0 = (window_height - icon_box_height - volume_box_height) / 2;
911+ volume_box_x0 = round (icon_box_x0);
912+ volume_box_y0 = round (icon_box_height + icon_box_y0);
913+
914+#if 0
915+ g_message ("icon box: w=%f h=%f _x0=%f _y0=%f",
916+ icon_box_width,
917+ icon_box_height,
918+ icon_box_x0,
919+ icon_box_y0);
920+ g_message ("volume box: w=%f h=%f _x0=%f _y0=%f",
921+ volume_box_width,
922+ volume_box_height,
923+ volume_box_x0,
924+ volume_box_y0);
925+#endif
926+
927+ res = render_speaker (window,
928+ cr,
929+ icon_box_x0, icon_box_y0,
930+ icon_box_width, icon_box_height);
931+ if (! res) {
932+ double speaker_width;
933+ double speaker_height;
934+ double speaker_cx;
935+ double speaker_cy;
936+
937+ speaker_width = icon_box_width * 0.5;
938+ speaker_height = icon_box_height * 0.75;
939+ speaker_cx = icon_box_x0 + speaker_width / 2;
940+ speaker_cy = icon_box_y0 + speaker_height / 2;
941+
942+#if 0
943+ g_message ("speaker box: w=%f h=%f cx=%f cy=%f",
944+ speaker_width,
945+ speaker_height,
946+ speaker_cx,
947+ speaker_cy);
948+#endif
949+
950+ /* draw speaker symbol */
951+ draw_speaker (cr, speaker_cx, speaker_cy, speaker_width, speaker_height);
952+
953+ if (! window->priv->volume_muted) {
954+ /* draw sound waves */
955+ double wave_x0;
956+ double wave_y0;
957+ double wave_radius;
958+
959+ wave_x0 = window_width / 2;
960+ wave_y0 = speaker_cy;
961+ wave_radius = icon_box_width / 2;
962+
963+ draw_waves (cr, wave_x0, wave_y0, wave_radius, window->priv->volume_level);
964+ } else {
965+ /* draw 'mute' cross */
966+ double cross_x0;
967+ double cross_y0;
968+ double cross_size;
969+
970+ cross_size = speaker_width * 3 / 4;
971+ cross_x0 = icon_box_x0 + icon_box_width - cross_size;
972+ cross_y0 = speaker_cy;
973+
974+ draw_cross (cr, cross_x0, cross_y0, cross_size);
975+ }
976+ }
977+
978+ /* draw volume meter */
979+ draw_volume_boxes (window,
980+ cr,
981+ (double)window->priv->volume_level / 100.0,
982+ volume_box_x0,
983+ volume_box_y0,
984+ volume_box_width,
985+ volume_box_height);
986+}
987+
988+static gboolean
989+render_custom (GsdMediaKeysWindow *window,
990+ cairo_t *cr,
991+ double _x0,
992+ double _y0,
993+ double width,
994+ double height)
995+{
996+ GdkPixbuf *pixbuf;
997+ int icon_size;
998+
999+ icon_size = (int)width;
1000+
1001+ pixbuf = load_pixbuf (window, window->priv->icon_name, icon_size);
1002+
1003+ if (pixbuf == NULL) {
1004+ char *name;
1005+ if (gtk_widget_get_direction (GTK_WIDGET (window)) == GTK_TEXT_DIR_RTL)
1006+ name = g_strdup_printf ("%s-rtl", window->priv->icon_name);
1007+ else
1008+ name = g_strdup_printf ("%s-ltr", window->priv->icon_name);
1009+ pixbuf = load_pixbuf (window, name, icon_size);
1010+ g_free (name);
1011+ if (pixbuf == NULL)
1012+ return FALSE;
1013+ }
1014+
1015+ gdk_cairo_set_source_pixbuf (cr, pixbuf, _x0, _y0);
1016+ cairo_paint_with_alpha (cr, FG_ALPHA);
1017+
1018+ g_object_unref (pixbuf);
1019+
1020+ return TRUE;
1021+}
1022+
1023+static void
1024+draw_action_custom (GsdMediaKeysWindow *window,
1025+ cairo_t *cr)
1026+{
1027+ int window_width;
1028+ int window_height;
1029+ double icon_box_width;
1030+ double icon_box_height;
1031+ double icon_box_x0;
1032+ double icon_box_y0;
1033+ double bright_box_x0;
1034+ double bright_box_y0;
1035+ double bright_box_width;
1036+ double bright_box_height;
1037+ gboolean res;
1038+
1039+ gtk_window_get_size (GTK_WINDOW (window), &window_width, &window_height);
1040+
1041+ icon_box_width = round (window_width * 0.65);
1042+ icon_box_height = round (window_height * 0.65);
1043+ bright_box_width = round (icon_box_width);
1044+ bright_box_height = round (window_height * 0.05);
1045+
1046+ icon_box_x0 = (window_width - icon_box_width) / 2;
1047+ icon_box_y0 = (window_height - icon_box_height - bright_box_height) / 2;
1048+ bright_box_x0 = round (icon_box_x0);
1049+ bright_box_y0 = round (icon_box_height + icon_box_y0);
1050+
1051+#if 0
1052+ g_message ("icon box: w=%f h=%f _x0=%f _y0=%f",
1053+ icon_box_width,
1054+ icon_box_height,
1055+ icon_box_x0,
1056+ icon_box_y0);
1057+ g_message ("brightness box: w=%f h=%f _x0=%f _y0=%f",
1058+ bright_box_width,
1059+ bright_box_height,
1060+ bright_box_x0,
1061+ bright_box_y0);
1062+#endif
1063+
1064+ res = render_custom (window,
1065+ cr,
1066+ icon_box_x0, icon_box_y0,
1067+ icon_box_width, icon_box_height);
1068+ if (! res && g_strcmp0 (window->priv->icon_name, "media-eject") == 0) {
1069+ /* draw eject symbol */
1070+ draw_eject (cr,
1071+ icon_box_x0, icon_box_y0,
1072+ icon_box_width, icon_box_height);
1073+ }
1074+
1075+ if (window->priv->show_level != FALSE) {
1076+ /* draw volume meter */
1077+ draw_volume_boxes (window,
1078+ cr,
1079+ (double)window->priv->volume_level / 100.0,
1080+ bright_box_x0,
1081+ bright_box_y0,
1082+ bright_box_width,
1083+ bright_box_height);
1084+ }
1085+}
1086+
1087+static void
1088+draw_action (GsdMediaKeysWindow *window,
1089+ cairo_t *cr)
1090+{
1091+ switch (window->priv->action) {
1092+ case GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME:
1093+ draw_action_volume (window, cr);
1094+ break;
1095+ case GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM:
1096+ draw_action_custom (window, cr);
1097+ break;
1098+ default:
1099+ break;
1100+ }
1101+}
1102+
1103+static gboolean
1104+on_expose_event (GtkWidget *widget,
1105+ GdkEventExpose *event,
1106+ GsdMediaKeysWindow *window)
1107+{
1108+ cairo_t *context;
1109+ cairo_t *cr;
1110+ cairo_surface_t *surface;
1111+ int width;
1112+ int height;
1113+ GtkStyle *style;
1114+ GdkColor color;
1115+ double r, g, b;
1116+
1117+ context = gdk_cairo_create (gtk_widget_get_window (widget));
1118+
1119+ style = gtk_widget_get_style (widget);
1120+ cairo_set_operator (context, CAIRO_OPERATOR_SOURCE);
1121+ gtk_window_get_size (GTK_WINDOW (widget), &width, &height);
1122+
1123+ surface = cairo_surface_create_similar (cairo_get_target (context),
1124+ CAIRO_CONTENT_COLOR_ALPHA,
1125+ width,
1126+ height);
1127+
1128+ if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
1129+ goto done;
1130+ }
1131+
1132+ cr = cairo_create (surface);
1133+ if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
1134+ goto done;
1135+ }
1136+ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0);
1137+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
1138+ cairo_paint (cr);
1139+
1140+ /* draw a box */
1141+ rounded_rectangle (cr, 1.0, 0.5, 0.5, height / 10, width-1, height-1);
1142+ color_reverse (&style->bg[GTK_STATE_NORMAL], &color);
1143+ r = (float)color.red / 65535.0;
1144+ g = (float)color.green / 65535.0;
1145+ b = (float)color.blue / 65535.0;
1146+ cairo_set_source_rgba (cr, r, g, b, BG_ALPHA);
1147+ cairo_fill_preserve (cr);
1148+
1149+ color_reverse (&style->text_aa[GTK_STATE_NORMAL], &color);
1150+ r = (float)color.red / 65535.0;
1151+ g = (float)color.green / 65535.0;
1152+ b = (float)color.blue / 65535.0;
1153+ cairo_set_source_rgba (cr, r, g, b, BG_ALPHA / 2);
1154+ cairo_set_line_width (cr, 1);
1155+ cairo_stroke (cr);
1156+
1157+ /* draw action */
1158+ draw_action (window, cr);
1159+
1160+ cairo_destroy (cr);
1161+
1162+ /* Make sure we have a transparent background */
1163+ cairo_rectangle (context, 0, 0, width, height);
1164+ cairo_set_source_rgba (context, 0.0, 0.0, 0.0, 0.0);
1165+ cairo_fill (context);
1166+
1167+ cairo_set_source_surface (context, surface, 0, 0);
1168+ cairo_paint_with_alpha (context, window->priv->fade_out_alpha);
1169+
1170+ done:
1171+ if (surface != NULL) {
1172+ cairo_surface_destroy (surface);
1173+ }
1174+ cairo_destroy (context);
1175+
1176+ return FALSE;
1177+}
1178+
1179+static void
1180+gsd_media_keys_window_real_show (GtkWidget *widget)
1181+{
1182+ GsdMediaKeysWindow *window;
1183+
1184+ if (GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->show) {
1185+ GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->show (widget);
1186+ }
1187+
1188+ window = GSD_MEDIA_KEYS_WINDOW (widget);
1189+ remove_hide_timeout (window);
1190+ add_hide_timeout (window);
1191+}
1192+
1193+static void
1194+gsd_media_keys_window_real_hide (GtkWidget *widget)
1195+{
1196+ GsdMediaKeysWindow *window;
1197+
1198+ if (GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->hide) {
1199+ GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->hide (widget);
1200+ }
1201+
1202+ window = GSD_MEDIA_KEYS_WINDOW (widget);
1203+ remove_hide_timeout (window);
1204+}
1205+
1206+static void
1207+gsd_media_keys_window_real_realize (GtkWidget *widget)
1208+{
1209+ GdkColormap *colormap;
1210+ GtkAllocation allocation;
1211+ GdkBitmap *mask;
1212+ cairo_t *cr;
1213+
1214+ colormap = gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget));
1215+
1216+ if (colormap != NULL) {
1217+ gtk_widget_set_colormap (widget, colormap);
1218+ }
1219+
1220+ if (GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->realize) {
1221+ GTK_WIDGET_CLASS (gsd_media_keys_window_parent_class)->realize (widget);
1222+ }
1223+
1224+ gtk_widget_get_allocation (widget, &allocation);
1225+ mask = gdk_pixmap_new (gtk_widget_get_window (widget),
1226+ allocation.width,
1227+ allocation.height,
1228+ 1);
1229+ cr = gdk_cairo_create (mask);
1230+
1231+ cairo_set_source_rgba (cr, 1., 1., 1., 0.);
1232+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
1233+ cairo_paint (cr);
1234+
1235+ /* make the whole window ignore events */
1236+ gdk_window_input_shape_combine_mask (gtk_widget_get_window (widget), mask, 0, 0);
1237+ g_object_unref (mask);
1238+ cairo_destroy (cr);
1239+}
1240+
1241+static void
1242+gsd_media_keys_window_class_init (GsdMediaKeysWindowClass *klass)
1243+{
1244+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
1245+
1246+ widget_class->show = gsd_media_keys_window_real_show;
1247+ widget_class->hide = gsd_media_keys_window_real_hide;
1248+ widget_class->realize = gsd_media_keys_window_real_realize;
1249+
1250+ g_type_class_add_private (klass, sizeof (GsdMediaKeysWindowPrivate));
1251+}
1252+
1253+gboolean
1254+gsd_media_keys_window_is_valid (GsdMediaKeysWindow *window)
1255+{
1256+ GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (window));
1257+ return gdk_screen_is_composited (screen) == window->priv->is_composited;
1258+}
1259+
1260+static void
1261+gsd_media_keys_window_init (GsdMediaKeysWindow *window)
1262+{
1263+ GdkScreen *screen;
1264+
1265+ window->priv = GSD_MEDIA_KEYS_WINDOW_GET_PRIVATE (window);
1266+
1267+ screen = gtk_widget_get_screen (GTK_WIDGET (window));
1268+
1269+ window->priv->is_composited = gdk_screen_is_composited (screen);
1270+
1271+ if (window->priv->is_composited) {
1272+ gdouble scalew, scaleh, scale;
1273+ gint size;
1274+
1275+ gtk_window_set_decorated (GTK_WINDOW (window), FALSE);
1276+ gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE);
1277+
1278+ /* assume 130x130 on a 640x480 display and scale from there */
1279+ scalew = gdk_screen_get_width (screen) / 640.0;
1280+ scaleh = gdk_screen_get_height (screen) / 480.0;
1281+ scale = MIN (scalew, scaleh);
1282+ size = 130 * MAX (1, scale);
1283+
1284+ gtk_window_set_default_size (GTK_WINDOW (window), size, size);
1285+ g_signal_connect (window, "expose-event", G_CALLBACK (on_expose_event), window);
1286+
1287+ window->priv->fade_out_alpha = 1.0;
1288+ } else {
1289+ GtkBuilder *builder;
1290+ const gchar *objects[] = {"acme_frame", NULL};
1291+ GtkWidget *frame;
1292+
1293+ builder = gtk_builder_new ();
1294+ gtk_builder_add_objects_from_string (builder, acme_ui, acme_ui_length, (char **)objects, NULL);
1295+
1296+ window->priv->image = GTK_IMAGE (gtk_builder_get_object (builder, "acme_image"));
1297+ window->priv->progress = GTK_WIDGET (gtk_builder_get_object (builder, "acme_volume_progressbar"));
1298+ frame = GTK_WIDGET (gtk_builder_get_object (builder,
1299+ "acme_frame"));
1300+
1301+ if (frame != NULL) {
1302+ gtk_container_add (GTK_CONTAINER (window), frame);
1303+ gtk_widget_show_all (frame);
1304+ }
1305+
1306+ /* The builder needs to stay alive until the window
1307+ takes ownership of the frame (and its children) */
1308+ g_object_unref (builder);
1309+ }
1310+}
1311+
1312+GtkWidget *
1313+gsd_media_keys_window_new (void)
1314+{
1315+ GObject *object;
1316+
1317+ object = g_object_new (GSD_TYPE_MEDIA_KEYS_WINDOW,
1318+ "type", GTK_WINDOW_POPUP,
1319+ "type-hint", GDK_WINDOW_TYPE_HINT_NOTIFICATION,
1320+ "skip-taskbar-hint", TRUE,
1321+ "skip-pager-hint", TRUE,
1322+ "focus-on-map", FALSE,
1323+ NULL);
1324+
1325+ return GTK_WIDGET (object);
1326+}
1327
1328=== added file '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.h'
1329--- .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.h 1970-01-01 00:00:00 +0000
1330+++ .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/gsd-media-keys-window.h 2013-08-12 21:07:54 +0000
1331@@ -0,0 +1,71 @@
1332+/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*-
1333+ *
1334+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
1335+ *
1336+ * This program is free software; you can redistribute it and/or
1337+ * modify it under the terms of the GNU General Public License as
1338+ * published by the Free Software Foundation; either version 2 of the
1339+ * License, or (at your option) any later version.
1340+ *
1341+ * This program is distributed in the hope that it will be useful,
1342+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1343+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1344+ * General Public License for more details.
1345+ *
1346+ * You should have received a copy of the GNU General Public
1347+ * License along with this program; if not, write to the
1348+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1349+ * Boston, MA 02111-1307, USA.
1350+ *
1351+ */
1352+
1353+#ifndef GSD_MEDIA_KEYS_WINDOW_H
1354+#define GSD_MEDIA_KEYS_WINDOW_H
1355+
1356+#include <glib-object.h>
1357+#include <gtk/gtk.h>
1358+
1359+G_BEGIN_DECLS
1360+
1361+#define GSD_TYPE_MEDIA_KEYS_WINDOW (gsd_media_keys_window_get_type ())
1362+#define GSD_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSD_TYPE_MEDIA_KEYS_WINDOW, GsdMediaKeysWindow))
1363+#define GSD_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSD_TYPE_MEDIA_KEYS_WINDOW, GsdMediaKeysWindowClass))
1364+#define GSD_IS_MEDIA_KEYS_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSD_TYPE_MEDIA_KEYS_WINDOW))
1365+#define GSD_IS_MEDIA_KEYS_WINDOW_CLASS(klass) (G_TYPE_INSTANCE_GET_CLASS ((klass), GSD_TYPE_MEDIA_KEYS_WINDOW))
1366+
1367+typedef struct GsdMediaKeysWindow GsdMediaKeysWindow;
1368+typedef struct GsdMediaKeysWindowClass GsdMediaKeysWindowClass;
1369+typedef struct GsdMediaKeysWindowPrivate GsdMediaKeysWindowPrivate;
1370+
1371+struct GsdMediaKeysWindow {
1372+ GtkWindow parent;
1373+
1374+ GsdMediaKeysWindowPrivate *priv;
1375+};
1376+
1377+struct GsdMediaKeysWindowClass {
1378+ GtkWindowClass parent_class;
1379+};
1380+
1381+typedef enum {
1382+ GSD_MEDIA_KEYS_WINDOW_ACTION_VOLUME,
1383+ GSD_MEDIA_KEYS_WINDOW_ACTION_CUSTOM
1384+} GsdMediaKeysWindowAction;
1385+
1386+GType gsd_media_keys_window_get_type (void);
1387+
1388+GtkWidget * gsd_media_keys_window_new (void);
1389+void gsd_media_keys_window_set_action (GsdMediaKeysWindow *window,
1390+ GsdMediaKeysWindowAction action);
1391+void gsd_media_keys_window_set_action_custom (GsdMediaKeysWindow *window,
1392+ const char *icon_name,
1393+ gboolean show_level);
1394+void gsd_media_keys_window_set_volume_muted (GsdMediaKeysWindow *window,
1395+ gboolean muted);
1396+void gsd_media_keys_window_set_volume_level (GsdMediaKeysWindow *window,
1397+ int level);
1398+gboolean gsd_media_keys_window_is_valid (GsdMediaKeysWindow *window);
1399+
1400+G_END_DECLS
1401+
1402+#endif
1403
1404=== added file '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-backlight.c'
1405--- .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-backlight.c 1970-01-01 00:00:00 +0000
1406+++ .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-backlight.c 2013-08-12 21:07:54 +0000
1407@@ -0,0 +1,478 @@
1408+/*
1409+ * * Copyright (C) 2009-2011 Ali <aliov@xfce.org>
1410+ *
1411+ * Licensed under the GNU General Public License Version 2
1412+ *
1413+ * This program is free software; you can redistribute it and/or modify
1414+ * it under the terms of the GNU General Public License as published by
1415+ * the Free Software Foundation; either version 2 of the License, or
1416+ * (at your option) any later version.
1417+ *
1418+ * This program is distributed in the hope that it will be useful,
1419+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1420+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1421+ * GNU General Public License for more details.
1422+ *
1423+ * You should have received a copy of the GNU General Public License
1424+ * along with this program; if not, write to the Free Software
1425+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1426+ */
1427+
1428+#ifdef HAVE_CONFIG_H
1429+#include <config.h>
1430+#endif
1431+
1432+#include <stdio.h>
1433+#include <stdlib.h>
1434+#include <string.h>
1435+
1436+#include <math.h>
1437+
1438+#include <gtk/gtk.h>
1439+#include <libxfce4util/libxfce4util.h>
1440+
1441+#include "xfpm-backlight.h"
1442+#include "egg-idletime.h"
1443+#include "xfpm-notify.h"
1444+#include "xfpm-xfconf.h"
1445+#include "xfpm-power.h"
1446+#include "xfpm-config.h"
1447+#include "xfpm-button.h"
1448+#include "xfpm-brightness.h"
1449+#include "xfpm-debug.h"
1450+#include "xfpm-icons.h"
1451+
1452+#include "gsd-media-keys-window.h"
1453+
1454+static void xfpm_backlight_finalize (GObject *object);
1455+
1456+static void xfpm_backlight_create_popup (XfpmBacklight *backlight);
1457+
1458+#define ALARM_DISABLED 9
1459+#define BRIGHTNESS_POPUP_SIZE 180
1460+
1461+#define XFPM_BACKLIGHT_GET_PRIVATE(o) \
1462+(G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_BACKLIGHT, XfpmBacklightPrivate))
1463+
1464+struct XfpmBacklightPrivate
1465+{
1466+ XfpmBrightness *brightness;
1467+ XfpmPower *power;
1468+ EggIdletime *idle;
1469+ XfpmXfconf *conf;
1470+ XfpmButton *button;
1471+ XfpmNotify *notify;
1472+
1473+ GtkWidget *osd;
1474+ NotifyNotification *n;
1475+
1476+
1477+ gulong destroy_id;
1478+
1479+ gboolean has_hw;
1480+ gboolean on_battery;
1481+
1482+ glong last_level;
1483+ glong max_level;
1484+
1485+ gboolean dimmed;
1486+ gboolean block;
1487+};
1488+
1489+G_DEFINE_TYPE (XfpmBacklight, xfpm_backlight, G_TYPE_OBJECT)
1490+
1491+static void
1492+xfpm_backlight_dim_brightness (XfpmBacklight *backlight)
1493+{
1494+ gboolean ret;
1495+
1496+ if (xfpm_power_get_mode (backlight->priv->power) == XFPM_POWER_MODE_NORMAL )
1497+ {
1498+ glong dim_level;
1499+
1500+ g_object_get (G_OBJECT (backlight->priv->conf),
1501+ backlight->priv->on_battery ? BRIGHTNESS_LEVEL_ON_BATTERY : BRIGHTNESS_LEVEL_ON_AC, &dim_level,
1502+ NULL);
1503+
1504+ ret = xfpm_brightness_get_level (backlight->priv->brightness, &backlight->priv->last_level);
1505+
1506+ if ( !ret )
1507+ {
1508+ g_warning ("Unable to get current brightness level");
1509+ return;
1510+ }
1511+
1512+ dim_level = dim_level * backlight->priv->max_level / 100;
1513+
1514+ /**
1515+ * Only reduce if the current level is brighter than
1516+ * the configured dim_level
1517+ **/
1518+ if (backlight->priv->last_level > dim_level)
1519+ {
1520+ XFPM_DEBUG ("Current brightness level before dimming : %li, new %li", backlight->priv->last_level, dim_level);
1521+ backlight->priv->dimmed = xfpm_brightness_set_level (backlight->priv->brightness, dim_level);
1522+ }
1523+ }
1524+}
1525+
1526+static gboolean
1527+xfpm_backlight_destroy_popup (gpointer data)
1528+{
1529+ XfpmBacklight *backlight;
1530+
1531+ backlight = XFPM_BACKLIGHT (data);
1532+
1533+ if ( backlight->priv->osd )
1534+ {
1535+ gtk_widget_destroy (backlight->priv->osd);
1536+ backlight->priv->osd = NULL;
1537+ }
1538+
1539+ if ( backlight->priv->n )
1540+ {
1541+ g_object_unref (backlight->priv->n);
1542+ backlight->priv->n = NULL;
1543+ }
1544+
1545+ return FALSE;
1546+}
1547+
1548+static void
1549+xfpm_backlight_composited_changed_cb (XfpmBacklight *backlight)
1550+{
1551+ xfpm_backlight_destroy_popup (backlight);
1552+ xfpm_backlight_create_popup (backlight);
1553+}
1554+
1555+static void
1556+xfpm_backlight_show_notification (XfpmBacklight *backlight, gfloat value)
1557+{
1558+ gint i;
1559+
1560+ static const char *display_icon_name[] =
1561+ {
1562+ "notification-display-brightness-off",
1563+ "notification-display-brightness-low",
1564+ "notification-display-brightness-medium",
1565+ "notification-display-brightness-high",
1566+ "notification-display-brightness-full",
1567+ NULL
1568+ };
1569+
1570+ if ( backlight->priv->n == NULL )
1571+ {
1572+ backlight->priv->n = xfpm_notify_new_notification (backlight->priv->notify,
1573+ " ",
1574+ "",
1575+ NULL,
1576+ 0,
1577+ XFPM_NOTIFY_NORMAL,
1578+ NULL);
1579+ }
1580+
1581+ i = (gint)value / 25;
1582+
1583+ if ( i > 4 || i < 0 )
1584+ return;
1585+
1586+ notify_notification_set_hint_int32 (backlight->priv->n,
1587+ "value",
1588+ value);
1589+
1590+ notify_notification_set_hint_string (backlight->priv->n,
1591+ "x-canonical-private-synchronous",
1592+ "brightness");
1593+
1594+ notify_notification_update (backlight->priv->n,
1595+ " ",
1596+ "",
1597+ display_icon_name[i]);
1598+
1599+ notify_notification_show (backlight->priv->n, NULL);
1600+}
1601+
1602+static void
1603+xfpm_backlight_create_popup (XfpmBacklight *backlight)
1604+{
1605+ if ( backlight->priv->osd != NULL )
1606+ return;
1607+
1608+ backlight->priv->osd = gsd_media_keys_window_new ();
1609+ gsd_media_keys_window_set_action_custom (GSD_MEDIA_KEYS_WINDOW (backlight->priv->osd),
1610+ XFPM_DISPLAY_BRIGHTNESS_ICON,
1611+ TRUE);
1612+ gtk_window_set_position (GTK_WINDOW (backlight->priv->osd), GTK_WIN_POS_CENTER);
1613+
1614+ g_signal_connect_swapped (backlight->priv->osd, "composited-changed",
1615+ G_CALLBACK (xfpm_backlight_composited_changed_cb), backlight);
1616+
1617+}
1618+
1619+static void
1620+xfpm_backlight_show (XfpmBacklight *backlight, gint level)
1621+{
1622+ gfloat value;
1623+ gboolean sync_notify;
1624+ gboolean show_popup;
1625+
1626+ XFPM_DEBUG ("Level %u", level);
1627+
1628+ g_object_get (G_OBJECT (backlight->priv->conf),
1629+ SHOW_BRIGHTNESS_POPUP, &show_popup,
1630+ NULL);
1631+
1632+ if ( !show_popup )
1633+ goto out;
1634+
1635+ g_object_get (G_OBJECT (backlight->priv->notify),
1636+ "sync", &sync_notify,
1637+ NULL);
1638+
1639+ value = (gfloat) 100 * level / backlight->priv->max_level;
1640+
1641+ if ( !sync_notify ) /*Notification server doesn't support sync notifications*/
1642+ {
1643+ xfpm_backlight_create_popup (backlight);
1644+ gsd_media_keys_window_set_volume_level (GSD_MEDIA_KEYS_WINDOW (backlight->priv->osd),
1645+ round (value));
1646+ if ( !GTK_WIDGET_VISIBLE (backlight->priv->osd))
1647+ gtk_window_present (GTK_WINDOW (backlight->priv->osd));
1648+ }
1649+ else
1650+ {
1651+ xfpm_backlight_show_notification (backlight, value);
1652+ }
1653+
1654+ if ( backlight->priv->destroy_id != 0 )
1655+ {
1656+ g_source_remove (backlight->priv->destroy_id);
1657+ backlight->priv->destroy_id = 0;
1658+ }
1659+
1660+out:
1661+ /* Release the memory after 60 seconds */
1662+ backlight->priv->destroy_id = g_timeout_add_seconds (60, (GSourceFunc) xfpm_backlight_destroy_popup, backlight);
1663+}
1664+
1665+
1666+static void
1667+xfpm_backlight_alarm_timeout_cb (EggIdletime *idle, guint id, XfpmBacklight *backlight)
1668+{
1669+ backlight->priv->block = FALSE;
1670+
1671+ if ( id == TIMEOUT_BRIGHTNESS_ON_AC && !backlight->priv->on_battery)
1672+ xfpm_backlight_dim_brightness (backlight);
1673+ else if ( id == TIMEOUT_BRIGHTNESS_ON_BATTERY && backlight->priv->on_battery)
1674+ xfpm_backlight_dim_brightness (backlight);
1675+}
1676+
1677+static void
1678+xfpm_backlight_reset_cb (EggIdletime *idle, XfpmBacklight *backlight)
1679+{
1680+ if ( backlight->priv->dimmed)
1681+ {
1682+ if ( !backlight->priv->block)
1683+ {
1684+ XFPM_DEBUG ("Alarm reset, setting level to %li", backlight->priv->last_level);
1685+ xfpm_brightness_set_level (backlight->priv->brightness, backlight->priv->last_level);
1686+ }
1687+ backlight->priv->dimmed = FALSE;
1688+ }
1689+}
1690+
1691+static void
1692+xfpm_backlight_button_pressed_cb (XfpmButton *button, XfpmButtonKey type, XfpmBacklight *backlight)
1693+{
1694+ glong level;
1695+ gboolean ret = TRUE;
1696+
1697+ gboolean enable_brightness, show_popup;
1698+
1699+ g_object_get (G_OBJECT (backlight->priv->conf),
1700+ ENABLE_BRIGHTNESS_CONTROL, &enable_brightness,
1701+ SHOW_BRIGHTNESS_POPUP, &show_popup,
1702+ NULL);
1703+
1704+ if ( type == BUTTON_MON_BRIGHTNESS_UP )
1705+ {
1706+ backlight->priv->block = TRUE;
1707+ if ( enable_brightness )
1708+ ret = xfpm_brightness_up (backlight->priv->brightness, &level);
1709+ if ( ret && show_popup)
1710+ xfpm_backlight_show (backlight, level);
1711+ }
1712+ else if ( type == BUTTON_MON_BRIGHTNESS_DOWN )
1713+ {
1714+ backlight->priv->block = TRUE;
1715+ if ( enable_brightness )
1716+ ret = xfpm_brightness_down (backlight->priv->brightness, &level);
1717+ if ( ret && show_popup)
1718+ xfpm_backlight_show (backlight, level);
1719+ }
1720+}
1721+
1722+static void
1723+xfpm_backlight_brightness_on_ac_settings_changed (XfpmBacklight *backlight)
1724+{
1725+ guint timeout_on_ac;
1726+
1727+ g_object_get (G_OBJECT (backlight->priv->conf),
1728+ BRIGHTNESS_ON_AC, &timeout_on_ac,
1729+ NULL);
1730+
1731+ XFPM_DEBUG ("Alarm on ac timeout changed %u", timeout_on_ac);
1732+
1733+ if ( timeout_on_ac == ALARM_DISABLED )
1734+ {
1735+ egg_idletime_alarm_remove (backlight->priv->idle, TIMEOUT_BRIGHTNESS_ON_AC );
1736+ }
1737+ else
1738+ {
1739+ egg_idletime_alarm_set (backlight->priv->idle, TIMEOUT_BRIGHTNESS_ON_AC, timeout_on_ac * 1000);
1740+ }
1741+}
1742+
1743+static void
1744+xfpm_backlight_brightness_on_battery_settings_changed (XfpmBacklight *backlight)
1745+{
1746+ guint timeout_on_battery ;
1747+
1748+ g_object_get (G_OBJECT (backlight->priv->conf),
1749+ BRIGHTNESS_ON_BATTERY, &timeout_on_battery,
1750+ NULL);
1751+
1752+ XFPM_DEBUG ("Alarm on battery timeout changed %u", timeout_on_battery);
1753+
1754+ if ( timeout_on_battery == ALARM_DISABLED )
1755+ {
1756+ egg_idletime_alarm_remove (backlight->priv->idle, TIMEOUT_BRIGHTNESS_ON_BATTERY );
1757+ }
1758+ else
1759+ {
1760+ egg_idletime_alarm_set (backlight->priv->idle, TIMEOUT_BRIGHTNESS_ON_BATTERY, timeout_on_battery * 1000);
1761+ }
1762+}
1763+
1764+
1765+static void
1766+xfpm_backlight_set_timeouts (XfpmBacklight *backlight)
1767+{
1768+ xfpm_backlight_brightness_on_ac_settings_changed (backlight);
1769+ xfpm_backlight_brightness_on_battery_settings_changed (backlight);
1770+}
1771+
1772+static void
1773+xfpm_backlight_on_battery_changed_cb (XfpmPower *power, gboolean on_battery, XfpmBacklight *backlight)
1774+{
1775+ backlight->priv->on_battery = on_battery;
1776+}
1777+
1778+static void
1779+xfpm_backlight_class_init (XfpmBacklightClass *klass)
1780+{
1781+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
1782+
1783+ object_class->finalize = xfpm_backlight_finalize;
1784+
1785+ g_type_class_add_private (klass, sizeof (XfpmBacklightPrivate));
1786+}
1787+
1788+static void
1789+xfpm_backlight_init (XfpmBacklight *backlight)
1790+{
1791+ backlight->priv = XFPM_BACKLIGHT_GET_PRIVATE (backlight);
1792+
1793+ backlight->priv->brightness = xfpm_brightness_new ();
1794+ backlight->priv->has_hw = xfpm_brightness_setup (backlight->priv->brightness);
1795+
1796+ backlight->priv->osd = NULL;
1797+ backlight->priv->notify = NULL;
1798+ backlight->priv->idle = NULL;
1799+ backlight->priv->conf = NULL;
1800+ backlight->priv->button = NULL;
1801+ backlight->priv->power = NULL;
1802+ backlight->priv->dimmed = FALSE;
1803+ backlight->priv->block = FALSE;
1804+ backlight->priv->destroy_id = 0;
1805+
1806+ if ( !backlight->priv->has_hw )
1807+ {
1808+ g_object_unref (backlight->priv->brightness);
1809+ backlight->priv->brightness = NULL;
1810+ }
1811+ else
1812+ {
1813+ backlight->priv->idle = egg_idletime_new ();
1814+ backlight->priv->conf = xfpm_xfconf_new ();
1815+ backlight->priv->button = xfpm_button_new ();
1816+ backlight->priv->power = xfpm_power_get ();
1817+ backlight->priv->notify = xfpm_notify_new ();
1818+ backlight->priv->max_level = xfpm_brightness_get_max_level (backlight->priv->brightness);
1819+ g_signal_connect (backlight->priv->idle, "alarm-expired",
1820+ G_CALLBACK (xfpm_backlight_alarm_timeout_cb), backlight);
1821+
1822+ g_signal_connect (backlight->priv->idle, "reset",
1823+ G_CALLBACK(xfpm_backlight_reset_cb), backlight);
1824+
1825+ g_signal_connect (backlight->priv->button, "button-pressed",
1826+ G_CALLBACK (xfpm_backlight_button_pressed_cb), backlight);
1827+
1828+ g_signal_connect_swapped (backlight->priv->conf, "notify::" BRIGHTNESS_ON_AC,
1829+ G_CALLBACK (xfpm_backlight_brightness_on_ac_settings_changed), backlight);
1830+
1831+ g_signal_connect_swapped (backlight->priv->conf, "notify::" BRIGHTNESS_ON_BATTERY,
1832+ G_CALLBACK (xfpm_backlight_brightness_on_battery_settings_changed), backlight);
1833+
1834+ g_signal_connect (backlight->priv->power, "on-battery-changed",
1835+ G_CALLBACK (xfpm_backlight_on_battery_changed_cb), backlight);
1836+ g_object_get (G_OBJECT (backlight->priv->power),
1837+ "on-battery", &backlight->priv->on_battery,
1838+ NULL);
1839+ xfpm_brightness_get_level (backlight->priv->brightness, &backlight->priv->last_level);
1840+ xfpm_backlight_set_timeouts (backlight);
1841+ }
1842+}
1843+
1844+static void
1845+xfpm_backlight_finalize (GObject *object)
1846+{
1847+ XfpmBacklight *backlight;
1848+
1849+ backlight = XFPM_BACKLIGHT (object);
1850+
1851+ xfpm_backlight_destroy_popup (backlight);
1852+
1853+ if ( backlight->priv->brightness )
1854+ g_object_unref (backlight->priv->brightness);
1855+
1856+ if ( backlight->priv->idle )
1857+ g_object_unref (backlight->priv->idle);
1858+
1859+ if ( backlight->priv->conf )
1860+ g_object_unref (backlight->priv->conf);
1861+
1862+ if ( backlight->priv->button )
1863+ g_object_unref (backlight->priv->button);
1864+
1865+ if ( backlight->priv->power )
1866+ g_object_unref (backlight->priv->power);
1867+
1868+ if ( backlight->priv->notify)
1869+ g_object_unref (backlight->priv->notify);
1870+
1871+ G_OBJECT_CLASS (xfpm_backlight_parent_class)->finalize (object);
1872+}
1873+
1874+XfpmBacklight *
1875+xfpm_backlight_new (void)
1876+{
1877+ XfpmBacklight *backlight = NULL;
1878+ backlight = g_object_new (XFPM_TYPE_BACKLIGHT, NULL);
1879+ return backlight;
1880+}
1881+
1882+gboolean xfpm_backlight_has_hw (XfpmBacklight *backlight)
1883+{
1884+ return backlight->priv->has_hw;
1885+}
1886
1887=== added file '.pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-notify.c'
1888--- .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-notify.c 1970-01-01 00:00:00 +0000
1889+++ .pc/01_Remove_custom_OSD_brightness_popup,_use_libnotify_instead.patch/src/xfpm-notify.c 2013-08-12 21:07:54 +0000
1890@@ -0,0 +1,409 @@
1891+/*
1892+ * * Copyright (C) 2008-2011 Ali <aliov@xfce.org>
1893+ *
1894+ * Licensed under the GNU General Public License Version 2
1895+ *
1896+ * This program is free software; you can redistribute it and/or modify
1897+ * it under the terms of the GNU General Public License as published by
1898+ * the Free Software Foundation; either version 2 of the License, or
1899+ * (at your option) any later version.
1900+ *
1901+ * This program is distributed in the hope that it will be useful,
1902+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1903+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1904+ * GNU General Public License for more details.
1905+ *
1906+ * You should have received a copy of the GNU General Public License
1907+ * along with this program; if not, write to the Free Software
1908+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1909+ */
1910+
1911+#ifdef HAVE_CONFIG_H
1912+#include <config.h>
1913+#endif
1914+
1915+#include <stdio.h>
1916+
1917+#ifdef HAVE_STDLIB_H
1918+#include <stdlib.h>
1919+#endif
1920+
1921+#ifdef HAVE_STRING_H
1922+#include <string.h>
1923+#endif
1924+
1925+#ifdef HAVE_ERRNO_H
1926+#include <errno.h>
1927+#endif
1928+
1929+#include <gtk/gtk.h>
1930+
1931+#include <libxfce4util/libxfce4util.h>
1932+
1933+#include <libnotify/notify.h>
1934+
1935+#include "xfpm-common.h"
1936+#include "xfpm-notify.h"
1937+#include "xfpm-dbus-monitor.h"
1938+
1939+static void xfpm_notify_finalize (GObject *object);
1940+
1941+static NotifyNotification * xfpm_notify_new_notification_internal (const gchar *title,
1942+ const gchar *message,
1943+ const gchar *icon_name,
1944+ guint timeout,
1945+ XfpmNotifyUrgency urgency,
1946+ GtkStatusIcon *icon) G_GNUC_MALLOC;
1947+
1948+#define XFPM_NOTIFY_GET_PRIVATE(o) \
1949+(G_TYPE_INSTANCE_GET_PRIVATE((o), XFPM_TYPE_NOTIFY, XfpmNotifyPrivate))
1950+
1951+struct XfpmNotifyPrivate
1952+{
1953+ XfpmDBusMonitor *monitor;
1954+
1955+ NotifyNotification *notification;
1956+ NotifyNotification *critical;
1957+
1958+ gulong critical_id;
1959+ gulong notify_id;
1960+
1961+ gboolean supports_actions;
1962+ gboolean supports_sync; /*For x-canonical-private-synchronous */
1963+};
1964+
1965+enum
1966+{
1967+ PROP_0,
1968+ PROP_ACTIONS,
1969+ PROP_SYNC
1970+};
1971+
1972+G_DEFINE_TYPE(XfpmNotify, xfpm_notify, G_TYPE_OBJECT)
1973+
1974+static void
1975+xfpm_notify_get_server_caps (XfpmNotify *notify)
1976+{
1977+ GList *caps = NULL;
1978+ notify->priv->supports_actions = FALSE;
1979+ notify->priv->supports_sync = FALSE;
1980+
1981+ caps = notify_get_server_caps ();
1982+
1983+ if (caps != NULL)
1984+ {
1985+ if (g_list_find_custom (caps, "x-canonical-private-synchronous", (GCompareFunc) g_strcmp0) != NULL)
1986+ notify->priv->supports_sync = TRUE;
1987+
1988+ if (g_list_find_custom (caps, "actions", (GCompareFunc) g_strcmp0) != NULL)
1989+ notify->priv->supports_actions = TRUE;
1990+
1991+ g_list_foreach(caps, (GFunc)g_free, NULL);
1992+ g_list_free(caps);
1993+ }
1994+}
1995+
1996+static void
1997+xfpm_notify_check_server (XfpmDBusMonitor *monitor,
1998+ gchar *service_name,
1999+ gboolean connected,
2000+ gboolean on_session,
2001+ XfpmNotify *notify)
2002+{
2003+ if ( !g_strcmp0 (service_name, "org.freedesktop.Notifications") && on_session && connected )
2004+ xfpm_notify_get_server_caps (notify);
2005+}
2006+
2007+static void xfpm_notify_get_property (GObject *object,
2008+ guint prop_id,
2009+ GValue *value,
2010+ GParamSpec *pspec)
2011+{
2012+ XfpmNotify *notify;
2013+
2014+ notify = XFPM_NOTIFY (object);
2015+
2016+ switch (prop_id)
2017+ {
2018+ case PROP_ACTIONS:
2019+ g_value_set_boolean (value, notify->priv->supports_actions);
2020+ break;
2021+ case PROP_SYNC:
2022+ g_value_set_boolean (value, notify->priv->supports_sync);
2023+ break;
2024+ default:
2025+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2026+ break;
2027+ }
2028+}
2029+
2030+static void
2031+xfpm_notify_class_init (XfpmNotifyClass *klass)
2032+{
2033+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
2034+
2035+ object_class->finalize = xfpm_notify_finalize;
2036+ object_class->get_property = xfpm_notify_get_property;
2037+
2038+ g_object_class_install_property (object_class,
2039+ PROP_ACTIONS,
2040+ g_param_spec_boolean ("actions",
2041+ NULL, NULL,
2042+ FALSE,
2043+ G_PARAM_READABLE));
2044+
2045+ g_object_class_install_property (object_class,
2046+ PROP_SYNC,
2047+ g_param_spec_boolean ("sync",
2048+ NULL, NULL,
2049+ FALSE,
2050+ G_PARAM_READABLE));
2051+
2052+ g_type_class_add_private (klass, sizeof (XfpmNotifyPrivate));
2053+}
2054+
2055+static void
2056+xfpm_notify_init (XfpmNotify *notify)
2057+{
2058+ notify->priv = XFPM_NOTIFY_GET_PRIVATE (notify);
2059+
2060+ notify->priv->notification = NULL;
2061+ notify->priv->critical = NULL;
2062+
2063+ notify->priv->critical_id = 0;
2064+ notify->priv->notify_id = 0;
2065+
2066+ notify->priv->monitor = xfpm_dbus_monitor_new ();
2067+ xfpm_dbus_monitor_add_service (notify->priv->monitor, DBUS_BUS_SESSION, "org.freedesktop.Notifications");
2068+ g_signal_connect (notify->priv->monitor, "service-connection-changed",
2069+ G_CALLBACK (xfpm_notify_check_server), notify);
2070+
2071+ xfpm_notify_get_server_caps (notify);
2072+}
2073+
2074+static void
2075+xfpm_notify_finalize (GObject *object)
2076+{
2077+ XfpmNotify *notify;
2078+
2079+ notify = XFPM_NOTIFY (object);
2080+
2081+ xfpm_notify_close_normal (notify);
2082+ xfpm_notify_close_critical (notify);
2083+
2084+ G_OBJECT_CLASS (xfpm_notify_parent_class)->finalize(object);
2085+}
2086+
2087+static void
2088+xfpm_notify_set_notification_icon (NotifyNotification *n, const gchar *icon_name )
2089+{
2090+ GdkPixbuf *pix = xfpm_icon_load (icon_name, 48);
2091+
2092+ if ( pix )
2093+ {
2094+ notify_notification_set_icon_from_pixbuf (n,
2095+ pix);
2096+ g_object_unref ( G_OBJECT(pix));
2097+ }
2098+
2099+}
2100+
2101+static NotifyNotification *
2102+xfpm_notify_new_notification_internal (const gchar *title, const gchar *message,
2103+ const gchar *icon_name, guint timeout,
2104+ XfpmNotifyUrgency urgency, GtkStatusIcon *icon)
2105+{
2106+ NotifyNotification *n;
2107+
2108+#ifdef NOTIFY_CHECK_VERSION
2109+#if NOTIFY_CHECK_VERSION (0, 7, 0)
2110+ n = notify_notification_new (title, message, NULL);
2111+#else
2112+ n = notify_notification_new (title, message, NULL, NULL);
2113+#endif
2114+#else
2115+ n = notify_notification_new (title, message, NULL, NULL);
2116+#endif
2117+
2118+
2119+ if ( icon_name )
2120+ xfpm_notify_set_notification_icon (n, icon_name);
2121+
2122+#ifdef NOTIFY_CHECK_VERSION
2123+#if !NOTIFY_CHECK_VERSION (0, 7, 0)
2124+ if ( icon )
2125+ notify_notification_attach_to_status_icon (n, icon);
2126+#endif
2127+#else
2128+ if ( icon )
2129+ notify_notification_attach_to_status_icon (n, icon);
2130+#endif
2131+
2132+ notify_notification_set_urgency (n, (NotifyUrgency)urgency);
2133+
2134+ if ( timeout != 0)
2135+ notify_notification_set_timeout (n, timeout);
2136+
2137+ return n;
2138+}
2139+
2140+static void
2141+xfpm_notify_closed_cb (NotifyNotification *n, XfpmNotify *notify)
2142+{
2143+ notify->priv->notification = NULL;
2144+ g_object_unref (G_OBJECT (n));
2145+}
2146+
2147+static void
2148+xfpm_notify_close_critical_cb (NotifyNotification *n, XfpmNotify *notify)
2149+{
2150+ notify->priv->critical = NULL;
2151+ g_object_unref (G_OBJECT (n));
2152+}
2153+
2154+static gboolean
2155+xfpm_notify_show (NotifyNotification *n)
2156+{
2157+ notify_notification_show (n, NULL);
2158+ return FALSE;
2159+}
2160+
2161+static void
2162+xfpm_notify_close_notification (XfpmNotify *notify )
2163+{
2164+ if (notify->priv->notify_id != 0)
2165+ {
2166+ g_source_remove (notify->priv->notify_id);
2167+ notify->priv->notify_id = 0;
2168+ }
2169+
2170+ if ( notify->priv->notification )
2171+ {
2172+ if (!notify_notification_close (notify->priv->notification, NULL))
2173+ g_warning ("Failed to close notification\n");
2174+
2175+ g_object_unref (G_OBJECT(notify->priv->notification) );
2176+ notify->priv->notification = NULL;
2177+ }
2178+}
2179+
2180+XfpmNotify *
2181+xfpm_notify_new (void)
2182+{
2183+ static gpointer xfpm_notify_object = NULL;
2184+
2185+ if ( xfpm_notify_object != NULL )
2186+ {
2187+ g_object_ref (xfpm_notify_object);
2188+ }
2189+ else
2190+ {
2191+ xfpm_notify_object = g_object_new (XFPM_TYPE_NOTIFY, NULL);
2192+ g_object_add_weak_pointer (xfpm_notify_object, &xfpm_notify_object);
2193+ }
2194+ return XFPM_NOTIFY (xfpm_notify_object);
2195+}
2196+
2197+void xfpm_notify_show_notification (XfpmNotify *notify, const gchar *title,
2198+ const gchar *text, const gchar *icon_name,
2199+ gint timeout, gboolean simple,
2200+ XfpmNotifyUrgency urgency, GtkStatusIcon *icon)
2201+{
2202+ NotifyNotification *n;
2203+
2204+ if ( !simple )
2205+ xfpm_notify_close_notification (notify);
2206+
2207+ n = xfpm_notify_new_notification_internal (title,
2208+ text, icon_name,
2209+ timeout, urgency,
2210+ icon);
2211+
2212+ xfpm_notify_present_notification (notify, n, simple);
2213+}
2214+
2215+NotifyNotification *xfpm_notify_new_notification (XfpmNotify *notify,
2216+ const gchar *title,
2217+ const gchar *text,
2218+ const gchar *icon_name,
2219+ guint timeout,
2220+ XfpmNotifyUrgency urgency,
2221+ GtkStatusIcon *icon)
2222+{
2223+ NotifyNotification *n = xfpm_notify_new_notification_internal (title,
2224+ text, icon_name,
2225+ timeout, urgency,
2226+ icon);
2227+ return n;
2228+}
2229+
2230+void xfpm_notify_add_action_to_notification (XfpmNotify *notify, NotifyNotification *n,
2231+ const gchar *id, const gchar *action_label,
2232+ NotifyActionCallback callback, gpointer data)
2233+{
2234+ g_return_if_fail (XFPM_IS_NOTIFY(notify));
2235+
2236+ notify_notification_add_action (n, id, action_label,
2237+ (NotifyActionCallback)callback,
2238+ data, NULL);
2239+
2240+}
2241+
2242+void xfpm_notify_present_notification (XfpmNotify *notify, NotifyNotification *n, gboolean simple)
2243+{
2244+ g_return_if_fail (XFPM_IS_NOTIFY(notify));
2245+
2246+ if ( !simple )
2247+ xfpm_notify_close_notification (notify);
2248+
2249+ if ( !simple )
2250+ {
2251+ g_signal_connect (G_OBJECT(n),"closed",
2252+ G_CALLBACK(xfpm_notify_closed_cb), notify);
2253+ notify->priv->notification = n;
2254+ }
2255+
2256+ notify->priv->notify_id = g_idle_add ((GSourceFunc) xfpm_notify_show, n);
2257+}
2258+
2259+void xfpm_notify_critical (XfpmNotify *notify, NotifyNotification *n)
2260+{
2261+ g_return_if_fail (XFPM_IS_NOTIFY (notify));
2262+
2263+ xfpm_notify_close_critical (notify);
2264+
2265+ notify->priv->critical = n;
2266+
2267+ g_signal_connect (G_OBJECT (n), "closed",
2268+ G_CALLBACK (xfpm_notify_close_critical_cb), notify);
2269+
2270+ notify->priv->critical_id = g_idle_add ((GSourceFunc) xfpm_notify_show, n);
2271+}
2272+
2273+void xfpm_notify_close_critical (XfpmNotify *notify)
2274+{
2275+ g_return_if_fail (XFPM_IS_NOTIFY (notify));
2276+
2277+
2278+ if (notify->priv->critical_id != 0)
2279+ {
2280+ g_source_remove (notify->priv->critical_id);
2281+ notify->priv->critical_id = 0;
2282+ }
2283+
2284+ if ( notify->priv->critical )
2285+ {
2286+ if (!notify_notification_close (notify->priv->critical, NULL))
2287+ g_warning ("Failed to close notification\n");
2288+
2289+ g_object_unref (G_OBJECT(notify->priv->critical) );
2290+ notify->priv->critical = NULL;
2291+ }
2292+}
2293+
2294+void xfpm_notify_close_normal (XfpmNotify *notify)
2295+{
2296+ g_return_if_fail (XFPM_IS_NOTIFY (notify));
2297+
2298+ xfpm_notify_close_notification (notify);
2299+}
2300
2301=== added file '.pc/02_translations-fix-invalid-format-strings.patch/.timestamp'
2302=== added directory '.pc/03_fix-insert-battery.patch'
2303=== added file '.pc/03_fix-insert-battery.patch/.timestamp'
2304=== added directory '.pc/03_fix-insert-battery.patch/src'
2305=== added file '.pc/03_fix-insert-battery.patch/src/xfpm-battery.c'
2306--- .pc/03_fix-insert-battery.patch/src/xfpm-battery.c 1970-01-01 00:00:00 +0000
2307+++ .pc/03_fix-insert-battery.patch/src/xfpm-battery.c 2013-08-12 21:07:54 +0000
2308@@ -0,0 +1,916 @@
2309+/*
2310+ * * Copyright (C) 2009-2011 Ali <aliov@xfce.org>
2311+ *
2312+ * Licensed under the GNU General Public License Version 2
2313+ *
2314+ * This program is free software; you can redistribute it and/or modify
2315+ * it under the terms of the GNU General Public License as published by
2316+ * the Free Software Foundation; either version 2 of the License, or
2317+ * (at your option) any later version.
2318+ *
2319+ * This program is distributed in the hope that it will be useful,
2320+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2321+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2322+ * GNU General Public License for more details.
2323+ *
2324+ * You should have received a copy of the GNU General Public License
2325+ * along with this program; if not, write to the Free Software
2326+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
2327+ */
2328+
2329+#ifdef HAVE_CONFIG_H
2330+#include <config.h>
2331+#endif
2332+
2333+#include <stdio.h>
2334+#include <stdlib.h>
2335+#include <string.h>
2336+
2337+#include <gtk/gtk.h>
2338+
2339+#include <libxfce4util/libxfce4util.h>
2340+
2341+#include "xfpm-battery.h"
2342+#include "xfpm-dbus.h"
2343+#include "xfpm-icons.h"
2344+#include "xfpm-xfconf.h"
2345+#include "xfpm-notify.h"
2346+#include "xfpm-config.h"
2347+#include "xfpm-button.h"
2348+#include "xfpm-enum-glib.h"
2349+#include "xfpm-enum-types.h"
2350+#include "xfpm-debug.h"
2351+#include "xfpm-power-common.h"
2352+#include "xfpm-common.h"
2353+
2354+static void xfpm_battery_finalize (GObject *object);
2355+
2356+#define XFPM_BATTERY_GET_PRIVATE(o) \
2357+(G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_BATTERY, XfpmBatteryPrivate))
2358+
2359+struct XfpmBatteryPrivate
2360+{
2361+ XfpmXfconf *conf;
2362+ XfpmNotify *notify;
2363+ XfpmButton *button;
2364+ DBusGProxy *proxy;
2365+ DBusGProxy *proxy_prop;
2366+
2367+ gchar *icon_prefix;
2368+
2369+ XfpmBatteryCharge charge;
2370+ XfpmDeviceState state;
2371+ XfpmDeviceType type;
2372+ gboolean ac_online;
2373+ gboolean present;
2374+ guint percentage;
2375+ gint64 time_to_full;
2376+ gint64 time_to_empty;
2377+
2378+ const gchar *battery_name;
2379+
2380+ gulong sig;
2381+ gulong sig_bt;
2382+
2383+ guint notify_idle;
2384+};
2385+
2386+enum
2387+{
2388+ PROP_0,
2389+ PROP_AC_ONLINE,
2390+ PROP_CHARGE_STATUS,
2391+ PROP_DEVICE_TYPE
2392+};
2393+
2394+enum
2395+{
2396+ BATTERY_CHARGE_CHANGED,
2397+ LAST_SIGNAL
2398+};
2399+
2400+static guint signals [LAST_SIGNAL] = { 0 };
2401+
2402+G_DEFINE_TYPE (XfpmBattery, xfpm_battery, GTK_TYPE_STATUS_ICON)
2403+
2404+static const gchar * G_GNUC_CONST
2405+xfpm_battery_get_icon_index (XfpmDeviceType type, guint percent)
2406+{
2407+ if (percent < 10)
2408+ {
2409+ return "000";
2410+ }
2411+ else if (percent < 30)
2412+ {
2413+ return ( (type == XFPM_DEVICE_TYPE_BATTERY || type == XFPM_DEVICE_TYPE_UPS) ? "020" : "030");
2414+ }
2415+ else if (percent < 50)
2416+ {
2417+ return ( (type == XFPM_DEVICE_TYPE_BATTERY || type == XFPM_DEVICE_TYPE_UPS ) ? "040" : "030");
2418+ }
2419+ else if (percent < 70)
2420+ {
2421+ return "060";
2422+ }
2423+ else if (percent < 90)
2424+ {
2425+ return ((type == XFPM_DEVICE_TYPE_BATTERY || type == XFPM_DEVICE_TYPE_UPS) ? "080" : "060");
2426+ }
2427+
2428+ return "100";
2429+}
2430+
2431+static void
2432+xfpm_battery_refresh_visible (XfpmBattery *battery)
2433+{
2434+ XfpmShowIcon show_icon;
2435+ gboolean visible = TRUE;
2436+
2437+ g_object_get (G_OBJECT (battery->priv->conf),
2438+ SHOW_TRAY_ICON_CFG, &show_icon,
2439+ NULL);
2440+
2441+ if ( show_icon == SHOW_ICON_ALWAYS )
2442+ visible = TRUE;
2443+ else if ( show_icon == NEVER_SHOW_ICON )
2444+ visible = FALSE;
2445+ else if ( show_icon == SHOW_ICON_WHEN_BATTERY_PRESENT )
2446+ {
2447+ if ( battery->priv->present )
2448+ visible = TRUE;
2449+ else visible = FALSE;
2450+ }
2451+ else if ( show_icon == SHOW_ICON_WHEN_BATTERY_CHARGING_DISCHARGING )
2452+ {
2453+ if ( battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
2454+ visible = FALSE;
2455+ else visible = TRUE;
2456+ }
2457+
2458+ XFPM_DEBUG_ENUM (show_icon, XFPM_TYPE_SHOW_ICON, "visible=%s", xfpm_bool_to_string (visible));
2459+
2460+ gtk_status_icon_set_visible (GTK_STATUS_ICON (battery), visible);
2461+}
2462+
2463+
2464+/*
2465+ * Taken from gpm
2466+ */
2467+static gchar *
2468+xfpm_battery_get_time_string (guint seconds)
2469+{
2470+ char* timestring = NULL;
2471+ gint hours;
2472+ gint minutes;
2473+
2474+ /* Add 0.5 to do rounding */
2475+ minutes = (int) ( ( seconds / 60.0 ) + 0.5 );
2476+
2477+ if (minutes == 0)
2478+ {
2479+ timestring = g_strdup (_("Unknown time"));
2480+ return timestring;
2481+ }
2482+
2483+ if (minutes < 60)
2484+ {
2485+ timestring = g_strdup_printf (ngettext ("%i minute",
2486+ "%i minutes",
2487+ minutes), minutes);
2488+ return timestring;
2489+ }
2490+
2491+ hours = minutes / 60;
2492+ minutes = minutes % 60;
2493+
2494+ if (minutes == 0)
2495+ timestring = g_strdup_printf (ngettext (
2496+ "%i hour",
2497+ "%i hours",
2498+ hours), hours);
2499+ else
2500+ /* TRANSLATOR: "%i %s %i %s" are "%i hours %i minutes"
2501+ * Swap order with "%2$s %2$i %1$s %1$i if needed */
2502+ timestring = g_strdup_printf (_("%i %s %i %s"),
2503+ hours, ngettext ("hour", "hours", hours),
2504+ minutes, ngettext ("minute", "minutes", minutes));
2505+ return timestring;
2506+}
2507+
2508+static gchar *
2509+xfpm_battery_get_message_from_battery_state (XfpmBattery *battery)
2510+{
2511+ gchar *msg = NULL;
2512+
2513+
2514+ if (battery->priv->type == XFPM_DEVICE_TYPE_BATTERY || battery->priv->type == XFPM_DEVICE_TYPE_UPS)
2515+ {
2516+ switch (battery->priv->state)
2517+ {
2518+ case XFPM_DEVICE_STATE_FULLY_CHARGED:
2519+ msg = g_strdup_printf (_("Your %s is fully charged"), battery->priv->battery_name);
2520+ break;
2521+ case XFPM_DEVICE_STATE_CHARGING:
2522+ msg = g_strdup_printf (_("Your %s is charging"), battery->priv->battery_name);
2523+
2524+ if ( battery->priv->time_to_full != 0 )
2525+ {
2526+ gchar *tmp, *est_time_str;
2527+ tmp = g_strdup (msg);
2528+ g_free (msg);
2529+
2530+ est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_full);
2531+
2532+ msg = g_strdup_printf (_("%s (%i%%)\n%s until is fully charged."), tmp, battery->priv->percentage, est_time_str);
2533+ g_free (est_time_str);
2534+ g_free (tmp);
2535+ }
2536+
2537+ break;
2538+ case XFPM_DEVICE_STATE_DISCHARGING:
2539+ if (battery->priv->ac_online)
2540+ msg = g_strdup_printf (_("Your %s is discharging"), battery->priv->battery_name);
2541+ else
2542+ msg = g_strdup_printf (_("System is running on %s power"), battery->priv->battery_name);
2543+
2544+ if ( battery->priv->time_to_empty != 0 )
2545+ {
2546+ gchar *tmp, *est_time_str;
2547+ tmp = g_strdup (msg);
2548+ g_free (msg);
2549+
2550+ est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_empty);
2551+
2552+ msg = g_strdup_printf (_("%s (%i%%)\nEstimated time left is %s."), tmp, battery->priv->percentage, est_time_str);
2553+ g_free (tmp);
2554+ g_free (est_time_str);
2555+ }
2556+ break;
2557+ case XFPM_DEVICE_STATE_EMPTY:
2558+ msg = g_strdup_printf (_("Your %s is empty"), battery->priv->battery_name);
2559+ break;
2560+ default:
2561+ break;
2562+ }
2563+
2564+ }
2565+ else if (battery->priv->type >= XFPM_DEVICE_TYPE_MONITOR)
2566+ {
2567+ switch (battery->priv->state)
2568+ {
2569+ case XFPM_DEVICE_STATE_FULLY_CHARGED:
2570+ msg = g_strdup_printf (_("Your %s is fully charged"), battery->priv->battery_name);
2571+ break;
2572+ case XFPM_DEVICE_STATE_CHARGING:
2573+ msg = g_strdup_printf (_("Your %s is charging"), battery->priv->battery_name);
2574+ break;
2575+ case XFPM_DEVICE_STATE_DISCHARGING:
2576+ msg = g_strdup_printf (_("Your %s is discharging"), battery->priv->battery_name);
2577+ break;
2578+ case XFPM_DEVICE_STATE_EMPTY:
2579+ msg = g_strdup_printf (_("Your %s is empty"), battery->priv->battery_name);
2580+ break;
2581+ default:
2582+ break;
2583+ }
2584+ }
2585+
2586+ return msg;
2587+}
2588+
2589+static void
2590+xfpm_battery_refresh_icon (XfpmBattery *battery)
2591+{
2592+ gchar icon_name[128];
2593+
2594+ XFPM_DEBUG ("Battery state %d", battery->priv->state);
2595+
2596+ if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY ||
2597+ battery->priv->type == XFPM_DEVICE_TYPE_UPS )
2598+ {
2599+ if (!battery->priv->present)
2600+ {
2601+ g_snprintf (icon_name, 128, "%s%s", battery->priv->icon_prefix, "missing");
2602+ }
2603+ else if (battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
2604+ {
2605+ g_snprintf (icon_name, 128, "%s%s", battery->priv->icon_prefix, battery->priv->ac_online ? "charged" : "100");
2606+ }
2607+ else if ( battery->priv->state == XFPM_DEVICE_STATE_CHARGING ||
2608+ battery->priv->state == XFPM_DEVICE_STATE_PENDING_CHARGING)
2609+ {
2610+ g_snprintf (icon_name, 128, "%s%s-%s",
2611+ battery->priv->icon_prefix,
2612+ xfpm_battery_get_icon_index (battery->priv->type, battery->priv->percentage),
2613+ "charging");
2614+ }
2615+ else if ( battery->priv->state == XFPM_DEVICE_STATE_DISCHARGING ||
2616+ battery->priv->state == XFPM_DEVICE_STATE_PENDING_DISCHARGING)
2617+ {
2618+ g_snprintf (icon_name, 128, "%s%s",
2619+ battery->priv->icon_prefix,
2620+ xfpm_battery_get_icon_index (battery->priv->type, battery->priv->percentage));
2621+ }
2622+ else if ( battery->priv->state == XFPM_DEVICE_STATE_EMPTY)
2623+ {
2624+ g_snprintf (icon_name, 128, "%s%s", battery->priv->icon_prefix, battery->priv->ac_online ? "000-charging" : "000");
2625+ }
2626+ }
2627+ else
2628+ {
2629+ if ( !battery->priv->present || battery->priv->state == XFPM_DEVICE_STATE_EMPTY )
2630+ {
2631+ g_snprintf (icon_name, 128, "%s-000", battery->priv->icon_prefix);
2632+ }
2633+ else if ( battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
2634+ {
2635+ g_snprintf (icon_name, 128, "%s-100", battery->priv->icon_prefix);
2636+ }
2637+ else if ( battery->priv->state == XFPM_DEVICE_STATE_DISCHARGING )
2638+ {
2639+ g_snprintf (icon_name, 128, "%s-%s",
2640+ battery->priv->icon_prefix,
2641+ xfpm_battery_get_icon_index (battery->priv->type, battery->priv->percentage));
2642+ }
2643+ }
2644+
2645+ gtk_status_icon_set_from_icon_name (GTK_STATUS_ICON (battery), icon_name);
2646+}
2647+
2648+static void
2649+xfpm_battery_notify (XfpmBattery *battery)
2650+{
2651+ gchar *message = NULL;
2652+
2653+ message = xfpm_battery_get_message_from_battery_state (battery);
2654+
2655+ if ( !message )
2656+ return;
2657+
2658+ xfpm_notify_show_notification (battery->priv->notify,
2659+ _("Power Manager"),
2660+ message,
2661+ gtk_status_icon_get_icon_name (GTK_STATUS_ICON (battery)),
2662+ 8000,
2663+ FALSE,
2664+ XFPM_NOTIFY_NORMAL,
2665+ GTK_STATUS_ICON (battery));
2666+
2667+ g_free (message);
2668+}
2669+
2670+static gboolean
2671+xfpm_battery_notify_idle (gpointer data)
2672+{
2673+ XfpmBattery *battery = XFPM_BATTERY (data);
2674+
2675+ xfpm_battery_notify (battery);
2676+ battery->priv->notify_idle = 0;
2677+
2678+ return FALSE;
2679+}
2680+
2681+static void
2682+xfpm_battery_notify_state (XfpmBattery *battery)
2683+{
2684+ gboolean notify;
2685+ static gboolean starting_up = TRUE;
2686+
2687+ if ( !gtk_status_icon_get_visible (GTK_STATUS_ICON (battery)) )
2688+ return;
2689+
2690+ if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY ||
2691+ battery->priv->type == XFPM_DEVICE_TYPE_UPS )
2692+ {
2693+ if ( starting_up )
2694+ {
2695+ starting_up = FALSE;
2696+ return;
2697+ }
2698+
2699+ g_object_get (G_OBJECT (battery->priv->conf),
2700+ GENERAL_NOTIFICATION_CFG, &notify,
2701+ NULL);
2702+
2703+ if ( notify )
2704+ {
2705+ if (battery->priv->notify_idle == 0)
2706+ battery->priv->notify_idle = g_idle_add (xfpm_battery_notify_idle, battery);
2707+ }
2708+ }
2709+}
2710+
2711+/*
2712+ * Refresh tooltip function for UPS and battery device only.
2713+ */
2714+static void
2715+xfpm_battery_set_tooltip_primary (XfpmBattery *battery, GtkTooltip *tooltip)
2716+{
2717+ gchar *tip;
2718+ gchar *est_time_str = NULL;
2719+ gchar *power_status = NULL;
2720+
2721+ power_status = g_strdup_printf (battery->priv->ac_online ? _("Adaptor is online") : _("System is running on battery power"));
2722+
2723+ if ( battery->priv->state == XFPM_DEVICE_STATE_FULLY_CHARGED )
2724+ {
2725+ if ( battery->priv->time_to_empty > 0 )
2726+ {
2727+ est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_empty);
2728+ tip = g_strdup_printf (_("%s\nYour %s is fully charged (%i%%).\nProvides %s runtime"),
2729+ power_status,
2730+ battery->priv->battery_name,
2731+ battery->priv->percentage,
2732+ est_time_str);
2733+ g_free (est_time_str);
2734+ }
2735+ else
2736+ {
2737+ tip = g_strdup_printf (_("%s\nYour %s is fully charged (%i%%)."),
2738+ power_status,
2739+ battery->priv->battery_name,
2740+ battery->priv->percentage);
2741+ }
2742+ }
2743+ else if ( battery->priv->state == XFPM_DEVICE_STATE_CHARGING )
2744+ {
2745+ if ( battery->priv->time_to_full != 0 )
2746+ {
2747+ est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_full);
2748+ tip = g_strdup_printf (_("%s\nYour %s is charging (%i%%)\n%s until is fully charged."),
2749+ power_status,
2750+ battery->priv->battery_name,
2751+ battery->priv->percentage,
2752+ est_time_str);
2753+ g_free (est_time_str);
2754+ }
2755+ else
2756+ {
2757+ tip = g_strdup_printf (_("%s\nYour %s is charging (%i%%)."),
2758+ power_status,
2759+ battery->priv->battery_name,
2760+ battery->priv->percentage);
2761+ }
2762+ }
2763+ else if ( battery->priv->state == XFPM_DEVICE_STATE_DISCHARGING )
2764+ {
2765+ if ( battery->priv->time_to_empty != 0 )
2766+ {
2767+ est_time_str = xfpm_battery_get_time_string (battery->priv->time_to_empty);
2768+ tip = g_strdup_printf (_("%s\nYour %s is discharging (%i%%)\nEstimated time left is %s."),
2769+ power_status,
2770+ battery->priv->battery_name,
2771+ battery->priv->percentage,
2772+ est_time_str);
2773+ g_free (est_time_str);
2774+ }
2775+ else
2776+ {
2777+ tip = g_strdup_printf (_("%s\nYour %s is discharging (%i%%)."),
2778+ power_status,
2779+ battery->priv->battery_name,
2780+ battery->priv->percentage);
2781+ }
2782+
2783+ }
2784+ else if ( battery->priv->state == XFPM_DEVICE_STATE_PENDING_CHARGING )
2785+ {
2786+ tip = g_strdup_printf (_("%s\n%s waiting to discharge (%i%%)."), power_status, battery->priv->battery_name, battery->priv->percentage);
2787+ }
2788+ else if ( battery->priv->state == XFPM_DEVICE_STATE_PENDING_DISCHARGING )
2789+ {
2790+ tip = g_strdup_printf (_("%s\n%s waiting to charge (%i%%)."), power_status, battery->priv->battery_name, battery->priv->percentage);
2791+ }
2792+ else if ( battery->priv->state == XFPM_DEVICE_STATE_EMPTY )
2793+ {
2794+ tip = g_strdup_printf (_("%s\nYour %s is empty"), power_status, battery->priv->battery_name);
2795+ }
2796+
2797+ gtk_tooltip_set_text (tooltip, tip);
2798+ g_free (power_status);
2799+ g_free (tip);
2800+}
2801+
2802+static void
2803+xfpm_battery_check_charge (XfpmBattery *battery)
2804+{
2805+ XfpmBatteryCharge charge;
2806+ guint critical_level, low_level;
2807+
2808+ g_object_get (G_OBJECT (battery->priv->conf),
2809+ CRITICAL_POWER_LEVEL, &critical_level,
2810+ NULL);
2811+
2812+ low_level = critical_level + 10;
2813+
2814+ if ( battery->priv->percentage > low_level )
2815+ charge = XFPM_BATTERY_CHARGE_OK;
2816+ else if ( battery->priv->percentage <= low_level && battery->priv->percentage > critical_level )
2817+ charge = XFPM_BATTERY_CHARGE_LOW;
2818+ else if ( battery->priv->percentage <= critical_level )
2819+ charge = XFPM_BATTERY_CHARGE_CRITICAL;
2820+
2821+ if ( charge != battery->priv->charge)
2822+ {
2823+ battery->priv->charge = charge;
2824+ /*
2825+ * only emit signal when when battery charge changes from ok->low->critical
2826+ * and not the other way round.
2827+ */
2828+ if ( battery->priv->charge != XFPM_BATTERY_CHARGE_CRITICAL || charge != XFPM_BATTERY_CHARGE_LOW )
2829+ g_signal_emit (G_OBJECT (battery), signals [BATTERY_CHARGE_CHANGED], 0);
2830+ }
2831+}
2832+
2833+static void
2834+xfpm_battery_refresh (XfpmBattery *battery, GHashTable *props)
2835+{
2836+ GValue *value;
2837+ guint state;
2838+
2839+ value = g_hash_table_lookup (props, "IsPresent");
2840+
2841+ if ( value == NULL )
2842+ {
2843+ g_warning ("No 'IsPresent' property found");
2844+ goto out;
2845+ }
2846+
2847+ battery->priv->present = g_value_get_boolean (value);
2848+
2849+ value = g_hash_table_lookup (props, "State");
2850+
2851+ if ( value == NULL )
2852+ {
2853+ g_warning ("No 'State' property found");
2854+ }
2855+
2856+ state = g_value_get_uint (value);
2857+ if ( state != battery->priv->state )
2858+ {
2859+ battery->priv->state = state;
2860+ xfpm_battery_refresh_visible (battery);
2861+ xfpm_battery_notify_state (battery);
2862+ }
2863+
2864+ value = g_hash_table_lookup (props, "Percentage");
2865+
2866+ if ( value == NULL )
2867+ {
2868+ g_warning ("No 'Percentage' property found on battery device");
2869+ goto out;
2870+ }
2871+
2872+ battery->priv->percentage = (guint) g_value_get_double (value);
2873+
2874+ xfpm_battery_check_charge (battery);
2875+
2876+ xfpm_battery_refresh_icon (battery);
2877+
2878+ if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY ||
2879+ battery->priv->type == XFPM_DEVICE_TYPE_UPS )
2880+ {
2881+ value = g_hash_table_lookup (props, "TimeToEmpty");
2882+
2883+ if ( value == NULL )
2884+ {
2885+ g_warning ("No 'TimeToEmpty' property found on battery device");
2886+ goto out;
2887+ }
2888+
2889+ battery->priv->time_to_empty = g_value_get_int64 (value);
2890+
2891+ value = g_hash_table_lookup (props, "TimeToFull");
2892+
2893+ if ( value == NULL )
2894+ {
2895+ g_warning ("No 'TimeToFull' property found on battery device");
2896+ goto out;
2897+ }
2898+
2899+ battery->priv->time_to_full = g_value_get_int64 (value);
2900+ }
2901+
2902+ out:
2903+ g_hash_table_destroy (props);
2904+}
2905+
2906+static void
2907+xfpm_battery_button_pressed_cb (XfpmButton *button, XfpmButtonKey type, XfpmBattery *battery)
2908+{
2909+ if (type == BUTTON_BATTERY)
2910+ xfpm_battery_notify (battery);
2911+}
2912+
2913+static void
2914+xfpm_battery_changed_cb (DBusGProxy *proxy, XfpmBattery *battery)
2915+{
2916+ GHashTable *props;
2917+
2918+ props = xfpm_power_get_interface_properties (battery->priv->proxy_prop,
2919+ UPOWER_IFACE_DEVICE);
2920+
2921+ if ( props )
2922+ xfpm_battery_refresh (battery, props);
2923+}
2924+
2925+static gboolean
2926+xfpm_battery_query_tooltip (GtkStatusIcon *icon,
2927+ gint x,
2928+ gint y,
2929+ gboolean keyboard_mode,
2930+ GtkTooltip *tooltip)
2931+{
2932+ XfpmBattery *battery;
2933+
2934+ battery = XFPM_BATTERY (icon);
2935+
2936+ if ( battery->priv->type == XFPM_DEVICE_TYPE_BATTERY ||
2937+ battery->priv->type == XFPM_DEVICE_TYPE_UPS )
2938+ {
2939+ xfpm_battery_set_tooltip_primary (battery, tooltip);
2940+ return TRUE;
2941+ }
2942+
2943+ return FALSE;
2944+}
2945+
2946+static void
2947+xfpm_battery_tray_icon_settings_changed (GObject *obj, GParamSpec *spec, XfpmBattery *battery)
2948+{
2949+ xfpm_battery_refresh_visible (battery);
2950+}
2951+
2952+static void xfpm_battery_get_property (GObject *object,
2953+ guint prop_id,
2954+ GValue *value,
2955+ GParamSpec *pspec)
2956+{
2957+ XfpmBattery *battery;
2958+
2959+ battery = XFPM_BATTERY (object);
2960+
2961+ switch (prop_id)
2962+ {
2963+ case PROP_AC_ONLINE:
2964+ g_value_set_boolean (value, battery->priv->ac_online);
2965+ break;
2966+ case PROP_DEVICE_TYPE:
2967+ g_value_set_enum (value, battery->priv->type);
2968+ break;
2969+ case PROP_CHARGE_STATUS:
2970+ g_value_set_enum (value, battery->priv->charge);
2971+ break;
2972+ default:
2973+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2974+ break;
2975+ }
2976+}
2977+
2978+static void xfpm_battery_set_property (GObject *object,
2979+ guint prop_id,
2980+ const GValue *value,
2981+ GParamSpec *pspec)
2982+{
2983+ XfpmBattery *battery;
2984+
2985+ battery = XFPM_BATTERY (object);
2986+
2987+ switch (prop_id)
2988+ {
2989+ case PROP_AC_ONLINE:
2990+ battery->priv->ac_online = g_value_get_boolean (value);
2991+ xfpm_battery_refresh_icon (battery);
2992+ break;
2993+ default:
2994+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2995+ break;
2996+ }
2997+}
2998+
2999+
3000+static void
3001+xfpm_battery_class_init (XfpmBatteryClass *klass)
3002+{
3003+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
3004+ GtkStatusIconClass *status_icon_class = GTK_STATUS_ICON_CLASS (klass);
3005+
3006+ object_class->finalize = xfpm_battery_finalize;
3007+ object_class->get_property = xfpm_battery_get_property;
3008+ object_class->set_property = xfpm_battery_set_property;
3009+
3010+ status_icon_class->query_tooltip = xfpm_battery_query_tooltip;
3011+
3012+ signals [BATTERY_CHARGE_CHANGED] =
3013+ g_signal_new ("battery-charge-changed",
3014+ XFPM_TYPE_BATTERY,
3015+ G_SIGNAL_RUN_LAST,
3016+ G_STRUCT_OFFSET(XfpmBatteryClass, battery_charge_changed),
3017+ NULL, NULL,
3018+ g_cclosure_marshal_VOID__VOID,
3019+ G_TYPE_NONE, 0, G_TYPE_NONE);
3020+
3021+ g_object_class_install_property (object_class,
3022+ PROP_AC_ONLINE,
3023+ g_param_spec_boolean("ac-online",
3024+ NULL, NULL,
3025+ FALSE,
3026+ G_PARAM_READWRITE));
3027+
3028+ g_object_class_install_property (object_class,
3029+ PROP_DEVICE_TYPE,
3030+ g_param_spec_enum ("device-type",
3031+ NULL, NULL,
3032+ XFPM_TYPE_DEVICE_TYPE,
3033+ XFPM_DEVICE_TYPE_UNKNOWN,
3034+ G_PARAM_READABLE));
3035+
3036+ g_object_class_install_property (object_class,
3037+ PROP_CHARGE_STATUS,
3038+ g_param_spec_enum ("charge-status",
3039+ NULL, NULL,
3040+ XFPM_TYPE_BATTERY_CHARGE,
3041+ XFPM_BATTERY_CHARGE_UNKNOWN,
3042+ G_PARAM_READABLE));
3043+
3044+ g_type_class_add_private (klass, sizeof (XfpmBatteryPrivate));
3045+}
3046+
3047+static void
3048+xfpm_battery_init (XfpmBattery *battery)
3049+{
3050+ battery->priv = XFPM_BATTERY_GET_PRIVATE (battery);
3051+
3052+ battery->priv->conf = xfpm_xfconf_new ();
3053+ battery->priv->notify = xfpm_notify_new ();
3054+ battery->priv->proxy_prop = NULL;
3055+ battery->priv->state = XFPM_DEVICE_STATE_UNKNOWN;
3056+ battery->priv->type = XFPM_DEVICE_TYPE_UNKNOWN;
3057+ battery->priv->charge = XFPM_BATTERY_CHARGE_UNKNOWN;
3058+ battery->priv->icon_prefix = NULL;
3059+ battery->priv->time_to_full = 0;
3060+ battery->priv->time_to_empty = 0;
3061+ battery->priv->button = xfpm_button_new ();
3062+ battery->priv->ac_online = TRUE;
3063+
3064+ battery->priv->sig = g_signal_connect (G_OBJECT (battery->priv->conf), "notify::" SHOW_TRAY_ICON_CFG,
3065+ G_CALLBACK (xfpm_battery_tray_icon_settings_changed), battery);
3066+
3067+
3068+ battery->priv->sig_bt = g_signal_connect (G_OBJECT (battery->priv->button), "button-pressed",
3069+ G_CALLBACK (xfpm_battery_button_pressed_cb), battery);
3070+}
3071+
3072+static void
3073+xfpm_battery_finalize (GObject *object)
3074+{
3075+ XfpmBattery *battery;
3076+
3077+ battery = XFPM_BATTERY (object);
3078+
3079+ g_free (battery->priv->icon_prefix);
3080+
3081+ if (battery->priv->notify_idle != 0)
3082+ g_source_remove (battery->priv->notify_idle);
3083+
3084+ dbus_g_proxy_disconnect_signal (battery->priv->proxy, "Changed",
3085+ G_CALLBACK (xfpm_battery_changed_cb), battery);
3086+
3087+ if ( g_signal_handler_is_connected (battery->priv->conf, battery->priv->sig ) )
3088+ g_signal_handler_disconnect (G_OBJECT (battery->priv->conf), battery->priv->sig);
3089+
3090+ if ( g_signal_handler_is_connected (battery->priv->button, battery->priv->sig_bt ) )
3091+ g_signal_handler_disconnect (G_OBJECT (battery->priv->button), battery->priv->sig_bt);
3092+
3093+ g_object_unref (battery->priv->proxy);
3094+ g_object_unref (battery->priv->proxy_prop);
3095+ g_object_unref (battery->priv->conf);
3096+ g_object_unref (battery->priv->notify);
3097+ g_object_unref (battery->priv->button);
3098+
3099+ G_OBJECT_CLASS (xfpm_battery_parent_class)->finalize (object);
3100+}
3101+
3102+static gchar *
3103+xfpm_battery_get_icon_prefix_device_enum_type (XfpmDeviceType type)
3104+{
3105+ if ( type == XFPM_DEVICE_TYPE_BATTERY )
3106+ {
3107+ return g_strdup (XFPM_PRIMARY_ICON_PREFIX);
3108+ }
3109+ else if ( type == XFPM_DEVICE_TYPE_UPS )
3110+ {
3111+ return g_strdup (XFPM_UPS_ICON_PREFIX);
3112+ }
3113+ else if ( type == XFPM_DEVICE_TYPE_MOUSE )
3114+ {
3115+ return g_strdup (XFPM_MOUSE_ICON_PREFIX);
3116+ }
3117+ else if ( type == XFPM_DEVICE_TYPE_KBD )
3118+ {
3119+ return g_strdup (XFPM_KBD_ICON_PREFIX);
3120+ }
3121+ else if ( type == XFPM_DEVICE_TYPE_PHONE )
3122+ {
3123+ return g_strdup (XFPM_PHONE_ICON_PREFIX);
3124+ }
3125+
3126+ return g_strdup (XFPM_PRIMARY_ICON_PREFIX);
3127+}
3128+
3129+static const gchar *
3130+xfpm_battery_get_name (XfpmDeviceType type)
3131+{
3132+ const gchar *name = NULL;
3133+
3134+ switch (type)
3135+ {
3136+ case XFPM_DEVICE_TYPE_BATTERY:
3137+ name = _("battery");
3138+ break;
3139+ case XFPM_DEVICE_TYPE_UPS:
3140+ name = _("UPS");
3141+ break;
3142+ case XFPM_DEVICE_TYPE_MONITOR:
3143+ name = _("monitor battery");
3144+ break;
3145+ case XFPM_DEVICE_TYPE_MOUSE:
3146+ name = _("mouse battery");
3147+ break;
3148+ case XFPM_DEVICE_TYPE_KBD:
3149+ name = _("keyboard battery");
3150+ break;
3151+ case XFPM_DEVICE_TYPE_PDA:
3152+ name = _("PDA battery");
3153+ break;
3154+ case XFPM_DEVICE_TYPE_PHONE:
3155+ name = _("Phone battery");
3156+ break;
3157+ default:
3158+ name = _("Unknown");
3159+ break;
3160+ }
3161+
3162+ return name;
3163+}
3164+
3165+GtkStatusIcon *
3166+xfpm_battery_new (void)
3167+{
3168+ XfpmBattery *battery = NULL;
3169+
3170+ battery = g_object_new (XFPM_TYPE_BATTERY, NULL);
3171+
3172+ return GTK_STATUS_ICON (battery);
3173+}
3174+
3175+void xfpm_battery_monitor_device (XfpmBattery *battery,
3176+ DBusGProxy *proxy,
3177+ DBusGProxy *proxy_prop,
3178+ XfpmDeviceType device_type)
3179+{
3180+ battery->priv->type = device_type;
3181+ battery->priv->proxy_prop = proxy_prop;
3182+ battery->priv->proxy = proxy;
3183+ battery->priv->icon_prefix = xfpm_battery_get_icon_prefix_device_enum_type (device_type);
3184+ battery->priv->battery_name = xfpm_battery_get_name (device_type);
3185+
3186+
3187+ dbus_g_proxy_add_signal (proxy, "Changed", G_TYPE_INVALID);
3188+ dbus_g_proxy_connect_signal (proxy, "Changed",
3189+ G_CALLBACK (xfpm_battery_changed_cb), battery, NULL);
3190+
3191+ g_object_set (G_OBJECT (battery),
3192+ "has-tooltip", TRUE,
3193+ NULL);
3194+
3195+ xfpm_battery_changed_cb (proxy, battery);
3196+}
3197+
3198+XfpmDeviceType xfpm_battery_get_device_type (XfpmBattery *battery)
3199+{
3200+ g_return_val_if_fail (XFPM_IS_BATTERY (battery), XFPM_DEVICE_TYPE_UNKNOWN );
3201+
3202+ return battery->priv->type;
3203+}
3204+
3205+XfpmBatteryCharge xfpm_battery_get_charge (XfpmBattery *battery)
3206+{
3207+ g_return_val_if_fail (XFPM_IS_BATTERY (battery), XFPM_BATTERY_CHARGE_UNKNOWN);
3208+
3209+ return battery->priv->charge;
3210+}
3211+
3212+const gchar *xfpm_battery_get_battery_name (XfpmBattery *battery)
3213+{
3214+ g_return_val_if_fail (XFPM_IS_BATTERY (battery), NULL);
3215+
3216+ return battery->priv->battery_name;
3217+}
3218+
3219+gchar *xfpm_battery_get_time_left (XfpmBattery *battery)
3220+{
3221+ g_return_val_if_fail (XFPM_IS_BATTERY (battery), NULL);
3222+
3223+ return xfpm_battery_get_time_string (battery->priv->time_to_empty);
3224+}
3225
3226=== added file '.pc/03_fix-insert-battery.patch/src/xfpm-power.c'
3227--- .pc/03_fix-insert-battery.patch/src/xfpm-power.c 1970-01-01 00:00:00 +0000
3228+++ .pc/03_fix-insert-battery.patch/src/xfpm-power.c 2013-08-12 21:07:54 +0000
3229@@ -0,0 +1,1755 @@
3230+/*
3231+ * * Copyright (C) 2009-2011 Ali <aliov@xfce.org>
3232+ *
3233+ * Licensed under the GNU General Public License Version 2
3234+ *
3235+ * This program is free software; you can redistribute it and/or modify
3236+ * it under the terms of the GNU General Public License as published by
3237+ * the Free Software Foundation; either version 2 of the License, or
3238+ * (at your option) any later version.
3239+ *
3240+ * This program is distributed in the hope that it will be useful,
3241+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3242+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3243+ * GNU General Public License for more details.
3244+ *
3245+ * You should have received a copy of the GNU General Public License
3246+ * along with this program; if not, write to the Free Software
3247+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
3248+ */
3249+
3250+#ifdef HAVE_CONFIG_H
3251+#include <config.h>
3252+#endif
3253+
3254+#include <stdio.h>
3255+#include <stdlib.h>
3256+#include <string.h>
3257+
3258+#include <dbus/dbus-glib.h>
3259+#include <dbus/dbus-glib-lowlevel.h>
3260+
3261+#include <libxfce4util/libxfce4util.h>
3262+#include <libxfce4ui/libxfce4ui.h>
3263+
3264+#include "xfpm-power.h"
3265+#include "xfpm-dbus.h"
3266+#include "xfpm-dpms.h"
3267+#include "xfpm-battery.h"
3268+#include "xfpm-xfconf.h"
3269+#include "xfpm-notify.h"
3270+#include "xfpm-errors.h"
3271+#include "xfpm-console-kit.h"
3272+#include "xfpm-inhibit.h"
3273+#include "xfpm-polkit.h"
3274+#include "xfpm-network-manager.h"
3275+#include "xfpm-icons.h"
3276+#include "xfpm-common.h"
3277+#include "xfpm-power-common.h"
3278+#include "xfpm-config.h"
3279+#include "xfpm-debug.h"
3280+#include "xfpm-enum-types.h"
3281+#include "egg-idletime.h"
3282+
3283+static void xfpm_power_finalize (GObject *object);
3284+
3285+static void xfpm_power_get_property (GObject *object,
3286+ guint prop_id,
3287+ GValue *value,
3288+ GParamSpec *pspec);
3289+
3290+static void xfpm_power_dbus_class_init (XfpmPowerClass * klass);
3291+static void xfpm_power_dbus_init (XfpmPower *power);
3292+
3293+static void xfpm_power_refresh_adaptor_visible (XfpmPower *power);
3294+
3295+#define XFPM_POWER_GET_PRIVATE(o) \
3296+(G_TYPE_INSTANCE_GET_PRIVATE ((o), XFPM_TYPE_POWER, XfpmPowerPrivate))
3297+
3298+struct XfpmPowerPrivate
3299+{
3300+ DBusGConnection *bus;
3301+
3302+ DBusGProxy *proxy;
3303+ DBusGProxy *proxy_prop;
3304+
3305+ GHashTable *hash;
3306+
3307+ XfpmConsoleKit *console;
3308+ XfpmInhibit *inhibit;
3309+ XfpmXfconf *conf;
3310+ GtkStatusIcon *adapter_icon;
3311+
3312+ XfpmBatteryCharge overall_state;
3313+ gboolean critical_action_done;
3314+
3315+ XfpmPowerMode power_mode;
3316+ EggIdletime *idletime;
3317+
3318+ gboolean inhibited;
3319+
3320+ XfpmNotify *notify;
3321+#ifdef ENABLE_POLKIT
3322+ XfpmPolkit *polkit;
3323+#endif
3324+ gboolean auth_suspend;
3325+ gboolean auth_hibernate;
3326+
3327+ /* Properties */
3328+ gboolean on_low_battery;
3329+ gboolean lid_is_present;
3330+ gboolean lid_is_closed;
3331+ gboolean on_battery;
3332+ gchar *daemon_version;
3333+ gboolean can_suspend;
3334+ gboolean can_hibernate;
3335+
3336+ /**
3337+ * Warning dialog to use when notification daemon
3338+ * doesn't support actions.
3339+ **/
3340+ GtkWidget *dialog;
3341+};
3342+
3343+enum
3344+{
3345+ PROP_0,
3346+ PROP_ON_LOW_BATTERY,
3347+ PROP_ON_BATTERY,
3348+ PROP_AUTH_SUSPEND,
3349+ PROP_AUTH_HIBERNATE,
3350+ PROP_CAN_SUSPEND,
3351+ PROP_CAN_HIBERNATE,
3352+ PROP_HAS_LID
3353+};
3354+
3355+enum
3356+{
3357+ ON_BATTERY_CHANGED,
3358+ LOW_BATTERY_CHANGED,
3359+ LID_CHANGED,
3360+ WAKING_UP,
3361+ SLEEPING,
3362+ ASK_SHUTDOWN,
3363+ SHUTDOWN,
3364+ LAST_SIGNAL
3365+};
3366+
3367+static guint signals [LAST_SIGNAL] = { 0 };
3368+
3369+
3370+G_DEFINE_TYPE (XfpmPower, xfpm_power, G_TYPE_OBJECT)
3371+
3372+#ifdef ENABLE_POLKIT
3373+static void
3374+xfpm_power_check_polkit_auth (XfpmPower *power)
3375+{
3376+ power->priv->auth_suspend = xfpm_polkit_check_auth (power->priv->polkit,
3377+ POLKIT_AUTH_SUSPEND);
3378+
3379+ power->priv->auth_hibernate = xfpm_polkit_check_auth (power->priv->polkit,
3380+ POLKIT_AUTH_HIBERNATE);
3381+
3382+}
3383+#endif
3384+
3385+static void
3386+xfpm_power_check_pm (XfpmPower *power, GHashTable *props)
3387+{
3388+ GValue *value;
3389+ gboolean ret;
3390+
3391+ value = g_hash_table_lookup (props, "CanSuspend");
3392+
3393+ if (value == NULL)
3394+ {
3395+ g_warning ("No 'CanSuspend' property");
3396+ }
3397+ ret = g_value_get_boolean (value);
3398+
3399+ if (ret != power->priv->can_suspend)
3400+ {
3401+ power->priv->can_suspend = ret;
3402+ }
3403+
3404+ value = g_hash_table_lookup (props, "CanHibernate");
3405+
3406+ if (value == NULL)
3407+ {
3408+ g_warning ("No 'CanHibernate' property");
3409+ }
3410+
3411+ ret = g_value_get_boolean (value);
3412+
3413+ if (ret != power->priv->can_hibernate)
3414+ {
3415+ power->priv->can_hibernate = ret;
3416+ }
3417+}
3418+
3419+static void
3420+xfpm_power_check_power (XfpmPower *power, GHashTable *props)
3421+{
3422+ GValue *value;
3423+ gboolean on_battery;
3424+
3425+ value = g_hash_table_lookup (props, "OnBattery");
3426+
3427+ if (G_LIKELY (value))
3428+ {
3429+ on_battery = g_value_get_boolean (value);
3430+
3431+ if (on_battery != power->priv->on_battery )
3432+ {
3433+ GList *list;
3434+ guint len, i;
3435+ g_signal_emit (G_OBJECT (power), signals [ON_BATTERY_CHANGED], 0, on_battery);
3436+ power->priv->on_battery = on_battery;
3437+ list = g_hash_table_get_values (power->priv->hash);
3438+ len = g_list_length (list);
3439+ for ( i = 0; i < len; i++)
3440+ {
3441+ g_object_set (G_OBJECT (g_list_nth_data (list, i)),
3442+ "ac-online", !on_battery,
3443+ NULL);
3444+ }
3445+ }
3446+ }
3447+ else
3448+ {
3449+ g_warning ("No 'OnBattery' property");
3450+ }
3451+}
3452+
3453+static void
3454+xfpm_power_check_lid (XfpmPower *power, GHashTable *props)
3455+{
3456+ GValue *value;
3457+
3458+ value = g_hash_table_lookup (props, "LidIsPresent");
3459+
3460+ if (value == NULL)
3461+ {
3462+ g_warning ("No 'LidIsPresent' property");
3463+ return;
3464+ }
3465+
3466+ power->priv->lid_is_present = g_value_get_boolean (value);
3467+
3468+ if (power->priv->lid_is_present)
3469+ {
3470+ gboolean closed;
3471+
3472+ value = g_hash_table_lookup (props, "LidIsClosed");
3473+
3474+ if (value == NULL)
3475+ {
3476+ g_warning ("No 'LidIsClosed' property");
3477+ return;
3478+ }
3479+
3480+ closed = g_value_get_boolean (value);
3481+
3482+ if (closed != power->priv->lid_is_closed )
3483+ {
3484+ power->priv->lid_is_closed = closed;
3485+ g_signal_emit (G_OBJECT (power), signals [LID_CHANGED], 0, power->priv->lid_is_closed);
3486+ }
3487+ }
3488+}
3489+
3490+/*
3491+ * Get the properties on org.freedesktop.DeviceKit.Power
3492+ *
3493+ * DaemonVersion 's'
3494+ * CanSuspend' 'b'
3495+ * CanHibernate' 'b'
3496+ * OnBattery' 'b'
3497+ * OnLowBattery' 'b'
3498+ * LidIsClosed' 'b'
3499+ * LidIsPresent' 'b'
3500+ */
3501+static void
3502+xfpm_power_get_properties (XfpmPower *power)
3503+{
3504+ GHashTable *props;
3505+
3506+ props = xfpm_power_get_interface_properties (power->priv->proxy_prop, UPOWER_IFACE);
3507+
3508+ xfpm_power_check_pm (power, props);
3509+ xfpm_power_check_lid (power, props);
3510+ xfpm_power_check_power (power, props);
3511+
3512+ g_hash_table_destroy (props);
3513+}
3514+
3515+static void
3516+xfpm_power_report_error (XfpmPower *power, const gchar *error, const gchar *icon_name)
3517+{
3518+ GtkStatusIcon *battery = NULL;
3519+ guint i, len;
3520+ GList *list;
3521+
3522+ list = g_hash_table_get_values (power->priv->hash);
3523+ len = g_list_length (list);
3524+
3525+ for ( i = 0; i < len; i++)
3526+ {
3527+ XfpmDeviceType type;
3528+ battery = g_list_nth_data (list, i);
3529+ type = xfpm_battery_get_device_type (XFPM_BATTERY (battery));
3530+ if ( type == XFPM_DEVICE_TYPE_BATTERY ||
3531+ type == XFPM_DEVICE_TYPE_UPS )
3532+ break;
3533+ }
3534+
3535+ xfpm_notify_show_notification (power->priv->notify,
3536+ _("Power Manager"),
3537+ error,
3538+ icon_name,
3539+ 10000,
3540+ FALSE,
3541+ XFPM_NOTIFY_CRITICAL,
3542+ battery);
3543+
3544+}
3545+
3546+static void
3547+xfpm_power_sleep (XfpmPower *power, const gchar *sleep_time, gboolean force)
3548+{
3549+ GError *error = NULL;
3550+ gboolean lock_screen;
3551+
3552+ if ( power->priv->inhibited && force == FALSE)
3553+ {
3554+ gboolean ret;
3555+
3556+ ret = xfce_dialog_confirm (NULL,
3557+ GTK_STOCK_OK, _("_Hibernate"),
3558+ _("An application is currently disabling the automatic sleep. "
3559+ "Doing this action now may damage the working state of this application."),
3560+ _("Are you sure you want to hibernate the system?"));
3561+
3562+ if ( !ret )
3563+ return;
3564+ }
3565+
3566+ g_signal_emit (G_OBJECT (power), signals [SLEEPING], 0);
3567+ xfpm_network_manager_sleep (TRUE);
3568+
3569+ g_object_get (G_OBJECT (power->priv->conf),
3570+ LOCK_SCREEN_ON_SLEEP, &lock_screen,
3571+ NULL);
3572+
3573+ if ( lock_screen )
3574+ {
3575+ g_usleep (2000000); /* 2 seconds */
3576+ xfpm_lock_screen ();
3577+ }
3578+
3579+ dbus_g_proxy_call (power->priv->proxy, sleep_time, &error,
3580+ G_TYPE_INVALID,
3581+ G_TYPE_INVALID);
3582+
3583+ if ( error )
3584+ {
3585+ if ( g_error_matches (error, DBUS_GERROR, DBUS_GERROR_NO_REPLY) )
3586+ {
3587+ XFPM_DEBUG ("D-Bus time out, but should be harmless");
3588+ }
3589+ else
3590+ {
3591+ const gchar *icon_name;
3592+ if ( !g_strcmp0 (sleep_time, "Hibernate") )
3593+ icon_name = XFPM_HIBERNATE_ICON;
3594+ else
3595+ icon_name = XFPM_SUSPEND_ICON;
3596+
3597+ xfpm_power_report_error (power, error->message, icon_name);
3598+ g_error_free (error);
3599+ }
3600+ }
3601+
3602+ g_signal_emit (G_OBJECT (power), signals [WAKING_UP], 0);
3603+ xfpm_network_manager_sleep (FALSE);
3604+}
3605+
3606+static void
3607+xfpm_power_hibernate_cb (XfpmPower *power)
3608+{
3609+ xfpm_power_sleep (power, "Hibernate", FALSE);
3610+}
3611+
3612+static void
3613+xfpm_power_suspend_cb (XfpmPower *power)
3614+{
3615+ xfpm_power_sleep (power, "Suspend", FALSE);
3616+}
3617+
3618+static void
3619+xfpm_power_hibernate_clicked (XfpmPower *power)
3620+{
3621+ gtk_widget_destroy (power->priv->dialog );
3622+ power->priv->dialog = NULL;
3623+ xfpm_power_sleep (power, "Hibernate", TRUE);
3624+}
3625+
3626+static void
3627+xfpm_power_suspend_clicked (XfpmPower *power)
3628+{
3629+ gtk_widget_destroy (power->priv->dialog );
3630+ power->priv->dialog = NULL;
3631+ xfpm_power_sleep (power, "Suspend", TRUE);
3632+}
3633+
3634+static void
3635+xfpm_power_shutdown_clicked (XfpmPower *power)
3636+{
3637+ gtk_widget_destroy (power->priv->dialog );
3638+ power->priv->dialog = NULL;
3639+ g_signal_emit (G_OBJECT (power), signals [SHUTDOWN], 0);
3640+}
3641+
3642+static void
3643+xfpm_power_power_info_cb (gpointer data)
3644+{
3645+ g_spawn_command_line_async ("xfce4-power-information", NULL);
3646+}
3647+
3648+static void
3649+xfpm_power_tray_exit_activated_cb (gpointer data)
3650+{
3651+ gboolean ret;
3652+
3653+ ret = xfce_dialog_confirm (NULL,
3654+ GTK_STOCK_YES,
3655+ _("Quit"),
3656+ _("All running instances of the power manager will exit"),
3657+ "%s",
3658+ _("Quit the power manager?"));
3659+ if ( ret )
3660+ {
3661+ xfpm_quit ();
3662+ }
3663+}
3664+
3665+
3666+static void
3667+xfpm_power_change_mode (XfpmPower *power, XfpmPowerMode mode)
3668+{
3669+#ifdef HAVE_DPMS
3670+ XfpmDpms *dpms;
3671+
3672+ power->priv->power_mode = mode;
3673+
3674+ dpms = xfpm_dpms_new ();
3675+ xfpm_dpms_refresh (dpms);
3676+ g_object_unref (dpms);
3677+
3678+ if (mode == XFPM_POWER_MODE_NORMAL)
3679+ {
3680+ EggIdletime *idletime;
3681+ idletime = egg_idletime_new ();
3682+ egg_idletime_alarm_reset_all (idletime);
3683+
3684+ g_object_unref (idletime);
3685+ }
3686+#endif
3687+}
3688+
3689+static void
3690+xfpm_power_normal_mode_cb (XfpmPower *power)
3691+{
3692+ xfpm_power_change_mode (power, XFPM_POWER_MODE_NORMAL);
3693+}
3694+
3695+static void
3696+xfpm_power_presentation_mode_cb (XfpmPower *power)
3697+{
3698+ xfpm_power_change_mode (power, XFPM_POWER_MODE_PRESENTATION);
3699+}
3700+
3701+static void
3702+xfpm_power_show_tray_menu (XfpmPower *power,
3703+ GtkStatusIcon *icon,
3704+ guint button,
3705+ guint activate_time,
3706+ gboolean show_info_item)
3707+{
3708+ GtkWidget *menu, *mi, *img, *subm;
3709+
3710+ menu = gtk_menu_new();
3711+
3712+ // Hibernate menu option
3713+ mi = gtk_image_menu_item_new_with_label (_("Hibernate"));
3714+ img = gtk_image_new_from_icon_name (XFPM_HIBERNATE_ICON, GTK_ICON_SIZE_MENU);
3715+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
3716+ gtk_widget_set_sensitive (mi, FALSE);
3717+
3718+ if ( power->priv->can_hibernate && power->priv->auth_hibernate)
3719+ {
3720+ gtk_widget_set_sensitive (mi, TRUE);
3721+ g_signal_connect_swapped (G_OBJECT (mi), "activate",
3722+ G_CALLBACK (xfpm_power_hibernate_cb), power);
3723+ }
3724+ gtk_widget_show (mi);
3725+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3726+
3727+ // Suspend menu option
3728+ mi = gtk_image_menu_item_new_with_label (_("Suspend"));
3729+ img = gtk_image_new_from_icon_name (XFPM_SUSPEND_ICON, GTK_ICON_SIZE_MENU);
3730+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
3731+
3732+ gtk_widget_set_sensitive (mi, FALSE);
3733+
3734+ if ( power->priv->can_suspend && power->priv->auth_hibernate)
3735+ {
3736+ gtk_widget_set_sensitive (mi, TRUE);
3737+ g_signal_connect_swapped (mi, "activate",
3738+ G_CALLBACK (xfpm_power_suspend_cb), power);
3739+ }
3740+
3741+ gtk_widget_show (mi);
3742+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3743+/*
3744+ saver_inhibited = xfpm_screen_saver_get_inhibit (tray->priv->srv);
3745+ mi = gtk_check_menu_item_new_with_label (_("Monitor power control"));
3746+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), !saver_inhibited);
3747+ gtk_widget_set_tooltip_text (mi, _("Disable or enable monitor power control, "\
3748+ "for example you could disable the screen power "\
3749+ "control to avoid screen blanking when watching a movie."));
3750+
3751+ g_signal_connect (G_OBJECT (mi), "activate",
3752+ G_CALLBACK (xfpm_tray_icon_inhibit_active_cb), tray);
3753+ gtk_widget_set_sensitive (mi, TRUE);
3754+ gtk_widget_show(mi);
3755+ gtk_menu_shell_append(GTK_MENU_SHELL(menu),mi);
3756+*/
3757+
3758+ mi = gtk_separator_menu_item_new ();
3759+ gtk_widget_show (mi);
3760+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3761+
3762+ // Power information
3763+ mi = gtk_image_menu_item_new_with_label (_("Power Information"));
3764+ img = gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU);
3765+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
3766+
3767+ gtk_widget_set_sensitive (mi,TRUE);
3768+
3769+ g_signal_connect_swapped (mi, "activate",
3770+ G_CALLBACK (xfpm_power_power_info_cb), icon);
3771+
3772+ gtk_widget_show (mi);
3773+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3774+
3775+ /**
3776+ * Power Mode
3777+ **/
3778+ /* TRANSLATOR: Mode here is the power profile (presentation, power save, normal) */
3779+ mi = gtk_image_menu_item_new_with_label (_("Mode"));
3780+ img = gtk_image_new_from_icon_name (XFPM_AC_ADAPTER_ICON, GTK_ICON_SIZE_MENU);
3781+ gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), img);
3782+ gtk_widget_set_sensitive (mi,TRUE);
3783+ gtk_widget_show (mi);
3784+
3785+ subm = gtk_menu_new ();
3786+ gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), subm);
3787+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3788+
3789+ /* Normal*/
3790+ mi = gtk_check_menu_item_new_with_label (_("Normal"));
3791+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), power->priv->power_mode == XFPM_POWER_MODE_NORMAL);
3792+ gtk_widget_set_sensitive (mi,TRUE);
3793+
3794+ g_signal_connect_swapped (mi, "activate",
3795+ G_CALLBACK (xfpm_power_normal_mode_cb), power);
3796+ gtk_widget_show (mi);
3797+ gtk_menu_shell_append (GTK_MENU_SHELL (subm), mi);
3798+
3799+ /* Normal*/
3800+ mi = gtk_check_menu_item_new_with_label (_("Presentation"));
3801+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), power->priv->power_mode == XFPM_POWER_MODE_PRESENTATION);
3802+ gtk_widget_set_sensitive (mi, TRUE);
3803+
3804+ g_signal_connect_swapped (mi, "activate",
3805+ G_CALLBACK (xfpm_power_presentation_mode_cb), power);
3806+ gtk_widget_show (mi);
3807+ gtk_menu_shell_append (GTK_MENU_SHELL (subm), mi);
3808+
3809+
3810+ mi = gtk_separator_menu_item_new ();
3811+ gtk_widget_show (mi);
3812+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3813+
3814+ mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_HELP, NULL);
3815+ gtk_widget_set_sensitive (mi, TRUE);
3816+ gtk_widget_show (mi);
3817+ g_signal_connect (mi, "activate", G_CALLBACK (xfpm_help), NULL);
3818+
3819+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3820+
3821+ mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_ABOUT, NULL);
3822+ gtk_widget_set_sensitive (mi, TRUE);
3823+ gtk_widget_show (mi);
3824+ g_signal_connect (mi, "activate", G_CALLBACK (xfpm_about), _("Power Manager"));
3825+
3826+ gtk_menu_shell_append (GTK_MENU_SHELL(menu), mi);
3827+
3828+ mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_PREFERENCES, NULL);
3829+ gtk_widget_set_sensitive (mi, TRUE);
3830+ gtk_widget_show (mi);
3831+ g_signal_connect (mi, "activate",G_CALLBACK (xfpm_preferences), NULL);
3832+
3833+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3834+
3835+ mi = gtk_separator_menu_item_new ();
3836+ gtk_widget_show (mi);
3837+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3838+
3839+ mi = gtk_image_menu_item_new_from_stock (GTK_STOCK_QUIT, NULL);
3840+ gtk_widget_set_sensitive (mi, TRUE);
3841+ gtk_widget_show (mi);
3842+ g_signal_connect_swapped (mi, "activate", G_CALLBACK (xfpm_power_tray_exit_activated_cb), NULL);
3843+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
3844+
3845+ g_signal_connect (menu, "selection-done",
3846+ G_CALLBACK (gtk_widget_destroy), NULL);
3847+
3848+ // Popup the menu
3849+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL,
3850+ gtk_status_icon_position_menu,
3851+ icon, button, activate_time);
3852+
3853+}
3854+
3855+static void
3856+xfpm_power_show_tray_menu_battery (GtkStatusIcon *icon, guint button,
3857+ guint activate_time, XfpmPower *power)
3858+{
3859+ xfpm_power_show_tray_menu (power, icon, button, activate_time, TRUE);
3860+}
3861+
3862+static void
3863+xfpm_power_show_tray_menu_adaptor (GtkStatusIcon *icon, guint button,
3864+ guint activate_time, XfpmPower *power)
3865+{
3866+ xfpm_power_show_tray_menu (power, icon, button, activate_time, FALSE);
3867+}
3868+
3869+static XfpmBatteryCharge
3870+xfpm_power_get_current_charge_state (XfpmPower *power)
3871+{
3872+ GList *list;
3873+ guint len, i;
3874+ XfpmBatteryCharge max_charge_status = XFPM_BATTERY_CHARGE_UNKNOWN;
3875+
3876+ list = g_hash_table_get_values (power->priv->hash);
3877+ len = g_list_length (list);
3878+
3879+ for ( i = 0; i < len; i++)
3880+ {
3881+ XfpmBatteryCharge battery_charge;
3882+ XfpmDeviceType type;
3883+
3884+ g_object_get (G_OBJECT (g_list_nth_data (list, i)),
3885+ "charge-status", &battery_charge,
3886+ "device-type", &type,
3887+ NULL);
3888+ if ( type != XFPM_DEVICE_TYPE_BATTERY &&
3889+ type != XFPM_DEVICE_TYPE_UPS )
3890+ continue;
3891+
3892+ max_charge_status = MAX (max_charge_status, battery_charge);
3893+ }
3894+
3895+ return max_charge_status;
3896+}
3897+
3898+static void
3899+xfpm_power_notify_action_callback (NotifyNotification *n, gchar *action, XfpmPower *power)
3900+{
3901+ if ( !g_strcmp0 (action, "Shutdown") )
3902+ g_signal_emit (G_OBJECT (power), signals [SHUTDOWN], 0);
3903+ else
3904+ xfpm_power_sleep (power, action, TRUE);
3905+}
3906+
3907+static void
3908+xfpm_power_add_actions_to_notification (XfpmPower *power, NotifyNotification *n)
3909+{
3910+ gboolean can_shutdown;
3911+
3912+ g_object_get (G_OBJECT (power->priv->console),
3913+ "can-shutdown", &can_shutdown,
3914+ NULL);
3915+
3916+ if ( power->priv->can_hibernate && power->priv->auth_hibernate )
3917+ {
3918+ xfpm_notify_add_action_to_notification(
3919+ power->priv->notify,
3920+ n,
3921+ "Hibernate",
3922+ _("Hibernate the system"),
3923+ (NotifyActionCallback)xfpm_power_notify_action_callback,
3924+ power);
3925+ }
3926+
3927+ if ( power->priv->can_suspend && power->priv->auth_suspend )
3928+ {
3929+ xfpm_notify_add_action_to_notification(
3930+ power->priv->notify,
3931+ n,
3932+ "Suspend",
3933+ _("Suspend the system"),
3934+ (NotifyActionCallback)xfpm_power_notify_action_callback,
3935+ power);
3936+ }
3937+
3938+ if (can_shutdown )
3939+ xfpm_notify_add_action_to_notification(
3940+ power->priv->notify,
3941+ n,
3942+ "Shutdown",
3943+ _("Shutdown the system"),
3944+ (NotifyActionCallback)xfpm_power_notify_action_callback,
3945+ power);
3946+}
3947+
3948+static void
3949+xfpm_power_show_critical_action_notification (XfpmPower *power, XfpmBattery *battery)
3950+{
3951+ const gchar *message;
3952+ NotifyNotification *n;
3953+
3954+ message = _("System is running on low power. "\
3955+ "Save your work to avoid losing data");
3956+
3957+ n =
3958+ xfpm_notify_new_notification (power->priv->notify,
3959+ _("Power Manager"),
3960+ message,
3961+ gtk_status_icon_get_icon_name (GTK_STATUS_ICON (battery)),
3962+ 20000,
3963+ XFPM_NOTIFY_CRITICAL,
3964+ GTK_STATUS_ICON (battery));
3965+
3966+ xfpm_power_add_actions_to_notification (power, n);
3967+ xfpm_notify_critical (power->priv->notify, n);
3968+
3969+}
3970+
3971+static void
3972+xfpm_power_close_critical_dialog (XfpmPower *power)
3973+{
3974+ gtk_widget_destroy (power->priv->dialog);
3975+ power->priv->dialog = NULL;
3976+}
3977+
3978+static void
3979+xfpm_power_show_critical_action_gtk (XfpmPower *power)
3980+{
3981+ GtkWidget *dialog;
3982+ GtkWidget *content_area;
3983+ GtkWidget *img;
3984+ GtkWidget *cancel;
3985+ const gchar *message;
3986+ gboolean can_shutdown;
3987+
3988+ g_object_get (G_OBJECT (power->priv->console),
3989+ "can-shutdown", &can_shutdown,
3990+ NULL);
3991+
3992+ message = _("System is running on low power. "\
3993+ "Save your work to avoid losing data");
3994+
3995+ dialog = gtk_dialog_new_with_buttons (_("Power Manager"), NULL, GTK_DIALOG_MODAL,
3996+ NULL);
3997+
3998+ gtk_dialog_set_default_response (GTK_DIALOG (dialog),
3999+ GTK_RESPONSE_CANCEL);
4000+
4001+ content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
4002+
4003+ gtk_box_pack_start_defaults (GTK_BOX (content_area), gtk_label_new (message));
4004+
4005+ if ( power->priv->can_hibernate && power->priv->auth_hibernate )
4006+ {
4007+ GtkWidget *hibernate;
4008+ hibernate = gtk_button_new_with_label (_("Hibernate"));
4009+ img = gtk_image_new_from_icon_name (XFPM_HIBERNATE_ICON, GTK_ICON_SIZE_BUTTON);
4010+ gtk_button_set_image (GTK_BUTTON (hibernate), img);
4011+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), hibernate, GTK_RESPONSE_NONE);
4012+
4013+ g_signal_connect_swapped (hibernate, "clicked",
4014+ G_CALLBACK (xfpm_power_hibernate_clicked), power);
4015+ }
4016+
4017+ if ( power->priv->can_suspend && power->priv->auth_suspend )
4018+ {
4019+ GtkWidget *suspend;
4020+
4021+ suspend = gtk_button_new_with_label (_("Suspend"));
4022+ img = gtk_image_new_from_icon_name (XFPM_SUSPEND_ICON, GTK_ICON_SIZE_BUTTON);
4023+ gtk_button_set_image (GTK_BUTTON (suspend), img);
4024+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), suspend, GTK_RESPONSE_NONE);
4025+
4026+ g_signal_connect_swapped (suspend, "clicked",
4027+ G_CALLBACK (xfpm_power_suspend_clicked), power);
4028+ }
4029+
4030+ if ( can_shutdown )
4031+ {
4032+ GtkWidget *shutdown;
4033+
4034+ shutdown = gtk_button_new_with_label (_("Shutdown"));
4035+ img = gtk_image_new_from_icon_name (XFPM_SUSPEND_ICON, GTK_ICON_SIZE_BUTTON);
4036+ gtk_button_set_image (GTK_BUTTON (shutdown), img);
4037+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), shutdown, GTK_RESPONSE_NONE);
4038+
4039+ g_signal_connect_swapped (shutdown, "clicked",
4040+ G_CALLBACK (xfpm_power_shutdown_clicked), power);
4041+ }
4042+
4043+ cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
4044+ gtk_dialog_add_action_widget (GTK_DIALOG (dialog), cancel, GTK_RESPONSE_NONE);
4045+
4046+ g_signal_connect_swapped (cancel, "clicked",
4047+ G_CALLBACK (xfpm_power_close_critical_dialog), power);
4048+
4049+ g_signal_connect_swapped (dialog, "destroy",
4050+ G_CALLBACK (xfpm_power_close_critical_dialog), power);
4051+ if ( power->priv->dialog )
4052+ {
4053+ gtk_widget_destroy (power->priv->dialog);
4054+ power->priv->dialog = NULL;
4055+
4056+ }
4057+ power->priv->dialog = dialog;
4058+ gtk_widget_show_all (dialog);
4059+}
4060+
4061+static void
4062+xfpm_power_show_critical_action (XfpmPower *power, XfpmBattery *battery)
4063+{
4064+ gboolean supports_actions;
4065+
4066+ g_object_get (G_OBJECT (power->priv->notify),
4067+ "actions", &supports_actions,
4068+ NULL);
4069+
4070+ if ( supports_actions )
4071+ xfpm_power_show_critical_action_notification (power, battery);
4072+ else
4073+ xfpm_power_show_critical_action_gtk (power);
4074+}
4075+
4076+static void
4077+xfpm_power_process_critical_action (XfpmPower *power, XfpmShutdownRequest req)
4078+{
4079+ if ( req == XFPM_ASK )
4080+ g_signal_emit (G_OBJECT (power), signals [ASK_SHUTDOWN], 0);
4081+ else if ( req == XFPM_DO_SUSPEND )
4082+ xfpm_power_sleep (power, "Suspend", TRUE);
4083+ else if ( req == XFPM_DO_HIBERNATE )
4084+ xfpm_power_sleep (power, "Hibernate", TRUE);
4085+ else if ( req == XFPM_DO_SHUTDOWN )
4086+ g_signal_emit (G_OBJECT (power), signals [SHUTDOWN], 0);
4087+}
4088+
4089+static void
4090+xfpm_power_system_on_critical_power (XfpmPower *power, XfpmBattery *battery)
4091+{
4092+ XfpmShutdownRequest critical_action;
4093+
4094+ g_object_get (G_OBJECT (power->priv->conf),
4095+ CRITICAL_BATT_ACTION_CFG, &critical_action,
4096+ NULL);
4097+
4098+ XFPM_DEBUG ("System is running on low power");
4099+ XFPM_DEBUG_ENUM (critical_action, XFPM_TYPE_SHUTDOWN_REQUEST, "Critical battery action");
4100+
4101+ if ( critical_action == XFPM_DO_NOTHING )
4102+ {
4103+ xfpm_power_show_critical_action (power, battery);
4104+ }
4105+ else
4106+ {
4107+ if (power->priv->critical_action_done == FALSE)
4108+ {
4109+ power->priv->critical_action_done = TRUE;
4110+ xfpm_power_process_critical_action (power, critical_action);
4111+ }
4112+ else
4113+ {
4114+ xfpm_power_show_critical_action (power, battery);
4115+ }
4116+ }
4117+}
4118+
4119+static void
4120+xfpm_power_battery_charge_changed_cb (XfpmBattery *battery, XfpmPower *power)
4121+{
4122+ gboolean notify;
4123+ XfpmBatteryCharge battery_charge;
4124+ XfpmBatteryCharge current_charge;
4125+
4126+ battery_charge = xfpm_battery_get_charge (battery);
4127+ current_charge = xfpm_power_get_current_charge_state (power);
4128+
4129+ XFPM_DEBUG_ENUM (current_charge, XFPM_TYPE_BATTERY_CHARGE, "Current system charge status");
4130+
4131+ if (current_charge == power->priv->overall_state)
4132+ return;
4133+
4134+ if (current_charge >= XFPM_BATTERY_CHARGE_LOW)
4135+ power->priv->critical_action_done = FALSE;
4136+
4137+ power->priv->overall_state = current_charge;
4138+
4139+ if ( current_charge == XFPM_BATTERY_CHARGE_CRITICAL && power->priv->on_battery)
4140+ {
4141+ xfpm_power_system_on_critical_power (power, battery);
4142+
4143+ power->priv->on_low_battery = TRUE;
4144+ g_signal_emit (G_OBJECT (power), signals [LOW_BATTERY_CHANGED], 0, power->priv->on_low_battery);
4145+ return;
4146+ }
4147+
4148+ if ( power->priv->on_low_battery )
4149+ {
4150+ power->priv->on_low_battery = FALSE;
4151+ g_signal_emit (G_OBJECT (power), signals [LOW_BATTERY_CHANGED], 0, power->priv->on_low_battery);
4152+ }
4153+
4154+ g_object_get (G_OBJECT (power->priv->conf),
4155+ GENERAL_NOTIFICATION_CFG, &notify,
4156+ NULL);
4157+
4158+ if ( power->priv->on_battery )
4159+ {
4160+ if ( current_charge == XFPM_BATTERY_CHARGE_LOW )
4161+ {
4162+ if ( notify )
4163+ xfpm_notify_show_notification (power->priv->notify,
4164+ _("Power Manager"),
4165+ _("System is running on low power"),
4166+ gtk_status_icon_get_icon_name (GTK_STATUS_ICON (battery)),
4167+ 10000,
4168+ FALSE,
4169+ XFPM_NOTIFY_NORMAL,
4170+ GTK_STATUS_ICON (battery));
4171+
4172+ }
4173+ else if ( battery_charge == XFPM_BATTERY_CHARGE_LOW )
4174+ {
4175+ if ( notify )
4176+ {
4177+ gchar *msg;
4178+ gchar *time_str;
4179+
4180+ const gchar *battery_name = xfpm_battery_get_battery_name (battery);
4181+
4182+ time_str = xfpm_battery_get_time_left (battery);
4183+
4184+ msg = g_strdup_printf (_("Your %s charge level is low\nEstimated time left %s"), battery_name, time_str);
4185+
4186+
4187+ xfpm_notify_show_notification (power->priv->notify,
4188+ _("Power Manager"),
4189+ msg,
4190+ gtk_status_icon_get_icon_name (GTK_STATUS_ICON (battery)),
4191+ 10000,
4192+ FALSE,
4193+ XFPM_NOTIFY_NORMAL,
4194+ GTK_STATUS_ICON (battery));
4195+ g_free (msg);
4196+ g_free (time_str);
4197+ }
4198+ }
4199+ }
4200+
4201+ /*Current charge is okay now, then close the dialog*/
4202+ if ( power->priv->dialog )
4203+ {
4204+ gtk_widget_destroy (power->priv->dialog);
4205+ power->priv->dialog = NULL;
4206+ }
4207+}
4208+
4209+static void
4210+xfpm_power_add_device (XfpmPower *power, const gchar *object_path)
4211+{
4212+ DBusGProxy *proxy_prop;
4213+ guint device_type = XFPM_DEVICE_TYPE_UNKNOWN;
4214+ GValue value;
4215+
4216+ proxy_prop = dbus_g_proxy_new_for_name (power->priv->bus,
4217+ UPOWER_NAME,
4218+ object_path,
4219+ DBUS_INTERFACE_PROPERTIES);
4220+
4221+ if ( !proxy_prop )
4222+ {
4223+ g_warning ("Unable to create proxy for : %s", object_path);
4224+ return;
4225+ }
4226+
4227+ value = xfpm_power_get_interface_property (proxy_prop, UPOWER_IFACE_DEVICE, "Type");
4228+
4229+ device_type = g_value_get_uint (&value);
4230+
4231+ XFPM_DEBUG_ENUM (device_type, XFPM_TYPE_DEVICE_TYPE, " device added");
4232+
4233+ if ( device_type == XFPM_DEVICE_TYPE_BATTERY ||
4234+ device_type == XFPM_DEVICE_TYPE_UPS ||
4235+ device_type == XFPM_DEVICE_TYPE_MOUSE ||
4236+ device_type == XFPM_DEVICE_TYPE_KBD ||
4237+ device_type == XFPM_DEVICE_TYPE_PHONE)
4238+ {
4239+ GtkStatusIcon *battery;
4240+ DBusGProxy *proxy;
4241+ XFPM_DEBUG_ENUM (device_type, XFPM_TYPE_DEVICE_TYPE,
4242+ "Battery device detected at : %s", object_path);
4243+ proxy = dbus_g_proxy_new_for_name (power->priv->bus,
4244+ UPOWER_NAME,
4245+ object_path,
4246+ UPOWER_IFACE_DEVICE);
4247+ battery = xfpm_battery_new ();
4248+ gtk_status_icon_set_visible (battery, FALSE);
4249+ xfpm_battery_monitor_device (XFPM_BATTERY (battery),
4250+ proxy,
4251+ proxy_prop,
4252+ device_type);
4253+
4254+ g_hash_table_insert (power->priv->hash, g_strdup (object_path), battery);
4255+
4256+ g_signal_connect (battery, "popup-menu",
4257+ G_CALLBACK (xfpm_power_show_tray_menu_battery), power);
4258+
4259+ g_signal_connect (battery, "battery-charge-changed",
4260+ G_CALLBACK (xfpm_power_battery_charge_changed_cb), power);
4261+
4262+ xfpm_power_refresh_adaptor_visible (power);
4263+ }
4264+ else if ( device_type != XFPM_DEVICE_TYPE_LINE_POWER )
4265+ {
4266+ g_warning ("Unable to monitor unkown power device with object_path : %s", object_path);
4267+ g_object_unref (proxy_prop);
4268+ }
4269+}
4270+
4271+static void
4272+xfpm_power_get_power_devices (XfpmPower *power)
4273+{
4274+ GPtrArray *array = NULL;
4275+ guint i;
4276+
4277+ array = xfpm_power_enumerate_devices (power->priv->proxy);
4278+
4279+ if ( array )
4280+ {
4281+ for ( i = 0; i < array->len; i++)
4282+ {
4283+ const gchar *object_path = ( const gchar *) g_ptr_array_index (array, i);
4284+ XFPM_DEBUG ("Power device detected at : %s", object_path);
4285+ xfpm_power_add_device (power, object_path);
4286+ }
4287+ g_ptr_array_free (array, TRUE);
4288+ }
4289+
4290+}
4291+
4292+static void
4293+xfpm_power_remove_device (XfpmPower *power, const gchar *object_path)
4294+{
4295+ g_hash_table_remove (power->priv->hash, object_path);
4296+ xfpm_power_refresh_adaptor_visible (power);
4297+}
4298+
4299+static void
4300+xfpm_power_inhibit_changed_cb (XfpmInhibit *inhibit, gboolean is_inhibit, XfpmPower *power)
4301+{
4302+ power->priv->inhibited = is_inhibit;
4303+}
4304+
4305+static void
4306+xfpm_power_changed_cb (DBusGProxy *proxy, XfpmPower *power)
4307+{
4308+ xfpm_power_get_properties (power);
4309+ xfpm_power_refresh_adaptor_visible (power);
4310+}
4311+
4312+static void
4313+xfpm_power_device_added_cb (DBusGProxy *proxy, const gchar *object_path, XfpmPower *power)
4314+{
4315+ xfpm_power_add_device (power, object_path);
4316+}
4317+
4318+static void
4319+xfpm_power_device_removed_cb (DBusGProxy *proxy, const gchar *object_path, XfpmPower *power)
4320+{
4321+ xfpm_power_remove_device (power, object_path);
4322+}
4323+
4324+static void
4325+xfpm_power_device_changed_cb (DBusGProxy *proxy, const gchar *object_path, XfpmPower *power)
4326+{
4327+ xfpm_power_refresh_adaptor_visible (power);
4328+}
4329+
4330+#ifdef ENABLE_POLKIT
4331+static void
4332+xfpm_power_polkit_auth_changed_cb (XfpmPower *power)
4333+{
4334+ XFPM_DEBUG ("Auth configuration changed");
4335+ xfpm_power_check_polkit_auth (power);
4336+}
4337+#endif
4338+
4339+static void
4340+xfpm_power_hide_adapter_icon (XfpmPower *power)
4341+{
4342+ XFPM_DEBUG ("Hide adaptor icon");
4343+
4344+ if ( power->priv->adapter_icon )
4345+ {
4346+ g_object_unref (power->priv->adapter_icon);
4347+ power->priv->adapter_icon = NULL;
4348+ }
4349+}
4350+
4351+static void
4352+xfpm_power_show_adapter_icon (XfpmPower *power)
4353+{
4354+ g_return_if_fail (power->priv->adapter_icon == NULL);
4355+
4356+ power->priv->adapter_icon = gtk_status_icon_new ();
4357+
4358+ XFPM_DEBUG ("Showing adaptor icon");
4359+
4360+ gtk_status_icon_set_from_icon_name (power->priv->adapter_icon, XFPM_AC_ADAPTER_ICON);
4361+
4362+ gtk_status_icon_set_visible (power->priv->adapter_icon, TRUE);
4363+
4364+ g_signal_connect (power->priv->adapter_icon, "popup-menu",
4365+ G_CALLBACK (xfpm_power_show_tray_menu_adaptor), power);
4366+}
4367+
4368+static void
4369+xfpm_power_refresh_adaptor_visible (XfpmPower *power)
4370+{
4371+ XfpmShowIcon show_icon;
4372+
4373+ g_object_get (G_OBJECT (power->priv->conf),
4374+ SHOW_TRAY_ICON_CFG, &show_icon,
4375+ NULL);
4376+
4377+ XFPM_DEBUG_ENUM (show_icon, XFPM_TYPE_SHOW_ICON, "Tray icon configuration: ");
4378+
4379+ if ( show_icon == SHOW_ICON_ALWAYS )
4380+ {
4381+ if ( g_hash_table_size (power->priv->hash) == 0 )
4382+ {
4383+ xfpm_power_show_adapter_icon (power);
4384+#if GTK_CHECK_VERSION (2, 16, 0)
4385+ gtk_status_icon_set_tooltip_text (power->priv->adapter_icon,
4386+ power->priv->on_battery ?
4387+ _("Adaptor is offline") :
4388+ _("Adaptor is online") );
4389+#else
4390+ gtk_status_icon_set_tooltip (power->priv->adapter_icon,
4391+ power->priv->on_battery ?
4392+ _("Adaptor is offline") :
4393+ _("Adaptor is online") );
4394+#endif
4395+ }
4396+ else
4397+ {
4398+ xfpm_power_hide_adapter_icon (power);
4399+ }
4400+ }
4401+ else
4402+ {
4403+ xfpm_power_hide_adapter_icon (power);
4404+ }
4405+}
4406+
4407+static void
4408+xfpm_power_class_init (XfpmPowerClass *klass)
4409+{
4410+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
4411+
4412+ object_class->finalize = xfpm_power_finalize;
4413+
4414+ object_class->get_property = xfpm_power_get_property;
4415+
4416+ signals [ON_BATTERY_CHANGED] =
4417+ g_signal_new ("on-battery-changed",
4418+ XFPM_TYPE_POWER,
4419+ G_SIGNAL_RUN_LAST,
4420+ G_STRUCT_OFFSET(XfpmPowerClass, on_battery_changed),
4421+ NULL, NULL,
4422+ g_cclosure_marshal_VOID__BOOLEAN,
4423+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
4424+
4425+ signals [LOW_BATTERY_CHANGED] =
4426+ g_signal_new ("low-battery-changed",
4427+ XFPM_TYPE_POWER,
4428+ G_SIGNAL_RUN_LAST,
4429+ G_STRUCT_OFFSET(XfpmPowerClass, low_battery_changed),
4430+ NULL, NULL,
4431+ g_cclosure_marshal_VOID__BOOLEAN,
4432+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
4433+
4434+ signals [LID_CHANGED] =
4435+ g_signal_new ("lid-changed",
4436+ XFPM_TYPE_POWER,
4437+ G_SIGNAL_RUN_LAST,
4438+ G_STRUCT_OFFSET(XfpmPowerClass, lid_changed),
4439+ NULL, NULL,
4440+ g_cclosure_marshal_VOID__BOOLEAN,
4441+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
4442+
4443+ signals [WAKING_UP] =
4444+ g_signal_new ("waking-up",
4445+ XFPM_TYPE_POWER,
4446+ G_SIGNAL_RUN_LAST,
4447+ G_STRUCT_OFFSET(XfpmPowerClass, waking_up),
4448+ NULL, NULL,
4449+ g_cclosure_marshal_VOID__VOID,
4450+ G_TYPE_NONE, 0, G_TYPE_NONE);
4451+
4452+ signals [SLEEPING] =
4453+ g_signal_new ("sleeping",
4454+ XFPM_TYPE_POWER,
4455+ G_SIGNAL_RUN_LAST,
4456+ G_STRUCT_OFFSET(XfpmPowerClass, sleeping),
4457+ NULL, NULL,
4458+ g_cclosure_marshal_VOID__VOID,
4459+ G_TYPE_NONE, 0, G_TYPE_NONE);
4460+
4461+ signals [ASK_SHUTDOWN] =
4462+ g_signal_new ("ask-shutdown",
4463+ XFPM_TYPE_POWER,
4464+ G_SIGNAL_RUN_LAST,
4465+ G_STRUCT_OFFSET(XfpmPowerClass, ask_shutdown),
4466+ NULL, NULL,
4467+ g_cclosure_marshal_VOID__VOID,
4468+ G_TYPE_NONE, 0, G_TYPE_NONE);
4469+
4470+ signals [SHUTDOWN] =
4471+ g_signal_new ("shutdown",
4472+ XFPM_TYPE_POWER,
4473+ G_SIGNAL_RUN_LAST,
4474+ G_STRUCT_OFFSET(XfpmPowerClass, shutdown),
4475+ NULL, NULL,
4476+ g_cclosure_marshal_VOID__VOID,
4477+ G_TYPE_NONE, 0, G_TYPE_NONE);
4478+
4479+ g_object_class_install_property (object_class,
4480+ PROP_ON_BATTERY,
4481+ g_param_spec_boolean ("on-battery",
4482+ NULL, NULL,
4483+ FALSE,
4484+ G_PARAM_READABLE));
4485+
4486+ g_object_class_install_property (object_class,
4487+ PROP_ON_LOW_BATTERY,
4488+ g_param_spec_boolean ("on-low-battery",
4489+ NULL, NULL,
4490+ FALSE,
4491+ G_PARAM_READABLE));
4492+
4493+ g_object_class_install_property (object_class,
4494+ PROP_AUTH_SUSPEND,
4495+ g_param_spec_boolean ("auth-suspend",
4496+ NULL, NULL,
4497+ FALSE,
4498+ G_PARAM_READABLE));
4499+
4500+ g_object_class_install_property (object_class,
4501+ PROP_AUTH_HIBERNATE,
4502+ g_param_spec_boolean ("auth-hibernate",
4503+ NULL, NULL,
4504+ FALSE,
4505+ G_PARAM_READABLE));
4506+
4507+ g_object_class_install_property (object_class,
4508+ PROP_CAN_HIBERNATE,
4509+ g_param_spec_boolean ("can-hibernate",
4510+ NULL, NULL,
4511+ FALSE,
4512+ G_PARAM_READABLE));
4513+
4514+ g_object_class_install_property (object_class,
4515+ PROP_CAN_SUSPEND,
4516+ g_param_spec_boolean ("can-suspend",
4517+ NULL, NULL,
4518+ FALSE,
4519+ G_PARAM_READABLE));
4520+
4521+ g_object_class_install_property (object_class,
4522+ PROP_HAS_LID,
4523+ g_param_spec_boolean ("has-lid",
4524+ NULL, NULL,
4525+ FALSE,
4526+ G_PARAM_READABLE));
4527+
4528+ g_type_class_add_private (klass, sizeof (XfpmPowerPrivate));
4529+
4530+ xfpm_power_dbus_class_init (klass);
4531+}
4532+
4533+static void
4534+xfpm_power_init (XfpmPower *power)
4535+{
4536+ GError *error = NULL;
4537+
4538+ power->priv = XFPM_POWER_GET_PRIVATE (power);
4539+
4540+ power->priv->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
4541+ power->priv->lid_is_present = FALSE;
4542+ power->priv->lid_is_closed = FALSE;
4543+ power->priv->on_battery = FALSE;
4544+ power->priv->on_low_battery = FALSE;
4545+ power->priv->daemon_version = NULL;
4546+ power->priv->can_suspend = FALSE;
4547+ power->priv->can_hibernate = FALSE;
4548+ power->priv->auth_hibernate = TRUE;
4549+ power->priv->auth_suspend = TRUE;
4550+ power->priv->dialog = NULL;
4551+ power->priv->adapter_icon = NULL;
4552+ power->priv->overall_state = XFPM_BATTERY_CHARGE_OK;
4553+ power->priv->critical_action_done = FALSE;
4554+ power->priv->power_mode = XFPM_POWER_MODE_NORMAL;
4555+
4556+ power->priv->inhibit = xfpm_inhibit_new ();
4557+ power->priv->notify = xfpm_notify_new ();
4558+ power->priv->conf = xfpm_xfconf_new ();
4559+ power->priv->console = xfpm_console_kit_new ();
4560+
4561+ g_signal_connect_swapped (power->priv->conf, "notify::" SHOW_TRAY_ICON_CFG,
4562+ G_CALLBACK (xfpm_power_refresh_adaptor_visible), power);
4563+
4564+#ifdef ENABLE_POLKIT
4565+ power->priv->polkit = xfpm_polkit_get ();
4566+ g_signal_connect_swapped (power->priv->polkit, "auth-changed",
4567+ G_CALLBACK (xfpm_power_polkit_auth_changed_cb), power);
4568+#endif
4569+
4570+ g_signal_connect (power->priv->inhibit, "has-inhibit-changed",
4571+ G_CALLBACK (xfpm_power_inhibit_changed_cb), power);
4572+
4573+ power->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
4574+
4575+ if ( error )
4576+ {
4577+ g_critical ("Unable to connect to the system bus : %s", error->message);
4578+ g_error_free (error);
4579+ goto out;
4580+ }
4581+
4582+ power->priv->proxy = dbus_g_proxy_new_for_name (power->priv->bus,
4583+ UPOWER_NAME,
4584+ UPOWER_PATH,
4585+ UPOWER_IFACE);
4586+
4587+
4588+ power->priv->proxy_prop = dbus_g_proxy_new_for_name (power->priv->bus,
4589+ UPOWER_NAME,
4590+ UPOWER_PATH,
4591+ DBUS_INTERFACE_PROPERTIES);
4592+ if (power->priv->proxy_prop == NULL)
4593+ {
4594+ g_critical ("Unable to create proxy for %s", UPOWER_NAME);
4595+ goto out;
4596+ }
4597+
4598+ xfpm_power_get_power_devices (power);
4599+ xfpm_power_get_properties (power);
4600+#ifdef ENABLE_POLKIT
4601+ xfpm_power_check_polkit_auth (power);
4602+#endif
4603+
4604+ dbus_g_proxy_add_signal (power->priv->proxy, "Changed", G_TYPE_INVALID);
4605+ dbus_g_proxy_add_signal (power->priv->proxy, "DeviceAdded", G_TYPE_STRING, G_TYPE_INVALID);
4606+ dbus_g_proxy_add_signal (power->priv->proxy, "DeviceRemoved", G_TYPE_STRING, G_TYPE_INVALID);
4607+ dbus_g_proxy_add_signal (power->priv->proxy, "DeviceChanged", G_TYPE_STRING, G_TYPE_INVALID);
4608+
4609+ dbus_g_proxy_connect_signal (power->priv->proxy, "Changed",
4610+ G_CALLBACK (xfpm_power_changed_cb), power, NULL);
4611+ dbus_g_proxy_connect_signal (power->priv->proxy, "DeviceRemoved",
4612+ G_CALLBACK (xfpm_power_device_removed_cb), power, NULL);
4613+ dbus_g_proxy_connect_signal (power->priv->proxy, "DeviceAdded",
4614+ G_CALLBACK (xfpm_power_device_added_cb), power, NULL);
4615+
4616+ dbus_g_proxy_connect_signal (power->priv->proxy, "DeviceChanged",
4617+ G_CALLBACK (xfpm_power_device_changed_cb), power, NULL);
4618+
4619+
4620+out:
4621+ xfpm_power_refresh_adaptor_visible (power);
4622+
4623+ xfpm_power_dbus_init (power);
4624+
4625+ /*
4626+ * Emit org.freedesktop.PowerManagement session signals on startup
4627+ */
4628+ g_signal_emit (G_OBJECT (power), signals [ON_BATTERY_CHANGED], 0, power->priv->on_battery);
4629+}
4630+
4631+static void xfpm_power_get_property (GObject *object,
4632+ guint prop_id,
4633+ GValue *value,
4634+ GParamSpec *pspec)
4635+{
4636+ XfpmPower *power;
4637+ power = XFPM_POWER (object);
4638+
4639+ switch (prop_id)
4640+ {
4641+ case PROP_ON_BATTERY:
4642+ g_value_set_boolean (value, power->priv->on_battery);
4643+ break;
4644+ case PROP_AUTH_HIBERNATE:
4645+ g_value_set_boolean (value, power->priv->auth_hibernate);
4646+ break;
4647+ case PROP_AUTH_SUSPEND:
4648+ g_value_set_boolean (value, power->priv->auth_suspend);
4649+ break;
4650+ case PROP_CAN_SUSPEND:
4651+ g_value_set_boolean (value, power->priv->can_suspend);
4652+ break;
4653+ case PROP_CAN_HIBERNATE:
4654+ g_value_set_boolean (value, power->priv->can_hibernate);
4655+ break;
4656+ case PROP_HAS_LID:
4657+ g_value_set_boolean (value, power->priv->lid_is_present);
4658+ break;
4659+ default:
4660+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4661+ break;
4662+ }
4663+}
4664+
4665+static void
4666+xfpm_power_finalize (GObject *object)
4667+{
4668+ XfpmPower *power;
4669+
4670+ power = XFPM_POWER (object);
4671+
4672+ g_free (power->priv->daemon_version);
4673+
4674+ g_object_unref (power->priv->inhibit);
4675+ g_object_unref (power->priv->notify);
4676+ g_object_unref (power->priv->conf);
4677+ g_object_unref (power->priv->console);
4678+
4679+ xfpm_power_hide_adapter_icon (power);
4680+
4681+ dbus_g_connection_unref (power->priv->bus);
4682+
4683+ if ( power->priv->proxy )
4684+ {
4685+ dbus_g_proxy_disconnect_signal (power->priv->proxy, "Changed",
4686+ G_CALLBACK (xfpm_power_changed_cb), power);
4687+ dbus_g_proxy_disconnect_signal (power->priv->proxy, "DeviceRemoved",
4688+ G_CALLBACK (xfpm_power_device_removed_cb), power);
4689+ dbus_g_proxy_disconnect_signal (power->priv->proxy, "DeviceAdded",
4690+ G_CALLBACK (xfpm_power_device_added_cb), power);
4691+ dbus_g_proxy_disconnect_signal (power->priv->proxy, "DeviceChanged",
4692+ G_CALLBACK (xfpm_power_device_changed_cb), power);
4693+ g_object_unref (power->priv->proxy);
4694+ }
4695+
4696+ if ( power->priv->proxy_prop )
4697+ g_object_unref (power->priv->proxy_prop);
4698+
4699+ g_hash_table_destroy (power->priv->hash);
4700+
4701+#ifdef ENABLE_POLKIT
4702+ g_object_unref (power->priv->polkit);
4703+#endif
4704+
4705+ G_OBJECT_CLASS (xfpm_power_parent_class)->finalize (object);
4706+}
4707+
4708+XfpmPower *
4709+xfpm_power_get (void)
4710+{
4711+ static gpointer xfpm_power_object = NULL;
4712+
4713+ if ( G_LIKELY (xfpm_power_object != NULL ) )
4714+ {
4715+ g_object_ref (xfpm_power_object);
4716+ }
4717+ else
4718+ {
4719+ xfpm_power_object = g_object_new (XFPM_TYPE_POWER, NULL);
4720+ g_object_add_weak_pointer (xfpm_power_object, &xfpm_power_object);
4721+ }
4722+
4723+ return XFPM_POWER (xfpm_power_object);
4724+}
4725+
4726+void xfpm_power_suspend (XfpmPower *power, gboolean force)
4727+{
4728+ xfpm_power_sleep (power, "Suspend", force);
4729+}
4730+
4731+void xfpm_power_hibernate (XfpmPower *power, gboolean force)
4732+{
4733+ xfpm_power_sleep (power, "Hibernate", force);
4734+}
4735+
4736+gboolean xfpm_power_has_battery (XfpmPower *power)
4737+{
4738+ GtkStatusIcon *battery = NULL;
4739+ guint i, len;
4740+ GList *list;
4741+
4742+ gboolean ret = FALSE;
4743+
4744+ list = g_hash_table_get_values (power->priv->hash);
4745+ len = g_list_length (list);
4746+
4747+ for ( i = 0; i < len; i++)
4748+ {
4749+ XfpmDeviceType type;
4750+ battery = g_list_nth_data (list, i);
4751+ type = xfpm_battery_get_device_type (XFPM_BATTERY (battery));
4752+ if ( type == XFPM_DEVICE_TYPE_BATTERY ||
4753+ type == XFPM_DEVICE_TYPE_UPS )
4754+ {
4755+ ret = TRUE;
4756+ break;
4757+ }
4758+ }
4759+
4760+ return ret;
4761+}
4762+
4763+XfpmPowerMode xfpm_power_get_mode (XfpmPower *power)
4764+{
4765+ g_return_val_if_fail (XFPM_IS_POWER (power), XFPM_POWER_MODE_NORMAL);
4766+
4767+ return power->priv->power_mode;
4768+}
4769+
4770+/*
4771+ *
4772+ * DBus server implementation for org.freedesktop.PowerManagement
4773+ *
4774+ */
4775+static gboolean xfpm_power_dbus_shutdown (XfpmPower *power,
4776+ GError **error);
4777+
4778+static gboolean xfpm_power_dbus_reboot (XfpmPower *power,
4779+ GError **error);
4780+
4781+static gboolean xfpm_power_dbus_hibernate (XfpmPower * power,
4782+ GError **error);
4783+
4784+static gboolean xfpm_power_dbus_suspend (XfpmPower * power,
4785+ GError ** error);
4786+
4787+static gboolean xfpm_power_dbus_can_reboot (XfpmPower * power,
4788+ gboolean * OUT_can_reboot,
4789+ GError ** error);
4790+
4791+static gboolean xfpm_power_dbus_can_shutdown (XfpmPower * power,
4792+ gboolean * OUT_can_reboot,
4793+ GError ** error);
4794+
4795+static gboolean xfpm_power_dbus_can_hibernate (XfpmPower * power,
4796+ gboolean * OUT_can_hibernate,
4797+ GError ** error);
4798+
4799+static gboolean xfpm_power_dbus_can_suspend (XfpmPower * power,
4800+ gboolean * OUT_can_suspend,
4801+ GError ** error);
4802+
4803+static gboolean xfpm_power_dbus_get_power_save_status (XfpmPower * power,
4804+ gboolean * OUT_save_power,
4805+ GError ** error);
4806+
4807+static gboolean xfpm_power_dbus_get_on_battery (XfpmPower * power,
4808+ gboolean * OUT_on_battery,
4809+ GError ** error);
4810+
4811+static gboolean xfpm_power_dbus_get_low_battery (XfpmPower * power,
4812+ gboolean * OUT_low_battery,
4813+ GError ** error);
4814+
4815+#include "org.freedesktop.PowerManagement.h"
4816+
4817+static void
4818+xfpm_power_dbus_class_init (XfpmPowerClass * klass)
4819+{
4820+ dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass),
4821+ &dbus_glib_xfpm_power_object_info);
4822+}
4823+
4824+static void
4825+xfpm_power_dbus_init (XfpmPower *power)
4826+{
4827+ DBusGConnection *bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
4828+
4829+ dbus_g_connection_register_g_object (bus,
4830+ "/org/freedesktop/PowerManagement",
4831+ G_OBJECT (power));
4832+}
4833+
4834+static gboolean xfpm_power_dbus_shutdown (XfpmPower *power,
4835+ GError **error)
4836+{
4837+ gboolean can_reboot;
4838+
4839+ g_object_get (G_OBJECT (power->priv->console),
4840+ "can-shutdown", &can_reboot,
4841+ NULL);
4842+
4843+ if ( !can_reboot)
4844+ {
4845+ g_set_error (error, XFPM_ERROR, XFPM_ERROR_PERMISSION_DENIED,
4846+ _("Permission denied"));
4847+ return FALSE;
4848+ }
4849+
4850+ xfpm_console_kit_shutdown (power->priv->console, error);
4851+
4852+ return TRUE;
4853+}
4854+
4855+static gboolean xfpm_power_dbus_reboot (XfpmPower *power,
4856+ GError **error)
4857+{
4858+ gboolean can_reboot;
4859+
4860+ g_object_get (G_OBJECT (power->priv->console),
4861+ "can-restart", &can_reboot,
4862+ NULL);
4863+
4864+ if ( !can_reboot)
4865+ {
4866+ g_set_error (error, XFPM_ERROR, XFPM_ERROR_PERMISSION_DENIED,
4867+ _("Permission denied"));
4868+ return FALSE;
4869+ }
4870+
4871+ xfpm_console_kit_reboot (power->priv->console, error);
4872+
4873+ return TRUE;
4874+}
4875+
4876+static gboolean xfpm_power_dbus_hibernate (XfpmPower * power,
4877+ GError **error)
4878+{
4879+ if ( !power->priv->auth_suspend )
4880+ {
4881+ g_set_error (error, XFPM_ERROR, XFPM_ERROR_PERMISSION_DENIED,
4882+ _("Permission denied"));
4883+ return FALSE;
4884+
4885+ }
4886+
4887+ if (!power->priv->can_hibernate )
4888+ {
4889+ g_set_error (error, XFPM_ERROR, XFPM_ERROR_NO_HARDWARE_SUPPORT,
4890+ _("Suspend not supported"));
4891+ return FALSE;
4892+ }
4893+
4894+ xfpm_power_sleep (power, "Hibernate", FALSE);
4895+
4896+ return TRUE;
4897+}
4898+
4899+static gboolean xfpm_power_dbus_suspend (XfpmPower * power,
4900+ GError ** error)
4901+{
4902+ if ( !power->priv->auth_suspend )
4903+ {
4904+ g_set_error (error, XFPM_ERROR, XFPM_ERROR_PERMISSION_DENIED,
4905+ _("Permission denied"));
4906+ return FALSE;
4907+
4908+ }
4909+
4910+ if (!power->priv->can_suspend )
4911+ {
4912+ g_set_error (error, XFPM_ERROR, XFPM_ERROR_NO_HARDWARE_SUPPORT,
4913+ _("Suspend not supported"));
4914+ return FALSE;
4915+ }
4916+
4917+ xfpm_power_sleep (power, "Suspend", FALSE);
4918+
4919+ return TRUE;
4920+}
4921+
4922+static gboolean xfpm_power_dbus_can_reboot (XfpmPower * power,
4923+ gboolean * OUT_can_reboot,
4924+ GError ** error)
4925+{
4926+ g_object_get (G_OBJECT (power->priv->console),
4927+ "can-reboot", OUT_can_reboot,
4928+ NULL);
4929+
4930+ return TRUE;
4931+}
4932+
4933+static gboolean xfpm_power_dbus_can_shutdown (XfpmPower * power,
4934+ gboolean * OUT_can_shutdown,
4935+ GError ** error)
4936+{
4937+ g_object_get (G_OBJECT (power->priv->console),
4938+ "can-shutdown", OUT_can_shutdown,
4939+ NULL);
4940+ return TRUE;
4941+}
4942+
4943+static gboolean xfpm_power_dbus_can_hibernate (XfpmPower * power,
4944+ gboolean * OUT_can_hibernate,
4945+ GError ** error)
4946+{
4947+ *OUT_can_hibernate = power->priv->can_hibernate;
4948+ return TRUE;
4949+}
4950+
4951+static gboolean xfpm_power_dbus_can_suspend (XfpmPower * power,
4952+ gboolean * OUT_can_suspend,
4953+ GError ** error)
4954+{
4955+ *OUT_can_suspend = power->priv->can_suspend;
4956+
4957+ return TRUE;
4958+}
4959+
4960+static gboolean xfpm_power_dbus_get_power_save_status (XfpmPower * power,
4961+ gboolean * OUT_save_power,
4962+ GError ** error)
4963+{
4964+ //FIXME
4965+ return TRUE;
4966+}
4967+
4968+static gboolean xfpm_power_dbus_get_on_battery (XfpmPower * power,
4969+ gboolean * OUT_on_battery,
4970+ GError ** error)
4971+{
4972+ *OUT_on_battery = power->priv->on_battery;
4973+
4974+ return TRUE;
4975+}
4976+
4977+static gboolean xfpm_power_dbus_get_low_battery (XfpmPower * power,
4978+ gboolean * OUT_low_battery,
4979+ GError ** error)
4980+{
4981+ *OUT_low_battery = power->priv->on_low_battery;
4982+
4983+ return TRUE;
4984+}
4985
4986=== added file '.pc/06_fix-suspend-auth-check.patch/.timestamp'
4987=== modified file '.pc/06_fix-suspend-auth-check.patch/src/xfpm-power.c'
4988--- .pc/06_fix-suspend-auth-check.patch/src/xfpm-power.c 2012-05-18 21:50:54 +0000
4989+++ .pc/06_fix-suspend-auth-check.patch/src/xfpm-power.c 2013-08-12 21:07:54 +0000
4990@@ -1114,6 +1114,7 @@
4991
4992 if ( power->priv->adapter_icon )
4993 {
4994+ gtk_status_icon_set_visible (power->priv->adapter_icon, FALSE);
4995 g_object_unref (power->priv->adapter_icon);
4996 power->priv->adapter_icon = NULL;
4997 }
4998
4999=== added file '.pc/08_show_preferences_lxde.patch/.timestamp'
5000=== removed directory '.pc/09_fix_insert_battery.patch'
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: