~darkxst/ubuntu/saucy/gnome-shell/upstart_log

« back to all changes in this revision

Viewing changes to js/ui/remoteSearch.js

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-31 12:01:12 UTC
  • mfrom: (1.1.49) (19.1.36 experimental)
  • Revision ID: package-import@ubuntu.com-20130531120112-ew91khxf051x9i2r
Tags: 3.8.2-1ubuntu1
* Merge with Debian (LP: #1185869, #1185721). Remaining changes:
  - debian/control.in:
    + Build-depend on libsystemd-login-dev & libsystemd-daemon-dev
    + Depend on gdm instead of gdm3
    + Don't recommend gnome-session-fallback
  - debian/patches/40_change-pam-name-to-match-gdm.patch:
  - debian/patches/revert-suspend-break.patch:
    + Disabled, not needed on Ubuntu
  - debian/patches/ubuntu-lightdm-user-switching.patch:
    + Allow user switching when using LightDM. Thanks Gerhard Stein
      for rebasing against gnome-shell 3.8!
  - debian/patches/ubuntu_lock_on_suspend.patch
    + Respect Ubuntu's lock-on-suspend setting.
      Disabled until it can be rewritten.
  - debian/patches/git_relock_screen_after_crash.patch:
    + Add Upstream fix for unlocked session after crash (LP: #1064584)
* Note that the new GNOME Classic mode (which requires installing
  gnome-shell-extensions) won't work until gnome-session 3.8 is
  available in Ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
2
2
 
 
3
const GdkPixbuf = imports.gi.GdkPixbuf;
3
4
const Gio = imports.gi.Gio;
4
5
const GLib = imports.gi.GLib;
5
6
const Lang = imports.lang;
6
7
const St = imports.gi.St;
 
8
const Shell = imports.gi.Shell;
7
9
 
8
10
const FileUtils = imports.misc.fileUtils;
9
11
const Search = imports.ui.search;
29
31
</method>
30
32
</interface>;
31
33
 
 
34
const SearchProvider2Iface = <interface name="org.gnome.Shell.SearchProvider2">
 
35
<method name="GetInitialResultSet">
 
36
    <arg type="as" direction="in" />
 
37
    <arg type="as" direction="out" />
 
38
</method>
 
39
<method name="GetSubsearchResultSet">
 
40
    <arg type="as" direction="in" />
 
41
    <arg type="as" direction="in" />
 
42
    <arg type="as" direction="out" />
 
43
</method>
 
44
<method name="GetResultMetas">
 
45
    <arg type="as" direction="in" />
 
46
    <arg type="aa{sv}" direction="out" />
 
47
</method>
 
48
<method name="ActivateResult">
 
49
    <arg type="s" direction="in" />
 
50
    <arg type="as" direction="in" />
 
51
    <arg type="u" direction="in" />
 
52
</method>
 
53
<method name="LaunchSearch">
 
54
    <arg type="as" direction="in" />
 
55
    <arg type="u" direction="in" />
 
56
</method>
 
57
</interface>;
 
58
 
32
59
var SearchProviderProxy = Gio.DBusProxy.makeProxyWrapper(SearchProviderIface);
33
 
 
 
60
var SearchProvider2Proxy = Gio.DBusProxy.makeProxyWrapper(SearchProvider2Iface);
34
61
 
35
62
function loadRemoteSearchProviders(addProviderCallback) {
36
 
    let dataDirs = GLib.get_system_data_dirs();
37
 
    let loadedProviders = {};
38
 
    for (let i = 0; i < dataDirs.length; i++) {
39
 
        let path = GLib.build_filenamev([dataDirs[i], 'gnome-shell', 'search-providers']);
40
 
        let dir = Gio.file_new_for_path(path);
41
 
        if (!dir.query_exists(null))
42
 
            continue;
43
 
        loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback);
44
 
    }
45
 
};
46
 
 
47
 
function loadRemoteSearchProvidersFromDir(dir, loadedProviders, addProviderCallback) {
48
 
    let dirPath = dir.get_path();
49
 
    FileUtils.listDirAsync(dir, Lang.bind(this, function(files) {
50
 
        for (let i = 0; i < files.length; i++) {
51
 
            let keyfile = new GLib.KeyFile();
52
 
            let path = GLib.build_filenamev([dirPath, files[i].get_name()]);
53
 
 
54
 
            try {
55
 
                keyfile.load_from_file(path, 0);
56
 
            } catch(e) {
57
 
                continue;
58
 
            }
59
 
 
60
 
            if (!keyfile.has_group(KEY_FILE_GROUP))
61
 
                continue;
62
 
 
63
 
            let remoteProvider, title;
64
 
            try {
65
 
                let group = KEY_FILE_GROUP;
66
 
                let busName = keyfile.get_string(group, 'BusName');
67
 
                let objectPath = keyfile.get_string(group, 'ObjectPath');
68
 
 
69
 
                if (loadedProviders[objectPath])
70
 
                    continue;
71
 
 
72
 
                let appInfo = null;
73
 
                try {
74
 
                    let desktopId = keyfile.get_string(group, 'DesktopId');
75
 
                    appInfo = Gio.DesktopAppInfo.new(desktopId);
76
 
                } catch (e) {
77
 
                }
78
 
 
79
 
                let icon;
80
 
                if (appInfo) {
81
 
                    icon = appInfo.get_icon();
82
 
                    title = appInfo.get_name();
83
 
                } else {
84
 
                    let iconName = keyfile.get_string(group, 'Icon');
85
 
                    icon = new Gio.ThemedIcon({ name: iconName });
86
 
                    title = keyfile.get_locale_string(group, 'Title', null);
87
 
                }
88
 
 
89
 
                remoteProvider = new RemoteSearchProvider(title,
90
 
                                                          icon,
91
 
                                                          busName,
92
 
                                                          objectPath);
93
 
                loadedProviders[objectPath] = remoteProvider;
94
 
            } catch(e) {
95
 
                log('Failed to add search provider "%s": %s'.format(title, e.toString()));
96
 
                continue;
97
 
            }
98
 
 
99
 
            addProviderCallback(remoteProvider);
100
 
        }
101
 
    }));
102
 
 
103
 
};
 
63
    let data = { loadedProviders: [],
 
64
                 objectPaths: {},
 
65
                 addProviderCallback: addProviderCallback };
 
66
    FileUtils.collectFromDatadirsAsync('search-providers',
 
67
                                       { loadedCallback: remoteProvidersLoaded,
 
68
                                         processFile: loadRemoteSearchProvider,
 
69
                                         data: data
 
70
                                       });
 
71
}
 
