From 2f58a0670e644cdaca1fc0969a2ce846e310be66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Fri, 16 Oct 2026 04:05:29 -0400 Subject: [PATCH] T30: a hidden window keeps the size from before too, since X11 calls a maximized window unmaximized while it is minimized; the window is no smaller than 100 by 100, the least the settings keep, so each size it takes can be kept --- AGENTS.md | 2 +- PRD.md | 2 +- src/app.rs | 12 +++++++++--- tasks/acceptance.md | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 760614e..6838ba7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -93,4 +93,4 @@ ELYTerminal. A terminal on GPUI and Ely components. `PRD.md` says what it does; - 2026-10-15: on Omarchy 4 (Linux) ELYTerminal follows the system's theme. Omarchy renders the current theme's `colors.toml` through its own resolver into `~/.local/state/omarchy/current/theme/ghostty.conf`, under `$HOME` whatever `XDG_STATE_HOME` says, so ELYTerminal reads that file and wears what Ghostty wears there: its color lines go through the strict parser the bundled themes use, and the rest, such as the glass block, pass by. Omarchy writes no `cursor-text`, so the background stands in, as in Ghostty and Omarchy's kitty template. ELYTerminal reads the file twice a second, since Omarchy signals only Alacritty, kitty and Ghostty, by name, and wears it whenever its text changes and parses; a check that fails is logged once while it lasts and tried again, so a file made readable again is worn though nothing else about it changed. The Omarchy theme is the default unless that file is surely absent, so a folder that cannot be read makes a fresh install wear it and the start name the error; another pick stops following. At start a missing file means no Omarchy unless the settings wear it, a file that cannot be read stops the start, and one that does not parse stops it only when worn, else it is logged and no Omarchy card shows. While running, a missing file is a switch in progress, and any other failure keeps the last theme. Omarchy 3's `~/.config/omarchy/current` gets no shim. - 2026-10-16: on Hyprland 0.56 a window blurs only while Hyprland's own `decoration:blur:enabled` is on: its `shouldBlur` reads that option first, then the window's `no_blur`, RGBX and opaque rules, then the blur region a surface sets through `ext_background_effect_v1`, which Hyprland offers with the blur capability whatever the option says. Omarchy 4.0.4's default `looknfeel.lua` turns the option off, so on Omarchy no window blurs until the user turns it on; ELYTerminal leaves the compositor's settings alone. On the owner's Omarchy the log named `ext_background_effect_v1` and the pane's region, and the wallpaper behind the window blurred with the option on and showed sharp with it off. - 2026-10-16: herdr 0.9 keeps its panes' OSC 7 and writes only a title, notifications, OSC 52 and bells to the terminal it runs in, so no terminal hears a folder from inside it; herdr's server knows each pane's `cwd`, the folder its shell reported, else the shell's own. On macOS and Linux each session asks twice a second which process group leads its pty's foreground (`tcgetpgrp` on a copy of the master) and what executable that group's leader runs: an exec keeps the group and swaps the executable, so `exec herdr` from a shell is a new program, and one that did not read is tried again; on Linux the ` (deleted)` mark an update leaves on a running executable is set aside. When that executable is `herdr` and its arguments start herdr's terminal client (no command, `session attach NAME` or `client`), ELYTerminal reads the client's arguments and variables (`/proc` on Linux; `KERN_PROCARGS2` on macOS, which hides only the variables of Apple's own programs) and finds its socket as herdr 0.9 does: `--session NAME`, then `HERDR_SOCKET_PATH`, then `HERDR_SESSION`, under `$XDG_CONFIG_HOME/herdr`, else `~/.config/herdr`; a relative socket lies in the client's folder, as herdr reads it (`/proc/PID/cwd`; `proc_pidinfo` on macOS). It asks that socket for `session.snapshot` twice a second, a connection each, since herdr closes one after its reply, and reports the focused pane's `cwd` as the session's folder when it changes and again each time herdr takes the foreground. Focus belongs to herdr's server, so clients of one server follow one focus; a client of another machine's server (`--remote`, `--machine`) is logged, not followed. A failure is logged once while it lasts. Windows has none of this: there herdr is a beta on named pipes. -- 2026-10-16: the main window opens at the size it was left at, which the owner asked for on macOS, Windows and Linux: `window_width` and `window_height` in the settings hold the size gpui's `window_bounds` gives 0.5 s after the bounds settle, saved through `SettingsStore::update`, which writes only a change, so a drag saves once and a move saves nothing. A maximized or full-screen window keeps the size from before; its state and size are read once they settle, since X11 marks a window maximized after its new size, and gpui's X11 window then gives a maximized window's own size. The window opens centered, its place not kept, and a kept side past the primary display's visible area shrinks to it, logged. A size outside 100 to 16384 stops the start, as any value out of range does. +- 2026-10-16: the main window opens at the size it was left at, which the owner asked for on macOS, Windows and Linux: `window_width` and `window_height` in the settings hold the size gpui's `window_bounds` gives 0.5 s after the bounds settle, saved through `SettingsStore::update`, which writes only a change, so a drag saves once and a move saves nothing. A maximized, full-screen or hidden window keeps the size from before; its state and size are read once they settle, since X11 marks a window maximized after its new size, gpui's X11 window then gives a maximized window's own size, and it calls a maximized window unmaximized while minimized. The window is no smaller than 100 by 100, the least the settings keep, or a smaller size the platform allows could not be kept. The window opens centered, its place not kept, and a kept side past the primary display's visible area shrinks to it, logged. A size outside 100 to 16384 stops the start, as any value out of range does. diff --git a/PRD.md b/PRD.md index 31eb076..06c90ee 100644 --- a/PRD.md +++ b/PRD.md @@ -61,7 +61,7 @@ Ghostty is the bar for what the terminal does. ELYTerminal owns its engine on `a - Ely's `ColumnShell`: sessions column, terminal column, right column. The window opens with blur when the setting is on. - The sessions column and the right column toggle, each by a button at its end of the title bar or by key, and keep their state in settings, so the window opens as it was left. -- The window opens at the size it was left at, on macOS, Windows and Linux: the size is kept in settings once it settles; a maximized or full-screen window keeps the size from before; a kept size past the screen shrinks to it. +- The window opens at the size it was left at, on macOS, Windows and Linux: the size is kept in settings once it settles; a maximized or full-screen window keeps the size from before; a kept size past the screen shrinks to it; the window is no smaller than 100 by 100, the least the settings keep. - The title shows the active session's title, and no other text. - The pointer over the terminal is the arrow. - The title bar is transparent, as Ghostty's: the window's background, opacity and blur run under it, so it wears the terminal's color. diff --git a/src/app.rs b/src/app.rs index c4afe72..f257363 100644 --- a/src/app.rs +++ b/src/app.rs @@ -91,8 +91,11 @@ pub fn open(launch: Launch, cx: &mut App) -> anyhow::Result Size { ) } -/// Keeps the window's size in the settings once it settles; maximized or full screen, the size before stays. +/// Keeps the window's size in the settings once it settles; maximized, full screen or hidden, the size before stays. fn keep_size(window: &mut Window, cx: &mut Context) { let mut _settling: Option> = None; cx.observe_window_bounds(window, move |_, window, cx| { _settling = Some(cx.spawn_in(window, async move |_, cx| { cx.background_executor().timer(SETTLE).await; - // Read once settled: X11 marks a window maximized after its new size. + // Read once settled: X11 marks a window maximized late, and unmaximized while hidden. let kept = cx.update(|window, cx| { - if window.is_maximized() || window.is_fullscreen() { + if !window.is_visible() || window.is_maximized() || window.is_fullscreen() { + log::debug!( + "app: the window is hidden, maximized or full screen; its kept size stays" + ); return Ok(()); } let area = window.window_bounds().get_bounds().size; diff --git a/tasks/acceptance.md b/tasks/acceptance.md index efba858..7dba5fc 100644 --- a/tasks/acceptance.md +++ b/tasks/acceptance.md @@ -70,7 +70,7 @@ What no check reached: no one has looked at the window on Windows, which CI buil |---|---|---|---| | `ColumnShell` with three columns; blur when the setting is on | T11, T19 | `shot` names a `BlurredView` under the window | Pass | | Columns toggle and keep their state | T11, T23 | a click on each title bar button hid its column and saved it, and a restart opened the window with both hidden (147 columns against 87); Cmd-B with the app active; Ctrl-Shift-B on a real X11 window | Pass | -| The window opens at the size it was left at; maximized or full screen, the size before stays; a kept size past the screen shrinks to it | T30 | `a_value_out_of_range_names_its_field`; on X11 under xfwm4: the first start opened at 1200 by 760 and wrote nothing; a resize to 900 by 600 was kept with one write, and the next start opened at 900 by 600 and wrote nothing; maximized by xfwm4's Alt+F10 the window spanned the 1400 by 900 screen while the file kept 900 by 600, and restored it was 900 by 600 again; a kept 3000 by 2000 opened at 1400 by 900, logged; on macOS under `shot`, a kept 900 by 600 opened at 900 by 600 and a kept 5000 by 4000 at the visible 1920 by 1113, logged; a resize on macOS and any run on Windows not yet shown | Partial | +| The window opens at the size it was left at; maximized or full screen, the size before stays; a kept size past the screen shrinks to it | T30 | `a_value_out_of_range_names_its_field`; on X11 under xfwm4: the first start opened at 1200 by 760 and wrote nothing; a resize to 900 by 600 was kept with one write, and the next start opened at 900 by 600 and wrote nothing; maximized by xfwm4's Alt+F10 the window spanned the 1400 by 900 screen while the file kept 900 by 600, and restored it was 900 by 600 again; maximized, minimized and restored, the file kept 900 by 600, and the next start opened at 900 by 600; `WM_NORMAL_HINTS` names a 100 by 100 minimum, and a resize to 900 by 50 held at 900 by 100, kept so; a kept 3000 by 2000 opened at 1400 by 900, logged; on macOS under `shot`, a kept 900 by 600 opened at 900 by 600 and a kept 5000 by 4000 at the visible 1920 by 1113, logged; a resize on macOS and any run on Windows not yet shown | Partial | | The title shows the session's title, nothing else | T11 | log: "the title is", per session shown | Pass | | The pointer over the terminal is the arrow | T26 | the terminal sets no pointer, so gpui's arrow shows; on X11 with the pointer over the grid, gpui asked for no I-beam ("text"), which it had asked for, and failed to load under Xvfb, before | Pass | | The title bar is transparent | T11, T19 | T19 review | Pass |