aboutsummaryrefslogtreecommitdiffstats
path: root/src/pane.c
diff options
context:
space:
mode:
authoruser <user@clank>2026-08-14 12:14:17 +0200
committeruser <user@clank>2026-08-14 12:14:17 +0200
commit1ceafa4d82bdc37449c174a75fcd38b4be880080 (patch)
tree33c2904620ac1e5477eb1b8d387bff00ba3f2157 /src/pane.c
parentsl0ppty: one-shot --headless printed a blank screen (diff)
downloadslosh-1ceafa4d82bdc37449c174a75fcd38b4be880080.tar.gz
slosh-1ceafa4d82bdc37449c174a75fcd38b4be880080.tar.xz
slosh-1ceafa4d82bdc37449c174a75fcd38b4be880080.zip
sl0ppty: the pane title is a name — double-click it to rename
The top row was both the frame's drag handle and its top edge: resting on it armed the split guide, and a click that never moved split upward. That is right for a border and wrong for the cells the title sits on, because it left no gesture free for naming a pane — a double-click there split twice. So the title text carves its own hit region out of the top row. It is registered after the row's handle and after the title is painted, which is what makes it correct: hit_test scans backwards, so the region that wins is the one whose glyphs the user can actually see, and its width comes from screen_text's return so a title of wide characters claims the cells it drew. Resting there arms nothing (draw_split_guide matches "title:" exactly), and a press takes no side, so the click-splits path — now guarded on a side being set — does nothing. Dragging still moves the pane: that reads as grabbing it by its name. Everything else on the top row still splits upward. Renaming happens in the title cell itself. There is no dialog to place, nothing to dismiss, and the pane it belongs to cannot be in doubt. It is the finder's shape: state on app_t, a key handler that owns the keyboard while it is open, drawn by the pass that draws the frame. Enter keeps the name, Escape abandons it, clicking away keeps it the way leaving a field does. A typed name shadows the program's title rather than overwriting it. The program's OSC 2 keeps arriving underneath, so a shell that rewrites its title cannot undo a rename, and clearing the name gives the pane back to what the program calls itself *now* rather than to whatever it happened to say when the rename began. That is the whole reason pane_t grew a second string instead of a flag. Backspace deletes a character rather than a byte — a title is whatever a program could set, and half a UTF-8 sequence is not a name — and a name too long for the frame scrolls its head off, because the caret is the one thing that has to stay visible. double_click_ms (400) joins hover_delay_ms in the config. The tests keep a control beside each behaviour, since most of these could pass by breaking something else: two slow clicks must open no editor, the top edge must still split, keystrokes must not reach the shell, and a pane closing mid-rename must give the keyboard back.
Diffstat (limited to 'src/pane.c')
-rw-r--r--src/pane.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/pane.c b/src/pane.c
index 8969065..51c3970 100644
--- a/src/pane.c
+++ b/src/pane.c
@@ -27,6 +27,11 @@ struct pane {
bool alive;
bool dirty;
char title[256];
+ /* A name the user typed. It shadows `title` rather than overwriting it, so
+ * the program's own title keeps arriving underneath and clearing the name
+ * (renaming to nothing) falls back to whatever the program calls itself
+ * now — not to whatever it happened to say when the rename began. */
+ char name[256];
/* OSC 5577 state: what this pane asked us to draw in its frame */
/* A suspended pane is real, sized and laid out, but has not run anything:
@@ -312,7 +317,17 @@ void pane_free(pane_t *p) {
int pane_fd(const pane_t *p) { return p->pty.fd; }
bool pane_alive(const pane_t *p) { return p->alive; }
bool pane_dirty(pane_t *p) { return p->dirty; }
-const char *pane_title(const pane_t *p) { return p->title; }
+const char *pane_title(const pane_t *p) {
+ return p->name[0] ? p->name : p->title;
+}
+
+const char *pane_name(const pane_t *p) { return p->name; }
+
+void pane_set_name(pane_t *p, const char *name) {
+ if (!name) name = "";
+ snprintf(p->name, sizeof p->name, "%s", name);
+ p->dirty = true;
+}
ssize_t pane_pump(pane_t *p) {
if (p->pty.fd < 0) return 0;