Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions book/src/configuration/misc.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,19 @@ window-management-key = "Alt_L"
The value should be a keysym name from
[KBVM](https://docs.rs/kbvm/latest/kbvm/syms/index.html).

## Split Reuses Container

Controls whether splitting a window that is the only window in its container
reuses that container.

If this is disabled, splitting such a window wraps it in another container,
creating a redundant nesting level. If this is enabled, the split direction of
the existing container is changed instead.

```toml
split-reuses-container = false # default
```

## Middle-Click Paste

Controls whether middle-clicking pastes the primary selection. Changing this
Expand Down
10 changes: 10 additions & 0 deletions jay-config/src/_private/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,16 @@ impl ConfigClient {
above
}

pub fn set_split_reuses_container(&self, reuse: bool) {
self.send(&ClientMessage::SetSplitReusesContainer { reuse });
}

pub fn get_split_reuses_container(&self) -> bool {
let res = self.send_with_response(&ClientMessage::GetSplitReusesContainer);
get_response!(res, false, GetSplitReusesContainer { reuse });
reuse
}

pub fn set_show_bar(&self, show: bool) {
self.send(&ClientMessage::SetShowBar { show });
}
Expand Down
7 changes: 7 additions & 0 deletions jay-config/src/_private/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,10 @@ pub enum ClientMessage<'a> {
GetPlaneColorPipelinesEnabled {
device: DrmDevice,
},
SetSplitReusesContainer {
reuse: bool,
},
GetSplitReusesContainer,
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down Expand Up @@ -1282,6 +1286,9 @@ pub enum Response {
GetPlaneColorPipelinesEnabled {
enabled: bool,
},
GetSplitReusesContainer {
reuse: bool,
},
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down
24 changes: 24 additions & 0 deletions jay-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,30 @@ pub fn set_show_float_pin_icon(show: bool) {
get!().set_show_float_pin_icon(show);
}

/// Sets whether splitting a window that is the only child of its container reuses
/// that container.
///
/// If disabled, splitting such a window wraps it in another container. If enabled, the split direction of the existing container
/// is changed instead.
///
/// The default is `false`.
pub fn set_split_reuses_container(reuse: bool) {
get!().set_split_reuses_container(reuse)
}

/// Returns whether splitting a window that is the only child of its container reuses
/// that container.
pub fn get_split_reuses_container() -> bool {
get!(false).get_split_reuses_container()
}

/// Toggles whether splitting a window that is the only child of its container reuses
/// that container.
pub fn toggle_split_reuses_container() {
let get = get!();
get.set_split_reuses_container(!get.get_split_reuses_container());
}

/// Sets whether the built-in bar is shown.
///
/// The default is `true`.
Expand Down
1 change: 1 addition & 0 deletions src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ fn start_compositor2(
backend_connector_state_serials: Default::default(),
head_names: Default::default(),
show_bar: Cell::new(true),
split_reuses_container: Cell::new(false),
enable_primary_selection: Cell::new(true),
workspace_display_order: Cell::new(WorkspaceDisplayOrder::Manual),
outputs_without_hc: Default::default(),
Expand Down
14 changes: 14 additions & 0 deletions src/config/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1816,6 +1816,16 @@ impl ConfigProxyHandler {
});
}

fn handle_set_split_reuses_container(&self, reuse: bool) {
self.state.set_split_reuses_container(reuse);
}

fn handle_get_split_reuses_container(&self) {
self.respond(Response::GetSplitReusesContainer {
reuse: self.state.split_reuses_container.get(),
});
}

fn handle_set_show_bar(&self, show: bool) {
self.state.set_show_bar(show);
}
Expand Down Expand Up @@ -3832,6 +3842,10 @@ impl ConfigProxyHandler {
ClientMessage::GetContentType { window } => self
.handle_get_content_type(window)
.wrn("get_content_type")?,
ClientMessage::SetSplitReusesContainer { reuse } => {
self.handle_set_split_reuses_container(reuse)
}
ClientMessage::GetSplitReusesContainer => self.handle_get_split_reuses_container(),
ClientMessage::SetShowBar { show } => self.handle_set_show_bar(show),
ClientMessage::GetShowBar => self.handle_get_show_bar(),
ClientMessage::SetShowTitles { show } => self.handle_set_show_titles(show),
Expand Down
15 changes: 15 additions & 0 deletions src/control_center/cc_look_and_feel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,21 @@ impl LookAndFeelPane {
self.state.float_above_fullscreen.get(),
|v| self.state.set_float_above_fullscreen(v),
);
bool_ui(
ui,
"Split Reuses Container",
|ui| {
tip(ui, |ui| {
ui.label(concat!(
"Splitting the only window in a container changes the split ",
"direction of that container.",
));
ui.label("Otherwise the window is wrapped in a new container.");
});
},
self.state.split_reuses_container.get(),
|v| self.state.set_split_reuses_container(v),
);
row(ui, "Font", |ui| {
let mut v = self.state.theme.font.get().to_string();
if text_edit(ui, &mut v).changed() {
Expand Down
10 changes: 10 additions & 0 deletions src/it/test_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,16 @@ impl TestConfig {
self.send(ClientMessage::SetBarPosition { position })
}

pub fn set_split_reuses_container(&self, reuse: bool) -> TestResult {
self.send(ClientMessage::SetSplitReusesContainer { reuse })
}

pub fn get_split_reuses_container(&self) -> Result<bool, TestError> {
let reply = self.send_with_reply(ClientMessage::GetSplitReusesContainer)?;
get_response!(reply, GetSplitReusesContainer { reuse });
Ok(reuse)
}

pub fn set_show_bar(&self, show: bool) -> TestResult {
self.send(ClientMessage::SetShowBar { show })
}
Expand Down
6 changes: 6 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ pub struct State {
pub backend_connector_state_serials: BackendConnectorStateSerials,
pub head_names: HeadNames,
pub show_bar: Cell<bool>,
pub split_reuses_container: Cell<bool>,
pub enable_primary_selection: Cell<bool>,
pub workspace_display_order: Cell<WorkspaceDisplayOrder>,
pub outputs_without_hc: NumCell<usize>,
Expand Down Expand Up @@ -2612,6 +2613,11 @@ impl State {
let initial = config.initial_output_for_workspace(name)?;
Some(initial.map(|o| o.id))
}

pub fn set_split_reuses_container(&self, v: bool) {
self.split_reuses_container.set(v);
self.trigger_cci(CCI_LOOK_AND_FEEL);
}
}

#[derive(Debug, Error)]
Expand Down
4 changes: 4 additions & 0 deletions src/tree/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,10 @@ impl ContainerNode {
self.update_title();
}

pub fn num_children(&self) -> usize {
self.num_children.get()
}

pub fn set_split(self: &Rc<Self>, split: ContainerSplit) {
if self.set_ns_split(split) != split {
self.update_content_size();
Expand Down
7 changes: 7 additions & 0 deletions src/tree/toplevel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,13 @@ pub fn toplevel_create_split(state: &Rc<State>, tl: Rc<dyn ToplevelNode>, axis:
Some(pn) => pn,
_ => return,
};
if state.split_reuses_container.get()
&& let Some(pn) = toplevel_parent_container(&*tl)
&& pn.num_children() == 1
{
pn.set_split(axis);
return;
}
if let Some(pn) = pn.node_into_containing_node() {
let cn = ContainerNode::new(state, &ws, tl.clone(), axis);
pn.cnode_replace_child(&*tl, cn);
Expand Down
1 change: 1 addition & 0 deletions toml-config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ pub struct Config {
pub pointer_revert_key: Option<KeySym>,
pub use_hardware_cursor: Option<bool>,
pub show_bar: Option<bool>,
pub split_reuses_container: Option<bool>,
pub show_titles: Option<bool>,
pub focus_history: Option<FocusHistory>,
pub middle_click_paste: Option<bool>,
Expand Down
3 changes: 3 additions & 0 deletions toml-config/src/config/parsers/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ impl Parser for ConfigParser<'_, '_> {
transactions_val,
cursor_size,
device_config_filter,
split_reuses_container,
),
) = ext.extract((
(
Expand Down Expand Up @@ -242,6 +243,7 @@ impl Parser for ConfigParser<'_, '_> {
opt(val("transactions")),
recover(opt(s32("cursor-size"))),
recover(opt(str("device-config-filter"))),
recover(opt(bol("split-reuses-container"))),
),
))?;
let mut keymap = None;
Expand Down Expand Up @@ -679,6 +681,7 @@ impl Parser for ConfigParser<'_, '_> {
pointer_revert_key,
use_hardware_cursor: use_hardware_cursor.despan(),
show_bar: show_bar.despan(),
split_reuses_container: split_reuses_container.despan(),
show_titles: show_titles.despan(),
focus_history,
middle_click_paste: middle_click_paste.despan(),
Expand Down
4 changes: 4 additions & 0 deletions toml-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ use jay_config::set_session_management_enabled;
use jay_config::set_show_bar;
use jay_config::set_show_float_pin_icon;
use jay_config::set_show_titles;
use jay_config::set_split_reuses_container;
use jay_config::set_transaction_timeout;
use jay_config::set_ui_drag_enabled;
use jay_config::set_ui_drag_threshold;
Expand Down Expand Up @@ -1840,6 +1841,9 @@ fn load_config(initial_load: bool, auto_reload: bool, persistent: &Rc<Persistent
if let Some(v) = config.show_bar {
set_show_bar(v);
}
if let Some(v) = config.split_reuses_container {
set_split_reuses_container(v);
}
if let Some(v) = config.show_titles {
set_show_titles(v);
}
Expand Down
4 changes: 4 additions & 0 deletions toml-spec/spec/spec.generated.json
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,10 @@
"type": "boolean",
"description": "Configures whether the default seat uses hardware cursors.\n\nThe default is `true`.\n"
},
"split-reuses-container": {
"type": "boolean",
"description": "Configures whether splitting a window that is the only window in its container\nreuses that container.\n\nIf this is disabled, splitting such a window wraps it in another container. If this is enabled, the split direction of\nthe existing container is changed instead.\n\nThe default is `false`.\n"
},
"show-bar": {
"type": "boolean",
"description": "Configures whether the built-in bar is shown.\n\nThe default is `true`.\n"
Expand Down
12 changes: 12 additions & 0 deletions toml-spec/spec/spec.generated.md
Original file line number Diff line number Diff line change
Expand Up @@ -2489,6 +2489,18 @@ The table has the following fields:

The value of this field should be a boolean.

- `split-reuses-container` (optional):

Configures whether splitting a window that is the only window in its container
reuses that container.

If this is disabled, splitting such a window wraps it in another container. If this is enabled, the split direction of
the existing container is changed instead.

The default is `false`.

The value of this field should be a boolean.

- `show-bar` (optional):

Configures whether the built-in bar is shown.
Expand Down
11 changes: 11 additions & 0 deletions toml-spec/spec/spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3304,6 +3304,17 @@ Config:
Configures whether the default seat uses hardware cursors.

The default is `true`.
split-reuses-container:
kind: boolean
required: false
description: |
Configures whether splitting a window that is the only window in its container
reuses that container.

If this is disabled, splitting such a window wraps it in another container. If this is enabled, the split direction of
the existing container is changed instead.

The default is `false`.
show-bar:
kind: boolean
required: false
Expand Down