Change all *State.with(thing, ...) to thing.with_state(...)

This commit is contained in:
Ottatop 2023-07-10 17:14:37 -05:00 committed by Ottatop
parent ac6130408b
commit 930925a8f1
8 changed files with 263 additions and 253 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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();

View file

@ -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(),
}
}
}

View file

@ -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())
}
}

View file

@ -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(&current_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(&current_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())
})
}
}

View file

@ -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;
}

View file

@ -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,
}
}
}