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",
// 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
-------

View File

@ -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>

View File

@ -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);
}
}
}

View File

@ -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"
],