tiling: Add proper output_enter/leave events

This commit is contained in:
Victoria Brekenfeld 2022-11-14 11:54:22 +01:00
parent 77858d3628
commit 7e45e51781
3 changed files with 90 additions and 60 deletions

View file

@ -291,6 +291,7 @@ impl TilingLayout {
focus_stack: impl Iterator<Item = &'a CosmicMapped> + 'a,
) {
let output = seat.active_output();
window.output_enter(&output, window.bbox());
self.map_internal(window, &output, Some(focus_stack));
self.refresh();
}
@ -345,17 +346,27 @@ impl TilingLayout {
*window.tiling_node_id.lock().unwrap() = Some(window_id);
}
pub fn unmap(&mut self, window: &CosmicMapped) -> bool {
if self.unmap_window_internal(window) {
window.set_tiled(false);
self.refresh();
true
} else {
false
}
pub fn unmap(&mut self, window: &CosmicMapped) -> Option<Output> {
let output = {
let node_id = window.tiling_node_id.lock().unwrap().clone()?;
self.trees
.iter()
.find(|(_, tree)| {
tree.get(&node_id)
.map(|node| node.data().is_mapped(Some(window)))
.unwrap_or(false)
})
.map(|(o, _)| o.output.clone())?
};
self.unmap_window_internal(window);
window.output_leave(&output);
window.set_tiled(false);
self.refresh();
Some(output)
}
fn unmap_window_internal(&mut self, mapped: &CosmicMapped) -> bool {
fn unmap_window_internal(&mut self, mapped: &CosmicMapped) {
if let Some(node_id) = mapped.tiling_node_id.lock().unwrap().as_ref() {
if let Some(tree) = self.trees.values_mut().find(|tree| {
tree.get(node_id)
@ -415,11 +426,8 @@ impl TilingLayout {
}
None => {} // root
}
return true;
}
}
false
}
pub fn output_for_element(&self, elem: &CosmicMapped) -> Option<&Output> {

View file

@ -1006,58 +1006,55 @@ impl Shell {
let from_workspace = state.common.shell.workspaces.active_mut(from_output);
let maybe_window = from_workspace.focus_stack.get(seat).last().cloned();
if let Some(mapped) = maybe_window {
let was_floating = from_workspace.floating_layer.unmap(&mapped);
let was_tiling = from_workspace.tiling_layer.unmap(&mapped);
assert!(was_floating != was_tiling);
let Some(mapped) = maybe_window else { return; };
let Some(window_state) = from_workspace.unmap(&mapped) else { return; };
for (toplevel, _) in mapped.windows() {
state
.common
.shell
.toplevel_info_state
.toplevel_leave_workspace(&toplevel, &from_workspace.handle);
}
let elements = from_workspace.mapped().cloned().collect::<Vec<_>>();
std::mem::drop(from_workspace);
for mapped in elements.into_iter() {
state.common.shell.update_reactive_popups(&mapped);
}
let to_workspace = state
for (toplevel, _) in mapped.windows() {
state
.common
.shell
.workspaces
.get_mut(to_idx, to_output)
.unwrap(); // checked above
let focus_stack = to_workspace.focus_stack.get(&seat);
if was_floating {
to_workspace.floating_layer.map(mapped.clone(), &seat, None);
} else {
to_workspace
.tiling_layer
.map(mapped.clone(), &seat, focus_stack.iter());
}
for (toplevel, _) in mapped.windows() {
state
.common
.shell
.toplevel_info_state
.toplevel_enter_workspace(&toplevel, &to_workspace.handle);
}
for mapped in to_workspace
.mapped()
.cloned()
.collect::<Vec<_>>()
.into_iter()
{
state.common.shell.update_reactive_popups(&mapped);
}
state.common.shell.activate(to_output, to_idx);
Common::set_focus(state, Some(&KeyboardFocusTarget::from(mapped)), &seat, None);
.toplevel_info_state
.toplevel_leave_workspace(&toplevel, &from_workspace.handle);
}
let elements = from_workspace.mapped().cloned().collect::<Vec<_>>();
std::mem::drop(from_workspace);
for mapped in elements.into_iter() {
state.common.shell.update_reactive_popups(&mapped);
}
let to_workspace = state
.common
.shell
.workspaces
.get_mut(to_idx, to_output)
.unwrap(); // checked above
let focus_stack = to_workspace.focus_stack.get(&seat);
if window_state == ManagedState::Floating {
to_workspace.floating_layer.map(mapped.clone(), &seat, None);
} else {
to_workspace
.tiling_layer
.map(mapped.clone(), &seat, focus_stack.iter());
}
for (toplevel, _) in mapped.windows() {
state
.common
.shell
.toplevel_info_state
.toplevel_enter_workspace(&toplevel, &to_workspace.handle);
}
for mapped in to_workspace
.mapped()
.cloned()
.collect::<Vec<_>>()
.into_iter()
{
state.common.shell.update_reactive_popups(&mapped);
}
state.common.shell.activate(to_output, to_idx);
Common::set_focus(state, Some(&KeyboardFocusTarget::from(mapped)), &seat, None);
}
pub fn update_reactive_popups(&self, mapped: &CosmicMapped) {

View file

@ -55,6 +55,12 @@ pub struct Workspace {
#[derive(Debug, Default)]
pub struct FocusStacks(HashMap<Seat<State>, IndexSet<CosmicMapped>>);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ManagedState {
Tiling,
Floating,
}
impl Workspace {
pub fn new(handle: WorkspaceHandle) -> Workspace {
Workspace {
@ -100,6 +106,25 @@ impl Workspace {
self.refresh();
}
pub fn unmap(&mut self, mapped: &CosmicMapped) -> Option<ManagedState> {
let was_floating = self.floating_layer.unmap(&mapped);
let was_tiling = self.tiling_layer.unmap(&mapped).is_some();
if was_floating || was_tiling {
assert!(was_floating != was_tiling);
}
self.focus_stack
.0
.values_mut()
.for_each(|set| set.retain(|m| m != mapped));
if was_floating {
Some(ManagedState::Floating)
} else if was_tiling {
Some(ManagedState::Tiling)
} else {
None
}
}
pub fn element_for_surface(&self, surface: &WlSurface) -> Option<&CosmicMapped> {
self.floating_layer
.mapped()