foxygit / screen Log in
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