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 "gdkdisplay.h"
25 #include "gdkintl.h"
26
27
28 /**
29 * GdkAppLaunchContext:
30 *
31 * `GdkAppLaunchContext` handles launching an application in a graphical context.
32 *
33 * It is an implementation of `GAppLaunchContext` that provides startup
34 * notification and allows to launch applications on a specific screen
35 * or workspace.
36 *
37 * ## Launching an application
38 *
39 * ```c
40 * GdkAppLaunchContext *context;
41 *
42 * context = gdk_display_get_app_launch_context (display);
43 *
44 * gdk_app_launch_context_set_display (display);
45 * gdk_app_launch_context_set_timestamp (gdk_event_get_time (event));
46 *
47 * if (!g_app_info_launch_default_for_uri ("http://www.gtk.org", context, &error))
48 * g_warning ("Launching failed: %s\n", error->message);
49 *
50 * g_object_unref (context);
51 * ```
52 */
53
54 static void gdk_app_launch_context_finalize (GObject *object);
55 static char * gdk_app_launch_context_get_display_name (GAppLaunchContext *context,
56 GAppInfo *info,
57 GList *files);
58 static char * gdk_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
59 GAppInfo *info,
60 GList *files);
61 static void gdk_app_launch_context_launch_failed (GAppLaunchContext *context,
62 const char *startup_notify_id);
63
64
65 enum
66 {
67 PROP_0,
68 PROP_DISPLAY
69 };
70
G_DEFINE_TYPE(GdkAppLaunchContext,gdk_app_launch_context,G_TYPE_APP_LAUNCH_CONTEXT)71 G_DEFINE_TYPE (GdkAppLaunchContext, gdk_app_launch_context, G_TYPE_APP_LAUNCH_CONTEXT)
72
73 static void
74 gdk_app_launch_context_get_property (GObject *object,
75 guint prop_id,
76 GValue *value,
77 GParamSpec *pspec)
78 {
79 GdkAppLaunchContext *context = GDK_APP_LAUNCH_CONTEXT (object);
80
81 switch (prop_id)
82 {
83 case PROP_DISPLAY:
84 g_value_set_object (value, context->display);
85 break;
86 default:
87 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
88 }
89 }
90
91 static void
gdk_app_launch_context_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)92 gdk_app_launch_context_set_property (GObject *object,
93 guint prop_id,
94 const GValue *value,
95 GParamSpec *pspec)
96 {
97 GdkAppLaunchContext *context = GDK_APP_LAUNCH_CONTEXT (object);
98
99 switch (prop_id)
100 {
101 case PROP_DISPLAY:
102 context->display = g_value_dup_object (value);
103 break;
104 default:
105 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
106 }
107 }
108
109 static void
gdk_app_launch_context_class_init(GdkAppLaunchContextClass * klass)110 gdk_app_launch_context_class_init (GdkAppLaunchContextClass *klass)
111 {
112 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
113 GAppLaunchContextClass *context_class = G_APP_LAUNCH_CONTEXT_CLASS (klass);
114
115 gobject_class->set_property = gdk_app_launch_context_set_property,
116 gobject_class->get_property = gdk_app_launch_context_get_property;
117
118 gobject_class->finalize = gdk_app_launch_context_finalize;
119
120 context_class->get_display = gdk_app_launch_context_get_display_name;
121 context_class->get_startup_notify_id = gdk_app_launch_context_get_startup_notify_id;
122 context_class->launch_failed = gdk_app_launch_context_launch_failed;
123
124 /**
125 * GdkAppLaunchContext:display: (attributes org.gtk.Property.get=gdk_app_launch_context_get_display)
126 *
127 * The display that the `GdkAppLaunchContext` is on.
128 */
129 g_object_class_install_property (gobject_class, PROP_DISPLAY,
130 g_param_spec_object ("display", P_("Display"), P_("Display"),
131 GDK_TYPE_DISPLAY,
132 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
133 }
134
135 static void
gdk_app_launch_context_init(GdkAppLaunchContext * context)136 gdk_app_launch_context_init (GdkAppLaunchContext *context)
137 {
138 context->workspace = -1;
139 }
140
141 static void
gdk_app_launch_context_finalize(GObject * object)142 gdk_app_launch_context_finalize (GObject *object)
143 {
144 GdkAppLaunchContext *context = GDK_APP_LAUNCH_CONTEXT (object);
145
146 if (context->display)
147 g_object_unref (context->display);
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 char *
gdk_app_launch_context_get_display_name(GAppLaunchContext * context,GAppInfo * info,GList * files)158 gdk_app_launch_context_get_display_name (GAppLaunchContext *context,
159 GAppInfo *info,
160 GList *files)
161 {
162 GdkAppLaunchContext *ctx = GDK_APP_LAUNCH_CONTEXT (context);
163 GdkDisplay *display;
164
165 if (ctx->display)
166 display = ctx->display;
167 else
168 display = gdk_display_get_default ();
169
170 return g_strdup (gdk_display_get_name (display));
171 }
172
173 /**
174 * gdk_app_launch_context_get_display: (attributes org.gtk.Method.get_property=display)
175 * @context: a `GdkAppLaunchContext`
176 *
177 * Gets the `GdkDisplay` that @context is for.
178 *
179 * Returns: (transfer none): the display of @context
180 */
181 GdkDisplay *
gdk_app_launch_context_get_display(GdkAppLaunchContext * context)182 gdk_app_launch_context_get_display (GdkAppLaunchContext *context)
183 {
184 g_return_val_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context), NULL);
185
186 return context->display;
187 }
188
189 /**
190 * gdk_app_launch_context_set_desktop:
191 * @context: a `GdkAppLaunchContext`
192 * @desktop: the number of a workspace, or -1
193 *
194 * Sets the workspace on which applications will be launched.
195 *
196 * This only works when running under a window manager that
197 * supports multiple workspaces, as described in the
198 * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec).
199 *
200 * When the workspace is not specified or @desktop is set to -1,
201 * it is up to the window manager to pick one, typically it will
202 * be the current workspace.
203 */
204 void
gdk_app_launch_context_set_desktop(GdkAppLaunchContext * context,int desktop)205 gdk_app_launch_context_set_desktop (GdkAppLaunchContext *context,
206 int desktop)
207 {
208 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
209
210 context->workspace = desktop;
211 }
212
213 /**
214 * gdk_app_launch_context_set_timestamp:
215 * @context: a `GdkAppLaunchContext`
216 * @timestamp: a timestamp
217 *
218 * Sets the timestamp of @context.
219 *
220 * The timestamp should ideally be taken from the event that
221 * triggered the launch.
222 *
223 * Window managers can use this information to avoid moving the
224 * focus to the newly launched application when the user is busy
225 * typing in another window. This is also known as 'focus stealing
226 * prevention'.
227 */
228 void
gdk_app_launch_context_set_timestamp(GdkAppLaunchContext * context,guint32 timestamp)229 gdk_app_launch_context_set_timestamp (GdkAppLaunchContext *context,
230 guint32 timestamp)
231 {
232 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
233
234 context->timestamp = timestamp;
235 }
236
237 /**
238 * gdk_app_launch_context_set_icon:
239 * @context: a `GdkAppLaunchContext`
240 * @icon: (nullable): a `GIcon`
241 *
242 * Sets the icon for applications that are launched with this
243 * context.
244 *
245 * Window Managers can use this information when displaying startup
246 * notification.
247 *
248 * See also [method@Gdk.AppLaunchContext.set_icon_name].
249 */
250 void
gdk_app_launch_context_set_icon(GdkAppLaunchContext * context,GIcon * icon)251 gdk_app_launch_context_set_icon (GdkAppLaunchContext *context,
252 GIcon *icon)
253 {
254 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
255 g_return_if_fail (icon == NULL || G_IS_ICON (icon));
256
257 if (context->icon)
258 {
259 g_object_unref (context->icon);
260 context->icon = NULL;
261 }
262
263 if (icon)
264 context->icon = g_object_ref (icon);
265 }
266
267 /**
268 * gdk_app_launch_context_set_icon_name:
269 * @context: a `GdkAppLaunchContext`
270 * @icon_name: (nullable): an icon name
271 *
272 * Sets the icon for applications that are launched with this context.
273 *
274 * The @icon_name will be interpreted in the same way as the Icon field
275 * in desktop files. See also [method@Gdk.AppLaunchContext.set_icon].
276 *
277 * If both @icon and @icon_name are set, the @icon_name takes priority.
278 * If neither @icon or @icon_name is set, the icon is taken from either
279 * the file that is passed to launched application or from the `GAppInfo`
280 * for the launched application itself.
281 */
282 void
gdk_app_launch_context_set_icon_name(GdkAppLaunchContext * context,const char * icon_name)283 gdk_app_launch_context_set_icon_name (GdkAppLaunchContext *context,
284 const char *icon_name)
285 {
286 g_return_if_fail (GDK_IS_APP_LAUNCH_CONTEXT (context));
287
288 g_free (context->icon_name);
289 context->icon_name = g_strdup (icon_name);
290 }
291
292 static char *
gdk_app_launch_context_get_startup_notify_id(GAppLaunchContext * context,GAppInfo * info,GList * files)293 gdk_app_launch_context_get_startup_notify_id (GAppLaunchContext *context,
294 GAppInfo *info,
295 GList *files)
296 {
297 return NULL;
298 }
299
300 static void
gdk_app_launch_context_launch_failed(GAppLaunchContext * context,const char * startup_notify_id)301 gdk_app_launch_context_launch_failed (GAppLaunchContext *context,
302 const char *startup_notify_id)
303 {
304 }
305