72
 
 
73
function loadRemoteSearchProvider(file, info, data) {
 
74
    let keyfile = new GLib.KeyFile();
 
75
    let path = file.get_path();
 
76
 
 
77
    try {
 
78
        keyfile.load_from_file(path, 0);
 
79
    } catch(e) {
 
80
        return;
 
81
    }
 
82
 
 
83
    if (!keyfile.has_group(KEY_FILE_GROUP))
 
84
        return;
 
85
 
 
86
    let remoteProvider;
 
87
    try {
 
88
        let group = KEY_FILE_GROUP;
 
89
        let busName = keyfile.get_string(group, 'BusName');
 
90
        let objectPath = keyfile.get_string(group, 'ObjectPath');
 
91
 
 
92
        if (data.objectPaths[objectPath])
 
93
            return;
 
94
 
 
95
        let appInfo = null;
 
96
        try {
 
97
            let desktopId = keyfile.get_string(group, 'DesktopId');
 
98
            appInfo = Gio.DesktopAppInfo.new(desktopId);
 
99
        } catch (e) {
 
100
            log('Ignoring search provider ' + path + ': missing DesktopId');
 
101
            return;
 
102
        }
 
103
 
 
104
        let version = '1';
 
105
        try {
 
106
            version = keyfile.get_string(group, 'Version');
 
107
        } catch (e) {
 
108
            // ignore error
 
109
        }
 
110
 
 
111
        if (version >= 2)
 
112
            remoteProvider = new RemoteSearchProvider2(appInfo, busName, objectPath);
 
113
        else
 
114
            remoteProvider = new RemoteSearchProvider(appInfo, busName, objectPath);
 
115
 
 
116
        data.objectPaths[objectPath] = remoteProvider;
 
117
        data.loadedProviders.push(remoteProvider);
 
118
    } catch(e) {
 
119
        log('Failed to add search provider %s: %s'.format(path, e.toString()));
 
120
    }
 
121
}
 
