1/* gdkapplaunchcontext.c - Gtk+ implementation for GAppLaunchContext
2
3 Copyright (C) 2007 Red Hat, Inc.
4
5 The Gnome Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The Gnome Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library. If not, see <http://www.gnu.org/licenses/>.
17
18 Author: Alexander Larsson <alexl@redhat.com>
19*/
20
21#include "config.h"
22
23#include "gdkapplaunchcontextprivate.h"
24#include "gdkscreen.h"
25#include "gdkintl.h"
26
27
28/**
29 * SECTION:gdkapplaunchcontext
30 * @Short_description: Startup notification for applications
31 * @Title: Application launching
32 *
33 * GdkAppLaunchContext is an implementation of #GAppLaunchContext that
34 * handles launching an application in a graphical context. It provides
35 * startup notification and allows to launch applications on a specific
36 * screen or workspace.
37 *
38 * ## Launching an application
39 *
40 * |[<!-- language="C" -->
41 * GdkAppLaunchContext *context;
42 *
43 * context = gdk_display_get_app_launch_context (display);
44 *
45 * gdk_app_launch_context_set_screen (screen);
46 * gdk_app_launch_context_set_timestamp (event->time);
47 *
48 * if (!g_app_info_launch_default_for_uri ("http://www.gtk.org", context, &error))
49 * g_warning ("Launching failed: %s\n", error->message);
50 *
51 * g_object_unref (context);
52 * ]|
53 */
54
55
56static void gdk_app_launch_context_finalize (GObject *object);
57static gchar * gdk_app_launch_context_get_display (GAppLaunchContext *context,
58 GAppInfo *info,
59 GList *files);
60static gchar * gdk_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
61 GAppInfo *info,
62 GList *files);
63static void gdk_app_launch_context_launch_failed (GAppLaunchContext *context,
64 const gchar *startup_notify_id);
65
66
67enum
68{
69 PROP_0,
70 PROP_DISPLAY
71};
72
73G_DEFINE_TYPE (GdkAppLaunchContext, gdk_app_launch_context, G_TYPE_APP_LAUNCH_CONTEXT)
74
75static void
76gdk_app_launch_context_get_property (GObject *object,
77 guint prop_id,
78 GValue *value,
79 GParamSpec *pspec)
80{
81 GdkAppLaunchContext *context = GDK_APP_LAUNCH_CONTEXT (object);
82
83 switch (prop_id)
84 {
85 case PROP_DISPLAY:
86 g_value_set_object (value, context->display);
87 break;
88 default:
89 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
90 }
91}
92
93static void
94gdk_app_launch_context_set_property (GObject *object,
95 guint prop_id,
96 const GValue *value,
97 GParamSpec *pspec)
98{
99 GdkAppLaunchContext *context = GDK_APP_LAUNCH_CONTEXT (object);
100
101 switch (prop_id)
102 {
103 case PROP_DISPLAY:
104 context->display = g_value_dup_object (value);
105 break;
106 default:
107 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
108 }
109}
110
111static void
112gdk_app_launch_context_class_init (GdkAppLaunchContextClass *klass)
113{
114 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
115 GAppLaunchContextClass *context_class = G_APP_LAUNCH_CONTEXT_CLASS (klass);
116
117 gobject_class->set_property = gdk_app_launch_context_set_property,
118 gobject_class->get_property = gdk_app_launch_context_get_property;
119
120 gobject_class->finalize = gdk_app_launch_context_finalize;
121
122 context_class->get_display = gdk_app_launch_context_get_display;
123 context_class->get_startup_notify_id = gdk_app_launch_context_get_startup_notify_id;
124 context_class->launch_failed = gdk_app_launch_context_launch_failed;
125
126 g_object_class_install_property (gobject_class, PROP_DISPLAY,
127 g_param_spec_object ("display", P_("Display"), P_("Display"),
128 GDK_TYPE_DISPLAY,
129 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
130}
131
132static void
133gdk_app_launch_context_init (GdkAppLaunchContext *context)
134{
135 context->workspace = -1;
136}
137
138static void
139gdk_app_launch_context_finalize (GObject *object)
140{
141 GdkAppLaunchContext *context = GDK_APP_LAUNCH_CONTEXT (object);
142
143 if (context->display)
144 g_object_unref (context->display);
145
146 if (context->screen)
147 g_object_unref (context->screen);
148
149 if (context->icon)
150 g_object_unref (context->icon);
151
152 g_free (context->icon_name);
153
154 G_OBJECT_CLASS (gdk_app_launch_context_parent_class)->finalize (object);
155}
156
157static gchar *
158gdk_app_launch_context_get_display (GAppLaunchContext *context,
159 GAppInfo *info,
160 GList *files)
161{
162 GdkAppLaunchContext *ctx = GDK_APP_LAUNCH_CONTEXT (context);
163 GdkDisplay *display;
164
165 if (ctx->screen)
166 return gdk_screen_make_display_name (ctx->screen);
167
168 if (ctx->display)
169 display = ctx->display;
170 else
171 display = gdk_display_get_default ();
172
173 return g_strdup (gdk_display_get_name (display));
174}
175
176/**
177 * gdk_app_launch_context_set_display:
178 * @context: a #GdkAppLaunchContext
179 * @display: a #GdkDisplay
180 *
181 * Sets the display on which applications will be launched when
182 * using this context. See also gdk_app_launch_context_set_screen().
183 *
184 * Since: 2.14
185 *
186 * Deprecated: 3.0: Use gdk_display_get_app_launch_context() instead
187 */
188void
189gdk_app_launch_context_set_display (GdkAppLaunchContext *context,
190 GdkDisplay *display)
191{
192 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
193 g_return_if_fail (display == NULL || GDK_IS_DISPLAY (display));
194
195 g_warn_if_fail (display == NULL || display == context->display);
196}
197
198/**
199 * gdk_app_launch_context_set_screen:
200 * @context: a #GdkAppLaunchContext
201 * @screen: a #GdkScreen
202 *
203 * Sets the screen on which applications will be launched when
204 * using this context. See also gdk_app_launch_context_set_display().
205 *
206 * If both @screen and @display are set, the @screen takes priority.
207 * If neither @screen or @display are set, the default screen and
208 * display are used.
209 *
210 * Since: 2.14
211 */
212void
213gdk_app_launch_context_set_screen (GdkAppLaunchContext *context,
214 GdkScreen *screen)
215{
216 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
217 g_return_if_fail (screen == NULL || GDK_IS_SCREEN (screen));
218
219 g_return_if_fail (screen == NULL || gdk_screen_get_display (screen) == context->display);
220
221 if (context->screen)
222 {
223 g_object_unref (context->screen);
224 context->screen = NULL;
225 }
226
227 if (screen)
228 context->screen = g_object_ref (screen);
229}
230
231/**
232 * gdk_app_launch_context_set_desktop:
233 * @context: a #GdkAppLaunchContext
234 * @desktop: the number of a workspace, or -1
235 *
236 * Sets the workspace on which applications will be launched when
237 * using this context when running under a window manager that
238 * supports multiple workspaces, as described in the
239 * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec).
240 *
241 * When the workspace is not specified or @desktop is set to -1,
242 * it is up to the window manager to pick one, typically it will
243 * be the current workspace.
244 *
245 * Since: 2.14
246 */
247void
248gdk_app_launch_context_set_desktop (GdkAppLaunchContext *context,
249 gint desktop)
250{
251 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
252
253 context->workspace = desktop;
254}
255
256/**
257 * gdk_app_launch_context_set_timestamp:
258 * @context: a #GdkAppLaunchContext
259 * @timestamp: a timestamp
260 *
261 * Sets the timestamp of @context. The timestamp should ideally
262 * be taken from the event that triggered the launch.
263 *
264 * Window managers can use this information to avoid moving the
265 * focus to the newly launched application when the user is busy
266 * typing in another window. This is also known as 'focus stealing
267 * prevention'.
268 *
269 * Since: 2.14
270 */
271void
272gdk_app_launch_context_set_timestamp (GdkAppLaunchContext *context,
273 guint32 timestamp)
274{
275 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
276
277 context->timestamp = timestamp;
278}
279
280/**
281 * gdk_app_launch_context_set_icon:
282 * @context: a #GdkAppLaunchContext
283 * @icon: (allow-none): a #GIcon, or %NULL
284 *
285 * Sets the icon for applications that are launched with this
286 * context.
287 *
288 * Window Managers can use this information when displaying startup
289 * notification.
290 *
291 * See also gdk_app_launch_context_set_icon_name().
292 *
293 * Since: 2.14
294 */
295void
296gdk_app_launch_context_set_icon (GdkAppLaunchContext *context,
297 GIcon *icon)
298{
299 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
300 g_return_if_fail (icon == NULL || G_IS_ICON (icon));
301
302 if (context->icon)
303 {
304 g_object_unref (context->icon);
305 context->icon = NULL;
306 }
307
308 if (icon)
309 context->icon = g_object_ref (icon);
310}
311
312/**
313 * gdk_app_launch_context_set_icon_name:
314 * @context: a #GdkAppLaunchContext
315 * @icon_name: (allow-none): an icon name, or %NULL
316 *
317 * Sets the icon for applications that are launched with this context.
318 * The @icon_name will be interpreted in the same way as the Icon field
319 * in desktop files. See also gdk_app_launch_context_set_icon().
320 *
321 * If both @icon and @icon_name are set, the @icon_name takes priority.
322 * If neither @icon or @icon_name is set, the icon is taken from either
323 * the file that is passed to launched application or from the #GAppInfo
324 * for the launched application itself.
325 *
326 * Since: 2.14
327 */
328void
329gdk_app_launch_context_set_icon_name (GdkAppLaunchContext *context,
330 const char *icon_name)
331{
332 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
333
334 g_free (context->icon_name);
335 context->icon_name = g_strdup (icon_name);
336}
337
338/**
339 * gdk_app_launch_context_new:
340 *
341 * Creates a new #GdkAppLaunchContext.
342 *
343 * Returns: a new #GdkAppLaunchContext
344 *
345 * Since: 2.14
346 *
347 * Deprecated: 3.0: Use gdk_display_get_app_launch_context() instead
348 */
349GdkAppLaunchContext *
350gdk_app_launch_context_new (void)
351{
352 return gdk_display_get_app_launch_context (gdk_display_get_default ());
353}
354
355static char *
356gdk_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
357 GAppInfo *info,
358 GList *files)
359{
360 return NULL;
361}
362
363static void
364gdk_app_launch_context_launch_failed (GAppLaunchContext *context,
365 const gchar *startup_notify_id)
366{
367}
368