diff --git a/book/src/tiling.md b/book/src/tiling.md index 2ff61d5e..650cd73a 100644 --- a/book/src/tiling.md +++ b/book/src/tiling.md @@ -77,20 +77,6 @@ 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. -## Autotiling - -Autotiling makes newly tiled windows alternate split direction from the focused -tiled window. The first split uses the containing group direction, then later -windows wrap the focused tile in the opposite direction, producing a horizontal, -vertical, horizontal pattern as the layout grows. - -```toml -[shortcuts] -alt-a = "toggle-autotile" -``` - -Manual grouping and split commands still use the direction you request. - ## Fullscreen Press `alt-u` (`toggle-fullscreen`) to make the focused window fill the entire diff --git a/crates/jay-config-schema/src/action.rs b/crates/jay-config-schema/src/action.rs index 8a774a06..647308b0 100644 --- a/crates/jay-config-schema/src/action.rs +++ b/crates/jay-config-schema/src/action.rs @@ -17,9 +17,6 @@ pub enum SimpleCommand { SetFloating(bool), ToggleFullscreen, SetFullscreen(bool), - SendToScratchpad, - ToggleScratchpad, - CycleScratchpad, Forward(bool), EnableWindowManagement(bool), SetFloatAboveFullscreen(bool), diff --git a/crates/jay-config-schema/src/command.rs b/crates/jay-config-schema/src/command.rs index 062dee52..4dc63f98 100644 --- a/crates/jay-config-schema/src/command.rs +++ b/crates/jay-config-schema/src/command.rs @@ -5,7 +5,6 @@ pub struct Exec { pub prog: String, pub args: Vec, pub envs: Vec<(String, String)>, - pub tag: Option, } #[derive(Debug, Clone)] diff --git a/crates/jay-config-schema/src/lib.rs b/crates/jay-config-schema/src/lib.rs index 051a5ee7..432a7810 100644 --- a/crates/jay-config-schema/src/lib.rs +++ b/crates/jay-config-schema/src/lib.rs @@ -20,9 +20,7 @@ pub use animations::{AnimationCurveConfig, Animations}; pub use command::{Exec, Status}; pub use input::InputMatch; pub use keymap::ConfigKeymap; -pub use model::{ - Action, ClientRule, Config, Input, InputMode, NamedAction, Scratchpad, Shortcut, WindowRule, -}; +pub use model::{Action, ClientRule, Config, Input, InputMode, NamedAction, Shortcut, WindowRule}; pub use options::{ ColorManagement, Float, FocusHistory, Libei, RepeatRate, SimpleIm, Tearing, UiDrag, Vrr, Xwayland, diff --git a/crates/jay-config-schema/src/model.rs b/crates/jay-config-schema/src/model.rs index 291bb448..4a4bf430 100644 --- a/crates/jay-config-schema/src/model.rs +++ b/crates/jay-config-schema/src/model.rs @@ -48,15 +48,6 @@ pub enum Action { MoveToWorkspace { name: String, }, - SendToScratchpad { - name: String, - }, - ToggleScratchpad { - name: String, - }, - CycleScratchpad { - name: String, - }, Multi { actions: Vec, }, @@ -245,12 +236,4 @@ pub struct Config { pub simple_im: Option, pub fallback_output_mode: Option, pub mouse_follows_focus: Option, - pub scratchpads: Vec, - pub autotile: Option, -} - -#[derive(Debug, Clone)] -pub struct Scratchpad { - pub name: String, - pub exec: Option, } diff --git a/crates/jay-config-schema/src/rules.rs b/crates/jay-config-schema/src/rules.rs index 563c60e1..da36cc89 100644 --- a/crates/jay-config-schema/src/rules.rs +++ b/crates/jay-config-schema/src/rules.rs @@ -32,8 +32,6 @@ pub struct ClientMatch { pub comm_regex: Option, pub exe: Option, pub exe_regex: Option, - pub tag: Option, - pub tag_regex: Option, } #[derive(Default, Debug, Clone)] diff --git a/crates/jay-config/src/_private/client.rs b/crates/jay-config/src/_private/client.rs index 4bd15acf..c28f1597 100644 --- a/crates/jay-config/src/_private/client.rs +++ b/crates/jay-config/src/_private/client.rs @@ -308,15 +308,7 @@ impl ConfigClient { .drain() .map(|(a, b)| (a, b.into_raw_fd())) .collect(); - if command.tag.is_some() { - self.send(&ClientMessage::Run3 { - prog: &command.prog, - args: command.args.clone(), - env, - fds, - tag: command.tag.as_deref(), - }); - } else if fds.is_empty() { + if fds.is_empty() { self.send(&ClientMessage::Run { prog: &command.prog, args: command.args.clone(), @@ -600,22 +592,6 @@ impl ConfigClient { self.send(&ClientMessage::SetWindowWorkspace { window, workspace }); } - pub fn seat_send_to_scratchpad(&self, seat: Seat, name: &str) { - self.send(&ClientMessage::SeatSendToScratchpad { seat, name }); - } - - pub fn seat_toggle_scratchpad(&self, seat: Seat, name: &str) { - self.send(&ClientMessage::SeatToggleScratchpad { seat, name }); - } - - pub fn seat_cycle_scratchpad(&self, seat: Seat, name: &str) { - self.send(&ClientMessage::SeatCycleScratchpad { seat, name }); - } - - pub fn window_send_to_scratchpad(&self, window: Window, name: &str) { - self.send(&ClientMessage::WindowSendToScratchpad { window, name }); - } - pub fn seat_split(&self, seat: Seat) -> Axis { let res = self.send_with_response(&ClientMessage::GetSeatSplit { seat }); get_response!(res, Axis::Horizontal, GetSplit { axis }); @@ -1822,8 +1798,6 @@ impl ConfigClient { ClientCriterion::CommRegex(t) => string!(t, Comm, true), ClientCriterion::Exe(t) => string!(t, Exe, false), ClientCriterion::ExeRegex(t) => string!(t, Exe, true), - ClientCriterion::Tag(t) => string!(t, Tag, false), - ClientCriterion::TagRegex(t) => string!(t, Tag, true), }; let res = self.send_with_response(&ClientMessage::CreateClientMatcher { criterion }); get_response!( @@ -2042,12 +2016,6 @@ impl ConfigClient { self.send(&ClientMessage::SetAutotile { enabled }); } - pub fn get_autotile(&self) -> bool { - let res = self.send_with_response(&ClientMessage::GetAutotile); - get_response!(res, false, GetAutotile { enabled }); - enabled - } - pub fn set_tab_title_align(&self, align: u32) { self.send(&ClientMessage::SetTabTitleAlign { align }); } diff --git a/crates/jay-config/src/client.rs b/crates/jay-config/src/client.rs index 5a2e4173..5365329c 100644 --- a/crates/jay-config/src/client.rs +++ b/crates/jay-config/src/client.rs @@ -91,10 +91,6 @@ pub enum ClientCriterion<'a> { Exe(&'a str), /// Matches the `/proc/pid/exe` of the client with a regular expression. ExeRegex(&'a str), - /// Matches the tag of the client verbatim. - Tag(&'a str), - /// Matches the tag of the client with a regular expression. - TagRegex(&'a str), } impl ClientCriterion<'_> { diff --git a/crates/jay-config/src/exec.rs b/crates/jay-config/src/exec.rs index bedc70c3..4c858900 100644 --- a/crates/jay-config/src/exec.rs +++ b/crates/jay-config/src/exec.rs @@ -22,7 +22,6 @@ pub struct Command { pub(crate) args: Vec, pub(crate) env: HashMap, pub(crate) fds: RefCell>, - pub(crate) tag: Option, } impl Command { @@ -38,7 +37,6 @@ impl Command { args: vec![], env: Default::default(), fds: Default::default(), - tag: Default::default(), } } @@ -84,12 +82,6 @@ impl Command { self.fd(2, fd) } - /// Adds a tag to Wayland connections created by the spawned command. - pub fn tag(&mut self, tag: &str) -> &mut Self { - self.tag = Some(tag.to_owned()); - self - } - /// Executes the command. /// /// This consumes all attached file descriptors. diff --git a/crates/jay-config/src/input.rs b/crates/jay-config/src/input.rs index c052bba7..36f4bfa6 100644 --- a/crates/jay-config/src/input.rs +++ b/crates/jay-config/src/input.rs @@ -466,33 +466,6 @@ impl Seat { get!().set_seat_workspace(self, workspace) } - /// Sends the currently focused window to a scratchpad. - /// - /// Use an empty string for the default scratchpad. - pub fn send_to_scratchpad(self, name: &str) { - get!().seat_send_to_scratchpad(self, name) - } - - /// Toggles a scratchpad. - /// - /// If the scratchpad has a visible window, that window is hidden. Otherwise, the - /// most recently hidden window in the scratchpad is shown on the current workspace. - /// Scratchpad windows are always shown floating. - /// Use an empty string for the default scratchpad. - pub fn toggle_scratchpad(self, name: &str) { - get!().seat_toggle_scratchpad(self, name) - } - - /// Cycles through the windows of a scratchpad, one at a time. - /// - /// With nothing shown, the first window is brought up; each further invocation - /// hides the current window and shows the next; after the last window the - /// scratchpad is hidden again. Scratchpad windows are always shown floating. - /// Use an empty string for the default scratchpad. - pub fn cycle_scratchpad(self, name: &str) { - get!().seat_cycle_scratchpad(self, name) - } - /// Toggles whether the currently focused window is fullscreen. pub fn toggle_fullscreen(self) { let c = get!(); diff --git a/crates/jay-config/src/lib.rs b/crates/jay-config/src/lib.rs index 91dbbcae..c7e585bf 100644 --- a/crates/jay-config/src/lib.rs +++ b/crates/jay-config/src/lib.rs @@ -437,21 +437,14 @@ pub fn get_corner_radius() -> f32 { /// Enables or disables autotiling. /// -/// When enabled, newly tiled windows alternate split orientation from the -/// focused tiled window: the first split uses the containing group's direction, -/// then subsequent splits wrap the focused window in the perpendicular -/// direction. +/// When enabled, new windows are automatically placed in a perpendicular +/// sub-container if the predicted body would be narrower than tall (or vice versa). /// /// The default is `false`. pub fn set_autotile(enabled: bool) { get!().set_autotile(enabled) } -/// Returns whether autotiling is enabled. -pub fn get_autotile() -> bool { - get!(false).get_autotile() -} - /// Sets the horizontal alignment of title text within tab buttons. /// /// - `"start"` — left-aligned (default) diff --git a/crates/jay-config/src/protocol.rs b/crates/jay-config/src/protocol.rs index e45224a0..89bb5556 100644 --- a/crates/jay-config/src/protocol.rs +++ b/crates/jay-config/src/protocol.rs @@ -116,7 +116,6 @@ pub enum ClientCriterionStringField { SandboxInstanceId, Comm, Exe, - Tag, } #[derive(Serialize, Deserialize, Clone, Debug, Hash, Eq, PartialEq)] @@ -412,18 +411,6 @@ pub enum ClientMessage<'a> { seat: Seat, workspace: Workspace, }, - SeatSendToScratchpad { - seat: Seat, - name: &'a str, - }, - SeatToggleScratchpad { - seat: Seat, - name: &'a str, - }, - SeatCycleScratchpad { - seat: Seat, - name: &'a str, - }, GetTimer { name: &'a str, }, @@ -570,13 +557,6 @@ pub enum ClientMessage<'a> { env: Vec<(String, String)>, fds: Vec<(i32, i32)>, }, - Run3 { - prog: &'a str, - args: Vec, - env: Vec<(String, String)>, - fds: Vec<(i32, i32)>, - tag: Option<&'a str>, - }, DisableDefaultSeat, DestroyKeymap { keymap: Keymap, @@ -837,10 +817,6 @@ pub enum ClientMessage<'a> { window: Window, workspace: Workspace, }, - WindowSendToScratchpad { - window: Window, - name: &'a str, - }, SetWindowFullscreen { window: Window, fullscreen: bool, @@ -1062,7 +1038,6 @@ pub enum ClientMessage<'a> { SetAutotile { enabled: bool, }, - GetAutotile, SetTabTitleAlign { align: u32, }, @@ -1326,9 +1301,6 @@ pub enum Response { GetCornerRadius { radius: f32, }, - GetAutotile { - enabled: bool, - }, } #[derive(Serialize, Deserialize, Clone, Debug)] diff --git a/crates/jay-config/src/window.rs b/crates/jay-config/src/window.rs index 96e4d3b1..662cda44 100644 --- a/crates/jay-config/src/window.rs +++ b/crates/jay-config/src/window.rs @@ -205,13 +205,6 @@ impl Window { get!().set_window_workspace(self, workspace) } - /// Sends the window to a scratchpad. - /// - /// Use an empty string for the default scratchpad. - pub fn send_to_scratchpad(self, name: &str) { - get!().window_send_to_scratchpad(self, name) - } - /// Toggles whether the currently focused window is fullscreen. pub fn toggle_fullscreen(self) { self.set_fullscreen(!self.fullscreen()) diff --git a/crates/toml-config/src/config.rs b/crates/toml-config/src/config.rs index f081f3fe..6b82768b 100644 --- a/crates/toml-config/src/config.rs +++ b/crates/toml-config/src/config.rs @@ -28,8 +28,8 @@ pub use jay_config_schema::{ Action, AnimationCurveConfig, Animations, ClientMatch, ClientRule, ColorManagement, Config, ConfigConnector, ConfigDrmDevice, ConfigKeymap, ConnectorMatch, DrmDeviceMatch, Exec, Float, FocusHistory, GenericMatch, Input, InputMatch, InputMode, Libei, MatchExactly, Mode, - NamedAction, Output, OutputMatch, RepeatRate, Scratchpad, Shortcut, SimpleCommand, SimpleIm, - Status, Tearing, Theme, UiDrag, Vrr, WindowMatch, WindowRule, Xwayland, + NamedAction, Output, OutputMatch, RepeatRate, Shortcut, SimpleCommand, SimpleIm, Status, + Tearing, Theme, UiDrag, Vrr, WindowMatch, WindowRule, Xwayland, }; #[derive(Debug, Error)] diff --git a/crates/toml-config/src/config/parsers.rs b/crates/toml-config/src/config/parsers.rs index 4b9cdebd..5bea6371 100644 --- a/crates/toml-config/src/config/parsers.rs +++ b/crates/toml-config/src/config/parsers.rs @@ -40,7 +40,6 @@ pub mod modified_keysym; mod output; mod output_match; mod repeat_rate; -mod scratchpad; pub mod shortcuts; mod simple_im; mod status; diff --git a/crates/toml-config/src/config/parsers/action.rs b/crates/toml-config/src/config/parsers/action.rs index d1cf153a..951cc929 100644 --- a/crates/toml-config/src/config/parsers/action.rs +++ b/crates/toml-config/src/config/parsers/action.rs @@ -117,9 +117,6 @@ impl ActionParser<'_> { "toggle-fullscreen" => ToggleFullscreen, "enter-fullscreen" => SetFullscreen(true), "exit-fullscreen" => SetFullscreen(false), - "send-to-scratchpad" => SendToScratchpad, - "toggle-scratchpad" => ToggleScratchpad, - "cycle-scratchpad" => CycleScratchpad, "focus-parent" => FocusParent, "close" => Close, "disable-pointer-constraint" => DisablePointerConstraint, @@ -224,33 +221,6 @@ impl ActionParser<'_> { Ok(Action::MoveToWorkspace { name }) } - fn parse_send_to_scratchpad(&mut self, ext: &mut Extractor<'_>) -> ParseResult { - let name = ext - .extract(opt(str("name")))? - .map(|name| name.value) - .unwrap_or("") - .to_string(); - Ok(Action::SendToScratchpad { name }) - } - - fn parse_toggle_scratchpad(&mut self, ext: &mut Extractor<'_>) -> ParseResult { - let name = ext - .extract(opt(str("name")))? - .map(|name| name.value) - .unwrap_or("") - .to_string(); - Ok(Action::ToggleScratchpad { name }) - } - - fn parse_cycle_scratchpad(&mut self, ext: &mut Extractor<'_>) -> ParseResult { - let name = ext - .extract(opt(str("name")))? - .map(|name| name.value) - .unwrap_or("") - .to_string(); - Ok(Action::CycleScratchpad { name }) - } - fn parse_configure_connector(&mut self, ext: &mut Extractor<'_>) -> ParseResult { let con = ext .extract(val("connector"))? @@ -580,9 +550,6 @@ impl Parser for ActionParser<'_> { "switch-to-vt" => self.parse_switch_to_vt(&mut ext), "show-workspace" => self.parse_show_workspace(&mut ext), "move-to-workspace" => self.parse_move_to_workspace(&mut ext), - "send-to-scratchpad" => self.parse_send_to_scratchpad(&mut ext), - "toggle-scratchpad" => self.parse_toggle_scratchpad(&mut ext), - "cycle-scratchpad" => self.parse_cycle_scratchpad(&mut ext), "configure-connector" => self.parse_configure_connector(&mut ext), "configure-input" => self.parse_configure_input(&mut ext), "configure-output" => self.parse_configure_output(&mut ext), diff --git a/crates/toml-config/src/config/parsers/client_match.rs b/crates/toml-config/src/config/parsers/client_match.rs index ab61f653..1d8050c2 100644 --- a/crates/toml-config/src/config/parsers/client_match.rs +++ b/crates/toml-config/src/config/parsers/client_match.rs @@ -59,7 +59,7 @@ impl Parser for ClientMatchParser<'_> { exe, exe_regex, ), - (is_xwayland, tag, tag_regex), + (is_xwayland,), ) = ext.extract(( ( opt(str("name")), @@ -83,11 +83,7 @@ impl Parser for ClientMatchParser<'_> { opt(str("exe")), opt(str("exe-regex")), ), - ( - opt(bol("is-xwayland")), - opt(str("tag")), - opt(str("tag-regex")), - ), + (opt(bol("is-xwayland")),), ))?; let mut not = None; if let Some(value) = not_val { @@ -134,8 +130,6 @@ impl Parser for ClientMatchParser<'_> { comm_regex: comm_regex.despan_into(), exe: exe.despan_into(), exe_regex: exe_regex.despan_into(), - tag: tag.despan_into(), - tag_regex: tag_regex.despan_into(), }) } } diff --git a/crates/toml-config/src/config/parsers/config.rs b/crates/toml-config/src/config/parsers/config.rs index ed3b1e70..0932a410 100644 --- a/crates/toml-config/src/config/parsers/config.rs +++ b/crates/toml-config/src/config/parsers/config.rs @@ -28,7 +28,6 @@ use { log_level::LogLevelParser, output::OutputsParser, repeat_rate::RepeatRateParser, - scratchpad::ScratchpadsParser, shortcuts::{ ComplexShortcutsParser, ShortcutsParser, ShortcutsParserError, parse_modified_keysym_str, @@ -157,7 +156,6 @@ impl Parser for ConfigParser<'_> { mouse_follows_focus, animations_val, ), - (scratchpads_val, autotile), ) = ext.extract(( ( opt(val("keymap")), @@ -219,7 +217,6 @@ impl Parser for ConfigParser<'_> { recover(opt(bol("unstable-mouse-follows-focus"))), opt(val("animations")), ), - (opt(val("scratchpads")), recover(opt(bol("autotile")))), ))?; let mut keymap = None; if let Some(value) = keymap_val { @@ -575,13 +572,6 @@ impl Parser for ConfigParser<'_> { } } } - let mut scratchpads = vec![]; - if let Some(value) = scratchpads_val { - match value.parse(&mut ScratchpadsParser(self.0)) { - Ok(v) => scratchpads = v, - Err(e) => log::warn!("Could not parse the scratchpads: {}", self.0.error(e)), - } - } Ok(Config { keymap, repeat_rate, @@ -634,8 +624,6 @@ impl Parser for ConfigParser<'_> { simple_im, fallback_output_mode, mouse_follows_focus: mouse_follows_focus.despan(), - scratchpads, - autotile: autotile.despan(), }) } } diff --git a/crates/toml-config/src/config/parsers/exec.rs b/crates/toml-config/src/config/parsers/exec.rs index 6924bb4a..09473de3 100644 --- a/crates/toml-config/src/config/parsers/exec.rs +++ b/crates/toml-config/src/config/parsers/exec.rs @@ -11,7 +11,7 @@ use { }, }, jay_toml::{ - toml_span::{DespanExt, Span, Spanned, SpannedExt}, + toml_span::{Span, Spanned, SpannedExt}, toml_value::Value, }, }, @@ -52,7 +52,6 @@ impl Parser for ExecParser<'_> { prog: string.to_string(), args: vec![], envs: vec![], - tag: None, }) } @@ -69,7 +68,6 @@ impl Parser for ExecParser<'_> { prog, args, envs: vec![], - tag: None, }) } @@ -79,12 +77,11 @@ impl Parser for ExecParser<'_> { table: &IndexMap, Spanned>, ) -> ParseResult { let mut ext = Extractor::new(self.0, span, table); - let (prog_opt, shell_opt, args_val, envs_val, tag) = ext.extract(( + let (prog_opt, shell_opt, args_val, envs_val) = ext.extract(( opt(str("prog")), opt(str("shell")), opt(arr("args")), opt(val("env")), - opt(str("tag")), ))?; let prog; let mut args = vec![]; @@ -116,7 +113,6 @@ impl Parser for ExecParser<'_> { prog, args, envs, - tag: tag.despan_into(), }) } } diff --git a/crates/toml-config/src/config/parsers/scratchpad.rs b/crates/toml-config/src/config/parsers/scratchpad.rs deleted file mode 100644 index 139935a1..00000000 --- a/crates/toml-config/src/config/parsers/scratchpad.rs +++ /dev/null @@ -1,87 +0,0 @@ -use { - crate::{ - config::{ - Scratchpad, - context::Context, - extractor::{Extractor, ExtractorError, opt, str, val}, - parser::{DataType, ParseResult, Parser, UnexpectedDataType}, - parsers::exec::{ExecParser, ExecParserError}, - }, - jay_toml::{ - toml_span::{Span, Spanned}, - toml_value::Value, - }, - }, - indexmap::IndexMap, - thiserror::Error, -}; - -#[derive(Debug, Error)] -pub enum ScratchpadParserError { - #[error(transparent)] - Expected(#[from] UnexpectedDataType), - #[error(transparent)] - Extract(#[from] ExtractorError), - #[error(transparent)] - Exec(#[from] ExecParserError), -} - -pub struct ScratchpadParser<'a>(pub &'a Context<'a>); - -impl Parser for ScratchpadParser<'_> { - type Value = Scratchpad; - type Error = ScratchpadParserError; - const EXPECTED: &'static [DataType] = &[DataType::Table]; - - fn parse_table( - &mut self, - span: Span, - table: &IndexMap, Spanned>, - ) -> ParseResult { - let mut ext = Extractor::new(self.0, span, table); - let (name, exec_val) = ext.extract((str("name"), opt(val("exec"))))?; - let exec = match exec_val { - None => None, - Some(e) => Some(e.parse_map(&mut ExecParser(self.0))?), - }; - Ok(Scratchpad { - name: name.value.to_string(), - exec, - }) - } -} - -pub struct ScratchpadsParser<'a>(pub &'a Context<'a>); - -impl Parser for ScratchpadsParser<'_> { - type Value = Vec; - type Error = ScratchpadParserError; - const EXPECTED: &'static [DataType] = &[DataType::Table, DataType::Array]; - - fn parse_array(&mut self, _span: Span, array: &[Spanned]) -> ParseResult { - let mut res = vec![]; - for el in array { - match el.parse(&mut ScratchpadParser(self.0)) { - Ok(o) => res.push(o), - Err(e) => { - log::warn!("Could not parse scratchpad: {}", self.0.error(e)); - } - } - } - Ok(res) - } - - fn parse_table( - &mut self, - span: Span, - table: &IndexMap, Spanned>, - ) -> ParseResult { - log::warn!( - "`scratchpads` value should be an array: {}", - self.0.error3(span) - ); - ScratchpadParser(self.0) - .parse_table(span, table) - .map(|v| vec![v]) - } -} diff --git a/crates/toml-config/src/lib.rs b/crates/toml-config/src/lib.rs index 33bc3343..86b411fe 100644 --- a/crates/toml-config/src/lib.rs +++ b/crates/toml-config/src/lib.rs @@ -14,10 +14,9 @@ pub(crate) use jay_toml; use { crate::{ config::{ - Action, AnimationCurveConfig, ClientMatch, ClientRule, Config, ConfigConnector, - ConfigDrmDevice, ConfigKeymap, ConnectorMatch, DrmDeviceMatch, Exec, Input, - InputMatch, Output, OutputMatch, SimpleCommand, Status, Theme, WindowMatch, - WindowRule, parse_config, + Action, AnimationCurveConfig, ClientRule, Config, ConfigConnector, ConfigDrmDevice, + ConfigKeymap, ConnectorMatch, DrmDeviceMatch, Exec, Input, InputMatch, Output, + OutputMatch, SimpleCommand, Status, Theme, WindowRule, parse_config, }, rules::{MatcherTemp, RuleMapper}, shortcuts::ModeState, @@ -29,7 +28,7 @@ use { client::Client, config_dir, exec::{Command, set_env, unset_env}, - get_autotile, get_workspace, + get_workspace, input::{ FocusFollowsMouseMode, InputDevice, Seat, SwitchEvent, capability::CAP_SWITCH, get_seat, input_devices, on_input_device_removed, on_new_input_device, @@ -42,11 +41,11 @@ use { on_devices_enumerated, on_idle, on_unload, quit, set_animation_cubic_bezier, set_animation_curve, set_animation_duration_ms, set_animation_style, set_animations_enabled, set_autotile, set_color_management_enabled, set_corner_radius, - set_default_workspace_capture, set_explicit_sync_enabled, set_float_above_fullscreen, - set_floating_titles, set_idle, set_idle_grace_period, set_key_press_enables_dpms, - set_middle_click_paste_enabled, set_mouse_move_enables_dpms, set_show_bar, - set_show_float_pin_icon, set_show_titles, set_tab_title_align, set_ui_drag_enabled, - set_ui_drag_threshold, + set_default_workspace_capture, + set_explicit_sync_enabled, set_float_above_fullscreen, set_floating_titles, set_idle, + set_idle_grace_period, set_key_press_enables_dpms, set_middle_click_paste_enabled, + set_mouse_move_enables_dpms, set_show_bar, set_show_float_pin_icon, set_show_titles, + set_tab_title_align, set_ui_drag_enabled, set_ui_drag_threshold, status::{set_i3bar_separator, set_status, set_status_command, unset_status_command}, switch_to_vt, tasks::{self, JoinHandle}, @@ -186,9 +185,6 @@ impl ActionExt for Action { SimpleCommand::Move(dir) => window_or_seat!(s, s.move_(dir)), SimpleCommand::ToggleFullscreen => window_or_seat!(s, s.toggle_fullscreen()), SimpleCommand::SetFullscreen(b) => window_or_seat!(s, s.set_fullscreen(b)), - SimpleCommand::SendToScratchpad => window_or_seat!(s, s.send_to_scratchpad("")), - SimpleCommand::ToggleScratchpad => b.new(move || s.toggle_scratchpad("")), - SimpleCommand::CycleScratchpad => b.new(move || s.cycle_scratchpad("")), SimpleCommand::FocusParent => b.new(move || s.focus_parent()), SimpleCommand::Close => window_or_seat!(s, s.close()), SimpleCommand::DisablePointerConstraint => { @@ -284,7 +280,12 @@ impl ActionExt for Action { SimpleCommand::MoveTabLeft => b.new(move || s.move_tab(false)), SimpleCommand::MoveTabRight => b.new(move || s.move_tab(true)), SimpleCommand::SetAutotile(enabled) => b.new(move || set_autotile(enabled)), - SimpleCommand::ToggleAutotile => b.new(move || set_autotile(!get_autotile())), + SimpleCommand::ToggleAutotile => { + b.new(move || { + // Toggle not directly supported; set to true + set_autotile(true) + }) + } }, Action::Multi { actions } => { let actions: Vec<_> = actions.into_iter().map(|a| a.into_fn(state)).collect(); @@ -321,9 +322,6 @@ impl ActionExt for Action { let workspace = get_workspace(&name); window_or_seat!(s, s.set_workspace(workspace)) } - Action::SendToScratchpad { name } => window_or_seat!(s, s.send_to_scratchpad(&name)), - Action::ToggleScratchpad { name } => b.new(move || s.toggle_scratchpad(&name)), - Action::CycleScratchpad { name } => b.new(move || s.cycle_scratchpad(&name)), Action::ConfigureConnector { con } => b.new(move || { for c in connectors() { if con.match_.matches(c) { @@ -1528,46 +1526,6 @@ fn load_config(initial_load: bool, auto_reload: bool, persistent: &Rc Command { @@ -1867,9 +1822,6 @@ fn create_command(exec: &Exec) -> Command { for (k, v) in &exec.envs { command.env(k, v); } - if let Some(tag) = &exec.tag { - command.tag(tag); - } command } diff --git a/crates/toml-config/src/rules.rs b/crates/toml-config/src/rules.rs index 4b83eecd..f5d6d6d7 100644 --- a/crates/toml-config/src/rules.rs +++ b/crates/toml-config/src/rules.rs @@ -127,8 +127,6 @@ impl Rule for ClientRule { value_ref!(CommRegex, comm_regex); value_ref!(Exe, exe); value_ref!(ExeRegex, exe_regex); - value_ref!(Tag, tag); - value_ref!(TagRegex, tag_regex); value!(Uid, uid); value!(Pid, pid); bool!(Sandboxed, sandboxed); diff --git a/crates/toml-spec/spec/spec.generated.json b/crates/toml-spec/spec/spec.generated.json index 61312cf6..182dde2f 100644 --- a/crates/toml-spec/spec/spec.generated.json +++ b/crates/toml-spec/spec/spec.generated.json @@ -162,54 +162,6 @@ "name" ] }, - { - "description": "Sends the currently focused window to a scratchpad and hides it.\n\nA scratchpad can hold any number of windows. If `name` is omitted, the\ndefault scratchpad is used.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-shift-minus = { type = \"send-to-scratchpad\", name = \"terminal\" }\n ```\n", - "type": "object", - "properties": { - "type": { - "const": "send-to-scratchpad" - }, - "name": { - "type": "string", - "description": "The name of the scratchpad." - } - }, - "required": [ - "type" - ] - }, - { - "description": "Toggles a scratchpad.\n\nIf the scratchpad has a visible window, that window is hidden. Otherwise, the\nmost recently hidden window in the scratchpad is shown on the current workspace.\nOnly one window of a scratchpad is shown at a time, and scratchpad windows are\nalways shown floating. If `name` is omitted, the default scratchpad is used.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-minus = { type = \"toggle-scratchpad\", name = \"terminal\" }\n ```\n", - "type": "object", - "properties": { - "type": { - "const": "toggle-scratchpad" - }, - "name": { - "type": "string", - "description": "The name of the scratchpad." - } - }, - "required": [ - "type" - ] - }, - { - "description": "Cycles through the windows of a scratchpad, one at a time.\n\nWith no window shown, the first window is brought up. Each further invocation\nhides the current window and shows the next; after the last window the\nscratchpad is hidden again. Scratchpad windows are always shown floating.\nIf `name` is omitted, the default scratchpad is used.\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-minus = { type = \"cycle-scratchpad\", name = \"terminal\" }\n ```\n", - "type": "object", - "properties": { - "type": { - "const": "cycle-scratchpad" - }, - "name": { - "type": "string", - "description": "The name of the scratchpad." - } - }, - "required": [ - "type" - ] - }, { "description": "Moves a workspace to a different output.\n\n- Example 1: Move a specific workspace to a named output\n\n ```toml\n [shortcuts]\n alt-F1 = { type = \"move-to-output\", workspace = \"1\", output.name = \"right\" }\n ```\n\n- Example 2: Move the current workspace to a named output\n\n ```toml\n [shortcuts]\n alt-F1 = { type = \"move-to-output\", output.name = \"right\" }\n ```\n\n- Example 3: Move the current workspace to the output on the right (directional)\n\n ```toml\n [shortcuts]\n \"logo+ctrl+shift+Right\" = { type = \"move-to-output\", direction = \"right\" }\n \"logo+ctrl+shift+Left\" = { type = \"move-to-output\", direction = \"left\" }\n \"logo+ctrl+shift+Up\" = { type = \"move-to-output\", direction = \"up\" }\n \"logo+ctrl+shift+Down\" = { type = \"move-to-output\", direction = \"down\" }\n ```\n", "type": "object", @@ -889,14 +841,6 @@ "exe-regex": { "type": "string", "description": "Matches the `/proc/pid/exe` of the client with a regular expression." - }, - "tag": { - "type": "string", - "description": "Matches the tag of the client verbatim." - }, - "tag-regex": { - "type": "string", - "description": "Matches the tag of the client with a regular expression." } }, "required": [] @@ -1213,10 +1157,6 @@ "type": "boolean", "description": "Configures whether middle-click pasting is enabled.\n\nChanging this has no effect on running applications.\n\nThe default is `true`.\n" }, - "autotile": { - "type": "boolean", - "description": "Configures whether autotiling is enabled by default.\n\nWhen enabled, newly mapped tiled windows alternate their split\norientation automatically. This can also be toggled at runtime via the\n`enable-autotile`, `disable-autotile`, and `toggle-autotile` actions.\n\nThe default is `false`.\n" - }, "modes": { "description": "Configures the input modes.\n\nModes can be used to define shortcuts that are only active when the mode is\nactive.\n\n- Example\n\n ```toml\n [modes.\"navigation\".shortcuts]\n w = \"focus-up\"\n a = \"focus-left\"\n s = \"focus-down\"\n d = \"focus-right\"\n r = \"focus-above\"\n f = \"focus-below\"\n q = \"focus-prev\"\n e = \"focus-next\"\n ```\n\nModes can be activated with the `push-mode` and `latch-mode` actions.\n", "type": "object", @@ -1244,14 +1184,6 @@ "egui": { "description": "Sets the egui settings of the compositor.\n", "$ref": "#/$defs/Egui" - }, - "scratchpads": { - "type": "array", - "description": "An array of pre-configured scratchpads.\n\nEach entry launches a program when the graphics are first initialized and\nimmediately parks its window in the named scratchpad. The window is captured\nvia a unique tag attached to the spawned process, so other windows of the\nsame application are never affected.\n\nUse a `toggle-scratchpad` or `cycle-scratchpad` action to bring the windows\nup; they are always shown floating.\n\n- Example:\n\n ```toml\n [[scratchpads]]\n name = \"term\"\n exec = \"foot\"\n\n [[scratchpads]]\n name = \"notes\"\n exec = [\"obsidian\"]\n ```\n", - "items": { - "description": "", - "$ref": "#/$defs/Scratchpad" - } } }, "required": [] @@ -1481,10 +1413,6 @@ "type": "string", "description": "" } - }, - "tag": { - "type": "string", - "description": "Specifies a tag to apply to all spawned wayland connections.\n" } }, "required": [] @@ -2062,23 +1990,6 @@ }, "required": [] }, - "Scratchpad": { - "description": "A pre-configured scratchpad whose program is launched at startup and parked\nin the scratchpad.\n\n- Example:\n\n ```toml\n [[scratchpads]]\n name = \"term\"\n exec = \"foot\"\n ```\n", - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "The name of the scratchpad that the spawned window is parked in." - }, - "exec": { - "description": "The program to launch when the graphics are first initialized.\n\nIf omitted, no program is launched and the scratchpad is only created on\ndemand by `send-to-scratchpad`.\n", - "$ref": "#/$defs/Exec" - } - }, - "required": [ - "name" - ] - }, "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- `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", @@ -2097,15 +2008,9 @@ "make-group-tab", "change-group-opposite", "toggle-tab", - "enable-autotile", - "disable-autotile", - "toggle-autotile", "toggle-fullscreen", "enter-fullscreen", "exit-fullscreen", - "send-to-scratchpad", - "toggle-scratchpad", - "cycle-scratchpad", "focus-parent", "close", "disable-pointer-constraint", diff --git a/crates/toml-spec/spec/spec.generated.md b/crates/toml-spec/spec/spec.generated.md index 27a25895..e68ded70 100644 --- a/crates/toml-spec/spec/spec.generated.md +++ b/crates/toml-spec/spec/spec.generated.md @@ -286,76 +286,6 @@ This table is a tagged union. The variant is determined by the `type` field. It The value of this field should be a string. -- `send-to-scratchpad`: - - Sends the currently focused window to a scratchpad and hides it. - - A scratchpad can hold any number of windows. If `name` is omitted, the - default scratchpad is used. - - - Example: - - ```toml - [shortcuts] - alt-shift-minus = { type = "send-to-scratchpad", name = "terminal" } - ``` - - The table has the following fields: - - - `name` (optional): - - The name of the scratchpad. - - The value of this field should be a string. - -- `toggle-scratchpad`: - - Toggles a scratchpad. - - If the scratchpad has a visible window, that window is hidden. Otherwise, the - most recently hidden window in the scratchpad is shown on the current workspace. - Only one window of a scratchpad is shown at a time, and scratchpad windows are - always shown floating. If `name` is omitted, the default scratchpad is used. - - - Example: - - ```toml - [shortcuts] - alt-minus = { type = "toggle-scratchpad", name = "terminal" } - ``` - - The table has the following fields: - - - `name` (optional): - - The name of the scratchpad. - - The value of this field should be a string. - -- `cycle-scratchpad`: - - Cycles through the windows of a scratchpad, one at a time. - - With no window shown, the first window is brought up. Each further invocation - hides the current window and shows the next; after the last window the - scratchpad is hidden again. Scratchpad windows are always shown floating. - If `name` is omitted, the default scratchpad is used. - - - Example: - - ```toml - [shortcuts] - alt-minus = { type = "cycle-scratchpad", name = "terminal" } - ``` - - The table has the following fields: - - - `name` (optional): - - The name of the scratchpad. - - The value of this field should be a string. - - `move-to-output`: Moves a workspace to a different output. @@ -1479,18 +1409,6 @@ The table has the following fields: The value of this field should be a string. -- `tag` (optional): - - Matches the tag of the client verbatim. - - The value of this field should be a string. - -- `tag-regex` (optional): - - Matches the tag of the client with a regular expression. - - The value of this field should be a string. - ### `ClientMatchExactly` @@ -2436,18 +2354,6 @@ The table has the following fields: The value of this field should be a boolean. -- `autotile` (optional): - - Configures whether autotiling is enabled by default. - - When enabled, newly mapped tiled windows alternate their split - orientation automatically. This can also be toggled at runtime via the - `enable-autotile`, `disable-autotile`, and `toggle-autotile` actions. - - The default is `false`. - - The value of this field should be a boolean. - - `modes` (optional): Configures the input modes. @@ -2548,32 +2454,6 @@ The table has the following fields: The value of this field should be a [Egui](#types-Egui). -- `scratchpads` (optional): - - An array of pre-configured scratchpads. - - Each entry launches a program when the graphics are first initialized and - immediately parks its window in the named scratchpad. The window is captured - via a unique tag attached to the spawned process, so other windows of the - same application are never affected. - - Use a `toggle-scratchpad` or `cycle-scratchpad` action to bring the windows - up; they are always shown floating. - - - Example: - - ```toml - [[scratchpads]] - name = "term" - exec = "foot" - - [[scratchpads]] - name = "notes" - exec = ["obsidian"] - ``` - - The value of this field should be an array of [Scratchpads](#types-Scratchpad). - ### `Connector` @@ -3053,12 +2933,6 @@ The table has the following fields: The value of this field should be a table whose values are strings. -- `tag` (optional): - - Specifies a tag to apply to all spawned wayland connections. - - The value of this field should be a string. - ### `FallbackOutputMode` @@ -4483,40 +4357,6 @@ The table has the following fields: The value of this field should be a string. - -### `Scratchpad` - -A pre-configured scratchpad whose program is launched at startup and parked -in the scratchpad. - -- Example: - - ```toml - [[scratchpads]] - name = "term" - exec = "foot" - ``` - -Values of this type should be tables. - -The table has the following fields: - -- `name` (required): - - The name of the scratchpad that the spawned window is parked in. - - The value of this field should be a string. - -- `exec` (optional): - - The program to launch when the graphics are first initialized. - - If omitted, no program is launched and the scratchpad is only created on - demand by `send-to-scratchpad`. - - The value of this field should be a [Exec](#types-Exec). - - ### `SimpleActionName` @@ -4608,18 +4448,6 @@ The string should have one of the following values: Toggles the current group between tabbed and split mode. -- `enable-autotile`: - - Enables alternating split orientation for newly tiled windows. - -- `disable-autotile`: - - Disables alternating split orientation for newly tiled windows. - -- `toggle-autotile`: - - Toggles alternating split orientation for newly tiled windows. - - `toggle-fullscreen`: Toggle the currently focused window between fullscreen and windowed. @@ -4632,18 +4460,6 @@ The string should have one of the following values: Makes the currently focused window windowed. -- `send-to-scratchpad`: - - Sends the currently focused window to the default scratchpad. - -- `toggle-scratchpad`: - - Toggles the default scratchpad. - -- `cycle-scratchpad`: - - Cycles through the windows of the default scratchpad. - - `focus-parent`: Focus the parent of the currently focused window. diff --git a/crates/toml-spec/spec/spec.yaml b/crates/toml-spec/spec/spec.yaml index 6c3b96dc..ce83f243 100644 --- a/crates/toml-spec/spec/spec.yaml +++ b/crates/toml-spec/spec/spec.yaml @@ -345,64 +345,6 @@ Action: description: The name of the workspace. required: true kind: string - send-to-scratchpad: - description: | - Sends the currently focused window to a scratchpad and hides it. - - A scratchpad can hold any number of windows. If `name` is omitted, the - default scratchpad is used. - - - Example: - - ```toml - [shortcuts] - alt-shift-minus = { type = "send-to-scratchpad", name = "terminal" } - ``` - fields: - name: - description: The name of the scratchpad. - required: false - kind: string - toggle-scratchpad: - description: | - Toggles a scratchpad. - - If the scratchpad has a visible window, that window is hidden. Otherwise, the - most recently hidden window in the scratchpad is shown on the current workspace. - Only one window of a scratchpad is shown at a time, and scratchpad windows are - always shown floating. If `name` is omitted, the default scratchpad is used. - - - Example: - - ```toml - [shortcuts] - alt-minus = { type = "toggle-scratchpad", name = "terminal" } - ``` - fields: - name: - description: The name of the scratchpad. - required: false - kind: string - cycle-scratchpad: - description: | - Cycles through the windows of a scratchpad, one at a time. - - With no window shown, the first window is brought up. Each further invocation - hides the current window and shows the next; after the last window the - scratchpad is hidden again. Scratchpad windows are always shown floating. - If `name` is omitted, the default scratchpad is used. - - - Example: - - ```toml - [shortcuts] - alt-minus = { type = "cycle-scratchpad", name = "terminal" } - ``` - fields: - name: - description: The name of the scratchpad. - required: false - kind: string move-to-output: description: | Moves a workspace to a different output. @@ -1036,11 +978,6 @@ Exec: values: kind: string description: The environment variables to pass to the executable. - tag: - kind: string - required: false - description: | - Specifies a tag to apply to all spawned wayland connections. SimpleActionName: @@ -1102,24 +1039,12 @@ SimpleActionName: description: Toggles the current group's direction. - value: toggle-tab description: Toggles the current group between tabbed and split mode. - - value: enable-autotile - description: Enables alternating split orientation for newly tiled windows. - - value: disable-autotile - description: Disables alternating split orientation for newly tiled windows. - - value: toggle-autotile - description: Toggles alternating split orientation for newly tiled windows. - value: toggle-fullscreen description: Toggle the currently focused window between fullscreen and windowed. - value: enter-fullscreen description: Makes the currently focused window fullscreen. - value: exit-fullscreen description: Makes the currently focused window windowed. - - value: send-to-scratchpad - description: Sends the currently focused window to the default scratchpad. - - value: toggle-scratchpad - description: Toggles the default scratchpad. - - value: cycle-scratchpad - description: Cycles through the windows of the default scratchpad. - value: focus-parent description: Focus the parent of the currently focused window. - value: close @@ -3177,21 +3102,10 @@ Config: required: false description: | Configures whether middle-click pasting is enabled. - + Changing this has no effect on running applications. The default is `true`. - autotile: - kind: boolean - required: false - description: | - Configures whether autotiling is enabled by default. - - When enabled, newly mapped tiled windows alternate their split - orientation automatically. This can also be toggled at runtime via the - `enable-autotile`, `disable-autotile`, and `toggle-autotile` actions. - - The default is `false`. modes: kind: map values: @@ -3288,61 +3202,6 @@ Config: required: false description: | Sets the egui settings of the compositor. - scratchpads: - kind: array - items: - ref: Scratchpad - required: false - description: | - An array of pre-configured scratchpads. - - Each entry launches a program when the graphics are first initialized and - immediately parks its window in the named scratchpad. The window is captured - via a unique tag attached to the spawned process, so other windows of the - same application are never affected. - - Use a `toggle-scratchpad` or `cycle-scratchpad` action to bring the windows - up; they are always shown floating. - - - Example: - - ```toml - [[scratchpads]] - name = "term" - exec = "foot" - - [[scratchpads]] - name = "notes" - exec = ["obsidian"] - ``` - - -Scratchpad: - kind: table - description: | - A pre-configured scratchpad whose program is launched at startup and parked - in the scratchpad. - - - Example: - - ```toml - [[scratchpads]] - name = "term" - exec = "foot" - ``` - fields: - name: - kind: string - required: true - description: The name of the scratchpad that the spawned window is parked in. - exec: - ref: Exec - required: false - description: | - The program to launch when the graphics are first initialized. - - If omitted, no program is launched and the scratchpad is only created on - demand by `send-to-scratchpad`. Idle: @@ -4251,14 +4110,6 @@ ClientMatch: kind: string required: false description: Matches the `/proc/pid/exe` of the client with a regular expression. - tag: - kind: string - required: false - description: Matches the tag of the client verbatim. - tag-regex: - kind: string - required: false - description: Matches the tag of the client with a regular expression. ClientMatchExactly: diff --git a/crates/wire-to-xml/src/main.rs b/crates/wire-to-xml/src/main.rs index 6a73075e..5341e137 100644 --- a/crates/wire-to-xml/src/main.rs +++ b/crates/wire-to-xml/src/main.rs @@ -21,7 +21,7 @@ use { std::{io, os::unix::ffi::OsStrExt, path::PathBuf}, }; -#[path = "../../../build/wire/parser.rs"] +#[path = "../../build/wire/parser.rs"] #[allow(dead_code)] mod parser; diff --git a/src/client.rs b/src/client.rs index 058d2373..fd3b7266 100644 --- a/src/client.rs +++ b/src/client.rs @@ -80,7 +80,6 @@ pub struct ClientMetadata { pub sandbox_engine: Option, pub app_id: Option, pub instance_id: Option, - pub tag: Option, } impl Clients { diff --git a/src/compositor.rs b/src/compositor.rs index 6520cadd..783ca284 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -286,7 +286,6 @@ fn start_compositor2( display: Default::default(), }, acceptor: Default::default(), - tagged_acceptors: Default::default(), serial: Default::default(), idle_inhibitor_ids: Default::default(), run_toplevel, @@ -386,7 +385,6 @@ fn start_compositor2( bo_drop_queue: Rc::new(ObjectDropQueue::new(&ring)), virtual_outputs: Default::default(), clean_logs_older_than: Default::default(), - scratchpads: Default::default(), }); state.tracker.register(ClientId::from_raw(0)); create_dummy_output(&state); diff --git a/src/config/handler.rs b/src/config/handler.rs index d50d54b4..18f785ad 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -8,7 +8,7 @@ use { }, client::{Client, ClientId}, cmm::cmm_eotf::Eotf, - compositor::{MAX_EXTENTS, WAYLAND_DISPLAY}, + compositor::MAX_EXTENTS, criteria::{ CritLiteralOrRegex, CritMgrExt, CritTarget, CritUpstreamNode, clm::ClmLeafMatcher, @@ -25,7 +25,6 @@ use { output_schedule::map_cursor_hz, scale::Scale, state::{ConnectorData, DeviceHandlerData, DrmDevData, OutputData, State}, - tagged_acceptor::TaggedAcceptorError, theme::{ThemeColor, ThemeSized}, tree::{ ContainerSplit, OutputNode, TearingMode, TileState, ToplevelData, ToplevelIdentifier, @@ -407,8 +406,6 @@ enum CphError { UnknownFallbackOutputMode(FallbackOutputMode), #[error("Unknown tile state {0:?}")] UnknownTileState(ConfigTileState), - #[error("Could not create tagged acceptor")] - CreateTaggedAcceptor(#[source] TaggedAcceptorError), } trait WithRequestName { diff --git a/src/config/handler/dispatch.rs b/src/config/handler/dispatch.rs index 97936039..99efeeae 100644 --- a/src/config/handler/dispatch.rs +++ b/src/config/handler/dispatch.rs @@ -60,7 +60,7 @@ impl ConfigProxyHandler { ClientMessage::GetSeats => self.handle_get_seats(), ClientMessage::RemoveSeat { .. } => {} ClientMessage::Run { prog, args, env } => { - self.handle_run(prog, args, env, vec![], None).wrn("run")? + self.handle_run(prog, args, env, vec![]).wrn("run")? } ClientMessage::GrabKb { kb, grab } => self.handle_grab(kb, grab).wrn("grab")?, ClientMessage::SetColor { colorable, color } => { @@ -111,15 +111,6 @@ impl ConfigProxyHandler { ClientMessage::SetSeatWorkspace { seat, workspace } => self .handle_set_seat_workspace(seat, workspace) .wrn("set_seat_workspace")?, - ClientMessage::SeatSendToScratchpad { seat, name } => self - .handle_seat_send_to_scratchpad(seat, name) - .wrn("seat_send_to_scratchpad")?, - ClientMessage::SeatToggleScratchpad { seat, name } => self - .handle_seat_toggle_scratchpad(seat, name) - .wrn("seat_toggle_scratchpad")?, - ClientMessage::SeatCycleScratchpad { seat, name } => self - .handle_seat_cycle_scratchpad(seat, name) - .wrn("seat_cycle_scratchpad")?, ClientMessage::GetConnector { ty, idx } => { self.handle_get_connector(ty, idx).wrn("get_connector")? } @@ -277,14 +268,7 @@ impl ConfigProxyHandler { args, env, fds, - } => self.handle_run(prog, args, env, fds, None).wrn("run")?, - ClientMessage::Run3 { - prog, - args, - env, - fds, - tag, - } => self.handle_run(prog, args, env, fds, tag).wrn("run")?, + } => self.handle_run(prog, args, env, fds).wrn("run")?, ClientMessage::DisableDefaultSeat => self.state.create_default_seat.set(false), ClientMessage::DestroyKeymap { keymap } => self.handle_destroy_keymap(keymap), ClientMessage::GetConnectorName { connector } => self @@ -516,9 +500,6 @@ impl ConfigProxyHandler { ClientMessage::SetWindowWorkspace { window, workspace } => self .handle_set_window_workspace(window, workspace) .wrn("set_window_workspace")?, - ClientMessage::WindowSendToScratchpad { window, name } => self - .handle_window_send_to_scratchpad(window, name) - .wrn("window_send_to_scratchpad")?, ClientMessage::SetWindowFullscreen { window, fullscreen } => self .handle_set_window_fullscreen(window, fullscreen) .wrn("set_window_fullscreen")?, @@ -720,11 +701,6 @@ impl ConfigProxyHandler { ClientMessage::SetAutotile { enabled } => { self.state.theme.autotile_enabled.set(enabled); } - ClientMessage::GetAutotile => { - self.respond(Response::GetAutotile { - enabled: self.state.theme.autotile_enabled.get(), - }); - } ClientMessage::SeatToggleExpand { .. } => { // Removed feature; kept for binary protocol compatibility. } diff --git a/src/config/handler/matchers.rs b/src/config/handler/matchers.rs index ed9577d1..cc00a346 100644 --- a/src/config/handler/matchers.rs +++ b/src/config/handler/matchers.rs @@ -105,7 +105,6 @@ impl ConfigProxyHandler { } ClientCriterionStringField::Comm => mgr.comm(needle), ClientCriterionStringField::Exe => mgr.exe(needle), - ClientCriterionStringField::Tag => mgr.tag(needle), } } ClientCriterionPayload::Sandboxed => mgr.sandboxed(), diff --git a/src/config/handler/runtime.rs b/src/config/handler/runtime.rs index ebd286df..2b730264 100644 --- a/src/config/handler/runtime.rs +++ b/src/config/handler/runtime.rs @@ -58,18 +58,9 @@ impl ConfigProxyHandler { &self, prog: &str, args: Vec, - mut env: Vec<(String, String)>, + env: Vec<(String, String)>, fds: Vec<(i32, i32)>, - tag: Option<&str>, ) -> Result<(), CphError> { - if let Some(tag) = tag { - let display = self - .state - .tagged_acceptors - .get(&self.state, tag) - .map_err(CphError::CreateTaggedAcceptor)?; - env.push((WAYLAND_DISPLAY.to_string(), display.to_string())); - } let fds: Vec<_> = fds .into_iter() .map(|(a, b)| (a, Rc::new(OwnedFd::new(b)))) diff --git a/src/config/handler/seats.rs b/src/config/handler/seats.rs index 3711a0af..3f52ee1b 100644 --- a/src/config/handler/seats.rs +++ b/src/config/handler/seats.rs @@ -120,44 +120,6 @@ impl ConfigProxyHandler { }) } - pub(super) fn handle_seat_send_to_scratchpad( - &self, - seat: Seat, - name: &str, - ) -> Result<(), CphError> { - self.state.with_linear_layout_animations(|| { - let seat = self.get_seat(seat)?; - if let Some(toplevel) = seat.get_keyboard_node().node_toplevel() { - self.state.send_to_scratchpad(name, toplevel); - } - Ok(()) - }) - } - - pub(super) fn handle_seat_toggle_scratchpad( - &self, - seat: Seat, - name: &str, - ) -> Result<(), CphError> { - self.state.with_linear_layout_animations(|| { - let seat = self.get_seat(seat)?; - self.state.toggle_scratchpad(&seat, name); - Ok(()) - }) - } - - pub(super) fn handle_seat_cycle_scratchpad( - &self, - seat: Seat, - name: &str, - ) -> Result<(), CphError> { - self.state.with_linear_layout_animations(|| { - let seat = self.get_seat(seat)?; - self.state.cycle_scratchpad(&seat, name); - Ok(()) - }) - } - pub(super) fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), CphError> { let seat = self.get_seat(seat)?; let (rate, delay) = seat.get_rate(); diff --git a/src/config/handler/windows.rs b/src/config/handler/windows.rs index 829af1b8..faaf1b6e 100644 --- a/src/config/handler/windows.rs +++ b/src/config/handler/windows.rs @@ -124,18 +124,6 @@ impl ConfigProxyHandler { }) } - pub(super) fn handle_window_send_to_scratchpad( - &self, - window: Window, - name: &str, - ) -> Result<(), CphError> { - self.state.with_linear_layout_animations(|| { - let window = self.get_window(window)?; - self.state.send_to_scratchpad(name, window); - Ok(()) - }) - } - pub(super) fn handle_window_exists(&self, window: Window) { self.respond(Response::WindowExists { exists: self.get_window(window).is_ok(), diff --git a/src/criteria/clm.rs b/src/criteria/clm.rs index a042d3f7..87f0a8db 100644 --- a/src/criteria/clm.rs +++ b/src/criteria/clm.rs @@ -13,7 +13,7 @@ use { clmm_sandboxed::ClmMatchSandboxed, clmm_string::{ ClmMatchComm, ClmMatchExe, ClmMatchSandboxAppId, ClmMatchSandboxEngine, - ClmMatchSandboxInstanceId, ClmMatchTag, + ClmMatchSandboxInstanceId, }, clmm_uid::ClmMatchUid, }, @@ -62,7 +62,6 @@ pub struct RootMatchers { pid: ClmRootMatcherMap, comm: ClmRootMatcherMap, exe: ClmRootMatcherMap, - tag: ClmRootMatcherMap, id: ClmRootMatcherMap, } @@ -75,7 +74,6 @@ impl RootMatchers { self.pid.clear(); self.comm.clear(); self.exe.clear(); - self.tag.clear(); self.id.clear(); } } @@ -187,7 +185,6 @@ impl ClMatcherManager { unconditional!(pid); unconditional!(comm); unconditional!(exe); - unconditional!(tag); unconditional!(id); fixed!(sandboxed); fixed!(is_xwayland); @@ -231,9 +228,6 @@ impl ClMatcherManager { self.root(ClmMatchExe::new(string)) } - pub fn tag(&self, string: CritLiteralOrRegex) -> Rc { - self.root(ClmMatchTag::new(string)) - } } pub struct ClientTargetOwner { diff --git a/src/criteria/clm/clm_matchers/clmm_string.rs b/src/criteria/clm/clm_matchers/clmm_string.rs index 367bdf0a..aaf82198 100644 --- a/src/criteria/clm/clm_matchers/clmm_string.rs +++ b/src/criteria/clm/clm_matchers/clmm_string.rs @@ -14,7 +14,6 @@ pub type ClmMatchString = CritMatchString; pub type ClmMatchSandboxEngine = ClmMatchString>; pub type ClmMatchSandboxAppId = ClmMatchString>; pub type ClmMatchSandboxInstanceId = ClmMatchString>; -pub type ClmMatchTag = ClmMatchString>; pub type ClmMatchComm = ClmMatchString; pub type ClmMatchExe = ClmMatchString; @@ -32,7 +31,6 @@ trait ClientMetadataField: Sized + 'static { pub struct SandboxEngineField; pub struct SandboxAppIdField; pub struct SandboxInstanceIdField; -pub struct TagField; impl StringAccess for ClientMetadataAccess where @@ -83,18 +81,6 @@ impl ClientMetadataField for SandboxInstanceIdField { } } -impl ClientMetadataField for TagField { - fn field(meta: &ClientMetadata) -> &Option { - &meta.tag - } - - fn nodes( - roots: &RootMatchers, - ) -> &ClmRootMatcherMap>> { - &roots.tag - } -} - impl StringAccess for CommAccess { fn with_string(data: &Client, f: impl FnOnce(&str) -> bool) -> bool { f(&data.pid_info.comm) diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index 195f1e8c..2397925e 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -1364,25 +1364,25 @@ impl WlSurface { let bounds = self.toplevel.get().and_then(|tl| tl.tl_render_bounds()); let pos = self.buffer_abs_pos.get(); let apply_damage = |pos: Rect| { - let clip_damage = |mut damage: Rect| { - damage = damage.intersect(pos); + if pending.damage_full { + let mut damage = pos; if let Some(bounds) = bounds { damage = damage.intersect(bounds); } - damage - }; - if pending.damage_full { - self.client.state.damage(clip_damage(pos)); + self.client.state.damage(damage); } else { let matrix = self.damage_matrix.get(); if let Some(buffer) = self.buffer.get() { for damage in &pending.buffer_damage { - let damage = matrix.apply( + let mut damage = matrix.apply( pos.x1(), pos.y1(), damage.intersect(buffer.buffer.buf.rect), ); - self.client.state.damage(clip_damage(damage)); + if let Some(bounds) = bounds { + damage = damage.intersect(bounds); + } + self.client.state.damage(damage); } } for damage in &pending.surface_damage { @@ -1394,7 +1394,8 @@ impl WlSurface { let y2 = (damage.y2() + scale - 1) / scale; damage = Rect::new_saturating(x1, y1, x2, y2); } - self.client.state.damage(clip_damage(damage)); + damage = damage.intersect(bounds.unwrap_or(pos)); + self.client.state.damage(damage); } } }; diff --git a/src/it/test_config.rs b/src/it/test_config.rs index a81ba905..267e7833 100644 --- a/src/it/test_config.rs +++ b/src/it/test_config.rs @@ -272,27 +272,6 @@ impl TestConfig { }) } - pub fn send_to_scratchpad(&self, seat: SeatId, name: &str) -> TestResult { - self.send(ClientMessage::SeatSendToScratchpad { - seat: Seat(seat.raw() as _), - name, - }) - } - - pub fn toggle_scratchpad(&self, seat: SeatId, name: &str) -> TestResult { - self.send(ClientMessage::SeatToggleScratchpad { - seat: Seat(seat.raw() as _), - name, - }) - } - - pub fn cycle_scratchpad(&self, seat: SeatId, name: &str) -> TestResult { - self.send(ClientMessage::SeatCycleScratchpad { - seat: Seat(seat.raw() as _), - name, - }) - } - fn clear(&self) { unsafe { if let Some(srv) = self.srv.take() { @@ -340,10 +319,6 @@ impl TestConfig { pub fn set_show_titles(&self, show: bool) -> TestResult { self.send(ClientMessage::SetShowTitles { show }) } - - pub fn set_autotile(&self, enabled: bool) -> TestResult { - self.send(ClientMessage::SetAutotile { enabled }) - } } impl Drop for TestConfig { diff --git a/src/it/test_ifs/test_viewport.rs b/src/it/test_ifs/test_viewport.rs index e08266de..b25105c8 100644 --- a/src/it/test_ifs/test_viewport.rs +++ b/src/it/test_ifs/test_viewport.rs @@ -29,17 +29,6 @@ impl TestViewport { Ok(()) } - pub fn unset_source(&self) -> Result<(), TestError> { - self.tran.send(SetSource { - self_id: self.id, - x: Fixed::from_int(-1), - y: Fixed::from_int(-1), - width: Fixed::from_int(-1), - height: Fixed::from_int(-1), - })?; - Ok(()) - } - pub fn set_destination(&self, width: i32, height: i32) -> Result<(), TestError> { self.tran.send(SetDestination { self_id: self.id, @@ -48,15 +37,6 @@ impl TestViewport { })?; Ok(()) } - - pub fn unset_destination(&self) -> Result<(), TestError> { - self.tran.send(SetDestination { - self_id: self.id, - width: -1, - height: -1, - })?; - Ok(()) - } } impl Drop for TestViewport { diff --git a/src/it/tests.rs b/src/it/tests.rs index 35b6be97..dc28888c 100644 --- a/src/it/tests.rs +++ b/src/it/tests.rs @@ -85,8 +85,6 @@ mod t0051_pointer_warp; mod t0052_bar; mod t0053_theme; mod t0054_subsurface_already_attached; -mod t0055_autotiling; -mod t0055_scratchpad; pub trait TestCase: Sync { fn name(&self) -> &'static str; @@ -160,7 +158,5 @@ pub fn tests() -> Vec<&'static dyn TestCase> { t0052_bar, t0053_theme, t0054_subsurface_already_attached, - t0055_autotiling, - t0055_scratchpad, } } diff --git a/src/it/tests/t0002_window.rs b/src/it/tests/t0002_window.rs index 28ee359f..84571c57 100644 --- a/src/it/tests/t0002_window.rs +++ b/src/it/tests/t0002_window.rs @@ -1,6 +1,7 @@ use { crate::{ it::{test_error::TestError, testrun::TestRun}, + rect::Rect, tree::Node, }, std::rc::Rc, @@ -10,19 +11,29 @@ testcase!(); /// Create and map a single surface async fn test(run: Rc) -> Result<(), TestError> { - let ds = run.create_default_setup().await?; + run.backend.install_default()?; let client = run.create_client().await?; let window = client.create_window().await?; window.map().await?; - let workspace_rect = ds.output.workspace_rect.get(); + tassert_eq!(window.tl.core.width.get(), 800); + tassert_eq!( + window.tl.core.height.get(), + 600 - 2 * run.state.theme.title_plus_underline_height() + ); - tassert_eq!(window.tl.core.width.get(), workspace_rect.width()); - tassert_eq!(window.tl.core.height.get(), workspace_rect.height()); - - tassert_eq!(window.tl.server.node_absolute_position(), workspace_rect); + tassert_eq!( + window.tl.server.node_absolute_position(), + Rect::new_sized( + 0, + 2 * run.state.theme.title_plus_underline_height(), + window.tl.core.width.get(), + window.tl.core.height.get(), + ) + .unwrap() + ); Ok(()) } diff --git a/src/it/tests/t0003_multi_window.rs b/src/it/tests/t0003_multi_window.rs index db726f90..3fbf599c 100644 --- a/src/it/tests/t0003_multi_window.rs +++ b/src/it/tests/t0003_multi_window.rs @@ -11,7 +11,7 @@ testcase!(); /// Create and map two surfaces async fn test(run: Rc) -> Result<(), TestError> { - let ds = run.create_default_setup().await?; + run.backend.install_default()?; let client = run.create_client().await?; @@ -21,30 +21,17 @@ async fn test(run: Rc) -> Result<(), TestError> { let window2 = client.create_window().await?; window2.map().await?; - let workspace_rect = ds.output.workspace_rect.get(); + let otop = 2 * run.state.theme.title_plus_underline_height(); let bw = run.state.theme.sizes.border_width.get(); - let child_width = (workspace_rect.width() - bw) / 2; tassert_eq!( window.tl.server.node_absolute_position(), - Rect::new_sized( - workspace_rect.x1(), - workspace_rect.y1(), - child_width, - workspace_rect.height(), - ) - .unwrap() + Rect::new_sized(0, otop, (800 - bw) / 2, 600 - otop).unwrap() ); tassert_eq!( window2.tl.server.node_absolute_position(), - Rect::new_sized( - workspace_rect.x1() + child_width + bw, - workspace_rect.y1(), - child_width, - workspace_rect.height(), - ) - .unwrap() + Rect::new_sized((800 - bw) / 2 + bw, otop, (800 - bw) / 2, 600 - otop).unwrap() ); Ok(()) diff --git a/src/it/tests/t0007_subsurface/screenshot_1.qoi b/src/it/tests/t0007_subsurface/screenshot_1.qoi index b5954651..230c0408 100644 Binary files a/src/it/tests/t0007_subsurface/screenshot_1.qoi and b/src/it/tests/t0007_subsurface/screenshot_1.qoi differ diff --git a/src/it/tests/t0007_subsurface/screenshot_2.qoi b/src/it/tests/t0007_subsurface/screenshot_2.qoi index 718d5c29..722271f6 100644 Binary files a/src/it/tests/t0007_subsurface/screenshot_2.qoi and b/src/it/tests/t0007_subsurface/screenshot_2.qoi differ diff --git a/src/it/tests/t0014_container_scroll_focus.rs b/src/it/tests/t0014_container_scroll_focus.rs index dccd1096..0186cbaf 100644 --- a/src/it/tests/t0014_container_scroll_focus.rs +++ b/src/it/tests/t0014_container_scroll_focus.rs @@ -48,18 +48,13 @@ async fn test(run: Rc) -> TestResult { let mono_container = w_mono2.tl.container_parent()?; let container_pos = mono_container.tl_data().pos.get(); - let (tab_x, tab_y) = { - let tab_bar = mono_container.tab_bar.borrow(); - let Some(tab_bar) = tab_bar.as_ref() else { - bail!("no tab bar"); - }; - let w_mono1_title = &tab_bar.entries[0]; - ( - container_pos.x1() + w_mono1_title.x.get() + w_mono1_title.width.get() / 2, - container_pos.y1() + tab_bar.height / 2, - ) - }; - ds.mouse.abs(&ds.connector, tab_x as _, tab_y as _); + let w_mono1_title = mono_container.render_data.borrow_mut().title_rects[0] + .move_(container_pos.x1(), container_pos.y1()); + ds.mouse.abs( + &ds.connector, + w_mono1_title.x1() as _, + w_mono1_title.y1() as _, + ); client.sync().await; tassert!(enters.next().is_err()); diff --git a/src/it/tests/t0015_scroll_partial.rs b/src/it/tests/t0015_scroll_partial.rs index f5cb6e3c..c6cf49b7 100644 --- a/src/it/tests/t0015_scroll_partial.rs +++ b/src/it/tests/t0015_scroll_partial.rs @@ -26,18 +26,12 @@ async fn test(run: Rc) -> TestResult { let container = w_mono2.tl.container_parent()?; let pos = container.tl_data().pos.get(); - let (tab_x, tab_y) = { - let tab_bar = container.tab_bar.borrow(); - let Some(tab_bar) = tab_bar.as_ref() else { - bail!("no tab bar"); - }; - let w_mono1_title = &tab_bar.entries[0]; - ( - pos.x1() + w_mono1_title.x.get() + w_mono1_title.width.get() / 2, - pos.y1() + tab_bar.height / 2, - ) - }; - ds.mouse.abs(&ds.connector, tab_x as f64, tab_y as f64); + let w_mono1_title = container.render_data.borrow_mut().title_rects[0].move_(pos.x1(), pos.y1()); + ds.mouse.abs( + &ds.connector, + w_mono1_title.x1() as f64, + w_mono1_title.y1() as f64, + ); client.sync().await; let enters = dss.kb.enter.expect()?; diff --git a/src/it/tests/t0020_surface_offset/screenshot_1.qoi b/src/it/tests/t0020_surface_offset/screenshot_1.qoi index 4c826f86..eef5f37a 100644 Binary files a/src/it/tests/t0020_surface_offset/screenshot_1.qoi and b/src/it/tests/t0020_surface_offset/screenshot_1.qoi differ diff --git a/src/it/tests/t0020_surface_offset/screenshot_2.qoi b/src/it/tests/t0020_surface_offset/screenshot_2.qoi index 0fb763e2..7e8cf143 100644 Binary files a/src/it/tests/t0020_surface_offset/screenshot_2.qoi and b/src/it/tests/t0020_surface_offset/screenshot_2.qoi differ diff --git a/src/it/tests/t0022_toplevel_suspended.rs b/src/it/tests/t0022_toplevel_suspended.rs index 524856e3..1fdacb1a 100644 --- a/src/it/tests/t0022_toplevel_suspended.rs +++ b/src/it/tests/t0022_toplevel_suspended.rs @@ -2,7 +2,7 @@ use { crate::{ ifs::wl_surface::xdg_surface::xdg_toplevel::STATE_SUSPENDED, it::{ - test_error::{TestErrorExt, TestResult}, + test_error::TestResult, test_utils::{ test_ouput_node_ext::TestOutputNodeExt, test_toplevel_node_ext::TestToplevelNodeExt, }, @@ -10,7 +10,7 @@ use { }, }, isnt::std_1::collections::IsntHashSetExt, - std::{rc::Rc, time::Duration}, + std::rc::Rc, }; testcase!(); @@ -19,7 +19,6 @@ async fn test(run: Rc) -> TestResult { let ds = run.create_default_setup().await?; let client = run.create_client().await?; - let default_seat = client.get_default_seat().await?; let win1 = client.create_window().await?; win1.set_color(255, 0, 0, 255); @@ -45,23 +44,5 @@ async fn test(run: Rc) -> TestResult { client.sync().await; tassert!(win2.tl.core.states.borrow().not_contains(&STATE_SUSPENDED)); - let leaves = default_seat.kb.leave.expect()?; - let enters = default_seat.kb.enter.expect()?; - - run.cfg.set_idle(Duration::from_micros(100))?; - run.cfg.set_idle_grace_period(Duration::from_secs(0))?; - run.state.wheel.timeout(3).await?; - - client.sync().await; - tassert!(win2.tl.core.states.borrow().contains(&STATE_SUSPENDED)); - let leave = leaves.next().with_context(|| "no leave on suspend")?; - tassert_eq!(leave.surface, win2.surface.id); - - ds.mouse.rel(1.0, 1.0); - client.sync().await; - tassert!(win2.tl.core.states.borrow().not_contains(&STATE_SUSPENDED)); - let enter = enters.next().with_context(|| "no enter on restore")?; - tassert_eq!(enter.surface, win2.surface.id); - Ok(()) } diff --git a/src/it/tests/t0023_xdg_activation/screenshot_1.qoi b/src/it/tests/t0023_xdg_activation/screenshot_1.qoi index 960da20a..1fa8d204 100644 Binary files a/src/it/tests/t0023_xdg_activation/screenshot_1.qoi and b/src/it/tests/t0023_xdg_activation/screenshot_1.qoi differ diff --git a/src/it/tests/t0026_output_transform/screenshot_1.qoi b/src/it/tests/t0026_output_transform/screenshot_1.qoi index f11111bb..2206fc85 100644 Binary files a/src/it/tests/t0026_output_transform/screenshot_1.qoi and b/src/it/tests/t0026_output_transform/screenshot_1.qoi differ diff --git a/src/it/tests/t0028_top_level_restacking/screenshot_1.qoi b/src/it/tests/t0028_top_level_restacking/screenshot_1.qoi index 9f5fca3c..f7bf53bf 100644 Binary files a/src/it/tests/t0028_top_level_restacking/screenshot_1.qoi and b/src/it/tests/t0028_top_level_restacking/screenshot_1.qoi differ diff --git a/src/it/tests/t0028_top_level_restacking/screenshot_2.qoi b/src/it/tests/t0028_top_level_restacking/screenshot_2.qoi index aaf1b108..b454acd3 100644 Binary files a/src/it/tests/t0028_top_level_restacking/screenshot_2.qoi and b/src/it/tests/t0028_top_level_restacking/screenshot_2.qoi differ diff --git a/src/it/tests/t0029_double_click_float/screenshot_1.qoi b/src/it/tests/t0029_double_click_float/screenshot_1.qoi index e08dc525..dd974ccf 100644 Binary files a/src/it/tests/t0029_double_click_float/screenshot_1.qoi and b/src/it/tests/t0029_double_click_float/screenshot_1.qoi differ diff --git a/src/it/tests/t0029_double_click_float/screenshot_2.qoi b/src/it/tests/t0029_double_click_float/screenshot_2.qoi index e08dc525..f49edd4d 100644 Binary files a/src/it/tests/t0029_double_click_float/screenshot_2.qoi and b/src/it/tests/t0029_double_click_float/screenshot_2.qoi differ diff --git a/src/it/tests/t0037_toplevel_drag/screenshot_2.qoi b/src/it/tests/t0037_toplevel_drag/screenshot_2.qoi index 36c68e4e..b9826001 100644 Binary files a/src/it/tests/t0037_toplevel_drag/screenshot_2.qoi and b/src/it/tests/t0037_toplevel_drag/screenshot_2.qoi differ diff --git a/src/it/tests/t0038_subsurface_parent_state/screenshot_1.qoi b/src/it/tests/t0038_subsurface_parent_state/screenshot_1.qoi index e6f6db74..988bc767 100644 Binary files a/src/it/tests/t0038_subsurface_parent_state/screenshot_1.qoi and b/src/it/tests/t0038_subsurface_parent_state/screenshot_1.qoi differ diff --git a/src/it/tests/t0038_subsurface_parent_state/screenshot_2.qoi b/src/it/tests/t0038_subsurface_parent_state/screenshot_2.qoi index 9abc8de3..a7509404 100644 Binary files a/src/it/tests/t0038_subsurface_parent_state/screenshot_2.qoi and b/src/it/tests/t0038_subsurface_parent_state/screenshot_2.qoi differ diff --git a/src/it/tests/t0039_alpha_modifier/screenshot_1.qoi b/src/it/tests/t0039_alpha_modifier/screenshot_1.qoi index 80a29c84..8fe5d0b2 100644 Binary files a/src/it/tests/t0039_alpha_modifier/screenshot_1.qoi and b/src/it/tests/t0039_alpha_modifier/screenshot_1.qoi differ diff --git a/src/it/tests/t0039_alpha_modifier/screenshot_2.qoi b/src/it/tests/t0039_alpha_modifier/screenshot_2.qoi index 735af290..9874e2f5 100644 Binary files a/src/it/tests/t0039_alpha_modifier/screenshot_2.qoi and b/src/it/tests/t0039_alpha_modifier/screenshot_2.qoi differ diff --git a/src/it/tests/t0041_input_method/screenshot_1.qoi b/src/it/tests/t0041_input_method/screenshot_1.qoi index cd07ecd4..d25fcf64 100644 Binary files a/src/it/tests/t0041_input_method/screenshot_1.qoi and b/src/it/tests/t0041_input_method/screenshot_1.qoi differ diff --git a/src/it/tests/t0041_input_method/screenshot_2.qoi b/src/it/tests/t0041_input_method/screenshot_2.qoi index d76ea9a0..7f93231a 100644 Binary files a/src/it/tests/t0041_input_method/screenshot_2.qoi and b/src/it/tests/t0041_input_method/screenshot_2.qoi differ diff --git a/src/it/tests/t0041_input_method/screenshot_3.qoi b/src/it/tests/t0041_input_method/screenshot_3.qoi index cd07ecd4..d25fcf64 100644 Binary files a/src/it/tests/t0041_input_method/screenshot_3.qoi and b/src/it/tests/t0041_input_method/screenshot_3.qoi differ diff --git a/src/it/tests/t0042_toplevel_select/screenshot_1.qoi b/src/it/tests/t0042_toplevel_select/screenshot_1.qoi index 6d57d140..6423ef6d 100644 Binary files a/src/it/tests/t0042_toplevel_select/screenshot_1.qoi and b/src/it/tests/t0042_toplevel_select/screenshot_1.qoi differ diff --git a/src/it/tests/t0042_toplevel_select/screenshot_2.qoi b/src/it/tests/t0042_toplevel_select/screenshot_2.qoi index 478b3c43..823fd750 100644 Binary files a/src/it/tests/t0042_toplevel_select/screenshot_2.qoi and b/src/it/tests/t0042_toplevel_select/screenshot_2.qoi differ diff --git a/src/it/tests/t0042_toplevel_select/screenshot_3.qoi b/src/it/tests/t0042_toplevel_select/screenshot_3.qoi index 478b3c43..823fd750 100644 Binary files a/src/it/tests/t0042_toplevel_select/screenshot_3.qoi and b/src/it/tests/t0042_toplevel_select/screenshot_3.qoi differ diff --git a/src/it/tests/t0042_toplevel_select/screenshot_4.qoi b/src/it/tests/t0042_toplevel_select/screenshot_4.qoi index 07dd87fb..714222f1 100644 Binary files a/src/it/tests/t0042_toplevel_select/screenshot_4.qoi and b/src/it/tests/t0042_toplevel_select/screenshot_4.qoi differ diff --git a/src/it/tests/t0047_surface_damage.rs b/src/it/tests/t0047_surface_damage.rs index c2d0d6dd..d9760bc8 100644 --- a/src/it/tests/t0047_surface_damage.rs +++ b/src/it/tests/t0047_surface_damage.rs @@ -308,8 +308,9 @@ async fn test(run: Rc) -> TestResult { let output_damage = connector_data.damage.borrow(); tassert!(!output_damage.is_empty()); - // The test window maps its 1x1 buffer through a viewport to the full window size. - let expected_buffer_damage = surface_pos; + // Buffer damage is transformed by the damage matrix which includes the surface position + // The buffer damage (0,0,1,1) should be transformed to surface coordinates + let expected_buffer_damage = buffer_damage.move_(surface_pos.x1(), surface_pos.y1()); // Find the exact output damage that matches our expected buffer damage let mut found_exact_buffer_damage = false; @@ -330,12 +331,10 @@ async fn test(run: Rc) -> TestResult { // Test 7: Check output damage from existing window's viewport (which already has scaling) connector_data.damage.borrow_mut().clear(); - // The existing window was created with create_surface_ext() which automatically creates a viewport. - // Commit the viewport size change separately; that commit intentionally damages the old/new extents. - window.surface.viewport.set_destination(150, 100)?; - window.surface.commit()?; - client.sync().await; - connector_data.damage.borrow_mut().clear(); + // The existing window was created with create_surface_ext() which automatically creates a viewport + // Let's verify that the viewport's existing scaling affects buffer damage correctly + // First, let's modify the viewport scaling that already exists on the window + window.surface.viewport.set_destination(150, 100)?; // Change scaling to 150x100 // Add buffer damage to test viewport scaling coordinate transformation window.surface.damage_buffer(0, 0, 1, 1)?; // Damage entire 1x1 buffer @@ -347,8 +346,8 @@ async fn test(run: Rc) -> TestResult { let output_damage = connector_data.damage.borrow(); tassert!(!output_damage.is_empty()); - // With viewporter scaling, the 1x1 buffer damage should scale to the viewport destination. - let surface_pos = window.surface.server.buffer_abs_pos.get(); + // With viewporter scaling, the 1x1 buffer damage should scale to 150x100 + // and be moved by surface position (0, 36) to get output coordinates (0, 36, 150, 136) let expected_scaled_damage = Rect::new_sized(0, 0, 150, 100).unwrap(); let expected_output_damage = expected_scaled_damage.move_(surface_pos.x1(), surface_pos.y1()); @@ -403,9 +402,8 @@ async fn test(run: Rc) -> TestResult { rotation_window.map().await?; client.sync().await; - // Disable viewporter to rely purely on buffer dimensions. - rotation_window.surface.viewport.unset_source()?; - rotation_window.surface.viewport.unset_destination()?; + // Disable viewporter by setting destination to 0x0 to rely purely on buffer dimensions + rotation_window.surface.viewport.set_destination(0, 0)?; // Disable viewporter // Use a rectangular buffer (4x2) so rotation has a visible geometric effect // Attach AFTER mapping to avoid being overwritten by map()'s single-pixel buffer diff --git a/src/it/tests/t0055_autotiling.rs b/src/it/tests/t0055_autotiling.rs deleted file mode 100644 index 4b3611c4..00000000 --- a/src/it/tests/t0055_autotiling.rs +++ /dev/null @@ -1,58 +0,0 @@ -use { - crate::{ - it::{test_error::TestResult, testrun::TestRun}, - tree::{ContainerSplit, Node, ToplevelNodeBase}, - }, - std::rc::Rc, -}; - -testcase!(); - -async fn test(run: Rc) -> TestResult { - run.backend.install_default()?; - run.cfg.set_autotile(true)?; - - let client = run.create_client().await?; - - let win1 = client.create_window().await?; - win1.map().await?; - let root = win1.tl.container_parent()?; - tassert_eq!(root.split.get(), ContainerSplit::Horizontal); - - let win2 = client.create_window().await?; - win2.map().await?; - client.sync().await; - - tassert_eq!(root.split.get(), ContainerSplit::Horizontal); - tassert_eq!(win1.tl.container_parent()?.node_id(), root.node_id()); - tassert_eq!(win2.tl.container_parent()?.node_id(), root.node_id()); - - let win3 = client.create_window().await?; - win3.map().await?; - client.sync().await; - - let v_group = win3.tl.container_parent()?; - tassert_eq!(root.split.get(), ContainerSplit::Horizontal); - tassert_eq!(v_group.split.get(), ContainerSplit::Vertical); - tassert_eq!(win2.tl.container_parent()?.node_id(), v_group.node_id()); - - let win4 = client.create_window().await?; - win4.map().await?; - client.sync().await; - - let h_group = win4.tl.container_parent()?; - tassert_eq!(h_group.split.get(), ContainerSplit::Horizontal); - tassert_eq!(win3.tl.container_parent()?.node_id(), h_group.node_id()); - let h_parent = match h_group - .tl_data() - .parent - .get() - .and_then(|p| p.node_into_container()) - { - Some(parent) => parent, - None => bail!("autotile group does not have a container parent"), - }; - tassert_eq!(h_parent.node_id(), v_group.node_id()); - - Ok(()) -} diff --git a/src/it/tests/t0055_scratchpad.rs b/src/it/tests/t0055_scratchpad.rs deleted file mode 100644 index 5abf2440..00000000 --- a/src/it/tests/t0055_scratchpad.rs +++ /dev/null @@ -1,107 +0,0 @@ -use { - crate::{ - it::{test_error::TestResult, testrun::TestRun}, - tree::{Node, ToplevelNodeBase}, - }, - std::rc::Rc, -}; - -testcase!(); - -async fn test(run: Rc) -> TestResult { - let ds = run.create_default_setup().await?; - - let client = run.create_client().await?; - let win1 = client.create_window().await?; - win1.map2().await?; - let win2 = client.create_window().await?; - win2.map2().await?; - - run.cfg.send_to_scratchpad(ds.seat.id(), "term")?; - client.sync().await; - tassert!(win1.tl.server.node_visible()); - tassert!(!win2.tl.server.node_visible()); - - run.cfg.show_workspace(ds.seat.id(), "2")?; - run.cfg.toggle_scratchpad(ds.seat.id(), "term")?; - client.sync().await; - tassert!(win2.tl.server.node_visible()); - tassert_eq!(ds.output.workspace.get().unwrap().name.as_str(), "2"); - - run.cfg.toggle_scratchpad(ds.seat.id(), "term")?; - client.sync().await; - tassert!(!win2.tl.server.node_visible()); - - run.cfg.toggle_scratchpad(ds.seat.id(), "term")?; - client.sync().await; - tassert!(win2.tl.server.node_visible()); - tassert_eq!(ds.output.workspace.get().unwrap().name.as_str(), "2"); - - run.cfg.show_workspace(ds.seat.id(), "3")?; - client.sync().await; - tassert!(!win2.tl.server.node_visible()); - - run.cfg.toggle_scratchpad(ds.seat.id(), "term")?; - client.sync().await; - tassert!(win2.tl.server.node_visible()); - tassert_eq!(ds.output.workspace.get().unwrap().name.as_str(), "3"); - // Scratchpad windows are always shown floating. - tassert!(win2.tl.server.tl_data().parent_is_float.get()); - - // Park win2 again, then build a multi-window scratchpad and cycle it. - run.cfg.toggle_scratchpad(ds.seat.id(), "term")?; - client.sync().await; - tassert!(!win2.tl.server.node_visible()); - - // Build a three-window scratchpad. Each window is focused right after it is - // mapped, so sending the focused window parks them in a known order. - let cyc1 = client.create_window().await?; - cyc1.map2().await?; - run.cfg.send_to_scratchpad(ds.seat.id(), "cyc")?; - let cyc2 = client.create_window().await?; - cyc2.map2().await?; - run.cfg.send_to_scratchpad(ds.seat.id(), "cyc")?; - let cyc3 = client.create_window().await?; - cyc3.map2().await?; - run.cfg.send_to_scratchpad(ds.seat.id(), "cyc")?; - client.sync().await; - tassert!(!cyc1.tl.server.node_visible()); - tassert!(!cyc2.tl.server.node_visible()); - tassert!(!cyc3.tl.server.node_visible()); - - // Nothing shown: cycle brings up the first window (insertion order: cyc1). - run.cfg.cycle_scratchpad(ds.seat.id(), "cyc")?; - client.sync().await; - tassert!(cyc1.tl.server.node_visible()); - tassert!(!cyc2.tl.server.node_visible()); - tassert!(!cyc3.tl.server.node_visible()); - // Scratchpad windows are always shown floating. - tassert!(cyc1.tl.server.tl_data().parent_is_float.get()); - - // Cycle advances one at a time. - run.cfg.cycle_scratchpad(ds.seat.id(), "cyc")?; - client.sync().await; - tassert!(!cyc1.tl.server.node_visible()); - tassert!(cyc2.tl.server.node_visible()); - tassert!(!cyc3.tl.server.node_visible()); - - run.cfg.cycle_scratchpad(ds.seat.id(), "cyc")?; - client.sync().await; - tassert!(!cyc1.tl.server.node_visible()); - tassert!(!cyc2.tl.server.node_visible()); - tassert!(cyc3.tl.server.node_visible()); - - // On the final window, the next cycle hides everything. - run.cfg.cycle_scratchpad(ds.seat.id(), "cyc")?; - client.sync().await; - tassert!(!cyc1.tl.server.node_visible()); - tassert!(!cyc2.tl.server.node_visible()); - tassert!(!cyc3.tl.server.node_visible()); - - // And it wraps back to the first window. - run.cfg.cycle_scratchpad(ds.seat.id(), "cyc")?; - client.sync().await; - tassert!(cyc1.tl.server.node_visible()); - - Ok(()) -} diff --git a/src/main.rs b/src/main.rs index 22c1f8bf..e95b8c01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -99,7 +99,6 @@ mod scale; mod screenshoter; mod sighand; mod state; -mod tagged_acceptor; mod tasks; mod text; mod theme; diff --git a/src/state.rs b/src/state.rs index 7186c6c9..f81ed745 100644 --- a/src/state.rs +++ b/src/state.rs @@ -87,7 +87,6 @@ use { pr_caps::PrCapsThread, rect::Rect, scale::Scale, - tagged_acceptor::TaggedAcceptors, theme::Theme, time::Time, tree::{ @@ -186,7 +185,6 @@ pub struct State { pub run_args: RunArgs, pub xwayland: XWaylandState, pub acceptor: CloneCell>>, - pub tagged_acceptors: TaggedAcceptors, pub serial: NumCell, pub run_toplevel: Rc, pub config_dir: Option, @@ -285,7 +283,6 @@ pub struct State { pub bo_drop_queue: Rc>>, pub virtual_outputs: VirtualOutputs, pub clean_logs_older_than: Cell>, - pub scratchpads: RefCell>>>, } // impl Drop for State { @@ -305,27 +302,6 @@ pub struct ScreenlockState { pub lock: CloneCell>>, } -pub struct ScratchpadEntry { - node: Weak, - identifier: ToplevelIdentifier, - hidden: Cell, -} - -impl ScratchpadEntry { - fn alive(&self) -> bool { - self.node().is_some() - } - - fn node(&self) -> Option> { - let node = self.node.upgrade()?; - if node.tl_data().identifier.get() == self.identifier { - Some(node) - } else { - None - } - } -} - pub struct InputDeviceData { pub _handler: SpawnedFuture<()>, pub id: InputDeviceId, @@ -499,7 +475,6 @@ impl State { self.eng.clear(); self.ei_acceptor.take(); self.ei_acceptor_future.take(); - self.tagged_acceptors.clear(); self.ei_clients.clear(); self.slow_ei_clients.clear(); self.toplevels.clear(); @@ -509,7 +484,6 @@ impl State { self.node_at_tree.borrow_mut().clear(); self.position_hint_requests.clear(); self.pending_warp_mouse_to_focus.clear(); - self.scratchpads.borrow_mut().clear(); self.head_managers.clear(); self.head_managers_async.clear(); self.const_40hz_latch.clear(); diff --git a/src/state/animations.rs b/src/state/animations.rs index 39e712bb..98bc1995 100644 --- a/src/state/animations.rs +++ b/src/state/animations.rs @@ -859,3 +859,4 @@ mod tests { assert_eq!(merged[1].node_id, NodeId(2)); } } + diff --git a/src/state/tree_ops.rs b/src/state/tree_ops.rs index 5e0ed85e..8a8e8f99 100644 --- a/src/state/tree_ops.rs +++ b/src/state/tree_ops.rs @@ -5,14 +5,13 @@ use { tree::{ ContainerNode, ContainerSplit, Direction, FindTreeUsecase, FloatNode, FoundNode, Node, OutputNode, TileState, ToplevelData, ToplevelNode, ToplevelNodeBase, WorkspaceNode, - WsMoveConfig, generic_node_visitor, move_ws_to_output, toplevel_hide_for_scratchpad, - toplevel_restore_from_scratchpad, toplevel_set_workspace, + WsMoveConfig, generic_node_visitor, move_ws_to_output, }, }, - std::{cell::Cell, ops::Deref, rc::Rc}, + std::{ops::Deref, rc::Rc}, }; -use super::{ScratchpadEntry, State}; +use super::State; impl State { pub fn tree_changed(&self) { @@ -42,39 +41,19 @@ impl State { && node.tl_data().kind.is_app_window() && !node.tl_data().visible.get(); if animate_new_app_map { - self.with_layout_animations(|| self.do_map_tiled(seat.as_deref(), node.clone(), true)); + self.with_layout_animations(|| self.do_map_tiled(seat.as_deref(), node.clone())); } else { - self.do_map_tiled(seat.as_deref(), node.clone(), true); + self.do_map_tiled(seat.as_deref(), node.clone()); } self.focus_after_map(node, seat.as_deref()); } - pub fn map_tiled_without_autotile(self: &Rc, node: Rc) { - let seat = self.seat_queue.last(); - self.do_map_tiled(seat.as_deref(), node.clone(), false); - self.focus_after_map(node, seat.as_deref()); - } - - fn do_map_tiled( - self: &Rc, - seat: Option<&Rc>, - node: Rc, - autotile: bool, - ) { + fn do_map_tiled(self: &Rc, seat: Option<&Rc>, node: Rc) { let ws = self.ensure_map_workspace(seat); - self.map_tiled_on_(node, &ws, autotile); + self.map_tiled_on(node, &ws); } pub fn map_tiled_on(self: &Rc, node: Rc, ws: &Rc) { - self.map_tiled_on_(node, ws, false); - } - - fn map_tiled_on_( - self: &Rc, - node: Rc, - ws: &Rc, - autotile: bool, - ) { if let Some(c) = ws.container.get() { let la = c.clone().tl_last_active_child(); let lap = la @@ -83,11 +62,7 @@ impl State { .get() .and_then(|n| n.node_into_container()); if let Some(lap) = lap { - if autotile { - lap.add_tiled_child_after(&*la, node); - } else { - lap.add_child_after(&*la, node); - } + lap.add_child_after(&*la, node); } else { c.append_child(node); } @@ -140,146 +115,6 @@ impl State { float } - pub fn send_to_scratchpad(self: &Rc, name: &str, node: Rc) { - if node.node_is_placeholder() { - return; - } - let identifier = node.tl_data().identifier.get(); - if !toplevel_hide_for_scratchpad(node.clone()) { - return; - } - let entry = Rc::new(ScratchpadEntry { - node: Rc::downgrade(&node), - identifier, - hidden: Cell::new(true), - }); - { - let mut scratchpads = self.scratchpads.borrow_mut(); - for entries in scratchpads.values_mut() { - entries.retain(|entry| entry.alive() && entry.identifier != identifier); - } - scratchpads - .entry(name.to_string()) - .or_default() - .push(entry); - } - self.tree_changed(); - } - - pub fn toggle_scratchpad(self: &Rc, seat: &Rc, name: &str) { - let entry = { - let mut scratchpads = self.scratchpads.borrow_mut(); - let Some(entries) = scratchpads.get_mut(name) else { - return; - }; - entries.retain(|entry| entry.alive()); - // Prefer the currently-shown window; otherwise act on the most recent. - entries - .iter() - .rev() - .find(|entry| !entry.hidden.get()) - .or_else(|| entries.last()) - .cloned() - }; - let Some(entry) = entry else { - return; - }; - if entry.hidden.get() { - self.show_scratchpad_entry(seat, name, &entry); - } else if entry.node().is_some_and(|node| !node.node_visible()) { - self.move_scratchpad_entry_to_current_workspace(seat, &entry); - } else { - self.hide_scratchpad_entry(&entry); - } - } - - /// Cycles through the windows of a scratchpad, one at a time: - /// nothing shown -> first window -> ... -> last window -> nothing shown. - pub fn cycle_scratchpad(self: &Rc, seat: &Rc, name: &str) { - let (current, next) = { - let mut scratchpads = self.scratchpads.borrow_mut(); - let Some(entries) = scratchpads.get_mut(name) else { - return; - }; - entries.retain(|entry| entry.alive()); - match entries.iter().position(|entry| !entry.hidden.get()) { - // Nothing shown yet: bring up the first window. - None => (None, entries.first().cloned()), - // Hide the shown window and advance; on the last window, `next` - // is `None`, so the scratchpad toggles off. - Some(i) => (entries.get(i).cloned(), entries.get(i + 1).cloned()), - } - }; - if let Some(current) = ¤t { - self.hide_scratchpad_entry(current); - } - if let Some(next) = &next { - self.show_scratchpad_entry(seat, name, next); - } - } - - fn hide_scratchpad_entry(self: &Rc, entry: &Rc) { - if entry.hidden.get() { - return; - } - let Some(node) = entry.node() else { - return; - }; - if toplevel_hide_for_scratchpad(node) { - entry.hidden.set(true); - self.tree_changed(); - } - } - - fn show_scratchpad_entry( - self: &Rc, - seat: &Rc, - name: &str, - entry: &Rc, - ) { - if !entry.hidden.get() { - return; - } - let Some(node) = entry.node() else { - return; - }; - // Only one window of a scratchpad is visible at a time. - let siblings: Vec<_> = { - let scratchpads = self.scratchpads.borrow(); - scratchpads - .get(name) - .into_iter() - .flatten() - .filter(|sibling| !Rc::ptr_eq(sibling, entry) && !sibling.hidden.get()) - .cloned() - .collect() - }; - for sibling in siblings { - self.hide_scratchpad_entry(&sibling); - } - let ws = seat.get_fallback_output().ensure_workspace(); - toplevel_restore_from_scratchpad(self, node.clone(), &ws); - entry.hidden.set(false); - node.node_do_focus(seat, Direction::Unspecified); - seat.maybe_schedule_warp_mouse_to_focus(); - self.tree_changed(); - } - - fn move_scratchpad_entry_to_current_workspace( - self: &Rc, - seat: &Rc, - entry: &Rc, - ) { - let Some(node) = entry.node() else { - return; - }; - let ws = seat.get_fallback_output().ensure_workspace(); - toplevel_set_workspace(self, node.clone(), &ws); - node.node_do_focus(seat, Direction::Unspecified); - seat.maybe_schedule_warp_mouse_to_focus(); - self.tree_changed(); - } - fn focus_after_map(&self, node: Rc, seat: Option<&Rc>) { if !node.node_visible() { return; diff --git a/src/tagged_acceptor.rs b/src/tagged_acceptor.rs deleted file mode 100644 index 9133f29a..00000000 --- a/src/tagged_acceptor.rs +++ /dev/null @@ -1,191 +0,0 @@ -use { - crate::{ - async_engine::SpawnedFuture, - client::ClientMetadata, - state::State, - utils::{ - errorfmt::ErrorFmt, - numcell::NumCell, - oserror::{OsError, OsErrorExt, OsErrorExt2}, - xrd::xrd, - }, - }, - ahash::AHashMap, - std::{ - cell::{Cell, RefCell}, - rc::Rc, - }, - thiserror::Error, - uapi::{OwnedFd, Ustring, c, format_ustr}, -}; - -#[derive(Debug, Error)] -pub enum TaggedAcceptorError { - #[error("XDG_RUNTIME_DIR is not set")] - XrdNotSet, - #[error("XDG_RUNTIME_DIR ({0:?}) is too long to form a unix socket address")] - XrdTooLong(String), - #[error("Could not create a wayland socket")] - SocketFailed(#[source] OsError), - #[error("Could not stat the existing socket")] - SocketStat(#[source] OsError), - #[error("Could not start listening for incoming connections")] - ListenFailed(#[source] OsError), - #[error("Could not open the lock file")] - OpenLockFile(#[source] OsError), - #[error("Could not lock the lock file")] - LockLockFile(#[source] OsError), - #[error("Could not bind the socket to an address")] - BindFailed(#[source] OsError), -} - -#[derive(Default)] -pub struct TaggedAcceptors { - acceptors: RefCell>>, - next_name: NumCell, -} - -struct Acceptor { - socket: AllocatedSocket, - tag: String, - state: Rc, - metadata: Rc, - future: Cell>>, -} - -impl TaggedAcceptors { - pub fn clear(&self) { - let acceptors = self.acceptors.take(); - for (_, acceptor) in acceptors { - acceptor.kill(); - } - } - - pub fn get(&self, state: &Rc, tag: &str) -> Result, TaggedAcceptorError> { - let acceptors = &mut *self.acceptors.borrow_mut(); - if let Some(acceptor) = acceptors.get(tag) { - return Ok(acceptor.socket.name.clone()); - } - let acceptor = Rc::new(Acceptor { - socket: self.allocate_socket()?, - tag: tag.to_owned(), - state: state.clone(), - metadata: Rc::new(ClientMetadata { - tag: Some(tag.to_owned()), - ..Default::default() - }), - future: Default::default(), - }); - log::info!("Creating tagged acceptor `{tag}`"); - acceptor.future.set(Some( - state.eng.spawn("tagged accept", acceptor.clone().accept()), - )); - acceptors.insert(tag.to_owned(), acceptor.clone()); - Ok(acceptor.socket.name.clone()) - } - - fn allocate_socket(&self) -> Result { - let xrd = xrd().ok_or(TaggedAcceptorError::XrdNotSet)?; - let socket = uapi::socket(c::AF_UNIX, c::SOCK_STREAM | c::SOCK_CLOEXEC, 0) - .map(Rc::new) - .map_os_err(TaggedAcceptorError::SocketFailed)?; - loop { - let i = self.next_name.fetch_add(1) + 1000; - if let Some(s) = bind_socket(&socket, &xrd, i)? { - return Ok(s); - } - } - } -} - -impl Acceptor { - fn kill(&self) { - log::info!("Destroying tagged acceptor `{}`", self.tag); - self.future.take(); - self.state - .tagged_acceptors - .acceptors - .borrow_mut() - .remove(&self.tag); - } - - async fn accept(self: Rc) { - let state = &self.state; - loop { - let fd = match state.ring.accept(&self.socket.socket, c::SOCK_CLOEXEC).await { - Ok(fd) => fd, - Err(e) => { - log::error!("Could not accept a client: {}", ErrorFmt(e)); - break; - } - }; - let id = state.clients.id(); - if let Err(e) = state.clients.spawn(id, state, fd, &self.metadata) { - log::error!("Could not spawn a client: {}", ErrorFmt(e)); - break; - } - } - self.kill(); - } -} - -struct AllocatedSocket { - // wayland-x - name: Rc, - // /run/user/1000/wayland-x - path: Ustring, - socket: Rc, - // /run/user/1000/wayland-x.lock - lock_path: Ustring, - _lock_fd: OwnedFd, -} - -impl Drop for AllocatedSocket { - fn drop(&mut self) { - let _ = uapi::unlink(&self.path); - let _ = uapi::unlink(&self.lock_path); - } -} - -fn bind_socket( - fd: &Rc, - xrd: &str, - id: u64, -) -> Result, TaggedAcceptorError> { - let mut addr: c::sockaddr_un = uapi::pod_zeroed(); - addr.sun_family = c::AF_UNIX as _; - let name = Rc::new(format!("wayland-{}", id)); - let path = format_ustr!("{}/{}", xrd, name); - let lock_path = format_ustr!("{}.lock", path.display()); - if path.len() + 1 > addr.sun_path.len() { - return Err(TaggedAcceptorError::XrdTooLong(xrd.to_string())); - } - let lock_fd = uapi::open(&*lock_path, c::O_CREAT | c::O_CLOEXEC | c::O_RDWR, 0o644) - .map_os_err(TaggedAcceptorError::OpenLockFile)?; - if let Err(e) = uapi::flock(lock_fd.raw(), c::LOCK_EX | c::LOCK_NB).to_os_error() { - if e.0 == c::EWOULDBLOCK { - return Ok(None); - } - return Err(TaggedAcceptorError::LockLockFile(e)); - } - match uapi::lstat(&path).to_os_error() { - Ok(_) => { - log::info!("Unlinking {}", path.display()); - let _ = uapi::unlink(&path); - } - Err(OsError(c::ENOENT)) => {} - Err(e) => return Err(TaggedAcceptorError::SocketStat(e)), - } - let sun_path = uapi::as_bytes_mut(&mut addr.sun_path[..]); - sun_path[..path.len()].copy_from_slice(path.as_bytes()); - sun_path[path.len()] = 0; - uapi::bind(fd.raw(), &addr).map_os_err(TaggedAcceptorError::BindFailed)?; - uapi::listen(fd.raw(), 4096).map_os_err(TaggedAcceptorError::ListenFailed)?; - Ok(Some(AllocatedSocket { - name, - path, - socket: fd.clone(), - lock_path, - _lock_fd: lock_fd, - })) -} diff --git a/src/tree/container.rs b/src/tree/container.rs index 85b1e065..3fbda5a7 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -36,7 +36,6 @@ use { linkedlist::{LinkedList, LinkedNode, NodeRef}, numcell::NumCell, rc_eq::rc_eq, - scroller::Scroller, threshold_counter::ThresholdCounter, }, }, @@ -155,7 +154,6 @@ pub struct ContainerNode { pub child_removed: Rc, pub all_children_resized: Rc, pub tab_bar: RefCell>, - scroll: Scroller, pub update_tab_textures_scheduled: Cell, pub ephemeral: Cell, } @@ -255,7 +253,6 @@ impl ContainerNode { child_removed: state.lazy_event_sources.create_source(), all_children_resized: state.post_layout_event_sources.create_source(), tab_bar: RefCell::new(None), - scroll: Default::default(), update_tab_textures_scheduled: Cell::new(false), ephemeral: Cell::new(Ephemeral::Off), }); @@ -280,47 +277,6 @@ impl ContainerNode { self.add_child_x(prev, new, |prev, new| self.add_child_after_(prev, new)); } - pub fn add_tiled_child_after(self: &Rc, prev: &dyn Node, new: Rc) { - if !self.state.theme.autotile_enabled.get() - || self.mono_child.is_some() - || self.num_children.get() <= 1 - { - self.add_child_after(prev, new); - return; - } - let focused = self - .child_nodes - .borrow() - .get(&prev.node_id()) - .map(|n| n.to_ref()); - let Some(focused) = focused else { - log::error!( - "Tried to autotile a child into a container but the preceding node is not in the container" - ); - return; - }; - let focused_node = focused.node.clone(); - let focused_active = focused_node.tl_data().active(); - let sub = ContainerNode::new( - &self.state, - &self.workspace.get(), - focused_node.clone(), - self.split.get().other(), - ); - // Autotile-created groups are structural and collapse once only one - // child remains. Explicit make-group commands control their own - // grouping through the regular manual paths. - sub.ephemeral.set(Ephemeral::On); - sub.append_child(new); - let sub_id = sub.node_id(); - 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); - } - } - pub fn add_child_before(self: &Rc, prev: &dyn Node, new: Rc) { self.add_child_x(prev, new, |prev, new| self.add_child_before_(prev, new)); } @@ -571,18 +527,6 @@ impl ContainerNode { self.activate_child2(child, false); } - fn activate_child_from_input( - self: &Rc, - child: &NodeRef, - seat: &Rc, - ) { - self.activate_child(child); - child - .node - .clone() - .node_do_focus(seat, Direction::Unspecified); - } - fn activate_child2(self: &Rc, child: &NodeRef, preserve_focus: bool) { if let Some(mc) = self.mono_child.get() { if mc.node.node_id() == child.node.node_id() { @@ -1200,6 +1144,42 @@ impl ContainerNode { } pub fn insert_child(self: &Rc, node: Rc, direction: Direction) { + // Autotile: if the container would become too narrow/tall, wrap the + // focused child and new node in a perpendicular sub-container. + if self.state.theme.autotile_enabled.get() && self.mono_child.is_none() { + let (pw, ph) = self.predict_child_body_size(); + let opposite = match self.split.get() { + ContainerSplit::Horizontal if pw > 0 && ph > 0 && pw < ph => { + Some(ContainerSplit::Vertical) + } + ContainerSplit::Vertical if pw > 0 && ph > 0 && ph < pw => { + Some(ContainerSplit::Horizontal) + } + _ => None, + }; + if let Some(opp_split) = opposite { + if let Some(focused) = self.focus_history.last() { + if self.num_children.get() <= 1 { + // Single child, autotile not applicable. + } else { + let focused_node = focused.node.clone(); + let was_ephemeral = self.ephemeral.replace(Ephemeral::Off); + self.clone().cnode_remove_child2(&*focused_node, true); + self.ephemeral.set(was_ephemeral); + let sub = ContainerNode::new( + &self.state, + &self.workspace.get(), + focused_node, + opp_split, + ); + sub.ephemeral.set(Ephemeral::On); + sub.append_child(node); + self.append_child(sub); + return; + } + } + } + } let (split, right) = direction_to_split(direction); if split != self.split.get() || right { self.append_child(node); @@ -1309,7 +1289,7 @@ impl ContainerNode { fn button( self: Rc, id: CursorType, - seat: &Rc, + _seat: &Rc, _time_usec: u64, pressed: bool, button: u32, @@ -1339,7 +1319,7 @@ impl ContainerNode { if let Some(child) = children.get(&child_id) { let child_ref = child.to_ref(); drop(children); - self.activate_child_from_input(&child_ref, seat); + self.activate_child(&child_ref); } return; } @@ -1712,33 +1692,31 @@ impl Node for ContainerNode { self.button(id, seat, time_usec, state == ButtonState::Pressed, button); } - fn node_on_axis_event(self: Rc, seat: &Rc, event: &PendingScroll) { + fn node_on_axis_event(self: Rc, _seat: &Rc, event: &PendingScroll) { if self.mono_child.is_none() { return; } - let steps = match self.scroll.handle(event) { - Some(steps) => steps, + // Use vertical scroll (index 1) to switch tabs. + let v = match event.v120[1].get() { + Some(v) if v != 0 => v, _ => return, }; - let mut target = match self.mono_child.get() { + let mono = match self.mono_child.get() { Some(m) => m, None => return, }; - let current_id = target.node.node_id(); - for _ in 0..steps.abs() { - let next = if steps > 0 { - target.next().or_else(|| self.children.first()) - } else { - target.prev().or_else(|| self.children.last()) - }; - match next { - Some(next) => target = next, - None => break, + let next = if v > 0 { + // Scroll down → next tab. + mono.next().or_else(|| self.children.first()) + } else { + // Scroll up → previous tab. + mono.prev().or_else(|| self.children.last()) + }; + if let Some(next) = next { + if next.node.node_id() != mono.node.node_id() { + self.activate_child(&next); } } - if target.node.node_id() != current_id { - self.activate_child_from_input(&target, seat); - } } fn node_on_leave(&self, seat: &WlSeatGlobal) { diff --git a/src/tree/container/tasks.rs b/src/tree/container/tasks.rs index 977e47f0..4c90413e 100644 --- a/src/tree/container/tasks.rs +++ b/src/tree/container/tasks.rs @@ -154,3 +154,4 @@ impl ContainerNode { self.damage(); } } + diff --git a/src/tree/display.rs b/src/tree/display.rs index 26b31a88..440916bf 100644 --- a/src/tree/display.rs +++ b/src/tree/display.rs @@ -8,25 +8,18 @@ use { renderer::Renderer, state::State, tree::{ - Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, - NodeLocation, OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination, + FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation, + OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination, WorkspaceNodeId, walker::NodeVisitor, }, utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList}, }, - std::{ - cell::{Cell, RefCell}, - mem, - ops::Deref, - rc::{Rc, Weak}, - }, + std::{cell::Cell, ops::Deref, rc::Rc}, }; pub struct DisplayNode { pub id: NodeId, pub extents: Cell, - visible: Cell, - suspend_restore_kb_foci: RefCell, Weak)>>, pub outputs: CopyHashMap>, pub stacked: Rc>>, pub stacked_above_layers: Rc>>, @@ -38,8 +31,6 @@ impl DisplayNode { let slf = Self { id, extents: Default::default(), - visible: Default::default(), - suspend_restore_kb_foci: Default::default(), outputs: Default::default(), stacked: Default::default(), stacked_above_layers: Default::default(), @@ -80,17 +71,6 @@ impl DisplayNode { pub fn update_visible(&self, state: &State) { let visible = state.root_visible(); - let was_visible = self.visible.replace(visible); - if !visible && was_visible { - let mut foci = self.suspend_restore_kb_foci.borrow_mut(); - foci.clear(); - for seat in state.globals.seats.lock().values() { - let node = seat.get_keyboard_node(); - if node.node_id() != self.id { - foci.push((seat.clone(), Rc::downgrade(&node))); - } - } - } for output in self.outputs.lock().values() { output.update_visible(); } @@ -102,20 +82,6 @@ impl DisplayNode { for seat in state.globals.seats.lock().values() { seat.set_visible(visible); } - if visible && !was_visible { - for (seat, node) in mem::take(&mut *self.suspend_restore_kb_foci.borrow_mut()) { - if seat.get_keyboard_node().node_id() == self.id { - if let Some(node) = node.upgrade() - && node.node_visible() - { - seat.focus_node(node); - } else { - seat.get_fallback_output() - .take_keyboard_navigation_focus(&seat, Direction::Unspecified); - } - } - } - } if visible { state.damage(self.extents.get()); } diff --git a/src/tree/toplevel.rs b/src/tree/toplevel.rs index 22f9ea9a..2b06ec42 100644 --- a/src/tree/toplevel.rs +++ b/src/tree/toplevel.rs @@ -967,7 +967,7 @@ impl ToplevelData { } fd.workspace.remove_fullscreen_node(); if fd.placeholder.is_destroyed() { - state.map_tiled_without_autotile(node); + state.map_tiled(node); return; } let parent = fd.placeholder.tl_data().parent.take().unwrap(); @@ -1247,7 +1247,7 @@ pub fn toplevel_set_floating(state: &Rc, tl: Rc, floati }; if !floating { parent.cnode_remove_child2(&*tl, true); - state.map_tiled_without_autotile(tl); + state.map_tiled(tl); } else if let Some(ws) = data.workspace.get() { let node_id = data.node_id; let old_body = @@ -1308,54 +1308,3 @@ pub fn toplevel_set_workspace(state: &Rc, tl: Rc, ws: & tl.tl_set_fullscreen(true, Some(ws.clone())); } } - -/// Removes a toplevel from the tree so it can be parked in a scratchpad. -/// -/// Returns `true` if the window was hidden. A placeholder, a window without a -/// parent, or a window that refuses to leave fullscreen cannot be parked. -pub fn toplevel_hide_for_scratchpad(tl: Rc) -> bool { - if tl.node_is_placeholder() { - return false; - } - let data = tl.tl_data(); - let workspace = data.workspace.get(); - if data.is_fullscreen.get() { - tl.clone().tl_set_fullscreen(false, None); - if data.is_fullscreen.get() { - return false; - } - } - let Some(parent) = data.parent.get() else { - return false; - }; - let kb_foci = collect_kb_foci(tl.clone()); - parent.cnode_remove_child2(&*tl, true); - data.parent.take(); - data.float.take(); - if data.parent_is_float.replace(false) { - data.property_changed(TL_CHANGED_FLOATING); - } - if data.workspace.take().is_some() { - data.property_changed(TL_CHANGED_WORKSPACE); - } - tl.tl_set_visible(false); - if let Some(workspace) = &workspace { - for seat in kb_foci { - workspace - .clone() - .node_do_focus(&seat, Direction::Unspecified); - } - } - true -} - -/// Maps a parked scratchpad window back onto `ws`. Scratchpad windows always -/// return floating, regardless of how they were laid out before parking. -pub fn toplevel_restore_from_scratchpad( - state: &Rc, - tl: Rc, - ws: &Rc, -) { - let (width, height) = tl.tl_data().float_size(ws); - state.map_floating(tl.clone(), width, height, ws, None); -}