122
 
 
123
function remoteProvidersLoaded(loadState) {
 
124
    let searchSettings = new Gio.Settings({ schema: Search.SEARCH_PROVIDERS_SCHEMA });
 
125
    let sortOrder = searchSettings.get_strv('sort-order');
 
126
 
 
127
    // Special case gnome-control-center to be always active and always first
 
128
    sortOrder.unshift('gnome-control-center.desktop');
 
129
 
 
130
    loadState.loadedProviders.sort(
 
131
        function(providerA, providerB) {
 
132
            let idxA, idxB;
 
133
            let appIdA, appIdB;
 
134
 
 
135
            appIdA = providerA.appInfo.get_id();
 
136
            appIdB = providerB.appInfo.get_id();
 
137
 
 
138
            idxA = sortOrder.indexOf(appIdA);
 
139
            idxB = sortOrder.indexOf(appIdB);
 
140
 
 
141
            // if no provider is found in the order, use alphabetical order
 
142
            if ((idxA == -1) && (idxB == -1)) {
 
143
                let nameA = providerA.appInfo.get_name();
 
144
                let nameB = providerB.appInfo.get_name();
 
145
 
 
146
                return GLib.utf8_collate(nameA, nameB);
 
147
            }
 
148
 
 
149
            // if providerA isn't found, it's sorted after providerB
 
150
            if (idxA == -1)
 
151
                return 1;
 
152
 
 
153
            // if providerB isn't found, it's sorted after providerA
 
154
            if (idxB == -1)
 
155
                return -1;
 
156
 
 
157
            // finally, if both providers are found, return their order in the list
 
158
            return (idxA - idxB);
 
159
        });
 
160
 
 
161
    loadState.loadedProviders.forEach(
 
162
        function(provider) {
 
163
            loadState.addProviderCallback(provider);
 
164
        });
 
165
}
104
166
 
105
167
const RemoteSearchProvider = new Lang.Class({
106
168
    Name: 'RemoteSearchProvider',
107
 
    Extends: Search.SearchProvider,
108
 
 
109
 
    _init: function(title, icon, dbusName, dbusPath) {
110
 
        this._proxy = new SearchProviderProxy(Gio.DBus.session,
111
 
                                              dbusName, dbusPath);
112
 
 
113
 
        this.parent(title.toUpperCase());
 
169
 
 
170
    _init: function(appInfo, dbusName, dbusPath, proxyType) {
 
171
        if (!proxyType)
 
172
            proxyType = SearchProviderProxy;
 
173
 
 
174
        this.proxy = new proxyType(Gio.DBus.session,
 
175
                dbusName, dbusPath, Lang.bind(this, this._onProxyConstructed));
 
176
 
 
177
        this.appInfo = appInfo;
 
178
        this.id = appInfo.get_id();
 
179
        this.isRemoteProvider = true;
 
180
 
114
181
        this._cancellable = new Gio.Cancellable();
115
182
    },
116
183
 
 
184
    _onProxyConstructed: function(proxy) {
 
185
        // Do nothing
 
186
    },
 
187
 
117
188
    createIcon: function(size, meta) {
 
189
        let gicon;
118
190
        if (meta['gicon']) {
119
 
            return new St.Icon({ gicon: Gio.icon_new_for_string(meta['gicon']),
120
 
                                 icon_size: size });
 
191
            gicon = Gio.icon_new_for_string(meta['gicon']);
121
192
        } else if (meta['icon-data']) {
122
193
            let [width, height, rowStride, hasAlpha,
123
194
                 bitsPerSample, nChannels, data] = meta['icon-data'];
124
 
            let textureCache = St.TextureCache.get_default();
125
 
            return textureCache.load_from_raw(data, hasAlpha,
126
 
                                              width, height, rowStride, size);
 
195
            gicon = Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
 
196
                                                       bitsPerSample, width, height, rowStride);
127
197
        }
128
198
 
129
 
        // Ugh, but we want to fall back to something ...
130
 
        return new St.Icon({ icon_name: 'text-x-generic',
 
199
        return new St.Icon({ gicon: gicon,
131
200
                             icon_size: size });
132
201
    },
133
202
 
141
210
        this._cancellable.cancel();
142
211
        this._cancellable.reset();
143
212
        try {
144
 
            this._proxy.GetInitialResultSetRemote(terms,
145
 
                                                  Lang.bind(this, this._getResultsFinished),
146
 
                                                  this._cancellable);
 
213
            this.proxy.GetInitialResultSetRemote(terms,
 
214
                                                 Lang.bind(this, this._getResultsFinished),
 
215
                                                 this._cancellable);
147
216
        } catch(e) {
148
 
            log('Error calling GetInitialResultSet for provider %s: %s'.format( this.title, e.toString()));
 
217
            log('Error calling GetInitialResultSet for provider %s: %s'.format(this.id, e.toString()));
149
218
            this.searchSystem.pushResults(this, []);
150
219
        }
151
220
    },
154
223
        this._cancellable.cancel();
155
224
        this._cancellable.reset();
156
225
        try {
157
 
            this._proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
158
 
                                                    Lang.bind(this, this._getResultsFinished),
159
 
                                                    this._cancellable);
 
226
            this.proxy.GetSubsearchResultSetRemote(previousResults, newTerms,
 
227
                                                   Lang.bind(this, this._getResultsFinished),
 
228
                                                   this._cancellable);
160
229
        } catch(e) {
161
 
            log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.title, e.toString()));
 
230
            log('Error calling GetSubsearchResultSet for provider %s: %s'.format(this.id, e.toString()));
162
231
            this.searchSystem.pushResults(this, []);
163
232
        }
