2022-07-04 15:28:03 +02:00
|
|
|
use crate::{
|
2022-07-04 16:00:29 +02:00
|
|
|
shell::layout::{floating::FloatingLayout, tiling::TilingLayout},
|
2022-07-04 15:28:03 +02:00
|
|
|
state::State,
|
|
|
|
|
wayland::protocols::workspace::WorkspaceHandle,
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-24 20:32:31 +01:00
|
|
|
use smithay::{
|
2022-08-31 13:01:23 +02:00
|
|
|
desktop::{Kind, Space, Window, WindowSurfaceType},
|
|
|
|
|
input::{pointer::GrabStartData as PointerGrabStartData, Seat},
|
2022-09-09 20:00:00 -07:00
|
|
|
output::Output,
|
2022-07-04 15:28:03 +02:00
|
|
|
reexports::{
|
|
|
|
|
wayland_protocols::xdg::shell::server::xdg_toplevel::{self, ResizeEdge},
|
2022-08-31 13:01:23 +02:00
|
|
|
wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle},
|
2022-03-24 20:32:31 +01:00
|
|
|
},
|
2022-08-31 13:01:23 +02:00
|
|
|
utils::{IsAlive, Serial},
|
2022-03-24 20:32:31 +01:00
|
|
|
};
|
2022-07-04 15:28:03 +02:00
|
|
|
use std::collections::HashMap;
|
2022-03-30 22:00:44 +02:00
|
|
|
|
2022-03-24 20:32:31 +01:00
|
|
|
pub struct Workspace {
|
2022-07-18 21:26:02 +02:00
|
|
|
pub idx: u8,
|
2022-03-24 20:32:31 +01:00
|
|
|
pub space: Space,
|
2022-07-04 15:28:03 +02:00
|
|
|
pub tiling_layer: TilingLayout,
|
|
|
|
|
pub floating_layer: FloatingLayout,
|
2022-07-07 22:41:17 +02:00
|
|
|
tiling_enabled: bool,
|
2022-04-22 15:18:28 +02:00
|
|
|
pub fullscreen: HashMap<String, Window>,
|
2022-07-04 15:28:03 +02:00
|
|
|
pub handle: WorkspaceHandle,
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Workspace {
|
2022-07-04 15:28:03 +02:00
|
|
|
pub fn new(idx: u8, handle: WorkspaceHandle) -> Workspace {
|
2022-03-24 20:32:31 +01:00
|
|
|
Workspace {
|
2022-03-30 22:00:44 +02:00
|
|
|
idx,
|
2022-03-24 20:32:31 +01:00
|
|
|
space: Space::new(None),
|
2022-07-04 15:28:03 +02:00
|
|
|
tiling_layer: TilingLayout::new(),
|
|
|
|
|
floating_layer: FloatingLayout::new(),
|
2022-07-07 22:41:17 +02:00
|
|
|
tiling_enabled: true,
|
2022-04-22 15:18:28 +02:00
|
|
|
fullscreen: HashMap::new(),
|
2022-07-04 15:28:03 +02:00
|
|
|
handle,
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-04 15:28:03 +02:00
|
|
|
pub fn refresh(&mut self, dh: &DisplayHandle) {
|
2022-04-22 15:18:28 +02:00
|
|
|
let outputs = self.space.outputs().collect::<Vec<_>>();
|
2022-05-03 13:37:51 +02:00
|
|
|
let dead_output_windows = self
|
|
|
|
|
.fullscreen
|
2022-04-22 15:18:28 +02:00
|
|
|
.iter()
|
2022-05-03 13:37:51 +02:00
|
|
|
.filter(|(name, _)| !outputs.iter().any(|o| o.name() == **name))
|
2022-04-22 15:18:28 +02:00
|
|
|
.map(|(_, w)| w)
|
|
|
|
|
.cloned()
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
for window in dead_output_windows {
|
|
|
|
|
self.unfullscreen_request(&window);
|
|
|
|
|
}
|
2022-07-04 15:28:03 +02:00
|
|
|
self.fullscreen.retain(|_, w| w.alive());
|
|
|
|
|
self.floating_layer.refresh(&mut self.space);
|
|
|
|
|
self.tiling_layer.refresh(&mut self.space);
|
|
|
|
|
self.space.refresh(dh);
|
2022-03-30 23:08:35 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-24 20:32:31 +01:00
|
|
|
pub fn maximize_request(&mut self, window: &Window, output: &Output) {
|
2022-04-22 15:18:28 +02:00
|
|
|
if self.fullscreen.values().any(|w| w == window) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-07-04 15:28:03 +02:00
|
|
|
if self.floating_layer.windows.contains(window) {
|
2022-07-04 16:00:29 +02:00
|
|
|
self.floating_layer
|
|
|
|
|
.maximize_request(&mut self.space, window, output);
|
2022-07-04 15:28:03 +02:00
|
|
|
}
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
2022-08-30 13:28:36 +02:00
|
|
|
|
2022-07-08 15:20:29 +02:00
|
|
|
pub fn unmaximize_request(&mut self, window: &Window) {
|
|
|
|
|
if self.fullscreen.values().any(|w| w == window) {
|
|
|
|
|
return self.unfullscreen_request(window);
|
|
|
|
|
}
|
|
|
|
|
if self.floating_layer.windows.contains(window) {
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.unmaximize_request(&mut self.space, window);
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-24 20:32:31 +01:00
|
|
|
|
|
|
|
|
pub fn resize_request(
|
2022-08-31 13:01:23 +02:00
|
|
|
state: &mut State,
|
|
|
|
|
surface: &WlSurface,
|
2022-07-04 15:28:03 +02:00
|
|
|
seat: &Seat<State>,
|
2022-03-24 20:32:31 +01:00
|
|
|
serial: Serial,
|
2022-08-31 13:01:23 +02:00
|
|
|
start_data: PointerGrabStartData<State>,
|
2022-03-24 20:32:31 +01:00
|
|
|
edges: ResizeEdge,
|
|
|
|
|
) {
|
2022-08-31 13:01:23 +02:00
|
|
|
let workspace = state.common.shell.space_for_window_mut(surface).unwrap();
|
|
|
|
|
let window = workspace
|
|
|
|
|
.space
|
|
|
|
|
.window_for_surface(surface, WindowSurfaceType::TOPLEVEL)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.clone();
|
|
|
|
|
|
|
|
|
|
if workspace.fullscreen.values().any(|w| w == &window) {
|
2022-04-22 15:18:28 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2022-08-31 13:01:23 +02:00
|
|
|
if workspace.floating_layer.windows.contains(&window) {
|
|
|
|
|
FloatingLayout::resize_request(state, &window, seat, serial, start_data.clone(), edges)
|
|
|
|
|
} else if workspace.tiling_layer.windows.contains(&window) {
|
|
|
|
|
TilingLayout::resize_request(state, &window, seat, serial, start_data, edges)
|
2022-07-04 15:28:03 +02:00
|
|
|
}
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
2022-04-22 15:18:28 +02:00
|
|
|
|
|
|
|
|
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() {
|
2022-07-04 15:28:03 +02:00
|
|
|
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_f64()
|
|
|
|
|
.to_logical(output.current_scale().fractional_scale())
|
|
|
|
|
.to_i32_round(),
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
xdg.send_configure();
|
|
|
|
|
self.fullscreen.insert(output.name(), window.clone());
|
2022-04-22 15:18:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-05-03 13:37:51 +02:00
|
|
|
|
2022-04-22 15:18:28 +02:00
|
|
|
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() {
|
2022-07-04 15:28:03 +02:00
|
|
|
xdg.with_pending_state(|state| {
|
|
|
|
|
state.states.unset(xdg_toplevel::State::Fullscreen);
|
|
|
|
|
state.size = None;
|
|
|
|
|
});
|
|
|
|
|
self.floating_layer.refresh(&mut self.space);
|
|
|
|
|
self.tiling_layer.refresh(&mut self.space);
|
|
|
|
|
xdg.send_configure();
|
2022-04-22 15:18:28 +02:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
|
}
|
2022-07-04 16:00:29 +02:00
|
|
|
self.fullscreen.get(&output.name()).filter(|w| w.alive())
|
2022-04-22 15:18:28 +02:00
|
|
|
}
|
2022-07-07 22:41:17 +02:00
|
|
|
|
|
|
|
|
pub fn toggle_tiling(&mut self, seat: &Seat<State>) {
|
|
|
|
|
if self.tiling_enabled {
|
|
|
|
|
for window in self.tiling_layer.windows.clone().into_iter() {
|
|
|
|
|
self.tiling_layer.unmap_window(&mut self.space, &window);
|
2022-08-30 13:28:36 +02:00
|
|
|
self.floating_layer
|
|
|
|
|
.map_window(&mut self.space, window, seat, None);
|
2022-07-07 22:41:17 +02:00
|
|
|
}
|
|
|
|
|
self.tiling_enabled = false;
|
|
|
|
|
} else {
|
|
|
|
|
let focus_stack = self.focus_stack(seat);
|
|
|
|
|
for window in self.floating_layer.windows.clone().into_iter() {
|
|
|
|
|
self.floating_layer.unmap_window(&mut self.space, &window);
|
2022-08-30 13:28:36 +02:00
|
|
|
self.tiling_layer
|
|
|
|
|
.map_window(&mut self.space, window, seat, focus_stack.iter())
|
2022-07-07 22:41:17 +02:00
|
|
|
}
|
|
|
|
|
self.tiling_enabled = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn toggle_floating_window(&mut self, seat: &Seat<State>) {
|
|
|
|
|
if self.tiling_enabled {
|
|
|
|
|
if let Some(window) = self.focus_stack(seat).iter().next().cloned() {
|
|
|
|
|
if self.tiling_layer.windows.contains(&window) {
|
|
|
|
|
self.tiling_layer.unmap_window(&mut self.space, &window);
|
2022-08-30 13:28:36 +02:00
|
|
|
self.floating_layer
|
|
|
|
|
.map_window(&mut self.space, window, seat, None);
|
2022-07-07 22:41:17 +02:00
|
|
|
} else if self.floating_layer.windows.contains(&window) {
|
|
|
|
|
let focus_stack = self.focus_stack(seat);
|
|
|
|
|
self.floating_layer.unmap_window(&mut self.space, &window);
|
2022-08-30 13:28:36 +02:00
|
|
|
self.tiling_layer
|
|
|
|
|
.map_window(&mut self.space, window, seat, focus_stack.iter())
|
2022-07-07 22:41:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|