tiling: Add proper output_enter/leave events
This commit is contained in:
parent
77858d3628
commit
7e45e51781
3 changed files with 90 additions and 60 deletions
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue