Skip to content

Instantly share code, notes, and snippets.

@JamesMcMahon
Last active October 2, 2026 04:55
Show Gist options
  • Select an option

  • Save JamesMcMahon/c815a2d9bc8117a6dbebbf2cc9b9644e to your computer and use it in GitHub Desktop.

Select an option

Save JamesMcMahon/c815a2d9bc8117a6dbebbf2cc9b9644e to your computer and use it in GitHub Desktop.
HDR Toggle for Gnome - can be assigned to shortcut and run via gjs
#!/usr/bin/gjs
const {GLib, Gio} = imports.gi;
const BUS_NAME = 'org.gnome.Mutter.DisplayConfig';
const BUS_PATH = '/org/gnome/Mutter/DisplayConfig';
const ColorMode = {SDR: 0, HDR: 1};
const PERSISTENT = 2;
const connection = Gio.bus_get_sync(Gio.BusType.SESSION, null);
const dbusCall = (method, params) =>
connection.call_sync(
BUS_NAME, BUS_PATH, BUS_NAME,
method, params, null,
Gio.DBusCallFlags.NONE, -1, null
);
const notify = message => {
Gio.Subprocess.new(
['notify-send', '-a', 'HDR Toggle', message],
Gio.SubprocessFlags.NONE
);
};
// recursiveUnpack unwraps the values inside Mutter's a{sv} dictionaries.
const [serial, monitors, displayLayouts, topLevelProps] =
dbusCall('GetCurrentState', null).recursiveUnpack();
// Mode tuples contain the ID at index 0 and properties at index 6.
const monitorsByConnector = new Map(monitors.map(([[connector], modes, props]) => {
const modeId = modes.find(mode => mode[6]['is-current'] === true)?.[0] ?? modes[0]?.[0];
return [connector, {
modeId,
colorMode: props['color-mode'] ?? ColorMode.SDR,
hdrCapable: (props['supported-color-modes'] ?? []).includes(ColorMode.HDR),
underscanning: props['underscanning'],
}];
}));
const monitorsWithoutMode = [...monitorsByConnector]
.filter(([, monitor]) => monitor.modeId == null)
.map(([connector]) => connector);
if (monitorsWithoutMode.length > 0) {
notify(`Could not determine a display mode for: ${monitorsWithoutMode.join(', ')}`);
imports.system.exit(1);
}
const hdrMonitors = [...monitorsByConnector.values()].filter(monitor => monitor.hdrCapable === true);
if (hdrMonitors.length === 0) {
notify('No HDR-capable monitors.');
imports.system.exit(1);
}
// Any non-SDR mode (including mode 2) counts as HDR being on.
const targetColorMode = hdrMonitors.some(monitor => monitor.colorMode === ColorMode.SDR)
? ColorMode.HDR
: ColorMode.SDR;
// ApplyMonitorsConfig takes per-monitor properties, unlike GetCurrentState.
const updatedLayouts = displayLayouts.map(([x, y, scale, transform, primary, displays]) =>
[x, y, scale, transform, primary, displays.map(([connector]) => {
const monitor = monitorsByConnector.get(connector);
const props = {};
if (monitor.underscanning !== undefined) {
props['underscanning'] = new GLib.Variant('b', monitor.underscanning);
}
if (monitor.hdrCapable === true) {
props['color-mode'] = new GLib.Variant('u', targetColorMode);
}
return [connector, monitor.modeId, props];
})]
);
const applyProps = {};
if (topLevelProps['layout-mode'] !== undefined) {
applyProps['layout-mode'] = new GLib.Variant('u', topLevelProps['layout-mode']);
}
dbusCall('ApplyMonitorsConfig',
new GLib.Variant('(uua(iiduba(ssa{sv}))a{sv})', [serial, PERSISTENT, updatedLayouts, applyProps])
);
const nightLight = new Gio.Settings({schema_id: 'org.gnome.settings-daemon.plugins.color'});
const stateDir = GLib.get_user_state_dir();
const nightLightMarker = GLib.build_filenamev([stateDir, 'hdr-toggle-night-light']);
if (targetColorMode === ColorMode.HDR && nightLight.get_boolean('night-light-enabled') === true) {
GLib.mkdir_with_parents(stateDir, 0o700);
GLib.file_set_contents(nightLightMarker, '');
nightLight.set_boolean('night-light-enabled', false);
} else if (targetColorMode === ColorMode.SDR &&
GLib.file_test(nightLightMarker, GLib.FileTest.EXISTS) === true) {
if (nightLight.set_boolean('night-light-enabled', true) === true) {
GLib.unlink(nightLightMarker);
}
}
notify(`HDR ${targetColorMode === ColorMode.HDR ? 'enabled' : 'disabled'}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment