1
0
Fork 0
forked from wry/wry

fix split bug on single windows and elide titles

This commit is contained in:
kossLAN 2026-05-03 15:35:34 -04:00
parent 7f71a6556b
commit c555593ae2
No known key found for this signature in database
8 changed files with 207 additions and 145 deletions

View file

@ -97,10 +97,10 @@ alt-shift-l = "move-right"
```toml
[shortcuts]
alt-d = "split-horizontal"
alt-v = "split-vertical"
alt-t = "toggle-split"
alt-m = "toggle-mono"
alt-d = "make-group-h"
alt-v = "make-group-v"
alt-t = "change-group-opposite"
alt-m = "toggle-tab"
alt-f = "focus-parent"
```
@ -475,7 +475,7 @@ table and reference them with `$name`:
```toml
[actions]
my-layout = [
"split-horizontal",
"make-group-h",
{ type = "exec", exec = "alacritty" },
]
@ -535,10 +535,9 @@ mode = {
When certain simple actions are used inside a [window rule](../window-rules.md),
they apply to the **matched window** instead of the focused window. The
affected actions are: `move-left`, `move-down`, `move-up`, `move-right`,
`split-horizontal`, `split-vertical`, `toggle-split`, `tile-horizontal`,
`tile-vertical`, `show-single`, `show-all`, `toggle-fullscreen`,
`enter-fullscreen`, `exit-fullscreen`, `close`, `toggle-floating`, `float`,
`tile`, `toggle-float-pinned`, `pin-float`, `unpin-float`, and `resize`.
`toggle-fullscreen`, `enter-fullscreen`, `exit-fullscreen`, `close`,
`toggle-floating`, `float`, `tile`, `toggle-float-pinned`, `pin-float`,
`unpin-float`, and `resize`.
Similarly, `kill-client` applies to the matched window's client in a window
rule, or to the matched client in a client rule.

View file

@ -4,32 +4,20 @@ Jay uses an i3-like tiling layout. Windows are arranged automatically in
containers that can be split horizontally or vertically. Containers can be nested
to create complex layouts.
## Splitting Containers
## Grouping Containers
When you split a window, Jay wraps it in a new container with the specified
direction. Subsequent windows opened in that container are placed side by side
(horizontal split) or stacked top to bottom (vertical split).
When you group a window, Jay wraps it in a new container with the specified
direction. Subsequent windows opened in that group are placed side by side
(horizontal group) or stacked top to bottom (vertical group).
`alt-d` -- `split-horizontal`
: Split the focused window horizontally
`alt-d` -- `make-group-h`
: Group the focused window horizontally
`alt-v` -- `split-vertical`
: Split the focused window vertically
`alt-v` -- `make-group-v`
: Group the focused window vertically
`alt-t` -- `toggle-split`
: Toggle the container's split direction
You can also set the direction explicitly without toggling:
```toml
[shortcuts]
alt-shift-d = "tile-horizontal"
alt-shift-v = "tile-vertical"
```
The `tile-horizontal` action sets the container to horizontal, and
`tile-vertical` sets it to vertical -- unlike `split-horizontal`/`split-vertical`
which wrap the window in a new container first.
`alt-t` -- `change-group-opposite`
: Toggle the current group's direction
## Moving Focus
@ -81,22 +69,14 @@ windows at once. For example, focusing a parent container and then using
By default, a container shows all its children side by side. Mono mode changes
this so only one child is visible at a time, similar to a tabbed view.
`alt-m` -- `toggle-mono`
: Toggle between mono and side-by-side
`alt-m` -- `toggle-tab`
: Toggle between tabbed and side-by-side
You can also right-click any title in a container to toggle mono mode.
In mono mode, scroll over the title bar to cycle between windows in the
container.
For explicit control without toggling:
```toml
[shortcuts]
alt-s = "show-single" # Enter mono mode
alt-a = "show-all" # Exit mono mode
```
## Fullscreen
Press `alt-u` (`toggle-fullscreen`) to make the focused window fill the entire
@ -137,20 +117,17 @@ Double-click a tile's title bar to toggle it between tiled and floating. See
## Summary of Tiling Actions
`split-horizontal`
: Wrap focused window in a horizontal container
`make-group-h`
: Wrap focused window in a horizontal group
`split-vertical`
: Wrap focused window in a vertical container
`make-group-v`
: Wrap focused window in a vertical group
`toggle-split`
: Toggle container split direction
`make-group-tab`
: Wrap focused window in a tabbed group
`tile-horizontal`
: Set container direction to horizontal
`tile-vertical`
: Set container direction to vertical
`change-group-opposite`
: Toggle group direction
`focus-left/right/up/down`
: Move keyboard focus
@ -161,14 +138,8 @@ Double-click a tile's title bar to toggle it between tiled and floating. See
`focus-parent`
: Focus the parent container
`toggle-mono`
: Toggle mono mode
`show-single`
: Enter mono mode
`show-all`
: Exit mono mode
`toggle-tab`
: Toggle tabbed mode
`toggle-fullscreen`
: Toggle fullscreen

View file

@ -92,6 +92,23 @@ impl<'a> Config<'a> {
markup,
scale,
},
Config::RenderFittingOrEllipsized {
height,
max_width,
font,
text,
color,
markup,
scale,
} => Config::RenderFittingOrEllipsized {
height,
max_width,
font,
text: text.into_owned().into(),
color,
markup,
scale,
},
Config::Render {
x,
y,
@ -262,6 +279,26 @@ fn render_fitting(
)
}
fn render_fitting_or_ellipsized(
memfd: &Memfd,
height: Option<i32>,
max_width: i32,
font: &str,
text: &str,
color: Color,
markup: bool,
scale: Option<f64>,
) -> Result<RenderedText, TextError> {
let measurement = measure(memfd, font, text, markup, scale)?;
if measurement.ink_rect.width() <= max_width {
return render_fitting(memfd, height, font, text, color, markup, scale);
}
let height = height.unwrap_or(measurement.ink_rect.height());
render(
memfd, 0, None, max_width, height, 0, font, text, color, true, markup, scale,
)
}
#[derive(Debug, Copy, Clone, Default)]
pub struct TextMeasurement {
pub ink_rect: Rect,
@ -303,6 +340,24 @@ impl RenderWork {
markup,
scale,
} => render_fitting(&self.memfd, height, font, text, color, markup, scale),
Config::RenderFittingOrEllipsized {
height,
max_width,
ref font,
ref text,
color,
markup,
scale,
} => render_fitting_or_ellipsized(
&self.memfd,
height,
max_width,
font,
text,
color,
markup,
scale,
),
Config::Render {
x,
y,
@ -428,6 +483,15 @@ enum Config<'a> {
markup: bool,
scale: Option<f64>,
},
RenderFittingOrEllipsized {
height: Option<i32>,
max_width: i32,
font: Arc<String>,
text: Cow<'a, str>,
color: Color,
markup: bool,
scale: Option<f64>,
},
Render {
x: i32,
y: Option<i32>,
@ -573,6 +637,29 @@ impl TextTexture {
self.apply_config(on_completed, config)
}
pub fn schedule_render_fitting_or_ellipsized(
&self,
on_completed: Rc<dyn OnCompleted>,
height: Option<i32>,
max_width: i32,
font: &Arc<String>,
text: &str,
color: Color,
markup: bool,
scale: Option<f64>,
) {
let config = Config::RenderFittingOrEllipsized {
height,
max_width,
font: font.clone(),
text: text.into(),
color,
markup,
scale,
};
self.apply_config(on_completed, config)
}
pub fn flip(&self) -> Result<(), TextError> {
let res = self
.data

View file

@ -937,14 +937,29 @@ impl ContainerNode {
.persistent
.scale
.get();
let old_textures: AHashMap<_, _> = self
.tab_bar
.borrow()
.as_ref()
.map(|bar| {
bar.entries
.iter()
.map(|entry| (entry.child_id, entry.title_texture.clone()))
.collect()
})
.unwrap_or_default();
let mut bar = TabBar::new(height, render_scale);
for child in self.children.iter() {
let child_id = child.node.node_id();
let title = self.get_child_tab_title(&child, override_id, override_title);
let title_texture = old_textures
.get(&child_id)
.cloned()
.unwrap_or_else(|| Rc::new(RefCell::new(None)));
bar.entries.push(TabBarEntry {
child_id,
title,
title_texture: Rc::new(RefCell::new(None)),
title_texture,
active: child_id == active_id,
attention_requested: child.attention_requested.get(),
x: Cell::new(0),
@ -964,10 +979,27 @@ impl ContainerNode {
let Some(focused) = self.focus_history.last() else {
return;
};
if self.num_children.get() <= 1 {
let focused_node = focused.node.clone();
let focused_active = focused_node.tl_data().active();
if self.num_children.get() == 1 {
let sub = ContainerNode::new(
&self.state,
&self.workspace.get(),
focused_node.clone(),
split,
);
let sub_id = sub.node_id();
if ephemeral {
sub.ephemeral.set(Ephemeral::On);
}
self.clone().cnode_replace_child(&*focused_node, sub);
if focused_active
&& let Some(group) = self.child_nodes.borrow().get(&sub_id).map(|n| n.to_ref())
{
self.update_child_active(&group, true, 1);
}
return;
}
let focused_node = focused.node.clone();
// Record the sibling that comes AFTER the focused child so we can
// insert the new group at the same position.
let next_sibling: Option<Rc<dyn ToplevelNode>> = {
@ -1774,6 +1806,7 @@ impl ContainerNode {
e.title.clone(),
TabBar::entry_colors(&self.state, e),
e.title_texture.clone(),
e.width.get(),
)
})
.collect();
@ -1794,12 +1827,24 @@ impl ContainerNode {
texture_height = (bar_height as f64 * s).round() as _;
}
let mut texture_refs = Vec::new();
for (title, (_, _, text_color), title_texture) in &entries {
let text_padding = self.state.theme.sizes.tab_bar_text_padding.get();
let border_width = self.state.theme.sizes.tab_bar_border_width.get();
for (title, (_, _, text_color), title_texture, tab_width) in &entries {
let max_width = (*tab_width - 2 * (text_padding + border_width)).max(0);
let max_width = if let Some(s) = scale {
(max_width as f64 * s).round() as i32
} else {
max_width
};
if max_width <= 0 {
continue;
}
let mut tex_ref = title_texture.borrow_mut();
let tex = tex_ref.get_or_insert_with(|| TextTexture::new(&self.state, &ctx));
tex.schedule_render_fitting(
tex.schedule_render_fitting_or_ellipsized(
on_completed.clone(),
Some(texture_height),
max_width,
&font,
title,
*text_color,
@ -2465,6 +2510,7 @@ impl ToplevelNodeBase for ContainerNode {
let padding = self.state.theme.sizes.tab_bar_padding.get();
bar.layout_entries(rect.width(), padding);
}
self.schedule_update_tab_textures();
}
// log::info!("tl_change_extents");
self.perform_layout();

View file

@ -23,11 +23,11 @@ alt-shift-j = "move-down"
alt-shift-k = "move-up"
alt-shift-l = "move-right"
alt-d = "split-horizontal"
alt-v = "split-vertical"
alt-d = "make-group-h"
alt-v = "make-group-v"
alt-t = "toggle-split"
alt-m = "toggle-mono"
alt-t = "change-group-opposite"
alt-m = "toggle-tab"
alt-u = "toggle-fullscreen"
alt-f = "focus-parent"

View file

@ -930,7 +930,7 @@
"required": []
},
"Config": {
"description": "This is the top-level table.\n\n- Example:\n\n ```toml\n keymap = \"\"\"\n xkb_keymap {\n xkb_keycodes { include \"evdev+aliases(qwerty)\" };\n xkb_types { include \"complete\" };\n xkb_compat { include \"complete\" };\n xkb_symbols { include \"pc+us+inet(evdev)\" };\n };\n \"\"\"\n\n on-graphics-initialized = { type = \"exec\", exec = \"mako\" }\n\n [shortcuts]\n alt-h = \"focus-left\"\n alt-j = \"focus-down\"\n alt-k = \"focus-up\"\n alt-l = \"focus-right\"\n\n alt-shift-h = \"move-left\"\n alt-shift-j = \"move-down\"\n alt-shift-k = \"move-up\"\n alt-shift-l = \"move-right\"\n\n alt-d = \"split-horizontal\"\n alt-v = \"split-vertical\"\n\n alt-t = \"toggle-split\"\n alt-m = \"toggle-mono\"\n alt-u = \"toggle-fullscreen\"\n\n alt-f = \"focus-parent\"\n alt-shift-c = \"close\"\n alt-shift-f = \"toggle-floating\"\n Super_L = { type = \"exec\", exec = \"alacritty\" }\n alt-p = { type = \"exec\", exec = \"bemenu-run\" }\n alt-q = \"quit\"\n alt-shift-r = \"reload-config-toml\"\n\n ctrl-alt-F1 = { type = \"switch-to-vt\", num = 1 }\n ctrl-alt-F2 = { type = \"switch-to-vt\", num = 2 }\n # ...\n\n alt-F1 = { type = \"show-workspace\", name = \"1\" }\n alt-F2 = { type = \"show-workspace\", name = \"2\" }\n # ...\n\n alt-shift-F1 = { type = \"move-to-workspace\", name = \"1\" }\n alt-shift-F2 = { type = \"move-to-workspace\", name = \"2\" }\n # ...\n ```\n",
"description": "This is the top-level table.\n\n- Example:\n\n ```toml\n keymap = \"\"\"\n xkb_keymap {\n xkb_keycodes { include \"evdev+aliases(qwerty)\" };\n xkb_types { include \"complete\" };\n xkb_compat { include \"complete\" };\n xkb_symbols { include \"pc+us+inet(evdev)\" };\n };\n \"\"\"\n\n on-graphics-initialized = { type = \"exec\", exec = \"mako\" }\n\n [shortcuts]\n alt-h = \"focus-left\"\n alt-j = \"focus-down\"\n alt-k = \"focus-up\"\n alt-l = \"focus-right\"\n\n alt-shift-h = \"move-left\"\n alt-shift-j = \"move-down\"\n alt-shift-k = \"move-up\"\n alt-shift-l = \"move-right\"\n\n alt-d = \"make-group-h\"\n alt-v = \"make-group-v\"\n\n alt-t = \"change-group-opposite\"\n alt-m = \"toggle-tab\"\n alt-u = \"toggle-fullscreen\"\n\n alt-f = \"focus-parent\"\n alt-shift-c = \"close\"\n alt-shift-f = \"toggle-floating\"\n Super_L = { type = \"exec\", exec = \"alacritty\" }\n alt-p = { type = \"exec\", exec = \"bemenu-run\" }\n alt-q = \"quit\"\n alt-shift-r = \"reload-config-toml\"\n\n ctrl-alt-F1 = { type = \"switch-to-vt\", num = 1 }\n ctrl-alt-F2 = { type = \"switch-to-vt\", num = 2 }\n # ...\n\n alt-F1 = { type = \"show-workspace\", name = \"1\" }\n alt-F2 = { type = \"show-workspace\", name = \"2\" }\n # ...\n\n alt-shift-F1 = { type = \"move-to-workspace\", name = \"1\" }\n alt-shift-F2 = { type = \"move-to-workspace\", name = \"2\" }\n # ...\n ```\n",
"type": "object",
"properties": {
"keymap": {
@ -1993,7 +1993,7 @@
},
"SimpleActionName": {
"type": "string",
"description": "The name of a `simple` Action.\n\nWhen used inside a window rule, the following actions apply to the matched window\ninstead fo the focused window:\n\n- `move-left`\n- `move-down`\n- `move-up`\n- `move-right`\n- `split-horizontal`\n- `split-vertical`\n- `toggle-split`\n- `tile-horizontal`\n- `tile-vertical`\n- `toggle-split`\n- `show-single`\n- `show-all`\n- `toggle-fullscreen`\n- `enter-fullscreen`\n- `exit-fullscreen`\n- `close`\n- `toggle-floating`\n- `float`\n- `tile`\n- `toggle-float-pinned`\n- `pin-float`\n- `unpin-float`\n\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n",
"description": "The name of a `simple` Action.\n\nWhen used inside a window rule, the following actions apply to the matched window\ninstead fo the focused window:\n\n- `move-left`\n- `move-down`\n- `move-up`\n- `move-right`\n- `toggle-fullscreen`\n- `enter-fullscreen`\n- `exit-fullscreen`\n- `close`\n- `toggle-floating`\n- `float`\n- `tile`\n- `toggle-float-pinned`\n- `pin-float`\n- `unpin-float`\n\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n",
"enum": [
"focus-left",
"focus-down",
@ -2004,14 +2004,11 @@
"move-up",
"move-right",
"move-right",
"split-horizontal",
"split-vertical",
"toggle-split",
"tile-horizontal",
"tile-vertical",
"toggle-mono",
"show-single",
"show-all",
"make-group-h",
"make-group-v",
"make-group-tab",
"change-group-opposite",
"toggle-tab",
"toggle-fullscreen",
"enter-fullscreen",
"exit-fullscreen",

View file

@ -1659,11 +1659,11 @@ This is the top-level table.
alt-shift-k = "move-up"
alt-shift-l = "move-right"
alt-d = "split-horizontal"
alt-v = "split-vertical"
alt-d = "make-group-h"
alt-v = "make-group-v"
alt-t = "toggle-split"
alt-m = "toggle-mono"
alt-t = "change-group-opposite"
alt-m = "toggle-tab"
alt-u = "toggle-fullscreen"
alt-f = "focus-parent"
@ -4397,14 +4397,6 @@ instead fo the focused window:
- `move-down`
- `move-up`
- `move-right`
- `split-horizontal`
- `split-vertical`
- `toggle-split`
- `tile-horizontal`
- `tile-vertical`
- `toggle-split`
- `show-single`
- `show-all`
- `toggle-fullscreen`
- `enter-fullscreen`
- `exit-fullscreen`
@ -4464,38 +4456,25 @@ The string should have one of the following values:
Move the currently focused window one to the right.
- `split-horizontal`:
- `make-group-h`:
Split the currently focused window horizontally.
Wraps the focused window in a horizontal group.
- `split-vertical`:
- `make-group-v`:
Split the currently focused window vertically.
Wraps the focused window in a vertical group.
- `toggle-split`:
- `make-group-tab`:
Toggle the split of the currently focused container between vertical and
horizontal.
Wraps the focused window in a tabbed group.
- `tile-horizontal`:
- `change-group-opposite`:
Sets the split of the currently focused container to horizontal.
Toggles the current group's direction.
- `tile-vertical`:
- `toggle-tab`:
Sets the split of the currently focused container to vertical.
- `toggle-mono`:
Toggle the currently focused container between showing a single and all children.
- `show-single`:
Makes the currently focused container show a single child.
- `show-all`:
Makes the currently focused container show all children.
Toggles the current group between tabbed and split mode.
- `toggle-fullscreen`:

View file

@ -1016,14 +1016,6 @@ SimpleActionName:
- `move-down`
- `move-up`
- `move-right`
- `split-horizontal`
- `split-vertical`
- `toggle-split`
- `tile-horizontal`
- `tile-vertical`
- `toggle-split`
- `show-single`
- `show-all`
- `toggle-fullscreen`
- `enter-fullscreen`
- `exit-fullscreen`
@ -1062,25 +1054,16 @@ SimpleActionName:
description: Move the currently focused window one to the right.
- value: move-right
description: Move the currently focused window one to the right.
- value: split-horizontal
description: Split the currently focused window horizontally.
- value: split-vertical
description: Split the currently focused window vertically.
- value: toggle-split
description: |
Toggle the split of the currently focused container between vertical and
horizontal.
- value: tile-horizontal
description: Sets the split of the currently focused container to horizontal.
- value: tile-vertical
description: Sets the split of the currently focused container to vertical.
- value: toggle-mono
description: |
Toggle the currently focused container between showing a single and all children.
- value: show-single
description: Makes the currently focused container show a single child.
- value: show-all
description: Makes the currently focused container show all children.
- value: make-group-h
description: Wraps the focused window in a horizontal group.
- value: make-group-v
description: Wraps the focused window in a vertical group.
- value: make-group-tab
description: Wraps the focused window in a tabbed group.
- value: change-group-opposite
description: Toggles the current group's direction.
- value: toggle-tab
description: Toggles the current group between tabbed and split mode.
- value: toggle-fullscreen
description: Toggle the currently focused window between fullscreen and windowed.
- value: enter-fullscreen
@ -2467,11 +2450,11 @@ Config:
alt-shift-k = "move-up"
alt-shift-l = "move-right"
alt-d = "split-horizontal"
alt-v = "split-vertical"
alt-d = "make-group-h"
alt-v = "make-group-v"
alt-t = "toggle-split"
alt-m = "toggle-mono"
alt-t = "change-group-opposite"
alt-m = "toggle-tab"
alt-u = "toggle-fullscreen"
alt-f = "focus-parent"