Blame SOURCES/resurrect-system-monitor.patch

7d7a48
From 7c3b0af4fde0b542089f2b0c84250404eef0ecca Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 17 May 2017 19:13:50 +0200
7d7a48
Subject: [PATCH 1/5] extensions: Resurrect systemMonitor extension
7d7a48
7d7a48
The extension was removed upstream because:
7d7a48
 - it hooks into the message tray that was removed
7d7a48
 - it was known to have performance issues
7d7a48
 - there are plenty of alternatives
7d7a48
7d7a48
Those aren't good enough reasons for dropping it downstream
7d7a48
as well though, so we need to bring it back ...
7d7a48
7d7a48
This reverts commit c9a6421f362cd156cf731289eadc11f44f6970ac.
7d7a48
---
7d7a48
 extensions/systemMonitor/extension.js     | 376 ++++++++++++++++++++++
7d7a48
 extensions/systemMonitor/meson.build      |   5 +
7d7a48
 extensions/systemMonitor/metadata.json.in |  11 +
7d7a48
 extensions/systemMonitor/stylesheet.css   |  35 ++
7d7a48
 meson.build                               |   1 +
7d7a48
 5 files changed, 428 insertions(+)
7d7a48
 create mode 100644 extensions/systemMonitor/extension.js
7d7a48
 create mode 100644 extensions/systemMonitor/meson.build
7d7a48
 create mode 100644 extensions/systemMonitor/metadata.json.in
7d7a48
 create mode 100644 extensions/systemMonitor/stylesheet.css
