12 Commits
v4 ... v12

5 changed files with 121 additions and 70 deletions

View File

@@ -7,6 +7,10 @@ This GNOME Shell Extension aims to display information to center box. Using DBUS
Installation
------------
Install it from https://extensions.gnome.org/extension/2826/generic-monitor/
OR
Create a symbolic link from your _.local_ directory and enable extension
ln -s $PWD/generic-monitor@gnome-shell-extensions/ ~/.local/share/gnome-shell/extensions/
@@ -109,11 +113,11 @@ Signals can be :
Targets :
* signal : emit a signal to desktop application
* delete : Delete item
* open-popup : Open the popup if there is one
* close-popup : Close the popup if there is one
* toggle-popup : Toggle (open/close) the popup if there is one
* signal : Emit a signal to desktop application
* delete : Delete item
* open-popup : Open the popup if there is one
* close-popup : Close the popup if there is one
* toggle-popup : Toggle (open/close) the popup if there is one
Signal names emit when action "signal" is specified :
@@ -142,11 +146,11 @@ Example
You can test it with command line :
gdbus call --session --dest org.gnome.Shell --object-path /com/soutade/GenericMonitor --method com.soutade.GenericMonitor.notify '{"group":"new","items":[{"name":"first","on-click":"toggle-popup","text":{"text":"Hello","style":"color:green"},"popup":{"items":[{"picture":{"path":"/tmp/cat2.jpg"}}]}}]}'
gdbus call --session --dest org.gnome.Shell --object-path /com/soutade/GenericMonitor --method com.soutade.GenericMonitor.notify '{"group":"new","items":[{"name":"first","on-click":"toggle-popup","text":{"text":"Hello","style":"color:green"},"popup":{"items":[{"picture":{"path":"/tmp/cat.jpg"}}]}}]}'
gdbus call --session --dest org.gnome.Shell --object-path /com/soutade/GenericMonitor --method com.soutade.GenericMonitor.deleteGroups '{"groups":["new"]}'
Python examples is available
Python examples are available @ https://indefero.soutade.fr/p/genericmonitor/source/tree/master/examples
Development

View File

@@ -1,47 +1,47 @@
<interface name="com.soutade.GenericMonitor">
<!-- Functions -->
<method name="notify">
<arg type="s" direction="in" />
<arg name="parameters" type="s" direction="in" />
</method>
<method name="deleteItems">
<arg type="s" direction="in" />
<arg name="items" type="s" direction="in" />
</method>
<method name="deleteGroups">
<arg type="s" direction="in" />
<arg name="groups" type="s" direction="in" />
</method>
<method name="openPopup">
<arg type="s" direction="in" />
<arg name="popup" type="s" direction="in" />
</method>
<method name="closePopup">
<arg type="s" direction="in" />
<arg name="popup" type="s" direction="in" />
</method>
<method name="togglePopup">
<arg type="s" direction="in" />
<arg name="popup" type="s" direction="in" />
</method>
<!-- Events -->
<signal name="onClick">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<signal name="onRightClick">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<signal name="onDblClick">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<signal name="onRightDblClick">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<signal name="onScrollUp">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<signal name="onScrollDown">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<signal name="onEnter">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<signal name="onLeave">
<arg type="s" direction="out" />
<arg name="fullName" type="s" direction="out" />
</signal>
<!-- Activate/Deactivate signals -->
<signal name="onActivate">

View File

