Codebase list gnome-shell-extension-appindicator / 2fb515a
Inline documentation updates everywhere Jonas Kuemmerlin 10 years ago
11 changed file(s) with 57 addition(s) and 33 deletion(s). Raw diff Collapse all Expand all
132132 </interface>;
133133 const PropertiesProxy = Gio.DBusProxy.makeProxyWrapper(PropertiesIface);
134134
135 /**
136 * the AppIndicator class serves as a generic container for indicator information and functions common
137 * for every displaying implementation (IndicatorMessageSource and IndicatorStatusIcon)
138 */
135139 const AppIndicator = new Lang.Class({
136140 Name: 'AppIndicator',
137141
1919 statusNotifierWatcher = null;
2020 }
2121
22 //HACK: while entering the lock screen, the extension will be enabled and disabled multiple times rapidly.
22 //HACK: while entering the lock screen, the extension will be enabled and disabled multiple times rapidly (why?).
2323 // this causes the own_name stuff to disintegrate, so we need to make sure we do not toggle the extension too often.
24 // however, this will cause a slight delay at initialization.
24 // however, this will cause a slight delay at initialization. It is also a very ugly hack since we rely on guessed
25 // timers instead of waiting for async calls to finish
2526 var debounced_executor = debounce_func(function(func) {
2627 func();
2728 });
2525 // The presence of an inUse property set to true on the icon will extend the lifetime.
2626
2727 // how to use: see IconCache.add, IconCache.get
28 // make sure the cached icon has a property inUse se to true if you don't want icon cache to destroy it for you.
28 // make sure the cached icon has a property inUse set to true if you don't want icon cache to destroy it for you.
2929 const IconCache = new Lang.Class({
3030 Name: 'IconCache',
3131
2828 const Gtk = imports.gi.Gtk;
2929 const Clutter = imports.gi.Clutter;
3030
31 /*
32 * A MessageTray.Source subclass that implements an indicator icon in the message tray
33 */
3134 const IndicatorMessageSource = new Lang.Class({
3235 Name: 'IndicatorMessageSource',
3336 Extends: MessageTray.Source,
127130 }
128131 });
129132
133 /*
134 * Standard popup menus can't be embedded in other widgets, but DbusMenu needs an instance of
135 * PopupMenu.PopupMenu to work correctly. Instead of mocking the popup menu api, we subclass it
136 * and apply some ugly hacks. This is extremely dependant of the internal implementation of PopupMenu.PopupMenu
137 */
130138 const PopupMenuEmbedded = new Lang.Class({
131139 Name: 'PopupMenuEmbedded',
132140 Extends: PopupMenu.PopupMenu,
151159 close: function() { }
152160 })
153161
162 /*
163 * we also need a custom notification widget which carries the menu
164 */
154165 const IndicatorNotification = new Lang.Class({
155166 Name: 'IndicatorNotification',
156167 Extends: MessageTray.Notification,
2323 const Panel = imports.ui.panel;
2424 const Clutter = imports.gi.Clutter;
2525
26 /*
27 * IndicatorStatusIcon implements an icon in the system status area
28 */
2629 const IndicatorStatusIcon = new Lang.Class({
2730 Name: 'IndicatorStatusIcon',
2831 Extends: PanelMenu.SystemStatusButton,
77 msgstr ""
88 "Project-Id-Version: PACKAGE VERSION\n"
99 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2013-03-04 18:39+0100\n"
10 "POT-Creation-Date: 2013-04-14 20:06+0200\n"
1111 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1212 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1313 "Language-Team: LANGUAGE <LL@li.org>\n"
4545 default_box.add(default_switch);
4646 widget.pack_start(default_box, false, false, 10);
4747 var overrides_frame = new Gtk.Frame({ label: _("Application specific settings")})
48 var overrides_scroll = new Gtk.ScrolledWindow(); //jsut in case our list gets _really_ big...
48 var overrides_scroll = new Gtk.ScrolledWindow(); // just in case our list gets _really_ big...
4949 var overrides_table = new Gtk.Grid({ margin: 10 });
5050 populateGrid.apply(overrides_table);
5151 overrides_frame.add(overrides_scroll);
1919 const Extension = imports.misc.extensionUtils.getCurrentExtension();
2020 const Convenience = Extension.imports.convenience;
2121
22 /*
23 * The Settings class manages the settings requested for each indicator.
24 * It listens to gsettings changes and emits changed events for each single changed override
25 */
2226 const Settings = new Lang.Class({
2327 Name: 'Settings',
2428
2731 this._overrides = {};
2832 this._gsettings = Convenience.getSettings();
2933 this._gsettings.connect("changed", Lang.bind(this, this._gsettingsChanged));
30 this._gsettingsChanged(); //initial read
34 this._gsettingsChanged(); // initial read
3135 },
3236
3337 get: function(id) {
6367 var def = this._gsettings.get_string("default");
6468 if (def != this._default) {
6569 this._default = def;
66 this.emit("changed", null); //null should tell the listeners to revalidate every item
70 this.emit("changed", null); // null should tell the listeners to revalidate every item
6771 }
68 //sync overrides with local copy
72 // sync overrides with local copy
6973 var overrides = JSON.parse(this._gsettings.get_string("overrides"));
7074 var changed = [];
7175 for (var i in overrides) {
7478 }
7579 delete this._overrides[i];
7680 }
77 //any old overrides left?
81 // any old overrides left?
7882 for (var i in this._overrides) {
7983 changed.push(i);
8084 }
81 //save new overrides
85 // save new overrides
8286 this._overrides = overrides;
83 //emit events
87 // emit events
8488 changed.forEach(this.emit.bind(this, 'changed'));
8589 }
8690 });
8791 Signals.addSignalMethods(Settings.prototype);
88 Object.defineProperty(Settings, "instance", {
89 get: function() {
90 if (Settings._instance) return Settings._instance;
91 else return Settings._instance = new Settings();
92 }
93 });
92 // lazy singleton implementation
93 Settings.instance = new Settings();
2323 const IndicatorMessageSource = Extension.imports.indicatorMessageSource;
2424 const Settings = Extension.imports.settings.Settings;
2525
26 /*
27 * The IndicatorDispatcher class will get all newly added or changed indicators
28 * and delegate them to IndicatorStatusIcon or IndicatorMessageSource or discard them
29 * depending on the settings and indicator state
30 */
2631 const IndicatorDispatcher = new Lang.Class({
2732 Name: 'IndicatorDispatcher',
2833
3742 },
3843
3944 _doDispatch: function(indicator) {
40 //this is actually needed for the whole lifetime of indicator. It will be disconnected automatically on destroy.
45 // this is actually needed for the whole lifetime of indicator. It will be disconnected automatically on destroy.
4146 indicator.connect('status', Lang.bind(this, this._updatedStatus, indicator));
4247 this._updatedStatus(indicator);
4348 },
4651 if (!indicator) return;
4752 var status = indicator.status;
4853 if (status == SNIStatus.PASSIVE) {
49 //remove it
54 // remove it
5055 if (indicator.id in this._icons) {
5156 this._remove(indicator);
5257 }
8893 if (name) {
8994 this._readd(name);
9095 } else {
91 //readd every item
96 // readd every item
9297 for (var i in this._icons) {
9398 this._readd(i);
9499 }
106111 });
107112 IndicatorDispatcher.instance = new IndicatorDispatcher();
108113
109 //used by IndicatorDispatcher for blacklisted indicators
114 // used by IndicatorDispatcher for blacklisted indicators
110115 const NullIcon = new Lang.Class({
111116 Name: 'IndicatorNullIcon',
112117
6060 <property name="IsStatusNotifierHostRegistered" type="b" access="read" />
6161 </interface>;
6262
63 function StatusNotifierWatcher() {
64 this._init.apply(this, arguments);
65 }
66
67 StatusNotifierWatcher.prototype = {
63 /*
64 * The StatusNotifierWatcher class implements the StatusNotifierWatcher dbus object
65 */
66 const StatusNotifierWatcher = new Lang.Class({
67 Name: 'StatusNotifierWatcher',
68
6869 _init: function() {
6970 this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(StatusNotifierWatcherIface, this);
7071 this._dbusImpl.export(Gio.DBus.session, WATCHER_OBJECT);
9091 },
9192
9293
93 //create a unique index for the _items dictionary
94 // create a unique index for the _items dictionary
9495 _getItemId: function(bus_name, obj_path) {
9596 return bus_name + obj_path;
9697 },
101102 // while kde apps send a bus name
102103 let service = params[0];
103104 let bus_name, obj_path;
104 if (service.charAt(0)=='/') { // looks like a path
105 if (service.charAt(0) == '/') { // looks like a path
105106 bus_name = invocation.get_sender();
106107 obj_path = service;
107108 } else { // we hope it is a bus name
112113 let id = this._getItemId(bus_name, obj_path);
113114
114115 if(this._items[id]) {
115 /*throw new DBus.DBusError('org.gnome.Shell.UnsupportedMethod',
116 'Registering more than one application indicator for the same connection and same path is not supported (how the hell did you expect that to work?) '+id);*/
117
118116 //delete the old one and add the new indicator
119117 log("WARNING: Attempting to re-register "+id+"; resetting instead");
120118 this._items[id].reset();
173171
174172 destroy: function() {
175173 if (!this._isDestroyed) {
174 // this doesn't do any sync operation and doesn't allow us to hook up the event of being finished
175 // which results in our unholy debounce hack (see extension.js)
176176 Gio.DBus.session.unown_name(this._ownName);
177177 this._dbusImpl.unexport();
178178 for (var i in this._nameWatcher) {
186186 this._isDestroyed = true;
187187 }
188188 }
189 };
189 });
5252
5353 /*
5454 * AsyncTaskQueue:
55 * Shedules asynchrouns tasks which may not overlap during execution
55 * Schedules asynchrouns tasks which may not overlap during execution
5656 *
5757 * The scheduled functions are required to take a callback as their last arguments, and all other arguments
5858 * need to be bound using Function.prototype.bind