diff --git a/api/lua/example_config.lua b/api/lua/example_config.lua index 143b64a..72cf9b2 100644 --- a/api/lua/example_config.lua +++ b/api/lua/example_config.lua @@ -42,55 +42,49 @@ require("pinnacle").setup(function(pinnacle) -- Mousebinds -------------------------------------------------------------------- - input.mousebind({ "Ctrl" }, buttons.left, "Press", function() - window.begin_move(buttons.left) - end) - input.mousebind({ "Ctrl" }, buttons.right, "Press", function() - window.begin_resize(buttons.right) - end) + input.mousebind({"Ctrl"}, buttons.left, "Press", + function() window.begin_move(buttons.left) end) + input.mousebind({"Ctrl"}, buttons.right, "Press", + function() window.begin_resize(buttons.right) end) -- Keybinds ---------------------------------------------------------------------- -- mod_key + Alt + q quits the compositor - input.keybind({ mod_key, "Alt" }, keys.q, pinnacle.quit) + input.keybind({mod_key, "Alt"}, keys.q, pinnacle.quit) -- mod_key + Alt + c closes the focused window - input.keybind({ mod_key, "Alt" }, keys.c, function() - window.get_focused():close() - end) + input.keybind({mod_key, "Alt"}, keys.c, + function() window.get_focused():close() end) -- mod_key + return spawns a terminal - input.keybind({ mod_key }, keys.Return, function() + input.keybind({mod_key}, keys.Return, function() process.spawn(terminal, function(stdout, stderr, exit_code, exit_msg) -- do something with the output here end) end) -- mod_key + Alt + Space toggle floating on the focused window - input.keybind({ mod_key, "Alt" }, keys.space, function() - window.get_focused():toggle_floating() - end) + input.keybind({mod_key, "Alt"}, keys.space, + function() window.get_focused():toggle_floating() end) -- mod_key + f toggles fullscreen on the focused window - input.keybind({ mod_key }, keys.f, function() - window.get_focused():toggle_fullscreen() - end) + input.keybind({mod_key}, keys.f, + function() window.get_focused():toggle_fullscreen() end) -- mod_key + m toggles maximized on the focused window - input.keybind({ mod_key }, keys.m, function() - window.get_focused():toggle_maximized() - end) + input.keybind({mod_key}, keys.m, + function() window.get_focused():toggle_maximized() end) -- Tags --------------------------------------------------------------------------- - local tags = { "1", "2", "3", "4", "5" } + local tags = {"1", "2", "3", "4", "5"} output.connect_for_all(function(op) -- Add tags 1, 2, 3, 4 and 5 on all monitors, and toggle tag 1 active by default op:add_tags(tags) -- Same as tag.add(op, "1", "2", "3", "4", "5") - tag.toggle({ name = "1", output = op }) + tag.toggle({name = "1", output = op}) -- Window rules -- Add your own window rules here. Below is an example. @@ -117,35 +111,30 @@ require("pinnacle").setup(function(pinnacle) -- Create a layout cycler to cycle your tag layouts. This will store which layout each tag has -- and change to the next or previous one in the array when the respective function is called. local layout_cycler = tag.layout_cycler({ - "MasterStack", - "Dwindle", - "Spiral", - "CornerTopLeft", - "CornerTopRight", - "CornerBottomLeft", - "CornerBottomRight", + "MasterStack", "Dwindle", "Spiral", "CornerTopLeft", "CornerTopRight", + "CornerBottomLeft", "CornerBottomRight" }) - input.keybind({ mod_key }, keys.space, layout_cycler.next) - input.keybind({ mod_key, "Shift" }, keys.space, layout_cycler.prev) + input.keybind({mod_key}, keys.space, layout_cycler.next) + input.keybind({mod_key, "Shift"}, keys.space, layout_cycler.prev) -- Tag manipulation for _, tag_name in pairs(tags) do -- mod_key + 1-5 switches tags - input.keybind({ mod_key }, tag_name, function() - tag.switch_to(tag_name) - end) + input.keybind({mod_key}, tag_name, + function() tag.switch_to(tag_name) end) -- mod_key + Shift + 1-5 toggles tags - input.keybind({ mod_key, "Shift" }, tag_name, function() - tag.toggle(tag_name) - end) + input.keybind({mod_key, "Shift"}, tag_name, + function() tag.toggle(tag_name) end) -- mod_key + Alt + 1-5 moves windows to tags - input.keybind({ mod_key, "Alt" }, tag_name, function() + input.keybind({mod_key, "Alt"}, tag_name, + function() window:get_focused():move_to_tag(tag_name) end) -- mod_key + Shift + Alt + 1-5 toggles tags on windows - input.keybind({ mod_key, "Shift", "Alt" }, tag_name, function() + input.keybind({mod_key, "Shift", "Alt"}, tag_name, + function() window.get_focused():toggle_tag(tag_name) end) end diff --git a/src/backend/udev.rs b/src/backend/udev.rs index 441cda1..6ab9677 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -1340,61 +1340,6 @@ fn render_surface( clock: &Clock, ) -> Result { - use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; - - let pending_wins = windows - .iter() - .filter(|win| win.alive()) - .filter(|win| { - let pending_size = if let WindowElement::Wayland(win) = win { - let current_state = win.toplevel().current_state(); - win.toplevel() - .with_pending_state(|state| state.size != current_state.size) - } else { - false - }; - pending_size || win.with_state(|state| !state.loc_request_state.is_idle()) - }) - .filter(|win| { - if let WindowElement::Wayland(win) = win { - !win.toplevel() - .current_state() - .states - .contains(xdg_toplevel::State::Resizing) - } else { - true - } - }) - .map(|win| { - ( - win.class().unwrap_or("None".to_string()), - win.title().unwrap_or("None".to_string()), - win.with_state(|state| state.loc_request_state.clone()), - ) - }) - .collect::>(); - - if !pending_wins.is_empty() { - tracing::debug!("Skipping frame, waiting on {pending_wins:?}"); - for win in windows.iter() { - win.send_frame(output, clock.now(), Some(Duration::ZERO), |_, _| { - Some(output.clone()) - }); - } - - surface - .compositor - .queue_frame(None) - .map_err(Into::::into)?; - - tracing::debug!("queued no frame"); - - // TODO: still draw the cursor here - surface.render_state = RenderState::WaitingForVblank { dirty: false }; - - return Ok(true); - } - let output_render_elements = crate::render::generate_render_elements( output, renderer, diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 1250d8c..609d701 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -257,57 +257,6 @@ impl State { fn render_winit_window(&mut self, output: &Output) { let winit = self.backend.winit_mut(); - // let pending_wins = self - // .windows - // .iter() - // .filter(|win| win.alive()) - // .filter(|win| { - // let pending_size = if let WindowElement::Wayland(win) = win { - // let current_state = win.toplevel().current_state(); - // win.toplevel() - // .with_pending_state(|state| state.size != current_state.size) - // } else { - // false - // }; - // pending_size || win.with_state(|state| !state.loc_request_state.is_idle()) - // }) - // .filter(|win| { - // if let WindowElement::Wayland(win) = win { - // !win.toplevel() - // .current_state() - // .states - // .contains(xdg_toplevel::State::Resizing) - // } else { - // true - // } - // }) - // .map(|win| { - // ( - // win.class().unwrap_or("None".to_string()), - // win.title().unwrap_or("None".to_string()), - // win.with_state(|state| state.loc_request_state.clone()), - // ) - // }) - // .collect::>(); - // - // if !pending_wins.is_empty() { - // // tracing::debug!("Skipping frame, waiting on {pending_wins:?}"); - // let op_clone = output.clone(); - // self.loop_handle.insert_idle(move |dt| { - // for win in dt.state.windows.iter() { - // win.send_frame( - // &op_clone, - // dt.state.clock.now(), - // Some(Duration::ZERO), - // surface_primary_scanout_output, - // ); - // } - // }); - // - // // TODO: still draw the cursor here - // - // return; - // } let full_redraw = &mut winit.full_redraw; *full_redraw = full_redraw.saturating_sub(1); diff --git a/src/layout.rs b/src/layout.rs index 45e1b9f..cbed4db 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later +use std::sync::atomic::AtomicU32; + use smithay::{ backend::renderer::utils::with_renderer_surface_state, desktop::layer_map_for_output, @@ -55,6 +57,10 @@ impl State { /// Compute tiled window locations and sizes, resize maximized and fullscreen windows correctly, /// and send configures and that cool stuff. pub fn update_windows(&mut self, output: &Output) { + static UPDATE_COUNT: AtomicU32 = AtomicU32::new(0); + UPDATE_COUNT.fetch_add(1, std::sync::atomic::Ordering::Relaxed); + let current_update_count = UPDATE_COUNT.load(std::sync::atomic::Ordering::Relaxed); + tracing::debug!("Updating windows"); let Some(layout) = output.with_state(|state| state.focused_tags().next().map(|tag| tag.layout())) @@ -173,14 +179,38 @@ impl State { for (win, _) in pending_wins.iter() { if let Some(surface) = win.wl_surface() { + let client = surface + .client() + .expect("Surface has no client/is no longer alive"); + self.client_compositor_state(&client) + .blocker_cleared(self, &self.display_handle.clone()); + + tracing::debug!("blocker cleared"); compositor::add_blocker(&surface, tiling_blocker.clone()); } } let pending_wins_clone = pending_wins.clone(); let pending_wins_clone2 = pending_wins.clone(); + self.schedule( - move |_dt| { + move |data| { + if UPDATE_COUNT.load(std::sync::atomic::Ordering::Relaxed) > current_update_count { + for (win, _) in pending_wins_clone2.iter() { + let Some(surface) = win.wl_surface() else { + continue; + }; + + let client = surface + .client() + .expect("Surface has no client/is no longer alive"); + data.state + .client_compositor_state(&client) + .blocker_cleared(&mut data.state, &data.display_handle); + + tracing::debug!("blocker cleared"); + } + } tiling_blocker.ready() && pending_wins_clone2.iter().all(|(win, _)| { if let Some(surface) = win.wl_surface() { @@ -205,21 +235,9 @@ impl State { tracing::debug!("blocker cleared"); } - }, - ); - self.schedule( - move |_dt| { - let all_idle = pending_wins - .iter() - .filter(|(win, _)| win.alive()) - .all(|(win, _)| win.with_state(|state| state.loc_request_state.is_idle())); - - all_idle - }, - move |dt| { for (loc, win) in non_pending_wins { - dt.state.space.map_element(win, loc, false); + data.state.space.map_element(win, loc, false); } }, );