breezy-desktop/gnome/src/monitormanager.js

169 lines
5.9 KiB
JavaScript

// Taken from https://github.com/jkitching/soft-brightness-plus
//
// Copyright (C) 2019, 2021 Philippe Troin (F-i-f on Github)
// Copyright (C) 2023 Joel Kitching (jkitching on Github)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
import Gio from 'gi://Gio';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import Globals from './globals.js';
let cachedDisplayConfigProxy = null;
function getDisplayConfigProxy(extPath) {
if (cachedDisplayConfigProxy == null) {
let xml = null;
const file = Gio.File.new_for_path(extPath + '/dbus-interfaces/org.gnome.Mutter.DisplayConfig.xml');
try {
const [ok, bytes] = file.load_contents(null);
if (ok) {
xml = new TextDecoder().decode(bytes);
}
} catch (e) {
Globals.logger.log('ERROR: failed to load DisplayConfig interface XML');
throw e;
}
cachedDisplayConfigProxy = Gio.DBusProxy.makeProxyWrapper(xml);
}
return cachedDisplayConfigProxy;
}
export function newDisplayConfig(extPath, callback) {
const DisplayConfigProxy = getDisplayConfigProxy(extPath);
new DisplayConfigProxy(
Gio.DBus.session,
'org.gnome.Mutter.DisplayConfig',
'/org/gnome/Mutter/DisplayConfig',
callback
);
}
export function getMonitorConfig(displayConfigProxy, callback) {
displayConfigProxy.GetResourcesRemote((result) => {
if (result.length <= 2) {
callback(null, 'Cannot get DisplayConfig: No outputs in GetResources()');
} else {
const monitors = [];
for (let i = 0; i < result[2].length; i++) {
const output = result[2][i];
if (output.length <= 7) {
callback(null, 'Cannot get DisplayConfig: No properties on output #' + i);
return;
}
const props = output[7];
const displayName = props['display-name'].get_string()[0];
const connectorName = output[4];
if (!displayName || displayName == '') {
const displayName = 'Monitor on output ' + connectorName;
}
const vendor = props['vendor'].get_string()[0];
const product = props['product'].get_string()[0];
const serial = props['serial'].get_string()[0];
// grab refresh rate from the modes array
const refreshRate = result[3][i][4];
monitors.push([displayName, connectorName, vendor, product, serial, refreshRate]);
}
callback(monitors, null);
}
});
}
// Monitor change handling
export default class MonitorManager {
constructor(extPath) {
this._extPath = extPath;
this._monitorsChangedConnection = null;
this._displayConfigProxy = null;
this._backendManager = null;
this._monitorProperties = null;
this._changeHookFn = null;
}
enable() {
this._backendManager = global.backend.get_monitor_manager();
newDisplayConfig(this._extPath, (proxy, error) => {
if (error) {
return;
}
this._displayConfigProxy = proxy;
this._on_monitors_change();
});
this._monitorsChangedConnection = Main.layoutManager.connect('monitors-changed', this._on_monitors_change.bind(this));
}
disable() {
Main.layoutManager.disconnect(this._monitorsChangedConnection);
this._monitorsChangedConnection = null;
this._displayConfigProxy = null;
this._backendManager = null;
this._monitorProperties = null;
this._changeHookFn = null;
}
setChangeHook(fn) {
this._changeHookFn = fn;
}
setPostCallback(callback) {
this._postCallback = callback;
}
getMonitors() {
return Main.layoutManager.monitors;
}
getMonitorPropertiesList() {
return this._monitorProperties;
}
_on_monitors_change() {
if (this._displayConfigProxy == null) {
return;
}
getMonitorConfig(this._displayConfigProxy, (result, error) => {
if (error) {
return;
}
const monitorProperties = [];
for (let i = 0; i < result.length; i++) {
const [monitorName, connectorName, vendor, product, serial, refreshRate] = result[i];
const monitorIndex = this._backendManager.get_monitor_for_connector(connectorName);
Globals.logger.log(`Found monitor ${monitorName}, vendor ${vendor}, product ${product}, serial ${serial}, connector ${connectorName}, index ${monitorIndex}`);
if (monitorIndex >= 0) {
monitorProperties[monitorIndex] = {
index: monitorIndex,
name: monitorName,
vendor: vendor,
product: product,
serial: serial,
connector: connectorName,
refreshRate: refreshRate
};
}
}
this._monitorProperties = monitorProperties;
if (this._changeHookFn !== null) {
this._changeHookFn();
}
});
}
}