shell: Handle maximize requests before commit
This commit is contained in:
parent
a3714b036e
commit
156f634944
5 changed files with 130 additions and 52 deletions
|
|
@ -229,12 +229,27 @@ impl From<&CosmicSurface> for ActivationKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PendingWindow {
|
||||||
|
pub surface: CosmicSurface,
|
||||||
|
pub seat: Seat<State>,
|
||||||
|
pub fullscreen: Option<Output>,
|
||||||
|
pub maximized: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PendingLayer {
|
||||||
|
pub surface: LayerSurface,
|
||||||
|
pub seat: Seat<State>,
|
||||||
|
pub output: Output,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Shell {
|
pub struct Shell {
|
||||||
pub workspaces: Workspaces,
|
pub workspaces: Workspaces,
|
||||||
|
|
||||||
pub pending_windows: Vec<(CosmicSurface, Seat<State>, Option<Output>)>,
|
pub pending_windows: Vec<PendingWindow>,
|
||||||
pub pending_layers: Vec<(LayerSurface, Output, Seat<State>)>,
|
pub pending_layers: Vec<PendingLayer>,
|
||||||
pub pending_activations: HashMap<ActivationKey, ActivationContext>,
|
pub pending_activations: HashMap<ActivationKey, ActivationContext>,
|
||||||
pub override_redirect_windows: Vec<X11Surface>,
|
pub override_redirect_windows: Vec<X11Surface>,
|
||||||
pub session_lock: Option<SessionLock>,
|
pub session_lock: Option<SessionLock>,
|
||||||
|
|
@ -1612,14 +1627,14 @@ impl Shell {
|
||||||
})
|
})
|
||||||
// pending layer map surface?
|
// pending layer map surface?
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.pending_layers.iter().find_map(|(l, output, _)| {
|
self.pending_layers.iter().find_map(|pending| {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
l.with_surfaces(|s, _| {
|
pending.surface.with_surfaces(|s, _| {
|
||||||
if s == surface {
|
if s == surface {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
found.then_some(output)
|
found.then_some(&pending.output)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// override redirect window?
|
// override redirect window?
|
||||||
|
|
@ -1975,8 +1990,10 @@ impl Shell {
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|or| or.refresh());
|
.for_each(|or| or.refresh());
|
||||||
|
|
||||||
self.pending_layers.retain(|(s, _, _)| s.alive());
|
self.pending_layers
|
||||||
self.pending_windows.retain(|(s, _, _)| s.alive());
|
.retain(|pending| pending.surface.alive());
|
||||||
|
self.pending_windows
|
||||||
|
.retain(|pending| pending.surface.alive());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_pointer_position(&mut self, location: Point<f64, Local>, output: &Output) {
|
pub fn update_pointer_position(&mut self, location: Point<f64, Local>, output: &Output) {
|
||||||
|
|
@ -2067,9 +2084,14 @@ impl Shell {
|
||||||
let pos = self
|
let pos = self
|
||||||
.pending_windows
|
.pending_windows
|
||||||
.iter()
|
.iter()
|
||||||
.position(|(w, _, _)| w == window)
|
.position(|pending| &pending.surface == window)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (window, seat, output) = self.pending_windows.remove(pos);
|
let PendingWindow {
|
||||||
|
surface: window,
|
||||||
|
seat,
|
||||||
|
fullscreen: output,
|
||||||
|
maximized: should_be_maximized,
|
||||||
|
} = self.pending_windows.remove(pos);
|
||||||
|
|
||||||
let parent_is_sticky = if let Some(toplevel) = window.0.toplevel() {
|
let parent_is_sticky = if let Some(toplevel) = window.0.toplevel() {
|
||||||
if let Some(parent) = toplevel.parent() {
|
if let Some(parent) = toplevel.parent() {
|
||||||
|
|
@ -2155,7 +2177,7 @@ impl Shell {
|
||||||
|
|
||||||
let maybe_focused = workspace.focus_stack.get(&seat).iter().next().cloned();
|
let maybe_focused = workspace.focus_stack.get(&seat).iter().next().cloned();
|
||||||
if let Some(focused) = maybe_focused {
|
if let Some(focused) = maybe_focused {
|
||||||
if (focused.is_stack() && !is_dialog && !should_be_fullscreen)
|
if (focused.is_stack() && !is_dialog && !should_be_fullscreen && !should_be_maximized)
|
||||||
&& !(workspace.is_tiled(&focused) && floating_exception)
|
&& !(workspace.is_tiled(&focused) && floating_exception)
|
||||||
{
|
{
|
||||||
focused.stack_ref().unwrap().add_window(window, None);
|
focused.stack_ref().unwrap().add_window(window, None);
|
||||||
|
|
@ -2205,6 +2227,10 @@ impl Shell {
|
||||||
self.toggle_sticky(&seat, &mapped);
|
self.toggle_sticky(&seat, &mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !should_be_fullscreen && should_be_maximized {
|
||||||
|
self.maximize_request(&mapped, &seat);
|
||||||
|
}
|
||||||
|
|
||||||
let new_target = if (workspace_output == seat.active_output()
|
let new_target = if (workspace_output == seat.active_output()
|
||||||
&& active_handle == workspace_handle)
|
&& active_handle == workspace_handle)
|
||||||
|| parent_is_sticky
|
|| parent_is_sticky
|
||||||
|
|
@ -2246,12 +2272,12 @@ impl Shell {
|
||||||
let pos = self
|
let pos = self
|
||||||
.pending_layers
|
.pending_layers
|
||||||
.iter()
|
.iter()
|
||||||
.position(|(l, _, _)| l == layer_surface)
|
.position(|pending| &pending.surface == layer_surface)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (layer_surface, output, _seat) = self.pending_layers.remove(pos);
|
let pending = self.pending_layers.remove(pos);
|
||||||
|
|
||||||
let wants_focus = {
|
let wants_focus = {
|
||||||
with_states(layer_surface.wl_surface(), |states| {
|
with_states(pending.surface.wl_surface(), |states| {
|
||||||
let mut state = states.cached_state.get::<LayerSurfaceCachedState>();
|
let mut state = states.cached_state.get::<LayerSurfaceCachedState>();
|
||||||
matches!(state.current().layer, Layer::Top | Layer::Overlay)
|
matches!(state.current().layer, Layer::Top | Layer::Overlay)
|
||||||
&& state.current().keyboard_interactivity != KeyboardInteractivity::None
|
&& state.current().keyboard_interactivity != KeyboardInteractivity::None
|
||||||
|
|
@ -2259,14 +2285,14 @@ impl Shell {
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut map = layer_map_for_output(&output);
|
let mut map = layer_map_for_output(&pending.output);
|
||||||
map.map_layer(&layer_surface).unwrap();
|
map.map_layer(&pending.surface).unwrap();
|
||||||
}
|
}
|
||||||
for workspace in self.workspaces.spaces_mut() {
|
for workspace in self.workspaces.spaces_mut() {
|
||||||
workspace.tiling_layer.recalculate();
|
workspace.tiling_layer.recalculate();
|
||||||
}
|
}
|
||||||
|
|
||||||
wants_focus.then(|| layer_surface.into())
|
wants_focus.then(|| pending.surface.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unmap_surface<S>(
|
pub fn unmap_surface<S>(
|
||||||
|
|
@ -2323,7 +2349,12 @@ impl Shell {
|
||||||
|
|
||||||
if let Some(surface) = surface {
|
if let Some(surface) = surface {
|
||||||
toplevel_info.remove_toplevel(&surface);
|
toplevel_info.remove_toplevel(&surface);
|
||||||
self.pending_windows.push((surface, seat.clone(), None));
|
self.pending_windows.push(PendingWindow {
|
||||||
|
surface,
|
||||||
|
seat: seat.clone(),
|
||||||
|
fullscreen: None,
|
||||||
|
maximized: false,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -277,11 +277,11 @@ impl State {
|
||||||
fn send_initial_configure_and_map(&mut self, surface: &WlSurface) -> bool {
|
fn send_initial_configure_and_map(&mut self, surface: &WlSurface) -> bool {
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
||||||
if let Some((window, _, _)) = shell
|
if let Some(window) = shell
|
||||||
.pending_windows
|
.pending_windows
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(window, _, _)| window.wl_surface().as_deref() == Some(surface))
|
.find(|pending| pending.surface.wl_surface().as_deref() == Some(surface))
|
||||||
.cloned()
|
.map(|pending| pending.surface.clone())
|
||||||
{
|
{
|
||||||
if let Some(toplevel) = window.0.toplevel() {
|
if let Some(toplevel) = window.0.toplevel() {
|
||||||
if toplevel_ensure_initial_configure(&toplevel)
|
if toplevel_ensure_initial_configure(&toplevel)
|
||||||
|
|
@ -305,11 +305,11 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((layer_surface, _, _)) = shell
|
if let Some(layer_surface) = shell
|
||||||
.pending_layers
|
.pending_layers
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(layer_surface, _, _)| layer_surface.wl_surface() == surface)
|
.find(|pending| pending.surface.wl_surface() == surface)
|
||||||
.cloned()
|
.map(|pending| pending.surface.clone())
|
||||||
{
|
{
|
||||||
if !layer_surface_check_inital_configure(&layer_surface) {
|
if !layer_surface_check_inital_configure(&layer_surface) {
|
||||||
// compute initial dimensions by mapping
|
// compute initial dimensions by mapping
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::utils::prelude::*;
|
use crate::{shell::PendingLayer, utils::prelude::*};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
delegate_layer_shell,
|
delegate_layer_shell,
|
||||||
desktop::{layer_map_for_output, LayerSurface, PopupKind, WindowSurfaceType},
|
desktop::{layer_map_for_output, LayerSurface, PopupKind, WindowSurfaceType},
|
||||||
|
|
@ -32,9 +32,11 @@ impl WlrLayerShellHandler for State {
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(Output::from_resource)
|
.and_then(Output::from_resource)
|
||||||
.unwrap_or_else(|| seat.active_output());
|
.unwrap_or_else(|| seat.active_output());
|
||||||
shell
|
shell.pending_layers.push(PendingLayer {
|
||||||
.pending_layers
|
surface: LayerSurface::new(surface, namespace),
|
||||||
.push((LayerSurface::new(surface, namespace), output, seat));
|
output,
|
||||||
|
seat,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_popup(&mut self, _parent: WlrLayerSurface, popup: PopupSurface) {
|
fn new_popup(&mut self, _parent: WlrLayerSurface, popup: PopupSurface) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
shell::{element::CosmicWindow, grabs::ReleaseMode, CosmicMapped, CosmicSurface, ManagedLayer},
|
shell::{
|
||||||
|
element::CosmicWindow, grabs::ReleaseMode, CosmicMapped, CosmicSurface, ManagedLayer,
|
||||||
|
PendingWindow,
|
||||||
|
},
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::protocols::toplevel_info::{toplevel_enter_output, toplevel_enter_workspace},
|
wayland::protocols::toplevel_info::{toplevel_enter_output, toplevel_enter_workspace},
|
||||||
};
|
};
|
||||||
|
|
@ -45,7 +48,12 @@ impl XdgShellHandler for State {
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
let seat = shell.seats.last_active().clone();
|
let seat = shell.seats.last_active().clone();
|
||||||
let window = CosmicSurface::from(surface);
|
let window = CosmicSurface::from(surface);
|
||||||
shell.pending_windows.push((window, seat, None));
|
shell.pending_windows.push(PendingWindow {
|
||||||
|
surface: window,
|
||||||
|
seat,
|
||||||
|
fullscreen: None,
|
||||||
|
maximized: false,
|
||||||
|
});
|
||||||
// We will position the window after the first commit, when we know its size hints
|
// We will position the window after the first commit, when we know its size hints
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,6 +227,12 @@ impl XdgShellHandler for State {
|
||||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||||
let seat = shell.seats.last_active().clone();
|
let seat = shell.seats.last_active().clone();
|
||||||
shell.maximize_request(&mapped, &seat)
|
shell.maximize_request(&mapped, &seat)
|
||||||
|
} else if let Some(pending) = shell
|
||||||
|
.pending_windows
|
||||||
|
.iter_mut()
|
||||||
|
.find(|pending| pending.surface.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||||
|
{
|
||||||
|
pending.maximized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -226,6 +240,12 @@ impl XdgShellHandler for State {
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
if let Some(mapped) = shell.element_for_surface(surface.wl_surface()).cloned() {
|
||||||
shell.unmaximize_request(&mapped);
|
shell.unmaximize_request(&mapped);
|
||||||
|
} else if let Some(pending) = shell
|
||||||
|
.pending_windows
|
||||||
|
.iter_mut()
|
||||||
|
.find(|pending| pending.surface.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||||
|
{
|
||||||
|
pending.maximized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -339,15 +359,12 @@ impl XdgShellHandler for State {
|
||||||
workspace.fullscreen_request(&window, None, from, &seat)
|
workspace.fullscreen_request(&window, None, from, &seat)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(pending) = shell
|
||||||
if let Some(o) = shell
|
.pending_windows
|
||||||
.pending_windows
|
.iter_mut()
|
||||||
.iter_mut()
|
.find(|pending| pending.surface.wl_surface().as_deref() == Some(surface.wl_surface()))
|
||||||
.find(|(s, _, _)| s.wl_surface().as_deref() == Some(surface.wl_surface()))
|
{
|
||||||
.map(|(_, _, o)| o)
|
pending.fullscreen = Some(output);
|
||||||
{
|
|
||||||
*o = Some(output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,6 +393,12 @@ impl XdgShellHandler for State {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} 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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ use std::{ffi::OsString, os::unix::io::OwnedFd, process::Stdio};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::cursor::{load_cursor_theme, Cursor},
|
backend::render::cursor::{load_cursor_theme, Cursor},
|
||||||
shell::{focus::target::KeyboardFocusTarget, grabs::ReleaseMode, CosmicSurface, Shell},
|
shell::{
|
||||||
|
focus::target::KeyboardFocusTarget, grabs::ReleaseMode, CosmicSurface, PendingWindow, Shell,
|
||||||
|
},
|
||||||
state::State,
|
state::State,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::handlers::{
|
wayland::handlers::{
|
||||||
|
|
@ -349,16 +351,21 @@ impl XwmHandler for State {
|
||||||
}
|
}
|
||||||
|
|
||||||
let surface = CosmicSurface::from(window);
|
let surface = CosmicSurface::from(window);
|
||||||
shell.pending_windows.push((surface, seat, None));
|
shell.pending_windows.push(PendingWindow {
|
||||||
|
surface,
|
||||||
|
seat,
|
||||||
|
fullscreen: None,
|
||||||
|
maximized: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_window_notify(&mut self, _xwm: XwmId, surface: X11Surface) {
|
fn map_window_notify(&mut self, _xwm: XwmId, surface: X11Surface) {
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
if let Some((window, _, _)) = shell
|
if let Some(window) = shell
|
||||||
.pending_windows
|
.pending_windows
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(window, _, _)| window.x11_surface() == Some(&surface))
|
.find(|pending| pending.surface.x11_surface() == Some(&surface))
|
||||||
.cloned()
|
.map(|pending| pending.surface.clone())
|
||||||
{
|
{
|
||||||
if !shell
|
if !shell
|
||||||
.pending_activations
|
.pending_activations
|
||||||
|
|
@ -606,6 +613,12 @@ impl XwmHandler for State {
|
||||||
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
||||||
let seat = shell.seats.last_active().clone();
|
let seat = shell.seats.last_active().clone();
|
||||||
shell.maximize_request(&mapped, &seat);
|
shell.maximize_request(&mapped, &seat);
|
||||||
|
} else if let Some(pending) = shell
|
||||||
|
.pending_windows
|
||||||
|
.iter_mut()
|
||||||
|
.find(|pending| pending.surface.x11_surface() == Some(&window))
|
||||||
|
{
|
||||||
|
pending.maximized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -613,6 +626,12 @@ impl XwmHandler for State {
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
if let Some(mapped) = shell.element_for_surface(&window).cloned() {
|
||||||
shell.unmaximize_request(&mapped);
|
shell.unmaximize_request(&mapped);
|
||||||
|
} else if let Some(pending) = shell
|
||||||
|
.pending_windows
|
||||||
|
.iter_mut()
|
||||||
|
.find(|pending| pending.surface.x11_surface() == Some(&window))
|
||||||
|
{
|
||||||
|
pending.maximized = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -659,16 +678,13 @@ impl XwmHandler for State {
|
||||||
.fullscreen_request(&surface, None, from, &seat);
|
.fullscreen_request(&surface, None, from, &seat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else if let Some(pending) = shell
|
||||||
|
.pending_windows
|
||||||
|
.iter_mut()
|
||||||
|
.find(|pending| pending.surface.x11_surface() == Some(&window))
|
||||||
|
{
|
||||||
let output = seat.active_output();
|
let output = seat.active_output();
|
||||||
if let Some(o) = shell
|
pending.fullscreen = Some(output);
|
||||||
.pending_windows
|
|
||||||
.iter_mut()
|
|
||||||
.find(|(s, _, _)| s.x11_surface() == Some(&window))
|
|
||||||
.map(|(_, _, o)| o)
|
|
||||||
{
|
|
||||||
*o = Some(output);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -683,6 +699,12 @@ impl XwmHandler for State {
|
||||||
let previous = workspace.unfullscreen_request(&window);
|
let previous = workspace.unfullscreen_request(&window);
|
||||||
assert!(previous.is_none());
|
assert!(previous.is_none());
|
||||||
}
|
}
|
||||||
|
} else if let Some(pending) = shell
|
||||||
|
.pending_windows
|
||||||
|
.iter_mut()
|
||||||
|
.find(|pending| pending.surface.x11_surface() == Some(&window))
|
||||||
|
{
|
||||||
|
pending.fullscreen.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue