From f34736156ed324ea4d00f5c6d4d77a39f3f08e78 Mon Sep 17 00:00:00 2001 From: rpm-build Date: Sep 25 2020 17:50:56 +0000 Subject: resurrect-system-monitor.patch patch_name: resurrect-system-monitor.patch present_in_specfile: true location_in_specfile: 5 --- diff --git a/extensions/systemMonitor/classic.css b/extensions/systemMonitor/classic.css new file mode 100644 index 0000000..946863d --- /dev/null +++ b/extensions/systemMonitor/classic.css @@ -0,0 +1,6 @@ +@import url("stylesheet.css"); + +.extension-systemMonitor-indicator-label { + background-color: rgba(237,237,237,0.9); + border: 1px solid #a1a1a1; +} diff --git a/extensions/systemMonitor/extension.js b/extensions/systemMonitor/extension.js new file mode 100644 index 0000000..b4d5a9d --- /dev/null +++ b/extensions/systemMonitor/extension.js @@ -0,0 +1,395 @@ +/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ + +/* exported init */ + +const { Clutter, GLib, GTop, Shell, St } = imports.gi; +const Signals = imports.signals; + +const ExtensionUtils = imports.misc.extensionUtils; +const Main = imports.ui.main; +const MessageList = imports.ui.messageList; +const Tweener = imports.ui.tweener; + +const Gettext = imports.gettext.domain('gnome-shell-extensions'); +const _ = Gettext.gettext; + +const INDICATOR_UPDATE_INTERVAL = 500; +const INDICATOR_NUM_GRID_LINES = 3; + +const ITEM_LABEL_SHOW_TIME = 0.15; +const ITEM_LABEL_HIDE_TIME = 0.1; +const ITEM_HOVER_TIMEOUT = 300; + +const Indicator = class { + constructor() { + this._initValues(); + this._drawingArea = new St.DrawingArea(); + this._drawingArea.connect('repaint', this._draw.bind(this)); + + this.actor = new St.Button({ + style_class: 'message message-content extension-systemMonitor-indicator-area', + child: this._drawingArea, + x_expand: true, + x_fill: true, + y_fill: true, + can_focus: true + }); + + this.actor.connect('clicked', () => { + let app = Shell.AppSystem.get_default().lookup_app('gnome-system-monitor.desktop'); + app.open_new_window(-1); + + Main.overview.hide(); + Main.panel.closeCalendar(); + }); + + this.actor.connect('destroy', this._onDestroy.bind(this)); + + this._timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + INDICATOR_UPDATE_INTERVAL, + () => { + this._updateValues(); + this._drawingArea.queue_repaint(); + return GLib.SOURCE_CONTINUE; + }); + } + + showLabel() { + if (this.label == null) + return; + + this.label.opacity = 0; + this.label.show(); + + let [stageX, stageY] = this.actor.get_transformed_position(); + + let itemWidth = this.actor.allocation.x2 - this.actor.allocation.x1; + + let labelWidth = this.label.width; + let xOffset = Math.floor((itemWidth - labelWidth) / 2); + + let x = stageX + xOffset; + + let node = this.label.get_theme_node(); + let yOffset = node.get_length('-y-offset'); + + let y = stageY - this.label.get_height() - yOffset; + + this.label.set_position(x, y); + this.label.get_parent().set_child_above_sibling(this.label, null); + Tweener.addTween(this.label, { + opacity: 255, + time: ITEM_LABEL_SHOW_TIME, + transition: 'easeOutQuad', + }); + } + + setLabelText(text) { + if (this.label == null) + this.label = new St.Label({ + style_class: 'extension-systemMonitor-indicator-label' + }); + + this.label.set_text(text); + Main.layoutManager.addChrome(this.label); + this.label.hide(); + } + + hideLabel() { + Tweener.addTween(this.label, { + opacity: 0, + time: ITEM_LABEL_HIDE_TIME, + transition: 'easeOutQuad', + onComplete: () => this.label.hide() + }); + } + + /* MessageList.Message boilerplate */ + canClose() { + return false; + } + + clear() { + } + + destroy() { + this.actor.destroy(); + } + + _onDestroy() { + GLib.source_remove(this._timeout); + + if (this.label) + this.label.destroy(); + } + + _initValues() { + } + + _updateValues() { + } + + _draw(area) { + let [width, height] = area.get_surface_size(); + let themeNode = this.actor.get_theme_node(); + let cr = area.get_context(); + + //draw the background grid + let color = themeNode.get_color(this.gridColor); + let gridOffset = Math.floor(height / (INDICATOR_NUM_GRID_LINES + 1)); + for (let i = 1; i <= INDICATOR_NUM_GRID_LINES; ++i) { + cr.moveTo(0, i * gridOffset + .5); + cr.lineTo(width, i * gridOffset + .5); + } + Clutter.cairo_set_source_color(cr, color); + cr.setLineWidth(1); + cr.setDash([4, 1], 0); + cr.stroke(); + + //draw the foreground + + function makePath(values, reverse, nudge) { + if (nudge == null) { + nudge = 0; + } + //if we are going in reverse, we are completing the bottom of a chart, so use lineTo + if (reverse) { + cr.lineTo(values.length - 1, (1 - values[values.length - 1]) * height + nudge); + for (let k = values.length - 2; k >= 0; --k) { + cr.lineTo(k, (1 - values[k]) * height + nudge); + } + } else { + cr.moveTo(0, (1 - values[0]) * height + nudge); + for (let k = 1; k < values.length; ++k) { + cr.lineTo(k, (1 - values[k]) * height + nudge); + } + + } + } + + let renderStats = this.renderStats; + + // Make sure we don't have more sample points than pixels + renderStats.map(k => { + let stat = this.stats[k]; + if (stat.values.length > width) { + stat.values = stat.values.slice(stat.values.length - width, stat.values.length); + } + }); + + for (let i = 0; i < renderStats.length; ++i) { + let stat = this.stats[renderStats[i]]; + // We outline at full opacity and fill with 40% opacity + let outlineColor = themeNode.get_color(stat.color); + let color = new Clutter.Color(outlineColor); + color.alpha = color.alpha * .4; + + // Render the background between us and the next level + makePath(stat.values, false); + // If there is a process below us, render the cpu between us and it, otherwise, + // render to the bottom of the chart + if (i == renderStats.length - 1) { + cr.lineTo(stat.values.length - 1, height); + cr.lineTo(0, height); + cr.closePath(); + } else { + let nextStat = this.stats[renderStats[i + 1]]; + makePath(nextStat.values, true); + } + cr.closePath(); + Clutter.cairo_set_source_color(cr, color); + cr.fill(); + + // Render the outline of this level + makePath(stat.values, false, .5); + Clutter.cairo_set_source_color(cr, outlineColor); + cr.setLineWidth(1.0); + cr.setDash([], 0); + cr.stroke(); + } + } +}; +Signals.addSignalMethods(Indicator.prototype); // For MessageList.Message compat + +const CpuIndicator = class extends Indicator { + constructor() { + super(); + + this.gridColor = '-grid-color'; + this.renderStats = ['cpu-user', 'cpu-sys', 'cpu-iowait']; + + // Make sure renderStats is sorted as necessary for rendering + let renderStatOrder = { + 'cpu-total': 0, + 'cpu-user': 1, + 'cpu-sys': 2, + 'cpu-iowait': 3 + }; + this.renderStats = this.renderStats.sort((a, b) => { + return renderStatOrder[a] - renderStatOrder[b]; + }); + + this.setLabelText(_('CPU')); + } + + _initValues() { + this._prev = new GTop.glibtop_cpu; + GTop.glibtop_get_cpu(this._prev); + + this.stats = { + 'cpu-user': { color: '-cpu-user-color', values: [] }, + 'cpu-sys': { color: '-cpu-sys-color', values: [] }, + 'cpu-iowait': { color: '-cpu-iowait-color', values: [] }, + 'cpu-total': { color: '-cpu-total-color', values: [] } + }; + } + + _updateValues() { + let cpu = new GTop.glibtop_cpu; + let t = 0.0; + GTop.glibtop_get_cpu(cpu); + let total = cpu.total - this._prev.total; + let user = cpu.user - this._prev.user; + let sys = cpu.sys - this._prev.sys; + let iowait = cpu.iowait - this._prev.iowait; + let idle = cpu.idle - this._prev.idle; + + t += iowait / total; + this.stats['cpu-iowait'].values.push(t); + t += sys / total; + this.stats['cpu-sys'].values.push(t); + t += user / total; + this.stats['cpu-user'].values.push(t); + this.stats['cpu-total'].values.push(1 - idle / total); + + this._prev = cpu; + } +}; + +const MemoryIndicator = class extends Indicator { + constructor() { + super(); + + this.gridColor = '-grid-color'; + this.renderStats = ['mem-user', 'mem-other', 'mem-cached']; + + // Make sure renderStats is sorted as necessary for rendering + let renderStatOrder = { 'mem-cached': 0, 'mem-other': 1, 'mem-user': 2 }; + this.renderStats = this.renderStats.sort((a, b) => { + return renderStatOrder[a] - renderStatOrder[b]; + }); + + this.setLabelText(_('Memory')); + } + + _initValues() { + this.mem = new GTop.glibtop_mem; + this.stats = { + 'mem-user': { color: '-mem-user-color', values: [] }, + 'mem-other': { color: '-mem-other-color', values: [] }, + 'mem-cached': { color: '-mem-cached-color', values: [] } + }; + } + + _updateValues() { + GTop.glibtop_get_mem(this.mem); + + let t = this.mem.user / this.mem.total; + this.stats['mem-user'].values.push(t); + t += (this.mem.used - this.mem.user - this.mem.cached) / this.mem.total; + this.stats['mem-other'].values.push(t); + t += this.mem.cached / this.mem.total; + this.stats['mem-cached'].values.push(t); + } +}; + +class SystemMonitorSection extends MessageList.MessageListSection { + constructor() { + super(_('System Monitor')); + } + + _onTitleClicked() { + super._onTitleClicked(); + + let appSys = Shell.AppSystem.get_default(); + let app = appSys.lookup_app('gnome-system-monitor.desktop'); + if (app) + app.open_new_window(-1); + } +} + +const INDICATORS = [CpuIndicator, MemoryIndicator]; + +class Extension { + constructor() { + ExtensionUtils.initTranslations(); + + this._showLabelTimeoutId = 0; + this._resetHoverTimeoutId = 0; + this._labelShowing = false; + } + + enable() { + this._section = new SystemMonitorSection(); + this._indicators = []; + + for (let i = 0; i < INDICATORS.length; i++) { + let indicator = new (INDICATORS[i])(); + + indicator.actor.connect('notify::hover', () => { + this._onHover(indicator); + }); + this._section.addMessage(indicator, false); + this._indicators.push(indicator); + } + + Main.panel.statusArea.dateMenu._messageList._addSection(this._section); + this._section.actor.get_parent().set_child_at_index(this._section.actor, 0); + } + + disable() { + this._indicators.forEach(i => i.destroy()); + + Main.panel.statusArea.dateMenu._messageList._removeSection(this._section); + } + + _onHover(item) { + if (item.actor.get_hover()) { + if (this._showLabelTimeoutId) + return; + + let timeout = this._labelShowing ? 0 : ITEM_HOVER_TIMEOUT; + this._showLabelTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + timeout, + () => { + this._labelShowing = true; + item.showLabel(); + this._showLabelTimeoutId = 0; + return GLib.SOURCE_REMOVE; + }); + + if (this._resetHoverTimeoutId > 0) { + GLib.source_remove(this._resetHoverTimeoutId); + this._resetHoverTimeoutId = 0; + } + } else { + if (this._showLabelTimeoutId > 0) + GLib.source_remove(this._showLabelTimeoutId); + this._showLabelTimeoutId = 0; + item.hideLabel(); + if (!this._labelShowing) + return; + + this._resetHoverTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + ITEM_HOVER_TIMEOUT, + () => { + this._labelShowing = false; + return GLib.SOURCE_REMOVE; + }); + } + } +} + +function init() { + return new Extension(); +} diff --git a/extensions/systemMonitor/meson.build b/extensions/systemMonitor/meson.build new file mode 100644 index 0000000..b6548b1 --- /dev/null +++ b/extensions/systemMonitor/meson.build @@ -0,0 +1,9 @@ +extension_data += configure_file( + input: metadata_name + '.in', + output: metadata_name, + configuration: metadata_conf +) + +if classic_mode_enabled + extension_data += files('classic.css') +endif diff --git a/extensions/systemMonitor/metadata.json.in b/extensions/systemMonitor/metadata.json.in new file mode 100644 index 0000000..fa75007 --- /dev/null +++ b/extensions/systemMonitor/metadata.json.in @@ -0,0 +1,11 @@ +{ + "shell-version": ["@shell_current@" ], + "uuid": "@uuid@", + "extension-id": "@extension_id@", + "settings-schema": "@gschemaname@", + "gettext-domain": "@gettext_domain@", + "original-author": "zaspire@rambler.ru", + "name": "SystemMonitor", + "description": "System monitor showing CPU and memory usage in the message tray.", + "url": "@url@" +} diff --git a/extensions/systemMonitor/stylesheet.css b/extensions/systemMonitor/stylesheet.css new file mode 100644 index 0000000..978ac12 --- /dev/null +++ b/extensions/systemMonitor/stylesheet.css @@ -0,0 +1,21 @@ +.extension-systemMonitor-indicator-area { + height: 50px; + -grid-color: #575757; + -cpu-total-color: rgb(0,154,62); + -cpu-user-color: rgb(69,154,0); + -cpu-sys-color: rgb(255,253,81); + -cpu-iowait-color: rgb(210,148,0); + -mem-user-color: rgb(210,148,0); + -mem-cached-color: rgb(90,90,90); + -mem-other-color: rgb(205,203,41); +} + +.extension-systemMonitor-indicator-label { + border-radius: 7px; + padding: 4px 12px; + background-color: rgba(0,0,0,0.9); + text-align: center; + -y-offset: 8px; + font-size: 9pt; + font-weight: bold; +} diff --git a/meson.build b/meson.build index 6e8c41f..6764f9a 100644 --- a/meson.build +++ b/meson.build @@ -55,6 +55,7 @@ all_extensions += [ 'native-window-placement', 'no-hot-corner', 'panel-favorites', + 'systemMonitor', 'top-icons', 'updates-dialog', 'user-theme',