Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
tuner-displays
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ximper Linux
tuner-displays
Commits
355bd1d9
Verified
Commit
355bd1d9
authored
Jun 15, 2026
by
Kirill Unitsaev
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
displays: add monitor config include prompt
parent
18cf5dd4
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
420 additions
and
42 deletions
+420
-42
displays-view.blp
data/ui/displays-view.blp
+13
-0
ru.po
po/ru.po
+51
-21
tuner-displays.pot
po/tuner-displays.pot
+51
-21
display-backend.vala
src/backends/display-backend.vala
+104
-0
hyprland-backend.vala
src/backends/hyprland-backend.vala
+62
-0
niri-backend.vala
src/backends/niri-backend.vala
+57
-0
meson.build
src/meson.build
+1
-0
config-include-validator.vala
src/ui/config-include-validator.vala
+59
-0
displays-view.vala
src/ui/displays-view.vala
+22
-0
No files found.
data/ui/displays-view.blp
View file @
355bd1d9
...
@@ -7,6 +7,19 @@ template $TunerDisplaysDisplaysView : Adw.PreferencesPage {
...
@@ -7,6 +7,19 @@ template $TunerDisplaysDisplaysView : Adw.PreferencesPage {
title: _("Displays");
title: _("Displays");
icon-name: "video-display-symbolic";
icon-name: "video-display-symbolic";
Adw.PreferencesGroup config_include_group {
Adw.ActionRow config_include_row {
visible: false;
title: _("Monitor configuration is not connected");
[suffix]
Button config_include_button {
valign: center;
label: _("Connect");
}
}
}
Adw.PreferencesGroup status_group {}
Adw.PreferencesGroup status_group {}
Adw.PreferencesGroup layout_group {}
Adw.PreferencesGroup layout_group {}
...
...
po/ru.po
View file @
355bd1d9
...
@@ -2,7 +2,7 @@ msgid ""
...
@@ -2,7 +2,7 @@ msgid ""
msgstr ""
msgstr ""
"Project-Id-Version: tuner-displays\n"
"Project-Id-Version: tuner-displays\n"
"Report-Msgid-Bugs-To: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-0
5-31 21:4
8+0300\n"
"POT-Creation-Date: 2026-0
6-15 11:5
8+0300\n"
"PO-Revision-Date: 2026-05-28 00:00+0000\n"
"PO-Revision-Date: 2026-05-28 00:00+0000\n"
"Last-Translator: Automatically generated\n"
"Last-Translator: Automatically generated\n"
"Language-Team: Russian\n"
"Language-Team: Russian\n"
...
@@ -15,7 +15,17 @@ msgstr ""
...
@@ -15,7 +15,17 @@ msgstr ""
msgid "Displays"
msgid "Displays"
msgstr "Мониторы"
msgstr "Мониторы"
#: data/ui/displays-view.blp:15
#: data/ui/displays-view.blp:13 src/backends/hyprland-backend.vala:40
#: src/backends/hyprland-backend.vala:55 src/backends/niri-backend.vala:46
#: src/backends/niri-backend.vala:61
msgid "Monitor configuration is not connected"
msgstr "Конфигурация мониторов не подключена"
#: data/ui/displays-view.blp:18
msgid "Connect"
msgstr "Подключить"
#: data/ui/displays-view.blp:28
msgid "Details"
msgid "Details"
msgstr "Параметры"
msgstr "Параметры"
...
@@ -55,11 +65,27 @@ msgstr "Нет включённых мониторов для зеркалиро
...
@@ -55,11 +65,27 @@ msgstr "Нет включённых мониторов для зеркалиро
msgid "No common mirror mode is available"
msgid "No common mirror mode is available"
msgstr "Нет общего режима для зеркалирования"
msgstr "Нет общего режима для зеркалирования"
#: src/backends/hyprland-backend.vala:39
#: src/backends/hyprland-backend.vala:41
msgid "Hyprland configuration file was not found."
msgstr "Файл конфигурации Hyprland не найден."
#: src/backends/hyprland-backend.vala:56
msgid "Add monitors.conf to the Hyprland configuration."
msgstr "Добавьте monitors.conf в конфигурацию Hyprland."
#: src/backends/hyprland-backend.vala:80
msgid "hyprctl monitors all returned non-array JSON"
msgid "hyprctl monitors all returned non-array JSON"
msgstr "hyprctl monitors all вернул JSON не в виде массива"
msgstr "hyprctl monitors all вернул JSON не в виде массива"
#: src/backends/niri-backend.vala:44
#: src/backends/niri-backend.vala:47
msgid "niri configuration file was not found."
msgstr "Файл конфигурации niri не найден."
#: src/backends/niri-backend.vala:62
msgid "Add monitor.kdl to the niri configuration."
msgstr "Добавьте monitor.kdl в конфигурацию niri."
#: src/backends/niri-backend.vala:85
msgid "niri msg outputs returned non-object JSON"
msgid "niri msg outputs returned non-object JSON"
msgstr "niri msg outputs вернул JSON не в виде объекта"
msgstr "niri msg outputs вернул JSON не в виде объекта"
...
@@ -67,73 +93,77 @@ msgstr "niri msg outputs вернул JSON не в виде объекта"
...
@@ -67,73 +93,77 @@ msgstr "niri msg outputs вернул JSON не в виде объекта"
msgid "Built-in Display"
msgid "Built-in Display"
msgstr "Встроенный дисплей"
msgstr "Встроенный дисплей"
#: src/ui/displays-view.vala:
68
#: src/ui/displays-view.vala:
72
msgid "Failed to load monitors"
msgid "Failed to load monitors"
msgstr "Не удалось загрузить мониторы"
msgstr "Не удалось загрузить мониторы"
#: src/ui/displays-view.vala:
77
#: src/ui/displays-view.vala:
81
msgid "Monitor settings applied"
msgid "Monitor settings applied"
msgstr "Настройки мониторов применены"
msgstr "Настройки мониторов применены"
#: src/ui/displays-view.vala:16
0
#: src/ui/displays-view.vala:16
5
msgid "Read-only backend"
msgid "Read-only backend"
msgstr "Режим только для чтения"
msgstr "Режим только для чтения"
#: src/ui/displays-view.vala:16
1
#: src/ui/displays-view.vala:16
6
msgid "Applying monitor layouts is not supported by this backend."
msgid "Applying monitor layouts is not supported by this backend."
msgstr "Применение раскладок мониторов не поддерживается этим бэкендом."
msgstr "Применение раскладок мониторов не поддерживается этим бэкендом."
#: src/ui/displays-view.vala:171
#: src/ui/displays-view.vala:189
msgid "Monitor configuration connected"
msgstr "Конфигурация мониторов подключена"
#: src/ui/displays-view.vala:201
msgid "Mirror Displays"
msgid "Mirror Displays"
msgstr "Зеркалировать мониторы"
msgstr "Зеркалировать мониторы"
#: src/ui/displays-view.vala:2
3
1 src/ui/monitor-settings-content.vala:88
#: src/ui/displays-view.vala:2
6
1 src/ui/monitor-settings-content.vala:88
#: src/ui/monitor-settings-content.vala:127
#: src/ui/monitor-settings-content.vala:127
msgid "Resolution"
msgid "Resolution"
msgstr "Разрешение"
msgstr "Разрешение"
#: src/ui/displays-view.vala:
27
7 src/ui/monitor-settings-content.vala:265
#: src/ui/displays-view.vala:
30
7 src/ui/monitor-settings-content.vala:265
#: src/ui/monitor-settings-content.vala:291
#: src/ui/monitor-settings-content.vala:291
msgid "Scale"
msgid "Scale"
msgstr "Масштаб"
msgstr "Масштаб"
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "Normal"
msgid "Normal"
msgstr "Обычный"
msgstr "Обычный"
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "90 degrees"
msgid "90 degrees"
msgstr "90 градусов"
msgstr "90 градусов"
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "180 degrees"
msgid "180 degrees"
msgstr "180 градусов"
msgstr "180 градусов"
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "270 degrees"
msgid "270 degrees"
msgstr "270 градусов"
msgstr "270 градусов"
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped"
msgid "Flipped"
msgstr "Отражённый"
msgstr "Отражённый"
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped 90 degrees"
msgid "Flipped 90 degrees"
msgstr "Отражённый 90 градусов"
msgstr "Отражённый 90 градусов"
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped 180 degrees"
msgid "Flipped 180 degrees"
msgstr "Отражённый 180 градусов"
msgstr "Отражённый 180 градусов"
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped 270 degrees"
msgid "Flipped 270 degrees"
msgstr "Отражённый 270 градусов"
msgstr "Отражённый 270 градусов"
#: src/ui/displays-view.vala:3
0
2 src/ui/monitor-settings-content.vala:315
#: src/ui/displays-view.vala:3
3
2 src/ui/monitor-settings-content.vala:315
msgid "Rotation"
msgid "Rotation"
msgstr "Поворот"
msgstr "Поворот"
#: src/ui/displays-view.vala:3
3
5
#: src/ui/displays-view.vala:3
6
5
msgid "Primary Display"
msgid "Primary Display"
msgstr "Основной дисплей"
msgstr "Основной дисплей"
...
...
po/tuner-displays.pot
View file @
355bd1d9
...
@@ -8,7 +8,7 @@ msgid ""
...
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
msgstr ""
"Project-Id-Version: tuner-displays\n"
"Project-Id-Version: tuner-displays\n"
"Report-Msgid-Bugs-To: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-0
5-31 21:4
8+0300\n"
"POT-Creation-Date: 2026-0
6-15 11:5
8+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
...
@@ -21,7 +21,17 @@ msgstr ""
...
@@ -21,7 +21,17 @@ msgstr ""
msgid "Displays"
msgid "Displays"
msgstr ""
msgstr ""
#: data/ui/displays-view.blp:15
#: data/ui/displays-view.blp:13 src/backends/hyprland-backend.vala:40
#: src/backends/hyprland-backend.vala:55 src/backends/niri-backend.vala:46
#: src/backends/niri-backend.vala:61
msgid "Monitor configuration is not connected"
msgstr ""
#: data/ui/displays-view.blp:18
msgid "Connect"
msgstr ""
#: data/ui/displays-view.blp:28
msgid "Details"
msgid "Details"
msgstr ""
msgstr ""
...
@@ -61,11 +71,27 @@ msgstr ""
...
@@ -61,11 +71,27 @@ msgstr ""
msgid "No common mirror mode is available"
msgid "No common mirror mode is available"
msgstr ""
msgstr ""
#: src/backends/hyprland-backend.vala:39
#: src/backends/hyprland-backend.vala:41
msgid "Hyprland configuration file was not found."
msgstr ""
#: src/backends/hyprland-backend.vala:56
msgid "Add monitors.conf to the Hyprland configuration."
msgstr ""
#: src/backends/hyprland-backend.vala:80
msgid "hyprctl monitors all returned non-array JSON"
msgid "hyprctl monitors all returned non-array JSON"
msgstr ""
msgstr ""
#: src/backends/niri-backend.vala:44
#: src/backends/niri-backend.vala:47
msgid "niri configuration file was not found."
msgstr ""
#: src/backends/niri-backend.vala:62
msgid "Add monitor.kdl to the niri configuration."
msgstr ""
#: src/backends/niri-backend.vala:85
msgid "niri msg outputs returned non-object JSON"
msgid "niri msg outputs returned non-object JSON"
msgstr ""
msgstr ""
...
@@ -73,73 +99,77 @@ msgstr ""
...
@@ -73,73 +99,77 @@ msgstr ""
msgid "Built-in Display"
msgid "Built-in Display"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
68
#: src/ui/displays-view.vala:
72
msgid "Failed to load monitors"
msgid "Failed to load monitors"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
77
#: src/ui/displays-view.vala:
81
msgid "Monitor settings applied"
msgid "Monitor settings applied"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:16
0
#: src/ui/displays-view.vala:16
5
msgid "Read-only backend"
msgid "Read-only backend"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:16
1
#: src/ui/displays-view.vala:16
6
msgid "Applying monitor layouts is not supported by this backend."
msgid "Applying monitor layouts is not supported by this backend."
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:171
#: src/ui/displays-view.vala:189
msgid "Monitor configuration connected"
msgstr ""
#: src/ui/displays-view.vala:201
msgid "Mirror Displays"
msgid "Mirror Displays"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:2
3
1 src/ui/monitor-settings-content.vala:88
#: src/ui/displays-view.vala:2
6
1 src/ui/monitor-settings-content.vala:88
#: src/ui/monitor-settings-content.vala:127
#: src/ui/monitor-settings-content.vala:127
msgid "Resolution"
msgid "Resolution"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
27
7 src/ui/monitor-settings-content.vala:265
#: src/ui/displays-view.vala:
30
7 src/ui/monitor-settings-content.vala:265
#: src/ui/monitor-settings-content.vala:291
#: src/ui/monitor-settings-content.vala:291
msgid "Scale"
msgid "Scale"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "Normal"
msgid "Normal"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "90 degrees"
msgid "90 degrees"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "180 degrees"
msgid "180 degrees"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
5 src/ui/monitor-settings-content.vala:308
#: src/ui/displays-view.vala:
32
5 src/ui/monitor-settings-content.vala:308
msgid "270 degrees"
msgid "270 degrees"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped"
msgid "Flipped"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped 90 degrees"
msgid "Flipped 90 degrees"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped 180 degrees"
msgid "Flipped 180 degrees"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:
29
6 src/ui/monitor-settings-content.vala:309
#: src/ui/displays-view.vala:
32
6 src/ui/monitor-settings-content.vala:309
msgid "Flipped 270 degrees"
msgid "Flipped 270 degrees"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:3
0
2 src/ui/monitor-settings-content.vala:315
#: src/ui/displays-view.vala:3
3
2 src/ui/monitor-settings-content.vala:315
msgid "Rotation"
msgid "Rotation"
msgstr ""
msgstr ""
#: src/ui/displays-view.vala:3
3
5
#: src/ui/displays-view.vala:3
6
5
msgid "Primary Display"
msgid "Primary Display"
msgstr ""
msgstr ""
...
...
src/backends/display-backend.vala
View file @
355bd1d9
...
@@ -7,7 +7,23 @@ namespace TunerDisplays {
...
@@ -7,7 +7,23 @@ namespace TunerDisplays {
APPLY_FAILED
APPLY_FAILED
}
}
public
enum
ConfigIncludeState
{
NOT_NEEDED
,
INCLUDED
,
NOT_INCLUDED
,
MISSING_MAIN_CONFIG
,
UNSUPPORTED
}
public
class
ConfigIncludeInfo
:
Object
{
public
ConfigIncludeState
state
{
get
;
set
;
default
=
ConfigIncludeState
.
NOT_NEEDED
;
}
public
string
title
{
get
;
set
;
default
=
""
;
}
public
string
subtitle
{
get
;
set
;
default
=
""
;
}
}
public
abstract
class
DisplayBackend
:
Object
{
public
abstract
class
DisplayBackend
:
Object
{
protected
delegate
bool
ConfigIncludeMatcher
(
string
content
);
public
abstract
string
id
{
get
;
}
public
abstract
string
id
{
get
;
}
public
abstract
string
title
{
owned
get
;
}
public
abstract
string
title
{
owned
get
;
}
public
abstract
bool
can_apply
{
get
;
}
public
abstract
bool
can_apply
{
get
;
}
...
@@ -33,6 +49,14 @@ namespace TunerDisplays {
...
@@ -33,6 +49,14 @@ namespace TunerDisplays {
public
abstract
Gee
.
ArrayList
<
MonitorConfig
>
load
()
throws
Error
;
public
abstract
Gee
.
ArrayList
<
MonitorConfig
>
load
()
throws
Error
;
public
abstract
void
apply
(
Gee
.
ArrayList
<
MonitorConfig
>
monitors
)
throws
Error
;
public
abstract
void
apply
(
Gee
.
ArrayList
<
MonitorConfig
>
monitors
)
throws
Error
;
public
virtual
ConfigIncludeInfo
config_include_info
()
{
return
new
ConfigIncludeInfo
();
}
public
virtual
void
include_monitor_config
()
throws
Error
{
throw
new
BackendError
.
UNSUPPORTED
(
"Including monitor config is not supported by this backend"
);
}
protected
static
Json
.
Node
backend_parse_json
(
string
text
)
throws
Error
{
protected
static
Json
.
Node
backend_parse_json
(
string
text
)
throws
Error
{
var
parser
=
new
Json
.
Parser
();
var
parser
=
new
Json
.
Parser
();
parser
.
load_from_data
(
text
);
parser
.
load_from_data
(
text
);
...
@@ -78,6 +102,86 @@ namespace TunerDisplays {
...
@@ -78,6 +102,86 @@ namespace TunerDisplays {
return
value
.
replace
(
"\\"
,
"\\\\"
).
replace
(
"\""
,
"\\\""
);
return
value
.
replace
(
"\\"
,
"\\\\"
).
replace
(
"\""
,
"\\\""
);
}
}
protected
static
void
backend_include_config_file
(
string
main_path
,
string
included_path
,
string
include_line
,
string
comment_prefix
,
ConfigIncludeMatcher
matcher
)
throws
Error
{
backend_ensure_config_file
(
included_path
);
string
content
=
""
;
if
(
FileUtils
.
test
(
main_path
,
FileTest
.
EXISTS
))
FileUtils
.
get_contents
(
main_path
,
out
content
);
if
(
matcher
(
content
))
return
;
string
updated
;
if
(
backend_uncomment_config_include
(
content
,
comment_prefix
,
matcher
,
out
updated
))
{
FileUtils
.
set_contents
(
main_path
,
updated
);
return
;
}
var
separator
=
content
==
""
||
content
.
has_suffix
(
"\n"
)
?
""
:
"\n"
;
FileUtils
.
set_contents
(
main_path
,
content
+
separator
+
include_line
);
}
private
static
void
backend_ensure_config_file
(
string
path
)
throws
Error
{
DirUtils
.
create_with_parents
(
Path
.
get_dirname
(
path
),
0755
);
if
(!
FileUtils
.
test
(
path
,
FileTest
.
EXISTS
))
FileUtils
.
set_contents
(
path
,
""
);
}
private
static
bool
backend_uncomment_config_include
(
string
content
,
string
comment_prefix
,
ConfigIncludeMatcher
matcher
,
out
string
updated
)
{
var
builder
=
new
StringBuilder
();
var
lines
=
content
.
split
(
"\n"
);
var
changed
=
false
;
for
(
var
i
=
0
;
i
<
lines
.
length
;
i
++)
{
var
line
=
lines
[
i
];
if
(!
changed
&&
backend_uncomment_config_line
(
line
,
comment_prefix
,
matcher
,
out
line
))
changed
=
true
;
if
(
i
>
0
)
builder
.
append_c
(
'\n'
);
builder
.
append
(
line
);
}
updated
=
builder
.
str
;
return
changed
;
}
private
static
bool
backend_uncomment_config_line
(
string
line
,
string
comment_prefix
,
ConfigIncludeMatcher
matcher
,
out
string
uncommented
)
{
uncommented
=
line
;
var
comment
=
line
.
index_of
(
comment_prefix
);
if
(
comment
<
0
||
line
.
substring
(
0
,
comment
).
strip
()
!=
""
)
return
false
;
var
prefix
=
line
.
substring
(
0
,
comment
);
var
candidate
=
line
.
substring
(
comment
+
comment_prefix
.
length
);
if
(
candidate
.
has_prefix
(
" "
))
candidate
=
candidate
.
substring
(
1
);
if
(!
matcher
(
candidate
))
return
false
;
uncommented
=
prefix
+
candidate
;
return
true
;
}
public
static
DisplayBackend
create_for_session
()
{
public
static
DisplayBackend
create_for_session
()
{
var
desktop
=
(
Environment
.
get_variable
(
"XDG_CURRENT_DESKTOP"
)
??
""
).
down
();
var
desktop
=
(
Environment
.
get_variable
(
"XDG_CURRENT_DESKTOP"
)
??
""
).
down
();
var
session
=
(
Environment
.
get_variable
(
"XDG_SESSION_DESKTOP"
)
??
""
).
down
();
var
session
=
(
Environment
.
get_variable
(
"XDG_SESSION_DESKTOP"
)
??
""
).
down
();
...
...
src/backends/hyprland-backend.vala
View file @
355bd1d9
...
@@ -29,6 +29,41 @@ namespace TunerDisplays {
...
@@ -29,6 +29,41 @@ namespace TunerDisplays {
public
override
bool
supports_color_management
{
get
{
return
true
;
}
}
public
override
bool
supports_color_management
{
get
{
return
true
;
}
}
public
override
bool
supports_hdr_metadata
{
get
{
return
true
;
}
}
public
override
bool
supports_hdr_metadata
{
get
{
return
true
;
}
}
public
override
ConfigIncludeInfo
config_include_info
()
{
var
main_path
=
main_config_path
();
if
(!
FileUtils
.
test
(
main_path
,
FileTest
.
EXISTS
))
{
return
new
ConfigIncludeInfo
()
{
state
=
ConfigIncludeState
.
MISSING_MAIN_CONFIG
,
title
=
_
(
"Monitor configuration is not connected"
),
subtitle
=
_
(
"Hyprland configuration file was not found."
)
};
}
try
{
string
content
;
if
(
FileUtils
.
get_contents
(
main_path
,
out
content
)
&&
hyprland_config_includes_monitor_config
(
content
))
return
new
ConfigIncludeInfo
()
{
state
=
ConfigIncludeState
.
INCLUDED
};
}
catch
(
Error
err
)
{
warning
(
"Failed to check Hyprland monitor config include: %s"
,
err
.
message
);
}
return
new
ConfigIncludeInfo
()
{
state
=
ConfigIncludeState
.
NOT_INCLUDED
,
title
=
_
(
"Monitor configuration is not connected"
),
subtitle
=
_
(
"Add monitors.conf to the Hyprland configuration."
)
};
}
public
override
void
include_monitor_config
()
throws
Error
{
backend_include_config_file
(
main_config_path
(),
monitors_path
(),
"source = ~/.config/hypr/monitors.conf\n"
,
"#"
,
hyprland_config_includes_monitor_config
);
}
public
override
Gee
.
ArrayList
<
MonitorConfig
>
load
()
throws
Error
{
public
override
Gee
.
ArrayList
<
MonitorConfig
>
load
()
throws
Error
{
var
monitors
=
new
Gee
.
ArrayList
<
MonitorConfig
>();
var
monitors
=
new
Gee
.
ArrayList
<
MonitorConfig
>();
var
active
=
read_active_names
();
var
active
=
read_active_names
();
...
@@ -316,6 +351,33 @@ namespace TunerDisplays {
...
@@ -316,6 +351,33 @@ namespace TunerDisplays {
return
Path
.
build_filename
(
Environment
.
get_user_config_dir
(),
"hypr"
,
"monitors.conf"
);
return
Path
.
build_filename
(
Environment
.
get_user_config_dir
(),
"hypr"
,
"monitors.conf"
);
}
}
private
static
string
main_config_path
()
{
return
Path
.
build_filename
(
Environment
.
get_user_config_dir
(),
"hypr"
,
"hyprland.conf"
);
}
private
static
bool
hyprland_config_includes_monitor_config
(
string
content
)
{
foreach
(
var
line
in
content
.
split
(
"\n"
))
{
var
trimmed
=
strip_hyprland_comment
(
line
).
strip
();
if
(!
trimmed
.
has_prefix
(
"source"
))
continue
;
var
equals
=
trimmed
.
index_of
(
"="
);
if
(
equals
<
0
)
continue
;
var
path
=
trimmed
.
substring
(
equals
+
1
).
strip
();
if
(
path
==
"~/.config/hypr/monitors.conf"
||
path
==
monitors_path
())
return
true
;
}
return
false
;
}
private
static
string
strip_hyprland_comment
(
string
line
)
{
var
index
=
line
.
index_of
(
"#"
);
return
index
>=
0
?
line
.
substring
(
0
,
index
)
:
line
;
}
private
static
DisplayMode
?
parse_mode
(
string
value
)
{
private
static
DisplayMode
?
parse_mode
(
string
value
)
{
var
cleaned
=
value
.
replace
(
"Hz"
,
""
);
var
cleaned
=
value
.
replace
(
"Hz"
,
""
);
var
parts
=
cleaned
.
split
(
"@"
);
var
parts
=
cleaned
.
split
(
"@"
);
...
...
src/backends/niri-backend.vala
View file @
355bd1d9
...
@@ -35,6 +35,41 @@ namespace TunerDisplays {
...
@@ -35,6 +35,41 @@ namespace TunerDisplays {
public
override
bool
supports_backdrop_color
{
get
{
return
true
;
}
}
public
override
bool
supports_backdrop_color
{
get
{
return
true
;
}
}
public
override
bool
supports_hot_corners
{
get
{
return
true
;
}
}
public
override
bool
supports_hot_corners
{
get
{
return
true
;
}
}
public
override
ConfigIncludeInfo
config_include_info
()
{
var
main_path
=
main_config_path
();
if
(!
FileUtils
.
test
(
main_path
,
FileTest
.
EXISTS
))
{
return
new
ConfigIncludeInfo
()
{
state
=
ConfigIncludeState
.
MISSING_MAIN_CONFIG
,
title
=
_
(
"Monitor configuration is not connected"
),
subtitle
=
_
(
"niri configuration file was not found."
)
};
}
try
{
string
content
;
if
(
FileUtils
.
get_contents
(
main_path
,
out
content
)
&&
niri_config_includes_monitor_config
(
content
))
return
new
ConfigIncludeInfo
()
{
state
=
ConfigIncludeState
.
INCLUDED
};
}
catch
(
Error
err
)
{
warning
(
"Failed to check niri monitor config include: %s"
,
err
.
message
);
}
return
new
ConfigIncludeInfo
()
{
state
=
ConfigIncludeState
.
NOT_INCLUDED
,
title
=
_
(
"Monitor configuration is not connected"
),
subtitle
=
_
(
"Add monitor.kdl to the niri configuration."
)
};
}
public
override
void
include_monitor_config
()
throws
Error
{
backend_include_config_file
(
main_config_path
(),
monitors_path
(),
"include \"monitor.kdl\"\n"
,
"//"
,
niri_config_includes_monitor_config
);
}
public
override
Gee
.
ArrayList
<
MonitorConfig
>
load
()
throws
Error
{
public
override
Gee
.
ArrayList
<
MonitorConfig
>
load
()
throws
Error
{
var
monitors
=
new
Gee
.
ArrayList
<
MonitorConfig
>();
var
monitors
=
new
Gee
.
ArrayList
<
MonitorConfig
>();
var
saved
=
read_saved_monitors
();
var
saved
=
read_saved_monitors
();
...
@@ -273,6 +308,28 @@ namespace TunerDisplays {
...
@@ -273,6 +308,28 @@ namespace TunerDisplays {
return
Path
.
build_filename
(
Environment
.
get_user_config_dir
(),
"niri"
,
"monitor.kdl"
);
return
Path
.
build_filename
(
Environment
.
get_user_config_dir
(),
"niri"
,
"monitor.kdl"
);
}
}
private
static
string
main_config_path
()
{
return
Path
.
build_filename
(
Environment
.
get_user_config_dir
(),
"niri"
,
"config.kdl"
);
}
private
static
bool
niri_config_includes_monitor_config
(
string
content
)
{
foreach
(
var
line
in
content
.
split
(
"\n"
))
{
var
trimmed
=
strip_comment
(
line
).
strip
();
if
(!
trimmed
.
has_prefix
(
"include "
))
continue
;
var
path
=
parse_quoted
(
trimmed
);
if
(
path
==
"monitor.kdl"
||
path
==
"./monitor.kdl"
||
path
==
"~/.config/niri/monitor.kdl"
||
path
==
monitors_path
())
{
return
true
;
}
}
return
false
;
}
private
static
void
append_hot_corners
(
StringBuilder
builder
,
string
value
)
{
private
static
void
append_hot_corners
(
StringBuilder
builder
,
string
value
)
{
if
(
value
==
""
)
if
(
value
==
""
)
return
;
return
;
...
...
src/meson.build
View file @
355bd1d9
...
@@ -12,6 +12,7 @@ sources = files(
...
@@ -12,6 +12,7 @@ sources = files(
'backends/niri-backend.vala',
'backends/niri-backend.vala',
'core/display-model.vala',
'core/display-model.vala',
'core/shell-command.vala',
'core/shell-command.vala',
'ui/config-include-validator.vala',
'ui/displays-view.vala',
'ui/displays-view.vala',
'ui/monitor-layout.vala',
'ui/monitor-layout.vala',
'ui/monitor-row.vala',
'ui/monitor-row.vala',
...
...
src/ui/config-include-validator.vala
0 → 100644
View file @
355bd1d9
namespace
TunerDisplays
{
public
class
ConfigIncludeBinding
:
Tuner
.
Binding
{
private
DisplayBackend
backend
;
public
ConfigIncludeBinding
(
DisplayBackend
backend
)
{
this
.
backend
=
backend
;
}
public
ConfigIncludeInfo
info
()
{
return
backend
.
config_include_info
();
}
public
void
connect_config
()
throws
Error
{
backend
.
include_monitor_config
();
emit_changed
();
}
public
override
Type
expected_type
{
get
{
return
typeof
(
bool
);
}
}
public
override
bool
get_value
(
ref
Value
value
)
{
value
=
info
().
state
==
ConfigIncludeState
.
NOT_INCLUDED
;
return
true
;
}
public
override
void
set_value
(
Value
value
)
{
}
}
public
class
ConfigIncludeValidator
:
Tuner
.
Validator
{
public
override
void
apply
(
Tuner
.
Binding
binding
,
Gtk
.
Widget
native_widget
)
{
var
include_binding
=
binding
as
ConfigIncludeBinding
;
var
row
=
native_widget
as
Adw
.
ActionRow
;
if
(
include_binding
==
null
||
row
==
null
)
return
;
update
(
include_binding
,
row
);
include_binding
.
changed
.
connect
(()
=>
update
(
include_binding
,
row
));
}
private
static
void
update
(
ConfigIncludeBinding
binding
,
Adw
.
ActionRow
row
)
{
var
info
=
binding
.
info
();
var
visible
=
info
.
state
==
ConfigIncludeState
.
NOT_INCLUDED
||
info
.
state
==
ConfigIncludeState
.
MISSING_MAIN_CONFIG
;
row
.
visible
=
visible
;
var
group
=
row
.
get_ancestor
(
typeof
(
Adw
.
PreferencesGroup
));
if
(
group
!=
null
)
group
.
visible
=
visible
;
if
(!
visible
)
return
;
row
.
title
=
info
.
title
;
row
.
subtitle
=
info
.
subtitle
;
}
}
}
src/ui/displays-view.vala
View file @
355bd1d9
...
@@ -11,8 +11,11 @@ namespace TunerDisplays {
...
@@ -11,8 +11,11 @@ namespace TunerDisplays {
private
MonitorSettingsContent
?
single_monitor_content
;
private
MonitorSettingsContent
?
single_monitor_content
;
private
MonitorLayout
layout
;
private
MonitorLayout
layout
;
private
Adw
.
PreferencesRow
layout_row
;
private
Adw
.
PreferencesRow
layout_row
;
private
ConfigIncludeBinding
config_include_binding
;
private
DBusConnection
?
session_bus
;
private
DBusConnection
?
session_bus
;
private
uint
monitors_changed_id
;
private
uint
monitors_changed_id
;
[
GtkChild
]
private
unowned
Adw
.
ActionRow
config_include_row
;
[
GtkChild
]
private
unowned
Gtk
.
Button
config_include_button
;
[
GtkChild
]
private
unowned
Adw
.
PreferencesGroup
monitors_group
;
[
GtkChild
]
private
unowned
Adw
.
PreferencesGroup
monitors_group
;
[
GtkChild
]
private
unowned
Adw
.
PreferencesGroup
layout_group
;
[
GtkChild
]
private
unowned
Adw
.
PreferencesGroup
layout_group
;
[
GtkChild
]
private
unowned
Adw
.
PreferencesGroup
status_group
;
[
GtkChild
]
private
unowned
Adw
.
PreferencesGroup
status_group
;
...
@@ -23,6 +26,7 @@ namespace TunerDisplays {
...
@@ -23,6 +26,7 @@ namespace TunerDisplays {
construct
{
construct
{
backend
=
DisplayBackend
.
create_for_session
();
backend
=
DisplayBackend
.
create_for_session
();
config_include_binding
=
new
ConfigIncludeBinding
(
backend
);
layout_row
=
new
Adw
.
PreferencesRow
()
{
layout_row
=
new
Adw
.
PreferencesRow
()
{
activatable
=
false
,
activatable
=
false
,
...
@@ -40,6 +44,9 @@ namespace TunerDisplays {
...
@@ -40,6 +44,9 @@ namespace TunerDisplays {
layout
.
layout_changed
.
connect
(
sync_rows
);
layout
.
layout_changed
.
connect
(
sync_rows
);
layout_row
.
child
=
layout
;
layout_row
.
child
=
layout
;
layout_group
.
add
(
layout_row
);
layout_group
.
add
(
layout_row
);
config_include_button
.
clicked
.
connect
(
connect_monitor_config
);
new
ConfigIncludeValidator
().
apply
(
config_include_binding
,
config_include_row
);
config_include_binding
.
changed
.
connect
(
sync_config_include_button
);
subscribe_monitor_changes
();
subscribe_monitor_changes
();
reload
();
reload
();
...
@@ -133,6 +140,7 @@ namespace TunerDisplays {
...
@@ -133,6 +140,7 @@ namespace TunerDisplays {
clear_status_rows
();
clear_status_rows
();
clear_mirror_settings_rows
();
clear_mirror_settings_rows
();
clear_single_monitor_settings
();
clear_single_monitor_settings
();
config_include_binding
.
emit_changed
();
sync_layout_visibility
();
sync_layout_visibility
();
sync_group_visibility
();
sync_group_visibility
();
...
@@ -163,6 +171,20 @@ namespace TunerDisplays {
...
@@ -163,6 +171,20 @@ namespace TunerDisplays {
}
}
}
}
private
void
sync_config_include_button
()
{
config_include_button
.
visible
=
config_include_binding
.
info
().
state
==
ConfigIncludeState
.
NOT_INCLUDED
;
}
private
void
connect_monitor_config
()
{
try
{
config_include_binding
.
connect_config
();
Tuner
.
toast
(
_
(
"Monitor configuration connected"
));
reload
();
}
catch
(
Error
err
)
{
Tuner
.
toast
(
err
.
message
);
}
}
private
void
add_gnome_mirror_row
()
{
private
void
add_gnome_mirror_row
()
{
if
(!
backend
.
supports_global_mirroring
||
monitors
.
size
<=
1
)
if
(!
backend
.
supports_global_mirroring
||
monitors
.
size
<=
1
)
return
;
return
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment