1 /*******************************************************************************
2 **3456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
3 ** 10 20 30 40 50 60 70 80
4 **
5 ** notify-osd
6 **
7 ** dnd.c - implements the "do not disturb"-mode, e.g. gsmgr, presentations
8 **
9 ** Copyright 2009 Canonical Ltd.
10 **
11 ** Authors:
12 ** Mirco "MacSlow" Mueller <mirco.mueller@canonical.com>
13 ** David Barth <david.barth@canonical.com>
14 **
15 ** This program is free software: you can redistribute it and/or modify it
16 ** under the terms of the GNU General Public License version 3, as published
17 ** by the Free Software Foundation.
18 **
19 ** This program is distributed in the hope that it will be useful, but
20 ** WITHOUT ANY WARRANTY; without even the implied warranties of
21 ** MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
22 ** PURPOSE. See the GNU General Public License for more details.
23 **
24 ** You should have received a copy of the GNU General Public License along
25 ** with this program. If not, see <http://www.gnu.org/licenses/>.
26 **
27 *******************************************************************************/
28
29 #include "config.h"
30 #include <stdlib.h>
31
32 #include <glib.h>
33 #include <glib-object.h>
34
35 #include <dbus/dbus-glib.h>
36
37 #include <X11/Xproto.h>
38 #include <X11/Xlib.h>
39 #include <X11/Xutil.h>
40 #include <X11/Xatom.h>
41 #include <gdk/gdkx.h>
42
43 #include <libwnck/libwnck.h>
44
45 #include "dbus.h"
46
47 static DBusGProxy *gsmgr = NULL;
48
49 gboolean
dnd_is_xscreensaver_active()50 dnd_is_xscreensaver_active ()
51 {
52 GdkDisplay *display = gdk_display_get_default ();
53
54 Atom XA_BLANK =
55 gdk_x11_get_xatom_by_name_for_display(display, "BLANK");
56 Atom XA_LOCK =
57 gdk_x11_get_xatom_by_name_for_display(display, "BLANK");
58 Atom XA_SCREENSAVER_STATUS =
59 gdk_x11_get_xatom_by_name_for_display(display,
60 "_SCREENSAVER_STATUS");
61 gboolean active = FALSE;
62
63 Atom type;
64 int format;
65 int status;
66 unsigned long nitems, bytesafter;
67 unsigned char* data = NULL;
68
69 Display *dpy = gdk_x11_get_default_xdisplay ();
70 Window win = gdk_x11_get_default_root_xwindow ();
71
72 gdk_error_trap_push ();
73 status = XGetWindowProperty (dpy, win,
74 XA_SCREENSAVER_STATUS,
75 0, 999, False, XA_INTEGER,
76 &type, &format, &nitems, &bytesafter,
77 (unsigned char **) &data);
78 gdk_flush ();
79 gdk_error_trap_pop_ignored ();
80
81 if (status == Success
82 && type == XA_INTEGER
83 && nitems >= 3
84 && data != NULL)
85 {
86 CARD32* tmp_data = (CARD32*) data;
87
88 active = (tmp_data[0] == XA_BLANK || tmp_data[0] == XA_LOCK)
89 && ((time_t)tmp_data[1] > (time_t)666000000L);
90
91 g_debug ("Screensaver is currently active");
92 }
93
94 if (data != NULL)
95 free (data);
96
97 return active;
98 }
99
100 static DBusGProxy*
get_screensaver_proxy(void)101 get_screensaver_proxy (void)
102 {
103 if (gsmgr == NULL)
104 {
105 DBusGConnection *connection = dbus_get_connection ();
106 gsmgr = dbus_g_proxy_new_for_name (connection,
107 "org.gnome.ScreenSaver",
108 "/org/gnome/ScreenSaver",
109 "org.gnome.ScreenSaver");
110 }
111
112 return gsmgr;
113 }
114
115 gboolean
dnd_is_screensaver_inhibited()116 dnd_is_screensaver_inhibited ()
117 {
118 GError *error = NULL;
119 gboolean inhibited = FALSE;
120 char **list;
121
122 if (! get_screensaver_proxy ())
123 return FALSE;
124
125 if (dbus_g_proxy_call_with_timeout (
126 gsmgr, "GetInhibitors", 2000, &error,
127 G_TYPE_INVALID,
128 G_TYPE_STRV, &list,
129 G_TYPE_INVALID))
130 {
131 if (error)
132 {
133 g_warning ("dnd_is_screensaver_inhibited(): "
134 "got error \"%s\"\n",
135 error->message);
136 g_error_free (error);
137 error = NULL;
138 }
139
140 /* if the list is not empty, the screensaver is inhibited */
141 if (*list)
142 {
143 inhibited = TRUE;
144 g_debug ("Screensaver has been inhibited");
145 }
146 g_strfreev (list);
147 }
148
149 return inhibited;
150 }
151
152 gboolean
dnd_is_screensaver_active()153 dnd_is_screensaver_active ()
154 {
155 GError *error = NULL;
156 gboolean active = FALSE;;
157
158 if (! get_screensaver_proxy ())
159 return FALSE;
160
161 dbus_g_proxy_call_with_timeout (
162 gsmgr, "GetActive", 2000, &error,
163 G_TYPE_INVALID,
164 G_TYPE_BOOLEAN, &active,
165 G_TYPE_INVALID);
166
167 if (error)
168 {
169 g_warning ("dnd_is_screensaver_active(): Got error \"%s\"\n",
170 error->message);
171 g_error_free (error);
172 error = NULL;
173 }
174
175 if (active)
176 g_debug ("Gnome screensaver is active");
177
178 return active;
179 }
180
181 static gboolean
dnd_is_online_presence_dnd()182 dnd_is_online_presence_dnd ()
183 {
184 /* TODO: ask FUSA if we're in DND mode */
185
186 return FALSE;
187 }
188
189 static int
is_fullscreen_cb(WnckWindow * window,WnckWorkspace * workspace)190 is_fullscreen_cb (WnckWindow *window, WnckWorkspace *workspace)
191 {
192 if (wnck_window_is_visible_on_workspace (window, workspace)
193 && wnck_window_is_fullscreen (window))
194 {
195 return 0;
196 } else {
197 return 1;
198 }
199 }
200
201 gboolean
dnd_has_one_fullscreen_window(void)202 dnd_has_one_fullscreen_window (void)
203 {
204 gboolean result;
205
206 WnckScreen *screen = wnck_screen_get_default ();
207 wnck_screen_force_update (screen);
208 WnckWorkspace *workspace = wnck_screen_get_active_workspace (screen);
209 GList *list = wnck_screen_get_windows (screen);
210 GList *item = g_list_find_custom (list, workspace, (GCompareFunc) is_fullscreen_cb);
211 result = item != NULL;
212 #ifdef HAVE_WNCK_SHUTDOWN
213 wnck_shutdown ();
214 #endif
215 return result;
216 }
217
218 /* Tries to determine whether the user is in "do not disturb" mode */
219 gboolean
dnd_dont_disturb_user(void)220 dnd_dont_disturb_user (void)
221 {
222 return (dnd_is_online_presence_dnd()
223 || dnd_is_xscreensaver_active()
224 || dnd_is_screensaver_active()
225 || dnd_is_screensaver_inhibited()
226 || dnd_has_one_fullscreen_window()
227 );
228 }
229