commit b1d39226fe4803774341bc6f7d5486b8c80be282
Author: MrJensK <jens.se@icloud.com>
AuthorDate: Wed May 13 19:26:28 2026 +0200
Commit: MrJensK <jens.se@icloud.com>
CommitDate: Wed May 13 19:26:28 2026 +0200
Enhance README and code to support XDG autostart and improve layout saving
---
.gitignore | 10 ++++++++++
README.md | 36 ++++++++++++++++++++++--------------
main.c | 2 +-
main.o | Bin 13440 -> 13440 bytes
monitors.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------
monitors.o | Bin 23208 -> 25632 bytes
xrantui | Bin 43032 -> 43736 bytes
7 files changed, 87 insertions(+), 21 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..caa47b3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+# build output
+xrantui
+*.o
+
+# editor
+.vscode/
+.idea/
+*.swp
+*.swo
+*~
diff --git a/README.md b/README.md
index 5e98c47..96689cf 100644
--- a/README.md
+++ b/README.md
@@ -6,21 +6,21 @@ Interactive terminal UI for arranging monitors, built with ncurses and Xrandr.
## Features
-- Visual scaled-down canvas of your monitor layout
-- Move monitors with arrow keys and apply instantly via xrandr
-- Snap-to-edge when dragging monitors near each other
+- Visual scaled-down canvas showing all active monitors
+- Move monitors with arrow keys — snaps to edges automatically
- Set primary monitor
-- Save layout to `~/.screenlayout/xrantui.sh` with automatic `~/.xprofile` hook for persistence across reboots
-- Undo to revert unsaved changes
+- Apply layout instantly via xrandr
+- Save layout for persistence across reboots (XDG autostart, `.xprofile`, `.xinitrc`)
+- Undo to revert to positions at startup
## Requirements
### Runtime
- X11 with Xrandr
-- `xrandr` CLI tool in `$PATH`
+- `xrandr` in `$PATH`
-### Build
+### Build dependencies
```bash
sudo apt install gcc make pkg-config libncurses-dev libxrandr-dev libx11-dev
@@ -38,8 +38,8 @@ sudo make install # installs to /usr/local/bin
Custom prefix:
```bash
-sudo make install PREFIX=/usr # → /usr/bin/xrantui
-make install PREFIX=~/.local # → ~/.local/bin/xrantui (no sudo needed)
+sudo make install PREFIX=/usr # → /usr/bin/xrantui
+make install PREFIX=~/.local # → ~/.local/bin/xrantui (no sudo)
```
Uninstall:
@@ -56,7 +56,7 @@ Run inside a terminal within an X session:
xrantui
```
-If your `DISPLAY` variable is not set:
+If `DISPLAY` is not set:
```bash
DISPLAY=:0 xrantui
@@ -71,14 +71,22 @@ DISPLAY=:0 xrantui
| `p` | Set selected monitor as primary |
| `u` | Undo — revert all monitors to positions at startup |
| `Enter` | Apply layout with xrandr |
-| `s` | Save layout to `~/.screenlayout/xrantui.sh` |
+| `s` | Save layout |
| `q` | Quit |
## Persistent layout
-Press `s` to save the current layout. This writes a shell script to
-`~/.screenlayout/xrantui.sh` and adds a one-time entry to `~/.xprofile` so the
-layout is restored automatically on every X login.
+Press `s` to save the current layout. xrantui writes to all relevant startup
+files automatically, covering most X setups:
+
+| File | Used by |
+|---|---|
+| `~/.screenlayout/xrantui.sh` | The xrandr script itself |
+| `~/.config/autostart/xrantui.desktop` | XDG autostart — GNOME, KDE, XFCE, LXDE |
+| `~/.xprofile` | Display manager without DE — e.g. LightDM + sxwm |
+| `~/.xinitrc` | `startx` + bare WM — e.g. sxwm. Inserted before `exec`. |
+
+`~/.xprofile` and `~/.xinitrc` are only modified if they already exist.
## Project structure
diff --git a/main.c b/main.c
index 9020f6c..ab3811e 100644
--- a/main.c
+++ b/main.c
@@ -108,7 +108,7 @@ int main(void) {
case 's':
case 'S':
if (monitors_save(mons, nmons) == 0)
- msg = "Sparat till ~/.screenlayout/xrantui.sh och ~/.xprofile";
+ msg = "Sparat — .desktop + .xprofile + .xinitrc (om de finns)";
else
msg = "Fel: kunde inte spara";
break;
diff --git a/main.o b/main.o
index fde4740..ec7f18e 100644
Binary files a/main.o and b/main.o differ
diff --git a/monitors.c b/monitors.c
index c126213..6012c2b 100644
--- a/monitors.c
+++ b/monitors.c
@@ -101,27 +101,75 @@ int monitors_save(Monitor *mons, int count) {
fclose(f);
chmod(path, 0755);
- /* lägg till anrop i ~/.xprofile om det inte redan finns */
+ /* 1. XDG autostart — GNOME, KDE, XFCE, LXDE m.fl. */
+ char autostart_dir[512];
+ snprintf(autostart_dir, sizeof(autostart_dir), "%s/.config/autostart", home);
+ mkdir(autostart_dir, 0755);
+
+ char desktop[560];
+ snprintf(desktop, sizeof(desktop), "%s/xrantui.desktop", autostart_dir);
+ f = fopen(desktop, "w");
+ if (f) {
+ fprintf(f,
+ "[Desktop Entry]\n"
+ "Type=Application\n"
+ "Name=xrantui monitor layout\n"
+ "Exec=sh %s\n"
+ "X-GNOME-Autostart-enabled=true\n"
+ "Hidden=false\n",
+ path);
+ fclose(f);
+ }
+
+ /* 2. ~/.xprofile — displayhanterare utan DE (t.ex. LightDM + sxwm) */
char xprofile[512];
snprintf(xprofile, sizeof(xprofile), "%s/.xprofile", home);
-
int found = 0;
f = fopen(xprofile, "r");
if (f) {
char line[256];
- while (fgets(line, sizeof(line), f)) {
+ while (fgets(line, sizeof(line), f))
if (strstr(line, "xrantui.sh")) { found = 1; break; }
- }
fclose(f);
}
if (!found) {
f = fopen(xprofile, "a");
if (f) {
- fprintf(f, "\n[ -f \"$HOME/.screenlayout/xrantui.sh\" ]"
- " && sh \"$HOME/.screenlayout/xrantui.sh\"\n");
+ fprintf(f, "\n[ -f \"%s\" ] && sh \"%s\"\n", path, path);
fclose(f);
}
}
+ /* 3. ~/.xinitrc — startx + bare WM (t.ex. sxwm)
+ Infoga före första "exec "-raden så kommandot faktiskt körs. */
+ char xinitrc[512];
+ snprintf(xinitrc, sizeof(xinitrc), "%s/.xinitrc", home);
+ f = fopen(xinitrc, "r");
+ if (f) {
+ /* läs in hela filen */
+ char lines[128][256];
+ int n = 0;
+ while (n < 127 && fgets(lines[n], sizeof(lines[0]), f)) {
+ if (strstr(lines[n], "xrantui.sh")) { n = -1; break; } /* redan finns */
+ n++;
+ }
+ fclose(f);
+
+ if (n >= 0) {
+ /* hitta första exec-raden */
+ int exec_idx = n;
+ for (int i = 0; i < n; i++) {
+ if (strncmp(lines[i], "exec ", 5) == 0) { exec_idx = i; break; }
+ }
+ f = fopen(xinitrc, "w");
+ if (f) {
+ for (int i = 0; i < exec_idx; i++) fputs(lines[i], f);
+ fprintf(f, "sh \"%s\"\n", path);
+ for (int i = exec_idx; i < n; i++) fputs(lines[i], f);
+ fclose(f);
+ }
+ }
+ }
+
return 0;
}
diff --git a/monitors.o b/monitors.o
index 67144b3..61ef6ed 100644
Binary files a/monitors.o and b/monitors.o differ
diff --git a/xrantui b/xrantui
index 2241454..073b8ac 100755
Binary files a/xrantui and b/xrantui differ