mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Change all *State.with(thing, ...) to thing.with_state(...)
This commit is contained in:
parent
ac6130408b
commit
930925a8f1
8 changed files with 263 additions and 253 deletions
|
@ -21,8 +21,8 @@ use smithay::{
|
|||
|
||||
use crate::{
|
||||
backend::Backend,
|
||||
state::State,
|
||||
window::window_state::{WindowResizeState, WindowState},
|
||||
state::{State, WithState},
|
||||
window::window_state::WindowResizeState,
|
||||
};
|
||||
|
||||
pub struct MoveSurfaceGrab<S: SeatHandler> {
|
||||
|
@ -51,7 +51,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(&self.window, |state| state.floating.is_tiled());
|
||||
let tiled = self.window.with_state(|state| state.floating.is_tiled());
|
||||
|
||||
if tiled {
|
||||
// INFO: this is being used instead of space.element_under(event.location) because that
|
||||
|
@ -76,16 +76,14 @@ impl<B: Backend> PointerGrab<State<B>> for MoveSurfaceGrab<State<B>> {
|
|||
return;
|
||||
}
|
||||
|
||||
let is_floating =
|
||||
WindowState::with(&window_under, |state| state.floating.is_floating());
|
||||
let is_floating = window_under.with_state(|state| state.floating.is_floating());
|
||||
|
||||
if is_floating {
|
||||
return;
|
||||
}
|
||||
|
||||
let has_pending_resize = WindowState::with(&window_under, |state| {
|
||||
!matches!(state.resize_state, WindowResizeState::Idle)
|
||||
});
|
||||
let has_pending_resize = window_under
|
||||
.with_state(|state| !matches!(state.resize_state, WindowResizeState::Idle));
|
||||
|
||||
if has_pending_resize {
|
||||
return;
|
||||
|
|
|
@ -18,7 +18,10 @@ use smithay::{
|
|||
wayland::{compositor, seat::WaylandFocus, shell::xdg::SurfaceCachedState},
|
||||
};
|
||||
|
||||
use crate::{backend::Backend, state::State, window::SurfaceState};
|
||||
use crate::{
|
||||
backend::Backend,
|
||||
state::{State, WithState},
|
||||
};
|
||||
|
||||
pub struct ResizeSurfaceGrab<S: SeatHandler> {
|
||||
start_data: GrabStartData<S>,
|
||||
|
@ -40,8 +43,8 @@ impl<S: SeatHandler> ResizeSurfaceGrab<S> {
|
|||
initial_window_rect: Rectangle<i32, Logical>,
|
||||
button_used: u32,
|
||||
) -> Self {
|
||||
ResizeSurfaceState::with_state(window.toplevel().wl_surface(), |state| {
|
||||
*state = ResizeSurfaceState::Resizing {
|
||||
window.toplevel().wl_surface().with_state(|state| {
|
||||
state.resize_state = ResizeSurfaceState::Resizing {
|
||||
edges,
|
||||
initial_window_rect,
|
||||
};
|
||||
|
@ -169,8 +172,8 @@ impl<B: Backend> PointerGrab<State<B>> for ResizeSurfaceGrab<State<B>> {
|
|||
|
||||
toplevel_surface.send_pending_configure();
|
||||
|
||||
ResizeSurfaceState::with_state(toplevel_surface.wl_surface(), |state| {
|
||||
*state = ResizeSurfaceState::WaitingForLastCommit {
|
||||
toplevel_surface.wl_surface().with_state(|state| {
|
||||
state.resize_state = ResizeSurfaceState::WaitingForLastCommit {
|
||||
edges: self.edges,
|
||||
initial_window_rect: self.initial_window_rect,
|
||||
};
|
||||
|
@ -193,7 +196,7 @@ impl<B: Backend> PointerGrab<State<B>> for ResizeSurfaceGrab<State<B>> {
|
|||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
|
||||
enum ResizeSurfaceState {
|
||||
pub enum ResizeSurfaceState {
|
||||
#[default]
|
||||
Idle,
|
||||
Resizing {
|
||||
|
@ -225,15 +228,14 @@ impl ResizeSurfaceState {
|
|||
}
|
||||
}
|
||||
|
||||
impl SurfaceState for ResizeSurfaceState {}
|
||||
|
||||
pub fn handle_commit<B: Backend>(state: &mut State<B>, surface: &WlSurface) -> Option<()> {
|
||||
let window = state.window_for_surface(surface)?;
|
||||
let mut window_loc = state.space.element_location(&window)?;
|
||||
let geometry = window.geometry();
|
||||
|
||||
let new_loc: Point<Option<i32>, Logical> = ResizeSurfaceState::with_state(surface, |state| {
|
||||
let new_loc: Point<Option<i32>, Logical> = surface.with_state(|state| {
|
||||
state
|
||||
.resize_state
|
||||
.commit()
|
||||
.map(|(edges, initial_window_rect)| {
|
||||
let mut new_x: Option<i32> = None;
|
||||
|
|
|
@ -48,9 +48,8 @@ use smithay::{
|
|||
use crate::{
|
||||
backend::Backend,
|
||||
layout::{Layout, LayoutVec},
|
||||
output::OutputState,
|
||||
state::{ClientState, State},
|
||||
window::window_state::{CommitState, WindowResizeState, WindowState},
|
||||
state::{ClientState, State, WithState},
|
||||
window::window_state::WindowResizeState,
|
||||
};
|
||||
|
||||
impl<B: Backend> BufferHandler for State<B> {
|
||||
|
@ -117,22 +116,11 @@ 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(&window, |state| {
|
||||
window.with_state(|state| {
|
||||
if let WindowResizeState::WaitingForCommit(new_pos) = state.resize_state {
|
||||
state.resize_state = WindowResizeState::Idle;
|
||||
self.space.map_element(window.clone(), new_pos, false);
|
||||
}
|
||||
|
||||
if let CommitState::Acked = state.needs_raise {
|
||||
let clone = window.clone();
|
||||
|
||||
// FIXME: happens before the other windows ack, so it's useless
|
||||
self.loop_handle.insert_idle(move |data| {
|
||||
tracing::debug!("raising window");
|
||||
data.state.space.raise_element(&clone, true);
|
||||
});
|
||||
state.needs_raise = CommitState::Idle;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -236,12 +224,12 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
fn new_toplevel(&mut self, surface: ToplevelSurface) {
|
||||
let window = Window::new(surface);
|
||||
|
||||
WindowState::with(&window, |state| {
|
||||
window.with_state(|state| {
|
||||
state.tags = match (
|
||||
&self.focus_state.focused_output,
|
||||
self.space.outputs().next(),
|
||||
) {
|
||||
(Some(output), _) | (None, Some(output)) => OutputState::with(output, |state| {
|
||||
(Some(output), _) | (None, Some(output)) => output.with_state(|state| {
|
||||
let output_tags = state
|
||||
.focused_tags()
|
||||
.map(|tag| tag.id.clone())
|
||||
|
@ -276,7 +264,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
|
||||
self.loop_handle.insert_idle(move |data| {
|
||||
if let Some(focused_output) = &data.state.focus_state.focused_output {
|
||||
OutputState::with(focused_output, |state| {
|
||||
focused_output.with_state(|state| {
|
||||
data.state
|
||||
.windows
|
||||
.to_master_stack(state.focused_tags().map(|tag| tag.id.clone()).collect())
|
||||
|
@ -290,7 +278,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
tracing::debug!("toplevel destroyed");
|
||||
self.windows.retain(|window| window.toplevel() != &surface);
|
||||
if let Some(focused_output) = self.focus_state.focused_output.as_ref() {
|
||||
OutputState::with(focused_output, |state| {
|
||||
focused_output.with_state(|state| {
|
||||
self.windows
|
||||
.to_master_stack(state.focused_tags().map(|tag| tag.id.clone()).collect())
|
||||
.layout(&self.space, focused_output);
|
||||
|
@ -400,7 +388,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
// tracing::debug!("start of ack_configure");
|
||||
if let Some(window) = self.window_for_surface(&surface) {
|
||||
// tracing::debug!("found window for surface");
|
||||
WindowState::with(&window, |state| {
|
||||
window.with_state(|state| {
|
||||
if let WindowResizeState::WaitingForAck(serial, new_loc) = state.resize_state {
|
||||
match &configure {
|
||||
Configure::Toplevel(configure) => {
|
||||
|
@ -412,9 +400,6 @@ impl<B: Backend> XdgShellHandler for State<B> {
|
|||
Configure::Popup(_) => todo!(),
|
||||
}
|
||||
}
|
||||
if let CommitState::RequestReceived(_serial) = state.needs_raise {
|
||||
state.needs_raise = CommitState::Acked;
|
||||
}
|
||||
});
|
||||
|
||||
// HACK: If a window is currently going through something that generates a bunch of
|
||||
|
@ -424,7 +409,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(&window, |state| {
|
||||
window.with_state(|state| {
|
||||
if let WindowResizeState::WaitingForCommit(new_loc) = state.resize_state {
|
||||
tracing::debug!("remapping window");
|
||||
let win = window.clone();
|
||||
|
|
180
src/layout.rs
180
src/layout.rs
|
@ -12,9 +12,9 @@ use smithay::{
|
|||
|
||||
use crate::{
|
||||
backend::Backend,
|
||||
state::State,
|
||||
state::{State, WithState},
|
||||
tag::TagId,
|
||||
window::window_state::{WindowResizeState, WindowState},
|
||||
window::window_state::WindowResizeState,
|
||||
};
|
||||
|
||||
pub enum Direction {
|
||||
|
@ -24,12 +24,12 @@ pub enum Direction {
|
|||
Bottom,
|
||||
}
|
||||
|
||||
pub struct MasterStack<S: SpaceElement> {
|
||||
inner: Vec<S>,
|
||||
pub trait Layout<S: SpaceElement> {
|
||||
fn layout(&self, space: &Space<S>, output: &Output);
|
||||
}
|
||||
|
||||
pub trait Layout<'a, S: SpaceElement> {
|
||||
fn layout(&self, space: &Space<S>, output: &Output);
|
||||
pub struct MasterStack<S: SpaceElement> {
|
||||
inner: Vec<S>,
|
||||
}
|
||||
|
||||
impl MasterStack<Window> {
|
||||
|
@ -40,9 +40,7 @@ impl MasterStack<Window> {
|
|||
pub fn stack(&self) -> impl Iterator<Item = &Window> {
|
||||
self.inner.iter().skip(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl MasterStack<Window> {
|
||||
fn layout_stack(&self, space: &Space<Window>, output: &Output) {
|
||||
let stack_count = self.stack().count();
|
||||
|
||||
|
@ -58,7 +56,7 @@ impl MasterStack<Window> {
|
|||
state.size = Some((output_geo.size.w / 2, height).into());
|
||||
});
|
||||
|
||||
WindowState::with(win, |state| {
|
||||
win.with_state(|state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
win.toplevel().send_configure(),
|
||||
(output_geo.size.w / 2, i as i32 * height).into(),
|
||||
|
@ -68,6 +66,96 @@ impl MasterStack<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Layout<Window> for MasterStack<Window> {
|
||||
fn layout(&self, space: &Space<Window>, output: &Output) {
|
||||
let Some(master) = self.master() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(output_geo) = space.output_geometry(output) else {
|
||||
tracing::error!("could not get output geometry");
|
||||
return;
|
||||
};
|
||||
|
||||
if self.stack().count() == 0 {
|
||||
// one window
|
||||
master.toplevel().with_pending_state(|state| {
|
||||
state.size = Some(output_geo.size);
|
||||
});
|
||||
|
||||
master.with_state(|state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
let new_master_size: Size<i32, Logical> =
|
||||
(output_geo.size.w / 2, output_geo.size.h).into();
|
||||
master.toplevel().with_pending_state(|state| {
|
||||
state.size = Some(new_master_size);
|
||||
});
|
||||
master.with_state(|state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
);
|
||||
});
|
||||
|
||||
self.layout_stack(space, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Dwindle<S: SpaceElement> {
|
||||
inner: Vec<S>,
|
||||
}
|
||||
|
||||
impl Layout<Window> for Dwindle<Window> {
|
||||
fn layout(&self, space: &Space<Window>, output: &Output) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LayoutVec<S: SpaceElement> {
|
||||
/// Interpret this vec as a master-stack layout.
|
||||
fn to_master_stack(&self, tags: Vec<TagId>) -> MasterStack<S>;
|
||||
fn to_dwindle(&self, tags: Vec<TagId>) -> Dwindle<S>;
|
||||
}
|
||||
|
||||
impl LayoutVec<Window> for Vec<Window> {
|
||||
fn to_master_stack(&self, tags: Vec<TagId>) -> MasterStack<Window> {
|
||||
MasterStack {
|
||||
inner: filter_windows(self, tags),
|
||||
}
|
||||
}
|
||||
|
||||
fn to_dwindle(&self, tags: Vec<TagId>) -> Dwindle<Window> {
|
||||
Dwindle {
|
||||
inner: filter_windows(self, tags),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn filter_windows(windows: &[Window], tags: Vec<TagId>) -> Vec<Window> {
|
||||
windows
|
||||
.iter()
|
||||
.filter(|window| {
|
||||
window.with_state(|state| {
|
||||
state.floating.is_tiled() && {
|
||||
for tag_id in state.tags.iter() {
|
||||
if tags.iter().any(|tag| tag == tag_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
})
|
||||
})
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
|
||||
impl<B: Backend> State<B> {
|
||||
pub fn swap_window_positions(&mut self, win1: &Window, win2: &Window) {
|
||||
// FIXME: moving the mouse quickly will break swapping
|
||||
|
@ -85,12 +173,12 @@ impl<B: Backend> State<B> {
|
|||
});
|
||||
|
||||
let serial = win1.toplevel().send_configure();
|
||||
WindowState::with(win1, |state| {
|
||||
win1.with_state(|state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(serial, win2_loc);
|
||||
});
|
||||
|
||||
let serial = win2.toplevel().send_configure();
|
||||
WindowState::with(win2, |state| {
|
||||
win2.with_state(|state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(serial, win1_loc);
|
||||
});
|
||||
|
||||
|
@ -108,73 +196,3 @@ impl<B: Backend> State<B> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Layout<'a, Window> for MasterStack<Window> {
|
||||
fn layout(&self, space: &Space<Window>, output: &Output) {
|
||||
let Some(master) = self.master() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let Some(output_geo) = space.output_geometry(output) else {
|
||||
tracing::error!("could not get output geometry");
|
||||
return;
|
||||
};
|
||||
|
||||
if self.stack().count() == 0 {
|
||||
// one window
|
||||
master.toplevel().with_pending_state(|state| {
|
||||
state.size = Some(output_geo.size);
|
||||
});
|
||||
|
||||
WindowState::with(master, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
let new_master_size: Size<i32, Logical> =
|
||||
(output_geo.size.w / 2, output_geo.size.h).into();
|
||||
master.toplevel().with_pending_state(|state| {
|
||||
state.size = Some(new_master_size);
|
||||
});
|
||||
WindowState::with(master, |state| {
|
||||
state.resize_state = WindowResizeState::WaitingForAck(
|
||||
master.toplevel().send_configure(),
|
||||
(0, 0).into(),
|
||||
);
|
||||
});
|
||||
|
||||
self.layout_stack(space, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LayoutVec<S: SpaceElement> {
|
||||
/// Interpret this vec as a master-stack layout.
|
||||
fn to_master_stack(&self, tags: Vec<TagId>) -> MasterStack<S>;
|
||||
// fn as_binary_tree(&mut self); TODO:
|
||||
}
|
||||
|
||||
impl LayoutVec<Window> for Vec<Window> {
|
||||
fn to_master_stack(&self, tags: Vec<TagId>) -> MasterStack<Window> {
|
||||
MasterStack {
|
||||
inner: self
|
||||
.iter()
|
||||
.filter(|window| {
|
||||
WindowState::with(window, |state| {
|
||||
state.floating.is_tiled() && {
|
||||
for tag_id in state.tags.iter() {
|
||||
if tags.iter().any(|tag| tag == tag_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
})
|
||||
})
|
||||
.cloned()
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,33 +8,34 @@ use std::cell::RefCell;
|
|||
|
||||
use smithay::output::Output;
|
||||
|
||||
use crate::tag::Tag;
|
||||
use crate::{state::WithState, tag::Tag};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct OutputState {
|
||||
pub tags: Vec<Tag>,
|
||||
}
|
||||
|
||||
impl WithState for Output {
|
||||
type State = OutputState;
|
||||
|
||||
fn with_state<F, T>(&self, mut func: F) -> T
|
||||
where
|
||||
F: FnMut(&mut Self::State) -> T,
|
||||
{
|
||||
self.user_data()
|
||||
.insert_if_missing(RefCell::<Self::State>::default);
|
||||
|
||||
let state = self
|
||||
.user_data()
|
||||
.get::<RefCell<Self::State>>()
|
||||
.expect("RefCell not in data map");
|
||||
|
||||
func(&mut state.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
||||
impl OutputState {
|
||||
pub fn focused_tags(&mut self) -> impl Iterator<Item = &mut Tag> {
|
||||
self.tags.iter_mut().filter(|tag| tag.active)
|
||||
}
|
||||
}
|
||||
|
||||
impl OutputState {
|
||||
pub fn with<F, T>(output: &Output, mut func: F) -> T
|
||||
where
|
||||
F: FnMut(&mut Self) -> T,
|
||||
{
|
||||
output
|
||||
.user_data()
|
||||
.insert_if_missing(RefCell::<Self>::default);
|
||||
|
||||
let mut state = output
|
||||
.user_data()
|
||||
.get::<RefCell<Self>>()
|
||||
.expect("RefCell not in data map");
|
||||
|
||||
func(&mut state.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
|
154
src/state.rs
154
src/state.rs
|
@ -5,6 +5,7 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
error::Error,
|
||||
ffi::OsString,
|
||||
os::{fd::AsRawFd, unix::net::UnixStream},
|
||||
|
@ -19,13 +20,10 @@ use crate::{
|
|||
PinnacleSocketSource,
|
||||
},
|
||||
focus::FocusState,
|
||||
grab::resize_grab::ResizeSurfaceState,
|
||||
layout::{Layout, LayoutVec},
|
||||
output::OutputState,
|
||||
tag::Tag,
|
||||
window::{
|
||||
window_state::{WindowResizeState, WindowState},
|
||||
WindowProperties,
|
||||
},
|
||||
window::{window_state::WindowResizeState, WindowProperties},
|
||||
};
|
||||
use calloop::futures::Scheduler;
|
||||
use futures_lite::AsyncBufReadExt;
|
||||
|
@ -47,6 +45,7 @@ use smithay::{
|
|||
},
|
||||
wayland_server::{
|
||||
backend::{ClientData, ClientId, DisconnectReason},
|
||||
protocol::wl_surface::WlSurface,
|
||||
Display,
|
||||
},
|
||||
},
|
||||
|
@ -138,7 +137,7 @@ impl<B: Backend> State<B> {
|
|||
|
||||
Msg::SetWindowSize { window_id, size } => {
|
||||
let Some(window) = self.space.elements().find(|&win| {
|
||||
WindowState::with(win, |state| state.id == window_id)
|
||||
win.with_state( |state| state.id == window_id)
|
||||
}) else { return; };
|
||||
|
||||
// TODO: tiled vs floating
|
||||
|
@ -151,18 +150,19 @@ impl<B: Backend> State<B> {
|
|||
if let Some(window) = self
|
||||
.windows
|
||||
.iter()
|
||||
.find(|&win| WindowState::with(win, |state| state.id == window_id))
|
||||
.find(|&win| win.with_state(|state| state.id == window_id))
|
||||
{
|
||||
WindowState::with(window, |state| {
|
||||
OutputState::with(
|
||||
&self.focus_state.focused_output.as_ref().unwrap(),
|
||||
|op_state| {
|
||||
window.with_state(|state| {
|
||||
self.focus_state
|
||||
.focused_output
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.with_state(|op_state| {
|
||||
let tag = op_state.tags.iter().find(|tag| tag.name == tag_id);
|
||||
if let Some(tag) = tag {
|
||||
state.tags = vec![tag.id.clone()];
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -172,12 +172,14 @@ impl<B: Backend> State<B> {
|
|||
if let Some(window) = self
|
||||
.windows
|
||||
.iter()
|
||||
.find(|&win| WindowState::with(win, |state| state.id == window_id))
|
||||
.find(|&win| win.with_state(|state| state.id == window_id))
|
||||
{
|
||||
WindowState::with(window, |state| {
|
||||
OutputState::with(
|
||||
&self.focus_state.focused_output.as_ref().unwrap(),
|
||||
|op_state| {
|
||||
window.with_state(|state| {
|
||||
self.focus_state
|
||||
.focused_output
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.with_state(|op_state| {
|
||||
let tag = op_state.tags.iter().find(|tag| tag.name == tag_id);
|
||||
if let Some(tag) = tag {
|
||||
if state.tags.contains(&tag.id) {
|
||||
|
@ -186,50 +188,54 @@ impl<B: Backend> State<B> {
|
|||
state.tags.push(tag.id.clone());
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
self.re_layout();
|
||||
}
|
||||
}
|
||||
Msg::ToggleTag { tag_id } => {
|
||||
OutputState::with(
|
||||
self.focus_state.focused_output.as_ref().unwrap(), // TODO: handle error
|
||||
|state| {
|
||||
self.focus_state
|
||||
.focused_output
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.with_state(|state| {
|
||||
if let Some(tag) = state.tags.iter_mut().find(|tag| tag.name == tag_id) {
|
||||
tag.active = !tag.active;
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
self.re_layout();
|
||||
}
|
||||
Msg::SwitchToTag { tag_id } => {
|
||||
OutputState::with(self.focus_state.focused_output.as_ref().unwrap(), |state| {
|
||||
if !state.tags.iter().any(|tag| tag.name == tag_id) {
|
||||
// TODO: notify error
|
||||
return;
|
||||
}
|
||||
for tag in state.tags.iter_mut() {
|
||||
tag.active = false;
|
||||
}
|
||||
self.focus_state
|
||||
.focused_output
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.with_state(|state| {
|
||||
if !state.tags.iter().any(|tag| tag.name == tag_id) {
|
||||
// TODO: notify error
|
||||
return;
|
||||
}
|
||||
for tag in state.tags.iter_mut() {
|
||||
tag.active = false;
|
||||
}
|
||||
|
||||
let Some(tag) = state.tags.iter_mut().find(|tag| tag.name == tag_id) else {
|
||||
let Some(tag) = state.tags.iter_mut().find(|tag| tag.name == tag_id) else {
|
||||
unreachable!()
|
||||
};
|
||||
tag.active = true;
|
||||
tag.active = true;
|
||||
|
||||
tracing::debug!(
|
||||
"focused tags: {:?}",
|
||||
state
|
||||
.tags
|
||||
.iter()
|
||||
.filter(|tag| tag.active)
|
||||
.map(|tag| &tag.name)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
});
|
||||
tracing::debug!(
|
||||
"focused tags: {:?}",
|
||||
state
|
||||
.tags
|
||||
.iter()
|
||||
.filter(|tag| tag.active)
|
||||
.map(|tag| &tag.name)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
});
|
||||
|
||||
self.re_layout();
|
||||
}
|
||||
|
@ -241,7 +247,7 @@ impl<B: Backend> State<B> {
|
|||
.as_ref()
|
||||
.or_else(|| self.space.outputs().next())
|
||||
{
|
||||
OutputState::with(output, |state| {
|
||||
output.with_state(|state| {
|
||||
state.tags.extend(
|
||||
tags.clone()
|
||||
.into_iter()
|
||||
|
@ -252,7 +258,7 @@ impl<B: Backend> State<B> {
|
|||
}
|
||||
Msg::RemoveTags { tags } => {
|
||||
for output in self.space.outputs() {
|
||||
OutputState::with(output, |state| {
|
||||
output.with_state(|state| {
|
||||
state.tags.retain(|tag| !tags.contains(&tag.name));
|
||||
});
|
||||
}
|
||||
|
@ -277,9 +283,8 @@ impl<B: Backend> State<B> {
|
|||
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||
(lock.app_id.clone(), lock.title.clone())
|
||||
});
|
||||
let (window_id, floating) = WindowState::with(¤t_focus, |state| {
|
||||
(state.id, state.floating.is_floating())
|
||||
});
|
||||
let (window_id, floating) =
|
||||
current_focus.with_state(|state| (state.id, state.floating.is_floating()));
|
||||
// TODO: unwrap
|
||||
let location = self.space.element_location(¤t_focus).unwrap();
|
||||
let props = WindowProperties {
|
||||
|
@ -320,9 +325,8 @@ impl<B: Backend> State<B> {
|
|||
.expect("Couldn't lock XdgToplevelSurfaceData");
|
||||
(lock.app_id.clone(), lock.title.clone())
|
||||
});
|
||||
let (window_id, floating) = WindowState::with(win, |state| {
|
||||
(state.id, state.floating.is_floating())
|
||||
});
|
||||
let (window_id, floating) =
|
||||
win.with_state(|state| (state.id, state.floating.is_floating()));
|
||||
// TODO: unwrap
|
||||
let location = self
|
||||
.space
|
||||
|
@ -511,12 +515,12 @@ impl<B: Backend> State<B> {
|
|||
|
||||
pub fn re_layout(&mut self) {
|
||||
let output = self.focus_state.focused_output.as_ref().unwrap();
|
||||
let (render, do_not_render) = OutputState::with(output, |state| {
|
||||
let (render, do_not_render) = output.with_state(|state| {
|
||||
self.windows
|
||||
.to_master_stack(state.focused_tags().map(|tag| tag.id.clone()).collect())
|
||||
.layout(&self.space, output);
|
||||
self.windows.iter().cloned().partition::<Vec<_>, _>(|win| {
|
||||
WindowState::with(win, |win_state| {
|
||||
win.with_state(|win_state| {
|
||||
if win_state.floating.is_floating() {
|
||||
return true;
|
||||
}
|
||||
|
@ -547,12 +551,11 @@ impl<B: Backend> State<B> {
|
|||
tracing::debug!("running idle cb");
|
||||
tracing::debug!("win len is {}", windows.len());
|
||||
for window in windows.iter() {
|
||||
WindowState::with(window, |state| {
|
||||
window.with_state(|state| {
|
||||
tracing::debug!("win state is {:?}", state.resize_state);
|
||||
});
|
||||
if WindowState::with(window, |state| {
|
||||
!matches!(state.resize_state, WindowResizeState::Idle)
|
||||
}) {
|
||||
if window.with_state(|state| !matches!(state.resize_state, WindowResizeState::Idle))
|
||||
{
|
||||
tracing::debug!("some windows not idle");
|
||||
data.state.loop_handle.insert_idle(|data| {
|
||||
data.state.schedule_on_commit(windows, on_commit);
|
||||
|
@ -784,3 +787,36 @@ impl ApiState {
|
|||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait WithState {
|
||||
type State: Default;
|
||||
fn with_state<F, T>(&self, func: F) -> T
|
||||
where
|
||||
F: FnMut(&mut Self::State) -> T;
|
||||
}
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct WlSurfaceState {
|
||||
pub resize_state: ResizeSurfaceState,
|
||||
}
|
||||
|
||||
impl WithState for WlSurface {
|
||||
type State = WlSurfaceState;
|
||||
|
||||
fn with_state<F, T>(&self, mut func: F) -> T
|
||||
where
|
||||
F: FnMut(&mut Self::State) -> T,
|
||||
{
|
||||
compositor::with_states(self, |states| {
|
||||
states
|
||||
.data_map
|
||||
.insert_if_missing(RefCell::<Self::State>::default);
|
||||
let state = states
|
||||
.data_map
|
||||
.get::<RefCell<Self::State>>()
|
||||
.expect("This should never happen");
|
||||
|
||||
func(&mut state.borrow_mut())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,43 +4,20 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
use smithay::{
|
||||
desktop::Window,
|
||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
wayland::{compositor, seat::WaylandFocus},
|
||||
desktop::Window, reexports::wayland_server::protocol::wl_surface::WlSurface,
|
||||
wayland::seat::WaylandFocus,
|
||||
};
|
||||
|
||||
use crate::{backend::Backend, output::OutputState, state::State};
|
||||
use crate::{
|
||||
backend::Backend,
|
||||
state::{State, WithState},
|
||||
};
|
||||
|
||||
use self::window_state::{Float, WindowId, WindowState};
|
||||
use self::window_state::{Float, WindowId};
|
||||
|
||||
pub mod window_state;
|
||||
|
||||
// TODO: maybe get rid of this and move the fn into resize_surface state because it's the only user
|
||||
pub trait SurfaceState: Default + 'static {
|
||||
/// Access the [`SurfaceState`] associated with a [`WlSurface`].
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic if you use it within itself due to the use of a [`RefCell`].
|
||||
fn with_state<F, T>(wl_surface: &WlSurface, function: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut Self) -> T,
|
||||
{
|
||||
compositor::with_states(wl_surface, |states| {
|
||||
states.data_map.insert_if_missing(RefCell::<Self>::default);
|
||||
let state = states
|
||||
.data_map
|
||||
.get::<RefCell<Self>>()
|
||||
.expect("This should never happen");
|
||||
|
||||
function(&mut state.borrow_mut())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Backend> State<B> {
|
||||
/// Returns the [Window] associated with a given [WlSurface].
|
||||
pub fn window_for_surface(&self, surface: &WlSurface) -> Option<Window> {
|
||||
|
@ -59,7 +36,7 @@ impl<B: Backend> State<B> {
|
|||
|
||||
/// Toggle a window's floating status.
|
||||
pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &Window) {
|
||||
WindowState::with(window, |window_state| {
|
||||
window.with_state(|window_state| {
|
||||
match window_state.floating {
|
||||
Float::Tiled(prev_loc_and_size) => {
|
||||
if let Some((prev_loc, prev_size)) = prev_loc_and_size {
|
||||
|
@ -88,13 +65,13 @@ pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &Window) {
|
|||
state.re_layout();
|
||||
|
||||
let output = state.focus_state.focused_output.as_ref().unwrap();
|
||||
let render = OutputState::with(output, |op_state| {
|
||||
let render = output.with_state(|op_state| {
|
||||
state
|
||||
.windows
|
||||
.iter()
|
||||
.cloned()
|
||||
.filter(|win| {
|
||||
WindowState::with(win, |win_state| {
|
||||
win.with_state(|win_state| {
|
||||
if win_state.floating.is_floating() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use smithay::{
|
|||
utils::{Logical, Point, Serial, Size},
|
||||
};
|
||||
|
||||
use crate::tag::TagId;
|
||||
use crate::{state::WithState, tag::TagId};
|
||||
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct WindowId(u32);
|
||||
|
@ -37,15 +37,6 @@ pub struct WindowState {
|
|||
pub resize_state: WindowResizeState,
|
||||
/// What tags the window is currently on.
|
||||
pub tags: Vec<TagId>,
|
||||
|
||||
// FIXME: this is a bandaid to get floating working again, figure out an actual solution
|
||||
pub needs_raise: CommitState,
|
||||
}
|
||||
|
||||
pub enum CommitState {
|
||||
Idle,
|
||||
RequestReceived(Serial),
|
||||
Acked,
|
||||
}
|
||||
|
||||
/// The state of a window's resize operation.
|
||||
|
@ -116,20 +107,23 @@ impl WindowState {
|
|||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Access a [Window]'s state, optionally returning something.
|
||||
pub fn with<F, T>(window: &Window, mut func: F) -> T
|
||||
impl WithState for Window {
|
||||
type State = WindowState;
|
||||
|
||||
fn with_state<F, T>(&self, mut func: F) -> T
|
||||
where
|
||||
F: FnMut(&mut Self) -> T,
|
||||
F: FnMut(&mut Self::State) -> T,
|
||||
{
|
||||
window
|
||||
.user_data()
|
||||
.insert_if_missing(RefCell::<Self>::default);
|
||||
self.user_data()
|
||||
.insert_if_missing(RefCell::<Self::State>::default);
|
||||
|
||||
let state = window
|
||||
let state = self
|
||||
.user_data()
|
||||
.get::<RefCell<Self>>()
|
||||
.expect("This should never happen");
|
||||
.get::<RefCell<Self::State>>()
|
||||
.expect("RefCell not in data map");
|
||||
|
||||
func(&mut state.borrow_mut())
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +136,6 @@ impl Default for WindowState {
|
|||
floating: Float::Tiled(None),
|
||||
resize_state: WindowResizeState::Idle,
|
||||
tags: vec![],
|
||||
needs_raise: CommitState::Idle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue