Better error message when defaults file is missing.
[xfwm4.git] / src / startup_notification.c
blobc3da61f3f27d4a611ef1b95636b748ed85c0a4fd
1 /* $Id$
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 Metacity - (c) 2003 Havoc Pennington
18 xfwm4 - (c) 2002-2007 Olivier Fourdan
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
27 #define SN_API_NOT_YET_FROZEN
29 #include <X11/Xlib.h>
30 #include <X11/Xatom.h>
31 #include <libsn/sn.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <glib.h>
36 #include <gdk/gdk.h>
37 #include <gdk/gdkx.h>
38 #include <gtk/gtk.h>
39 #include <libxfce4util/libxfce4util.h>
41 #include "display.h"
42 #include "screen.h"
43 #include "client.h"
45 #define STARTUP_TIMEOUT (30 /* seconds */ * 1000)
47 static SnDisplay *sn_display = NULL;
49 typedef struct
51 GSList *list;
52 GTimeVal now;
54 CollectTimedOutData;
56 static gboolean sn_startup_sequence_timeout (void *data);
58 static void
59 sn_error_trap_push (SnDisplay * sn_display, Display * dpy)
61 gdk_error_trap_push ();
64 static void
65 sn_error_trap_pop (SnDisplay * sn_display, Display * dpy)
67 gdk_error_trap_pop ();
70 static void
71 sn_update_feedback (ScreenInfo *screen_info)
73 g_return_if_fail (screen_info != NULL);
75 if (screen_info->startup_sequences != NULL)
77 XDefineCursor (myScreenGetXDisplay (screen_info), screen_info->xroot,
78 myDisplayGetCursorBusy(screen_info->display_info));
80 else
82 XDefineCursor (myScreenGetXDisplay (screen_info), screen_info->xroot,
83 myDisplayGetCursorRoot(screen_info->display_info));
87 static void
88 sn_add_sequence (ScreenInfo *screen_info, SnStartupSequence * sequence)
90 g_return_if_fail (screen_info != NULL);
91 g_return_if_fail (sequence != NULL);
93 sn_startup_sequence_ref (sequence);
94 screen_info->startup_sequences = g_slist_prepend (screen_info->startup_sequences, sequence);
96 if (screen_info->startup_sequence_timeout == 0)
98 screen_info->startup_sequence_timeout =
99 g_timeout_add (1000, sn_startup_sequence_timeout, screen_info);
101 sn_update_feedback (screen_info);
104 static void
105 sn_remove_sequence (ScreenInfo *screen_info, SnStartupSequence * sequence)
107 g_return_if_fail (screen_info != NULL);
108 g_return_if_fail (sequence != NULL);
110 screen_info->startup_sequences = g_slist_remove (screen_info->startup_sequences, sequence);
111 sn_startup_sequence_unref (sequence);
113 if ((screen_info->startup_sequences == NULL) && (screen_info->startup_sequence_timeout != 0))
115 g_source_remove (screen_info->startup_sequence_timeout);
116 screen_info->startup_sequence_timeout = 0;
118 sn_update_feedback (screen_info);
121 static void
122 sn_collect_timed_out_foreach (void *element, void *data)
124 CollectTimedOutData *ctod;
125 SnStartupSequence *sequence;
126 long tv_sec, tv_usec;
127 double elapsed;
129 g_return_if_fail (data != NULL);
130 g_return_if_fail (element != NULL);
132 sequence = element;
133 ctod = (CollectTimedOutData *) data;
134 sn_startup_sequence_get_last_active_time (sequence, &tv_sec, &tv_usec);
136 elapsed =
137 ((((double) ctod->now.tv_sec - tv_sec) * G_USEC_PER_SEC +
138 (ctod->now.tv_usec - tv_usec))) / 1000.0;
140 if (elapsed > STARTUP_TIMEOUT)
142 ctod->list = g_slist_prepend (ctod->list, sequence);
146 static gboolean
147 sn_startup_sequence_timeout (void *data)
149 ScreenInfo * screen_info;
150 CollectTimedOutData ctod;
151 GSList *tmp;
153 screen_info = (ScreenInfo *) data;
154 g_return_val_if_fail (screen_info != NULL, FALSE);
156 ctod.list = NULL;
157 g_get_current_time (&ctod.now);
158 g_slist_foreach (screen_info->startup_sequences, sn_collect_timed_out_foreach, &ctod);
160 tmp = ctod.list;
161 while (tmp != NULL)
163 SnStartupSequence *sequence = tmp->data;
165 sn_startup_sequence_complete (sequence);
167 tmp = tmp->next;
170 g_slist_free (ctod.list);
172 if (screen_info->startup_sequences != NULL)
174 return TRUE;
176 else
178 /* remove */
179 screen_info->startup_sequence_timeout = 0;
180 return FALSE;
184 static void
185 sn_screen_event (SnMonitorEvent * event, void *user_data)
187 const char *wmclass;
188 ScreenInfo *screen_info;
189 SnStartupSequence *sequence;
191 g_return_if_fail (event != NULL);
192 sequence = sn_monitor_event_get_startup_sequence (event);
194 screen_info = (ScreenInfo *) user_data;
195 g_return_if_fail (screen_info != NULL);
197 switch (sn_monitor_event_get_type (event))
199 case SN_MONITOR_EVENT_INITIATED:
200 wmclass = sn_startup_sequence_get_wmclass (sequence);
201 sn_add_sequence (screen_info, sequence);
202 break;
204 case SN_MONITOR_EVENT_COMPLETED:
205 sn_remove_sequence (screen_info, sn_monitor_event_get_startup_sequence (event));
206 break;
208 case SN_MONITOR_EVENT_CHANGED:
209 break;
211 case SN_MONITOR_EVENT_CANCELED:
212 default:
213 break;
217 void
218 sn_client_startup_properties (Client * c)
220 ScreenInfo *screen_info;
221 GSList *tmp;
222 SnStartupSequence *sequence;
223 char *startup_id;
225 g_return_if_fail (c != NULL);
227 startup_id = clientGetStartupId (c);
228 screen_info = c->screen_info;
229 sequence = NULL;
230 if (startup_id == NULL)
232 tmp = screen_info->startup_sequences;
233 while (tmp != NULL)
235 const char *wmclass;
237 wmclass = sn_startup_sequence_get_wmclass (tmp->data);
239 if ((wmclass != NULL) && ((c->class.res_class && !strcmp (wmclass, c->class.res_class))
240 || (c->class.res_name && !strcmp (wmclass, c->class.res_name))))
242 sequence = tmp->data;
244 free (c->startup_id);
245 c->startup_id = strdup (sn_startup_sequence_get_id (sequence));
246 startup_id = c->startup_id;
248 sn_startup_sequence_complete (sequence);
249 break;
252 tmp = tmp->next;
256 if (startup_id == NULL)
258 return;
261 if (sequence == NULL)
263 tmp = screen_info->startup_sequences;
264 while (tmp != NULL)
266 const char *id;
268 id = sn_startup_sequence_get_id (tmp->data);
270 if (!strcmp (id, startup_id))
272 sequence = tmp->data;
273 break;
276 tmp = tmp->next;
280 if (sequence != NULL)
282 int workspace;
283 Time timestamp;
285 /* Set initial time */
286 timestamp = sn_startup_sequence_get_timestamp (sequence);
287 TRACE ("Given startup time: %u", (unsigned int) timestamp);
288 if ((c->user_time == (Time) 0) || TIMESTAMP_IS_BEFORE(c->user_time, timestamp))
290 c->user_time = timestamp;
291 myDisplaySetLastUserTime (screen_info->display_info, c->user_time);
293 FLAG_SET (c->flags, CLIENT_FLAG_HAS_STARTUP_TIME);
295 /* Set initial workspace */
296 if (!FLAG_TEST (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET))
298 workspace = sn_startup_sequence_get_workspace (sequence);
299 if (workspace >= 0)
301 FLAG_SET (c->xfwm_flags, XFWM_FLAG_WORKSPACE_SET);
302 c->win_workspace = workspace;
308 void
309 sn_init_display (ScreenInfo *screen_info)
311 g_return_if_fail (screen_info != NULL);
312 g_return_if_fail (myScreenGetXDisplay (screen_info) != NULL);
314 if (!sn_display)
316 sn_display = sn_display_new (myScreenGetXDisplay (screen_info), sn_error_trap_push, sn_error_trap_pop);
318 screen_info->sn_context = NULL;
319 if (sn_display != NULL)
321 screen_info->sn_context =
322 sn_monitor_context_new (sn_display, screen_info->screen, sn_screen_event, screen_info, NULL);
324 screen_info->startup_sequences = NULL;
325 screen_info->startup_sequence_timeout = 0;
328 void
329 sn_close_display (void)
331 if (sn_display)
333 sn_display_unref (sn_display);
335 sn_display = NULL;
338 void
339 sn_process_event (XEvent * event)
341 g_return_if_fail (sn_display != NULL);
342 sn_display_process_event (sn_display, event);
345 #endif