7d7a48
7d7a48
diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js
7d7a48
new file mode 100644
7d7a48
index 0000000..7b09df0
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/systemMonitor/extension.js
7d7a48
@@ -0,0 +1,376 @@
7d7a48
+/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
7d7a48
+
7d7a48
+const Clutter = imports.gi.Clutter;
7d7a48
+const GTop = imports.gi.GTop;
7d7a48
+const Lang = imports.lang;
7d7a48
+const Mainloop = imports.mainloop;
7d7a48
+const St = imports.gi.St;
7d7a48
+const Shell = imports.gi.Shell;
7d7a48
+
7d7a48
+const Main = imports.ui.main;
7d7a48
+const Tweener = imports.ui.tweener;
7d7a48
+
7d7a48
+const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
+const _ = Gettext.gettext;
7d7a48
+
7d7a48
+const ExtensionUtils = imports.misc.extensionUtils;
7d7a48
+const Me = ExtensionUtils.getCurrentExtension();
7d7a48
+const Convenience = Me.imports.convenience;
7d7a48
+
7d7a48
+const INDICATOR_UPDATE_INTERVAL = 500;
7d7a48
+const INDICATOR_NUM_GRID_LINES = 3;
7d7a48
+
7d7a48
+const ITEM_LABEL_SHOW_TIME = 0.15;
7d7a48
+const ITEM_LABEL_HIDE_TIME = 0.1;
7d7a48
+const ITEM_HOVER_TIMEOUT = 300;
7d7a48
+
7d7a48
+const Indicator = new Lang.Class({
7d7a48
+    Name: 'SystemMonitor.Indicator',
7d7a48
+
7d7a48
+    _init: function() {
7d7a48
+        this._initValues();
7d7a48
+        this.drawing_area = new St.DrawingArea({ reactive: true });
7d7a48
+        this.drawing_area.connect('repaint', Lang.bind(this, this._draw));
7d7a48
+        this.drawing_area.connect('button-press-event', function() {
7d7a48
+            let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop');
7d7a48
+            app.open_new_window(-1);
7d7a48
+            return true;
7d7a48
+        });
7d7a48
+
7d7a48
+        this.actor = new St.Bin({ style_class: "extension-systemMonitor-indicator-area",
7d7a48
+                                  reactive: true, track_hover: true,
7d7a48
+				  x_fill: true, y_fill: true });
7d7a48
+        this.actor.add_actor(this.drawing_area);
7d7a48
+
7d7a48
+        this._timeout = Mainloop.timeout_add(INDICATOR_UPDATE_INTERVAL, Lang.bind(this, function () {
7d7a48
+            this._updateValues();
7d7a48
+            this.drawing_area.queue_repaint();
7d7a48
+            return true;
7d7a48
+        }));
7d7a48
+    },
7d7a48
+
7d7a48
+    showLabel: function() {
7d7a48
+        if (this.label == null)
7d7a48
+            return;
7d7a48
+
7d7a48
+        this.label.opacity = 0;
7d7a48
+        this.label.show();
7d7a48
+
7d7a48
+        let [stageX, stageY] = this.actor.get_transformed_position();
7d7a48
+
7d7a48
+	let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
7d7a48
+        let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
7d7a48
+
7d7a48
+	let labelWidth = this.label.width;
7d7a48
+        let labelHeight = this.label.height;
7d7a48
+        let xOffset = Math.floor((itemWidth - labelWidth) / 2)
7d7a48
+
7d7a48
+        let x = stageX + xOffset;
7d7a48
+
7d7a48
+        let node = this.label.get_theme_node();
7d7a48
+        let yOffset = node.get_length('-y-offset');
7d7a48
+
7d7a48
+        let y = stageY - this.label.get_height() - yOffset;
7d7a48
+
7d7a48
+        this.label.set_position(x, y);
7d7a48
+        Tweener.addTween(this.label,
7d7a48
+                         { opacity: 255,
7d7a48
+                           time: ITEM_LABEL_SHOW_TIME,
7d7a48
+                           transition: 'easeOutQuad',
7d7a48
+                         });
7d7a48
+    },
7d7a48
+
7d7a48
+    setLabelText: function(text) {
7d7a48
+        if (this.label == null)
7d7a48
+            this.label = new St.Label({ style_class: 'extension-systemMonitor-indicator-label'});
7d7a48
+
7d7a48
+        this.label.set_text(text);
7d7a48
+        Main.layoutManager.addChrome(this.label);
7d7a48
+        this.label.hide();
7d7a48
+    },
7d7a48
+
7d7a48
+    hideLabel: function () {
7d7a48
+        Tweener.addTween(this.label,
7d7a48
+                         { opacity: 0,
7d7a48
+                           time: ITEM_LABEL_HIDE_TIME,
7d7a48
+                           transition: 'easeOutQuad',
7d7a48
+                           onComplete: Lang.bind(this, function() {
7d7a48
+                               this.label.hide();
7d7a48
+                           })
7d7a48
+                         });
7d7a48
+    },
7d7a48
+
7d7a48
+    destroy: function() {
7d7a48
+        Mainloop.source_remove(this._timeout);
7d7a48
+
7d7a48
+        this.actor.destroy();
7d7a48
+	if (this.label)
7d7a48
+	    this.label.destroy();
7d7a48
+    },
7d7a48
+
7d7a48
+    _initValues: function() {
7d7a48
+    },
7d7a48
+
7d7a48
+    _updateValues: function() {
7d7a48
+    },
7d7a48
+
7d7a48
+    _draw: function(area) {
7d7a48
+        let [width, height] = area.get_surface_size();
7d7a48
+        let themeNode = this.actor.get_theme_node();
7d7a48
+        let cr = area.get_context();
7d7a48
+
7d7a48
+        //draw the background grid
7d7a48
+        let color = themeNode.get_color(this.gridColor);
7d7a48
+        let gridOffset = Math.floor(height / (INDICATOR_NUM_GRID_LINES + 1));
7d7a48
+        for (let i = 1; i <= INDICATOR_NUM_GRID_LINES; ++i) {
7d7a48
+                cr.moveTo(0, i * gridOffset + .5);
7d7a48
+                cr.lineTo(width, i * gridOffset + .5);
7d7a48
+        }
7d7a48
+        Clutter.cairo_set_source_color(cr, color);
7d7a48
+        cr.setLineWidth(1);
7d7a48
+        cr.setDash([4,1], 0);
7d7a48
+        cr.stroke();
7d7a48
+
7d7a48
+        //draw the foreground
7d7a48
+
7d7a48
+        function makePath(values, reverse, nudge) {
7d7a48
+            if (nudge == null) {
7d7a48
+                nudge = 0;
7d7a48
+            }
7d7a48
+            //if we are going in reverse, we are completing the bottom of a chart, so use lineTo
7d7a48
+            if (reverse) {
7d7a48
+                cr.lineTo(values.length - 1, (1 - values[values.length - 1]) * height + nudge);
7d7a48
+                for (let k = values.length - 2; k >= 0; --k) {
7d7a48
+                    cr.lineTo(k, (1 - values[k]) * height + nudge);
7d7a48
+                }
7d7a48
+            } else {
7d7a48
+                cr.moveTo(0, (1 - values[0]) * height + nudge);
7d7a48
+                for (let k = 1; k < values.length; ++k) {
7d7a48
+                    cr.lineTo(k, (1 - values[k]) * height + nudge);
7d7a48
+                }
7d7a48
+
7d7a48
+            }
7d7a48
+        }
7d7a48
+
7d7a48
+        let renderStats = this.renderStats;
7d7a48
+
7d7a48
+        // Make sure we don't have more sample points than pixels
7d7a48
+        renderStats.map(Lang.bind(this, function(k){
7d7a48
+            let stat = this.stats[k];
7d7a48
+            if (stat.values.length > width) {
7d7a48
+                stat.values = stat.values.slice(stat.values.length - width, stat.values.length);
7d7a48
+            }
7d7a48
+        }));
7d7a48
+
7d7a48
+        for (let i = 0; i < renderStats.length; ++i) {
7d7a48
+            let stat = this.stats[renderStats[i]];
7d7a48
+            // We outline at full opacity and fill with 40% opacity
7d7a48
+            let outlineColor = themeNode.get_color(stat.color);
7d7a48
+            let color = new Clutter.Color(outlineColor);
7d7a48
+            color.alpha = color.alpha * .4;
7d7a48
+
7d7a48
+            // Render the background between us and the next level
7d7a48
+            makePath(stat.values, false);
7d7a48
+            // If there is a process below us, render the cpu between us and it, otherwise,
7d7a48
+            // render to the bottom of the chart
7d7a48
+            if (i == renderStats.length - 1) {
7d7a48
+                cr.lineTo(stat.values.length - 1, height);
7d7a48
+                cr.lineTo(0, height);
7d7a48
+                cr.closePath();
7d7a48
+            } else {
7d7a48
+                let nextStat = this.stats[renderStats[i+1]];
7d7a48
+                makePath(nextStat.values, true);
7d7a48
+            }
7d7a48
+            cr.closePath()
7d7a48
+            Clutter.cairo_set_source_color(cr, color);
7d7a48
+            cr.fill();
7d7a48
+
7d7a48
+            // Render the outline of this level
7d7a48
+            makePath(stat.values, false, .5);
7d7a48
+            Clutter.cairo_set_source_color(cr, outlineColor);
7d7a48
+            cr.setLineWidth(1.0);
7d7a48
+            cr.setDash([], 0);
7d7a48
+            cr.stroke();
7d7a48
+        }
7d7a48
+    }
7d7a48
+});
7d7a48
+
7d7a48
+const CpuIndicator = new Lang.Class({
7d7a48
+    Name: 'SystemMonitor.CpuIndicator',
7d7a48
+    Extends: Indicator,
7d7a48
+
7d7a48
+    _init: function() {
7d7a48
+        this.parent();
7d7a48
+
7d7a48
+        this.gridColor = '-grid-color';
7d7a48
+        this.renderStats = [ 'cpu-user', 'cpu-sys', 'cpu-iowait' ];
7d7a48
+
7d7a48
+        // Make sure renderStats is sorted as necessary for rendering
7d7a48
+        let renderStatOrder = {'cpu-total': 0, 'cpu-user': 1, 'cpu-sys': 2, 'cpu-iowait': 3};
7d7a48
+        this.renderStats = this.renderStats.sort(function(a,b) {
7d7a48
+            return renderStatOrder[a] - renderStatOrder[b];
7d7a48
+        });
7d7a48
+
7d7a48
+	this.setLabelText(_("CPU"));
7d7a48
+    },
7d7a48
+
7d7a48
+    _initValues: function() {
7d7a48
+        this._prev = new GTop.glibtop_cpu;
7d7a48
+        GTop.glibtop_get_cpu(this._prev);
7d7a48
+
7d7a48
+        this.stats = {
7d7a48
+                       'cpu-user': {color: '-cpu-user-color', values: []},
7d7a48
+                       'cpu-sys': {color: '-cpu-sys-color', values: []},
7d7a48
+                       'cpu-iowait': {color: '-cpu-iowait-color', values: []},
7d7a48
+                       'cpu-total': {color: '-cpu-total-color', values: []}
7d7a48
+                     };
7d7a48
+    },
7d7a48
+
7d7a48
+    _updateValues: function() {
7d7a48
+        let cpu = new GTop.glibtop_cpu;
7d7a48
+        let t = 0.0;
7d7a48
+        GTop.glibtop_get_cpu(cpu);
7d7a48
+        let total = cpu.total - this._prev.total;
7d7a48
+        let user = cpu.user - this._prev.user;
7d7a48
+        let sys = cpu.sys - this._prev.sys;
7d7a48
+        let iowait = cpu.iowait - this._prev.iowait;
7d7a48
+        let idle = cpu.idle - this._prev.idle;
7d7a48
+
7d7a48
+        t += iowait / total;
7d7a48
+        this.stats['cpu-iowait'].values.push(t);
7d7a48
+        t += sys / total;
7d7a48
+        this.stats['cpu-sys'].values.push(t);
7d7a48
+        t += user / total;
7d7a48
+        this.stats['cpu-user'].values.push(t);
7d7a48
+        this.stats['cpu-total'].values.push(1 - idle / total);
7d7a48
+
7d7a48
+        this._prev = cpu;
7d7a48
+    }
7d7a48
+});
7d7a48
+
7d7a48
+const MemoryIndicator = new Lang.Class({
7d7a48
+    Name: 'SystemMonitor.MemoryIndicator',
7d7a48
+    Extends: Indicator,
7d7a48
+
7d7a48
+    _init: function() {
7d7a48
+        this.parent();
7d7a48
+
7d7a48
+        this.gridColor = '-grid-color';
7d7a48
+        this.renderStats = [ 'mem-user', 'mem-other', 'mem-cached' ];
7d7a48
+
7d7a48
+        // Make sure renderStats is sorted as necessary for rendering
7d7a48
+        let renderStatOrder = { 'mem-cached': 0, 'mem-other': 1, 'mem-user': 2 };
7d7a48
+        this.renderStats = this.renderStats.sort(function(a,b) {
7d7a48
+            return renderStatOrder[a] - renderStatOrder[b];
7d7a48
+        });
7d7a48
+
7d7a48
+	this.setLabelText(_("Memory"));
7d7a48
+    },
7d7a48
+
7d7a48
+    _initValues: function() {
7d7a48
+        this.mem = new GTop.glibtop_mem;
7d7a48
+        this.stats = {
7d7a48
+                        'mem-user': { color: "-mem-user-color", values: [] },
7d7a48
+                        'mem-other': { color: "-mem-other-color", values: [] },
7d7a48
+                        'mem-cached': { color: "-mem-cached-color", values: [] }
7d7a48
+                     };
7d7a48
+    },
7d7a48
+
7d7a48
+    _updateValues: function() {
7d7a48
+        GTop.glibtop_get_mem(this.mem);
7d7a48
+
7d7a48
+        let t = this.mem.user / this.mem.total;
7d7a48
+        this.stats['mem-user'].values.push(t);
7d7a48
+        t += (this.mem.used - this.mem.user - this.mem.cached) / this.mem.total;
7d7a48
+        this.stats['mem-other'].values.push(t);
7d7a48
+        t += this.mem.cached / this.mem.total;
7d7a48
+        this.stats['mem-cached'].values.push(t);
7d7a48
+    }
7d7a48
+});
7d7a48
+
7d7a48
+const INDICATORS = [CpuIndicator, MemoryIndicator];
7d7a48
+
7d7a48
+const Extension = new Lang.Class({
7d7a48
+    Name: 'SystemMonitor.Extension',
7d7a48
+
7d7a48
+    _init: function() {
7d7a48
+	Convenience.initTranslations();
7d7a48
+
7d7a48
+	this._showLabelTimeoutId = 0;
7d7a48
+	this._resetHoverTimeoutId = 0;
7d7a48
+	this._labelShowing = false;
7d7a48
+    },
7d7a48
+
7d7a48
+    enable: function() {
7d7a48
+	this._box = new St.BoxLayout({ style_class: 'extension-systemMonitor-container',
7d7a48
+				       x_align: Clutter.ActorAlign.START,
7d7a48
+				       x_expand: true });
7d7a48
+	this._indicators = [ ];
7d7a48
+
7d7a48
+	for (let i = 0; i < INDICATORS.length; i++) {
7d7a48
+	    let indicator = new (INDICATORS[i])();
7d7a48
+
7d7a48
+            indicator.actor.connect('notify::hover', Lang.bind(this, function() {
7d7a48
+		this._onHover(indicator);
7d7a48
+	    }));
7d7a48
+	    this._box.add_actor(indicator.actor);
7d7a48
+	    this._indicators.push(indicator);
7d7a48
+	}
7d7a48
+
7d7a48
+	this._boxHolder = new St.BoxLayout({ x_expand: true,
7d7a48
+					     y_expand: true,
7d7a48
+					     x_align: Clutter.ActorAlign.START,
7d7a48
+					   });
7d7a48
+	let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
+	Main.messageTray.actor.remove_child(menuButton);
7d7a48
+	Main.messageTray.actor.add_child(this._boxHolder);
7d7a48
+
7d7a48
+	this._boxHolder.add_child(this._box);
7d7a48
+	this._boxHolder.add_child(menuButton);
7d7a48
+    },
7d7a48
+
7d7a48
+    disable: function() {
7d7a48
+	this._indicators.forEach(function(i) { i.destroy(); });
7d7a48
+
7d7a48
+	let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
+	this._boxHolder.remove_child(menuButton);
7d7a48
+	Main.messageTray.actor.add_child(menuButton);
7d7a48
+
7d7a48
+	this._box.destroy();
7d7a48
+	this._boxHolder.destroy();
7d7a48
+    },
7d7a48
+
7d7a48
+    _onHover: function (item) {
7d7a48
+        if (item.actor.get_hover()) {
7d7a48
+            if (this._showLabelTimeoutId == 0) {
7d7a48
+                let timeout = this._labelShowing ? 0 : ITEM_HOVER_TIMEOUT;
7d7a48
+                this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
7d7a48
+                    Lang.bind(this, function() {
7d7a48
+                        this._labelShowing = true;
7d7a48
+                        item.showLabel();
7d7a48
+                        return false;
7d7a48
+                    }));
7d7a48
+                if (this._resetHoverTimeoutId > 0) {
7d7a48
+                    Mainloop.source_remove(this._resetHoverTimeoutId);
7d7a48
+                    this._resetHoverTimeoutId = 0;
7d7a48
+                }
7d7a48
+            }
7d7a48
+        } else {
7d7a48
+            if (this._showLabelTimeoutId > 0)
7d7a48
+                Mainloop.source_remove(this._showLabelTimeoutId);
7d7a48
+            this._showLabelTimeoutId = 0;
7d7a48
+            item.hideLabel();
7d7a48
+            if (this._labelShowing) {
7d7a48
+                this._resetHoverTimeoutId = Mainloop.timeout_add(ITEM_HOVER_TIMEOUT,
7d7a48
+                    Lang.bind(this, function() {
7d7a48
+                        this._labelShowing = false;
7d7a48
+                        return false;
7d7a48
+                    }));
7d7a48
+            }
7d7a48
+        }
7d7a48
+    },
7d7a48
+});
7d7a48
+
7d7a48
+function init() {
7d7a48
+    return new Extension();
7d7a48
+}
7d7a48
diff --git a/extensions/systemMonitor/meson.build b/extensions/systemMonitor/meson.build
7d7a48
new file mode 100644
7d7a48
index 0000000..48504f6
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/systemMonitor/meson.build
7d7a48
@@ -0,0 +1,5 @@
7d7a48
+extension_data += configure_file(
7d7a48
+  input: metadata_name + '.in',
7d7a48
+  output: metadata_name,
7d7a48
+  configuration: metadata_conf
7d7a48
+)
7d7a48
diff --git a/extensions/systemMonitor/metadata.json.in b/extensions/systemMonitor/metadata.json.in
7d7a48
new file mode 100644
7d7a48
index 0000000..fa75007
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/systemMonitor/metadata.json.in
7d7a48
@@ -0,0 +1,11 @@
7d7a48
+{
7d7a48
+    "shell-version": ["@shell_current@" ],
7d7a48
+    "uuid": "@uuid@",
7d7a48
+    "extension-id": "@extension_id@",
7d7a48
+    "settings-schema": "@gschemaname@",
7d7a48
+    "gettext-domain": "@gettext_domain@",
7d7a48
+    "original-author": "zaspire@rambler.ru",
7d7a48
+    "name": "SystemMonitor",
7d7a48
+    "description": "System monitor showing CPU and memory usage in the message tray.",
7d7a48
+    "url": "@url@"
7d7a48
+}
7d7a48
diff --git a/extensions/systemMonitor/stylesheet.css b/extensions/systemMonitor/stylesheet.css
7d7a48
new file mode 100644
7d7a48
index 0000000..13f95ec
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/systemMonitor/stylesheet.css
7d7a48
@@ -0,0 +1,35 @@
7d7a48
+.extension-systemMonitor-container {
7d7a48
+    spacing: 5px;
7d7a48
+    padding-left: 5px;
7d7a48
+    padding-right: 5px;
7d7a48
+    padding-bottom: 10px;
7d7a48
+    padding-top: 10px;
7d7a48
+}
7d7a48
+
7d7a48
+.extension-systemMonitor-indicator-area {
7d7a48
+    border: 1px solid #8d8d8d;
7d7a48
+    border-radius: 3px;
7d7a48
+    width: 100px;
7d7a48
+    /* message tray is 72px, so 20px padding of the container,
7d7a48
+       2px of border, makes it 50px */
7d7a48
+    height: 50px;
7d7a48
+    -grid-color: #575757;
7d7a48
+    -cpu-total-color: rgb(0,154,62);
7d7a48
+    -cpu-user-color: rgb(69,154,0);
7d7a48
+    -cpu-sys-color: rgb(255,253,81);
7d7a48
+    -cpu-iowait-color: rgb(210,148,0);
7d7a48
+    -mem-user-color: rgb(210,148,0);
7d7a48
+    -mem-cached-color: rgb(90,90,90);
7d7a48
+    -mem-other-color: rgb(205,203,41);
7d7a48
+    background-color: #1e1e1e;
7d7a48
+}
7d7a48
+
7d7a48
+.extension-systemMonitor-indicator-label {
7d7a48
+    border-radius: 7px;
7d7a48
+    padding: 4px 12px;
7d7a48
+    background-color: rgba(0,0,0,0.9);
7d7a48
+    text-align: center;
7d7a48
+    -y-offset: 8px;
7d7a48
+    font-size: 9pt;
7d7a48
+    font-weight: bold;
7d7a48
+}
7d7a48
diff --git a/meson.build b/meson.build
7d7a48
index 6e8c41f..6764f9a 100644
7d7a48
--- a/meson.build
7d7a48
+++ b/meson.build
7d7a48
@@ -55,6 +55,7 @@ all_extensions += [
7d7a48
   'native-window-placement',
7d7a48
   'no-hot-corner',
7d7a48
   'panel-favorites',
7d7a48
+  'systemMonitor',
7d7a48
   'top-icons',
7d7a48
   'updates-dialog',
7d7a48
   'user-theme',
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From ddf4d70df56321366a2cb8b89689d59be4dbb718 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Fri, 17 May 2019 22:55:48 +0000
7d7a48
Subject: [PATCH 2/5] systemMonitor: Modernise code
7d7a48
7d7a48
 - port to ES6 classes
7d7a48
 - replace Lang.bind()
7d7a48
 - destructure imports
7d7a48
 - fix style issues (stray/missing spaces/semi-colons, indent, ...)
7d7a48
---
7d7a48
 extensions/systemMonitor/extension.js | 377 +++++++++++++-------------
7d7a48
 1 file changed, 192 insertions(+), 185 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js
7d7a48
index 7b09df0..89f8916 100644
7d7a48
--- a/extensions/systemMonitor/extension.js
7d7a48
+++ b/extensions/systemMonitor/extension.js
7d7a48
@@ -1,22 +1,16 @@
7d7a48
 /* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
7d7a48
 
7d7a48
-const Clutter = imports.gi.Clutter;
7d7a48
-const GTop = imports.gi.GTop;
7d7a48
-const Lang = imports.lang;
7d7a48
-const Mainloop = imports.mainloop;
7d7a48
-const St = imports.gi.St;
7d7a48
-const Shell = imports.gi.Shell;
7d7a48
+/* exported init */
7d7a48
 
7d7a48
+const { Clutter, GLib, GTop, Shell, St } = imports.gi;
7d7a48
+
7d7a48
+const ExtensionUtils = imports.misc.extensionUtils;
7d7a48
 const Main = imports.ui.main;
7d7a48
 const Tweener = imports.ui.tweener;
7d7a48
 
7d7a48
 const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
 const _ = Gettext.gettext;
7d7a48
 
7d7a48
-const ExtensionUtils = imports.misc.extensionUtils;
7d7a48
-const Me = ExtensionUtils.getCurrentExtension();
7d7a48
-const Convenience = Me.imports.convenience;
7d7a48
-
7d7a48
 const INDICATOR_UPDATE_INTERVAL = 500;
7d7a48
 const INDICATOR_NUM_GRID_LINES = 3;
7d7a48
 
7d7a48
@@ -24,32 +18,38 @@ const ITEM_LABEL_SHOW_TIME = 0.15;
7d7a48
 const ITEM_LABEL_HIDE_TIME = 0.1;
7d7a48
 const ITEM_HOVER_TIMEOUT = 300;
7d7a48
 
7d7a48
-const Indicator = new Lang.Class({
7d7a48
-    Name: 'SystemMonitor.Indicator',
7d7a48
-
7d7a48
-    _init: function() {
7d7a48
+const Indicator = class {
7d7a48
+    constructor() {
7d7a48
         this._initValues();
7d7a48
-        this.drawing_area = new St.DrawingArea({ reactive: true });
7d7a48
-        this.drawing_area.connect('repaint', Lang.bind(this, this._draw));
7d7a48
-        this.drawing_area.connect('button-press-event', function() {
7d7a48
+        this._drawingArea = new St.DrawingArea({ reactive: true });
7d7a48
+        this._drawingArea.connect('repaint', this._draw.bind(this));
7d7a48
+        this._drawingArea.connect('button-press-event', () => {
7d7a48
             let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop');
7d7a48
             app.open_new_window(-1);
7d7a48
             return true;
7d7a48
         });
7d7a48
 
7d7a48
-        this.actor = new St.Bin({ style_class: "extension-systemMonitor-indicator-area",
7d7a48
-                                  reactive: true, track_hover: true,
7d7a48
-				  x_fill: true, y_fill: true });
7d7a48
-        this.actor.add_actor(this.drawing_area);
7d7a48
+        this.actor = new St.Bin({
7d7a48
+            style_class: 'extension-systemMonitor-indicator-area',
7d7a48
+            reactive: true,
7d7a48
+            track_hover: true,
7d7a48
+            x_fill: true,
7d7a48
+            y_fill: true
7d7a48
+        });
7d7a48
+        this.actor.add_actor(this._drawingArea);
7d7a48
 
7d7a48
-        this._timeout = Mainloop.timeout_add(INDICATOR_UPDATE_INTERVAL, Lang.bind(this, function () {
7d7a48
-            this._updateValues();
7d7a48
-            this.drawing_area.queue_repaint();
7d7a48
-            return true;
7d7a48
-        }));
7d7a48
-    },
7d7a48
+        this.actor.connect('destroy', this._onDestroy.bind(this));
7d7a48
 
7d7a48
-    showLabel: function() {
7d7a48
+        this._timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
7d7a48
+            INDICATOR_UPDATE_INTERVAL,
7d7a48
+            () => {
7d7a48
+                this._updateValues();
7d7a48
+                this._drawingArea.queue_repaint();
7d7a48
+                return GLib.SOURCE_CONTINUE;
7d7a48
+            });
7d7a48
+    }
7d7a48
+
7d7a48
+    showLabel() {
7d7a48
         if (this.label == null)
7d7a48
             return;
7d7a48
 
7d7a48
@@ -58,12 +58,10 @@ const Indicator = new Lang.Class({
7d7a48
 
7d7a48
         let [stageX, stageY] = this.actor.get_transformed_position();
7d7a48
 
7d7a48
-	let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
7d7a48
-        let itemHeight = this.actor.allocation.y2 - this.actor.allocation.y1;
7d7a48
+        let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1;
7d7a48
 
7d7a48
-	let labelWidth = this.label.width;
7d7a48
-        let labelHeight = this.label.height;
7d7a48
-        let xOffset = Math.floor((itemWidth - labelWidth) / 2)
7d7a48
+        let labelWidth = this.label.width;
7d7a48
+        let xOffset = Math.floor((itemWidth - labelWidth) / 2);
7d7a48
 
7d7a48
         let x = stageX + xOffset;
7d7a48
 
7d7a48
@@ -73,48 +71,51 @@ const Indicator = new Lang.Class({
7d7a48
         let y = stageY - this.label.get_height() - yOffset;
7d7a48
 
7d7a48
         this.label.set_position(x, y);
7d7a48
-        Tweener.addTween(this.label,
7d7a48
-                         { opacity: 255,
7d7a48
-                           time: ITEM_LABEL_SHOW_TIME,
7d7a48
-                           transition: 'easeOutQuad',
7d7a48
-                         });
7d7a48
-    },
7d7a48
-
7d7a48
-    setLabelText: function(text) {
7d7a48
+        Tweener.addTween(this.label, {
7d7a48
+            opacity: 255,
7d7a48
+            time: ITEM_LABEL_SHOW_TIME,
7d7a48
+            transition: 'easeOutQuad',
7d7a48
+        });
7d7a48
+    }
7d7a48
+
7d7a48
+    setLabelText(text) {
7d7a48
         if (this.label == null)
7d7a48
-            this.label = new St.Label({ style_class: 'extension-systemMonitor-indicator-label'});
7d7a48
+            this.label = new St.Label({
7d7a48
+                style_class: 'extension-systemMonitor-indicator-label'
7d7a48
+            });
7d7a48
 
7d7a48
         this.label.set_text(text);
7d7a48
         Main.layoutManager.addChrome(this.label);
7d7a48
         this.label.hide();
7d7a48
-    },
7d7a48
-
7d7a48
-    hideLabel: function () {
7d7a48
-        Tweener.addTween(this.label,
7d7a48
-                         { opacity: 0,
7d7a48
-                           time: ITEM_LABEL_HIDE_TIME,
7d7a48
-                           transition: 'easeOutQuad',
7d7a48
-                           onComplete: Lang.bind(this, function() {
7d7a48
-                               this.label.hide();
7d7a48
-                           })
7d7a48
-                         });
7d7a48
-    },
7d7a48
-
7d7a48
-    destroy: function() {
7d7a48
-        Mainloop.source_remove(this._timeout);
7d7a48
+    }
7d7a48
 
7d7a48
+    hideLabel() {
7d7a48
+        Tweener.addTween(this.label, {
7d7a48
+            opacity: 0,
7d7a48
+            time: ITEM_LABEL_HIDE_TIME,
7d7a48
+            transition: 'easeOutQuad',
7d7a48
+            onComplete: () => this.label.hide()
7d7a48
+        });
7d7a48
+    }
7d7a48
+
7d7a48
+    destroy() {
7d7a48
         this.actor.destroy();
7d7a48
-	if (this.label)
7d7a48
-	    this.label.destroy();
7d7a48
-    },
7d7a48
+    }
7d7a48
+
7d7a48
+    _onDestroy() {
7d7a48
+        GLib.source_remove(this._timeout);
7d7a48
+
7d7a48
+        if (this.label)
7d7a48
+            this.label.destroy();
7d7a48
+    }
7d7a48
 
7d7a48
-    _initValues: function() {
7d7a48
-    },
7d7a48
+    _initValues() {
7d7a48
+    }
7d7a48
 
7d7a48
-    _updateValues: function() {
7d7a48
-    },
7d7a48
+    _updateValues() {
7d7a48
+    }
7d7a48
 
7d7a48
-    _draw: function(area) {
7d7a48
+    _draw(area) {
7d7a48
         let [width, height] = area.get_surface_size();
7d7a48
         let themeNode = this.actor.get_theme_node();
7d7a48
         let cr = area.get_context();
7d7a48
@@ -123,12 +124,12 @@ const Indicator = new Lang.Class({
7d7a48
         let color = themeNode.get_color(this.gridColor);
7d7a48
         let gridOffset = Math.floor(height / (INDICATOR_NUM_GRID_LINES + 1));
7d7a48
         for (let i = 1; i <= INDICATOR_NUM_GRID_LINES; ++i) {
7d7a48
-                cr.moveTo(0, i * gridOffset + .5);
7d7a48
-                cr.lineTo(width, i * gridOffset + .5);
7d7a48
+            cr.moveTo(0, i * gridOffset + .5);
7d7a48
+            cr.lineTo(width, i * gridOffset + .5);
7d7a48
         }
7d7a48
         Clutter.cairo_set_source_color(cr, color);
7d7a48
         cr.setLineWidth(1);
7d7a48
-        cr.setDash([4,1], 0);
7d7a48
+        cr.setDash([4, 1], 0);
7d7a48
         cr.stroke();
7d7a48
 
7d7a48
         //draw the foreground
7d7a48
@@ -155,12 +156,12 @@ const Indicator = new Lang.Class({
7d7a48
         let renderStats = this.renderStats;
7d7a48
 
7d7a48
         // Make sure we don't have more sample points than pixels
7d7a48
-        renderStats.map(Lang.bind(this, function(k){
7d7a48
+        renderStats.map(k => {
7d7a48
             let stat = this.stats[k];
7d7a48
             if (stat.values.length > width) {
7d7a48
                 stat.values = stat.values.slice(stat.values.length - width, stat.values.length);
7d7a48
             }
7d7a48
-        }));
7d7a48
+        });
7d7a48
 
7d7a48
         for (let i = 0; i < renderStats.length; ++i) {
7d7a48
             let stat = this.stats[renderStats[i]];
7d7a48
@@ -178,10 +179,10 @@ const Indicator = new Lang.Class({
7d7a48
                 cr.lineTo(0, height);
7d7a48
                 cr.closePath();
7d7a48
             } else {
7d7a48
-                let nextStat = this.stats[renderStats[i+1]];
7d7a48
+                let nextStat = this.stats[renderStats[i + 1]];
7d7a48
                 makePath(nextStat.values, true);
7d7a48
             }
7d7a48
-            cr.closePath()
7d7a48
+            cr.closePath();
7d7a48
             Clutter.cairo_set_source_color(cr, color);
7d7a48
             cr.fill();
7d7a48
 
7d7a48
@@ -193,40 +194,42 @@ const Indicator = new Lang.Class({
7d7a48
             cr.stroke();
7d7a48
         }
7d7a48
     }
7d7a48
-});
7d7a48
-
7d7a48
-const CpuIndicator = new Lang.Class({
7d7a48
-    Name: 'SystemMonitor.CpuIndicator',
7d7a48
-    Extends: Indicator,
7d7a48
+};
7d7a48
 
7d7a48
-    _init: function() {
7d7a48
-        this.parent();
7d7a48
+const CpuIndicator = class extends Indicator {
7d7a48
+    constructor() {
7d7a48
+        super();
7d7a48
 
7d7a48
         this.gridColor = '-grid-color';
7d7a48
-        this.renderStats = [ 'cpu-user', 'cpu-sys', 'cpu-iowait' ];
7d7a48
+        this.renderStats = ['cpu-user', 'cpu-sys', 'cpu-iowait'];
7d7a48
 
7d7a48
         // Make sure renderStats is sorted as necessary for rendering
7d7a48
-        let renderStatOrder = {'cpu-total': 0, 'cpu-user': 1, 'cpu-sys': 2, 'cpu-iowait': 3};
7d7a48
-        this.renderStats = this.renderStats.sort(function(a,b) {
7d7a48
+        let renderStatOrder = {
7d7a48
+            'cpu-total': 0,
7d7a48
+            'cpu-user': 1,
7d7a48
+            'cpu-sys': 2,
7d7a48
+            'cpu-iowait': 3
7d7a48
+        };
7d7a48
+        this.renderStats = this.renderStats.sort((a, b) => {
7d7a48
             return renderStatOrder[a] - renderStatOrder[b];
7d7a48
         });
7d7a48
 
7d7a48
-	this.setLabelText(_("CPU"));
7d7a48
-    },
7d7a48
+        this.setLabelText(_('CPU'));
7d7a48
+    }
7d7a48
 
7d7a48
-    _initValues: function() {
7d7a48
+    _initValues() {
7d7a48
         this._prev = new GTop.glibtop_cpu;
7d7a48
         GTop.glibtop_get_cpu(this._prev);
7d7a48
 
7d7a48
         this.stats = {
7d7a48
-                       'cpu-user': {color: '-cpu-user-color', values: []},
7d7a48
-                       'cpu-sys': {color: '-cpu-sys-color', values: []},
7d7a48
-                       'cpu-iowait': {color: '-cpu-iowait-color', values: []},
7d7a48
-                       'cpu-total': {color: '-cpu-total-color', values: []}
7d7a48
-                     };
7d7a48
-    },
7d7a48
-
7d7a48
-    _updateValues: function() {
7d7a48
+            'cpu-user': { color: '-cpu-user-color', values: [] },
7d7a48
+            'cpu-sys': { color: '-cpu-sys-color', values: [] },
7d7a48
+            'cpu-iowait': { color: '-cpu-iowait-color', values: [] },
7d7a48
+            'cpu-total': { color: '-cpu-total-color', values: [] }
7d7a48
+        };
7d7a48
+    }
7d7a48
+
7d7a48
+    _updateValues() {
7d7a48
         let cpu = new GTop.glibtop_cpu;
7d7a48
         let t = 0.0;
7d7a48
         GTop.glibtop_get_cpu(cpu);
7d7a48
@@ -246,37 +249,34 @@ const CpuIndicator = new Lang.Class({
7d7a48
 
7d7a48
         this._prev = cpu;
7d7a48
     }
7d7a48
-});
7d7a48
+};
7d7a48
 
7d7a48
-const MemoryIndicator = new Lang.Class({
7d7a48
-    Name: 'SystemMonitor.MemoryIndicator',
7d7a48
-    Extends: Indicator,
7d7a48
-
7d7a48
-    _init: function() {
7d7a48
-        this.parent();
7d7a48
+const MemoryIndicator = class extends Indicator {
7d7a48
+    constructor() {
7d7a48
+        super();
7d7a48
 
7d7a48
         this.gridColor = '-grid-color';
7d7a48
-        this.renderStats = [ 'mem-user', 'mem-other', 'mem-cached' ];
7d7a48
+        this.renderStats = ['mem-user', 'mem-other', 'mem-cached'];
7d7a48
 
7d7a48
         // Make sure renderStats is sorted as necessary for rendering
7d7a48
         let renderStatOrder = { 'mem-cached': 0, 'mem-other': 1, 'mem-user': 2 };
7d7a48
-        this.renderStats = this.renderStats.sort(function(a,b) {
7d7a48
+        this.renderStats = this.renderStats.sort((a, b) => {
7d7a48
             return renderStatOrder[a] - renderStatOrder[b];
7d7a48
         });
7d7a48
 
7d7a48
-	this.setLabelText(_("Memory"));
7d7a48
-    },
7d7a48
+        this.setLabelText(_('Memory'));
7d7a48
+    }
7d7a48
 
7d7a48
-    _initValues: function() {
7d7a48
+    _initValues() {
7d7a48
         this.mem = new GTop.glibtop_mem;
7d7a48
         this.stats = {
7d7a48
-                        'mem-user': { color: "-mem-user-color", values: [] },
7d7a48
-                        'mem-other': { color: "-mem-other-color", values: [] },
7d7a48
-                        'mem-cached': { color: "-mem-cached-color", values: [] }
7d7a48
-                     };
7d7a48
-    },
7d7a48
+            'mem-user': { color: '-mem-user-color', values: [] },
7d7a48
+            'mem-other': { color: '-mem-other-color', values: [] },
7d7a48
+            'mem-cached': { color: '-mem-cached-color', values: [] }
7d7a48
+        };
7d7a48
+    }
7d7a48
 
7d7a48
-    _updateValues: function() {
7d7a48
+    _updateValues() {
7d7a48
         GTop.glibtop_get_mem(this.mem);
7d7a48
 
7d7a48
         let t = this.mem.user / this.mem.total;
7d7a48
@@ -286,90 +286,97 @@ const MemoryIndicator = new Lang.Class({
7d7a48
         t += this.mem.cached / this.mem.total;
7d7a48
         this.stats['mem-cached'].values.push(t);
7d7a48
     }
7d7a48
-});
7d7a48
+};
7d7a48
 
7d7a48
 const INDICATORS = [CpuIndicator, MemoryIndicator];
7d7a48
 
7d7a48
-const Extension = new Lang.Class({
7d7a48
-    Name: 'SystemMonitor.Extension',
7d7a48
-
7d7a48
-    _init: function() {
7d7a48
-	Convenience.initTranslations();
7d7a48
-
7d7a48
-	this._showLabelTimeoutId = 0;
7d7a48
-	this._resetHoverTimeoutId = 0;
7d7a48
-	this._labelShowing = false;
7d7a48
-    },
7d7a48
-
7d7a48
-    enable: function() {
7d7a48
-	this._box = new St.BoxLayout({ style_class: 'extension-systemMonitor-container',
7d7a48
-				       x_align: Clutter.ActorAlign.START,
7d7a48
-				       x_expand: true });
7d7a48
-	this._indicators = [ ];
7d7a48
-
7d7a48
-	for (let i = 0; i < INDICATORS.length; i++) {
7d7a48
-	    let indicator = new (INDICATORS[i])();
7d7a48
-
7d7a48
-            indicator.actor.connect('notify::hover', Lang.bind(this, function() {
7d7a48
-		this._onHover(indicator);
7d7a48
-	    }));
7d7a48
-	    this._box.add_actor(indicator.actor);
7d7a48
-	    this._indicators.push(indicator);
7d7a48
-	}
7d7a48
-
7d7a48
-	this._boxHolder = new St.BoxLayout({ x_expand: true,
7d7a48
-					     y_expand: true,
7d7a48
-					     x_align: Clutter.ActorAlign.START,
7d7a48
-					   });
7d7a48
-	let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
-	Main.messageTray.actor.remove_child(menuButton);
7d7a48
-	Main.messageTray.actor.add_child(this._boxHolder);
7d7a48
-
7d7a48
-	this._boxHolder.add_child(this._box);
7d7a48
-	this._boxHolder.add_child(menuButton);
7d7a48
-    },
7d7a48
-
7d7a48
-    disable: function() {
7d7a48
-	this._indicators.forEach(function(i) { i.destroy(); });
7d7a48
-
7d7a48
-	let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
-	this._boxHolder.remove_child(menuButton);
7d7a48
-	Main.messageTray.actor.add_child(menuButton);
7d7a48
-
7d7a48
-	this._box.destroy();
7d7a48
-	this._boxHolder.destroy();
7d7a48
-    },
7d7a48
-
7d7a48
-    _onHover: function (item) {
7d7a48
+class Extension {
7d7a48
+    constructor() {
7d7a48
+        ExtensionUtils.initTranslations();
7d7a48
+
7d7a48
+        this._showLabelTimeoutId = 0;
7d7a48
+        this._resetHoverTimeoutId = 0;
7d7a48
+        this._labelShowing = false;
7d7a48
+    }
7d7a48
+
7d7a48
+    enable() {
7d7a48
+        this._box = new St.BoxLayout({
7d7a48
+            style_class: 'extension-systemMonitor-container',
7d7a48
+            x_align: Clutter.ActorAlign.START,
7d7a48
+            x_expand: true
7d7a48
+        });
7d7a48
+        this._indicators = [];
7d7a48
+
7d7a48
+        for (let i = 0; i < INDICATORS.length; i++) {
7d7a48
+            let indicator = new (INDICATORS[i])();
7d7a48
+
7d7a48
+            indicator.actor.connect('notify::hover', () => {
7d7a48
+                this._onHover(indicator);
7d7a48
+            });
7d7a48
+            this._box.add_actor(indicator.actor);
7d7a48
+            this._indicators.push(indicator);
7d7a48
+        }
7d7a48
+
7d7a48
+        this._boxHolder = new St.BoxLayout({
7d7a48
+            x_expand: true,
7d7a48
+            y_expand: true,
7d7a48
+            x_align: Clutter.ActorAlign.START,
7d7a48
+        });
7d7a48
+        let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
+        Main.messageTray.actor.remove_child(menuButton);
7d7a48
+        Main.messageTray.actor.add_child(this._boxHolder);
7d7a48
+
7d7a48
+        this._boxHolder.add_child(this._box);
7d7a48
+        this._boxHolder.add_child(menuButton);
7d7a48
+    }
7d7a48
+
7d7a48
+    disable() {
7d7a48
+        this._indicators.forEach(i => i.destroy());
7d7a48
+
7d7a48
+        let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
+        this._boxHolder.remove_child(menuButton);
7d7a48
+        Main.messageTray.actor.add_child(menuButton);
7d7a48
+
7d7a48
+        this._box.destroy();
7d7a48
+        this._boxHolder.destroy();
7d7a48
+    }
7d7a48
+
7d7a48
+    _onHover(item) {
7d7a48
         if (item.actor.get_hover()) {
7d7a48
-            if (this._showLabelTimeoutId == 0) {
7d7a48
-                let timeout = this._labelShowing ? 0 : ITEM_HOVER_TIMEOUT;
7d7a48
-                this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
7d7a48
-                    Lang.bind(this, function() {
7d7a48
-                        this._labelShowing = true;
7d7a48
-                        item.showLabel();
7d7a48
-                        return false;
7d7a48
-                    }));
7d7a48
-                if (this._resetHoverTimeoutId > 0) {
7d7a48
-                    Mainloop.source_remove(this._resetHoverTimeoutId);
7d7a48
-                    this._resetHoverTimeoutId = 0;
7d7a48
-                }
7d7a48
+            if (this._showLabelTimeoutId)
7d7a48
+                return;
7d7a48
+
7d7a48
+            let timeout = this._labelShowing ? 0 : ITEM_HOVER_TIMEOUT;
7d7a48
+            this._showLabelTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
7d7a48
+                timeout,
7d7a48
+                () => {
7d7a48
+                    this._labelShowing = true;
7d7a48
+                    item.showLabel();
7d7a48
+                    this._showLabelTimeoutId = 0;
7d7a48
+                    return GLib.SOURCE_REMOVE;
7d7a48
+                });
7d7a48
+
7d7a48
+            if (this._resetHoverTimeoutId > 0) {
7d7a48
+                GLib.source_remove(this._resetHoverTimeoutId);
7d7a48
+                this._resetHoverTimeoutId = 0;
7d7a48
             }
7d7a48
         } else {
7d7a48
             if (this._showLabelTimeoutId > 0)
7d7a48
-                Mainloop.source_remove(this._showLabelTimeoutId);
7d7a48
+                GLib.source_remove(this._showLabelTimeoutId);
7d7a48
             this._showLabelTimeoutId = 0;
7d7a48
             item.hideLabel();
7d7a48
-            if (this._labelShowing) {
7d7a48
-                this._resetHoverTimeoutId = Mainloop.timeout_add(ITEM_HOVER_TIMEOUT,
7d7a48
-                    Lang.bind(this, function() {
7d7a48
-                        this._labelShowing = false;
7d7a48
-                        return false;
7d7a48
-                    }));
7d7a48
-            }
7d7a48
+            if (!this._labelShowing)
7d7a48
+                return;
7d7a48
+
7d7a48
+            this._resetHoverTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
7d7a48
+                ITEM_HOVER_TIMEOUT,
7d7a48
+                () => {
7d7a48
+                    this._labelShowing = false;
7d7a48
+                    return GLib.SOURCE_REMOVE;
7d7a48
+                });
7d7a48
         }
7d7a48
-    },
7d7a48
-});
7d7a48
+    }
7d7a48
+}
7d7a48
 
7d7a48
 function init() {
7d7a48
     return new Extension();
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From e7ea49cd416e8ede9767f5ade46a06764d1e9a5b Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Wed, 17 May 2017 19:31:58 +0200
7d7a48
Subject: [PATCH 3/5] systemMonitor: Move indicators to calendar
7d7a48
7d7a48
The message tray joined the invisible choir, so we have to find
7d7a48
a new home for the extension UI. The message list in the calendar
7d7a48
drop-down looks like the best option, given that it replaced the
7d7a48
old tray (and also took over the old keyboard shortcut to bring
7d7a48
it up quickly).
7d7a48
---
7d7a48
 extensions/systemMonitor/extension.js   | 65 ++++++++++++-------------
7d7a48
 extensions/systemMonitor/stylesheet.css | 14 ------
7d7a48
 2 files changed, 31 insertions(+), 48 deletions(-)
7d7a48
7d7a48
diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js
7d7a48
index 89f8916..0188960 100644
7d7a48
--- a/extensions/systemMonitor/extension.js
7d7a48
+++ b/extensions/systemMonitor/extension.js
7d7a48
@@ -3,9 +3,11 @@
7d7a48
 /* exported init */
7d7a48
 
7d7a48
 const { Clutter, GLib, GTop, Shell, St } = imports.gi;
7d7a48
+const Signals = imports.signals;
7d7a48
 
7d7a48
 const ExtensionUtils = imports.misc.extensionUtils;
7d7a48
 const Main = imports.ui.main;
7d7a48
+const MessageList = imports.ui.messageList;
7d7a48
 const Tweener = imports.ui.tweener;
7d7a48
 
7d7a48
 const Gettext = imports.gettext.domain('gnome-shell-extensions');
7d7a48
@@ -21,22 +23,25 @@ const ITEM_HOVER_TIMEOUT = 300;
7d7a48
 const Indicator = class {
7d7a48
     constructor() {
7d7a48
         this._initValues();
7d7a48
-        this._drawingArea = new St.DrawingArea({ reactive: true });
7d7a48
+        this._drawingArea = new St.DrawingArea();
7d7a48
         this._drawingArea.connect('repaint', this._draw.bind(this));
7d7a48
-        this._drawingArea.connect('button-press-event', () => {
7d7a48
+
7d7a48
+        this.actor = new St.Button({
7d7a48
+            style_class: 'message message-content extension-systemMonitor-indicator-area',
7d7a48
+            child: this._drawingArea,
7d7a48
+            x_expand: true,
7d7a48
+            x_fill: true,
7d7a48
+            y_fill: true,
7d7a48
+            can_focus: true
7d7a48
+        });
7d7a48
+
7d7a48
+        this.actor.connect('clicked', () => {
7d7a48
             let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop');
7d7a48
             app.open_new_window(-1);
7d7a48
-            return true;
7d7a48
-        });
7d7a48
 
7d7a48
-        this.actor = new St.Bin({
7d7a48
-            style_class: 'extension-systemMonitor-indicator-area',
7d7a48
-            reactive: true,
7d7a48
-            track_hover: true,
7d7a48
-            x_fill: true,
7d7a48
-            y_fill: true
7d7a48
+            Main.overview.hide();
7d7a48
+            Main.panel.closeCalendar();
7d7a48
         });
7d7a48
-        this.actor.add_actor(this._drawingArea);
7d7a48
 
7d7a48
         this.actor.connect('destroy', this._onDestroy.bind(this));
7d7a48
 
7d7a48
@@ -71,6 +76,7 @@ const Indicator = class {
7d7a48
         let y = stageY - this.label.get_height() - yOffset;
7d7a48
 
7d7a48
         this.label.set_position(x, y);
7d7a48
+        this.label.get_parent().set_child_above_sibling(this.label, null);
7d7a48
         Tweener.addTween(this.label, {
7d7a48
             opacity: 255,
7d7a48
             time: ITEM_LABEL_SHOW_TIME,
7d7a48
@@ -98,6 +104,14 @@ const Indicator = class {
7d7a48
         });
7d7a48
     }
7d7a48
 
7d7a48
+    /* MessageList.Message boilerplate */
7d7a48
+    canClose() {
7d7a48
+        return false;
7d7a48
+    }
7d7a48
+
7d7a48
+    clear() {
7d7a48
+    }
7d7a48
+
7d7a48
     destroy() {
7d7a48
         this.actor.destroy();
7d7a48
     }
7d7a48
@@ -195,6 +209,7 @@ const Indicator = class {
7d7a48
         }
7d7a48
     }
7d7a48
 };
7d7a48
+Signals.addSignalMethods(Indicator.prototype); // For MessageList.Message compat
7d7a48
 
7d7a48
 const CpuIndicator = class extends Indicator {
7d7a48
     constructor() {
7d7a48
@@ -300,11 +315,7 @@ class Extension {
7d7a48
     }
7d7a48
 
7d7a48
     enable() {
7d7a48
-        this._box = new St.BoxLayout({
7d7a48
-            style_class: 'extension-systemMonitor-container',
7d7a48
-            x_align: Clutter.ActorAlign.START,
7d7a48
-            x_expand: true
7d7a48
-        });
7d7a48
+        this._section = new MessageList.MessageListSection(_('System Monitor'));
7d7a48
         this._indicators = [];
7d7a48
 
7d7a48
         for (let i = 0; i < INDICATORS.length; i++) {
7d7a48
@@ -313,32 +324,18 @@ class Extension {
7d7a48
             indicator.actor.connect('notify::hover', () => {
7d7a48
                 this._onHover(indicator);
7d7a48
             });
7d7a48
-            this._box.add_actor(indicator.actor);
7d7a48
+            this._section.addMessage(indicator, false);
7d7a48
             this._indicators.push(indicator);
7d7a48
         }
7d7a48
 
7d7a48
-        this._boxHolder = new St.BoxLayout({
7d7a48
-            x_expand: true,
7d7a48
-            y_expand: true,
7d7a48
-            x_align: Clutter.ActorAlign.START,
7d7a48
-        });
7d7a48
-        let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
-        Main.messageTray.actor.remove_child(menuButton);
7d7a48
-        Main.messageTray.actor.add_child(this._boxHolder);
7d7a48
-
7d7a48
-        this._boxHolder.add_child(this._box);
7d7a48
-        this._boxHolder.add_child(menuButton);
7d7a48
+        Main.panel.statusArea.dateMenu._messageList._addSection(this._section);
7d7a48
+        this._section.actor.get_parent().set_child_at_index(this._section.actor, 0);
7d7a48
     }
7d7a48
 
7d7a48
     disable() {
7d7a48
         this._indicators.forEach(i => i.destroy());
7d7a48
 
7d7a48
-        let menuButton = Main.messageTray._messageTrayMenuButton.actor;
7d7a48
-        this._boxHolder.remove_child(menuButton);
7d7a48
-        Main.messageTray.actor.add_child(menuButton);
7d7a48
-
7d7a48
-        this._box.destroy();
7d7a48
-        this._boxHolder.destroy();
7d7a48
+        Main.panel.statusArea.dateMenu._messageList._removeSection(this._section);
7d7a48
     }
7d7a48
 
7d7a48
     _onHover(item) {
7d7a48
diff --git a/extensions/systemMonitor/stylesheet.css b/extensions/systemMonitor/stylesheet.css
7d7a48
index 13f95ec..978ac12 100644
7d7a48
--- a/extensions/systemMonitor/stylesheet.css
7d7a48
+++ b/extensions/systemMonitor/stylesheet.css
7d7a48
@@ -1,17 +1,4 @@
7d7a48
-.extension-systemMonitor-container {
7d7a48
-    spacing: 5px;
7d7a48
-    padding-left: 5px;
7d7a48
-    padding-right: 5px;
7d7a48
-    padding-bottom: 10px;
7d7a48
-    padding-top: 10px;
7d7a48
-}
7d7a48
-
7d7a48
 .extension-systemMonitor-indicator-area {
7d7a48
-    border: 1px solid #8d8d8d;
7d7a48
-    border-radius: 3px;
7d7a48
-    width: 100px;
7d7a48
-    /* message tray is 72px, so 20px padding of the container,
7d7a48
-       2px of border, makes it 50px */
7d7a48
     height: 50px;
7d7a48
     -grid-color: #575757;
7d7a48
     -cpu-total-color: rgb(0,154,62);
7d7a48
@@ -21,7 +8,6 @@
7d7a48
     -mem-user-color: rgb(210,148,0);
7d7a48
     -mem-cached-color: rgb(90,90,90);
7d7a48
     -mem-other-color: rgb(205,203,41);
7d7a48
-    background-color: #1e1e1e;
7d7a48
 }
7d7a48
 
7d7a48
 .extension-systemMonitor-indicator-label {
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From f73fe9cfb5f9dbd6647e4eb30a9af0fb7ff79219 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Thu, 18 May 2017 16:20:07 +0200
7d7a48
Subject: [PATCH 4/5] systemMonitor: Handle clicks on section title
7d7a48
7d7a48
While on 3.24.x only the event section still has a clickable title,
7d7a48
it's a generic message list feature in previous versions. It's easy
7d7a48
enough to support with a small subclass, so use that instead of
7d7a48
the generic baseclass.
7d7a48
7d7a48
Fixes: https://gitlab.gnome.org/GNOME/gnome-shell-extensions3
7d7a48
---
7d7a48
 extensions/systemMonitor/extension.js | 17 ++++++++++++++++-
7d7a48
 1 file changed, 16 insertions(+), 1 deletion(-)
7d7a48
7d7a48
diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js
7d7a48
index 0188960..b4d5a9d 100644
7d7a48
--- a/extensions/systemMonitor/extension.js
7d7a48
+++ b/extensions/systemMonitor/extension.js
7d7a48
@@ -303,6 +303,21 @@ const MemoryIndicator = class extends Indicator {
7d7a48
     }
7d7a48
 };
7d7a48
 
7d7a48
+class SystemMonitorSection extends MessageList.MessageListSection {
7d7a48
+    constructor() {
7d7a48
+        super(_('System Monitor'));
7d7a48
+    }
7d7a48
+
7d7a48
+    _onTitleClicked() {
7d7a48
+        super._onTitleClicked();
7d7a48
+
7d7a48
+        let appSys = Shell.AppSystem.get_default();
7d7a48
+        let app = appSys.lookup_app('gnome-system-monitor.desktop');
7d7a48
+        if (app)
7d7a48
+            app.open_new_window(-1);
7d7a48
+    }
7d7a48
+}
7d7a48
+
7d7a48
 const INDICATORS = [CpuIndicator, MemoryIndicator];
7d7a48
 
7d7a48
 class Extension {
7d7a48
@@ -315,7 +330,7 @@ class Extension {
7d7a48
     }
7d7a48
 
7d7a48
     enable() {
7d7a48
-        this._section = new MessageList.MessageListSection(_('System Monitor'));
7d7a48
+        this._section = new SystemMonitorSection();
7d7a48
         this._indicators = [];
7d7a48
 
7d7a48
         for (let i = 0; i < INDICATORS.length; i++) {
7d7a48
-- 
7d7a48
2.21.0
7d7a48
7d7a48
7d7a48
From df76e98d6bbac7dccc86f66e82eac2977fb5ed87 Mon Sep 17 00:00:00 2001
7d7a48
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
7d7a48
Date: Thu, 18 May 2017 18:00:17 +0200
7d7a48
Subject: [PATCH 5/5] systemMonitor: Provide classic styling
7d7a48
7d7a48
The indicator tooltips currently don't work out in classic mode
7d7a48
(dark text on dark background), so provide some mode-specific
7d7a48
style.
7d7a48
7d7a48
Fixes: #4
7d7a48
---
7d7a48
 extensions/systemMonitor/classic.css | 6 ++++++
7d7a48
 extensions/systemMonitor/meson.build | 4 ++++
7d7a48
 2 files changed, 10 insertions(+)
7d7a48
 create mode 100644 extensions/systemMonitor/classic.css
7d7a48
7d7a48
diff --git a/extensions/systemMonitor/classic.css b/extensions/systemMonitor/classic.css
7d7a48
new file mode 100644
7d7a48
index 0000000..946863d
7d7a48
--- /dev/null
7d7a48
+++ b/extensions/systemMonitor/classic.css
7d7a48
@@ -0,0 +1,6 @@
7d7a48
+@import url("stylesheet.css");
7d7a48
+
7d7a48
+.extension-systemMonitor-indicator-label {
7d7a48
+    background-color: rgba(237,237,237,0.9);
7d7a48
+    border: 1px solid #a1a1a1;
7d7a48
+}
7d7a48
diff --git a/extensions/systemMonitor/meson.build b/extensions/systemMonitor/meson.build
7d7a48
index 48504f6..b6548b1 100644
7d7a48
--- a/extensions/systemMonitor/meson.build
7d7a48
+++ b/extensions/systemMonitor/meson.build
7d7a48
@@ -3,3 +3,7 @@ extension_data += configure_file(
7d7a48
   output: metadata_name,
7d7a48
   configuration: metadata_conf
7d7a48
 )
7d7a48
+
7d7a48
+if classic_mode_enabled
7d7a48
+  extension_data += files('classic.css')
7d7a48
+endif
7d7a48
-- 
7d7a48
2.21.0
7d7a48