Add onClick feature
This commit is contained in:
parent
b3200da89c
commit
c7462662f4
11
README.md
11
README.md
|
@ -25,6 +25,7 @@ All functions read JSON formatted parameters
|
|||
"group": "groupname",
|
||||
// style and icon-style are optional
|
||||
// item can have text and/or icon
|
||||
// item can have click action "signal" or "delete"
|
||||
"items": [
|
||||
{
|
||||
"name":"",
|
||||
|
@ -32,6 +33,7 @@ All functions read JSON formatted parameters
|
|||
"style":"",
|
||||
"icon-style":"",
|
||||
"icon":"",
|
||||
"on-click":"",
|
||||
}, ...
|
||||
]
|
||||
}
|
||||
|
@ -48,6 +50,15 @@ All functions read JSON formatted parameters
|
|||
}
|
||||
|
||||
|
||||
When text/icon is clicked and on-click parameter is set to "signal",
|
||||
extension emit one of the following signals :
|
||||
|
||||
* onClick
|
||||
* onRightClick
|
||||
* onDblClick
|
||||
* onRightDblClick
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
|
|
12
dbus.xml
12
dbus.xml
|
@ -8,4 +8,16 @@
|
|||
<method name="deleteGroups">
|
||||
<arg type="s" direction="in" />
|
||||
</method>
|
||||
<signal name="onClick">
|
||||
<arg type="s" direction="out" />
|
||||
</signal>
|
||||
<signal name="onRightClick">
|
||||
<arg type="s" direction="out" />
|
||||
</signal>
|
||||
<signal name="onDblClick">
|
||||
<arg type="s" direction="out" />
|
||||
</signal>
|
||||
<signal name="onRightDblClick">
|
||||
<arg type="s" direction="out" />
|
||||
</signal>
|
||||
</interface>
|
||||
|
|
114
extension.js
114
extension.js
|
@ -20,14 +20,19 @@
|
|||
|
||||
const St = imports.gi.St;
|
||||
const Gio = imports.gi.Gio;
|
||||
const Lang = imports.lang;
|
||||
const GLib = imports.gi.GLib
|
||||
const Main = imports.ui.main;
|
||||
const Mainloop = imports.mainloop;
|
||||
const clutter = imports.gi.Clutter;
|
||||
|
||||
class MonitorWidget {
|
||||
constructor(name, group, text, style, icon, iconStyle) {
|
||||
constructor(name, group, text, style, icon, iconStyle, onClick) {
|
||||
this.name = name;
|
||||
this.group = group;
|
||||
this._createIcon(icon, iconStyle);
|
||||
this._createText(text, style);
|
||||
this.onClick = onClick;
|
||||
}
|
||||
|
||||
_createText(text, style) {
|
||||
|
@ -100,6 +105,8 @@ function loadInterfaceXml(filename) {
|
|||
class GenericMonitorDBUS {
|
||||
constructor() {
|
||||
this.monitor_groups = {};
|
||||
this.actor_clicked = {};
|
||||
this.clutterSettings = clutter.Settings.get_default();
|
||||
this.box = Main.panel._centerBox;
|
||||
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(loadInterfaceXml('dbus.xml'), this);
|
||||
this._dbusImpl.export(Gio.DBus.session, '/com/soutade/GenericMonitor');
|
||||
|
@ -118,6 +125,10 @@ class GenericMonitorDBUS {
|
|||
throw new Error('No name defined for item');
|
||||
if (!item.hasOwnProperty('text') && !item.hasOwnProperty('icon'))
|
||||
throw new Error('No text not icon defined for item');
|
||||
if (item.hasOwnProperty('on-click')) {
|
||||
if (item['on-click'] !== 'signal' && item['on-click'] !== 'delete')
|
||||
throw new Error('Invalid on-click value');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +142,73 @@ class GenericMonitorDBUS {
|
|||
return null;
|
||||
}
|
||||
|
||||
_doClickCallback() {
|
||||
for(let itemIndex in this.actor_clicked) {
|
||||
let item = this.actor_clicked[itemIndex];
|
||||
let right = '';
|
||||
let nbClicks = '';
|
||||
if (item['button'] == 3)
|
||||
right = 'Right';
|
||||
if (item['nbClicks'] > 1)
|
||||
nbClicks = 'Dbl';
|
||||
let signalName = 'on' + right + nbClicks + 'Click';
|
||||
this._dbusImpl.emit_signal(signalName, GLib.Variant.new('(s)',[item['name']]));
|
||||
}
|
||||
this.actor_clicked = {}
|
||||
}
|
||||
|
||||
_actorToMonitorWidget(actor) {
|
||||
for (let groupName in this.monitor_groups) {
|
||||
let group = this.monitor_groups[groupName];
|
||||
for (let itemIndex in group) {
|
||||
let item = group[itemIndex];
|
||||
if (item.widget === actor ||
|
||||
item.icon === actor)
|
||||
return [groupName, item];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_removeFromArray(array, value) {
|
||||
for(let i=0; i<array.length; i++) {
|
||||
if (array[i] === value) {
|
||||
array.splice(i, 1);
|
||||
if (array === null)
|
||||
array = [];
|
||||
break;
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/50100546/how-do-i-detect-clicks-on-the-gnome-appmenu
|
||||
_clicked(actor, event) {
|
||||
let result = this._actorToMonitorWidget(actor);
|
||||
if (result === null)
|
||||
return;
|
||||
|
||||
let groupName = result[0];
|
||||
let monitorWidget = result[1];
|
||||
|
||||
if (monitorWidget.onClick == 'signal') {
|
||||
let actorName = monitorWidget.name + '@' + groupName;
|
||||
if (!this.actor_clicked.hasOwnProperty(actorName)) {
|
||||
let clickItem = {};
|
||||
clickItem['name'] = actorName;
|
||||
clickItem['nbClicks'] = 1;
|
||||
clickItem['button'] = event.get_button();
|
||||
this.actor_clicked[actorName] = clickItem;
|
||||
Mainloop.timeout_add(this.clutterSettings['double-click-time'],
|
||||
Lang.bind(this, this._doClickCallback));
|
||||
} else {
|
||||
this.actor_clicked[actorName]['nbClicks'] = 2;
|
||||
}
|
||||
} else if (monitorWidget.onClick == 'delete') {
|
||||
this.deleteItem(monitorWidget, groupName);
|
||||
}
|
||||
}
|
||||
|
||||
notify(str) {
|
||||
let parameters = JSON.parse(str);
|
||||
this._checkParmeters(parameters);
|
||||
|
@ -158,13 +236,16 @@ class GenericMonitorDBUS {
|
|||
let iconStyle = '';
|
||||
if (item.hasOwnProperty('icon-style'))
|
||||
iconStyle = item['icon-style'];
|
||||
let onClick = '';
|
||||
if (item.hasOwnProperty('on-click'))
|
||||
onClick = item['on-click'];
|
||||
|
||||
let monitorWidget = this._getItemFromGroup(group, item['name']);
|
||||
let lastWidget = null;
|
||||
|
||||
// New widget
|
||||
if (monitorWidget === null) {
|
||||
monitorWidget = new MonitorWidget(item['name'], groupName, text, style, icon, iconStyle);
|
||||
monitorWidget = new MonitorWidget(item['name'], groupName, text, style, icon, iconStyle, onClick);
|
||||
if (group.length)
|
||||
lastWidget = group[group.length - 1].widget;
|
||||
group.push(monitorWidget);
|
||||
|
@ -175,6 +256,20 @@ class GenericMonitorDBUS {
|
|||
}
|
||||
if (monitorWidget.widget)
|
||||
this.box.insert_child_above(monitorWidget.widget, lastWidget);
|
||||
// Connect signals
|
||||
if (onClick !== '') {
|
||||
if (monitorWidget.widget)
|
||||
monitorWidget.widget.set_reactive(true);
|
||||
monitorWidget.widget.connect(
|
||||
'button-release-event', Lang.bind(this, this._clicked)
|
||||
);
|
||||
if (monitorWidget.icon) {
|
||||
monitorWidget.icon.set_reactive(true);
|
||||
monitorWidget.icon.connect(
|
||||
'button-release-event', Lang.bind(this, this._clicked)
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let prevWidget = monitorWidget.widget;
|
||||
let prevIcon = monitorWidget.icon;
|
||||
|
@ -201,6 +296,16 @@ class GenericMonitorDBUS {
|
|||
this.box.remove_child(item.icon);
|
||||
}
|
||||
|
||||
deleteItem(item, groupName) {
|
||||
let group = this.monitor_groups[groupName];
|
||||
this._removeItemFromBox(item);
|
||||
group = this._removeFromArray(group, item);
|
||||
if (group.length === 0)
|
||||
delete this.monitor_groups[groupName];
|
||||
else
|
||||
this.monitor_groups = group;
|
||||
}
|
||||
|
||||
deleteItems(str) {
|
||||
let parameters = JSON.parse(str);
|
||||
|
||||
|
@ -219,10 +324,7 @@ class GenericMonitorDBUS {
|
|||
let group = this.monitor_groups[groupName];
|
||||
let item = this._getItemFromGroup(group, itemName);
|
||||
if (item !== null) {
|
||||
this._removeItemFromBox(item);
|
||||
delete group[item['name']];
|
||||
if (group.length === 0)
|
||||
delete this.monitor_groups[groupName];
|
||||
this.deleteItem(item, groupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"uuid": "generic-monitor@gnome-shell-extensions",
|
||||
"name": "Generic Monitor",
|
||||
"description": "Generic monitor using DBUS",
|
||||
"version": "1",
|
||||
"description": "Display text & icon on systray using DBUS",
|
||||
"version": "2",
|
||||
"shell-version": [
|
||||
"3.34"
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue
Block a user