Rework window tracking

This commit is contained in:
Seaotatop 2023-07-09 17:48:46 -05:00 committed by Ottatop
parent c85ada88e8
commit ba69b21c52
9 changed files with 227 additions and 343 deletions

View file

@ -7,10 +7,7 @@
// The MessagePack format for these is a one-element map where the element's key is the enum name and its
// value is a map of the enum's values
use crate::{
tag::TagId,
window::{window_state::WindowId, WindowProperties},
};
use crate::window::{window_state::WindowId, WindowProperties};
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Copy)]
pub struct CallbackId(pub u32);
@ -42,25 +39,26 @@ pub enum Msg {
},
MoveWindowToTag {
window_id: WindowId,
tag_id: TagId,
tag_id: String,
},
ToggleTagOnWindow {
window_id: WindowId,
tag_id: TagId,
tag_id: String,
},
// Tag management
ToggleTag {
tag_id: TagId,
tag_id: String,
},
SwitchToTag {
tag_id: TagId,
tag_id: String,
},
AddTags {
tags: Vec<TagId>,
tags: Vec<String>,
},
RemoveTags {
tags: Vec<TagId>,
// TODO:
tags: Vec<String>,
},
// Process management

View file

@ -21,8 +21,6 @@ use smithay::{
use crate::{
backend::Backend,
layout::{Layout, LayoutVec},
output::OutputState,
state::State,
window::window_state::{WindowResizeState, WindowState},
};
@ -93,25 +91,7 @@ impl<B: Backend> PointerGrab<State<B>> for MoveSurfaceGrab<State<B>> {
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);
}
})
data.swap_window_positions(&self.window, &window_under);
}
} else {
let delta = event.location - self.start_data.location;

View file

@ -50,7 +50,7 @@ use crate::{
layout::{Layout, LayoutVec},
output::OutputState,
state::{ClientState, State},
window::window_state::{WindowResizeState, WindowState},
window::window_state::{CommitState, WindowResizeState, WindowState},
};
impl<B: Backend> BufferHandler for State<B> {
@ -122,6 +122,17 @@ impl<B: Backend> CompositorHandler for State<B> {
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;
}
});
}
}
@ -226,28 +237,31 @@ impl<B: Backend> XdgShellHandler for State<B> {
let window = Window::new(surface);
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.tags.iter().cloned().collect();
state.tags = match (
&self.focus_state.focused_output,
self.space.outputs().next(),
) {
(Some(output), _) | (None, Some(output)) => OutputState::with(output, |state| {
let output_tags = state
.focused_tags()
.map(|tag| tag.id.clone())
.collect::<Vec<_>>();
if !output_tags.is_empty() {
output_tags
} else if let Some(first_tag) = self.tag_state.tags.first() {
} else if let Some(first_tag) = state.tags.first() {
vec![first_tag.id.clone()]
} else {
vec![]
}
}) // TODO: repetition
} else if let Some(first_tag) = self.tag_state.tags.first() {
vec![first_tag.id.clone()]
} else {
vec![]
}),
(None, None) => vec![],
};
tracing::debug!("new window, tags are {:?}", state.tags);
});
self.windows.push(window.clone());
// self.space.map_element(window.clone(), (0, 0), true);
let clone = window.clone();
self.loop_handle.insert_idle(move |data| {
data.state
.seat
@ -255,7 +269,7 @@ impl<B: Backend> XdgShellHandler for State<B> {
.expect("Seat had no keyboard") // FIXME: actually handle error
.set_focus(
&mut data.state,
Some(clone.toplevel().wl_surface().clone()),
Some(window.toplevel().wl_surface().clone()),
SERIAL_COUNTER.next_serial(),
);
});
@ -263,26 +277,10 @@ 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| {
let window = window.clone();
let mut tags = data
.state
.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.add(&data.state.space, focused_output, window);
}
for tag in data.state.tag_state.tags.iter() {
tracing::debug!("tag {:?}, {}", tag.id, tag.windows.len());
}
data.state
.windows
.to_master_stack(state.focused_tags().map(|tag| tag.id.clone()).collect())
.layout(&data.state.space, focused_output);
});
}
});
@ -290,44 +288,15 @@ impl<B: Backend> XdgShellHandler for State<B> {
fn toplevel_destroyed(&mut self, surface: ToplevelSurface) {
tracing::debug!("toplevel destroyed");
let window = self
.windows
.iter()
.find(|&win| win.toplevel() == &surface)
.unwrap();
self.windows.retain(|window| window.toplevel() != &surface);
if let Some(focused_output) = self.focus_state.focused_output.as_ref() {
OutputState::with(focused_output, |state| {
let mut tags = self
.tag_state
.tags
.iter_mut()
.filter(|tg| state.tags.contains(&tg.id));
if let Some(first) = tags.next() {
tracing::debug!("first tag: {:?}", first.id);
let mut layout = first.windows.as_master_stack();
for tg in tags {
tracing::debug!("tag: {:?}", tg.id);
layout = layout.chain_with(&mut tg.windows);
}
// This will only remove the window from focused tags...
layout.remove(&self.space, focused_output, window);
}
// ...so here we remove the window from any tag that isn't focused
for tag in self.tag_state.tags.iter_mut() {
tag.windows.retain(|el| el != window);
}
self.windows
.to_master_stack(state.focused_tags().map(|tag| tag.id.clone()).collect())
.layout(&self.space, focused_output);
});
}
for tag in self.tag_state.tags.iter() {
tracing::debug!("tag {:?}, {}", tag.id, tag.windows.len());
}
self.windows.retain(|window| window.toplevel() != &surface);
// let mut windows: Vec<Window> = self.space.elements().cloned().collect();
// windows.retain(|window| window.toplevel() != &surface);
// Layouts::master_stack(self, windows, crate::layout::Direction::Left);
@ -443,6 +412,9 @@ 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

View file

@ -4,15 +4,18 @@
//
// SPDX-License-Identifier: MPL-2.0
use itertools::Itertools;
use smithay::{
desktop::{space::SpaceElement, Space, Window},
output::Output,
utils::{Logical, Size},
wayland::{compositor, shell::xdg::XdgToplevelSurfaceData},
};
use crate::window::window_state::{WindowResizeState, WindowState};
use crate::{
backend::Backend,
state::State,
tag::TagId,
window::window_state::{WindowResizeState, WindowState},
};
pub enum Direction {
Left,
@ -21,41 +24,26 @@ pub enum Direction {
Bottom,
}
pub struct MasterStack<'a, S: SpaceElement> {
inner: Vec<&'a mut Vec<S>>,
pub struct MasterStack<S: SpaceElement> {
inner: Vec<S>,
}
pub trait Layout<'a, S: SpaceElement> {
/// Add a [`SpaceElement`] to this layout and update positions.
fn add(&mut self, space: &Space<S>, output: &Output, elem: S);
/// Remove a [`SpaceElement`] from this layout and update positions.
fn remove(&mut self, space: &Space<S>, output: &Output, elem: &S);
// TODO: return result
/// Swap two elements in this layout and update their positions.
fn swap(&mut self, space: &Space<S>, elem1: &S, elem2: &S);
/// Perform a full layout with all elements. Use this when you are switching from another layout.
fn layout(&self, space: &Space<S>, output: &Output);
fn chain_with(self, vec: &'a mut Vec<S>) -> Self;
}
impl MasterStack<'_, Window> {
impl MasterStack<Window> {
pub fn master(&self) -> Option<&Window> {
self.inner.iter().flat_map(|vec| vec.iter()).next()
self.inner.first()
}
pub fn stack(&self) -> impl Iterator<Item = &Window> {
self.inner
.iter()
.flat_map(|vec| vec.iter())
.unique()
.skip(1)
self.inner.iter().skip(1)
}
}
impl MasterStack<'_, Window> {
impl MasterStack<Window> {
fn layout_stack(&self, space: &Space<Window>, output: &Output) {
let stack_count = self.stack().count();
@ -81,113 +69,36 @@ impl MasterStack<'_, Window> {
}
}
pub fn swap_window_positions(space: &Space<Window>, win1: &Window, win2: &Window) {
// FIXME: moving the mouse quickly will break swapping
impl<B: Backend> State<B> {
pub fn swap_window_positions(&mut self, win1: &Window, win2: &Window) {
// FIXME: moving the mouse quickly will break swapping
let win1_loc = space.element_location(win1).unwrap(); // TODO: handle unwraps
let win2_loc = space.element_location(win2).unwrap();
let win1_geo = win1.geometry();
let win2_geo = win2.geometry();
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();
win1.toplevel().with_pending_state(|state| {
state.size = Some(win2_geo.size);
});
win2.toplevel().with_pending_state(|state| {
state.size = Some(win1_geo.size);
});
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(win1, |state| {
state.resize_state = WindowResizeState::WaitingForAck(serial, win2_loc);
});
let serial = win1.toplevel().send_configure();
WindowState::with(win1, |state| {
state.resize_state = WindowResizeState::WaitingForAck(serial, win2_loc);
});
let serial = win2.toplevel().send_configure();
WindowState::with(win2, |state| {
state.resize_state = WindowResizeState::WaitingForAck(serial, win1_loc);
});
}
impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
fn add(&mut self, space: &Space<Window>, output: &Output, elem: Window) {
for vec in self.inner.iter_mut() {
vec.push(elem.clone());
}
if self.stack().count() == 0 {
let Some(master) = self.master() else { unreachable!() };
let Some(output_geo) = space.output_geometry(output) else {
tracing::error!("could not get output geometry");
return;
};
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 if self.stack().count() == 1 {
let Some(master) = self.master() else { unreachable!() };
let Some(output_geo) = space.output_geometry(output) else {
tracing::error!("could not get output geometry");
return;
};
master.toplevel().with_pending_state(|state| {
state.size = Some((output_geo.size.w / 2, output_geo.size.h).into());
});
WindowState::with(master, |state| {
state.resize_state = WindowResizeState::WaitingForAck(
master.toplevel().send_configure(),
(0, 0).into(),
);
});
self.layout_stack(space, output);
} else {
self.layout_stack(space, output);
}
}
fn remove(&mut self, space: &Space<Window>, output: &Output, elem: &Window) {
for vec in self.inner.iter_mut() {
vec.retain(|el| el != elem);
}
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 {
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 {
self.layout_stack(space, output);
}
}
fn swap(&mut self, space: &Space<Window>, elem1: &Window, elem2: &Window) {
tracing::debug!("top of swap");
let serial = win2.toplevel().send_configure();
WindowState::with(win2, |state| {
state.resize_state = WindowResizeState::WaitingForAck(serial, win1_loc);
});
let mut elems = self
.inner
.windows
.iter_mut()
.flat_map(|vec| vec.iter_mut())
.filter(|elem| *elem == elem1 || *elem == elem2)
.unique_by(|win| WindowState::with(win, |state| state.id));
.filter(|win| *win == win1 || *win == win2);
let (first, second) = (elems.next(), elems.next());
@ -196,33 +107,10 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
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);
}
}
impl<'a> Layout<'a, Window> for MasterStack<Window> {
fn layout(&self, space: &Space<Window>, output: &Output) {
let Some(master) = self.master() else {
return;
@ -232,27 +120,6 @@ 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
@ -282,22 +149,33 @@ impl<'a> Layout<'a, Window> for MasterStack<'a, Window> {
self.layout_stack(space, output);
}
}
/// Chain another tag's windows to this one to be layed out.
fn chain_with(mut self, vec: &'a mut Vec<Window>) -> Self {
self.inner.push(vec);
self
}
}
pub trait LayoutVec<S: SpaceElement> {
/// Interpret this vec as a master-stack layout.
fn as_master_stack(&mut self) -> MasterStack<S>;
fn to_master_stack(&self, tags: Vec<TagId>) -> MasterStack<S>;
// fn as_binary_tree(&mut self); TODO:
}
impl<S: SpaceElement> LayoutVec<S> for Vec<S> {
fn as_master_stack(&mut self) -> MasterStack<S> {
MasterStack { inner: vec![self] }
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

@ -4,15 +4,21 @@
//
// SPDX-License-Identifier: MPL-2.0
use std::{cell::RefCell, collections::HashSet};
use std::cell::RefCell;
use smithay::output::Output;
use crate::tag::TagId;
use crate::tag::Tag;
#[derive(Default)]
pub struct OutputState {
pub tags: HashSet<TagId>,
pub tags: Vec<Tag>,
}
impl OutputState {
pub fn focused_tags(&mut self) -> impl Iterator<Item = &mut Tag> {
self.tags.iter_mut().filter(|tag| tag.active)
}
}
impl OutputState {
@ -24,10 +30,10 @@ impl OutputState {
.user_data()
.insert_if_missing(RefCell::<Self>::default);
let state = output
let mut state = output
.user_data()
.get::<RefCell<Self>>()
.expect("RefCell doesn't exist in data map (This should NEVER happen. If you see this, something oofed big-time.)");
.expect("RefCell not in data map");
func(&mut state.borrow_mut())
}

View file

@ -21,7 +21,7 @@ use crate::{
focus::FocusState,
layout::{Layout, LayoutVec},
output::OutputState,
tag::{Tag, TagState},
tag::Tag,
window::{window_state::WindowState, WindowProperties},
};
use calloop::futures::Scheduler;
@ -88,7 +88,6 @@ pub struct State<B: Backend> {
pub input_state: InputState,
pub api_state: ApiState,
pub focus_state: FocusState,
pub tag_state: TagState,
pub popup_manager: PopupManager,
@ -152,7 +151,15 @@ impl<B: Backend> State<B> {
.find(|&win| WindowState::with(win, |state| state.id == window_id))
{
WindowState::with(window, |state| {
state.tags = vec![tag_id.clone()];
OutputState::with(
&self.focus_state.focused_output.as_ref().unwrap(),
|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()];
}
},
);
});
}
@ -165,11 +172,19 @@ impl<B: Backend> State<B> {
.find(|&win| WindowState::with(win, |state| state.id == window_id))
{
WindowState::with(window, |state| {
if state.tags.contains(&tag_id) {
state.tags.retain(|id| id != &tag_id);
} else {
state.tags.push(tag_id.clone());
}
OutputState::with(
&self.focus_state.focused_output.as_ref().unwrap(),
|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) {
state.tags.retain(|id| id != &tag.id);
} else {
state.tags.push(tag.id.clone());
}
}
},
);
});
self.re_layout();
@ -179,13 +194,8 @@ impl<B: Backend> State<B> {
OutputState::with(
self.focus_state.focused_output.as_ref().unwrap(), // TODO: handle error
|state| {
let should_remove = state.tags.get(&tag_id).is_some();
if should_remove {
state.tags.remove(&tag_id);
tracing::debug!("toggled tag {tag_id:?} off");
} else {
state.tags.insert(tag_id.clone());
tracing::debug!("toggled tag {tag_id:?} on");
if let Some(tag) = state.tags.iter_mut().find(|tag| tag.name == tag_id) {
tag.active = !tag.active;
}
},
);
@ -194,13 +204,33 @@ impl<B: Backend> State<B> {
}
Msg::SwitchToTag { tag_id } => {
OutputState::with(self.focus_state.focused_output.as_ref().unwrap(), |state| {
state.tags.clear();
state.tags.insert(tag_id.clone());
tracing::debug!("focused tags: {:?}", state.tags);
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 {
unreachable!()
};
tag.active = true;
tracing::debug!(
"focused tags: {:?}",
state
.tags
.iter()
.filter(|tag| tag.active)
.map(|tag| &tag.name)
.collect::<Vec<_>>()
);
});
self.re_layout();
}
// TODO: add output
Msg::AddTags { tags } => {
if let Some(output) = self
.focus_state
@ -208,15 +238,21 @@ impl<B: Backend> State<B> {
.as_ref()
.or_else(|| self.space.outputs().next())
{
self.tag_state.tags.extend(tags.into_iter().map(|tag| Tag {
id: tag,
windows: vec![],
output: output.clone(),
}));
OutputState::with(output, |state| {
state.tags.extend(
tags.clone()
.into_iter()
.map(|name| Tag::new(name, output.clone())),
);
});
}
}
Msg::RemoveTags { tags } => {
self.tag_state.tags.retain(|tag| !tags.contains(&tag.id));
for output in self.space.outputs() {
OutputState::with(output, |state| {
state.tags.retain(|tag| !tags.contains(&tag.name));
});
}
}
Msg::Quit => {
@ -475,8 +511,11 @@ impl<B: Backend> State<B> {
OutputState::with(output, |state| {
for window in self.space.elements().cloned().collect::<Vec<_>>() {
let should_render = WindowState::with(&window, |win_state| {
if win_state.floating.is_floating() {
return true;
}
for tag_id in win_state.tags.iter() {
if state.tags.get(tag_id).is_some() {
if state.focused_tags().any(|tag| &tag.id == tag_id) {
return true;
}
}
@ -487,21 +526,9 @@ impl<B: Backend> State<B> {
}
}
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);
}
layout.layout(&self.space, output);
}
self.windows
.to_master_stack(state.focused_tags().map(|tag| tag.id.clone()).collect())
.layout(&self.space, output);
});
}
}
@ -644,7 +671,6 @@ impl<B: Backend> State<B> {
input_state: InputState::new(),
api_state: ApiState::new(),
focus_state: FocusState::new(),
tag_state: TagState::new(),
seat,

View file

@ -4,26 +4,44 @@
//
// SPDX-License-Identifier: MPL-2.0
use smithay::{desktop::Window, output::Output};
use std::{
hash::Hash,
sync::atomic::{AtomicU32, Ordering},
};
use smithay::output::Output;
static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
#[derive(Debug, Hash, PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
pub struct TagId(String);
pub struct TagId(u32);
impl TagId {
fn next() -> Self {
Self(TAG_ID_COUNTER.fetch_add(1, Ordering::Relaxed))
}
}
#[derive(Debug)]
pub struct Tag {
/// The internal id of this tag.
pub id: TagId,
pub windows: Vec<Window>,
/// The name of this tag.
pub name: String,
/// The output that this tag should be on.
pub output: Output,
/// Whether this tag is active or not.
pub active: bool,
// TODO: layout
}
#[derive(Debug, Default)]
pub struct TagState {
pub tags: Vec<Tag>,
}
impl TagState {
pub fn new() -> Self {
Default::default()
impl Tag {
pub fn new(name: String, output: Output) -> Self {
Self {
id: TagId::next(),
name,
output,
active: false,
}
}
}

View file

@ -14,7 +14,7 @@ use smithay::{
use crate::{backend::Backend, state::State};
use self::window_state::{Float, WindowId, WindowState};
use self::window_state::{CommitState, Float, WindowId, WindowState};
pub mod window_state;
@ -86,7 +86,12 @@ pub fn toggle_floating<B: Backend>(state: &mut State<B>, window: &Window) {
});
state.re_layout();
state.space.raise_element(window, true);
// FIXME: every window gets mapped after this raise in `commit`, making this useless
WindowState::with(window, |state| {
state.needs_raise = CommitState::RequestReceived(window.toplevel().send_configure());
});
// state.space.raise_element(window, true);
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]

View file

@ -14,7 +14,7 @@ use smithay::{
utils::{Logical, Point, Serial, Size},
};
use crate::tag::{Tag, TagId, TagState};
use crate::tag::TagId;
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct WindowId(u32);
@ -37,15 +37,15 @@ 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,
}
/// Returns a vec of references to all the tags the window is on.
pub fn tags<'a>(tag_state: &'a TagState, window: &Window) -> Vec<&'a Tag> {
tag_state
.tags
.iter()
.filter(|&tag| WindowState::with(window, |state| state.tags.contains(&tag.id)))
.collect()
pub enum CommitState {
Idle,
RequestReceived(Serial),
Acked,
}
/// The state of a window's resize operation.
@ -142,6 +142,7 @@ impl Default for WindowState {
floating: Float::Tiled(None),
resize_state: WindowResizeState::Idle,
tags: vec![],
needs_raise: CommitState::Idle,
}
}
}