backends: add niri

parent 2feb9cd2
......@@ -6,6 +6,7 @@
- Hyprland: чтение через `hyprctl -j monitors all`, сохранение в `~/.config/hypr/monitors.conf`.
- GNOME: чтение и применение настроек через Mutter DisplayConfig.
- niri: чтение через `niri msg -j outputs`, сохранение в `~/.config/niri/monitor.kdl`.
Backend выбирается по XDG-переменным:
......@@ -37,6 +38,18 @@ monitorv2 {
GNOME-бэкенд поддерживает обычный и зеркальный режимы, выбор основного дисплея, разрешение, масштаб, поворот, частоту обновления, VRR, underscan и доступные цветовые режимы. В зеркальном режиме отдельные настройки мониторов скрываются, а общие параметры переносятся на главную страницу.
## niri
niri-бэкенд пишет отдельный KDL-файл:
```text
~/.config/niri/monitor.kdl
```
Плагин не подключает этот файл в основной конфиг и не вызывает ручную перезагрузку niri. Поддерживаются `mode`, `scale`, `position`, `transform`, `off`, VRR, `focus-at-startup`, `hot-corners` и `backdrop-color`.
При выключении монитора остальные параметры сохраняются рядом с `off`, чтобы не терять позицию и настройки при повторном включении.
## Сборка
```sh
......
data/ui/displays-view.blp
data/ui/monitor-settings-content.blp
src/plugin.vala
src/backends/niri-backend.vala
src/core/display-model.vala
src/ui/displays-view.vala
src/ui/monitor-settings-content.vala
......
......@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: tuner-displays\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-29 23:02+0300\n"
"POT-Creation-Date: 2026-05-30 14:03+0300\n"
"PO-Revision-Date: 2026-05-28 00:00+0000\n"
"Last-Translator: Automatically generated\n"
"Language-Team: Russian\n"
......@@ -47,7 +47,7 @@ msgstr "Применить"
msgid "Monitor"
msgstr "Монитор"
#: src/core/display-model.vala:62
#: src/core/display-model.vala:65
msgid "Built-in Display"
msgstr "Встроенный дисплей"
......@@ -71,49 +71,49 @@ msgstr "Применение раскладок мониторов не подд
msgid "Mirror Displays"
msgstr "Зеркалировать мониторы"
#: src/ui/displays-view.vala:230 src/ui/monitor-settings-content.vala:86
#: src/ui/monitor-settings-content.vala:125
#: src/ui/displays-view.vala:230 src/ui/monitor-settings-content.vala:90
#: src/ui/monitor-settings-content.vala:129
msgid "Resolution"
msgstr "Разрешение"
#: src/ui/displays-view.vala:276 src/ui/monitor-settings-content.vala:263
#: src/ui/monitor-settings-content.vala:289
#: src/ui/displays-view.vala:276 src/ui/monitor-settings-content.vala:267
#: src/ui/monitor-settings-content.vala:293
msgid "Scale"
msgstr "Масштаб"
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "Normal"
msgstr "Обычный"
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "90 degrees"
msgstr "90 градусов"
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "180 degrees"
msgstr "180 градусов"
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "270 degrees"
msgstr "270 градусов"
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped"
msgstr "Отражённый"
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped 90 degrees"
msgstr "Отражённый 90 градусов"
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped 180 degrees"
msgstr "Отражённый 180 градусов"
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped 270 degrees"
msgstr "Отражённый 270 градусов"
#: src/ui/displays-view.vala:301 src/ui/monitor-settings-content.vala:313
#: src/ui/displays-view.vala:301 src/ui/monitor-settings-content.vala:317
msgid "Rotation"
msgstr "Поворот"
......@@ -121,136 +121,180 @@ msgstr "Поворот"
msgid "Primary Display"
msgstr "Основной дисплей"
#: src/ui/monitor-settings-content.vala:154
#: src/ui/monitor-settings-content.vala:162
#: src/ui/monitor-settings-content.vala:158
#: src/ui/monitor-settings-content.vala:166
msgid "Refresh Rate"
msgstr "Частота обновления"
#: src/ui/monitor-settings-content.vala:184
#: src/ui/monitor-settings-content.vala:188
#: src/ui/monitor-settings-content.vala:404
msgid "Variable Refresh Rate"
msgstr "Переменная частота обновления"
#: src/ui/monitor-settings-content.vala:333
#: src/ui/monitor-settings-content.vala:337
msgid "None"
msgstr "Нет"
#: src/ui/monitor-settings-content.vala:348
#: src/ui/monitor-settings-content.vala:352
msgid "Mirror"
msgstr "Зеркалирование"
#: src/ui/monitor-settings-content.vala:364
#: src/ui/monitor-settings-content.vala:368
msgid "Use description"
msgstr "Использовать описание"
#: src/ui/monitor-settings-content.vala:373
#: src/ui/monitor-settings-content.vala:377
msgid "Bit depth"
msgstr "Глубина цвета"
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:378
msgid "VRR"
msgstr "VRR"
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:378
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:385
#: src/ui/monitor-settings-content.vala:405
#: src/ui/monitor-settings-content.vala:429
msgid "Off"
msgstr "Отключено"
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:378
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:385
#: src/ui/monitor-settings-content.vala:405
msgid "On"
msgstr "Включено"
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:378
msgid "Fullscreen"
msgstr "Полный экран"
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:378
msgid "Fullscreen video/game"
msgstr "Полноэкранное видео/игра"
#: src/ui/monitor-settings-content.vala:375
#: src/ui/monitor-settings-content.vala:379
msgid "Color management"
msgstr "Управление цветом"
#: src/ui/monitor-settings-content.vala:376
#: src/ui/monitor-settings-content.vala:380
msgid "SDR EOTF"
msgstr "SDR EOTF"
#: src/ui/monitor-settings-content.vala:377
#: src/ui/monitor-settings-content.vala:381
msgid "SDR brightness"
msgstr "Яркость SDR"
#: src/ui/monitor-settings-content.vala:378
#: src/ui/monitor-settings-content.vala:382
msgid "SDR saturation"
msgstr "Насыщенность SDR"
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:384
msgid "Force wide color"
msgstr "Принудительно широкий цветовой охват"
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:385
msgid "Auto"
msgstr "Авто"
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:385
msgid "Force HDR"
msgstr "Принудительно HDR"
#: src/ui/monitor-settings-content.vala:382
#: src/ui/monitor-settings-content.vala:386
msgid "SDR min luminance"
msgstr "Мин. яркость SDR"
#: src/ui/monitor-settings-content.vala:383
#: src/ui/monitor-settings-content.vala:387
msgid "SDR max luminance"
msgstr "Макс. яркость SDR"
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:388
msgid "Min luminance"
msgstr "Мин. яркость"
#: src/ui/monitor-settings-content.vala:385
#: src/ui/monitor-settings-content.vala:389
msgid "Max luminance"
msgstr "Макс. яркость"
#: src/ui/monitor-settings-content.vala:386
#: src/ui/monitor-settings-content.vala:390
msgid "Max average luminance"
msgstr "Макс. средняя яркость"
#: src/ui/monitor-settings-content.vala:389
#: src/ui/monitor-settings-content.vala:393
msgid "ICC profile"
msgstr "Профиль ICC"
#: src/ui/monitor-settings-content.vala:401
#: src/ui/monitor-settings-content.vala:405
msgid "On demand"
msgstr "По требованию"
#: src/ui/monitor-settings-content.vala:409
msgid "Focus at startup"
msgstr "Фокус при запуске"
#: src/ui/monitor-settings-content.vala:419
msgid "Backdrop color"
msgstr "Цвет фона"
#: src/ui/monitor-settings-content.vala:428
msgid "Hot corners"
msgstr "Активные углы"
#: src/ui/monitor-settings-content.vala:429
msgid "Default"
msgstr "По умолчанию"
#: src/ui/monitor-settings-content.vala:429
msgid "All"
msgstr "Все"
#: src/ui/monitor-settings-content.vala:429
msgid "Top left"
msgstr "Сверху слева"
#: src/ui/monitor-settings-content.vala:429
msgid "Top right"
msgstr "Сверху справа"
#: src/ui/monitor-settings-content.vala:429
msgid "Bottom left"
msgstr "Снизу слева"
#: src/ui/monitor-settings-content.vala:429
msgid "Bottom right"
msgstr "Снизу справа"
#: src/ui/monitor-settings-content.vala:437
msgid "Underscanning"
msgstr "Underscan"
#: src/ui/monitor-settings-content.vala:412
#: src/ui/monitor-settings-content.vala:448
msgid "HDR"
msgstr "HDR"
#: src/ui/monitor-settings-content.vala:571
#: src/ui/monitor-settings-content.vala:611
#, c-format
msgid "Variable (up to %.2f Hz)"
msgstr "Переменная (до %.2f Гц)"
#: src/ui/monitor-settings-content.vala:572
#: src/ui/monitor-settings-content.vala:612
msgid "Variable"
msgstr "Переменная"
#: src/ui/monitor-settings-content.vala:575 src/ui/ui-helpers.vala:50
#: src/ui/monitor-settings-content.vala:615 src/ui/ui-helpers.vala:50
#, c-format
msgid "%.2f Hz"
msgstr "%.2f Гц"
#~ msgid "Max BPC"
#~ msgstr "Макс. BPC"
#~ msgid "Color Mode"
#~ msgstr "Цветовой режим"
#~ msgid "Default"
#~ msgstr "По умолчанию"
#, c-format
#~ msgid "Mode %d"
#~ msgstr "Режим %d"
......@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: tuner-displays\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-05-29 23:02+0300\n"
"POT-Creation-Date: 2026-05-30 14:03+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
......@@ -53,7 +53,7 @@ msgstr ""
msgid "Monitor"
msgstr ""
#: src/core/display-model.vala:62
#: src/core/display-model.vala:65
msgid "Built-in Display"
msgstr ""
......@@ -77,49 +77,49 @@ msgstr ""
msgid "Mirror Displays"
msgstr ""
#: src/ui/displays-view.vala:230 src/ui/monitor-settings-content.vala:86
#: src/ui/monitor-settings-content.vala:125
#: src/ui/displays-view.vala:230 src/ui/monitor-settings-content.vala:90
#: src/ui/monitor-settings-content.vala:129
msgid "Resolution"
msgstr ""
#: src/ui/displays-view.vala:276 src/ui/monitor-settings-content.vala:263
#: src/ui/monitor-settings-content.vala:289
#: src/ui/displays-view.vala:276 src/ui/monitor-settings-content.vala:267
#: src/ui/monitor-settings-content.vala:293
msgid "Scale"
msgstr ""
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "Normal"
msgstr ""
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "90 degrees"
msgstr ""
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "180 degrees"
msgstr ""
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:306
#: src/ui/displays-view.vala:294 src/ui/monitor-settings-content.vala:310
msgid "270 degrees"
msgstr ""
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped"
msgstr ""
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped 90 degrees"
msgstr ""
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped 180 degrees"
msgstr ""
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:307
#: src/ui/displays-view.vala:295 src/ui/monitor-settings-content.vala:311
msgid "Flipped 270 degrees"
msgstr ""
#: src/ui/displays-view.vala:301 src/ui/monitor-settings-content.vala:313
#: src/ui/displays-view.vala:301 src/ui/monitor-settings-content.vala:317
msgid "Rotation"
msgstr ""
......@@ -127,126 +127,170 @@ msgstr ""
msgid "Primary Display"
msgstr ""
#: src/ui/monitor-settings-content.vala:154
#: src/ui/monitor-settings-content.vala:162
#: src/ui/monitor-settings-content.vala:158
#: src/ui/monitor-settings-content.vala:166
msgid "Refresh Rate"
msgstr ""
#: src/ui/monitor-settings-content.vala:184
#: src/ui/monitor-settings-content.vala:188
#: src/ui/monitor-settings-content.vala:404
msgid "Variable Refresh Rate"
msgstr ""
#: src/ui/monitor-settings-content.vala:333
#: src/ui/monitor-settings-content.vala:337
msgid "None"
msgstr ""
#: src/ui/monitor-settings-content.vala:348
#: src/ui/monitor-settings-content.vala:352
msgid "Mirror"
msgstr ""
#: src/ui/monitor-settings-content.vala:364
#: src/ui/monitor-settings-content.vala:368
msgid "Use description"
msgstr ""
#: src/ui/monitor-settings-content.vala:373
#: src/ui/monitor-settings-content.vala:377
msgid "Bit depth"
msgstr ""
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:378
msgid "VRR"
msgstr ""
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:378
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:385
#: src/ui/monitor-settings-content.vala:405
#: src/ui/monitor-settings-content.vala:429
msgid "Off"
msgstr ""
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:378
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:385
#: src/ui/monitor-settings-content.vala:405
msgid "On"
msgstr ""
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:378
msgid "Fullscreen"
msgstr ""
#: src/ui/monitor-settings-content.vala:374
#: src/ui/monitor-settings-content.vala:378
msgid "Fullscreen video/game"
msgstr ""
#: src/ui/monitor-settings-content.vala:375
#: src/ui/monitor-settings-content.vala:379
msgid "Color management"
msgstr ""
#: src/ui/monitor-settings-content.vala:376
#: src/ui/monitor-settings-content.vala:380
msgid "SDR EOTF"
msgstr ""
#: src/ui/monitor-settings-content.vala:377
#: src/ui/monitor-settings-content.vala:381
msgid "SDR brightness"
msgstr ""
#: src/ui/monitor-settings-content.vala:378
#: src/ui/monitor-settings-content.vala:382
msgid "SDR saturation"
msgstr ""
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:384
msgid "Force wide color"
msgstr ""
#: src/ui/monitor-settings-content.vala:380
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:385
msgid "Auto"
msgstr ""
#: src/ui/monitor-settings-content.vala:381
#: src/ui/monitor-settings-content.vala:385
msgid "Force HDR"
msgstr ""
#: src/ui/monitor-settings-content.vala:382
#: src/ui/monitor-settings-content.vala:386
msgid "SDR min luminance"
msgstr ""
#: src/ui/monitor-settings-content.vala:383
#: src/ui/monitor-settings-content.vala:387
msgid "SDR max luminance"
msgstr ""
#: src/ui/monitor-settings-content.vala:384
#: src/ui/monitor-settings-content.vala:388
msgid "Min luminance"
msgstr ""
#: src/ui/monitor-settings-content.vala:385
#: src/ui/monitor-settings-content.vala:389
msgid "Max luminance"
msgstr ""
#: src/ui/monitor-settings-content.vala:386
#: src/ui/monitor-settings-content.vala:390
msgid "Max average luminance"
msgstr ""
#: src/ui/monitor-settings-content.vala:389
#: src/ui/monitor-settings-content.vala:393
msgid "ICC profile"
msgstr ""
#: src/ui/monitor-settings-content.vala:401
#: src/ui/monitor-settings-content.vala:405
msgid "On demand"
msgstr ""
#: src/ui/monitor-settings-content.vala:409
msgid "Focus at startup"
msgstr ""
#: src/ui/monitor-settings-content.vala:419
msgid "Backdrop color"
msgstr ""
#: src/ui/monitor-settings-content.vala:428
msgid "Hot corners"
msgstr ""
#: src/ui/monitor-settings-content.vala:429
msgid "Default"
msgstr ""
#: src/ui/monitor-settings-content.vala:429
msgid "All"
msgstr ""
#: src/ui/monitor-settings-content.vala:429
msgid "Top left"
msgstr ""
#: src/ui/monitor-settings-content.vala:429
msgid "Top right"
msgstr ""
#: src/ui/monitor-settings-content.vala:429
msgid "Bottom left"
msgstr ""
#: src/ui/monitor-settings-content.vala:429
msgid "Bottom right"
msgstr ""
#: src/ui/monitor-settings-content.vala:437
msgid "Underscanning"
msgstr ""
#: src/ui/monitor-settings-content.vala:412
#: src/ui/monitor-settings-content.vala:448
msgid "HDR"
msgstr ""
#: src/ui/monitor-settings-content.vala:571
#: src/ui/monitor-settings-content.vala:611
#, c-format
msgid "Variable (up to %.2f Hz)"
msgstr ""
#: src/ui/monitor-settings-content.vala:572
#: src/ui/monitor-settings-content.vala:612
msgid "Variable"
msgstr ""
#: src/ui/monitor-settings-content.vala:575 src/ui/ui-helpers.vala:50
#: src/ui/monitor-settings-content.vala:615 src/ui/ui-helpers.vala:50
#, c-format
msgid "%.2f Hz"
msgstr ""
......@@ -15,11 +15,76 @@ namespace TunerDisplays {
public abstract Gee.ArrayList<MonitorConfig> load() throws Error;
public abstract void apply(Gee.ArrayList<MonitorConfig> monitors) throws Error;
protected static Json.Node backend_parse_json(string text) throws Error {
var parser = new Json.Parser();
parser.load_from_data(text);
return parser.get_root();
}
protected static string backend_get_string(Json.Object obj, string name, string fallback = "") {
return obj.has_member(name) && !obj.get_member(name).is_null() ? obj.get_string_member(name) : fallback;
}
protected static Json.Object? backend_get_object_or_null(Json.Object obj, string name) {
return obj.has_member(name) && !obj.get_member(name).is_null() ? obj.get_object_member(name) : null;
}
protected static bool backend_is_null_member(Json.Object obj, string name) {
return !obj.has_member(name) || obj.get_member(name).is_null();
}
protected static double backend_get_double(Json.Object obj, string name, double fallback) {
return obj.has_member(name) && !obj.get_member(name).is_null() ? obj.get_double_member(name) : fallback;
}
protected static bool backend_get_bool(Json.Object obj, string name, bool fallback) {
return obj.has_member(name) && !obj.get_member(name).is_null() ? obj.get_boolean_member(name) : fallback;
}
protected static void backend_apply_mode(MonitorConfig monitor, DisplayMode mode) {
monitor.width = mode.width;
monitor.height = mode.height;
monitor.refresh = mode.refresh;
}
protected static void backend_apply_first_available_mode(MonitorConfig monitor) {
if (monitor.modes.size > 0)
backend_apply_mode(monitor, monitor.modes[0]);
}
protected static double backend_logical_width(MonitorConfig monitor) {
if (monitor.scale <= 0)
return monitor.width;
return backend_is_rotated(monitor) ? monitor.height / monitor.scale : monitor.width / monitor.scale;
}
protected static double backend_logical_height(MonitorConfig monitor) {
if (monitor.scale <= 0)
return monitor.height;
return backend_is_rotated(monitor) ? monitor.width / monitor.scale : monitor.height / monitor.scale;
}
protected static bool backend_is_rotated(MonitorConfig monitor) {
return monitor.transform.index_of("90") >= 0 || monitor.transform.index_of("270") >= 0;
}
protected static string backend_format_double(double value, int precision = 2) {
return ("%." + precision.to_string() + "f").printf(value).replace(",", ".");
}
protected static string backend_escape_quoted_string(string value) {
return value.replace("\\", "\\\\").replace("\"", "\\\"");
}
public static DisplayBackend create_for_session() {
var desktop = (Environment.get_variable("XDG_CURRENT_DESKTOP") ?? "").down();
var session = (Environment.get_variable("XDG_SESSION_DESKTOP") ?? "").down();
var detected = desktop != "" ? desktop : session;
if ("niri" in detected) {
return new NiriBackend();
}
if ("hyprland" in detected) {
return new HyprlandBackend();
}
......
......@@ -54,6 +54,10 @@ namespace TunerDisplays {
public bool variable_refresh_rate { get; set; }
public Gee.ArrayList<int> supported_color_modes { get; private set; default = new Gee.ArrayList<int>(); }
public bool dpms { get; set; default = true; }
public bool niri_focus_at_startup { get; set; }
public string niri_backdrop_color { get; set; default = ""; }
public string niri_hot_corners { get; set; default = ""; }
public bool niri_has_saved_position { get; set; }
public Gee.ArrayList<DisplayMode> modes { get; private set; default = new Gee.ArrayList<DisplayMode>(); }
public string display_name {
......
......@@ -9,6 +9,7 @@ sources = files(
'backends/display-backend.vala',
'backends/gnome-backend.vala',
'backends/hyprland-backend.vala',
'backends/niri-backend.vala',
'core/display-model.vala',
'core/shell-command.vala',
'ui/displays-view.vala',
......
......@@ -144,7 +144,7 @@ namespace TunerDisplays {
} else {
add_gnome_primary_row();
foreach (var monitor in monitors) {
var row = new MonitorRow(monitor, monitor_settings_page_id(), monitors);
var row = new MonitorRow(monitor, monitor_settings_page_id(), monitors, backend.id);
row.monitor_selected.connect(monitor => monitor_settings_requested(monitor));
row.monitor_changed.connect(() => layout.recenter());
monitors_group.add(row);
......@@ -541,6 +541,10 @@ namespace TunerDisplays {
target.supports_variable_refresh_rate = source.supports_variable_refresh_rate;
target.variable_refresh_rate = source.variable_refresh_rate;
target.dpms = source.dpms;
target.niri_focus_at_startup = source.niri_focus_at_startup;
target.niri_backdrop_color = source.niri_backdrop_color;
target.niri_hot_corners = source.niri_hot_corners;
target.niri_has_saved_position = source.niri_has_saved_position;
target.modes.clear();
foreach (var mode in source.modes)
......
......@@ -4,12 +4,13 @@ namespace TunerDisplays {
private MonitorConfig monitor;
private Gee.ArrayList<MonitorConfig> all_monitors;
private string page_id;
private string backend_id;
private Gtk.Switch enabled_switch;
public signal void monitor_changed();
public signal void monitor_selected(MonitorConfig monitor);
public MonitorRow(MonitorConfig monitor, string page_id, Gee.ArrayList<MonitorConfig> all_monitors) {
public MonitorRow(MonitorConfig monitor, string page_id, Gee.ArrayList<MonitorConfig> all_monitors, string backend_id) {
Object(
title: monitor.title,
subtitle: "%dx%d@%.2f scale %.2f %dx%d".printf(
......@@ -19,6 +20,7 @@ namespace TunerDisplays {
this.monitor = monitor;
this.all_monitors = all_monitors;
this.page_id = page_id;
this.backend_id = backend_id;
build();
}
......@@ -36,7 +38,7 @@ namespace TunerDisplays {
can_focus = true
};
enabled_switch.notify["active"].connect(() => {
if (enabled_switch.active != monitor.enabled)
if (enabled_switch.active != monitor.enabled && backend_id != "niri")
place_monitor_after_active(monitor, all_monitors);
monitor.enabled = enabled_switch.active;
monitor_changed();
......
......@@ -32,7 +32,7 @@ namespace TunerDisplays {
enabled_row.visible = show_enabled;
enabled_row.active = monitor.enabled;
enabled_row.notify["active"].connect(() => {
if (enabled_row.active != monitor.enabled)
if (enabled_row.active != monitor.enabled && backend_id != "niri")
place_monitor_after_active(monitor, all_monitors);
monitor.enabled = enabled_row.active;
emit_changed();
......@@ -52,6 +52,10 @@ namespace TunerDisplays {
if (backend_id == "hyprland") {
add_hyprland_rows();
} else if (backend_id == "niri") {
add_niri_rows(basic_group);
hyprland_group.visible = false;
hdr_group.visible = false;
} else if (backend_id == "gnome") {
add_gnome_rows(basic_group);
hyprland_group.visible = false;
......@@ -396,6 +400,72 @@ namespace TunerDisplays {
hdr_group.add(icc);
}
private void add_niri_rows(Adw.PreferencesGroup group) {
if (monitor.supports_variable_refresh_rate) {
add_int_combo(group, _("Variable Refresh Rate"), new string[] {
_("Off"), _("On"), _("On demand")
}, new int[] { 0, 1, 2 }, monitor.vrr, value => monitor.vrr = value);
}
var focus = new Adw.SwitchRow() {
title = _("Focus at startup"),
active = monitor.niri_focus_at_startup
};
focus.notify["active"].connect(() => {
monitor.niri_focus_at_startup = focus.active;
emit_changed();
});
group.add(focus);
add_niri_backdrop_color_row(group);
add_string_combo_with_labels(group, _("Hot corners"), new string[] {
_("Default"), _("Off"), _("All"), _("Top left"), _("Top right"), _("Bottom left"), _("Bottom right")
}, new string[] {
"", "off", "all", "top-left", "top-right", "bottom-left", "bottom-right"
}, monitor.niri_hot_corners, value => monitor.niri_hot_corners = value);
}
private void add_niri_backdrop_color_row(Adw.PreferencesGroup group) {
var row = new Adw.ActionRow() {
title = _("Backdrop color")
};
var enabled = new Gtk.Switch() {
valign = Gtk.Align.CENTER,
active = monitor.niri_backdrop_color != ""
};
Gdk.RGBA color = { 0, 0, 0, 1 };
if (monitor.niri_backdrop_color != "")
color.parse(monitor.niri_backdrop_color);
var button = new Gtk.ColorButton.with_rgba(color) {
valign = Gtk.Align.CENTER,
sensitive = enabled.active,
title = _("Backdrop color"),
use_alpha = true
};
enabled.notify["active"].connect(() => {
button.sensitive = enabled.active;
var selected = button.rgba;
monitor.niri_backdrop_color = enabled.active ? rgba_to_css(selected) : "";
emit_changed();
});
button.notify["rgba"].connect(() => {
if (!enabled.active)
return;
var selected = button.rgba;
monitor.niri_backdrop_color = rgba_to_css(selected);
emit_changed();
});
row.add_suffix(button);
row.add_suffix(enabled);
group.add(row);
}
private void add_gnome_rows(Adw.PreferencesGroup group) {
var underscanning = new Adw.SwitchRow() {
title = _("Underscanning"),
......@@ -468,11 +538,15 @@ namespace TunerDisplays {
}
private void add_string_combo(Adw.PreferencesGroup group, string title, string[] values, string current, StringChanged changed) {
add_string_combo_with_labels(group, title, values, values, current, changed);
}
private void add_string_combo_with_labels(Adw.PreferencesGroup group, string title, string[] labels, string[] values, string current, StringChanged changed) {
var model = new Gtk.StringList(null);
var stored_values = new Gee.ArrayList<string>();
uint selected = 0;
for (int i = 0; i < values.length; i++) {
model.append(values[i]);
model.append(labels[i]);
stored_values.add(values[i]);
if (values[i] == current)
selected = i;
......@@ -493,6 +567,24 @@ namespace TunerDisplays {
group.add(row);
}
private static string rgba_to_css(Gdk.RGBA rgba) {
if (rgba.alpha >= 0.999) {
return "#%02x%02x%02x".printf(
(int) Math.round(rgba.red * 255),
(int) Math.round(rgba.green * 255),
(int) Math.round(rgba.blue * 255)
);
}
var alpha = "%.3f".printf(rgba.alpha).replace(",", ".");
return "rgba(%d, %d, %d, %s)".printf(
(int) Math.round(rgba.red * 255),
(int) Math.round(rgba.green * 255),
(int) Math.round(rgba.blue * 255),
alpha
);
}
private void emit_changed() {
monitor_changed();
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment