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 
56 static void    gdk_app_launch_context_finalize    (GObject           *object);
57 static gchar * gdk_app_launch_context_get_display (GAppLaunchContext *context,
58                                                    GAppInfo          *info,
59                                                    GList             *files);
60 static gchar * gdk_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
61                                                              GAppInfo          *info,
62                                                              GList             *files);
63 static void    gdk_app_launch_context_launch_failed (GAppLaunchContext *context,
64                                                      const gchar       *startup_notify_id);
65 
66 
67 enum
68 {
69   PROP_0,
70   PROP_DISPLAY
71 };
72 
G_DEFINE_TYPE(GdkAppLaunchContext,gdk_app_launch_context,G_TYPE_APP_LAUNCH_CONTEXT)73 G_DEFINE_TYPE (GdkAppLaunchContext, gdk_app_launch_context, G_TYPE_APP_LAUNCH_CONTEXT)
74 
75 static void
76 gdk_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 
93 static void
gdk_app_launch_context_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)94 gdk_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 
111 static void
gdk_app_launch_context_class_init(GdkAppLaunchContextClass * klass)112 gdk_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 
132 static void
gdk_app_launch_context_init(GdkAppLaunchContext * context)133 gdk_app_launch_context_init (GdkAppLaunchContext *context)
134 {
135   context->workspace = -1;
136 }
137 
138 static void
gdk_app_launch_context_finalize(GObject * object)139 gdk_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 
157 static gchar *
gdk_app_launch_context_get_display(GAppLaunchContext * context,GAppInfo * info,GList * files)158 gdk_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 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
166   if (ctx->screen)
167     return gdk_screen_make_display_name (ctx->screen);
168 G_GNUC_END_IGNORE_DEPRECATIONS
169 
170   if (ctx->display)
171     display = ctx->display;
172   else
173     display = gdk_display_get_default ();
174 
175   return g_strdup (gdk_display_get_name (display));
176 }
177 
178 /**
179  * gdk_app_launch_context_set_display:
180  * @context: a #GdkAppLaunchContext
181  * @display: a #GdkDisplay
182  *
183  * Sets the display on which applications will be launched when
184  * using this context. See also gdk_app_launch_context_set_screen().
185  *
186  * Since: 2.14
187  *
188  * Deprecated: 3.0: Use gdk_display_get_app_launch_context() instead
189  */
190 void
gdk_app_launch_context_set_display(GdkAppLaunchContext * context,GdkDisplay * display)191 gdk_app_launch_context_set_display (GdkAppLaunchContext *context,
192                                     GdkDisplay          *display)
193 {
194   g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
195   g_return_if_fail (display == NULL || GDK_IS_DISPLAY (display));
196 
197   g_warn_if_fail (display == NULL || display == context->display);
198 }
199 
200 /**
201  * gdk_app_launch_context_set_screen:
202  * @context: a #GdkAppLaunchContext
203  * @screen: a #GdkScreen
204  *
205  * Sets the screen on which applications will be launched when
206  * using this context. See also gdk_app_launch_context_set_display().
207  *
208  * If both @screen and @display are set, the @screen takes priority.
209  * If neither @screen or @display are set, the default screen and
210  * display are used.
211  *
212  * Since: 2.14
213  */
214 void
gdk_app_launch_context_set_screen(GdkAppLaunchContext * context,GdkScreen * screen)215 gdk_app_launch_context_set_screen (GdkAppLaunchContext *context,
216                                    GdkScreen           *screen)
217 {
218   g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
219   g_return_if_fail (screen == NULL || GDK_IS_SCREEN (screen));
220 
221   g_return_if_fail (screen == NULL || gdk_screen_get_display (screen) == context->display);
222 
223   if (context->screen)
224     {
225       g_object_unref (context->screen);
226       context->screen = NULL;
227     }
228 
229   if (screen)
230     context->screen = g_object_ref (screen);
231 }
232 
233 /**
234  * gdk_app_launch_context_set_desktop:
235  * @context: a #GdkAppLaunchContext
236  * @desktop: the number of a workspace, or -1
237  *
238  * Sets the workspace on which applications will be launched when
239  * using this context when running under a window manager that
240  * supports multiple workspaces, as described in the
241  * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec).
242  *
243  * When the workspace is not specified or @desktop is set to -1,
244  * it is up to the window manager to pick one, typically it will
245  * be the current workspace.
246  *
247  * Since: 2.14
248  */
249 void
gdk_app_launch_context_set_desktop(GdkAppLaunchContext * context,gint desktop)250 gdk_app_launch_context_set_desktop (GdkAppLaunchContext *context,
251                                     gint                 desktop)
252 {
253   g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
254 
255   context->workspace = desktop;
256 }
257 
258 /**
259  * gdk_app_launch_context_set_timestamp:
260  * @context: a #GdkAppLaunchContext
261  * @timestamp: a timestamp
262  *
263  * Sets the timestamp of @context. The timestamp should ideally
264  * be taken from the event that triggered the launch.
265  *
266  * Window managers can use this information to avoid moving the
267  * focus to the newly launched application when the user is busy
268  * typing in another window. This is also known as 'focus stealing
269  * prevention'.
270  *
271  * Since: 2.14
272  */
273 void
gdk_app_launch_context_set_timestamp(GdkAppLaunchContext * context,guint32 timestamp)274 gdk_app_launch_context_set_timestamp (GdkAppLaunchContext *context,
275                                       guint32              timestamp)
276 {
277   g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
278 
279   context->timestamp = timestamp;
280 }
281 
282 /**
283  * gdk_app_launch_context_set_icon:
284  * @context: a #GdkAppLaunchContext
285  * @icon: (allow-none): a #GIcon, or %NULL
286  *
287  * Sets the icon for applications that are launched with this
288  * context.
289  *
290  * Window Managers can use this information when displaying startup
291  * notification.
292  *
293  * See also gdk_app_launch_context_set_icon_name().
294  *
295  * Since: 2.14
296  */
297 void
gdk_app_launch_context_set_icon(GdkAppLaunchContext * context,GIcon * icon)298 gdk_app_launch_context_set_icon (GdkAppLaunchContext *context,
299                                  GIcon               *icon)
300 {
301   g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
302   g_return_if_fail (icon == NULL || G_IS_ICON (icon));
303 
304   if (context->icon)
305     {
306       g_object_unref (context->icon);
307       context->icon = NULL;
308     }
309 
310   if (icon)
311     context->icon = g_object_ref (icon);
312 }
313 
314 /**
315  * gdk_app_launch_context_set_icon_name:
316  * @context: a #GdkAppLaunchContext
317  * @icon_name: (allow-none): an icon name, or %NULL
318  *
319  * Sets the icon for applications that are launched with this context.
320  * The @icon_name will be interpreted in the same way as the Icon field
321  * in desktop files. See also gdk_app_launch_context_set_icon().
322  *
323  * If both @icon and @icon_name are set, the @icon_name takes priority.
324  * If neither @icon or @icon_name is set, the icon is taken from either
325  * the file that is passed to launched application or from the #GAppInfo
326  * for the launched application itself.
327  *
328  * Since: 2.14
329  */
330 void
gdk_app_launch_context_set_icon_name(GdkAppLaunchContext * context,const char * icon_name)331 gdk_app_launch_context_set_icon_name (GdkAppLaunchContext *context,
332                                       const char          *icon_name)
333 {
334   g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
335 
336   g_free (context->icon_name);
337   context->icon_name = g_strdup (icon_name);
338 }
339 
340 /**
341  * gdk_app_launch_context_new:
342  *
343  * Creates a new #GdkAppLaunchContext.
344  *
345  * Returns: a new #GdkAppLaunchContext
346  *
347  * Since: 2.14
348  *
349  * Deprecated: 3.0: Use gdk_display_get_app_launch_context() instead
350  */
351 GdkAppLaunchContext *
gdk_app_launch_context_new(void)352 gdk_app_launch_context_new (void)
353 {
354   return gdk_display_get_app_launch_context (gdk_display_get_default ());
355 }
356 
357 static char *
gdk_app_launch_context_get_startup_notify_id(GAppLaunchContext * context,GAppInfo * info,GList * files)358 gdk_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
359                                               GAppInfo          *info,
360                                               GList             *files)
361 {
362  return NULL;
363 }
364 
365 static void
gdk_app_launch_context_launch_failed(GAppLaunchContext * context,const gchar * startup_notify_id)366 gdk_app_launch_context_launch_failed (GAppLaunchContext *context,
367                                       const gchar       *startup_notify_id)
368 {
369 }
370