shell: handle fullscreen windows on a dedicated layer
I hoped to split this up into multiple commits, but the api
changes to `shell/workspace.rs` were to invasive to feasibly do this.
Here is a rough list of changes:
- Fullscreen windows aren't mapped to other layers anymore
- This they need their own logic for:
- Sending frames
- Dmabuf Feedback
- Primary outputs
- On commit handlers
- cursor tests
- They get their own unmap/remap logic
- They get a new restore state similar to minimized windows
- Refactored the minimized window state to reuse as much as possible
here
- They need to be part of focus stacks, which means adjusting them
to a new type `FocusTarget` as they previously only handled
`CosmicMapped`.
- Various shell handlers (minimize, move, menu) now have dedicated
logic for fullscreen surfaces
- This was partially necessary due to relying on CosmicSurface now,
partially because they should've had their own logic from the
start. E.g. the context menu is now reflecting the fullscreen
state
- Fullscreen windows may be rendered behind other windows now, when they
loose focus.
- This needed changes to input handling / rendering
This commit is contained in:
parent
8ef6c161a0
commit
adedb705e7
23 changed files with 2554 additions and 1796 deletions
|
|
@ -6,10 +6,11 @@ use smithay::{
|
|||
output::Output,
|
||||
reexports::wayland_server::DisplayHandle,
|
||||
utils::{Point, Rectangle, Size, SERIAL_COUNTER},
|
||||
wayland::seat::WaylandFocus,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
shell::{element::CosmicWindow, CosmicSurface, Shell, WorkspaceDelta},
|
||||
shell::{focus::target::KeyboardFocusTarget, CosmicSurface, Shell, WorkspaceDelta},
|
||||
utils::prelude::*,
|
||||
wayland::protocols::{
|
||||
toplevel_info::ToplevelInfoHandler,
|
||||
|
|
@ -41,17 +42,13 @@ impl ToplevelManagementHandler for State {
|
|||
.spaces_for_output(output)
|
||||
.enumerate()
|
||||
.find(|(_, w)| {
|
||||
w.mapped()
|
||||
.flat_map(|m| m.windows().map(|(s, _)| s))
|
||||
.any(|w| &w == window)
|
||||
w.get_fullscreen().is_some_and(|f| f == window)
|
||||
|| w.mapped()
|
||||
.flat_map(|m| m.windows().map(|(s, _)| s))
|
||||
.any(|w| &w == window)
|
||||
});
|
||||
if let Some((idx, workspace)) = maybe {
|
||||
let seat = seat.unwrap_or(shell.seats.last_active().clone());
|
||||
let mapped = workspace
|
||||
.mapped()
|
||||
.find(|m| m.windows().any(|(w, _)| &w == window))
|
||||
.unwrap()
|
||||
.clone();
|
||||
|
||||
let handle = workspace.handle;
|
||||
let res = shell.activate(
|
||||
|
|
@ -62,8 +59,12 @@ impl ToplevelManagementHandler for State {
|
|||
);
|
||||
|
||||
let workspace = shell.workspaces.space_for_handle_mut(&handle).unwrap();
|
||||
if seat.get_keyboard().unwrap().current_focus() != Some(mapped.clone().into())
|
||||
&& workspace.is_tiled(&mapped)
|
||||
if seat
|
||||
.get_keyboard()
|
||||
.unwrap()
|
||||
.current_focus()
|
||||
.is_some_and(|focus| !focus.windows().any(|w| w == *window))
|
||||
&& workspace.is_tiled(window)
|
||||
{
|
||||
for mapped in workspace
|
||||
.mapped()
|
||||
|
|
@ -75,6 +76,13 @@ impl ToplevelManagementHandler for State {
|
|||
workspace.unmaximize_request(&mapped);
|
||||
}
|
||||
}
|
||||
|
||||
let target = if let Some(mapped) = workspace.element_for_surface(window) {
|
||||
mapped.focus_window(window);
|
||||
KeyboardFocusTarget::Element(mapped.clone())
|
||||
} else {
|
||||
KeyboardFocusTarget::Fullscreen(window.clone())
|
||||
};
|
||||
std::mem::drop(shell);
|
||||
|
||||
if seat.active_output() != *output {
|
||||
|
|
@ -102,8 +110,7 @@ impl ToplevelManagementHandler for State {
|
|||
}
|
||||
}
|
||||
|
||||
mapped.focus_window(window);
|
||||
Shell::set_focus(self, Some(&mapped.clone().into()), &seat, None, false);
|
||||
Shell::set_focus(self, Some(&target), &seat, None, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -121,44 +128,27 @@ impl ToplevelManagementHandler for State {
|
|||
_output: Output,
|
||||
) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mut mapped) = shell.element_for_surface(window).cloned() {
|
||||
if let Some(from_workspace) = shell.space_for_mut(&mapped) {
|
||||
// If window is part of a stack, remove it and map it outside the stack
|
||||
if let Some(stack) = mapped.stack_ref() {
|
||||
stack.remove_window(&window);
|
||||
mapped = CosmicWindow::new(
|
||||
window.clone(),
|
||||
self.common.event_loop_handle.clone(),
|
||||
self.common.theme.clone(),
|
||||
)
|
||||
.into();
|
||||
if from_workspace.tiling_enabled {
|
||||
from_workspace.tiling_layer.map(
|
||||
mapped.clone(),
|
||||
None::<std::iter::Empty<_>>,
|
||||
None,
|
||||
);
|
||||
} else {
|
||||
from_workspace.floating_layer.map(mapped.clone(), None);
|
||||
}
|
||||
}
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let Some(surface) = window.wl_surface() else {
|
||||
return;
|
||||
};
|
||||
let Some((from_workspace, _)) = shell.workspace_for_surface(&*surface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let from_handle = from_workspace.handle;
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let res = shell.move_window(
|
||||
Some(&seat),
|
||||
&mapped,
|
||||
&from_handle,
|
||||
&to_handle,
|
||||
false,
|
||||
None,
|
||||
&mut self.common.workspace_state.update(),
|
||||
);
|
||||
if let Some((target, _)) = res {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None, true);
|
||||
}
|
||||
}
|
||||
let res = shell.move_window(
|
||||
Some(&seat),
|
||||
window,
|
||||
&from_workspace,
|
||||
&to_handle,
|
||||
false,
|
||||
None,
|
||||
&mut self.common.workspace_state.update(),
|
||||
&self.common.event_loop_handle,
|
||||
);
|
||||
if let Some((target, _)) = res {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -170,23 +160,18 @@ impl ToplevelManagementHandler for State {
|
|||
) {
|
||||
let mut shell = self.common.shell.write();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
if let Some((output, workspace)) =
|
||||
output.and_then(|output| shell.workspaces.active_mut(&output).map(|w| (output, w)))
|
||||
{
|
||||
let from = minimize_rectangle(&output, window);
|
||||
workspace.fullscreen_request(window, None, from, &seat);
|
||||
} else if let Some((output, handle)) = shell
|
||||
.space_for(&mapped)
|
||||
.map(|workspace| (workspace.output.clone(), workspace.handle.clone()))
|
||||
{
|
||||
let from = minimize_rectangle(&output, window);
|
||||
shell
|
||||
.workspaces
|
||||
.space_for_handle_mut(&handle)
|
||||
.unwrap()
|
||||
.fullscreen_request(window, None, from, &seat);
|
||||
}
|
||||
let output = output
|
||||
.or_else(|| {
|
||||
window
|
||||
.wl_surface()
|
||||
.and_then(|surface| shell.visible_output_for_surface(&*surface).cloned())
|
||||
})
|
||||
.unwrap_or_else(|| seat.focused_or_active_output());
|
||||
if let Some(target) =
|
||||
shell.fullscreen_request(window, output, &self.common.event_loop_handle)
|
||||
{
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,33 +181,14 @@ impl ToplevelManagementHandler for State {
|
|||
window: &<Self as ToplevelInfoHandler>::Window,
|
||||
) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
if let Some(workspace) = shell.space_for_mut(&mapped) {
|
||||
if let Some((layer, previous_workspace)) = workspace.unfullscreen_request(window) {
|
||||
let old_handle = workspace.handle.clone();
|
||||
let new_workspace_handle = shell
|
||||
.workspaces
|
||||
.space_for_handle(&previous_workspace)
|
||||
.is_some()
|
||||
.then_some(previous_workspace)
|
||||
.unwrap_or(old_handle); // if the workspace doesn't exist anymore, we can still remap on the right layer
|
||||
|
||||
shell.remap_unfullscreened_window(
|
||||
mapped,
|
||||
&old_handle,
|
||||
&new_workspace_handle,
|
||||
layer,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
shell.unfullscreen_request(window, &self.common.event_loop_handle);
|
||||
}
|
||||
|
||||
fn maximize(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.maximize_request(&mapped, &seat, true);
|
||||
shell.maximize_request(&mapped, &seat, true, &self.common.event_loop_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -235,22 +201,13 @@ impl ToplevelManagementHandler for State {
|
|||
|
||||
fn minimize(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
if !mapped.is_stack() || &mapped.active_window() == window {
|
||||
shell.minimize_request(&mapped);
|
||||
}
|
||||
}
|
||||
shell.minimize_request(window);
|
||||
}
|
||||
|
||||
fn unminimize(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mapped) = shell.element_for_surface(window).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.unminimize_request(&mapped, &seat);
|
||||
if mapped.is_stack() {
|
||||
mapped.stack_ref().unwrap().set_active(window);
|
||||
}
|
||||
}
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.unminimize_request(window, &seat, &self.common.event_loop_handle);
|
||||
}
|
||||
|
||||
fn set_sticky(&mut self, _dh: &DisplayHandle, window: &<Self as ToplevelInfoHandler>::Window) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::shell::focus::target::KeyboardFocusTarget;
|
||||
use crate::{shell::ActivationKey, state::ClientState, utils::prelude::*};
|
||||
use crate::{
|
||||
state::State,
|
||||
|
|
@ -93,8 +94,6 @@ impl XdgActivationHandler for State {
|
|||
.insert_if_missing(move || ActivationContext::Workspace(handle));
|
||||
|
||||
debug!(?token, "created workspace token");
|
||||
} else {
|
||||
debug!(?token, "created urgent-only token for invalid serial");
|
||||
}
|
||||
|
||||
valid
|
||||
|
|
@ -106,88 +105,118 @@ impl XdgActivationHandler for State {
|
|||
token_data: XdgActivationTokenData,
|
||||
surface: WlSurface,
|
||||
) {
|
||||
if let Some(context) = token_data.user_data.get::<ActivationContext>() {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(element) = shell.element_for_surface(&surface).cloned() {
|
||||
match context {
|
||||
ActivationContext::UrgentOnly => {
|
||||
if let Some((workspace, _output)) = shell.workspace_for_surface(&surface) {
|
||||
let mut workspace_guard = self.common.workspace_state.update();
|
||||
workspace_guard.add_workspace_state(&workspace, WState::Urgent);
|
||||
}
|
||||
}
|
||||
ActivationContext::Workspace(_) => {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let current_output = seat.active_output();
|
||||
let Some(context) = token_data.user_data.get::<ActivationContext>() else {
|
||||
return;
|
||||
};
|
||||
let mut shell = self.common.shell.write();
|
||||
|
||||
if element.is_minimized() {
|
||||
shell.unminimize_request(&element, &seat);
|
||||
}
|
||||
|
||||
let element_workspace = shell.space_for(&element).map(|w| w.handle.clone());
|
||||
let current_workspace = shell.active_space_mut(¤t_output).unwrap();
|
||||
|
||||
let in_current_workspace = element_workspace
|
||||
.as_ref()
|
||||
.map(|w| *w == current_workspace.handle)
|
||||
.unwrap_or(false);
|
||||
|
||||
if in_current_workspace {
|
||||
current_workspace
|
||||
.floating_layer
|
||||
.space
|
||||
.raise_element(&element, true);
|
||||
}
|
||||
|
||||
if element.is_stack() {
|
||||
if let Some((window, _)) = element.windows().find(|(window, _)| {
|
||||
let mut found = false;
|
||||
window.with_surfaces(|wl_surface, _| {
|
||||
if wl_surface == &surface {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
found
|
||||
}) {
|
||||
element.set_active(&window);
|
||||
}
|
||||
}
|
||||
|
||||
if in_current_workspace {
|
||||
if seat.get_keyboard().unwrap().current_focus()
|
||||
!= Some(element.clone().into())
|
||||
&& current_workspace.is_tiled(&element)
|
||||
{
|
||||
for mapped in current_workspace
|
||||
.mapped()
|
||||
.filter(|m| m.maximized_state.lock().unwrap().is_some())
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
{
|
||||
current_workspace.unmaximize_request(&mapped);
|
||||
}
|
||||
}
|
||||
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(
|
||||
self,
|
||||
Some(&element.clone().into()),
|
||||
&seat,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
} else if let Some(w) = element_workspace {
|
||||
shell.append_focus_stack(&element, &seat);
|
||||
let mut workspace_guard = self.common.workspace_state.update();
|
||||
workspace_guard.add_workspace_state(&w, WState::Urgent);
|
||||
}
|
||||
}
|
||||
match context {
|
||||
ActivationContext::UrgentOnly => {
|
||||
if let Some((workspace, _output)) = shell.workspace_for_surface(&surface) {
|
||||
let mut workspace_guard = self.common.workspace_state.update();
|
||||
workspace_guard.add_workspace_state(&workspace, WState::Urgent);
|
||||
}
|
||||
} else {
|
||||
shell
|
||||
.pending_activations
|
||||
.insert(ActivationKey::Wayland(surface), context.clone());
|
||||
}
|
||||
ActivationContext::Workspace(_) => {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let current_output = seat.active_output();
|
||||
|
||||
if let Some(element) = shell.element_for_surface(&surface).cloned() {
|
||||
if element.is_minimized() {
|
||||
shell.unminimize_request(&surface, &seat, &self.common.event_loop_handle);
|
||||
}
|
||||
|
||||
let element_workspace = shell.space_for(&element).map(|w| w.handle.clone());
|
||||
let current_workspace = shell.active_space_mut(¤t_output).unwrap();
|
||||
|
||||
let in_current_workspace = element_workspace
|
||||
.as_ref()
|
||||
.map(|w| *w == current_workspace.handle)
|
||||
.unwrap_or(false);
|
||||
|
||||
if in_current_workspace {
|
||||
current_workspace
|
||||
.floating_layer
|
||||
.space
|
||||
.raise_element(&element, true);
|
||||
}
|
||||
|
||||
if element.is_stack() {
|
||||
if let Some((window, _)) = element.windows().find(|(window, _)| {
|
||||
let mut found = false;
|
||||
window.with_surfaces(|wl_surface, _| {
|
||||
if wl_surface == &surface {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
found
|
||||
}) {
|
||||
element.set_active(&window);
|
||||
}
|
||||
}
|
||||
|
||||
if in_current_workspace {
|
||||
if seat.get_keyboard().unwrap().current_focus()
|
||||
!= Some(element.clone().into())
|
||||
&& current_workspace.is_tiled(&surface)
|
||||
{
|
||||
for mapped in current_workspace
|
||||
.mapped()
|
||||
.filter(|m| m.maximized_state.lock().unwrap().is_some())
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.into_iter()
|
||||
{
|
||||
current_workspace.unmaximize_request(&mapped);
|
||||
}
|
||||
}
|
||||
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(
|
||||
self,
|
||||
Some(&KeyboardFocusTarget::Element(element.clone())),
|
||||
&seat,
|
||||
None,
|
||||
false,
|
||||
);
|
||||
} else if let Some(w) = element_workspace {
|
||||
shell.append_focus_stack(element, &seat);
|
||||
let mut workspace_guard = self.common.workspace_state.update();
|
||||
workspace_guard.add_workspace_state(&w, WState::Urgent);
|
||||
}
|
||||
} else if let Some((workspace, _)) = shell.workspace_for_surface(&surface) {
|
||||
let current_workspace = shell.active_space(¤t_output).unwrap();
|
||||
if workspace == current_workspace.handle {
|
||||
let Some(target) = shell
|
||||
.workspaces
|
||||
.space_for_handle(&workspace)
|
||||
.unwrap()
|
||||
.get_fullscreen()
|
||||
.cloned()
|
||||
.map(KeyboardFocusTarget::Fullscreen)
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None, false);
|
||||
} else {
|
||||
if let Some(surface) = shell
|
||||
.workspaces
|
||||
.space_for_handle(&workspace)
|
||||
.and_then(|w| w.get_fullscreen())
|
||||
.cloned()
|
||||
{
|
||||
shell.append_focus_stack(surface, &seat)
|
||||
}
|
||||
let mut workspace_guard = self.common.workspace_state.update();
|
||||
workspace_guard.add_workspace_state(&workspace, WState::Urgent);
|
||||
}
|
||||
} else {
|
||||
shell
|
||||
.pending_activations
|
||||
.insert(ActivationKey::Wayland(surface), context.clone());
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
use crate::{
|
||||
shell::{
|
||||
element::CosmicWindow, grabs::ReleaseMode, CosmicMapped, CosmicSurface, ManagedLayer,
|
||||
PendingWindow,
|
||||
},
|
||||
shell::{grabs::ReleaseMode, CosmicSurface, PendingWindow},
|
||||
utils::prelude::*,
|
||||
wayland::protocols::toplevel_info::{toplevel_enter_output, toplevel_enter_workspace},
|
||||
};
|
||||
use smithay::{
|
||||
delegate_xdg_shell,
|
||||
|
|
@ -33,7 +29,7 @@ use smithay::{
|
|||
use std::cell::Cell;
|
||||
use tracing::warn;
|
||||
|
||||
use super::{compositor::client_compositor_state, toplevel_management::minimize_rectangle};
|
||||
use super::compositor::client_compositor_state;
|
||||
|
||||
pub mod popup;
|
||||
|
||||
|
|
@ -204,20 +200,14 @@ impl XdgShellHandler for State {
|
|||
|
||||
fn minimize_request(&mut self, surface: ToplevelSurface) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
if !mapped.is_stack()
|
||||
|| mapped.active_window().wl_surface().as_deref() == Some(surface.wl_surface())
|
||||
{
|
||||
shell.minimize_request(&mapped)
|
||||
}
|
||||
}
|
||||
shell.minimize_request(surface.wl_surface())
|
||||
}
|
||||
|
||||
fn maximize_request(&mut self, surface: ToplevelSurface) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
let seat = shell.seats.last_active().clone();
|
||||
shell.maximize_request(&mapped, &seat, true)
|
||||
shell.maximize_request(&mapped, &seat, true, &self.common.event_loop_handle)
|
||||
} else if let Some(pending) = shell
|
||||
.pending_windows
|
||||
.iter_mut()
|
||||
|
|
@ -243,153 +233,40 @@ impl XdgShellHandler for State {
|
|||
fn fullscreen_request(&mut self, surface: ToplevelSurface, output: Option<WlOutput>) {
|
||||
let mut shell = self.common.shell.write();
|
||||
let seat = shell.seats.last_active().clone();
|
||||
let Some(focused_output) = seat.focused_output() else {
|
||||
return;
|
||||
};
|
||||
let output = output
|
||||
.as_ref()
|
||||
.and_then(Output::from_resource)
|
||||
.unwrap_or_else(|| focused_output.clone());
|
||||
.or_else(|| {
|
||||
shell
|
||||
.visible_output_for_surface(surface.wl_surface())
|
||||
.cloned()
|
||||
})
|
||||
.unwrap_or_else(|| seat.focused_or_active_output());
|
||||
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
let from = minimize_rectangle(&output, &mapped.active_window());
|
||||
|
||||
if let Some(set) = shell
|
||||
.workspaces
|
||||
.sets
|
||||
.values_mut()
|
||||
.find(|set| set.sticky_layer.mapped().any(|m| m == &mapped))
|
||||
{
|
||||
let mapped = if mapped
|
||||
.stack_ref()
|
||||
.map(|stack| stack.len() > 1)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let stack = mapped.stack_ref().unwrap();
|
||||
let surface = stack
|
||||
.surfaces()
|
||||
.find(|s| s.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||
.unwrap();
|
||||
stack.remove_window(&surface);
|
||||
CosmicMapped::from(CosmicWindow::new(
|
||||
surface,
|
||||
self.common.event_loop_handle.clone(),
|
||||
self.common.theme.clone(),
|
||||
))
|
||||
} else {
|
||||
set.sticky_layer.unmap(&mapped);
|
||||
mapped
|
||||
};
|
||||
|
||||
let workspace_handle = shell.active_space(&output).unwrap().handle.clone();
|
||||
for (window, _) in mapped.windows() {
|
||||
toplevel_enter_output(&window, &output);
|
||||
toplevel_enter_workspace(&window, &workspace_handle);
|
||||
}
|
||||
|
||||
let workspace = shell.active_space_mut(&output).unwrap();
|
||||
workspace.floating_layer.map(mapped.clone(), None);
|
||||
|
||||
workspace.fullscreen_request(
|
||||
&mapped.active_window(),
|
||||
Some((ManagedLayer::Sticky, workspace_handle)),
|
||||
from,
|
||||
&seat,
|
||||
);
|
||||
} else if let Some(workspace) = shell.space_for_mut(&mapped) {
|
||||
if workspace.output != output {
|
||||
let (mapped, layer) = if mapped
|
||||
.stack_ref()
|
||||
.map(|stack| stack.len() > 1)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
let stack = mapped.stack_ref().unwrap();
|
||||
let surface = stack
|
||||
.surfaces()
|
||||
.find(|s| s.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||
.unwrap();
|
||||
stack.remove_window(&surface);
|
||||
(
|
||||
CosmicMapped::from(CosmicWindow::new(
|
||||
surface,
|
||||
self.common.event_loop_handle.clone(),
|
||||
self.common.theme.clone(),
|
||||
)),
|
||||
if workspace.is_tiled(&mapped) {
|
||||
ManagedLayer::Tiling
|
||||
} else {
|
||||
ManagedLayer::Floating
|
||||
},
|
||||
)
|
||||
} else {
|
||||
let layer = workspace.unmap(&mapped).unwrap().layer;
|
||||
(mapped, layer)
|
||||
};
|
||||
let handle = workspace.handle.clone();
|
||||
|
||||
let workspace_handle = shell.active_space(&output).unwrap().handle.clone();
|
||||
for (window, _) in mapped.windows() {
|
||||
toplevel_enter_output(&window, &output);
|
||||
toplevel_enter_workspace(&window, &workspace_handle);
|
||||
}
|
||||
|
||||
let workspace = shell.active_space_mut(&output).unwrap();
|
||||
workspace.floating_layer.map(mapped.clone(), None);
|
||||
|
||||
workspace.fullscreen_request(
|
||||
&mapped.active_window(),
|
||||
Some((layer, handle)),
|
||||
from,
|
||||
&seat,
|
||||
);
|
||||
} else {
|
||||
let (window, _) = mapped
|
||||
.windows()
|
||||
.find(|(w, _)| w.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||
.unwrap();
|
||||
workspace.fullscreen_request(&window, None, from, &seat)
|
||||
match shell.fullscreen_request(&surface, output.clone(), &self.common.event_loop_handle) {
|
||||
Some(target) => {
|
||||
std::mem::drop(shell);
|
||||
Shell::set_focus(self, Some(&target), &seat, None, true);
|
||||
}
|
||||
None => {
|
||||
if let Some(pending) = shell.pending_windows.iter_mut().find(|pending| {
|
||||
pending.surface.wl_surface().as_deref() == Some(surface.wl_surface())
|
||||
}) {
|
||||
pending.fullscreen = Some(output);
|
||||
}
|
||||
}
|
||||
} else if let Some(pending) = shell
|
||||
.pending_windows
|
||||
.iter_mut()
|
||||
.find(|pending| pending.surface.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||
{
|
||||
pending.fullscreen = Some(output);
|
||||
}
|
||||
}
|
||||
|
||||
fn unfullscreen_request(&mut self, surface: ToplevelSurface) {
|
||||
let mut shell = self.common.shell.write();
|
||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||
if let Some(workspace) = shell.space_for_mut(&mapped) {
|
||||
let (window, _) = mapped
|
||||
.windows()
|
||||
.find(|(w, _)| w.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||
.unwrap();
|
||||
if let Some((layer, previous_workspace)) = workspace.unfullscreen_request(&window) {
|
||||
let old_handle = workspace.handle.clone();
|
||||
let new_workspace_handle = shell
|
||||
.workspaces
|
||||
.space_for_handle(&previous_workspace)
|
||||
.is_some()
|
||||
.then_some(previous_workspace)
|
||||
.unwrap_or(old_handle); // if the workspace doesn't exist anymore, we can still remap on the right layer
|
||||
|
||||
shell.remap_unfullscreened_window(
|
||||
mapped,
|
||||
&old_handle,
|
||||
&new_workspace_handle,
|
||||
layer,
|
||||
);
|
||||
}
|
||||
if !shell.unfullscreen_request(&surface, &self.common.event_loop_handle) {
|
||||
if let Some(pending) = shell.pending_windows.iter_mut().find(|pending| {
|
||||
pending.surface.wl_surface().as_deref() == Some(surface.wl_surface())
|
||||
}) {
|
||||
pending.fullscreen.take();
|
||||
}
|
||||
} else if let Some(pending) = shell
|
||||
.pending_windows
|
||||
.iter_mut()
|
||||
.find(|pending| pending.surface.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||
{
|
||||
pending.fullscreen.take();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ impl Shell {
|
|||
(
|
||||
elem_geo.to_global(workspace.output()),
|
||||
workspace.output.clone(),
|
||||
workspace.is_tiled(elem),
|
||||
workspace.is_tiled(&elem.active_window()),
|
||||
)
|
||||
} else if let Some((output, set)) = self
|
||||
.workspaces
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue