diff -Nru gnome-shell-extension-appindicator-23/appIndicator.js gnome-shell-extension-appindicator-22/appIndicator.js --- gnome-shell-extension-appindicator-23/appIndicator.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/appIndicator.js 2017-10-23 14:27:00.000000000 +0000 @@ -19,16 +19,16 @@ const GdkPixbuf = imports.gi.GdkPixbuf const Gio = imports.gi.Gio const GLib = imports.gi.GLib -const GObject = imports.gi.GObject const Gtk = imports.gi.Gtk const St = imports.gi.St const Shell = imports.gi.Shell const Extension = imports.misc.extensionUtils.getCurrentExtension(); +const Lang = imports.lang const Signals = imports.signals const DBusMenu = Extension.imports.dbusMenu; -var IconCache = Extension.imports.iconCache; +const IconCache = Extension.imports.iconCache; const Util = Extension.imports.util; const Interfaces = Extension.imports.interfaces; @@ -39,7 +39,7 @@ HARDWARE: 'Hardware' }; -var SNIStatus = { +const SNIStatus = { PASSIVE: 'Passive', ACTIVE: 'Active', NEEDS_ATTENTION: 'NeedsAttention' @@ -49,9 +49,10 @@ * the AppIndicator class serves as a generic container for indicator information and functions common * for every displaying implementation (IndicatorMessageSource and IndicatorStatusIcon) */ -var AppIndicator = class AppIndicators_AppIndicator { +const AppIndicator = new Lang.Class({ + Name: 'AppIndicator', - constructor(bus_name, object) { + _init: function(bus_name, object) { this.busName = bus_name this._uniqueId = bus_name + object @@ -65,7 +66,7 @@ g_name: bus_name, g_object_path: object, g_flags: Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES }) - this._proxy.init_async(GLib.PRIORITY_DEFAULT, null, ((initable, result) => { + this._proxy.init_async(GLib.PRIORITY_DEFAULT, null, (function(initable, result) { try { initable.init_finish(result); @@ -74,39 +75,20 @@ } catch(e) { Util.Logger.warn("While intializing proxy for "+bus_name+object+": "+e) } - })) + }).bind(this)) + + this._proxyPropertyList = interface_info.properties.map(function(propinfo) { return propinfo.name }) - this._proxyPropertyList = interface_info.properties.map((propinfo) => { return propinfo.name }) - this._addExtraProperty('XAyatanaLabel'); - this._addExtraProperty('XAyatanaLabelGuide'); - this._addExtraProperty('XAyatanaOrderingIndex'); Util.connectSmart(this._proxy, 'g-properties-changed', this, '_onPropertiesChanged') Util.connectSmart(this._proxy, 'g-signal', this, '_translateNewSignals') - } - - _addExtraProperty(name) { - let propertyProps = { configurable: false, enumerable: true }; - - propertyProps.get = () => { - let v = this._proxy.get_cached_property(name); - return v ? v.deep_unpack() : null - }; - - Object.defineProperty(this._proxy, name, propertyProps); - this._proxyPropertyList.push(name); - } + }, // The Author of the spec didn't like the PropertiesChanged signal, so he invented his own - _translateNewSignals(proxy, sender, signal, params) { - let prop = null; - - if (signal.substr(0, 3) == 'New') - prop = signal.substr(3) - else if (signal.substr(0, 11) == 'XAyatanaNew') - prop = 'XAyatana' + signal.substr(11) + _translateNewSignals: function(proxy, sender, signal, params) { + if (signal.substr(0, 3) == 'New') { + let prop = signal.substr(3) - if (prop) { if (this._proxyPropertyList.indexOf(prop) > -1) Util.refreshPropertyOnProxy(this._proxy, prop) @@ -115,28 +97,34 @@ if (this._proxyPropertyList.indexOf(prop + 'Name') > -1) Util.refreshPropertyOnProxy(this._proxy, prop + 'Name') + } else if (signal == 'XAyatanaNewLabel') { + // and the ayatana guys made sure to invent yet another way of composing these signals... + Util.refreshPropertyOnProxy(this._proxy, 'XAyatanaLabel') } - } + }, //public property getters get title() { return this._proxy.Title; - } + }, get id() { return this._proxy.Id; - } + }, get uniqueId() { return this._uniqueId; - } + }, get status() { return this._proxy.Status; - } + }, get label() { - return this._proxy.XAyatanaLabel; - } + let v = this._proxy.get_cached_property('XAyatanaLabel'); + + if (v) return v.deep_unpack() + else return null + }, get menuPath() { return this._proxy.Menu || "/MenuBar" - } + }, get attentionIcon() { return [ @@ -144,7 +132,7 @@ this._proxy.AttentionIconPixmap, this._proxy.IconThemePath ] - } + }, get icon() { return [ @@ -152,7 +140,7 @@ this._proxy.IconPixmap, this._proxy.IconThemePath ] - } + }, get overlayIcon() { return [ @@ -160,12 +148,12 @@ this._proxy.OverlayIconPixmap, this._proxy.IconThemePath ] - } + }, - _onPropertiesChanged(proxy, changed, invalidated) { + _onPropertiesChanged: function(proxy, changed, invalidated) { let props = Object.keys(changed.deep_unpack()) - props.forEach((property) => { + props.forEach(function(property) { // some property changes require updates on our part, // a few need to be passed down to the displaying code @@ -191,55 +179,55 @@ if (property == 'Status') this.emit('status') }, this); - } + }, - reset() { + reset: function() { //TODO: reload all properties, or do some other useful things this.emit('reset') - } + }, - destroy() { + destroy: function() { this.emit('destroy') this.disconnectAll() delete this._proxy - } + }, - open() { + open: function() { // we can't use WindowID because we're not able to get the x11 window id from a MetaWindow // nor can we call any X11 functions. Luckily, the Activate method usually works fine. // parameters are "an hint to the item where to show eventual windows" [sic] // ... and don't seem to have any effect. this._proxy.ActivateRemote(0, 0) - } + }, - secondaryActivate() { + secondaryActivate: function () { this._proxy.SecondaryActivateRemote(0, 0) - } + }, - scroll(dx, dy) { + scroll: function(dx, dy) { if (dx != 0) this._proxy.ScrollRemote(Math.floor(dx), 'horizontal') if (dy != 0) this._proxy.ScrollRemote(Math.floor(dy), 'vertical') } -}; +}); Signals.addSignalMethods(AppIndicator.prototype); -var IconActor = GObject.registerClass( -class AppIndicators_IconActor extends Shell.Stack { - - _init(indicator, icon_size) { - super._init({ reactive: true }) - this.name = this.constructor.name; +const IconActor = new Lang.Class({ + Name: 'AppIndicatorIconActor', + Extends: Shell.Stack, + GTypeName: Util.WORKAROUND_RELOAD_TYPE_REGISTER('AppIndicatorIconActor'), + _init: function(indicator, icon_size) { + this.parent({ reactive: true }) let scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; this.width = icon_size * scale_factor this.height = icon_size * scale_factor this._indicator = indicator - this._iconSize = icon_size + this._iconSize = icon_size * scale_factor this._iconCache = new IconCache.IconCache() this._mainIcon = new St.Bin() @@ -258,11 +246,7 @@ if (indicator.isReady) this._invalidateIcon() - - this.connect('destroy', () => { - this._iconCache.destroy(); - }); - } + }, // Will look the icon up in the cache, if it's found // it will return it. Otherwise, it will create it and cache it. @@ -270,7 +254,7 @@ // the returned icon anymore, make sure to check the .inUse property // and set it to false if needed so that it can be picked up by the garbage // collector. - _cacheOrCreateIconByName(iconSize, iconName, themePath) { + _cacheOrCreateIconByName: function(iconSize, iconName, themePath) { let id = iconName + '@' + iconSize + (themePath ? '##' + themePath : '') let icon = this._iconCache.get(id) || this._createIconByName(iconSize, iconName, themePath) @@ -281,9 +265,9 @@ } return icon - } + }, - _createIconByName(icon_size, icon_name, themePath) { + _createIconByName: function(icon_size, icon_name, themePath) { // real_icon_size will contain the actual icon size in contrast to the requested icon size var real_icon_size = icon_size var gicon = null @@ -311,7 +295,7 @@ // we try to avoid messing with the default icon theme, so we'll create a new one if needed if (themePath) { var icon_theme = new Gtk.IconTheme() - Gtk.IconTheme.get_default().get_search_path().forEach((path) => { + Gtk.IconTheme.get_default().get_search_path().forEach(function(path) { icon_theme.append_search_path(path) }); icon_theme.append_search_path(themePath) @@ -348,11 +332,9 @@ return new St.Icon({ gicon: gicon, icon_size: real_icon_size }) else return null - } + }, - _createIconFromPixmap(iconSize, iconPixmapArray) { - let scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor; - iconSize = iconSize * scale_factor + _createIconFromPixmap: function(iconSize, iconPixmapArray) { // the pixmap actually is an array of pixmaps with different sizes // we use the one that is smaller or equal the iconSize @@ -360,7 +342,7 @@ if (!iconPixmapArray || iconPixmapArray.length < 1) return null - let sortedIconPixmapArray = iconPixmapArray.sort((pixmapA, pixmapB) => { + let sortedIconPixmapArray = iconPixmapArray.sort(function(pixmapA, pixmapB) { // we sort biggest to smallest let areaA = pixmapA[0] * pixmapA[1] let areaB = pixmapB[0] * pixmapB[1] @@ -368,7 +350,7 @@ return areaB - areaA }) - let qualifiedIconPixmapArray = sortedIconPixmapArray.filter((pixmap) => { + let qualifiedIconPixmapArray = sortedIconPixmapArray.filter(function(pixmap) { // we disqualify any pixmap that is bigger than our requested size return pixmap[0] <= iconSize && pixmap[1] <= iconSize }) @@ -406,10 +388,10 @@ // we could log it here, but that doesn't really help in tracking it down. return null } - } + }, // updates the base icon - _updateIcon() { + _updateIcon: function() { // remove old icon if (this._mainIcon.get_child()) { let child = this._mainIcon.get_child() @@ -447,9 +429,9 @@ } this._mainIcon.set_child(newIcon) - } + }, - _updateOverlayIcon() { + _updateOverlayIcon: function() { // remove old icon if (this._overlayIcon.get_child()) { let child = this._overlayIcon.get_child() @@ -479,9 +461,9 @@ newIcon = this._createIconFromPixmap(iconSize, pixmap) this._overlayIcon.set_child(newIcon) - } + }, - _handleScrollEvent(actor, event) { + _handleScrollEvent: function(actor, event) { if (actor != this) return Clutter.EVENT_PROPAGATE @@ -502,13 +484,19 @@ } return Clutter.EVENT_STOP - } + }, // called when the icon theme changes - _invalidateIcon() { + _invalidateIcon: function() { this._iconCache.clear() this._updateIcon() this._updateOverlayIcon() + }, + + destroy: function() { + this._iconCache.destroy() + + this.parent() } -}); +}) diff -Nru gnome-shell-extension-appindicator-23/dbusMenu.js gnome-shell-extension-appindicator-22/dbusMenu.js --- gnome-shell-extension-appindicator-23/dbusMenu.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/dbusMenu.js 2017-10-23 14:27:00.000000000 +0000 @@ -18,6 +18,7 @@ const Gio = imports.gi.Gio const GLib = imports.gi.GLib const GdkPixbuf = imports.gi.GdkPixbuf +const Lang = imports.lang const PopupMenu = imports.ui.popupMenu const Signals = imports.signals const St = imports.gi.St @@ -35,9 +36,10 @@ /** * Saves menu property values and handles type checking and defaults */ -var PropertyStore = class AppIndicators_PropertyStore { +const PropertyStore = new Lang.Class({ + Name: 'DbusMenuPropertyStore', - constructor(initial_properties) { + _init: function(initial_properties) { this._props = {} if (initial_properties) { @@ -45,18 +47,18 @@ this.set(i, initial_properties[i]) } } - } + }, - set(name, value) { + set: function(name, value) { if (name in PropertyStore.MandatedTypes && value && !value.is_of_type(PropertyStore.MandatedTypes[name])) Util.Logger.warn("Cannot set property "+name+": type mismatch!") else if (value) this._props[name] = value else delete this._props[name] - } + }, - get(name) { + get: function(name) { if (name in this._props) return this._props[name] else if (name in PropertyStore.DefaultValues) @@ -64,7 +66,7 @@ else return null } -}; +}) // we list all the properties we know and use here, so we won' have to deal with unexpected type mismatches PropertyStore.MandatedTypes = { @@ -90,51 +92,52 @@ /** * Represents a single menu item */ -var DbusMenuItem = class AppIndicators_DbusMenuItem { +const DbusMenuItem = new Lang.Class({ + Name: 'DbusMenuItem', // will steal the properties object - constructor(client, id, properties, children_ids) { + _init: function(client, id, properties, children_ids) { this._client = client this._id = id this._propStore = new PropertyStore(properties) this._children_ids = children_ids - } + }, - property_get(prop_name) { + property_get: function(prop_name) { let prop = this.property_get_variant(prop_name) return prop ? prop.get_string()[0] : null - } + }, - property_get_variant(prop_name) { + property_get_variant: function(prop_name) { return this._propStore.get(prop_name) - } + }, - property_get_bool(prop_name) { + property_get_bool: function(prop_name) { let prop = this.property_get_variant(prop_name) return prop ? prop.get_boolean() : false - } + }, - property_get_int(prop_name) { + property_get_int: function(prop_name) { let prop = this.property_get_variant(prop_name) return prop ? prop.get_int32() : 0 - } + }, - property_set(prop, value) { + property_set: function(prop, value) { this._propStore.set(prop, value) this.emit('property-changed', prop, this.property_get_variant(prop)) - } + }, - get_children_ids() { + get_children_ids: function() { return this._children_ids.concat() // clone it! - } + }, - add_child(pos, child_id) { + add_child: function(pos, child_id) { this._children_ids.splice(pos, 0, child_id) this.emit('child-added', this._client.get_item(child_id), pos) - } + }, - remove_child(child_id) { + remove_child: function(child_id) { // find it let pos = -1 for (let i = 0; i < this._children_ids.length; ++i) { @@ -150,9 +153,9 @@ this._children_ids.splice(pos, 1) this.emit('child-removed', this._client.get_item(child_id)) } - } + }, - move_child(child_id, newpos) { + move_child: function(child_id, newpos) { // find the old position let oldpos = -1 for (let i = 0; i < this._children_ids.length; ++i) { @@ -172,29 +175,29 @@ this._children_ids.splice(newpos, 0, child_id) this.emit('child-moved', oldpos, newpos, this._client.get_item(child_id)) } - } + }, - get_children() { - return this._children_ids.map((el) => { + get_children: function() { + return this._children_ids.map(function(el) { return this._client.get_item(el) }, this) - } + }, - handle_event(event, data, timestamp) { + handle_event: function(event, data, timestamp) { if (!data) data = GLib.Variant.new_int32(0) this._client.send_event(this._id, event, data, timestamp) - } + }, - get_id() { + get_id: function() { return this._id - } + }, - send_about_to_show() { + send_about_to_show: function() { this._client.send_about_to_show(this._id) } -} +}) Signals.addSignalMethods(DbusMenuItem.prototype) @@ -203,9 +206,10 @@ /** * The client does the heavy lifting of actually reading layouts and distributing events */ -var DBusClient = class AppIndicators_DBusClient { +const DBusClient = new Lang.Class({ + Name: 'DbusMenuBusClient', - constructor(busName, busPath) { + _init: function(busName, busPath) { this._proxy = new BusClientProxy(Gio.DBus.session, busName, busPath, this._clientReady.bind(this)) this._items = { 0: new DbusMenuItem(this, 0, { 'children-display': GLib.Variant.new_string('submenu') }, []) } @@ -216,56 +220,56 @@ // property requests are queued this._propertiesRequestedFor = [ /* ids */ ] - } + }, - get_root() { + get_root: function() { return this._items[0] - } + }, - _requestLayoutUpdate() { + _requestLayoutUpdate: function() { if (this._flagLayoutUpdateInProgress) this._flagLayoutUpdateRequired = true else this._beginLayoutUpdate() - } + }, - _requestProperties(id) { + _requestProperties: function(id) { // if we don't have any requests queued, we'll need to add one if (this._propertiesRequestedFor.length < 1) GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, this._beginRequestProperties.bind(this)) - if (this._propertiesRequestedFor.filter((e) => { return e === id }).length == 0) + if (this._propertiesRequestedFor.filter(function(e) { return e === id }).length == 0) this._propertiesRequestedFor.push(id) - } + }, - _beginRequestProperties() { + _beginRequestProperties: function() { this._proxy.GetGroupPropertiesRemote(this._propertiesRequestedFor, [], this._endRequestProperties.bind(this)) this._propertiesRequestedFor = [] return false - } + }, - _endRequestProperties(result, error) { + _endRequestProperties: function(result, error) { if (error) { Util.Logger.warn("Could not retrieve properties: "+error) return } // for some funny reason, the result array is hidden in an array - result[0].forEach(([id, properties]) => { + result[0].forEach(function([id, properties]) { if (!(id in this._items)) return for (let prop in properties) this._items[id].property_set(prop, properties[prop]) }, this) - } + }, // Traverses the list of cached menu items and removes everyone that is not in the list // so we don't keep alive unused items - _gcItems() { + _gcItems: function() { let tag = new Date().getTime() let toTraverse = [ 0 ] @@ -278,22 +282,22 @@ for (let i in this._items) if (this._items[i]._dbusClientGcTag != tag) delete this._items[i] - } + }, // the original implementation will only request partial layouts if somehow possible // we try to save us from multiple kinds of race conditions by always requesting a full layout - _beginLayoutUpdate() { + _beginLayoutUpdate: function() { // we only read the type property, because if the type changes after reading all properties, // the view would have to replace the item completely which we try to avoid this._proxy.GetLayoutRemote(0, -1, [ 'type', 'children-display' ], this._endLayoutUpdate.bind(this)) this._flagLayoutUpdateRequired = false this._flagLayoutUpdateInProgress = true - } + }, - _endLayoutUpdate(result, error) { + _endLayoutUpdate: function(result, error) { if (error) { - Util.Logger.warn("While reading menu layout on proxy '"+this._proxy.g_name_owner+": "+error) + Util.Logger.warn("While reading menu layout: "+error) return } @@ -305,13 +309,13 @@ this._beginLayoutUpdate() else this._flagLayoutUpdateInProgress = false - } + }, - _doLayoutUpdate(item) { + _doLayoutUpdate: function(item) { let [ id, properties, children ] = item - let children_unpacked = children.map((child) => { return child.deep_unpack() }) - let children_ids = children_unpacked.map((child) => { return child[0] }) + let children_unpacked = children.map(function(child) { return child.deep_unpack() }) + let children_ids = children_unpacked.map(function(child) { return child[0] }) // make sure all our children exist children_unpacked.forEach(this._doLayoutUpdate, this) @@ -345,7 +349,7 @@ } // remove any old children that weren't reused - old_children_ids.forEach((child_id) => { this._items[id].remove_child(child_id) }, this) + old_children_ids.forEach(function(child_id) { this._items[id].remove_child(child_id) }, this) } else { // we don't, so let's create us this._items[id] = new DbusMenuItem(this, id, properties, children_ids) @@ -353,9 +357,9 @@ } return id - } + }, - _clientReady(result, error) { + _clientReady: function(result, error) { if (error) { Util.Logger.warn("Could not initialize menu proxy: "+error) //FIXME: show message to the user? @@ -366,63 +370,63 @@ // listen for updated layouts and properties this._proxy.connectSignal("LayoutUpdated", this._onLayoutUpdated.bind(this)) this._proxy.connectSignal("ItemsPropertiesUpdated", this._onPropertiesUpdated.bind(this)) - } + }, - get_item(id) { + get_item: function(id) { if (id in this._items) return this._items[id] Util.Logger.warn("trying to retrieve item for non-existing id "+id+" !?") return null - } + }, // we don't need to cache and burst-send that since it will not happen that frequently - send_about_to_show(id) { - this._proxy.AboutToShowRemote(id, ((result, error) => { + send_about_to_show: function(id) { + this._proxy.AboutToShowRemote(id, (function(result, error) { if (error) Util.Logger.warn("while calling AboutToShow: "+error) else if (result && result[0]) this._requestLayoutUpdate() - })) - } + }).bind(this)) + }, - send_event(id, event, params, timestamp) { + send_event: function(id, event, params, timestamp) { if (!this._proxy) return this._proxy.EventRemote(id, event, params, timestamp, function(result, error) { /* we don't care */ }) - } + }, - _onLayoutUpdated() { + _onLayoutUpdated: function() { this._requestLayoutUpdate() - } + }, - _onPropertiesUpdated(proxy, name, [changed, removed]) { - changed.forEach(([id, props]) => { + _onPropertiesUpdated: function(proxy, name, [changed, removed]) { + changed.forEach(function([id, props]) { if (!(id in this._items)) return for (let prop in props) this._items[id].property_set(prop, props[prop]) }, this) - removed.forEach(([id, propNames]) => { + removed.forEach(function([id, propNames]) { if (!(id in this._items)) return - propNames.forEach((propName) => { + propNames.forEach(function(propName) { this._items[id].property_set(propName, null) }, this) }, this) - } + }, - destroy() { + destroy: function() { this.emit('destroy') Signals._disconnectAll.apply(this._proxy) this._proxy = null } -} +}) Signals.addSignalMethods(DBusClient.prototype) ////////////////////////////////////////////////////////////////////////// @@ -489,7 +493,7 @@ return shellItem }, - _onOpenStateChanged(menu, open) { + _onOpenStateChanged: function(menu, open) { if (open) { if (NEED_NESTED_SUBMENU_FIX) { // close our own submenus @@ -516,11 +520,11 @@ } }, - _onActivate() { + _onActivate: function() { this._dbusItem.handle_event("clicked", GLib.Variant.new("i", 0), 0) }, - _onPropertyChanged(dbusItem, prop, value) { + _onPropertyChanged: function(dbusItem, prop, value) { if (prop == "toggle-type" || prop == "toggle-state") MenuItemFactory._updateOrnament.call(this) else if (prop == "label") @@ -537,7 +541,7 @@ // Util.Logger.debug("Unhandled property change: "+prop) }, - _onChildAdded(dbusItem, child, position) { + _onChildAdded: function(dbusItem, child, position) { if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { Util.Logger.warn("Tried to add a child to non-submenu item. Better recreate it as whole") MenuItemFactory._replaceSelf.call(this) @@ -546,20 +550,20 @@ } }, - _onChildRemoved(dbusItem, child) { + _onChildRemoved: function(dbusItem, child) { if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { Util.Logger.warn("Tried to remove a child from non-submenu item. Better recreate it as whole") MenuItemFactory._replaceSelf.call(this) } else { // find it! - this.menu._getMenuItems().forEach((item) => { + this.menu._getMenuItems().forEach(function(item) { if (item._dbusItem == child) item.destroy() }) } }, - _onChildMoved(dbusItem, child, oldpos, newpos) { + _onChildMoved: function(dbusItem, child, oldpos, newpos) { if (!(this instanceof PopupMenu.PopupSubMenuMenuItem)) { Util.Logger.warn("Tried to move a child in non-submenu item. Better recreate it as whole") MenuItemFactory._replaceSelf.call(this) @@ -568,14 +572,14 @@ } }, - _updateLabel() { + _updateLabel: function() { let label = this._dbusItem.property_get("label").replace(/_([^_])/, "$1") if (this.label) // especially on GS3.8, the separator item might not even have a hidden label this.label.set_text(label) }, - _updateOrnament() { + _updateOrnament: function() { if (!this.setOrnament) return // separators and alike might not have gotten the polyfill if (this._dbusItem.property_get("toggle-type") == "checkmark" && this._dbusItem.property_get_int("toggle-state")) @@ -586,7 +590,7 @@ this.setOrnament(PopupMenu.Ornament.NONE) }, - _updateImage() { + _updateImage: function() { if (!this._icon) return // might be missing on submenus / separators let iconName = this._dbusItem.property_get("icon-name") @@ -597,15 +601,15 @@ this._icon.gicon = GdkPixbuf.Pixbuf.new_from_stream(Gio.MemoryInputStream.new_from_bytes(iconData.get_data_as_bytes()), null) }, - _updateVisible() { + _updateVisible: function() { this.actor.visible = this._dbusItem.property_get_bool("visible") }, - _updateSensitive() { + _updateSensitive: function() { this.setSensitive(this._dbusItem.property_get_bool("enabled")) }, - _replaceSelf(newSelf) { + _replaceSelf: function(newSelf) { // create our new self if needed if (!newSelf) newSelf = MenuItemFactory.createItem(this._dbusClient, this._dbusItem) @@ -634,7 +638,7 @@ * Utility functions not necessarily belonging into the item factory */ const MenuUtils = { - moveItemInMenu(menu, dbusItem, newpos) { + moveItemInMenu: function(menu, dbusItem, newpos) { //HACK: we're really getting into the internals of the PopupMenu implementation // First, find our wrapper. Children tend to lie. We do not trust the old positioning. @@ -663,19 +667,21 @@ * * Something like a mini-god-object */ -var Client = class AppIndicators_Client { +const Client = new Lang.Class({ + Name: 'DbusMenuClient', - constructor(busName, path) { + _init: function(busName, path) { + this.parent() this._busName = busName this._busPath = path this._client = new DBusClient(busName, path) this._rootMenu = null // the shell menu this._rootItem = null // the DbusMenuItem for the root - } + }, // this will attach the client to an already existing menu that will be used as the root menu. // it will also connect the client to be automatically destroyed when the menu dies. - attachToMenu(menu) { + attachToMenu: function(menu) { this._rootMenu = menu this._rootItem = this._client.get_root() @@ -697,12 +703,12 @@ this._rootItem.send_about_to_show() // fill the menu for the first time - this._rootItem.get_children().forEach((child) => { + this._rootItem.get_children().forEach(function(child) { this._rootMenu.addMenuItem(MenuItemFactory.createItem(this, child)) }, this) - } + }, - _setOpenedSubmenu(submenu) { + _setOpenedSubmenu: function(submenu) { if (!submenu) return @@ -716,26 +722,26 @@ this._openedSubMenu.close(true) this._openedSubMenu = submenu - } + }, - _onRootChildAdded(dbusItem, child, position) { + _onRootChildAdded: function(dbusItem, child, position) { this._rootMenu.addMenuItem(MenuItemFactory.createItem(this, child), position) - } + }, - _onRootChildRemoved(dbusItem, child) { + _onRootChildRemoved: function(dbusItem, child) { // children like to play hide and seek // but we know how to find it for sure! - this._rootMenu._getMenuItems().forEach((item) => { + this._rootMenu._getMenuItems().forEach(function(item) { if (item._dbusItem == child) item.destroy() }) - } + }, - _onRootChildMoved(dbusItem, child, oldpos, newpos) { + _onRootChildMoved: function(dbusItem, child, oldpos, newpos) { MenuUtils.moveItemInMenu(this._rootMenu, dbusItem, newpos) - } + }, - _onMenuOpened(menu, state) { + _onMenuOpened: function(menu, state) { if (!this._rootItem) return if (state) { @@ -747,9 +753,9 @@ } else { this._rootItem.handle_event("closed", null, 0) } - } + }, - destroy() { + destroy: function() { this.emit('destroy') if (this._client) @@ -759,5 +765,5 @@ this._rootItem = null this._rootMenu = null } -} +}) Signals.addSignalMethods(Client.prototype) diff -Nru gnome-shell-extension-appindicator-23/debian/changelog gnome-shell-extension-appindicator-22/debian/changelog --- gnome-shell-extension-appindicator-23/debian/changelog 2019-02-22 08:54:12.000000000 +0000 +++ gnome-shell-extension-appindicator-22/debian/changelog 2018-05-07 21:37:59.000000000 +0000 @@ -1,72 +1,5 @@ -gnome-shell-extension-appindicator (23-1) experimental; urgency=medium - - [ Marco Trevisan (Treviño) ] - * New upstream version: v23 - * iconCache: don't add an icon multiple times and remove it on destruction - * iconCache: use seconds granulated timeout for garbage collector - * iconCache: only run the garbage collector when we've icons - * Util: use var to define module functions - * statusNotifierWatcher: use nicer lambda functions in traverseBusNames - * iconCache: connect to destroy signal if the object has it - * indicatorStatusIcon: don't override the destroy, react on 'destroy' signal instead - * appIndicator: don't treat XAyatana* properties as 2nd clas citizen - * dbusMenu: add better logging on errors - * metadata: update url - * statusNotifierWatcher: return extension UUID - * appIndicators: use arrow functions in lambdas - * appindicators: rewrite classes using pure ES6 classes - * metadata: set supported shell versions to 3.30+ - * debian/control: update Homepage and Vcs-* flags - * debian/gbp.conf: add debian-tag option - * debian/patches/metadata-use-appindicator-namespace-and-naming.patch: - - Use ubuntu appindicator namespace, update description - * debian/gbp.conf: - - Use default gbp gnome configurations, and set proper upstream-vcs-tag - - [ Andrea Azzarone ] - * interfaces: Explicitly convert raw data to strings - - -- Marco Trevisan (Treviño) Fri, 22 Feb 2019 08:54:12 +0000 - gnome-shell-extension-appindicator (22-1) unstable; urgency=medium * Initial release (Closes: #898144) -- Matteo F. Vescovi Mon, 07 May 2018 23:37:59 +0200 - -gnome-shell-extension-appindicator (18.04.1) bionic; urgency=medium - - * Rebase on latest upstream with those fixes: - - Fix icons vertically stretched on HDPI screen - - Fix warnings from GNOME Shell 3.26 - - -- Didier Roche Tue, 27 Mar 2018 09:26:22 +0200 - -gnome-shell-extension-appindicator (18.04) bionic; urgency=medium - - * Rebase on latest upstream release: - - Fix icon are too small with some tray icons such as Telegram - (LP: #1730406) - - Fix warning with latest GJS. - - -- Didier Roche Thu, 16 Nov 2017 15:40:48 +0100 - -gnome-shell-extension-appindicator (17.10.2) artful; urgency=medium - - * Fix icons from qt applications disappearing after screen lock/sleep. - Thanks Marco (LP: #1712866) - - -- Didier Roche Mon, 23 Oct 2017 10:15:12 +0200 - -gnome-shell-extension-appindicator (17.10.1) artful; urgency=medium - - * Fix telegram icon not scaled is not properly scaled on hidpi setups. - Thanks Andrea (LP: #1720143) - - -- Didier Roche Thu, 05 Oct 2017 10:29:46 +0200 - -gnome-shell-extension-appindicator (17.10) artful; urgency=medium - - * Initial release of appindicator extension. - - -- Didier Roche Tue, 22 Aug 2017 08:51:13 +0200 diff -Nru gnome-shell-extension-appindicator-23/debian/control gnome-shell-extension-appindicator-22/debian/control --- gnome-shell-extension-appindicator-23/debian/control 2019-02-22 08:54:12.000000000 +0000 +++ gnome-shell-extension-appindicator-22/debian/control 2018-05-07 21:08:52.000000000 +0000 @@ -5,10 +5,10 @@ Uploaders: Matteo F. Vescovi Build-Depends: debhelper (>= 11) -Standards-Version: 4.2.1 +Standards-Version: 4.1.4 Homepage: https://github.com/ubuntu/gnome-shell-extension-appindicator -Vcs-Browser: https://salsa.debian.org/gnome-team/shell-extensions/gnome-shell-extension-appindicator -Vcs-Git: https://salsa.debian.org/gnome-team/shell-extensions/gnome-shell-extension-appindicator.git +Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-shell-extension-appindicator +Vcs-Git: https://salsa.debian.org/gnome-team/gnome-shell-extension-appindicator.git Package: gnome-shell-extension-appindicator Architecture: all diff -Nru gnome-shell-extension-appindicator-23/debian/gbp.conf gnome-shell-extension-appindicator-22/debian/gbp.conf --- gnome-shell-extension-appindicator-23/debian/gbp.conf 2019-02-22 08:54:12.000000000 +0000 +++ gnome-shell-extension-appindicator-22/debian/gbp.conf 2018-05-07 20:58:05.000000000 +0000 @@ -1,17 +1,3 @@ [DEFAULT] -pristine-tar = True debian-branch = debian/master -upstream-branch = upstream/latest -upstream-vcs-tag = v%(version)s - -[buildpackage] -sign-tags = True - -[dch] -multimaint-merge = True - -[import-orig] -postimport = dch -v%(version)s New upstream release; git add debian/changelog; debcommit - -[pq] -patch-numbers = False +upstream-branch = master diff -Nru gnome-shell-extension-appindicator-23/debian/patches/01-Add_3.28_support.patch gnome-shell-extension-appindicator-22/debian/patches/01-Add_3.28_support.patch --- gnome-shell-extension-appindicator-23/debian/patches/01-Add_3.28_support.patch 1970-01-01 00:00:00.000000000 +0000 +++ gnome-shell-extension-appindicator-22/debian/patches/01-Add_3.28_support.patch 2018-05-07 20:59:51.000000000 +0000 @@ -0,0 +1,15 @@ +Author: Matteo F. Vescovi +Description: Add support for GNOME Shell 3.28 +Date: 2018-05-07 + +diff --git a/metadata.json b/metadata.json +index aee011a..fff5934 100644 +--- a/metadata.json ++++ b/metadata.json +@@ -1,5 +1,5 @@ + { +- "shell-version": ["3.16", "3.17.91", "3.18", "3.20", "3.22", "3.24", "3.26"], ++ "shell-version": ["3.16", "3.17.91", "3.18", "3.20", "3.22", "3.24", "3.26", "3.28"], + "uuid": "appindicatorsupport@rgcjonas.gmail.com", + "name": "KStatusNotifierItem/AppIndicator Support", + "description": "Adds KStatusNotifierItem support to the Shell", diff -Nru gnome-shell-extension-appindicator-23/debian/patches/02-Fix_metadata.patch gnome-shell-extension-appindicator-22/debian/patches/02-Fix_metadata.patch --- gnome-shell-extension-appindicator-23/debian/patches/02-Fix_metadata.patch 1970-01-01 00:00:00.000000000 +0000 +++ gnome-shell-extension-appindicator-22/debian/patches/02-Fix_metadata.patch 2018-05-07 21:00:43.000000000 +0000 @@ -0,0 +1,19 @@ +Author: Matteo F. Vescovi +Description: Fix metadata.json to reflect real ownership +Forwarded: https://github.com/Ubuntu/gnome-shell-extension-appindicator/pull/122 +Date: 2018-05-07 + +diff --git a/metadata.json b/metadata.json +index aee011a..84ae2b0 100644 +--- a/metadata.json ++++ b/metadata.json +@@ -1,7 +1,7 @@ + { + "shell-version": ["3.16", "3.17.91", "3.18", "3.20", "3.22", "3.24", "3.26", "3.28"], +- "uuid": "appindicatorsupport@rgcjonas.gmail.com", ++ "uuid": "ubuntu-appindicators@ubuntu.com", + "name": "KStatusNotifierItem/AppIndicator Support", + "description": "Adds KStatusNotifierItem support to the Shell", +- "url": "https://github.com/rgcjonas/gnome-shell-extension-appindicator" ++ "url": "https://github.com/ubuntu/gnome-shell-extension-appindicator" + } diff -Nru gnome-shell-extension-appindicator-23/debian/patches/metadata-use-appindicator-namespace-and-naming.patch gnome-shell-extension-appindicator-22/debian/patches/metadata-use-appindicator-namespace-and-naming.patch --- gnome-shell-extension-appindicator-23/debian/patches/metadata-use-appindicator-namespace-and-naming.patch 2019-02-22 08:54:12.000000000 +0000 +++ gnome-shell-extension-appindicator-22/debian/patches/metadata-use-appindicator-namespace-and-naming.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -From: Debian GNOME Maintainers - -Date: Thu, 21 Feb 2019 18:01:46 +0100 -Subject: metadata: use appindicator namespace and naming - ---- - metadata.json | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/metadata.json b/metadata.json -index c148922..89db0e6 100644 ---- a/metadata.json -+++ b/metadata.json -@@ -1,11 +1,11 @@ - { -+ "name": "Ubuntu AppIndicators", -+ "description": "Support app indicators in top panel, as the default Ubuntu experience. System update of KStatusNotifierItem/AppIndicator extension.", -+ "uuid": "ubuntu-appindicators@ubuntu.com", -+ "url": "https://github.com/ubuntu/gnome-shell-extension-appindicator", - "shell-version": [ - "3.30", - "3.31", - "3.32" -- ], -- "uuid": "appindicatorsupport@rgcjonas.gmail.com", -- "name": "KStatusNotifierItem/AppIndicator Support", -- "description": "Adds KStatusNotifierItem support to the Shell", -- "url": "https://github.com/ubuntu/gnome-shell-extension-appindicator" -+ ] - } diff -Nru gnome-shell-extension-appindicator-23/debian/patches/series gnome-shell-extension-appindicator-22/debian/patches/series --- gnome-shell-extension-appindicator-23/debian/patches/series 2019-02-22 08:54:12.000000000 +0000 +++ gnome-shell-extension-appindicator-22/debian/patches/series 2018-05-07 21:05:17.000000000 +0000 @@ -1 +1,2 @@ -metadata-use-appindicator-namespace-and-naming.patch +01-Add_3.28_support.patch +02-Fix_metadata.patch diff -Nru gnome-shell-extension-appindicator-23/extension.js gnome-shell-extension-appindicator-22/extension.js --- gnome-shell-extension-appindicator-23/extension.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/extension.js 2017-10-23 14:27:00.000000000 +0000 @@ -23,11 +23,10 @@ let statusNotifierWatcher = null; let isEnabled = false; -let watchDog = null; function init() { - watchDog = new NameWatchdog(); - watchDog.onVanished = maybe_enable_after_name_available; + NameWatchdog.init(); + NameWatchdog.onVanished = maybe_enable_after_name_available; //HACK: we want to leave the watchdog alive when disabling the extension, // but if we are being reloaded, we destroy it since it could be considered @@ -35,9 +34,9 @@ if (typeof global['--appindicator-extension-on-reload'] == 'function') global['--appindicator-extension-on-reload']() - global['--appindicator-extension-on-reload'] = () => { + global['--appindicator-extension-on-reload'] = function() { Util.Logger.debug("Reload detected, destroying old watchdog") - watchDog.destroy(); + NameWatchdog.destroy() } } @@ -47,7 +46,7 @@ // monitor the bus manually to find out when the name vanished so we can reclaim it again. function maybe_enable_after_name_available() { // by the time we get called whe might not be enabled - if (isEnabled && !watchDog.isPresent && statusNotifierWatcher === null) + if (isEnabled && !NameWatchdog.isPresent && statusNotifierWatcher === null) statusNotifierWatcher = new StatusNotifierWatcher.StatusNotifierWatcher(); } @@ -67,29 +66,29 @@ /** * NameWatchdog will monitor the ork.kde.StatusNotifierWatcher bus name for us */ -var NameWatchdog = class AppIndicators_NameWatchdog { +const NameWatchdog = { + onAppeared: null, + onVanished: null, - constructor() { - this.onAppeared = null; - this.onVanished = null; + _watcher_id: null, - // will be set in the handlers which are guaranteed to be called at least once - this.isPresent = false; + isPresent: false, //will be set in the handlers which are guaranteed to be called at least once + init: function() { this._watcher_id = Gio.DBus.session.watch_name("org.kde.StatusNotifierWatcher", 0, this._appeared_handler.bind(this), this._vanished_handler.bind(this)); - } + }, - destroy() { + destroy: function() { Gio.DBus.session.unwatch_name(this._watcher_id); - } + }, - _appeared_handler() { + _appeared_handler: function() { this.isPresent = true; if (this.onAppeared) this.onAppeared(); - } + }, - _vanished_handler() { + _vanished_handler: function() { this.isPresent = false; if (this.onVanished) this.onVanished(); } diff -Nru gnome-shell-extension-appindicator-23/iconCache.js gnome-shell-extension-appindicator-22/iconCache.js --- gnome-shell-extension-appindicator-23/iconCache.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/iconCache.js 2017-10-23 14:27:00.000000000 +0000 @@ -15,8 +15,8 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. const GLib = imports.gi.GLib -const GObject = imports.gi.GObject +const Lang = imports.lang const Mainloop = imports.mainloop const Util = imports.misc.extensionUtils.getCurrentExtension().imports.util; @@ -27,108 +27,61 @@ // If the lifetime of an icon is over, the cache will destroy the icon. (!) // The presence of an inUse property set to true on the icon will extend the lifetime. -const LIFETIME_TIMESPAN = 5000; // milli-seconds -const GC_INTERVAL = 10; // seconds - // how to use: see IconCache.add, IconCache.get -var IconCache = class AppIndicators_IconCache { - constructor() { +const IconCache = new Lang.Class({ + Name: 'IconCache', + + LIFETIME_TIMESPAN: 5000, //5s + GC_INTERVAL: 10000, //10s + + _init: function() { this._cache = {}; this._lifetime = {}; //we don't want to attach lifetime to the object - this._destroyNotify = {}; - } + this._gc(); + }, - add(id, o) { - if (!(o && id)) - return null; - - if (!(id in this._cache) || this._cache[id] !== o) { + add: function(id, o) { + //Util.Logger.debug("IconCache: adding "+id); + if (!(o && id)) return null; + if (id in this._cache && this._cache[id] !== o) this._remove(id); - - //Util.Logger.debug("IconCache: adding "+id,o); - this._cache[id] = o; - - if ((o instanceof GObject.Object) && GObject.signal_lookup('destroy', o)) { - this._destroyNotify[id] = o.connect('destroy', () => { - this._remove(id); - }); - } - } - - this._renewLifetime(id); - this._checkGC(); - + this._cache[id] = o; + this._lifetime[id] = new Date().getTime() + this.LIFETIME_TIMESPAN; return o; - } - - _remove(id) { - if (!(id in this._cache)) - return; + }, + _remove: function(id) { //Util.Logger.debug('IconCache: removing '+id); - - let object = this._cache[id]; - - if ((object instanceof GObject.Object) && GObject.signal_lookup('destroy', object)) - object.disconnect(this._destroyNotify[id]); - - if (typeof object.destroy === 'function') - object.destroy(); - + if ('destroy' in this._cache[id]) this._cache[id].destroy(); delete this._cache[id]; delete this._lifetime[id]; - delete this._destroyNotify[id]; - - this._checkGC(); - } - - _renewLifetime(id) { - if (id in this._cache) - this._lifetime[id] = new Date().getTime() + LIFETIME_TIMESPAN; - } + }, - forceDestroy(id) { + forceDestroy: function(id) { this._remove(id); - } + }, // removes everything from the cache - clear() { + clear: function() { for (let id in this._cache) this._remove(id) - - this._checkGC(); - } + }, // returns an object from the cache, or null if it can't be found. - get(id) { + get: function(id) { if (id in this._cache) { //Util.Logger.debug('IconCache: retrieving '+id); - this._renewLifetime(id); + this._lifetime[id] = new Date().getTime() + this.LIFETIME_TIMESPAN; //renew lifetime return this._cache[id]; } + else return null; + }, - return null; - } - - _checkGC() { - let cacheIsEmpty = (Object.keys(this._cache).length === 0); - - if (!cacheIsEmpty && !this._gcTimeout) { - //Util.Logger.debug("IconCache: garbage collector started"); - this._gcTimeout = Mainloop.timeout_add_seconds(GC_INTERVAL, - this._gc.bind(this)); - } else if (cacheIsEmpty && this._gcTimeout) { - //Util.Logger.debug("IconCache: garbage collector stopped"); - GLib.Source.remove(this._gcTimeout); - this._gcTimeout = 0; - } - } - - _gc() { + _gc: function() { var time = new Date().getTime(); for (var id in this._cache) { if (this._cache[id].inUse) { - //Util.Logger.debug("IconCache: " + id + " is in use."); + //Util.Logger.debug ("IconCache: " + id + " is in use."); continue; } else if (this._lifetime[id] < time) { this._remove(id); @@ -136,11 +89,12 @@ //Util.Logger.debug("IconCache: " + id + " survived this round."); } } + if (!this._stopGc) Mainloop.timeout_add(this.GC_INTERVAL, Lang.bind(this, this._gc)); + return false; //we just added our timeout again. + }, - return true; - } - - destroy() { + destroy: function() { + this._stopGc = true; this.clear(); } -}; +}); diff -Nru gnome-shell-extension-appindicator-23/indicatorStatusIcon.js gnome-shell-extension-appindicator-22/indicatorStatusIcon.js --- gnome-shell-extension-appindicator-23/indicatorStatusIcon.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/indicatorStatusIcon.js 2017-10-23 14:27:00.000000000 +0000 @@ -14,9 +14,9 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. const Clutter = imports.gi.Clutter; -const GObject = imports.gi.GObject; const St = imports.gi.St; +const Lang = imports.lang; const Main = imports.ui.main; const Panel = imports.ui.panel; const PanelMenu = imports.ui.panelMenu; @@ -31,13 +31,16 @@ /* * IndicatorStatusIcon implements an icon in the system status area */ -var IndicatorStatusIcon = GObject.registerClass( -class AppIndicators_IndicatorStatusIcon extends PanelMenu.Button { - _init(indicator) { - super._init(null, indicator._uniqueId); +const IndicatorStatusIcon = new Lang.Class({ + Name: 'IndicatorStatusIcon', + Extends: PanelMenu.Button, + + _init: function(indicator) { + this.parent(null, 'FIXME'); //no name yet (?) + this._indicator = indicator; - this._iconBox = new AppIndicator.IconActor(indicator, Panel.PANEL_ICON_SIZE + 6); + this._iconBox = new AppIndicator.IconActor(indicator, Panel.PANEL_ICON_SIZE + 2); if (!this._box) // Gnome Shell 3.10 this.actor.add_actor(this._box = new St.BoxLayout()); @@ -49,18 +52,11 @@ Util.connectSmart(this._indicator, 'label', this, '_updateLabel') Util.connectSmart(this._indicator, 'status', this, '_updateStatus') - this.connect('destroy', () => { - if (this._menuClient) { - this._menuClient.destroy(); - this._menuClient = null; - } - }) - if (this._indicator.isReady) this._display() - } + }, - _updateLabel() { + _updateLabel: function() { var label = this._indicator.label; if (label) { if (!this._label || !this._labelBin) { @@ -80,16 +76,29 @@ delete this._label; } } - } + }, - _updateStatus() { + _updateStatus: function() { if (this._indicator.status != AppIndicator.SNIStatus.PASSIVE) this.actor.show() else this.actor.hide() - } + }, + + destroy: function() { + // destroy stuff owned by us + if (this._menuClient) + this._menuClient.destroy() + + this._iconBox.destroy() + + this._box.destroy_all_children() + + //call parent + this.parent() + }, - _display() { + _display: function() { this._updateLabel() this._updateStatus() @@ -99,9 +108,9 @@ } Main.panel.addToStatusArea("appindicator-"+this._indicator.uniqueId, this, 1, 'right') - } + }, - _boxClicked(actor, event) { + _boxClicked: function(actor, event) { // if middle mouse button clicked send SecondaryActivate dbus event and do not show appindicator menu if (event.get_button() == 2) { Main.panel.menuManager._closeMenu(true, Main.panel.menuManager.activeMenu); diff -Nru gnome-shell-extension-appindicator-23/indicator-test-tool/testTool.js gnome-shell-extension-appindicator-22/indicator-test-tool/testTool.js --- gnome-shell-extension-appindicator-23/indicator-test-tool/testTool.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/indicator-test-tool/testTool.js 2017-10-23 14:27:00.000000000 +0000 @@ -9,7 +9,7 @@ const AppIndicator = imports.gi.AppIndicator3; const GLib = imports.gi.GLib; -(() => { +(function() { var app = new Gtk.Application({ application_id: null @@ -17,11 +17,11 @@ var window = null; -app.connect("activate", () => { +app.connect("activate", function(){ window.present(); }); -app.connect("startup", () => { +app.connect("startup", function() { window = new Gtk.ApplicationWindow({ title: "test", application: app @@ -97,13 +97,13 @@ menu.append(item); item = Gtk.MenuItem.new_with_label("Set Label"); - item.connect('activate', () => { + item.connect('activate', function() { indicator.set_label(''+new Date().getSeconds(), 'Blub'); }); menu.append(item); item = Gtk.MenuItem.new_with_label("Unset Label"); - item.connect('activate', () => { + item.connect('activate', function() { indicator.set_label('', ''); }) menu.append(item); @@ -112,9 +112,9 @@ menu.append(item); item = Gtk.MenuItem.new_with_label("Hide for some time"); - item.connect('activate', () => { + item.connect('activate', function() { indicator.set_status(AppIndicator.IndicatorStatus.PASSIVE); - GLib.timeout_add(0, 5000, () => { + GLib.timeout_add(0, 5000, function() { indicator.set_status(AppIndicator.IndicatorStatus.ACTIVE); return false; }); @@ -122,8 +122,8 @@ menu.append(item); item = Gtk.MenuItem.new_with_label("Close in 5 seconds"); - item.connect('activate', () => { - GLib.timeout_add(0, 5000, () => { + item.connect('activate', function() { + GLib.timeout_add(0, 5000, function() { app.quit(); return false; }); diff -Nru gnome-shell-extension-appindicator-23/interfaces.js gnome-shell-extension-appindicator-22/interfaces.js --- gnome-shell-extension-appindicator-23/interfaces.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/interfaces.js 2017-10-23 14:27:00.000000000 +0000 @@ -14,10 +14,10 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -var StatusNotifierItem = loadInterfaceXml("StatusNotifierItem.xml") +const StatusNotifierItem = loadInterfaceXml("StatusNotifierItem.xml") const Properties = loadInterfaceXml("Properties.xml") -var StatusNotifierWatcher = loadInterfaceXml("StatusNotifierWatcher.xml") -var DBusMenu = loadInterfaceXml("DBusMenu.xml") +const StatusNotifierWatcher = loadInterfaceXml("StatusNotifierWatcher.xml") +const DBusMenu = loadInterfaceXml("DBusMenu.xml") // loads a xml file into an in-memory string function loadInterfaceXml(filename) { @@ -35,8 +35,6 @@ // Otherwise, it will try to check `instanceof XML` and fail miserably because there // is no `XML` on very recent SpiderMonkey releases (or, if SpiderMonkey is old enough, // will spit out a TypeError soon). - if (contents instanceof Uint8Array) - contents = imports.byteArray.toString(contents); return "" + contents + "" } else { throw new Error("AppIndicatorSupport: Could not load file: "+filename) diff -Nru gnome-shell-extension-appindicator-23/metadata.json gnome-shell-extension-appindicator-22/metadata.json --- gnome-shell-extension-appindicator-23/metadata.json 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/metadata.json 2017-10-23 14:27:00.000000000 +0000 @@ -1,11 +1,7 @@ { - "shell-version": [ - "3.30", - "3.31", - "3.32" - ], + "shell-version": ["3.16", "3.17.91", "3.18", "3.20", "3.22", "3.24", "3.26"], "uuid": "appindicatorsupport@rgcjonas.gmail.com", "name": "KStatusNotifierItem/AppIndicator Support", "description": "Adds KStatusNotifierItem support to the Shell", - "url": "https://github.com/ubuntu/gnome-shell-extension-appindicator" + "url": "https://github.com/rgcjonas/gnome-shell-extension-appindicator" } diff -Nru gnome-shell-extension-appindicator-23/statusNotifierWatcher.js gnome-shell-extension-appindicator-22/statusNotifierWatcher.js --- gnome-shell-extension-appindicator-23/statusNotifierWatcher.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/statusNotifierWatcher.js 2017-10-23 14:27:00.000000000 +0000 @@ -18,6 +18,7 @@ const GLib = imports.gi.GLib const Gtk = imports.gi.Gtk +const Lang = imports.lang const Mainloop = imports.mainloop const ShellConfig = imports.misc.config const Signals = imports.signals @@ -42,41 +43,42 @@ /* * The StatusNotifierWatcher class implements the StatusNotifierWatcher dbus object */ -var StatusNotifierWatcher = class AppIndicators_StatusNotifierWatcher { +const StatusNotifierWatcher = new Lang.Class({ + Name: 'StatusNotifierWatcher', - constructor() { + _init: function() { this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(Interfaces.StatusNotifierWatcher, this); this._dbusImpl.export(Gio.DBus.session, WATCHER_OBJECT); this._cancellable = new Gio.Cancellable; this._everAcquiredName = false; this._ownName = Gio.DBus.session.own_name(WATCHER_BUS_NAME, - Gio.BusNameOwnerFlags.NONE, - this._acquiredName.bind(this), - this._lostName.bind(this)); + Gio.BusNameOwnerFlags.NONE, + Lang.bind(this, this._acquiredName), + Lang.bind(this, this._lostName)); this._items = { }; this._nameWatcher = { }; this._seekStatusNotifierItems(); - } + }, - _acquiredName() { + _acquiredName: function() { this._everAcquiredName = true; - } + }, - _lostName() { + _lostName: function() { if (this._everAcquiredName) Util.Logger.debug('Lost name' + WATCHER_BUS_NAME); else Util.Logger.warn('Failed to acquire ' + WATCHER_BUS_NAME); - } + }, // create a unique index for the _items dictionary - _getItemId(bus_name, obj_path) { + _getItemId: function(bus_name, obj_path) { return bus_name + obj_path; - } + }, - _registerItem(service, bus_name, obj_path) { + _registerItem: function(service, bus_name, obj_path) { let id = this._getItemId(bus_name, obj_path); if (this._items[id]) { @@ -97,9 +99,9 @@ this._itemVanished.bind(this)); this._dbusImpl.emit_property_changed('RegisteredStatusNotifierItems', GLib.Variant.new('as', this.RegisteredStatusNotifierItems)); - } + }, - _ensureItemRegistered(service, bus_name, obj_path) { + _ensureItemRegistered: function(service, bus_name, obj_path) { let id = this._getItemId(bus_name, obj_path); if (this._items[id]) { @@ -109,27 +111,29 @@ } this._registerItem(service, bus_name, obj_path) - } + }, - _seekStatusNotifierItems() { + _seekStatusNotifierItems: function() { // Some indicators (*coff*, dropbox, *coff*) do not re-register again // when the plugin is enabled/disabled, thus we need to manually look // for the objects in the session bus that implements the // StatusNotifierItem interface... - Util.traverseBusNames(Gio.DBus.session, this._cancellable, (bus, name, cancellable) => { - Util.introspectBusObject(bus, name, cancellable, (node_info) => { - return Util.dbusNodeImplementsInterfaces(node_info, ['org.kde.StatusNotifierItem']); - }, (name, path) => { - let id = this._getItemId(name, path); - if (!this._items[id]) { + let self = this; + Util.traverseBusNames(Gio.DBus.session, this._cancellable, function(bus, name, cancellable) { + Util.introspectBusObject(bus, name, cancellable, function(node_info) { + return Util.dbusNodeImplementsInterfaces(node_info, ["org.kde.StatusNotifierItem"]); + }, + function(name, path) { + let id = self._getItemId(name, path); + if (!self._items[id]) { Util.Logger.debug("Using Brute-force mode for StatusNotifierItem "+id); - this._registerItem(path, name, path); + self._registerItem(path, name, path); } }) }); - } + }, - RegisterStatusNotifierItemAsync(params, invocation) { + RegisterStatusNotifierItemAsync: function(params, invocation) { // it would be too easy if all application behaved the same // instead, ayatana patched gnome apps to send a path // while kde apps send a bus name @@ -157,50 +161,50 @@ this._ensureItemRegistered(service, bus_name, obj_path); invocation.return_value(null); - } + }, - _itemVanished(proxy, bus_name) { + _itemVanished: function(proxy, bus_name) { // FIXME: this is useless if the path name disappears while the bus stays alive (not unheard of) for (var i in this._items) { if (i.indexOf(bus_name) == 0) { this._remove(i); } } - } + }, - _remove(id) { + _remove: function(id) { this._items[id].destroy(); delete this._items[id]; Gio.DBus.session.unwatch_name(this._nameWatcher[id]); delete this._nameWatcher[id]; this._dbusImpl.emit_signal('StatusNotifierItemUnregistered', GLib.Variant.new('(s)', id)); this._dbusImpl.emit_property_changed('RegisteredStatusNotifierItems', GLib.Variant.new('as', this.RegisteredStatusNotifierItems)); - } + }, - RegisterNotificationHost(service) { + RegisterNotificationHost: function(service) { throw new Gio.DBusError('org.gnome.Shell.UnsupportedMethod', 'Registering additional notification hosts is not supported'); - } + }, - IsNotificationHostRegistered() { + IsNotificationHostRegistered: function() { return true; - } + }, - ProtocolVersion() { + ProtocolVersion: function() { // "The version of the protocol the StatusNotifierWatcher instance implements." [sic] // in what syntax? - return `${Extension.uuid} (KDE; compatible; mostly) GNOME Shell/${ShellConfig.PACKAGE_VERSION}`; - } + return "appindicatorsupport@rgcjonas.gmail.com (KDE; compatible; mostly) GNOME Shell/%s".format(ShellConfig.PACKAGE_VERSION); + }, get RegisteredStatusNotifierItems() { return Object.keys(this._items); - } + }, get IsStatusNotifierHostRegistered() { return true; - } + }, - destroy() { + destroy: function() { if (!this._isDestroyed) { // this doesn't do any sync operation and doesn't allow us to hook up the event of being finished // which results in our unholy debounce hack (see extension.js) @@ -218,4 +222,4 @@ this._isDestroyed = true; } } -}; +}); diff -Nru gnome-shell-extension-appindicator-23/util.js gnome-shell-extension-appindicator-22/util.js --- gnome-shell-extension-appindicator-23/util.js 2019-02-21 15:35:26.000000000 +0000 +++ gnome-shell-extension-appindicator-22/util.js 2017-10-23 14:27:00.000000000 +0000 @@ -17,9 +17,10 @@ const GLib = imports.gi.GLib const GObject = imports.gi.GObject +const Lang = imports.lang const Signals = imports.signals -var refreshPropertyOnProxy = function(proxy, property_name) { +const refreshPropertyOnProxy = function(proxy, property_name) { proxy.g_connection.call(proxy.g_name, proxy.g_object_path, 'org.freedesktop.DBus.Properties', @@ -46,7 +47,7 @@ }) } -var getUniqueBusNameSync = function(bus, name) { +const getUniqueBusNameSync = function(bus, name) { if (name[0] == ':') return name; @@ -61,7 +62,7 @@ return unique; } -var traverseBusNames = function(bus, cancellable, callback) { +const traverseBusNames = function(bus, cancellable, callback) { if (typeof bus === "undefined" || !bus) bus = Gio.DBus.session; @@ -88,7 +89,7 @@ }); } -var introspectBusObject = function(bus, name, cancellable, filterFunction, targetCallback, path) { +const introspectBusObject = function(bus, name, cancellable, filterFunction, targetCallback, path) { if (typeof path === "undefined" || !path) path = "/"; @@ -120,7 +121,7 @@ }); } -var dbusNodeImplementsInterfaces = function(node_info, interfaces) { +const dbusNodeImplementsInterfaces = function(node_info, interfaces) { if (!(node_info instanceof Gio.DBusNodeInfo) || !Array.isArray(interfaces)) return false; @@ -136,7 +137,7 @@ let id = src.connect(signal, handler) if (src.connect && (!(src instanceof GObject.Object) || GObject.signal_lookup('destroy', src))) { - let destroy_id = src.connect('destroy', () => { + let destroy_id = src.connect('destroy', function() { src.disconnect(id) src.disconnect(destroy_id) }) @@ -170,9 +171,9 @@ * Usage: * Util.connectSmart(srcOb, 'signal', tgtObj, 'handler') * or - * Util.connectSmart(srcOb, 'signal', () => { ... }) + * Util.connectSmart(srcOb, 'signal', function() { ... }) */ -var connectSmart = function() { +const connectSmart = function() { if (arguments.length == 4) return connectSmart4A.apply(null, arguments) else @@ -182,25 +183,39 @@ /** * Helper class for logging stuff */ -var Logger = class AppIndicators_Logger { - static _log(prefix, message) { +const Logger = { + _log: function(prefix, message) { global.log("[AppIndicatorSupport-"+prefix+"] "+message) - } + }, - static debug(message) { - // CHeck the shell env variable to get what level to use + debug: function(message) { Logger._log("DEBUG", message); - } + }, - static warn(message) { + warn: function(message) { Logger._log("WARN", message); - } + }, - static error(message) { + error: function(message) { Logger._log("ERROR", message); - } + }, - static fatal(message) { + fatal: function(message) { Logger._log("FATAL", message); } }; + +/** + * Workaround for https://bugzilla.gnome.org/show_bug.cgi?id=734071 + * + * Will append the given name with a number to distinguish code loaded later from the last loaded version + */ +const WORKAROUND_RELOAD_TYPE_REGISTER = function(name) { + return 'Gjs_' + name + '__' + global['--appindicator-loaded-count'] +} + +// this will only execute once when the extension is loaded +if (!global['--appindicator-loaded-count']) + global['--appindicator-loaded-count'] = 1 +else + global['--appindicator-loaded-count']++