2
* Copyright (C) 2007 Intel
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU General Public
15
* License along with this library; if not, write to the
16
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
* Boston, MA 02111-1307, USA.
19
* Authored by Neil Jagdish Patel <njp@o-hand.com>
31
#include <X11/Xutil.h>
33
#define SN_API_NOT_YET_FROZEN 1
36
#include "launcher-startup.h"
37
#include "launcher-menu.h"
38
#include "launcher-util.h"
40
G_DEFINE_TYPE (LauncherStartup, launcher_startup, G_TYPE_OBJECT)
42
#define LAUNCHER_STARTUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE(obj, \
43
LAUNCHER_TYPE_STARTUP, LauncherStartupPrivate))
45
#define TIMEOUT 3000 /* Miliseconds */
46
#define SN_TIMEOUT 10000
48
struct _LauncherStartupPrivate
50
GdkWindow *root_window;
51
SnDisplay *sn_display;
65
* Load settings from the desktop file, this is important for the launch
70
load_settings (LauncherItem *item,
72
gboolean *single_instance,
75
LauncherMenuApplication *app;
78
const gchar *filename;
81
g_return_if_fail (LAUNCHER_IS_ITEM (item));
83
app = NULL;//launcher_item_get_application (item);
85
/* Get the exec string */
86
exec = launcher_menu_application_get_exec (app);
91
/* Create an argv from the string */
92
*argv = launcher_util_exec_to_argv (exec);
95
key_file = g_key_file_new ();
96
filename = launcher_menu_application_get_desktop_filename (app);
98
if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &error))
100
g_key_file_free (key_file);
101
g_warning ("Unable to load Desktop File values: %s", error->message);
102
g_error_free (error);
106
*single_instance = g_key_file_get_boolean (key_file, "Desktop Entry",
107
"SingleInstance", NULL);
108
*sn_enable = g_key_file_get_boolean (key_file, "Desktop Entry",
109
"StartupNotify", NULL);
111
g_key_file_free (key_file);
115
load_app_settings (LauncherMenuApplication *app,
117
gboolean *single_instance,
121
GError *error = NULL;
122
const gchar *filename;
125
g_return_if_fail (app);
127
/* Get the exec string */
128
exec = launcher_menu_application_get_exec (app);
133
/* Create an argv from the string */
134
*argv = launcher_util_exec_to_argv (exec);
137
key_file = g_key_file_new ();
138
filename = launcher_menu_application_get_desktop_filename (app);
140
if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &error))
142
g_key_file_free (key_file);
143
g_warning ("Unable to load Desktop File values: %s", error->message);
144
g_error_free (error);
148
*single_instance = g_key_file_get_boolean (key_file, "Desktop Entry",
149
"SingleInstance", NULL);
150
*sn_enable = g_key_file_get_boolean (key_file, "Desktop Entry",
151
"StartupNotify", NULL);
153
g_key_file_free (key_file);
158
child_setup (gpointer user_data)
161
sn_launcher_context_setup_child_process (user_data);
165
sn_timeout (LauncherStartup *startup)
167
LauncherStartupPrivate *priv;
169
g_return_val_if_fail (LAUNCHER_IS_STARTUP (startup), FALSE);
170
priv = startup->priv;
173
if (!LAUNCHER_IS_ITEM (priv->active))
176
//launcher_item_launch_completed (priv->active);
177
g_strfreev (priv->argv);
187
launcher_startup_launch_item (LauncherStartup *startup, LauncherItem *item)
189
LauncherStartupPrivate *priv;
190
LauncherMenuApplication *app;
191
GError *error = NULL;
192
SnLauncherContext *context = NULL;
193
gboolean sn_enable = FALSE;;
194
gboolean single_instance = FALSE;
197
g_return_val_if_fail (LAUNCHER_IS_STARTUP (startup), FALSE);
198
priv = startup->priv;
201
app = NULL;//launcher_item_get_application (item);
203
/* Load the important settings from the desktop file if not already done */
204
load_settings (item, &sn_enable, &single_instance, &priv->argv);
212
display = priv->xdisplay;
213
sn_dpy = priv->sn_display;
215
screen = gdk_screen_get_number (gdk_screen_get_default ());
217
context = sn_launcher_context_new (sn_dpy, screen);
219
sn_launcher_context_set_name (context,
220
launcher_menu_application_get_name (app));
221
sn_launcher_context_set_binary_name (context, priv->argv[0]);
223
sn_launcher_context_initiate (context,
224
g_get_prgname () ?: "unknown",
226
CLUTTER_CURRENT_TIME);
229
/* Execute the program */
230
if (!gdk_spawn_on_screen (gdk_screen_get_default (),
231
NULL, priv->argv, NULL,
238
g_warning ("Cannot launch %s: %s", priv->argv[0], error->message);
239
g_error_free (error);
241
sn_launcher_context_complete (context);
244
g_strfreev (priv->argv);
248
launcher_menu_application_set_pid (app, pid);
251
* Let the program know that the launch has started, Sn apps get a longer
255
priv->tag = g_timeout_add (SN_TIMEOUT, (GSourceFunc)sn_timeout, startup);
257
priv->tag = g_timeout_add (TIMEOUT, (GSourceFunc)sn_timeout, startup);
264
launcher_startup_launch_app (LauncherStartup *startup,
265
LauncherMenuApplication *app)
267
LauncherStartupPrivate *priv;
268
GError *error = NULL;
269
SnLauncherContext *context = NULL;
270
gboolean sn_enable = FALSE;;
271
gboolean single_instance = FALSE;
272
WnckWindow *window = NULL;
275
g_return_val_if_fail (LAUNCHER_IS_STARTUP (startup), FALSE);
276
priv = startup->priv;
280
/* Check if a window by this name already exists */
281
if ((pid = launcher_menu_application_get_pid (app)) > 0 && 0)
283
GList *windows = wnck_screen_get_windows (wnck_screen_get_default ());
285
for (w = windows; w; w = w->next)
287
gint id = wnck_window_get_pid (w->data);
290
wnck_window_activate (w->data, CLUTTER_CURRENT_TIME);
291
launcher_menu_application_set_window (app, w->data);
292
g_debug ("Found existing window, pid = %d", pid);
297
window = launcher_menu_application_get_window (app);
298
if (WNCK_IS_WINDOW (window))
300
wnck_window_activate (window, CLUTTER_CURRENT_TIME);
304
/* Load the important settings from the desktop file if not already done */
305
load_app_settings (app, &sn_enable, &single_instance, &priv->argv);
313
display = priv->xdisplay;
314
sn_dpy = priv->sn_display;
316
screen = gdk_screen_get_number (gdk_screen_get_default ());
318
context = sn_launcher_context_new (sn_dpy, screen);
320
sn_launcher_context_set_name (context,
321
launcher_menu_application_get_name (app));
322
sn_launcher_context_set_binary_name (context, priv->argv[0]);
324
sn_launcher_context_initiate (context,
325
g_get_prgname () ?: "unknown",
327
CLUTTER_CURRENT_TIME);
330
/* Execute the program */
331
if (!gdk_spawn_on_screen (gdk_screen_get_default (),
332
NULL, priv->argv, NULL,
339
g_warning ("Cannot launch %s: %s", priv->argv[0], error->message);
340
g_error_free (error);
342
sn_launcher_context_complete (context);
345
g_strfreev (priv->argv);
349
launcher_menu_application_set_pid (app, pid);
352
* Let the program know that the launch has started, Sn apps get a longer
356
priv->tag = g_timeout_add (SN_TIMEOUT, (GSourceFunc)sn_timeout, startup);
358
priv->tag = g_timeout_add (TIMEOUT, (GSourceFunc)sn_timeout, startup);
363
* Startup monitoring functions
367
monitor_event_func (SnMonitorEvent *event, LauncherStartup *startup)
369
LauncherStartupPrivate *priv;
370
SnStartupSequence *seq;
373
g_return_if_fail (LAUNCHER_IS_STARTUP (startup));
374
priv = startup->priv;
376
if (sn_monitor_event_get_type (event) != SN_MONITOR_EVENT_COMPLETED)
379
/*if (!LAUNCHER_IS_ITEM (priv->active) || priv->argv == NULL)
382
seq = sn_monitor_event_get_startup_sequence (event);
383
b_name = sn_startup_sequence_get_binary_name (seq);
388
if (strcmp (priv->argv[0], b_name) == 0)
390
g_source_remove (priv->tag);
393
* Give some time for the main animation, otherwise apps that start too
394
* fast mess up the animation
396
priv->tag = g_timeout_add (1000, (GSourceFunc)sn_timeout, startup);
400
static GdkFilterReturn
401
filter_func (GdkXEvent *gdk_xevent,
403
LauncherStartup *startup)
406
xevent = (XEvent *) gdk_xevent;
409
g_return_val_if_fail (LAUNCHER_IS_STARTUP (startup), GDK_FILTER_CONTINUE);
411
ret = sn_display_process_event (startup->priv->sn_display, xevent);
413
return GDK_FILTER_CONTINUE;
416
/* GObject functions */
418
launcher_startup_dispose (GObject *object)
420
G_OBJECT_CLASS (launcher_startup_parent_class)->dispose (object);
424
launcher_startup_finalize (GObject *startup)
426
LauncherStartupPrivate *priv;
428
g_return_if_fail (LAUNCHER_IS_STARTUP (startup));
429
priv = LAUNCHER_STARTUP (startup)->priv;
432
G_OBJECT_CLASS (launcher_startup_parent_class)->finalize (startup);
437
launcher_startup_class_init (LauncherStartupClass *klass)
439
GObjectClass *obj_class = G_OBJECT_CLASS (klass);
441
obj_class->finalize = launcher_startup_finalize;
442
obj_class->dispose = launcher_startup_dispose;
444
g_type_class_add_private (obj_class, sizeof (LauncherStartupPrivate));
448
launcher_startup_init (LauncherStartup *startup)
450
LauncherStartupPrivate *priv;
451
SnMonitorContext *context;
453
priv = startup->priv = LAUNCHER_STARTUP_GET_PRIVATE (startup);
456
priv->xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
457
priv->sn_display = sn_display_new (priv->xdisplay, NULL, NULL);
459
context = sn_monitor_context_new (priv->sn_display,
460
DefaultScreen (priv->xdisplay),
461
(SnMonitorEventFunc)monitor_event_func,
466
* We have to select for property events on at least one root window (but
467
* not all and INITIATE messages go to all root windows
469
XSelectInput (priv->xdisplay,
470
DefaultRootWindow (priv->xdisplay), PropertyChangeMask);
472
priv->root_window = gdk_window_lookup_for_display (
473
gdk_x11_lookup_xdisplay (priv->xdisplay), 0);
475
gdk_window_add_filter (priv->root_window,
476
(GdkFilterFunc)filter_func,
481
launcher_startup_get_default (void)
483
static LauncherStartup *startup = NULL;
486
startup = g_object_new (LAUNCHER_TYPE_STARTUP,