shell: Handle fullscreen surfaces

This commit is contained in:
Victoria Brekenfeld 2022-04-22 15:18:28 +02:00
parent 0e42f34065
commit f1f51e1714
7 changed files with 411 additions and 91 deletions

View file

@ -1,8 +1,8 @@
use super::{layout, Layout};
use indexmap::IndexSet;
use smithay::{
desktop::{LayerSurface, Space, Window},
reexports::wayland_protocols::xdg_shell::server::xdg_toplevel::ResizeEdge,
desktop::{LayerSurface, Space, Window, Kind},
reexports::wayland_protocols::xdg_shell::server::xdg_toplevel::{self, ResizeEdge},
wayland::{
output::Output,
seat::{PointerGrabStartData, Seat},
@ -53,6 +53,7 @@ pub struct Workspace {
pub(super) layout: Box<dyn Layout>,
pub(super) pending_windows: Vec<(Window, Seat)>,
pub(super) pending_layers: Vec<(LayerSurface, Output, Seat)>,
pub fullscreen: HashMap<String, Window>,
}
impl Workspace {
@ -63,6 +64,7 @@ impl Workspace {
layout: layout::new_default_layout(),
pending_windows: Vec::new(),
pending_layers: Vec::new(),
fullscreen: HashMap::new(),
}
}
@ -90,9 +92,10 @@ impl Workspace {
pub fn pending_window(&mut self, window: Window, seat: &Seat) {
self.pending_windows.push((window, seat.clone()));
}
pub fn pending_layer(&mut self, layer: LayerSurface, output: &Output, seat: &Seat) {
self.pending_layers.push((layer, output.clone(), seat.clone()));
self.pending_layers
.push((layer, output.clone(), seat.clone()));
}
pub(super) fn map_window(&mut self, window: &Window, seat: &Seat) {
@ -114,6 +117,18 @@ impl Workspace {
}
pub fn refresh(&mut self) {
let outputs = self.space.outputs().collect::<Vec<_>>();
let dead_output_windows = self.fullscreen
.iter()
.filter(|(name, _)|
!outputs.iter().any(|o| o.name() == **name)
)
.map(|(_, w)| w)
.cloned()
.collect::<Vec<_>>();
for window in dead_output_windows {
self.unfullscreen_request(&window);
}
self.layout.refresh(&mut self.space);
self.space.refresh();
}
@ -147,6 +162,9 @@ impl Workspace {
}
pub fn maximize_request(&mut self, window: &Window, output: &Output) {
if self.fullscreen.values().any(|w| w == window) {
return;
}
self.layout
.maximize_request(&mut self.space, window, output)
}
@ -158,6 +176,9 @@ impl Workspace {
serial: Serial,
start_data: PointerGrabStartData,
) {
if self.fullscreen.values().any(|w| w == window) {
return;
}
self.layout
.move_request(&mut self.space, window, seat, serial, start_data)
}
@ -170,7 +191,71 @@ impl Workspace {
start_data: PointerGrabStartData,
edges: ResizeEdge,
) {
if self.fullscreen.values().any(|w| w == window) {
return;
}
self.layout
.resize_request(&mut self.space, window, seat, serial, start_data, edges)
}
pub fn fullscreen_request(&mut self, window: &Window, output: &Output) {
if self.fullscreen.contains_key(&output.name()) {
return;
}
#[allow(irrefutable_let_patterns)]
if let Kind::Xdg(xdg) = &window.toplevel() {
if xdg.get_surface().is_some() {
let ret = xdg.with_pending_state(|state| {
state.states.set(xdg_toplevel::State::Fullscreen);
state.size = Some(
output
.current_mode()
.map(|m| m.size)
.unwrap_or((0, 0).into())
.to_logical(output.current_scale().integer_scale()),
);
});
if ret.is_ok() {
xdg.send_configure();
self.fullscreen.insert(output.name(), window.clone());
}
}
}
}
pub fn unfullscreen_request(&mut self, window: &Window) {
if self.fullscreen.values().any(|w| w == window) {
#[allow(irrefutable_let_patterns)]
if let Kind::Xdg(xdg) = &window.toplevel() {
if xdg.get_surface().is_some() {
let ret = xdg.with_pending_state(|state| {
state.states.unset(xdg_toplevel::State::Fullscreen);
state.size = None;
});
if ret.is_ok() {
self.layout.refresh(&mut self.space);
xdg.send_configure();
}
}
}
self.fullscreen.retain(|_, w| w != window);
}
}
pub fn fullscreen_toggle(&mut self, window: &Window, output: &Output) {
if self.fullscreen.contains_key(&output.name()) {
self.unfullscreen_request(window)
} else {
self.fullscreen_request(window, output)
}
}
pub fn get_fullscreen(&self, output: &Output) -> Option<&Window> {
if !self.space.outputs().any(|o| o == output) {
return None;
}
self.fullscreen.get(&output.name()).filter(|w| w.toplevel().get_surface().is_some())
}
}