xi-desktop-portals

Simpler specifications for Linux desktop APIs.
git clone https://git.ce9e.org/xi-desktop-portals.git

commit
e9d14d4512107849c9c644bda7f4c452127de096
parent
345a7f2a5ef179d85f3e6b96a3b1fade58910e90
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2026-03-12 07:55
[Settings] implement gsettings sync

Diffstat

A Settings/.gitignore 1 +
A Settings/Makefile 6 ++++++
A Settings/PKGBUILD 18 ++++++++++++++++++
A Settings/sync.c 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A Settings/systemd/service 8 ++++++++

5 files changed, 146 insertions, 0 deletions


diff --git a/Settings/.gitignore b/Settings/.gitignore

@@ -0,0 +1 @@
   -1     1 sync

diff --git a/Settings/Makefile b/Settings/Makefile

@@ -0,0 +1,6 @@
   -1     1 PREFIX = /usr
   -1     2 CFLAGS = -std=c99 -Wall -O2 -fstack-protector-strong -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 `pkg-config --cflags gio-2.0`
   -1     3 LDFLAGS = -s -Wl,-z,relro `pkg-config --libs gio-2.0`
   -1     4 
   -1     5 sync: sync.c
   -1     6 	gcc $< -o $@ ${CFLAGS} ${LDFLAGS}

diff --git a/Settings/PKGBUILD b/Settings/PKGBUILD

@@ -0,0 +1,18 @@
   -1     1 pkgname='xi-portal-settings-sync'
   -1     2 pkgdesc='Sync Settings portal to gsettings'
   -1     3 pkgver='0.0.0'
   -1     4 arch=('amd64')
   -1     5 url='https://github.com/xi/xi-desktop-portals'
   -1     6 license='MIT'
   -1     7 depends=(
   -1     8 	libglib2.0-0t64
   -1     9 )
   -1    10 makedepends=(
   -1    11 	libgio-2.0-dev
   -1    12 )
   -1    13 
   -1    14 package() {
   -1    15 	make
   -1    16 	install -Dm 755 sync "$pkgdir/usr/bin/$pkgname"
   -1    17 	install -Dm 644 systemd/service "$pkgdir/usr/lib/systemd/user/$pkgname.service"
   -1    18 }

diff --git a/Settings/sync.c b/Settings/sync.c

@@ -0,0 +1,113 @@
   -1     1 #include <dirent.h>
   -1     2 #include <fcntl.h>
   -1     3 #include <limits.h>
   -1     4 #include <stdio.h>
   -1     5 #include <stdlib.h>
   -1     6 #include <sys/inotify.h>
   -1     7 #include <sys/epoll.h>
   -1     8 #include <unistd.h>
   -1     9 
   -1    10 #include <gio/gio.h>
   -1    11 
   -1    12 #define EVENT_SIZE (sizeof(struct inotify_event))
   -1    13 #define BUF_LEN (1024 * (EVENT_SIZE + 16))
   -1    14 
   -1    15 char root[PATH_MAX - 64];
   -1    16 GSettings *settings, *settings_a11y;
   -1    17 
   -1    18 void on_change(const char *key) {
   -1    19     char path[PATH_MAX];
   -1    20     snprintf(path, sizeof(path), "%s/%s", root, key);
   -1    21 
   -1    22     int fd = open(path, O_RDONLY);
   -1    23     if (fd < 0) {
   -1    24         return;
   -1    25     }
   -1    26     char value[256];
   -1    27     int len = read(fd, value, sizeof(value) - 1);
   -1    28     close(fd);
   -1    29     if (len < 0) {
   -1    30         return;
   -1    31     }
   -1    32     value[len] = '\0';
   -1    33     g_strchomp(value);
   -1    34 
   -1    35     if (strcmp(key, "color-scheme") == 0) {
   -1    36         if (strcmp(value, "dark") == 0) {
   -1    37             g_settings_set_string(settings, "color-scheme", "prefer-dark");
   -1    38         } else if (strcmp(value, "light") == 0) {
   -1    39             g_settings_set_string(settings, "color-scheme", "prefer-light");
   -1    40         } else {
   -1    41             g_settings_set_string(settings, "color-scheme", "default");
   -1    42         }
   -1    43     } else if (strcmp(key, "accent-color") == 0) {
   -1    44         // TODO: translate color to color name
   -1    45         g_settings_set_string(settings, "accent-color", value);
   -1    46     } else if (strcmp(key, "reduced-motion") == 0) {
   -1    47         if (strcmp(value, "reduced") == 0) {
   -1    48             g_settings_set_string(settings_a11y, "reduced-motion", "reduce");
   -1    49         } else {
   -1    50             g_settings_set_string(settings_a11y, "reduced-motion", "no-preference");
   -1    51         }
   -1    52     } else if (strcmp(key, "contrast") == 0) {
   -1    53         if (strcmp(value, "high") == 0) {
   -1    54             g_settings_set_boolean(settings_a11y, "high-contrast", TRUE);
   -1    55         } else {
   -1    56             g_settings_set_boolean(settings_a11y, "high-contrast", FALSE);
   -1    57         }
   -1    58     }
   -1    59 }
   -1    60 
   -1    61 int main() {
   -1    62     snprintf(
   -1    63         root, sizeof(root), "%s/org.freedesktop.appearance", g_get_user_config_dir()
   -1    64     );
   -1    65 
   -1    66     settings = g_settings_new("org.gnome.desktop.interface");
   -1    67     settings_a11y = g_settings_new("org.gnome.desktop.a11y.interface");
   -1    68 
   -1    69     int fd = inotify_init();
   -1    70     if (fd < 0) {
   -1    71         perror("inotify_init");
   -1    72         return EXIT_FAILURE;
   -1    73     }
   -1    74     int wd = inotify_add_watch(fd, root, IN_CLOSE_WRITE);
   -1    75     if (wd < 0) {
   -1    76         perror("inotify_add_watch");
   -1    77         return EXIT_FAILURE;
   -1    78     }
   -1    79 
   -1    80     DIR *d = opendir(root);
   -1    81     struct dirent *entry;
   -1    82     if (d) {
   -1    83         while ((entry = readdir(d))) {
   -1    84             on_change(entry->d_name);
   -1    85         }
   -1    86         closedir(d);
   -1    87     }
   -1    88 
   -1    89     int epfd = epoll_create(1);
   -1    90     struct epoll_event ev, events[1];
   -1    91     ev.events = EPOLLIN;
   -1    92     epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
   -1    93 
   -1    94     char buf[BUF_LEN];
   -1    95     struct inotify_event *event;
   -1    96 
   -1    97     while (1) {
   -1    98         epoll_wait(epfd, events, 1, -1);
   -1    99 
   -1   100         int length = read(fd, buf, sizeof(buf));
   -1   101         if (length < 0) {
   -1   102             perror("read");
   -1   103             return EXIT_FAILURE;
   -1   104         }
   -1   105 
   -1   106         int i = 0;
   -1   107         while (i < length) {
   -1   108             event = (struct inotify_event *)&buf[i];
   -1   109             on_change(event->name);
   -1   110             i += EVENT_SIZE + event->len;
   -1   111         }
   -1   112     }
   -1   113 }

diff --git a/Settings/systemd/service b/Settings/systemd/service

@@ -0,0 +1,8 @@
   -1     1 [Unit]
   -1     2 Description=Settings portal sync
   -1     3 
   -1     4 [Service]
   -1     5 ExecStart=/usr/bin/xi-portal-settings-sync
   -1     6 
   -1     7 [Install]
   -1     8 WantedBy=graphical-session.target