Codebase list gnome-shell-extension-appindicator / debian/29-2 util.js
debian/29-2

Tree @debian/29-2 (Download .tar.gz)

util.js @debian/29-2

e2de1b7
ef1c3b8
 
 
 
 
 
 
 
 
 
 
 
 
 
90c376a
 
83fce78
2d2d1f7
90c376a
91e5aa8
2bb3172
83fce78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2bb3172
f8c439f
 
 
0a77d95
f8c439f
 
 
 
 
 
 
 
 
 
1dc5e56
0a77d95
34516c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1dc5e56
0a77d95
34516c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
0a77d95
34516c4
 
 
 
 
 
 
 
 
 
 
 
 
 
1dc5e56
34516c4
 
 
 
 
 
 
 
 
 
 
83fce78
 
 
 
da4c63b
83fce78
 
 
 
 
4a869e4
83fce78
1969d16
 
 
 
 
 
4a869e4
83fce78
 
 
 
4a869e4
83fce78
 
 
 
4a869e4
83fce78
4a869e4
83fce78
 
 
 
 
 
 
da4c63b
83fce78
1dc5e56
83fce78
 
 
 
 
4a869e4
ef1c3b8
 
 
f7d9118
 
ef1c3b8
f7d9118
ef1c3b8
f7d9118
2bb3172
ef1c3b8
f7d9118
ef1c3b8
f7d9118
ef1c3b8
f7d9118
ef1c3b8
f7d9118
ef1c3b8
f7d9118
ef1c3b8
f7d9118
ef1c3b8
 
 
// This file is part of the AppIndicator/KStatusNotifierItem GNOME Shell extension
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// 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, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
const Gio = imports.gi.Gio
const GLib = imports.gi.GLib
const GObject = imports.gi.GObject

const Signals = imports.signals

var refreshPropertyOnProxy = function(proxy, property_name) {
    proxy.g_connection.call(proxy.g_name,
                            proxy.g_object_path,
                            'org.freedesktop.DBus.Properties',
                            'Get',
                            GLib.Variant.new('(ss)', [ proxy.g_interface_name, property_name ]),
                            GLib.VariantType.new('(v)'),
                            Gio.DBusCallFlags.NONE,
                            -1,
                            null,
                            function(conn, result) {
                                try {
                                    let value_variant = conn.call_finish(result).deep_unpack()[0]

                                    proxy.set_cached_property(property_name, value_variant)

                                    // synthesize a property changed event
                                    let changed_obj = {}
                                    changed_obj[property_name] = value_variant
                                    proxy.emit('g-properties-changed', GLib.Variant.new('a{sv}', changed_obj), [])
                                } catch (e) {
                                    // the property may not even exist, silently ignore it
                                    //Logger.debug("While refreshing property "+property_name+": "+e)
                                }
                            })
}

var getUniqueBusNameSync = function(bus, name) {
    if (name[0] == ':')
        return name;

    if (!bus)
        bus = Gio.DBus.session;

    let variant_name = new GLib.Variant("(s)", [name]);
    let [unique] = bus.call_sync("org.freedesktop.DBus", "/", "org.freedesktop.DBus",
                                 "GetNameOwner", variant_name, null,
                                 Gio.DBusCallFlags.NONE, -1, null).deep_unpack();

    return unique;
}

var traverseBusNames = function(bus, cancellable, callback) {
    if (!bus)
        bus = Gio.DBus.session;

    if (typeof(callback) !== "function")
        throw new Error("No traversal callback provided");

    bus.call("org.freedesktop.DBus", "/", "org.freedesktop.DBus",
             "ListNames", null, new GLib.VariantType("(as)"), 0, -1, cancellable,
             function (bus, task) {
                if (task.had_error())
                    return;

                let [names] = bus.call_finish(task).deep_unpack();
                let unique_names = [];

                for (let name of names) {
                    let unique = getUniqueBusNameSync(bus, name);
                    if (unique_names.indexOf(unique) == -1)
                        unique_names.push(unique);
                }

                for (let name of unique_names)
                    callback(bus, name, cancellable);
            });
}

var introspectBusObject = function(bus, name, cancellable, filterFunction, targetCallback, path) {
    if (!path)
        path = "/";

    if (typeof targetCallback !== "function")
        throw new Error("No introspection callback defined");

    bus.call (name, path, "org.freedesktop.DBus.Introspectable", "Introspect",
              null, new GLib.VariantType("(s)"), Gio.DBusCallFlags.NONE, -1,
              cancellable, function (bus, task) {
                if (task.had_error())
                    return;

                let introspection = bus.call_finish(task).deep_unpack().toString();
                let node_info = Gio.DBusNodeInfo.new_for_xml(introspection);

                if ((typeof filterFunction === "function" && filterFunction(node_info) === true) ||
                    !filterFunction) {
                    targetCallback(name, path);
                }

                if (path === "/")
                    path = ""

                for (let sub_nodes of node_info.nodes) {
                    let sub_path = path+"/"+sub_nodes.path;
                    introspectBusObject (bus, name, cancellable, filterFunction,
                                         targetCallback, sub_path);
                }
            });
}

var dbusNodeImplementsInterfaces = function(node_info, interfaces) {
    if (!(node_info instanceof Gio.DBusNodeInfo) || !Array.isArray(interfaces))
        return false;

    for (let iface of interfaces) {
        if (node_info.lookup_interface(iface) !== null)
            return true;
    }

    return false;
}

const connectSmart3A = function(src, signal, handler) {
    let id = src.connect(signal, handler)

    if (src.connect && (!(src instanceof GObject.Object) || GObject.signal_lookup('destroy', src))) {
        let destroy_id = src.connect('destroy', () => {
            src.disconnect(id)
            src.disconnect(destroy_id)
        })
    }
}

const connectSmart4A = function(src, signal, target, method) {
    if (typeof method === 'string')
        method = target[method].bind(target)
    if (typeof method === 'function')
        method = method.bind(target)

    let signal_id = src.connect(signal, method)

    // GObject classes might or might not have a destroy signal
    // JS Classes will not complain when connecting to non-existent signals
    let src_destroy_id = src.connect && (!(src instanceof GObject.Object) || GObject.signal_lookup('destroy', src)) ? src.connect('destroy', on_destroy) : 0
    let tgt_destroy_id = target.connect && (!(target instanceof GObject.Object) || GObject.signal_lookup('destroy', target)) ? target.connect('destroy', on_destroy) : 0

    function on_destroy() {
        src.disconnect(signal_id)
        if (src_destroy_id) src.disconnect(src_destroy_id)
        if (tgt_destroy_id) target.disconnect(tgt_destroy_id)
    }
}

/**
 * Connect signals to slots, and remove the connection when either source or
 * target are destroyed
 *
 * Usage:
 *      Util.connectSmart(srcOb, 'signal', tgtObj, 'handler')
 * or
 *      Util.connectSmart(srcOb, 'signal', () => { ... })
 */
var connectSmart = function() {
    if (arguments.length == 4)
        return connectSmart4A.apply(null, arguments)
    else
        return connectSmart3A.apply(null, arguments)
}

/**
 * Helper class for logging stuff
 */
var Logger = class AppIndicators_Logger {
    static _log(prefix, message) {
        global.log("[AppIndicatorSupport-"+prefix+"] "+message)
    }

    static debug(message) {
        // CHeck the shell env variable to get what level to use
        Logger._log("DEBUG", message);
    }

    static warn(message) {
        Logger._log("WARN", message);
    }

    static error(message) {
        Logger._log("ERROR", message);
    }

    static fatal(message) {
        Logger._log("FATAL", message);
    }
};