mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Clean up old layouts
This commit is contained in:
parent
170addbad1
commit
d860172334
10 changed files with 160 additions and 304 deletions
|
@ -47,7 +47,6 @@ use smithay::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
layout::{Direction, Layouts},
|
||||
render::{pointer::PointerElement, CustomRenderElements, OutputRenderElements},
|
||||
state::{CalloopData, State},
|
||||
};
|
||||
|
@ -220,11 +219,7 @@ pub fn run_winit() -> Result<(), Box<dyn Error>> {
|
|||
None,
|
||||
None,
|
||||
);
|
||||
Layouts::master_stack(
|
||||
state,
|
||||
state.space.elements().cloned().collect(),
|
||||
Direction::Left,
|
||||
);
|
||||
state.re_layout();
|
||||
}
|
||||
WinitEvent::Focus(_) => {}
|
||||
WinitEvent::Input(input_evt) => {
|
||||
|
|
|
@ -19,7 +19,13 @@ use smithay::{
|
|||
utils::{IsAlive, Logical, Point, Rectangle},
|
||||
};
|
||||
|
||||
use crate::{backend::Backend, state::State, window::window_state::WindowState};
|
||||
use crate::{
|
||||
backend::Backend,
|
||||
layout::{Layout, LayoutVec},
|
||||
output::OutputState,
|
||||
state::State,
|
||||
window::window_state::{WindowResizeState, WindowState},
|
||||
};
|
||||
|
||||
pub struct MoveSurfaceGrab<S: SeatHandler> {
|
||||
pub start_data: GrabStartData<S>,
|
||||
|
@ -47,7 +53,7 @@ impl<B: Backend> PointerGrab<State<B>> for MoveSurfaceGrab<State<B>> {
|
|||
// tracing::info!("window geo is: {:?}", self.window.geometry());
|
||||
// tracing::info!("loc is: {:?}", data.space.element_location(&self.window));
|
||||
|
||||
let tiled = WindowState::with_state(&self.window, |state| state.floating.is_tiled());
|
||||
let tiled = WindowState::with(&self.window, |state| state.floating.is_tiled());
|
||||
|
||||
if tiled {
|
||||
// INFO: this is being used instead of space.element_under(event.location) because that
|
||||
|
@ -72,28 +78,46 @@ impl<B: Backend> PointerGrab<State<B>> for MoveSurfaceGrab<State<B>> {
|
|||
return;
|
||||
}
|
||||
|
||||
let window_under_floating =
|
||||
WindowState::with_state(&window_under, |state| state.floating.is_floating());
|
||||
let is_floating =
|
||||
WindowState::with(&window_under, |state| state.floating.is_floating());
|
||||
|
||||
if window_under_floating {
|
||||
if is_floating {
|
||||
return;
|
||||
}
|
||||
|
||||
data.swap_window_positions(&self.window, &window_under);
|
||||
let has_pending_resize = WindowState::with(&window_under, |state| {
|
||||
!matches!(state.resize_state, WindowResizeState::Idle)
|
||||
});
|
||||
|
||||
if has_pending_resize {
|
||||
return;
|
||||
}
|
||||
|
||||
// data.swap_window_positions(&self.window, &window_under);
|
||||
let output = data.focus_state.focused_output.as_ref().unwrap();
|
||||
OutputState::with(output, |state| {
|
||||
let mut tags = data
|
||||
.tag_state
|
||||
.tags
|
||||
.iter_mut()
|
||||
.filter(|tg| state.tags.contains(&tg.id));
|
||||
|
||||
if let Some(first) = tags.next() {
|
||||
let mut layout = first.windows.as_master_stack();
|
||||
|
||||
for tg in tags {
|
||||
layout = layout.chain_with(&mut tg.windows);
|
||||
}
|
||||
|
||||
layout.swap(&data.space, &self.window, &window_under);
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
let delta = event.location - self.start_data.location;
|
||||
let new_loc = self.initial_window_loc.to_f64() + delta;
|
||||
data.space
|
||||
.map_element(self.window.clone(), new_loc.to_i32_round(), true);
|
||||
// let loc = data
|
||||
// .space
|
||||
// .element_location(&self.window)
|
||||
// .unwrap_or((0, 0).into());
|
||||
// tracing::info!("new loc from element_location: {}, {}", loc.x, loc.y);
|
||||
// let geo = self.window.geometry();
|
||||
// tracing::info!("geo loc: {}, {}", geo.loc.x, geo.loc.y);
|
||||
// tracing::info!("geo size: {}, {}", geo.size.w, geo.size.h);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ impl<B: Backend> CompositorHandler for State<B> {
|
|||
crate::grab::resize_grab::handle_commit(self, surface);
|
||||
|
||||
if let Some(window) = self.window_for_surface(surface) {
|
||||
WindowState::with_state(&window, |state| {
|
||||
WindowState::with(&window, |state| {
|
||||
if let WindowResizeState::WaitingForCommit(new_pos) = state.resize_state {
|
||||
state.resize_state = WindowResizeState::Idle;
|
||||
self.space.map_element(window.clone(), new_pos, false);
|
||||
|
@ -225,11 +225,10 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
let window = Window::new(surface);
|
||||
|
||||
WindowState::with_state(&window, |state| {
|
||||
WindowState::with(&window, |state| {
|
||||
state.tags = if let Some(focused_output) = &self.focus_state.focused_output {
|
||||
OutputState::with(focused_output, |state| {
|
||||
let output_tags: Vec<crate::tag::TagId> =
|
||||
state.focused_tags.iter().cloned().collect();
|
||||
let output_tags: Vec<crate::tag::TagId> = state.tags.iter().cloned().collect();
|
||||
if !output_tags.is_empty() {
|
||||
output_tags
|
||||
} else if let Some(first_tag) = self.tag_state.tags.first() {
|
||||
|
@ -270,7 +269,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
.tag_state
|
||||
.tags
|
||||
.iter_mut()
|
||||
.filter(|tg| state.focused_tags.contains(&tg.id));
|
||||
.filter(|tg| state.tags.contains(&tg.id));
|
||||
|
||||
if let Some(first) = tags.next() {
|
||||
let mut layout = first.windows.as_master_stack();
|
||||
|
@ -302,7 +301,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
.tag_state
|
||||
.tags
|
||||
.iter_mut()
|
||||
.filter(|tg| state.focused_tags.contains(&tg.id));
|
||||
.filter(|tg| state.tags.contains(&tg.id));
|
||||
|
||||
if let Some(first) = tags.next() {
|
||||
tracing::debug!("first tag: {:?}", first.id);
|
||||
|
@ -429,10 +428,10 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
}
|
||||
|
||||
fn ack_configure(&mut self, surface: WlSurface, configure: Configure) {
|
||||
tracing::debug!("start of ack_configure");
|
||||
// tracing::debug!("start of ack_configure");
|
||||
if let Some(window) = self.window_for_surface(&surface) {
|
||||
tracing::debug!("found window for surface");
|
||||
WindowState::with_state(&window, |state| {
|
||||
// tracing::debug!("found window for surface");
|
||||
WindowState::with(&window, |state| {
|
||||
if let WindowResizeState::WaitingForAck(serial, new_loc) = state.resize_state {
|
||||
match &configure {
|
||||
Configure::Toplevel(configure) => {
|
||||
|
@ -453,7 +452,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
// | mapping the element in commit, this means that the window won't reappear on a tag
|
||||
// | change. The code below is a workaround until I can figure it out.
|
||||
if !self.space.elements().any(|win| win == &window) {
|
||||
WindowState::with_state(&window, |state| {
|
||||
WindowState::with(&window, |state| {
|
||||
if let WindowResizeState::WaitingForCommit(new_loc) = state.resize_state {
|
||||
tracing::debug!("remapping window");
|
||||
let win = window.clone();
|
||||
|
|
|
@ -9,15 +9,11 @@ use smithay::{
|
|||
desktop::{space::SpaceElement, Space, Window},
|
||||
output::Output,
|
||||
utils::{Logical, Size},
|
||||
wayland::{compositor, shell::xdg::XdgToplevelSurfaceData},
|
||||
};
|
||||
|
||||
use crate::window::window_state::{WindowResizeState, WindowState};
|
||||
|
||||
pub mod automatic;
|
||||
pub mod manual;
|
||||
|
||||
pub struct Layouts;
|
||||
|
||||
pub enum Direction {
|
||||
Left,
|
||||
Right,
|
||||
|
@ -75,7 +71,7 @@ impl MasterStack<'_, Window> {
|
|||
state.size = Some((output_geo.size.w / 2, height).into());
|
||||
});
|
||||
|
||||
WindowState::with_state(win, |state| {
|
||||
WindowState::with(win, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
win.toplevel().send_configure(),
|
||||
(output_geo.size.w / 2, i as i32 * height).into(),
|
||||
|
@ -101,12 +97,12 @@ pub fn swap_window_positions(space: &Space<Window>, win1: &Window, win2: &Window
|
|||
});
|
||||
|
||||
let serial = win1.toplevel().send_configure();
|
||||
WindowState::with_state(win1, |state| {
|
||||
WindowState::with(win1, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(serial, win2_loc);
|
||||
});
|
||||
|
||||
let serial = win2.toplevel().send_configure();
|
||||
WindowState::with_state(win2, |state| {
|
||||
WindowState::with(win2, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(serial, win1_loc);
|
||||
});
|
||||
}
|
||||
|
@ -127,7 +123,7 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
|
|||
state.size = Some(output_geo.size);
|
||||
});
|
||||
|
||||
WindowState::with_state(master, |state| {
|
||||
WindowState::with(master, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
|
@ -143,7 +139,7 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
|
|||
state.size = Some((output_geo.size.w / 2, output_geo.size.h).into());
|
||||
});
|
||||
|
||||
WindowState::with_state(master, |state| {
|
||||
WindowState::with(master, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
|
@ -172,7 +168,7 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
|
|||
state.size = Some(output_geo.size);
|
||||
});
|
||||
|
||||
WindowState::with_state(master, |state| {
|
||||
WindowState::with(master, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
|
@ -184,15 +180,46 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
|
|||
}
|
||||
|
||||
fn swap(&mut self, space: &Space<Window>, elem1: &Window, elem2: &Window) {
|
||||
let mut elems = self.inner.iter_mut().flat_map(|vec| vec.iter_mut());
|
||||
let first = elems.find(|elem| *elem == elem1);
|
||||
let second = elems.find(|elem| *elem == elem2);
|
||||
tracing::debug!("top of swap");
|
||||
|
||||
let mut elems = self
|
||||
.inner
|
||||
.iter_mut()
|
||||
.flat_map(|vec| vec.iter_mut())
|
||||
.filter(|elem| *elem == elem1 || *elem == elem2)
|
||||
.unique_by(|win| WindowState::with(win, |state| state.id));
|
||||
|
||||
let (first, second) = (elems.next(), elems.next());
|
||||
|
||||
if let Some(first) = first {
|
||||
if let Some(second) = second {
|
||||
std::mem::swap(first, second);
|
||||
}
|
||||
}
|
||||
|
||||
let wins = self
|
||||
.inner
|
||||
.iter()
|
||||
.map(|vec| {
|
||||
vec.iter()
|
||||
.enumerate()
|
||||
.map(|(i, win)| {
|
||||
compositor::with_states(win.toplevel().wl_surface(), |states| {
|
||||
let lock = states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.expect("XdgToplevelSurfaceData doesn't exist")
|
||||
.lock()
|
||||
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||
(i, lock.app_id.clone().unwrap_or("".to_string()))
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
tracing::debug!("windows are: {wins:?}");
|
||||
|
||||
swap_window_positions(space, elem1, elem2);
|
||||
}
|
||||
|
||||
|
@ -205,6 +232,27 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
|
|||
tracing::error!("could not get output geometry");
|
||||
return;
|
||||
};
|
||||
let wins = self
|
||||
.inner
|
||||
.iter()
|
||||
.map(|vec| {
|
||||
vec.iter()
|
||||
.enumerate()
|
||||
.map(|(i, win)| {
|
||||
compositor::with_states(win.toplevel().wl_surface(), |states| {
|
||||
let lock = states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.expect("XdgToplevelSurfaceData doesn't exist")
|
||||
.lock()
|
||||
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||
(i, lock.app_id.clone().unwrap_or("".to_string()))
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
tracing::debug!("windows are: {wins:?}");
|
||||
|
||||
if self.stack().count() == 0 {
|
||||
// one window
|
||||
|
@ -212,7 +260,7 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
|
|||
state.size = Some(output_geo.size);
|
||||
});
|
||||
|
||||
WindowState::with_state(master, |state| {
|
||||
WindowState::with(master, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
|
@ -224,7 +272,7 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
|
|||
master.toplevel().with_pending_state(|state| {
|
||||
state.size = Some(new_master_size);
|
||||
});
|
||||
WindowState::with_state(master, |state| {
|
||||
WindowState::with(master, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use smithay::{
|
||||
desktop::Window,
|
||||
wayland::{compositor, shell::xdg::XdgToplevelSurfaceData},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::Backend,
|
||||
state::State,
|
||||
window::window_state::{WindowResizeState, WindowState},
|
||||
};
|
||||
|
||||
use super::{Direction, Layouts};
|
||||
|
||||
impl Layouts {
|
||||
pub fn master_stack<B: Backend>(
|
||||
state: &mut State<B>,
|
||||
mut windows: Vec<Window>,
|
||||
side: Direction,
|
||||
) {
|
||||
windows.retain(|win| WindowState::with_state(win, |state| state.floating.is_tiled()));
|
||||
match side {
|
||||
Direction::Left => {
|
||||
let window_count = windows.len();
|
||||
if window_count == 0 {
|
||||
return;
|
||||
}
|
||||
// TODO: change focused_output to be not an option
|
||||
let Some(output) = state
|
||||
.focus_state
|
||||
.focused_output
|
||||
.as_ref()
|
||||
.or_else(|| state.space.outputs().next())
|
||||
else {
|
||||
tracing::warn!("no connected outputs");
|
||||
return;
|
||||
// TODO: no idea what happens if you spawn a window while no monitors are
|
||||
// | connected, figure that out
|
||||
};
|
||||
let output_size = state.space.output_geometry(output).unwrap().size;
|
||||
if window_count == 1 {
|
||||
tracing::debug!("Laying out only window");
|
||||
let window = windows[0].clone();
|
||||
|
||||
window.toplevel().with_pending_state(|tl_state| {
|
||||
tl_state.size = Some(state.space.output_geometry(output).unwrap().size);
|
||||
tracing::debug!("only size is {:?}", tl_state.size);
|
||||
});
|
||||
|
||||
let initial_configure_sent =
|
||||
compositor::with_states(window.toplevel().wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
tracing::debug!("initial configure sent is {initial_configure_sent}");
|
||||
if initial_configure_sent {
|
||||
WindowState::with_state(&window, |state| {
|
||||
tracing::debug!("sending configure");
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
window.toplevel().send_configure(),
|
||||
output.current_location(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tracing::debug!("layed out first window");
|
||||
let mut windows = windows.iter();
|
||||
let first_window = windows.next().unwrap();
|
||||
|
||||
first_window.toplevel().with_pending_state(|tl_state| {
|
||||
let mut size = state.space.output_geometry(output).unwrap().size;
|
||||
size.w /= 2;
|
||||
tl_state.size = Some(size);
|
||||
tracing::debug!("first size is {:?}", tl_state.size);
|
||||
});
|
||||
|
||||
let initial_configure_sent =
|
||||
compositor::with_states(first_window.toplevel().wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
if initial_configure_sent {
|
||||
WindowState::with_state(first_window, |state| {
|
||||
tracing::debug!("sending resize state");
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
first_window.toplevel().send_configure(),
|
||||
output.current_location(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
let window_count = windows.len() as i32;
|
||||
let height = output_size.h / window_count;
|
||||
let x = output.current_location().x + output_size.w / 2;
|
||||
|
||||
for (i, win) in windows.enumerate() {
|
||||
win.toplevel().with_pending_state(|state| {
|
||||
let mut new_size = output_size;
|
||||
new_size.w /= 2;
|
||||
new_size.w = new_size.w.clamp(1, i32::MAX);
|
||||
new_size.h /= window_count;
|
||||
// INFO: The newest window won't have its geometry.loc set until after here and I don't know
|
||||
// | why, so this is hardcoded to 40. I don't anticipate people using
|
||||
// | windows that are that short, so figuring it out is low priority.
|
||||
// | Kitty specifically will crash the compositor if it's resized such
|
||||
// | that the bottom border goes above the bottom of the title bar if
|
||||
// | this is set too low.
|
||||
new_size.h = new_size.h.clamp(40, i32::MAX);
|
||||
state.size = Some(new_size);
|
||||
tracing::debug!("size is {:?}", state.size);
|
||||
});
|
||||
|
||||
let mut new_loc = output.current_location();
|
||||
new_loc.x = x;
|
||||
new_loc.y = (i as i32) * height;
|
||||
|
||||
let initial_configure_sent =
|
||||
compositor::with_states(win.toplevel().wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
});
|
||||
if initial_configure_sent {
|
||||
WindowState::with_state(win, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
win.toplevel().send_configure(),
|
||||
new_loc,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Direction::Right => todo!(),
|
||||
Direction::Top => todo!(),
|
||||
Direction::Bottom => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
//
|
||||
// love how i'm licensing this empty file
|
|
@ -12,7 +12,7 @@ use crate::tag::TagId;
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct OutputState {
|
||||
pub focused_tags: HashSet<TagId>,
|
||||
pub tags: HashSet<TagId>,
|
||||
}
|
||||
|
||||
impl OutputState {
|
||||
|
|
90
src/state.rs
90
src/state.rs
|
@ -136,7 +136,7 @@ impl<B: Backend> State<B> {
|
|||
|
||||
Msg::SetWindowSize { window_id, size } => {
|
||||
let Some(window) = self.space.elements().find(|&win| {
|
||||
WindowState::with_state(win, |state| state.id == window_id)
|
||||
WindowState::with(win, |state| state.id == window_id)
|
||||
}) else { return; };
|
||||
|
||||
// TODO: tiled vs floating
|
||||
|
@ -149,9 +149,9 @@ impl<B: Backend> State<B> {
|
|||
if let Some(window) = self
|
||||
.windows
|
||||
.iter()
|
||||
.find(|&win| WindowState::with_state(win, |state| state.id == window_id))
|
||||
.find(|&win| WindowState::with(win, |state| state.id == window_id))
|
||||
{
|
||||
WindowState::with_state(window, |state| {
|
||||
WindowState::with(window, |state| {
|
||||
state.tags = vec![tag_id.clone()];
|
||||
});
|
||||
}
|
||||
|
@ -162,9 +162,9 @@ impl<B: Backend> State<B> {
|
|||
if let Some(window) = self
|
||||
.windows
|
||||
.iter()
|
||||
.find(|&win| WindowState::with_state(win, |state| state.id == window_id))
|
||||
.find(|&win| WindowState::with(win, |state| state.id == window_id))
|
||||
{
|
||||
WindowState::with_state(window, |state| {
|
||||
WindowState::with(window, |state| {
|
||||
if state.tags.contains(&tag_id) {
|
||||
state.tags.retain(|id| id != &tag_id);
|
||||
} else {
|
||||
|
@ -179,12 +179,12 @@ impl<B: Backend> State<B> {
|
|||
OutputState::with(
|
||||
self.focus_state.focused_output.as_ref().unwrap(), // TODO: handle error
|
||||
|state| {
|
||||
let should_remove = state.focused_tags.get(&tag_id).is_some();
|
||||
let should_remove = state.tags.get(&tag_id).is_some();
|
||||
if should_remove {
|
||||
state.focused_tags.remove(&tag_id);
|
||||
state.tags.remove(&tag_id);
|
||||
tracing::debug!("toggled tag {tag_id:?} off");
|
||||
} else {
|
||||
state.focused_tags.insert(tag_id.clone());
|
||||
state.tags.insert(tag_id.clone());
|
||||
tracing::debug!("toggled tag {tag_id:?} on");
|
||||
}
|
||||
},
|
||||
|
@ -194,9 +194,9 @@ impl<B: Backend> State<B> {
|
|||
}
|
||||
Msg::SwitchToTag { tag_id } => {
|
||||
OutputState::with(self.focus_state.focused_output.as_ref().unwrap(), |state| {
|
||||
state.focused_tags.clear();
|
||||
state.focused_tags.insert(tag_id.clone());
|
||||
tracing::debug!("focused tags: {:?}", state.focused_tags);
|
||||
state.tags.clear();
|
||||
state.tags.insert(tag_id.clone());
|
||||
tracing::debug!("focused tags: {:?}", state.tags);
|
||||
});
|
||||
|
||||
self.re_layout();
|
||||
|
@ -238,7 +238,7 @@ impl<B: Backend> State<B> {
|
|||
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||
(lock.app_id.clone(), lock.title.clone())
|
||||
});
|
||||
let (window_id, floating) = WindowState::with_state(¤t_focus, |state| {
|
||||
let (window_id, floating) = WindowState::with(¤t_focus, |state| {
|
||||
(state.id, state.floating.is_floating())
|
||||
});
|
||||
// TODO: unwrap
|
||||
|
@ -281,7 +281,7 @@ impl<B: Backend> State<B> {
|
|||
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||
(lock.app_id.clone(), lock.title.clone())
|
||||
});
|
||||
let (window_id, floating) = WindowState::with_state(win, |state| {
|
||||
let (window_id, floating) = WindowState::with(win, |state| {
|
||||
(state.id, state.floating.is_floating())
|
||||
});
|
||||
// TODO: unwrap
|
||||
|
@ -471,46 +471,38 @@ impl<B: Backend> State<B> {
|
|||
}
|
||||
|
||||
pub fn re_layout(&mut self) {
|
||||
let mut windows =
|
||||
OutputState::with(self.focus_state.focused_output.as_ref().unwrap(), |state| {
|
||||
for window in self.space.elements().cloned().collect::<Vec<_>>() {
|
||||
let should_render = WindowState::with_state(&window, |win_state| {
|
||||
for tag_id in win_state.tags.iter() {
|
||||
if state.focused_tags.get(tag_id).is_some() {
|
||||
return true;
|
||||
}
|
||||
let output = self.focus_state.focused_output.as_ref().unwrap();
|
||||
OutputState::with(output, |state| {
|
||||
for window in self.space.elements().cloned().collect::<Vec<_>>() {
|
||||
let should_render = WindowState::with(&window, |win_state| {
|
||||
for tag_id in win_state.tags.iter() {
|
||||
if state.tags.get(tag_id).is_some() {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
});
|
||||
if !should_render {
|
||||
self.space.unmap_elem(&window);
|
||||
}
|
||||
false
|
||||
});
|
||||
if !should_render {
|
||||
self.space.unmap_elem(&window);
|
||||
}
|
||||
}
|
||||
|
||||
let mut tags = self
|
||||
.tag_state
|
||||
.tags
|
||||
.iter_mut()
|
||||
.filter(|tg| state.tags.contains(&tg.id));
|
||||
|
||||
if let Some(first) = tags.next() {
|
||||
let mut layout = first.windows.as_master_stack();
|
||||
|
||||
for tg in tags {
|
||||
layout = layout.chain_with(&mut tg.windows);
|
||||
}
|
||||
|
||||
self.windows
|
||||
.iter()
|
||||
.filter(|&win| {
|
||||
WindowState::with_state(win, |win_state| {
|
||||
for tag_id in win_state.tags.iter() {
|
||||
if state.focused_tags.get(tag_id).is_some() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
})
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
|
||||
tracing::debug!("Laying out {} windows", windows.len());
|
||||
|
||||
windows.as_master_stack().layout(
|
||||
&self.space,
|
||||
self.focus_state.focused_output.as_ref().unwrap(),
|
||||
);
|
||||
|
||||
// Layouts::master_stack(self, windows, crate::layout::Direction::Left);
|
||||
layout.layout(&self.space, output);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,7 @@ use smithay::{
|
|||
wayland::{compositor, seat::WaylandFocus},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::Backend, layout::Layouts, state::State, window::window_state::WindowResizeState,
|
||||
};
|
||||
use crate::{backend::Backend, state::State};
|
||||
|
||||
use self::window_state::{Float, WindowId, WindowState};
|
||||
|
||||
|
@ -57,43 +55,11 @@ impl<B: Backend> State<B> {
|
|||
.cloned()
|
||||
})
|
||||
}
|
||||
|
||||
/// Swap the positions and sizes of two windows.
|
||||
pub fn swap_window_positions(&mut self, win1: &Window, win2: &Window) {
|
||||
// FIXME: moving the mouse quickly will break swapping
|
||||
|
||||
let win1_loc = self.space.element_location(win1).unwrap(); // TODO: handle unwraps
|
||||
let win2_loc = self.space.element_location(win2).unwrap();
|
||||
let win1_geo = win1.geometry();
|
||||
let win2_geo = win2.geometry();
|
||||
// tracing::info!("win1: {:?}, {:?}", win1_loc, win1_geo);
|
||||
// tracing::info!("win2: {:?}, {:?}", win2_loc, win2_geo);
|
||||
|
||||
win1.toplevel().with_pending_state(|state| {
|
||||
state.size = Some(win2_geo.size);
|
||||
});
|
||||
win2.toplevel().with_pending_state(|state| {
|
||||
state.size = Some(win1_geo.size);
|
||||
});
|
||||
|
||||
let serial = win1.toplevel().send_configure();
|
||||
WindowState::with_state(win1, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(serial, win2_loc);
|
||||
});
|
||||
|
||||
let serial = win2.toplevel().send_configure();
|
||||
WindowState::with_state(win2, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(serial, win1_loc);
|
||||
});
|
||||
|
||||
// self.space.map_element(win1.clone(), win2_loc, false);
|
||||
// self.space.map_element(win2.clone(), win1_loc, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Toggle a window's floating status.
|
||||
pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &Window) {
|
||||
WindowState::with_state(window, |window_state| {
|
||||
WindowState::with(window, |window_state| {
|
||||
match window_state.floating {
|
||||
Float::Tiled(prev_loc_and_size) => {
|
||||
if let Some((prev_loc, prev_size)) = prev_loc_and_size {
|
||||
|
@ -119,8 +85,7 @@ pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &Window) {
|
|||
}
|
||||
});
|
||||
|
||||
let windows = state.space.elements().cloned().collect::<Vec<_>>();
|
||||
Layouts::master_stack(state, windows, crate::layout::Direction::Left);
|
||||
state.re_layout();
|
||||
state.space.raise_element(window, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ use smithay::{
|
|||
|
||||
use crate::tag::{Tag, TagId, TagState};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct WindowId(u32);
|
||||
|
||||
// TODO: this probably doesn't need to be atomic
|
||||
|
@ -44,7 +44,7 @@ pub fn tags<'a>(tag_state: &'a TagState, window: &Window) -> Vec<&'a Tag> {
|
|||
tag_state
|
||||
.tags
|
||||
.iter()
|
||||
.filter(|&tag| WindowState::with_state(window, |state| state.tags.contains(&tag.id)))
|
||||
.filter(|&tag| WindowState::with(window, |state| state.tags.contains(&tag.id)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ impl WindowState {
|
|||
}
|
||||
|
||||
/// Access a [Window]'s state, optionally returning something.
|
||||
pub fn with_state<F, T>(window: &Window, mut func: F) -> T
|
||||
pub fn with<F, T>(window: &Window, mut func: F) -> T
|
||||
where
|
||||
F: FnMut(&mut Self) -> T,
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue