Add onClick feature

This commit is contained in:
Grégory Soutadé 2020-05-04 10:08:39 +02:00
parent b3200da89c
commit c7462662f4
4 changed files with 134 additions and 9 deletions

View File

@ -25,6 +25,7 @@ All functions read JSON formatted parameters
"group": "groupname", "group": "groupname",
// style and icon-style are optional // style and icon-style are optional
// item can have text and/or icon // item can have text and/or icon
// item can have click action "signal" or "delete"
"items": [ "items": [
{ {
"name":"", "name":"",
@ -32,6 +33,7 @@ All functions read JSON formatted parameters
"style":"", "style":"",
"icon-style":"", "icon-style":"",
"icon":"", "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 Example
------- -------

View File

@ -8,4 +8,16 @@
<method name="deleteGroups"> <method name="deleteGroups">
<arg type="s" direction="in" /> <arg type="s" direction="in" />
</method> </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> </interface>

View File

@ -20,14 +20,19 @@
const St = imports.gi.St; const St = imports.gi.St;
const Gio = imports.gi.Gio; const Gio = imports.gi.Gio;
const Lang = imports.lang;
const GLib = imports.gi.GLib
const Main = imports.ui.main; const Main = imports.ui.main;
const Mainloop = imports.mainloop;
const clutter = imports.gi.Clutter;
class MonitorWidget { class MonitorWidget {
constructor(name, group, text, style, icon, iconStyle) { constructor(name, group, text, style, icon, iconStyle, onClick) {
this.name = name; this.name = name;
this.group = group; this.group = group;
this._createIcon(icon, iconStyle); this._createIcon(icon, iconStyle);
this._createText(text, style); this._createText(text, style);
this.onClick = onClick;
} }
_createText(text, style) { _createText(text, style) {
@ -100,6 +105,8 @@ function loadInterfaceXml(filename) {
class GenericMonitorDBUS { class GenericMonitorDBUS {
constructor() { constructor() {
this.monitor_groups = {}; this.monitor_groups = {};
this.actor_clicked = {};
this.clutterSettings = clutter.Settings.get_default();
this.box = Main.panel._centerBox; this.box = Main.panel._centerBox;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(loadInterfaceXml('dbus.xml'), this); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(loadInterfaceXml('dbus.xml'), this);
this._dbusImpl.export(Gio.DBus.session, '/com/soutade/GenericMonitor'); this._dbusImpl.export(Gio.DBus.session, '/com/soutade/GenericMonitor');
@ -118,6 +125,10 @@ class GenericMonitorDBUS {
throw new Error('No name defined for item'); throw new Error('No name defined for item');
if (!item.hasOwnProperty('text') && !item.hasOwnProperty('icon')) if (!item.hasOwnProperty('text') && !item.hasOwnProperty('icon'))
throw new Error('No text not icon defined for item'); 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; 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) { notify(str) {
let parameters = JSON.parse(str); let parameters = JSON.parse(str);
this._checkParmeters(parameters); this._checkParmeters(parameters);
@ -158,13 +236,16 @@ class GenericMonitorDBUS {
let iconStyle = ''; let iconStyle = '';
if (item.hasOwnProperty('icon-style')) if (item.hasOwnProperty('icon-style'))
iconStyle = item['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 monitorWidget = this._getItemFromGroup(group, item['name']);
let lastWidget = null; let lastWidget = null;
// New widget // New widget
if (monitorWidget === null) { 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) if (group.length)
lastWidget = group[group.length - 1].widget; lastWidget = group[group.length - 1].widget;
group.push(monitorWidget); group.push(monitorWidget);
@ -175,6 +256,20 @@ class GenericMonitorDBUS {
} }
if (monitorWidget.widget) if (monitorWidget.widget)
this.box.insert_child_above(monitorWidget.widget, lastWidget); 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 { } else {
let prevWidget = monitorWidget.widget; let prevWidget = monitorWidget.widget;
let prevIcon = monitorWidget.icon; let prevIcon = monitorWidget.icon;
@ -201,6 +296,16 @@ class GenericMonitorDBUS {
this.box.remove_child(item.icon); 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) { deleteItems(str) {
let parameters = JSON.parse(str); let parameters = JSON.parse(str);
@ -219,10 +324,7 @@ class GenericMonitorDBUS {
let group = this.monitor_groups[groupName]; let group = this.monitor_groups[groupName];
let item = this._getItemFromGroup(group, itemName); let item = this._getItemFromGroup(group, itemName);
if (item !== null) { if (item !== null) {
this._removeItemFromBox(item); this.deleteItem(item, groupName);
delete group[item['name']];
if (group.length === 0)
delete this.monitor_groups[groupName];
} }
} }
} }

View File

@ -1,8 +1,8 @@
{ {
"uuid": "generic-monitor@gnome-shell-extensions", "uuid": "generic-monitor@gnome-shell-extensions",
"name": "Generic Monitor", "name": "Generic Monitor",
"description": "Generic monitor using DBUS", "description": "Display text & icon on systray using DBUS",
"version": "1", "version": "2",
"shell-version": [ "shell-version": [
"3.34" "3.34"
], ],