@@ -56,7 +56,7 @@ class PicturePopup(GenericMonitor):
popup = GenericMonitorPopup([url_widget, picture_widget])
signals = {
'on-click':'toggle-popup',
# Could also use this behavior
# Could also use this behavior [bugged since GNOME 42]
# 'on-enter':'open-popup',
# 'on-leave':'close-popup',
'on-dblclick':'signal',

View File

@@ -24,14 +24,13 @@
https://github.com/bananenfisch/RecentItems/blob/master/extension.js
https://github.com/julio641742/gnome-shell-extension-reference/blob/master/tutorials/POPUPMENU-EXTENSION.md
https://gjs-docs.gnome.org/st10~1.0_api/st.widget
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/panelMenu.js
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/popupMenu.js
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/master/js/ui/panel.js
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/panelMenu.js
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/popupMenu.js
https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/panel.js
*/
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;
@@ -57,14 +56,17 @@ function log(message) {
class SignalMgt {
constructor(item, name, group, dbus, menu) {
constructor(item, name, group, dbus, buttonMenu) {
this.name = name;
this.group = group;
this.fullname = this.name + '@' + this.group;
this.dbus = dbus;
this.menu = menu;
this.signals = {}
this.buttonMenu = buttonMenu;
this.signals = new WeakMap();
this.widgets = new Array();
this.timeouts = new Array();
this.menuOpen = false;
this.nbClicks = 0;
this.button = -1;
@@ -78,8 +80,10 @@ class SignalMgt {
}
destructor() {
for(let widgetIdx in this.signals)
this.disconnectWidgetSignals(this.signals[widgetIdx]);
for(let widgetIdx in this.widgets)
this.disconnectWidgetSignals(this.widgets[widgetIdx]);
for(let timeoutIdx in this.timeouts)
GLib.Source.remove(this.timeouts[timeoutIdx]);
}
updateSignals(item) {
@@ -93,44 +97,64 @@ class SignalMgt {
}
connectWidgetSignals(widget) {
this.signals[widget] = [];
this.widgets.push(widget);
let array = new Array();
this.signals.set(widget, array);
let id;
id = widget.connect('enter-event', this._onEnter.bind(this));
this.signals[widget].push(id);
array.push(id);
id = widget.connect('leave-event', this._onLeave.bind(this));
this.signals[widget].push(id);
array.push(id);
id = widget.connect('scroll-event', this._onScroll.bind(this));
this.signals[widget].push(id);
array.push(id);
widget.set_reactive(true);
id = widget.connect('button-release-event', Lang.bind(this, this._clicked));
this.signals[widget].push(id);
id = widget.connect('button-release-event', this._clicked.bind(this));
array.push(id);
}
disconnectWidgetSignals(widget) {
for(let idx in this.signals[widget])
widget.disconnect(this.signals[widget][idx]);
this.signals[widget] = null;
let array = this.signals.get(widget);
for(let idx in array)
widget.disconnect(array[idx]);
this.signals.set(widget, null);
}
toggleMenu() {
if (this.menuOpen)
{
this.buttonMenu.menu.close();
this.menuOpen = false;
}
else
{
this.buttonMenu.menu.open(true);
this.menuOpen = true;
}
}
_manageEventAction(action, signalName) {
if (action === 'open-popup')
this.menu.open(true);
{
this.buttonMenu.menu.open(true);
this.menuOpen = true;
}
else if (action === 'close-popup')
this.menu.close();
{
this.buttonMenu.menu.close();
this.menuOpen = false;
}
else if (action === 'toggle-popup')
this.menu.toggle();
else if (action == 'delete')
{
this.toggleMenu();
}
else if (action === 'delete')
this.dbus.deleteItem(this, this.group);
else if (action === 'signal')
this.dbus.emitSignal(signalName, this.fullname);
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_STOP;
}
_manageLeaveEvent() {
this._manageEventAction(this.onLeave);
}
_doClickCallback() {
let right = '';
let nbClicks = '';
@@ -165,8 +189,9 @@ class SignalMgt {
this.button = event.get_button();
this.nbClicks = 1;
Mainloop.timeout_add(this.dbus.ClutterSettings['double-click-time'],
Lang.bind(this, this._doClickCallback));
let sourceId = Mainloop.timeout_add(this.dbus.ClutterSettings['double-click-time'],
this._doClickCallback.bind(this));
this.timeouts.push(sourceId);
}
return Clutter.EVENT_PROPAGATE;
@@ -222,8 +247,10 @@ class MonitorWidget extends PanelMenu.Button {
this.group = group;
this.fullname = this.name + '@' + this.group;
this.dbus = dbus;
this.signals = new SignalMgt(item, this.name, group, dbus, this.menu);
this.popup_signals = {};
this.menuItem = null;
this.signalManager = new SignalMgt(item, this.name, group, dbus, this);
this.popup_signals = null;
this.popup_widgets = null;
if (item.hasOwnProperty('icon'))
{
@@ -232,7 +259,7 @@ class MonitorWidget extends PanelMenu.Button {
else
this.icon = this._createIcon(item['icon']);
if (this.icon !== null) {
this.signals.connectWidgetSignals(this.icon);
this.signalManager.connectWidgetSignals(this.icon);
this.add_child(this.icon);
}
} else
@@ -246,7 +273,7 @@ class MonitorWidget extends PanelMenu.Button {
this.widget = this._createText(item['text']);
if (this.widget !== null) {
this.signals.connectWidgetSignals(this.widget);
this.signalManager.connectWidgetSignals(this.widget);
this.add_child(this.widget);
}
} else
@@ -320,7 +347,7 @@ class MonitorWidget extends PanelMenu.Button {
}
if (prevIcon) {
this.signals.disconnectWidgetSignals(prevIcon);
this.signalManager.disconnectWidgetSignals(prevIcon);
this.insert_child_above(this.icon, prevIcon);
this.remove_child(prevIcon);
//delete prevIcon;
@@ -338,8 +365,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]);
for(let widgetIdx in this.popup_widgets)
this.signalManager.disconnectWidgetSignals(this.popup_widgets[widgetIdx]);
this.menu.removeAll();
//delete this.menuItem;
}
@@ -349,7 +376,7 @@ class MonitorWidget extends PanelMenu.Button {
this.menu.open(true);
}
this.signals.updateSignals(item);
this.signalManager.updateSignals(item);
}
openPopup() {
@@ -381,6 +408,8 @@ class MonitorWidget extends PanelMenu.Button {
}
let widgets = [];
this.popup_signals = new WeakMap();
this.popup_widgets = new Array();
for (let itemIndex in item['items']) {
let widget = null;
let widgetDict = item['items'][itemIndex];
@@ -388,7 +417,7 @@ class MonitorWidget extends PanelMenu.Button {
let nestedItem = null;
if (widgetDict.hasOwnProperty('text')) {
nestedItem = widgetDict['text'];
widget = this._createText(nestedItem);
widget = this._createLabel(nestedItem);
} else if (widgetDict.hasOwnProperty('picture')) {
nestedItem = widgetDict['picture'];
widget = this._createPicture(nestedItem);
@@ -404,8 +433,9 @@ class MonitorWidget extends PanelMenu.Button {
const name = hashGet(nestedItem, 'name', '');
this.popup_signals[widget] = new SignalMgt(nestedItem, name,
this.fullname, this.dbus,
this.menu);
this);
this.popup_signals[widget].connectWidgetSignals(widget);
this.popup_widgets.push(widget);
}
if (widgets.length > 0) {
@@ -426,7 +456,7 @@ class MonitorWidget extends PanelMenu.Button {
return this._createText(itemValues);
}
_createText(item) {
__createText(item, isLabel) {
if (!item.hasOwnProperty('text')) {
log('Text must have a \'text\' value');
return null;
@@ -439,13 +469,25 @@ class MonitorWidget extends PanelMenu.Button {
if (item['text'] === '') {
return null;
} else {
const widget = new St.Button({ label: item['text'] });
let widget = null;
if (isLabel)
widget = new St.Label({ text: item['text'] });
else
widget = new St.Button({ label: item['text'] });
widget.set_style(style);
return widget;
}
}
_createText(item) {
return this.__createText(item, false);
}
_createLabel(item) {
return this.__createText(item, true);
}
_createIconOld(item) {
var itemValues = {};
itemValues = { 'path':item['icon'] };
@@ -768,15 +810,19 @@ class Extension {
}
}
const extension = new Extension();
let extension = null;
function init() {
}
function enable() {
extension = new Extension();
extension.enable();
}
function disable() {
extension.disable();
if (extension) {
extension.disable();
extension = null;
}
}

View File

@@ -2,11 +2,12 @@
"uuid": "generic-monitor@gnome-shell-extensions",
"name": "Generic Monitor",
"description": "Display text & icon on systray using DBUS",
"version": "4",
"version": "12",
"shell-version": [
"3.38",
"3.36",
"3.34"
"43",
"42.3",
"42",
"41"
],
"url": "http://indefero.soutade.fr/p/genericmonitor"
}