164
233
    },
175
244
                metas[i][prop] = metas[i][prop].deep_unpack();
176
245
            resultMetas.push({ id: metas[i]['id'],
177
246
                               name: metas[i]['name'],
 
247
                               description: metas[i]['description'],
178
248
                               createIcon: Lang.bind(this,
179
249
                                                     this.createIcon, metas[i]) });
180
250
        }
185
255
        this._cancellable.cancel();
186
256
        this._cancellable.reset();
187
257
        try {
188
 
            this._proxy.GetResultMetasRemote(ids,
189
 
                                             Lang.bind(this, this._getResultMetasFinished, callback),
190
 
                                             this._cancellable);
 
258
            this.proxy.GetResultMetasRemote(ids,
 
259
                                            Lang.bind(this, this._getResultMetasFinished, callback),
 
260
                                            this._cancellable);
191
261
        } catch(e) {
192
 
            log('Error calling GetResultMetas for provider %s: %s'.format(this.title, e.toString()));
 
262
            log('Error calling GetResultMetas for provider %s: %s'.format(this.id, e.toString()));
193
263
            callback([]);
194
264
        }
195
265
    },
196
266
 
197
267
    activateResult: function(id) {
198
 
        this._proxy.ActivateResultRemote(id);
199
 
    }
200
 
});
201
 
 
202
 
 
 
268
        this.proxy.ActivateResultRemote(id);
 
269
    },
 
270
 
 
271
    launchSearch: function(terms) {
 
272
        // the provider is not compatible with the new version of the interface, launch
 
273
        // the app itself but warn so we can catch the error in logs
 
274
        log('Search provider ' + this.appInfo.get_id() + ' does not implement LaunchSearch');
 
275
        this.appInfo.launch([], global.create_app_launch_context());
 
276
    }
 
277
});
 
278
 
 
279
const RemoteSearchProvider2 = new Lang.Class({
 
280
    Name: 'RemoteSearchProvider2',
 
281
    Extends: RemoteSearchProvider,
 
282
 
 
283
    _init: function(appInfo, dbusName, dbusPath) {
 
284
        this.parent(appInfo, dbusName, dbusPath, SearchProvider2Proxy);
 
285
 
 
286
        this.canLaunchSearch = true;
 
287
    },
 
288
 
 
289
    activateResult: function(id, terms) {
 
290
        this.proxy.ActivateResultRemote(id, terms, global.get_current_time());
 
291
    },
 
292
 
 
293
    launchSearch: function(terms) {
 
294
        this.proxy.LaunchSearchRemote(terms, global.get_current_time());
 
295
    }
 
296
});