2013-03-02 04:48:25 -05:00
|
|
|
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
|
|
|
2019-02-08 22:21:36 -05:00
|
|
|
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
|
|
|
|
const Mainloop = imports.mainloop;
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2018-02-08 13:22:29 -05:00
|
|
|
const BarLevel = imports.ui.barLevel;
|
2013-03-02 04:48:25 -05:00
|
|
|
const Layout = imports.ui.layout;
|
|
|
|
const Main = imports.ui.main;
|
|
|
|
const Tweener = imports.ui.tweener;
|
|
|
|
|
2017-07-18 13:47:27 -04:00
|
|
|
var HIDE_TIMEOUT = 1500;
|
|
|
|
var FADE_TIME = 0.1;
|
|
|
|
var LEVEL_ANIMATION_TIME = 0.1;
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var LevelBar = class extends BarLevel.BarLevel {
|
|
|
|
constructor() {
|
|
|
|
super(0, { styleClass: 'level' });
|
2013-03-02 04:48:25 -05:00
|
|
|
|
|
|
|
this._level = 0;
|
2018-07-31 10:47:05 -04:00
|
|
|
this._maxLevel = 100;
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2018-02-08 13:22:29 -05:00
|
|
|
this.actor.accessible_name = _("Volume");
|
2016-06-03 19:29:07 -04:00
|
|
|
|
2019-01-27 19:42:00 -05:00
|
|
|
this.actor.connect('notify::width', () => this.level = this.level);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
|
|
|
get level() {
|
|
|
|
return this._level;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
|
|
|
set level(value) {
|
2018-07-31 10:47:05 -04:00
|
|
|
this._level = Math.max(0, Math.min(value, this._maxLevel));
|
2016-06-03 19:29:07 -04:00
|
|
|
|
2018-02-08 13:22:29 -05:00
|
|
|
this.setValue(this._level / 100);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2018-07-31 10:47:05 -04:00
|
|
|
|
|
|
|
get maxLevel() {
|
|
|
|
return this._maxLevel;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2018-07-31 10:47:05 -04:00
|
|
|
|
|
|
|
set maxLevel(value) {
|
|
|
|
this._maxLevel = Math.max(100, value);
|
|
|
|
|
|
|
|
this.setMaximumValue(this._maxLevel / 100);
|
2013-03-02 04:48:25 -05:00
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
};
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2017-10-30 21:23:39 -04:00
|
|
|
var OsdWindowConstraint = GObject.registerClass(
|
|
|
|
class OsdWindowConstraint extends Clutter.Constraint {
|
2017-10-30 20:03:21 -04:00
|
|
|
_init(props) {
|
2016-06-21 13:46:44 -04:00
|
|
|
this._minSize = 0;
|
2017-10-30 21:23:39 -04:00
|
|
|
super._init(props);
|
|
|
|
}
|
2016-06-21 13:46:44 -04:00
|
|
|
|
|
|
|
set minSize(v) {
|
|
|
|
this._minSize = v;
|
|
|
|
if (this.actor)
|
|
|
|
this.actor.queue_relayout();
|
2017-10-30 21:23:39 -04:00
|
|
|
}
|
2016-06-21 13:46:44 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
vfunc_update_allocation(actor, actorBox) {
|
2016-06-21 13:46:44 -04:00
|
|
|
// Clutter will adjust the allocation for margins,
|
|
|
|
// so add it to our minimum size
|
|
|
|
let minSize = this._minSize + actor.margin_top + actor.margin_bottom;
|
|
|
|
let [width, height] = actorBox.get_size();
|
|
|
|
|
|
|
|
// Enforce a ratio of 1
|
|
|
|
let size = Math.ceil(Math.max(minSize, height));
|
|
|
|
actorBox.set_size(size, size);
|
|
|
|
|
|
|
|
// Recenter
|
|
|
|
let [x, y] = actorBox.get_origin();
|
2016-10-10 19:59:31 -04:00
|
|
|
actorBox.set_origin(Math.ceil(x + width / 2 - size / 2),
|
|
|
|
Math.ceil(y + height / 2 - size / 2));
|
2016-06-21 13:46:44 -04:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var OsdWindow = class {
|
|
|
|
constructor(monitorIndex) {
|
2013-03-02 04:48:25 -05:00
|
|
|
this.actor = new St.Widget({ x_expand: true,
|
|
|
|
y_expand: true,
|
|
|
|
x_align: Clutter.ActorAlign.CENTER,
|
|
|
|
y_align: Clutter.ActorAlign.CENTER });
|
2014-04-17 04:23:30 -04:00
|
|
|
|
|
|
|
this._monitorIndex = monitorIndex;
|
|
|
|
let constraint = new Layout.MonitorConstraint({ index: monitorIndex });
|
|
|
|
this.actor.add_constraint(constraint);
|
|
|
|
|
2016-06-21 13:46:44 -04:00
|
|
|
this._boxConstraint = new OsdWindowConstraint();
|
2013-03-02 04:48:25 -05:00
|
|
|
this._box = new St.BoxLayout({ style_class: 'osd-window',
|
|
|
|
vertical: true });
|
2016-06-21 13:46:44 -04:00
|
|
|
this._box.add_constraint(this._boxConstraint);
|
2013-03-02 04:48:25 -05:00
|
|
|
this.actor.add_actor(this._box);
|
|
|
|
|
|
|
|
this._icon = new St.Icon();
|
|
|
|
this._box.add(this._icon, { expand: true });
|
|
|
|
|
|
|
|
this._label = new St.Label();
|
|
|
|
this._box.add(this._label);
|
|
|
|
|
|
|
|
this._level = new LevelBar();
|
|
|
|
this._box.add(this._level.actor);
|
|
|
|
|
|
|
|
this._hideTimeoutId = 0;
|
|
|
|
this._reset();
|
|
|
|
|
2018-09-22 21:06:21 -04:00
|
|
|
this.actor.connect('destroy', this._onDestroy.bind(this));
|
|
|
|
|
|
|
|
this._monitorsChangedId =
|
|
|
|
Main.layoutManager.connect('monitors-changed',
|
|
|
|
this._relayout.bind(this));
|
2016-10-10 19:56:35 -04:00
|
|
|
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
2018-09-22 21:06:21 -04:00
|
|
|
this._scaleChangedId =
|
|
|
|
themeContext.connect('notify::scale-factor',
|
|
|
|
this._relayout.bind(this));
|
2016-10-10 19:56:35 -04:00
|
|
|
this._relayout();
|
2013-05-18 20:59:46 -04:00
|
|
|
Main.uiGroup.add_child(this.actor);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2018-09-22 21:06:21 -04:00
|
|
|
_onDestroy() {
|
|
|
|
if (this._monitorsChangedId)
|
|
|
|
Main.layoutManager.disconnect(this._monitorsChangedId);
|
|
|
|
this._monitorsChangedId = 0;
|
|
|
|
|
|
|
|
let themeContext = St.ThemeContext.get_for_stage(global.stage);
|
|
|
|
if (this._scaleChangedId)
|
|
|
|
themeContext.disconnect(this._scaleChangedId);
|
|
|
|
this._scaleChangedId = 0;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2018-09-22 21:06:21 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
setIcon(icon) {
|
2013-03-02 04:48:25 -05:00
|
|
|
this._icon.gicon = icon;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
setLabel(label) {
|
2013-03-02 04:48:25 -05:00
|
|
|
this._label.visible = (label != undefined);
|
|
|
|
if (label)
|
|
|
|
this._label.text = label;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
setLevel(level) {
|
2013-03-02 04:48:25 -05:00
|
|
|
this._level.actor.visible = (level != undefined);
|
2014-04-25 09:14:22 -04:00
|
|
|
if (level != undefined) {
|
2013-04-14 11:32:21 -04:00
|
|
|
if (this.actor.visible)
|
|
|
|
Tweener.addTween(this._level,
|
|
|
|
{ level: level,
|
|
|
|
time: LEVEL_ANIMATION_TIME,
|
|
|
|
transition: 'easeOutQuad' });
|
|
|
|
else
|
|
|
|
this._level.level = level;
|
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2019-07-11 19:31:38 -04:00
|
|
|
setMaxLevel(maxLevel = 100) {
|
2018-07-31 10:47:05 -04:00
|
|
|
this._level.maxLevel = maxLevel;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2018-07-31 10:47:05 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
show() {
|
2013-03-02 04:48:25 -05:00
|
|
|
if (!this._icon.gicon)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!this.actor.visible) {
|
2018-01-03 02:55:38 -05:00
|
|
|
Meta.disable_unredirect_for_display(global.display);
|
2013-03-02 04:48:25 -05:00
|
|
|
this.actor.show();
|
|
|
|
this.actor.opacity = 0;
|
2013-05-30 08:29:31 -04:00
|
|
|
this.actor.get_parent().set_child_above_sibling(this.actor, null);
|
2013-03-02 04:48:25 -05:00
|
|
|
|
|
|
|
Tweener.addTween(this.actor,
|
|
|
|
{ opacity: 255,
|
|
|
|
time: FADE_TIME,
|
|
|
|
transition: 'easeOutQuad' });
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._hideTimeoutId)
|
|
|
|
Mainloop.source_remove(this._hideTimeoutId);
|
|
|
|
this._hideTimeoutId = Mainloop.timeout_add(HIDE_TIMEOUT,
|
2017-12-01 19:27:35 -05:00
|
|
|
this._hide.bind(this));
|
2014-04-10 13:26:52 -04:00
|
|
|
GLib.Source.set_name_by_id(this._hideTimeoutId, '[gnome-shell] this._hide');
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
cancel() {
|
2013-03-02 13:56:37 -05:00
|
|
|
if (!this._hideTimeoutId)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Mainloop.source_remove(this._hideTimeoutId);
|
|
|
|
this._hide();
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 13:56:37 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_hide() {
|
2013-06-24 17:15:33 -04:00
|
|
|
this._hideTimeoutId = 0;
|
2013-03-02 04:48:25 -05:00
|
|
|
Tweener.addTween(this.actor,
|
|
|
|
{ opacity: 0,
|
|
|
|
time: FADE_TIME,
|
|
|
|
transition: 'easeOutQuad',
|
2017-10-30 20:38:18 -04:00
|
|
|
onComplete: () => {
|
2019-01-29 14:36:54 -05:00
|
|
|
this._reset();
|
|
|
|
Meta.enable_unredirect_for_display(global.display);
|
2017-10-30 20:38:18 -04:00
|
|
|
}
|
2013-06-18 16:59:48 -04:00
|
|
|
});
|
2013-11-28 19:45:39 -05:00
|
|
|
return GLib.SOURCE_REMOVE;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_reset() {
|
2013-03-02 04:48:25 -05:00
|
|
|
this.actor.hide();
|
|
|
|
this.setLabel(null);
|
2018-07-31 10:47:05 -04:00
|
|
|
this.setMaxLevel(null);
|
2018-10-18 11:26:03 -04:00
|
|
|
this.setLevel(null);
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_relayout() {
|
2013-03-07 16:45:50 -05:00
|
|
|
/* assume 110x110 on a 640x480 display and scale from there */
|
2014-04-17 04:23:30 -04:00
|
|
|
let monitor = Main.layoutManager.monitors[this._monitorIndex];
|
2014-05-03 15:12:29 -04:00
|
|
|
if (!monitor)
|
|
|
|
return; // we are about to be removed
|
2013-11-18 07:48:19 -05:00
|
|
|
|
2013-03-02 04:48:25 -05:00
|
|
|
let scalew = monitor.width / 640.0;
|
|
|
|
let scaleh = monitor.height / 480.0;
|
|
|
|
let scale = Math.min(scalew, scaleh);
|
2016-06-21 13:46:44 -04:00
|
|
|
let popupSize = 110 * Math.max(1, scale);
|
2013-03-02 04:48:25 -05:00
|
|
|
|
2014-02-17 23:55:15 -05:00
|
|
|
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
|
2016-06-21 13:46:44 -04:00
|
|
|
this._icon.icon_size = popupSize / (2 * scaleFactor);
|
2017-05-26 11:46:35 -04:00
|
|
|
this._box.translation_y = Math.round(monitor.height / 4);
|
2016-06-21 13:46:44 -04:00
|
|
|
this._boxConstraint.minSize = popupSize;
|
2014-04-17 04:23:30 -04:00
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
};
|
2014-04-17 04:23:30 -04:00
|
|
|
|
2017-10-30 21:19:44 -04:00
|
|
|
var OsdWindowManager = class {
|
|
|
|
constructor() {
|
2014-04-17 04:23:30 -04:00
|
|
|
this._osdWindows = [];
|
|
|
|
Main.layoutManager.connect('monitors-changed',
|
2019-01-29 14:36:54 -05:00
|
|
|
this._monitorsChanged.bind(this));
|
2014-04-17 04:23:30 -04:00
|
|
|
this._monitorsChanged();
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-11-18 07:48:19 -05:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
_monitorsChanged() {
|
2014-04-17 04:23:30 -04:00
|
|
|
for (let i = 0; i < Main.layoutManager.monitors.length; i++) {
|
|
|
|
if (this._osdWindows[i] == undefined)
|
|
|
|
this._osdWindows[i] = new OsdWindow(i);
|
|
|
|
}
|
2013-11-18 07:48:19 -05:00
|
|
|
|
2014-04-17 04:23:30 -04:00
|
|
|
for (let i = Main.layoutManager.monitors.length; i < this._osdWindows.length; i++) {
|
|
|
|
this._osdWindows[i].actor.destroy();
|
|
|
|
this._osdWindows[i] = null;
|
|
|
|
}
|
2013-11-18 07:48:19 -05:00
|
|
|
|
2014-04-17 04:23:30 -04:00
|
|
|
this._osdWindows.length = Main.layoutManager.monitors.length;
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2013-11-18 07:48:19 -05:00
|
|
|
|
2018-07-31 10:47:05 -04:00
|
|
|
_showOsdWindow(monitorIndex, icon, label, level, maxLevel) {
|
2014-04-17 04:23:30 -04:00
|
|
|
this._osdWindows[monitorIndex].setIcon(icon);
|
|
|
|
this._osdWindows[monitorIndex].setLabel(label);
|
2018-07-31 10:47:05 -04:00
|
|
|
this._osdWindows[monitorIndex].setMaxLevel(maxLevel);
|
2018-10-18 11:26:03 -04:00
|
|
|
this._osdWindows[monitorIndex].setLevel(level);
|
2014-04-17 04:23:30 -04:00
|
|
|
this._osdWindows[monitorIndex].show();
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-04-17 04:23:30 -04:00
|
|
|
|
2018-07-31 10:47:05 -04:00
|
|
|
show(monitorIndex, icon, label, level, maxLevel) {
|
2014-04-17 04:23:30 -04:00
|
|
|
if (monitorIndex != -1) {
|
|
|
|
for (let i = 0; i < this._osdWindows.length; i++) {
|
|
|
|
if (i == monitorIndex)
|
2018-07-31 10:47:05 -04:00
|
|
|
this._showOsdWindow(i, icon, label, level, maxLevel);
|
2014-04-17 04:23:30 -04:00
|
|
|
else
|
|
|
|
this._osdWindows[i].cancel();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (let i = 0; i < this._osdWindows.length; i++)
|
2018-07-31 10:47:05 -04:00
|
|
|
this._showOsdWindow(i, icon, label, level, maxLevel);
|
2014-04-17 04:23:30 -04:00
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
}
|
2014-04-17 04:23:30 -04:00
|
|
|
|
2017-10-30 20:03:21 -04:00
|
|
|
hideAll() {
|
2014-04-17 04:23:30 -04:00
|
|
|
for (let i = 0; i < this._osdWindows.length; i++)
|
|
|
|
this._osdWindows[i].cancel();
|
2013-03-02 04:48:25 -05:00
|
|
|
}
|
2017-10-30 21:19:44 -04:00
|
|
|
};
|