Lines 44-49
Link Here
|
44 |
#undef GNOME_DISABLE_DEPRECATED |
44 |
#undef GNOME_DISABLE_DEPRECATED |
45 |
#include <libgnome/gnome-desktop-item.h> |
45 |
#include <libgnome/gnome-desktop-item.h> |
46 |
|
46 |
|
|
|
47 |
#ifdef HAVE_STARTUP_NOTIFICATION |
48 |
#define SN_API_NOT_YET_FROZEN |
49 |
#include <libsn/sn.h> |
50 |
#include <gdk/gdk.h> |
51 |
#include <gdk/gdkx.h> |
52 |
#endif |
53 |
|
47 |
static GHashTable *files = NULL; |
54 |
static GHashTable *files = NULL; |
48 |
static GHashTable *mime_table = NULL; |
55 |
static GHashTable *mime_table = NULL; |
49 |
|
56 |
|
Lines 458-463
Link Here
|
458 |
return permission; |
465 |
return permission; |
459 |
} |
466 |
} |
460 |
|
467 |
|
|
|
468 |
/* Copied from nautilus-program-choosing.c */ |
469 |
|
470 |
extern char **environ; |
471 |
|
472 |
/* Cut and paste from gdkspawn-x11.c */ |
473 |
static gchar ** |
474 |
my_gdk_spawn_make_environment_for_screen (GdkScreen *screen, |
475 |
gchar **envp) |
476 |
{ |
477 |
gchar **retval = NULL; |
478 |
gchar *display_name; |
479 |
gint display_index = -1; |
480 |
gint i, env_len; |
481 |
|
482 |
g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); |
483 |
|
484 |
if (envp == NULL) |
485 |
envp = environ; |
486 |
|
487 |
for (env_len = 0; envp[env_len]; env_len++) |
488 |
if (strncmp (envp[env_len], "DISPLAY", strlen ("DISPLAY")) == 0) |
489 |
display_index = env_len; |
490 |
|
491 |
retval = g_new (char *, env_len + 1); |
492 |
retval[env_len] = NULL; |
493 |
|
494 |
display_name = gdk_screen_make_display_name (screen); |
495 |
|
496 |
for (i = 0; i < env_len; i++) |
497 |
if (i == display_index) |
498 |
retval[i] = g_strconcat ("DISPLAY=", display_name, NULL); |
499 |
else |
500 |
retval[i] = g_strdup (envp[i]); |
501 |
|
502 |
g_assert (i == env_len); |
503 |
|
504 |
g_free (display_name); |
505 |
|
506 |
return retval; |
507 |
} |
508 |
|
509 |
#ifdef HAVE_STARTUP_NOTIFICATION |
510 |
static void |
511 |
sn_error_trap_push (SnDisplay *display, |
512 |
Display *xdisplay) |
513 |
{ |
514 |
gdk_error_trap_push (); |
515 |
} |
516 |
|
517 |
static void |
518 |
sn_error_trap_pop (SnDisplay *display, |
519 |
Display *xdisplay) |
520 |
{ |
521 |
gdk_error_trap_pop (); |
522 |
} |
523 |
|
524 |
static char ** |
525 |
make_spawn_environment_for_sn_context (SnLauncherContext *sn_context, |
526 |
char **envp) |
527 |
{ |
528 |
char **retval; |
529 |
int i, j; |
530 |
|
531 |
retval = NULL; |
532 |
|
533 |
if (envp == NULL) { |
534 |
envp = environ; |
535 |
} |
536 |
|
537 |
for (i = 0; envp[i]; i++) { |
538 |
/* Count length */ |
539 |
} |
540 |
|
541 |
retval = g_new (char *, i + 2); |
542 |
|
543 |
for (i = 0, j = 0; envp[i]; i++) { |
544 |
if (!g_str_has_prefix (envp[i], "DESKTOP_STARTUP_ID=")) { |
545 |
retval[j] = g_strdup (envp[i]); |
546 |
++j; |
547 |
} |
548 |
} |
549 |
|
550 |
retval[j] = g_strdup_printf ("DESKTOP_STARTUP_ID=%s", |
551 |
sn_launcher_context_get_startup_id (sn_context)); |
552 |
++j; |
553 |
retval[j] = NULL; |
554 |
|
555 |
return retval; |
556 |
} |
557 |
|
558 |
/* This should be fairly long, as it's confusing to users if a startup |
559 |
* ends when it shouldn't (it appears that the startup failed, and |
560 |
* they have to relaunch the app). Also the timeout only matters when |
561 |
* there are bugs and apps don't end their own startup sequence. |
562 |
* |
563 |
* This timeout is a "last resort" timeout that ignores whether the |
564 |
* startup sequence has shown activity or not. Metacity and the |
565 |
* tasklist have smarter, and correspondingly able-to-be-shorter |
566 |
* timeouts. The reason our timeout is dumb is that we don't monitor |
567 |
* the sequence (don't use an SnMonitorContext) |
568 |
*/ |
569 |
#define STARTUP_TIMEOUT_LENGTH (30 /* seconds */ * 1000) |
570 |
|
571 |
typedef struct |
572 |
{ |
573 |
GdkScreen *screen; |
574 |
GSList *contexts; |
575 |
guint timeout_id; |
576 |
} StartupTimeoutData; |
577 |
|
578 |
static void |
579 |
free_startup_timeout (void *data) |
580 |
{ |
581 |
StartupTimeoutData *std; |
582 |
|
583 |
std = data; |
584 |
|
585 |
g_slist_foreach (std->contexts, |
586 |
(GFunc) sn_launcher_context_unref, |
587 |
NULL); |
588 |
g_slist_free (std->contexts); |
589 |
|
590 |
if (std->timeout_id != 0) { |
591 |
g_source_remove (std->timeout_id); |
592 |
std->timeout_id = 0; |
593 |
} |
594 |
|
595 |
g_free (std); |
596 |
} |
597 |
|
598 |
static gboolean |
599 |
startup_timeout (void *data) |
600 |
{ |
601 |
StartupTimeoutData *std; |
602 |
GSList *tmp; |
603 |
GTimeVal now; |
604 |
int min_timeout; |
605 |
|
606 |
std = data; |
607 |
|
608 |
min_timeout = STARTUP_TIMEOUT_LENGTH; |
609 |
|
610 |
g_get_current_time (&now); |
611 |
|
612 |
tmp = std->contexts; |
613 |
while (tmp != NULL) { |
614 |
SnLauncherContext *sn_context; |
615 |
GSList *next; |
616 |
long tv_sec, tv_usec; |
617 |
double elapsed; |
618 |
|
619 |
sn_context = tmp->data; |
620 |
next = tmp->next; |
621 |
|
622 |
sn_launcher_context_get_last_active_time (sn_context, |
623 |
&tv_sec, &tv_usec); |
624 |
|
625 |
elapsed = |
626 |
((((double)now.tv_sec - tv_sec) * G_USEC_PER_SEC + |
627 |
(now.tv_usec - tv_usec))) / 1000.0; |
628 |
|
629 |
if (elapsed >= STARTUP_TIMEOUT_LENGTH) { |
630 |
std->contexts = g_slist_remove (std->contexts, |
631 |
sn_context); |
632 |
sn_launcher_context_complete (sn_context); |
633 |
sn_launcher_context_unref (sn_context); |
634 |
} else { |
635 |
min_timeout = MIN (min_timeout, (STARTUP_TIMEOUT_LENGTH - elapsed)); |
636 |
} |
637 |
|
638 |
tmp = next; |
639 |
} |
640 |
|
641 |
if (std->contexts == NULL) { |
642 |
std->timeout_id = 0; |
643 |
} else { |
644 |
std->timeout_id = g_timeout_add (min_timeout, |
645 |
startup_timeout, |
646 |
std); |
647 |
} |
648 |
|
649 |
/* always remove this one, but we may have reinstalled another one. */ |
650 |
return FALSE; |
651 |
} |
652 |
|
653 |
static void |
654 |
add_startup_timeout (GdkScreen *screen, |
655 |
SnLauncherContext *sn_context) |
656 |
{ |
657 |
StartupTimeoutData *data; |
658 |
|
659 |
data = g_object_get_data (G_OBJECT (screen), "nautilus-startup-data"); |
660 |
if (data == NULL) { |
661 |
data = g_new (StartupTimeoutData, 1); |
662 |
data->screen = screen; |
663 |
data->contexts = NULL; |
664 |
data->timeout_id = 0; |
665 |
|
666 |
g_object_set_data_full (G_OBJECT (screen), "nautilus-startup-data", |
667 |
data, free_startup_timeout); |
668 |
} |
669 |
|
670 |
sn_launcher_context_ref (sn_context); |
671 |
data->contexts = g_slist_prepend (data->contexts, sn_context); |
672 |
|
673 |
if (data->timeout_id == 0) { |
674 |
data->timeout_id = g_timeout_add (STARTUP_TIMEOUT_LENGTH, |
675 |
startup_timeout, |
676 |
data); |
677 |
} |
678 |
} |
679 |
|
680 |
#endif /* HAVE_STARTUP_NOTIFICATION */ |
681 |
|
682 |
gboolean |
683 |
ephy_file_launch_application (GnomeVFSMimeApplication *application, |
684 |
const char *parameter, |
685 |
guint32 user_time) |
686 |
{ |
687 |
GdkScreen *screen; |
688 |
GList *uris = NULL; |
689 |
char *uri; |
690 |
char **envp; |
691 |
GnomeVFSResult result; |
692 |
#ifdef HAVE_STARTUP_NOTIFICATION |
693 |
SnLauncherContext *sn_context; |
694 |
SnDisplay *sn_display; |
695 |
#endif |
696 |
|
697 |
g_return_val_if_fail (application != NULL, FALSE); |
698 |
g_return_val_if_fail (parameter != NULL, FALSE); |
699 |
|
700 |
uri = gnome_vfs_make_uri_canonical (parameter); |
701 |
if (uri == NULL) return FALSE; |
702 |
|
703 |
uris = g_list_prepend (NULL, uri); |
704 |
|
705 |
screen = gdk_screen_get_default (); |
706 |
envp = my_gdk_spawn_make_environment_for_screen (screen, NULL); |
707 |
|
708 |
#ifdef HAVE_STARTUP_NOTIFICATION |
709 |
sn_display = sn_display_new (gdk_display, |
710 |
sn_error_trap_push, |
711 |
sn_error_trap_pop); |
712 |
|
713 |
|
714 |
/* Only initiate notification if application supports it. */ |
715 |
if (gnome_vfs_mime_application_supports_startup_notification (application)) |
716 |
{ |
717 |
char *name; |
718 |
|
719 |
sn_context = sn_launcher_context_new (sn_display, |
720 |
screen ? gdk_screen_get_number (screen) : |
721 |
DefaultScreen (gdk_display)); |
722 |
|
723 |
name = g_filename_display_basename (uri); |
724 |
if (name != NULL) { |
725 |
char *description; |
726 |
|
727 |
sn_launcher_context_set_name (sn_context, name); |
728 |
|
729 |
/* FIXME: i18n after string freeze! */ |
730 |
description = g_strdup_printf ("Opening %s", name); |
731 |
|
732 |
sn_launcher_context_set_description (sn_context, description); |
733 |
|
734 |
g_free (name); |
735 |
g_free (description); |
736 |
} |
737 |
|
738 |
if (!sn_launcher_context_get_initiated (sn_context)) { |
739 |
const char *binary_name; |
740 |
char **old_envp; |
741 |
|
742 |
binary_name = gnome_vfs_mime_application_get_binary_name (application); |
743 |
|
744 |
sn_launcher_context_set_binary_name (sn_context, |
745 |
binary_name); |
746 |
|
747 |
sn_launcher_context_initiate (sn_context, |
748 |
g_get_prgname () ? g_get_prgname () : "unknown", |
749 |
binary_name, |
750 |
(Time) user_time); |
751 |
|
752 |
old_envp = envp; |
753 |
envp = make_spawn_environment_for_sn_context (sn_context, envp); |
754 |
g_strfreev (old_envp); |
755 |
} |
756 |
} else { |
757 |
sn_context = NULL; |
758 |
} |
759 |
#endif /* HAVE_STARTUP_NOTIFICATION */ |
760 |
|
761 |
result = gnome_vfs_mime_application_launch_with_env (application, uris, envp); |
762 |
|
763 |
#ifdef HAVE_STARTUP_NOTIFICATION |
764 |
if (sn_context != NULL) { |
765 |
if (result != GNOME_VFS_OK) { |
766 |
sn_launcher_context_complete (sn_context); /* end sequence */ |
767 |
} else { |
768 |
add_startup_timeout (screen ? screen : |
769 |
gdk_display_get_default_screen (gdk_display_get_default ()), |
770 |
sn_context); |
771 |
} |
772 |
sn_launcher_context_unref (sn_context); |
773 |
} |
774 |
|
775 |
sn_display_unref (sn_display); |
776 |
#endif /* HAVE_STARTUP_NOTIFICATION */ |
777 |
|
778 |
g_strfreev (envp); |
779 |
g_list_foreach (uris, (GFunc) g_free,NULL); |
780 |
g_list_free (uris); |
781 |
|
782 |
if (result != GNOME_VFS_OK) |
783 |
{ |
784 |
g_warning ("Cannot launch application '%s'\n", |
785 |
gnome_vfs_mime_application_get_name (application)); |
786 |
} |
787 |
|
788 |
return result == GNOME_VFS_OK; |
789 |
} |
790 |
|
791 |
/* End cut-paste-adapt from nautilus */ |
792 |
|
461 |
static int |
793 |
static int |
462 |
launch_desktop_item (const char *desktop_file, |
794 |
launch_desktop_item (const char *desktop_file, |
463 |
const char *parameter, |
795 |
const char *parameter, |
Lines 529-565
Link Here
|
529 |
} |
861 |
} |
530 |
|
862 |
|
531 |
gboolean |
863 |
gboolean |
532 |
ephy_file_launch_application (GnomeVFSMimeApplication *application, |
|
|
533 |
const char *parameter, |
534 |
guint32 user_time) |
535 |
{ |
536 |
GError *error = NULL; |
537 |
const char *desktop_file; |
538 |
int ret = -1; |
539 |
|
540 |
g_return_val_if_fail (application != NULL, FALSE); |
541 |
g_return_val_if_fail (parameter != NULL, FALSE); |
542 |
|
543 |
desktop_file = gnome_vfs_mime_application_get_desktop_file_path (application); |
544 |
if (desktop_file != NULL) |
545 |
{ |
546 |
ret = launch_desktop_item (desktop_file, parameter, user_time, &error); |
547 |
} |
548 |
|
549 |
if (ret == -1 || error != NULL) |
550 |
{ |
551 |
/* FIXME We should really warn the user here */ |
552 |
|
553 |
g_warning ("Cannot launch application '%s': %s\n", |
554 |
gnome_vfs_mime_application_get_name (application), |
555 |
error ? error->message : "(unknown error)"); |
556 |
g_clear_error (&error); |
557 |
} |
558 |
|
559 |
return ret >= 0; |
560 |
} |
561 |
|
562 |
gboolean |
563 |
ephy_file_launch_handler (const char *mime_type, |
864 |
ephy_file_launch_handler (const char *mime_type, |
564 |
const char *address, |
865 |
const char *address, |
565 |
guint32 user_time) |
866 |
guint32 user_time) |