Blame SOURCES/resurrect-system-monitor.patch

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