1 /* GIO - GLib Input, Output and Streaming Library 2 * 3 * Copyright (C) 2006-2007 Red Hat, Inc. 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2 of the License, or (at your option) any later version. 9 * 10 * This 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 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General 16 * Public License along with this library; if not, write to the 17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 18 * Boston, MA 02111-1307, USA. 19 * 20 * Author: Alexander Larsson <alexl (at) redhat.com> 21 */ 22 23 #include "config.h" 24 #include "gappinfo.h" 25 #include "glibintl.h" 26 #include <gioerror.h> 27 #include <gfile.h> 28 29 #include "gioalias.h" 30 31 /** 32 * SECTION:gappinfo 33 * @short_description: Application information and launch contexts 34 * @include: gio/gio.h 35 * 36 * #GAppInfo and #GAppLaunchContext are used for describing and launching 37 * applications installed on the system. 38 * 39 * As of GLib 2.20, URIs will always be converted to POSIX paths 40 * (using g_file_get_path()) when using g_app_info_launch() even if 41 * the application requested an URI and not a POSIX path. For example 42 * for an desktop-file based application with Exec key <literal>totem 43 * %%U</literal> and a single URI, 44 * <literal>sftp://foo/file.avi</literal>, then 45 * <literal>/home/user/.gvfs/sftp on foo/file.avi</literal> will be 46 * passed. This will only work if a set of suitable GIO extensions 47 * (such as gvfs 2.26 compiled with FUSE support), is available and 48 * operational; if this is not the case, the URI will be passed 49 * unmodified to the application. Some URIs, such as 50 * <literal>mailto:</literal>, of course cannot be mapped to a POSIX 51 * path (in gvfs there's no FUSE mount for it); such URIs will be 52 * passed unmodified to the application. 53 * 54 * Specifically for gvfs 2.26 and later, the POSIX URI will be mapped 55 * back to the GIO URI in the #GFile constructors (since gvfs 56 * implements the #GVfs extension point). As such, if the application 57 * needs to examine the URI, it needs to use g_file_get_uri() or 58 * similar on #GFile. In other words, an application cannot assume 59 * that the URI passed to e.g. g_file_new_for_commandline_arg() is 60 * equal to the result of g_file_get_uri(). The following snippet 61 * illustrates this: 62 * 63 * <programlisting> 64 * GFile *f; 65 * char *uri; 66 * 67 * file = g_file_new_for_commandline_arg (uri_from_commandline); 68 * 69 * uri = g_file_get_uri (file); 70 * strcmp (uri, uri_from_commandline) == 0; // FALSE 71 * g_free (uri); 72 * 73 * if (g_file_has_uri_scheme (file, "cdda")) 74 * { 75 * // do something special with uri 76 * } 77 * g_object_unref (file); 78 * </programlisting> 79 * 80 * This code will work when both <literal>cdda://sr0/Track 81 * 1.wav</literal> and <literal>/home/user/.gvfs/cdda on sr0/Track 82 * 1.wav</literal> is passed to the application. It should be noted 83 * that it's generally not safe for applications to rely on the format 84 * of a particular URIs. Different launcher applications (e.g. file 85 * managers) may have different ideas of what a given URI means. 86 * 87 **/ 88 89 static void g_app_info_base_init (gpointer g_class); 90 static void g_app_info_class_init (gpointer g_class, 91 gpointer class_data); 92 93 94 GType 95 g_app_info_get_type (void) 96 { 97 static volatile gsize g_define_type_id__volatile = 0; 98 99 if (g_once_init_enter (&g_define_type_id__volatile)) 100 { 101 const GTypeInfo app_info_info = 102 { 103 sizeof (GAppInfoIface), /* class_size */ 104 g_app_info_base_init, /* base_init */ 105 NULL, /* base_finalize */ 106 g_app_info_class_init, 107 NULL, /* class_finalize */ 108 NULL, /* class_data */ 109 0, 110 0, /* n_preallocs */ 111 NULL 112 }; 113 GType g_define_type_id = 114 g_type_register_static (G_TYPE_INTERFACE, I_("GAppInfo"), 115 &app_info_info, 0); 116 117 g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT); 118 119 g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); 120 } 121 122 return g_define_type_id__volatile; 123 } 124 125 static void 126 g_app_info_class_init (gpointer g_class, 127 gpointer class_data) 128 { 129 } 130 131 static void 132 g_app_info_base_init (gpointer g_class) 133 { 134 } 135 136 137 /** 138 * g_app_info_dup: 139 * @appinfo: a #GAppInfo. 140 * 141 * Creates a duplicate of a #GAppInfo. 142 * 143 * Returns: a duplicate of @appinfo. 144 **/ 145 GAppInfo * 146 g_app_info_dup (GAppInfo *appinfo) 147 { 148 GAppInfoIface *iface; 149 150 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); 151 152 iface = G_APP_INFO_GET_IFACE (appinfo); 153 154 return (* iface->dup) (appinfo); 155 } 156 157 /** 158 * g_app_info_equal: 159 * @appinfo1: the first #GAppInfo. 160 * @appinfo2: the second #GAppInfo. 161 * 162 * Checks if two #GAppInfos are equal. 163 * 164 * Returns: %TRUE if @appinfo1 is equal to @appinfo2. %FALSE otherwise. 165 **/ 166 gboolean 167 g_app_info_equal (GAppInfo *appinfo1, 168 GAppInfo *appinfo2) 169 { 170 GAppInfoIface *iface; 171 172 g_return_val_if_fail (G_IS_APP_INFO (appinfo1), FALSE); 173 g_return_val_if_fail (G_IS_APP_INFO (appinfo2), FALSE); 174 175 if (G_TYPE_FROM_INSTANCE (appinfo1) != G_TYPE_FROM_INSTANCE (appinfo2)) 176 return FALSE; 177 178 iface = G_APP_INFO_GET_IFACE (appinfo1); 179 180 return (* iface->equal) (appinfo1, appinfo2); 181 } 182 183 /** 184 * g_app_info_get_id: 185 * @appinfo: a #GAppInfo. 186 * 187 * Gets the ID of an application. An id is a string that 188 * identifies the application. The exact format of the id is 189 * platform dependent. For instance, on Unix this is the 190 * desktop file id from the xdg menu specification. 191 * 192 * Note that the returned ID may be %NULL, depending on how 193 * the @appinfo has been constructed. 194 * 195 * Returns: a string containing the application's ID. 196 **/ 197 const char * 198 g_app_info_get_id (GAppInfo *appinfo) 199 { 200 GAppInfoIface *iface; 201 202 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); 203 204 iface = G_APP_INFO_GET_IFACE (appinfo); 205 206 return (* iface->get_id) (appinfo); 207 } 208 209 /** 210 * g_app_info_get_name: 211 * @appinfo: a #GAppInfo. 212 * 213 * Gets the installed name of the application. 214 * 215 * Returns: the name of the application for @appinfo. 216 **/ 217 const char * 218 g_app_info_get_name (GAppInfo *appinfo) 219 { 220 GAppInfoIface *iface; 221 222 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); 223 224 iface = G_APP_INFO_GET_IFACE (appinfo); 225 226 return (* iface->get_name) (appinfo); 227 } 228 229 /** 230 * g_app_info_get_description: 231 * @appinfo: a #GAppInfo. 232 * 233 * Gets a human-readable description of an installed application. 234 * 235 * Returns: a string containing a description of the 236 * application @appinfo, or %NULL if none. 237 **/ 238 const char * 239 g_app_info_get_description (GAppInfo *appinfo) 240 { 241 GAppInfoIface *iface; 242 243 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); 244 245 iface = G_APP_INFO_GET_IFACE (appinfo); 246 247 return (* iface->get_description) (appinfo); 248 } 249 250 /** 251 * g_app_info_get_executable: 252 * @appinfo: a #GAppInfo 253 * 254 * Gets the executable's name for the installed application. 255 * 256 * Returns: a string containing the @appinfo's application 257 * binary's name 258 **/ 259 const char * 260 g_app_info_get_executable (GAppInfo *appinfo) 261 { 262 GAppInfoIface *iface; 263 264 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); 265 266 iface = G_APP_INFO_GET_IFACE (appinfo); 267 268 return (* iface->get_executable) (appinfo); 269 } 270 271 272 /** 273 * g_app_info_get_commandline: 274 * @appinfo: a #GAppInfo 275 * 276 * Gets the commandline with which the application will be 277 * started. 278 * 279 * Returns: a string containing the @appinfo's commandline, 280 * or %NULL if this information is not available 281 * 282 * Since: 2.20 283 **/ 284 const char * 285 g_app_info_get_commandline (GAppInfo *appinfo) 286 { 287 GAppInfoIface *iface; 288 289 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); 290 291 iface = G_APP_INFO_GET_IFACE (appinfo); 292 293 if (iface->get_commandline) 294 return (* iface->get_commandline) (appinfo); 295 296 return NULL; 297 } 298 299 /** 300 * g_app_info_set_as_default_for_type: 301 * @appinfo: a #GAppInfo. 302 * @content_type: the content type. 303 * @error: a #GError. 304 * 305 * Sets the application as the default handler for a given type. 306 * 307 * Returns: %TRUE on success, %FALSE on error. 308 **/ 309 gboolean 310 g_app_info_set_as_default_for_type (GAppInfo *appinfo, 311 const char *content_type, 312 GError **error) 313 { 314 GAppInfoIface *iface; 315 316 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 317 g_return_val_if_fail (content_type != NULL, FALSE); 318 319 iface = G_APP_INFO_GET_IFACE (appinfo); 320 321 return (* iface->set_as_default_for_type) (appinfo, content_type, error); 322 } 323 324 325 /** 326 * g_app_info_set_as_default_for_extension: 327 * @appinfo: a #GAppInfo. 328 * @extension: a string containing the file extension (without the dot). 329 * @error: a #GError. 330 * 331 * Sets the application as the default handler for the given file extention. 332 * 333 * Returns: %TRUE on success, %FALSE on error. 334 **/ 335 gboolean 336 g_app_info_set_as_default_for_extension (GAppInfo *appinfo, 337 const char *extension, 338 GError **error) 339 { 340 GAppInfoIface *iface; 341 342 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 343 g_return_val_if_fail (extension != NULL, FALSE); 344 345 iface = G_APP_INFO_GET_IFACE (appinfo); 346 347 if (iface->set_as_default_for_extension) 348 return (* iface->set_as_default_for_extension) (appinfo, extension, error); 349 350 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, 351 "g_app_info_set_as_default_for_extension not supported yet"); 352 return FALSE; 353 } 354 355 356 /** 357 * g_app_info_add_supports_type: 358 * @appinfo: a #GAppInfo. 359 * @content_type: a string. 360 * @error: a #GError. 361 * 362 * Adds a content type to the application information to indicate the 363 * application is capable of opening files with the given content type. 364 * 365 * Returns: %TRUE on success, %FALSE on error. 366 **/ 367 gboolean 368 g_app_info_add_supports_type (GAppInfo *appinfo, 369 const char *content_type, 370 GError **error) 371 { 372 GAppInfoIface *iface; 373 374 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 375 g_return_val_if_fail (content_type != NULL, FALSE); 376 377 iface = G_APP_INFO_GET_IFACE (appinfo); 378 379 if (iface->add_supports_type) 380 return (* iface->add_supports_type) (appinfo, content_type, error); 381 382 g_set_error_literal (error, G_IO_ERROR, 383 G_IO_ERROR_NOT_SUPPORTED, 384 "g_app_info_add_supports_type not supported yet"); 385 386 return FALSE; 387 } 388 389 390 /** 391 * g_app_info_can_remove_supports_type: 392 * @appinfo: a #GAppInfo. 393 * 394 * Checks if a supported content type can be removed from an application. 395 * 396 * Returns: %TRUE if it is possible to remove supported 397 * content types from a given @appinfo, %FALSE if not. 398 **/ 399 gboolean 400 g_app_info_can_remove_supports_type (GAppInfo *appinfo) 401 { 402 GAppInfoIface *iface; 403 404 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 405 406 iface = G_APP_INFO_GET_IFACE (appinfo); 407 408 if (iface->can_remove_supports_type) 409 return (* iface->can_remove_supports_type) (appinfo); 410 411 return FALSE; 412 } 413 414 415 /** 416 * g_app_info_remove_supports_type: 417 * @appinfo: a #GAppInfo. 418 * @content_type: a string. 419 * @error: a #GError. 420 * 421 * Removes a supported type from an application, if possible. 422 * 423 * Returns: %TRUE on success, %FALSE on error. 424 **/ 425 gboolean 426 g_app_info_remove_supports_type (GAppInfo *appinfo, 427 const char *content_type, 428 GError **error) 429 { 430 GAppInfoIface *iface; 431 432 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 433 g_return_val_if_fail (content_type != NULL, FALSE); 434 435 iface = G_APP_INFO_GET_IFACE (appinfo); 436 437 if (iface->remove_supports_type) 438 return (* iface->remove_supports_type) (appinfo, content_type, error); 439 440 g_set_error_literal (error, G_IO_ERROR, 441 G_IO_ERROR_NOT_SUPPORTED, 442 "g_app_info_remove_supports_type not supported yet"); 443 444 return FALSE; 445 } 446 447 448 /** 449 * g_app_info_get_icon: 450 * @appinfo: a #GAppInfo. 451 * 452 * Gets the icon for the application. 453 * 454 * Returns: the default #GIcon for @appinfo. 455 **/ 456 GIcon * 457 g_app_info_get_icon (GAppInfo *appinfo) 458 { 459 GAppInfoIface *iface; 460 461 g_return_val_if_fail (G_IS_APP_INFO (appinfo), NULL); 462 463 iface = G_APP_INFO_GET_IFACE (appinfo); 464 465 return (* iface->get_icon) (appinfo); 466 } 467 468 469 /** 470 * g_app_info_launch: 471 * @appinfo: a #GAppInfo 472 * @files: a #GList of #GFile objects 473 * @launch_context: a #GAppLaunchContext or %NULL 474 * @error: a #GError 475 * 476 * Launches the application. Passes @files to the launched application 477 * as arguments, using the optional @launch_context to get information 478 * about the details of the launcher (like what screen it is on). 479 * On error, @error will be set accordingly. 480 * 481 * To lauch the application without arguments pass a %NULL @files list. 482 * 483 * Note that even if the launch is successful the application launched 484 * can fail to start if it runs into problems during startup. There is 485 * no way to detect this. 486 * 487 * Some URIs can be changed when passed through a GFile (for instance 488 * unsupported uris with strange formats like mailto:), so if you have 489 * a textual uri you want to pass in as argument, consider using 490 * g_app_info_launch_uris() instead. 491 * 492 * Returns: %TRUE on successful launch, %FALSE otherwise. 493 **/ 494 gboolean 495 g_app_info_launch (GAppInfo *appinfo, 496 GList *files, 497 GAppLaunchContext *launch_context, 498 GError **error) 499 { 500 GAppInfoIface *iface; 501 502 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 503 504 iface = G_APP_INFO_GET_IFACE (appinfo); 505 506 return (* iface->launch) (appinfo, files, launch_context, error); 507 } 508 509 510 /** 511 * g_app_info_supports_uris: 512 * @appinfo: a #GAppInfo. 513 * 514 * Checks if the application supports reading files and directories from URIs. 515 * 516 * Returns: %TRUE if the @appinfo supports URIs. 517 **/ 518 gboolean 519 g_app_info_supports_uris (GAppInfo *appinfo) 520 { 521 GAppInfoIface *iface; 522 523 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 524 525 iface = G_APP_INFO_GET_IFACE (appinfo); 526 527 return (* iface->supports_uris) (appinfo); 528 } 529 530 531 /** 532 * g_app_info_supports_files: 533 * @appinfo: a #GAppInfo. 534 * 535 * Checks if the application accepts files as arguments. 536 * 537 * Returns: %TRUE if the @appinfo supports files. 538 **/ 539 gboolean 540 g_app_info_supports_files (GAppInfo *appinfo) 541 { 542 GAppInfoIface *iface; 543 544 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 545 546 iface = G_APP_INFO_GET_IFACE (appinfo); 547 548 return (* iface->supports_files) (appinfo); 549 } 550 551 552 /** 553 * g_app_info_launch_uris: 554 * @appinfo: a #GAppInfo 555 * @uris: a #GList containing URIs to launch. 556 * @launch_context: a #GAppLaunchContext or %NULL 557 * @error: a #GError 558 * 559 * Launches the application. Passes @uris to the launched application 560 * as arguments, using the optional @launch_context to get information 561 * about the details of the launcher (like what screen it is on). 562 * On error, @error will be set accordingly. 563 * 564 * To lauch the application without arguments pass a %NULL @uris list. 565 * 566 * Note that even if the launch is successful the application launched 567 * can fail to start if it runs into problems during startup. There is 568 * no way to detect this. 569 * 570 * Returns: %TRUE on successful launch, %FALSE otherwise. 571 **/ 572 gboolean 573 g_app_info_launch_uris (GAppInfo *appinfo, 574 GList *uris, 575 GAppLaunchContext *launch_context, 576 GError **error) 577 { 578 GAppInfoIface *iface; 579 580 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 581 582 iface = G_APP_INFO_GET_IFACE (appinfo); 583 584 return (* iface->launch_uris) (appinfo, uris, launch_context, error); 585 } 586 587 588 /** 589 * g_app_info_should_show: 590 * @appinfo: a #GAppInfo. 591 * 592 * Checks if the application info should be shown in menus that 593 * list available applications. 594 * 595 * Returns: %TRUE if the @appinfo should be shown, %FALSE otherwise. 596 **/ 597 gboolean 598 g_app_info_should_show (GAppInfo *appinfo) 599 { 600 GAppInfoIface *iface; 601 602 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 603 604 iface = G_APP_INFO_GET_IFACE (appinfo); 605 606 return (* iface->should_show) (appinfo); 607 } 608 609 /** 610 * g_app_info_launch_default_for_uri: 611 * @uri: the uri to show 612 * @launch_context: an optional #GAppLaunchContext. 613 * @error: a #GError. 614 * 615 * Utility function that launches the default application 616 * registered to handle the specified uri. Synchronous I/O 617 * is done on the uri to detect the type of the file if 618 * required. 619 * 620 * Returns: %TRUE on success, %FALSE on error. 621 **/ 622 gboolean 623 g_app_info_launch_default_for_uri (const char *uri, 624 GAppLaunchContext *launch_context, 625 GError **error) 626 { 627 GAppInfo *app_info; 628 GFile *file; 629 GList l; 630 gboolean res; 631 632 file = g_file_new_for_uri (uri); 633 app_info = g_file_query_default_handler (file, NULL, error); 634 g_object_unref (file); 635 if (app_info == NULL) 636 return FALSE; 637 638 /* Use the uri, not the GFile, as the GFile roundtrip may 639 * affect the uri which we don't want (for instance for a 640 * mailto: uri). 641 */ 642 l.data = (char *)uri; 643 l.next = l.prev = NULL; 644 res = g_app_info_launch_uris (app_info, &l, 645 launch_context, error); 646 647 g_object_unref (app_info); 648 649 return res; 650 } 651 652 /** 653 * g_app_info_can_delete: 654 * @appinfo: a #GAppInfo 655 * 656 * Obtains the information whether the GAppInfo can be deleted. 657 * See g_app_info_delete(). 658 * 659 * Returns: %TRUE if @appinfo can be deleted 660 * 661 * Since: 2.20 662 */ 663 gboolean 664 g_app_info_can_delete (GAppInfo *appinfo) 665 { 666 GAppInfoIface *iface; 667 668 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 669 670 iface = G_APP_INFO_GET_IFACE (appinfo); 671 672 if (iface->can_delete) 673 return (* iface->can_delete) (appinfo); 674 675 return FALSE; 676 } 677 678 679 /** 680 * g_app_info_delete: 681 * @appinfo: a #GAppInfo 682 * 683 * Tries to delete an #GAppInfo. 684 * 685 * On some platforms, there may be a difference between user-defined 686 * #GAppInfo<!-- -->s which can be deleted, and system-wide ones which 687 * cannot. See g_app_info_can_delete(). 688 * 689 * Returns: %TRUE if @appinfo has been deleted 690 * 691 * Since: 2.20 692 */ 693 gboolean 694 g_app_info_delete (GAppInfo *appinfo) 695 { 696 GAppInfoIface *iface; 697 698 g_return_val_if_fail (G_IS_APP_INFO (appinfo), FALSE); 699 700 iface = G_APP_INFO_GET_IFACE (appinfo); 701 702 if (iface->do_delete) 703 return (* iface->do_delete) (appinfo); 704 705 return FALSE; 706 } 707 708 709 G_DEFINE_TYPE (GAppLaunchContext, g_app_launch_context, G_TYPE_OBJECT); 710 711 /** 712 * g_app_launch_context_new: 713 * 714 * Creates a new application launch context. This is not normally used, 715 * instead you instantiate a subclass of this, such as #GdkAppLaunchContext. 716 * 717 * Returns: a #GAppLaunchContext. 718 **/ 719 GAppLaunchContext * 720 g_app_launch_context_new (void) 721 { 722 return g_object_new (G_TYPE_APP_LAUNCH_CONTEXT, NULL); 723 } 724 725 static void 726 g_app_launch_context_class_init (GAppLaunchContextClass *klass) 727 { 728 } 729 730 static void 731 g_app_launch_context_init (GAppLaunchContext *launch_context) 732 { 733 } 734 735 /** 736 * g_app_launch_context_get_display: 737 * @context: a #GAppLaunchContext 738 * @info: a #GAppInfo 739 * @files: a #GList of #GFile objects 740 * 741 * Gets the display string for the display. This is used to ensure new 742 * applications are started on the same display as the launching 743 * application. 744 * 745 * Returns: a display string for the display. 746 **/ 747 char * 748 g_app_launch_context_get_display (GAppLaunchContext *context, 749 GAppInfo *info, 750 GList *files) 751 { 752 GAppLaunchContextClass *class; 753 754 g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL); 755 g_return_val_if_fail (G_IS_APP_INFO (info), NULL); 756 757 class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context); 758 759 if (class->get_display == NULL) 760 return NULL; 761 762 return class->get_display (context, info, files); 763 } 764 765 /** 766 * g_app_launch_context_get_startup_notify_id: 767 * @context: a #GAppLaunchContext 768 * @info: a #GAppInfo 769 * @files: a #GList of of #GFile objects 770 * 771 * Initiates startup notification for the application and returns the 772 * DESKTOP_STARTUP_ID for the launched operation, if supported. 773 * 774 * Startup notification IDs are defined in the <ulink 775 * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt"> 776 * FreeDesktop.Org Startup Notifications standard</ulink>. 777 * 778 * Returns: a startup notification ID for the application, or %NULL if 779 * not supported. 780 **/ 781 char * 782 g_app_launch_context_get_startup_notify_id (GAppLaunchContext *context, 783 GAppInfo *info, 784 GList *files) 785 { 786 GAppLaunchContextClass *class; 787 788 g_return_val_if_fail (G_IS_APP_LAUNCH_CONTEXT (context), NULL); 789 g_return_val_if_fail (G_IS_APP_INFO (info), NULL); 790 791 class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context); 792 793 if (class->get_startup_notify_id == NULL) 794 return NULL; 795 796 return class->get_startup_notify_id (context, info, files); 797 } 798 799 800 /** 801 * g_app_launch_context_launch_failed: 802 * @context: a #GAppLaunchContext. 803 * @startup_notify_id: the startup notification id that was returned by g_app_launch_context_get_startup_notify_id(). 804 * 805 * Called when an application has failed to launch, so that it can cancel 806 * the application startup notification started in g_app_launch_context_get_startup_notify_id(). 807 * 808 **/ 809 void 810 g_app_launch_context_launch_failed (GAppLaunchContext *context, 811 const char *startup_notify_id) 812 { 813 GAppLaunchContextClass *class; 814 815 g_return_if_fail (G_IS_APP_LAUNCH_CONTEXT (context)); 816 g_return_if_fail (startup_notify_id != NULL); 817 818 class = G_APP_LAUNCH_CONTEXT_GET_CLASS (context); 819 820 if (class->launch_failed != NULL) 821 class->launch_failed (context, startup_notify_id); 822 } 823 824 825 #define __G_APP_INFO_C__ 826 #include "gioaliasdef.c" 827