diff --git a/extension.js b/extension.js index 8b910a9..a8e32fd 100644 --- a/extension.js +++ b/extension.js @@ -55,6 +55,143 @@ function log(message) { } +class SignalMgt { + + constructor(item, name, group, dbus, menu) { + this.name = name; + this.group = group; + this.fullname = this.name + '@' + this.group; + this.dbus = dbus; + this.menu = menu; + this.signals = {} + + this.nbClicks = 0; + this.button = -1; + + this.onClick = hashGet(item, 'on-click', ''); + this.onDblClick = hashGet(item, 'on-dblclick', ''); + this.onRightClick = hashGet(item, 'on-rightclick', ''); + this.onRightDblClick = hashGet(item, 'on-rightdblclick', ''); + this.onEnter = hashGet(item, 'on-enter', ''); + this.onLeave = hashGet(item, 'on-leave', ''); + this.onScroll = hashGet(item, 'on-scroll', ''); + } + + destructor() { + for(let widgetIdx in this.signals) + this.disconnectWidgetSignals(this.signals[widgetIdx]); + } + + updateSignals(item) { + this.onClick = hashGet(item, 'on-click', this.onClick); + this.onDblClick = hashGet(item, 'on-dblclick', this.onDblClick); + this.onRightClick = hashGet(item, 'on-rightclick', this.onRightClick); + this.onRightDblClick = hashGet(item, 'on-rightdblclick', this.onRightDblClick); + this.onEnter = hashGet(item, 'on-enter', this.onEnter); + this.onLeave = hashGet(item, 'on-leave', this.onLeave); + this.onScroll = hashGet(item, 'on-scroll', this.onScroll); + } + + connectWidgetSignals(widget) { + this.signals[widget] = []; + let id; + id = widget.connect('enter-event', this._onEnter.bind(this)); + this.signals[widget].push(id); + id = widget.connect('leave-event', this._onLeave.bind(this)); + this.signals[widget].push(id); + id = widget.connect('scroll-event', this._onScroll.bind(this)); + this.signals[widget].push(id); + widget.set_reactive(true); + id = widget.connect('button-release-event', Lang.bind(this, this._clicked)); + this.signals[widget].push(id); + } + + disconnectWidgetSignals(widget) { + for(let idx in this.signals[widget]) + widget.disconnect(this.signals[widget][idx]); + this.signals[widget] = null; + } + + _manageEventAction(action, signalName) { + if (action === 'open-popup') + this.menu.open(true); + else if (action === 'close-popup') + this.menu.close(); + else if (action === 'toggle-popup') + this.menu.toggle(); + else if (action == 'delete') + this.dbus.deleteItem(this, this.group); + else if (action === 'signal') + this.dbus.emitSignal(signalName, this.fullname); + + return Clutter.EVENT_PROPAGATE; + } + + _manageLeaveEvent() { + this._manageEventAction(this.onLeave); + } + + _doClickCallback() { + let right = ''; + let nbClicks = ''; + + if (this.button == 3) + right = 'Right'; + if (this.nbClicks > 1) + nbClicks = 'Dbl'; + + let signalName = 'on' + right + nbClicks + 'Click'; + + let action = 'signal'; + switch(signalName) { + case 'onClick': action = this.onClick; break; + case 'onDblClick': action = this.onDblClick; break; + case 'onRightClick': action = this.onRightClick; break; + case 'onRightDblClick': action = this.onRightDblClick; break; + } + + this._manageEventAction(action, signalName); + + this.nbClicks = 0; + this.button = -1; + + return false; + } + + _clicked(actor, event) { + if (event.get_button() == this.button) { + this.nbClicks++; + } else { + this.button = event.get_button(); + this.nbClicks = 1; + + Mainloop.timeout_add(this.dbus.ClutterSettings['double-click-time'], + Lang.bind(this, this._doClickCallback)); + } + + return Clutter.EVENT_PROPAGATE; + } + + _onEnter(/*actor, event*/) { + return this._manageEventAction(this.onEnter, 'onEnter'); + } + + _onLeave(/*actor, event*/) { + return this._manageEventAction(this.onLeave, 'onLeave'); + } + + _onScroll(actor, event) { + let signalName = ''; + let direction = event.get_scroll_direction (); + if (direction == Clutter.ScrollDirection.UP) + signalName = 'onScrollUp'; + else if (direction == Clutter.ScrollDirection.DOWN) + signalName = 'onScrollDown'; + + return this._manageEventAction(this.onScroll, signalName); + } +} + var MyPopupMenuItem = GObject.registerClass({ GTypeName: "MyPopupMenuItem" }, @@ -85,8 +222,9 @@ class MonitorWidget extends PanelMenu.Button { this.group = group; this.fullname = this.name + '@' + this.group; this.dbus = dbus; - this.signals = {} - + this.signals = new SignalMgt(item, this.name, group, dbus, this.menu); + this.popup_signals = {}; + if (item.hasOwnProperty('icon')) { if (typeof(item['icon']) === "string") @@ -94,7 +232,7 @@ class MonitorWidget extends PanelMenu.Button { else this.icon = this._createIcon(item['icon']); if (this.icon !== null) { - this._connectWidgetSignals(this.icon); + this.signals.connectWidgetSignals(this.icon); this.add_child(this.icon); } } @@ -109,7 +247,7 @@ class MonitorWidget extends PanelMenu.Button { this.widget = this._createText(item['text']); if (this.widget !== null) { - this._connectWidgetSignals(this.widget); + this.signals.connectWidgetSignals(this.widget); this.add_child(this.widget); } } @@ -119,27 +257,13 @@ class MonitorWidget extends PanelMenu.Button { if (item.hasOwnProperty('popup')) this._createPopup(item['popup']); - this.onClick = hashGet(item, 'on-click', ''); - this.onDblClick = hashGet(item, 'on-dblclick', ''); - this.onRightClick = hashGet(item, 'on-rightclick', ''); - this.onRightDblClick = hashGet(item, 'on-rightdblclick', ''); - this.onEnter = hashGet(item, 'on-enter', ''); - this.onLeave = hashGet(item, 'on-leave', ''); - this.onScroll = hashGet(item, 'on-scroll', ''); - let box = hashGet(item, 'box', 'center'); if (box === 'right' && position == -1) position = 0; this.connect('style-changed', this._onStyleChanged.bind(this)); - - // Disable click event at PanelMenu.button level - this.setSensitive(false); - this.nbClicks = 0; - this.button = -1; - Main.panel.addToStatusArea(this.fullname, this, position, box); } @@ -148,26 +272,6 @@ class MonitorWidget extends PanelMenu.Button { this._minHPadding = 1; this._natHPadding = 1; } - - _connectWidgetSignals(widget) { - this.signals[widget] = []; - let id; - id = widget.connect('enter-event', this._onEnter.bind(this)); - this.signals[widget].push(id); - id = widget.connect('leave-event', this._onLeave.bind(this)); - this.signals[widget].push(id); - id = widget.connect('scroll-event', this._onScroll.bind(this)); - this.signals[widget].push(id); - widget.set_reactive(true); - id = widget.connect('button-release-event', Lang.bind(this, this._clicked)); - this.signals[widget].push(id); - } - - _disconnectWidgetSignals(widget) { - for(let idx in this.signals[widget]) - widget.disconnect(this.signals[widget][idx]); - this.signals[widget] = null; - } _createPopup(item) { if (!item.hasOwnProperty('items')) { @@ -179,13 +283,29 @@ class MonitorWidget extends PanelMenu.Button { let widget = null; let widgetDict = item['items'][itemIndex]; - if (widgetDict.hasOwnProperty('text')) - widget = this._createText(widgetDict['text']); - else if (widgetDict.hasOwnProperty('picture')) - widget = this._createPicture(widgetDict['picture']); - - if (widget !== null) - widgets.push(widget); + let nestedItem = null; + if (widgetDict.hasOwnProperty('text')) { + nestedItem = widgetDict['text']; + widget = this._createText(nestedItem); + } + else if (widgetDict.hasOwnProperty('picture')) { + nestedItem = widgetDict['picture']; + widget = this._createPicture(nestedItem); + } + else { + log('No known widget defined in popup'); + } + + if (nestedItem === null) { + continue; + } + + widgets.push(widget); + let name = hashGet(nestedItem, 'name', ''); + this.popup_signals[widget] = new SignalMgt(nestedItem, name, + this.fullname, this.dbus, + this.menu); + this.popup_signals[widget].connectWidgetSignals(widget); } if (widgets.length > 0) { @@ -290,85 +410,6 @@ class MonitorWidget extends PanelMenu.Button { return box; } - _manageEventAction(action, signalName) { - if (action === 'open-popup') - this.menu.open(true); - else if (action === 'close-popup') - this.menu.close(); - else if (action === 'toggle-popup') - this.menu.toggle(); - else if (action == 'delete') - this.dbus.deleteItem(this, this.group); - else if (action === 'signal') - this.dbus.emitSignal(signalName, this.fullname); - - return Clutter.EVENT_PROPAGATE; - } - - _manageLeaveEvent() { - this._manageEventAction(this.onLeave); - } - - _doClickCallback() { - let right = ''; - let nbClicks = ''; - - if (this.button == 3) - right = 'Right'; - if (this.nbClicks > 1) - nbClicks = 'Dbl'; - - let signalName = 'on' + right + nbClicks + 'Click'; - - let action = 'signal'; - switch(signalName) { - case 'onClick': action = this.onClick; break; - case 'onDblClick': action = this.onDblClick; break; - case 'onRightClick': action = this.onRightClick; break; - case 'onRightDblClick': action = this.onRightDblClick; break; - } - - this._manageEventAction(action, signalName); - - this.nbClicks = 0; - this.button = -1; - - return false; - } - - _clicked(actor, event) { - if (event.get_button() == this.button) { - this.nbClicks++; - } else { - this.button = event.get_button(); - this.nbClicks = 1; - - Mainloop.timeout_add(this.dbus.ClutterSettings['double-click-time'], - Lang.bind(this, this._doClickCallback)); - } - - return Clutter.EVENT_PROPAGATE; - } - - _onEnter(/*actor, event*/) { - return this._manageEventAction(this.onEnter, 'onEnter'); - } - - _onLeave(/*actor, event*/) { - return this._manageEventAction(this.onLeave, 'onLeave'); - } - - _onScroll(actor, event) { - let signalName = ''; - let direction = event.get_scroll_direction (); - if (direction == Clutter.ScrollDirection.UP) - signalName = 'onScrollUp'; - else if (direction == Clutter.ScrollDirection.DOWN) - signalName = 'onScrollDown'; - - return this._manageEventAction(this.onScroll, signalName); - } - update(item) { let prevWidget = this.widget; let prevIcon = this.icon; @@ -424,7 +465,7 @@ class MonitorWidget extends PanelMenu.Button { } if (prevIcon) { - this._disconnectWidgetSignals(prevIcon); + this.signals.disconnectWidgetSignals(prevIcon); this.insert_child_above(this.icon, prevIcon); this.remove_child(prevIcon); //delete prevIcon; @@ -442,6 +483,8 @@ class MonitorWidget extends PanelMenu.Button { if (this.menuItem) { if (menuOpen) this.menu.close(); + for(let widgetIdx in this.popup_signals) + this.signals.disconnectWidgetSignals(this.popup_signals[widgetIdx]); this.menu.removeAll(); //delete this.menuItem; } @@ -451,13 +494,7 @@ class MonitorWidget extends PanelMenu.Button { this.menu.open(true); } - this.onClick = hashGet(item, 'on-click', this.onClick); - this.onDblClick = hashGet(item, 'on-dblclick', this.onDblClick); - this.onRightClick = hashGet(item, 'on-rightclick', this.onRightClick); - this.onRightDblClick = hashGet(item, 'on-rightdblclick', this.onRightDblClick); - this.onEnter = hashGet(item, 'on-enter', this.onEnter); - this.onLeave = hashGet(item, 'on-leave', this.onLeave); - this.onScroll = hashGet(item, 'on-scroll', this.onScroll); + this.signals.updateSignals(item); } openPopup() { diff --git a/metadata.json b/metadata.json index 5cc5f09..14d529d 100644 --- a/metadata.json +++ b/metadata.json @@ -2,7 +2,7 @@ "uuid": "generic-monitor@gnome-shell-extensions", "name": "Generic Monitor", "description": "Display text & icon on systray using DBUS", - "version": "3", + "version": "4", "shell-version": [ "3.38", "3.36",