1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
/*
* Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by Pawel Stolowski <pawel.stolowski@canonical.com>
*/
[CCode (gir_namespace = "UnityExtras", gir_version = "1.0")]
namespace Unity.Extras
{
private static const string FILE_MANAGER_DBUS_NAME = "org.freedesktop.FileManager1";
private static const string FILE_MANAGER_DBUS_PATH = "/org/freedesktop/FileManager1";
public delegate void CreateScopeCallback ();
[DBus (name = "org.freedesktop.FileManager1")]
internal interface FileManagerInterface: GLib.Object
{
public abstract async void show_items (string[] uris, string startup_id) throws Error;
/* These methods are currently unused
public abstract async void show_folders (string[] uris, string startup_id) throws Error;
public abstract async void show_item_properties (string[] uris, string startup_id) throws Error;*/
}
/**
* Opens file manager showing given uri in its parent folder.
* It tries to activate file manager using org.freedesktop.FileManager1 interface first and if it fails,
* uses GLib.AppInfo.launch_default_for_uri.
*/
public async void show_in_folder (string uri) throws Error
{
string[] uris = {uri};
var file = File.new_for_uri (uri);
if (file != null)
{
File? parent_dir = file.get_parent ();
if (parent_dir != null)
{
// try to launch file manager via dbus interface first
try
{
FileManagerInterface service = yield Bus.get_proxy (BusType.SESSION, FILE_MANAGER_DBUS_NAME, FILE_MANAGER_DBUS_PATH);
yield service.show_items (uris, "");
return;
}
catch (GLib.Error e)
{
warning ("Failed to activate file manager via dbus: '%s', uri '%s'", e.message, uri);
}
// fallback
GLib.AppInfo.launch_default_for_uri (parent_dir.get_uri (), null); // may throw
return;
}
else
{
throw new GLib.IOError.FAILED ("Failed to get parent dir for uri: '%s'".printf (uri));
}
}
else
{
throw new GLib.IOError.FAILED ("Failed to create file object for uri: '%s'".printf (uri));
}
}
/**
* Check if a given well known DBus is owned. Failure (exception) means ownership couldn't be determined.
* WARNING: This does sync IO!
*
* @param name DBus name to test for availability
* @return true if name is available
*/
public static bool dbus_name_has_owner (string name) throws Error
{
bool has_owner;
DBusConnection bus = Bus.get_sync (BusType.SESSION);
Variant result = bus.call_sync ("org.freedesktop.DBus",
"/org/freedesktop/dbus",
"org.freedesktop.DBus",
"NameHasOwner",
new Variant ("(s)", name),
new VariantType ("(b)"),
DBusCallFlags.NO_AUTO_START,
-1);
result.get ("(b)", out has_owner);
return has_owner;
}
/**
* Attempts to own DBus name (calls dbus_name_has_owner first). CreateScopeCallback should create Lens/Scope object -
* it will be called after initial dbus name availability check, but before acquiring the name, so this function may
* still fail even after executing the callback.
*
* @param name DBus name to own
* @param scope_creation_cb callback that creates Lens/Scope object
* @return application instance (on success)
*/
public static GLib.Application? dbus_own_name (string name, CreateScopeCallback scope_creation_cb) throws Error
{
GLib.Application? app = null;
if (!dbus_name_has_owner (name))
{
scope_creation_cb ();
app = new Application (name, ApplicationFlags.IS_SERVICE);
app.register ();
if (app.get_is_remote ())
{
app = null;
}
else
{
/* Hold()ing the app makes sure the GApplication doesn't exit */
app.hold ();
}
}
return app;
}
}
|