2022-07-04 15:28:03 +02:00
|
|
|
use crate::{
|
2022-09-28 12:01:29 +02:00
|
|
|
shell::{
|
|
|
|
|
element::CosmicWindow,
|
2022-10-26 15:26:07 +02:00
|
|
|
layout::{
|
|
|
|
|
floating::{FloatingLayout, MoveSurfaceGrab},
|
|
|
|
|
tiling::TilingLayout,
|
|
|
|
|
},
|
2022-09-28 12:01:29 +02:00
|
|
|
},
|
2022-07-04 15:28:03 +02:00
|
|
|
state::State,
|
2022-09-28 12:01:29 +02:00
|
|
|
utils::prelude::*,
|
2022-07-04 15:28:03 +02:00
|
|
|
wayland::protocols::workspace::WorkspaceHandle,
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-28 12:01:29 +02:00
|
|
|
use indexmap::IndexSet;
|
2022-03-24 20:32:31 +01:00
|
|
|
use smithay::{
|
2022-09-28 12:01:29 +02:00
|
|
|
backend::renderer::{
|
|
|
|
|
element::{surface::WaylandSurfaceRenderElement, AsRenderElements},
|
|
|
|
|
ImportAll, Renderer,
|
|
|
|
|
},
|
|
|
|
|
desktop::{
|
|
|
|
|
layer_map_for_output, space::SpaceElement, Kind, LayerSurface, Space, Window,
|
|
|
|
|
WindowSurfaceType,
|
|
|
|
|
},
|
2022-08-31 13:01:23 +02:00
|
|
|
input::{pointer::GrabStartData as PointerGrabStartData, Seat},
|
2022-09-28 12:01:29 +02:00
|
|
|
output::{Output, WeakOutput},
|
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-09-28 12:01:29 +02:00
|
|
|
render_elements,
|
|
|
|
|
utils::{IsAlive, Logical, Point, Rectangle, Scale, Serial},
|
|
|
|
|
wayland::shell::wlr_layer::Layer,
|
|
|
|
|
};
|
|
|
|
|
use std::{collections::HashMap, time::Duration};
|
|
|
|
|
|
|
|
|
|
use super::{
|
|
|
|
|
element::CosmicMapped,
|
|
|
|
|
focus::{FocusStack, FocusStackMut},
|
2022-10-25 14:43:50 +02:00
|
|
|
layout::{
|
|
|
|
|
floating::{FloatingRenderElement, ResizeSurfaceGrab},
|
|
|
|
|
tiling::TilingRenderElement,
|
|
|
|
|
},
|
2022-03-24 20:32:31 +01:00
|
|
|
};
|
2022-03-30 22:00:44 +02:00
|
|
|
|
2022-09-28 12:01:29 +02:00
|
|
|
#[derive(Debug)]
|
2022-03-24 20:32:31 +01:00
|
|
|
pub struct Workspace {
|
2022-07-04 15:28:03 +02:00
|
|
|
pub tiling_layer: TilingLayout,
|
|
|
|
|
pub floating_layer: FloatingLayout,
|
2022-09-28 12:01:29 +02:00
|
|
|
pub tiling_enabled: bool,
|
|
|
|
|
pub fullscreen: HashMap<Output, Window>,
|
2022-07-04 15:28:03 +02:00
|
|
|
pub handle: WorkspaceHandle,
|
2022-09-28 12:01:29 +02:00
|
|
|
pub focus_stack: FocusStacks,
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
|
|
|
|
|
2022-09-28 12:01:29 +02:00
|
|
|
#[derive(Debug, Default)]
|
|
|
|
|
pub struct FocusStacks(HashMap<Seat<State>, IndexSet<CosmicMapped>>);
|
|
|
|
|
|
2022-03-24 20:32:31 +01:00
|
|
|
impl Workspace {
|
2022-09-28 12:01:29 +02:00
|
|
|
pub fn new(handle: WorkspaceHandle) -> Workspace {
|
2022-03-24 20:32:31 +01:00
|
|
|
Workspace {
|
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-09-28 12:01:29 +02:00
|
|
|
focus_stack: FocusStacks::default(),
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-28 12:01:29 +02:00
|
|
|
pub fn refresh(&mut self) {
|
2022-07-04 15:28:03 +02:00
|
|
|
self.fullscreen.retain(|_, w| w.alive());
|
2022-09-28 12:01:29 +02:00
|
|
|
self.floating_layer.refresh();
|
|
|
|
|
self.tiling_layer.refresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn commit(&mut self, surface: &WlSurface) {
|
|
|
|
|
if let Some(mapped) = self.element_for_surface(surface) {
|
|
|
|
|
mapped
|
|
|
|
|
.windows()
|
|
|
|
|
.find(|(w, _)| w.toplevel().wl_surface() == surface)
|
|
|
|
|
.unwrap()
|
|
|
|
|
.0
|
|
|
|
|
.on_commit();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn map_output(&mut self, output: &Output, position: Point<i32, Logical>) {
|
|
|
|
|
self.tiling_layer.map_output(output, position);
|
|
|
|
|
self.floating_layer.map_output(output, position);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn unmap_output(&mut self, output: &Output) {
|
|
|
|
|
if let Some(dead_output_window) = self.fullscreen.remove(output) {
|
|
|
|
|
self.unfullscreen_request(&dead_output_window);
|
|
|
|
|
}
|
|
|
|
|
self.tiling_layer.unmap_output(output);
|
|
|
|
|
self.floating_layer.unmap_output(output);
|
|
|
|
|
self.refresh();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn element_for_surface(&self, surface: &WlSurface) -> Option<&CosmicMapped> {
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.mapped()
|
|
|
|
|
.chain(self.tiling_layer.mapped().map(|(_, w, _)| w))
|
|
|
|
|
.find(|e| {
|
|
|
|
|
e.windows()
|
|
|
|
|
.any(|(w, _)| w.toplevel().wl_surface() == surface)
|
|
|
|
|
})
|
2022-03-30 23:08:35 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-28 12:01:29 +02:00
|
|
|
pub fn outputs_for_element(&self, elem: &CosmicMapped) -> impl Iterator<Item = Output> {
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.space
|
|
|
|
|
.outputs_for_element(elem)
|
|
|
|
|
.into_iter()
|
|
|
|
|
.chain(self.tiling_layer.output_for_element(elem).cloned())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn output_under(&self, point: Point<i32, Logical>) -> Option<&Output> {
|
|
|
|
|
let space = &self.floating_layer.space;
|
|
|
|
|
space.outputs().find(|o| {
|
|
|
|
|
let internal_output_geo = space.output_geometry(o).unwrap();
|
|
|
|
|
let external_output_geo = o.geometry();
|
|
|
|
|
internal_output_geo.contains(point - external_output_geo.loc + internal_output_geo.loc)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn element_under(
|
|
|
|
|
&self,
|
|
|
|
|
location: Point<f64, Logical>,
|
|
|
|
|
) -> Option<(&CosmicMapped, Point<i32, Logical>)> {
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.space
|
|
|
|
|
.element_under(location)
|
|
|
|
|
.or_else(|| {
|
|
|
|
|
self.tiling_layer.mapped().find_map(|(_, mapped, loc)| {
|
2022-10-24 14:05:36 +02:00
|
|
|
let test_point = location - loc.to_f64() + mapped.geometry().loc.to_f64();
|
2022-09-28 12:01:29 +02:00
|
|
|
mapped
|
|
|
|
|
.is_in_input_region(&test_point)
|
2022-10-24 14:05:36 +02:00
|
|
|
.then_some((mapped, loc - mapped.geometry().loc))
|
2022-09-28 12:01:29 +02:00
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn element_geometry(&self, elem: &CosmicMapped) -> Option<Rectangle<i32, Logical>> {
|
|
|
|
|
let space = &self.floating_layer.space;
|
|
|
|
|
let outputs = space.outputs().collect::<Vec<_>>();
|
|
|
|
|
let offset = if outputs.len() == 1
|
|
|
|
|
&& space.output_geometry(&outputs[0]).unwrap().loc == Point::from((0, 0))
|
|
|
|
|
{
|
|
|
|
|
outputs[0].geometry().loc
|
|
|
|
|
} else {
|
|
|
|
|
(0, 0).into()
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.space
|
|
|
|
|
.element_geometry(elem)
|
|
|
|
|
.or_else(|| self.tiling_layer.element_geometry(elem))
|
|
|
|
|
.map(|mut geo| {
|
|
|
|
|
geo.loc += offset;
|
|
|
|
|
geo
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-24 18:32:53 +02:00
|
|
|
pub fn maximize_request(&mut self, window: &Window, output: &Output) {
|
|
|
|
|
if self.fullscreen.contains_key(output) {
|
2022-04-22 15:18:28 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2022-10-24 18:32:53 +02:00
|
|
|
|
|
|
|
|
self.floating_layer.maximize_request(window);
|
|
|
|
|
|
|
|
|
|
#[allow(irrefutable_let_patterns)]
|
|
|
|
|
if let Kind::Xdg(xdg) = &window.toplevel() {
|
|
|
|
|
xdg.with_pending_state(|state| {
|
|
|
|
|
state.states.set(xdg_toplevel::State::Maximized);
|
|
|
|
|
state.states.unset(xdg_toplevel::State::Fullscreen);
|
|
|
|
|
});
|
2022-07-04 15:28:03 +02:00
|
|
|
}
|
2022-10-24 18:32:53 +02:00
|
|
|
|
|
|
|
|
self.set_fullscreen(window, output)
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
2022-10-24 18:32:53 +02:00
|
|
|
pub fn unmaximize_request(&mut self, window: &Window) {
|
2022-07-08 15:20:29 +02:00
|
|
|
if self.fullscreen.values().any(|w| w == window) {
|
2022-10-26 15:26:07 +02:00
|
|
|
self.unfullscreen_request(window);
|
2022-10-24 18:32:53 +02:00
|
|
|
self.floating_layer.unmaximize_request(window);
|
2022-07-08 15:20:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-03-24 20:32:31 +01:00
|
|
|
|
2022-10-24 18:32:53 +02:00
|
|
|
pub fn fullscreen_request(&mut self, window: &Window, output: &Output) {
|
|
|
|
|
if self.fullscreen.contains_key(output) {
|
2022-04-22 15:18:28 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2022-10-24 18:32:53 +02:00
|
|
|
|
|
|
|
|
#[allow(irrefutable_let_patterns)]
|
|
|
|
|
if let Kind::Xdg(xdg) = &window.toplevel() {
|
|
|
|
|
xdg.with_pending_state(|state| {
|
|
|
|
|
state.states.set(xdg_toplevel::State::Fullscreen);
|
|
|
|
|
state.states.unset(xdg_toplevel::State::Maximized);
|
|
|
|
|
});
|
2022-07-04 15:28:03 +02:00
|
|
|
}
|
2022-10-24 18:32:53 +02:00
|
|
|
|
|
|
|
|
self.set_fullscreen(window, output)
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|
2022-04-22 15:18:28 +02:00
|
|
|
|
2022-10-24 18:32:53 +02:00
|
|
|
fn set_fullscreen(&mut self, window: &Window, output: &Output) {
|
|
|
|
|
if let Some(mapped) = self
|
|
|
|
|
.mapped()
|
|
|
|
|
.find(|m| m.windows().any(|(w, _)| &w == window))
|
|
|
|
|
{
|
|
|
|
|
mapped.set_active(window);
|
2022-04-22 15:18:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[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.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();
|
2022-04-22 15:18:28 +02:00
|
|
|
}
|
2022-10-24 18:32:53 +02:00
|
|
|
self.fullscreen.insert(output.clone(), 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);
|
2022-10-24 18:32:53 +02:00
|
|
|
state.states.unset(xdg_toplevel::State::Maximized);
|
2022-07-04 15:28:03 +02:00
|
|
|
state.size = None;
|
|
|
|
|
});
|
2022-09-28 12:01:29 +02:00
|
|
|
self.floating_layer.refresh();
|
|
|
|
|
self.tiling_layer.refresh();
|
2022-07-04 15:28:03 +02:00
|
|
|
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) {
|
2022-09-28 12:01:29 +02:00
|
|
|
if self.fullscreen.contains_key(output) {
|
2022-04-22 15:18:28 +02:00
|
|
|
self.unfullscreen_request(window)
|
|
|
|
|
} else {
|
|
|
|
|
self.fullscreen_request(window, output)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_fullscreen(&self, output: &Output) -> Option<&Window> {
|
2022-09-28 12:01:29 +02:00
|
|
|
self.fullscreen.get(output).filter(|w| w.alive())
|
2022-04-22 15:18:28 +02:00
|
|
|
}
|
2022-07-07 22:41:17 +02:00
|
|
|
|
2022-10-24 18:32:53 +02:00
|
|
|
pub fn resize_request(
|
2022-10-25 14:43:50 +02:00
|
|
|
&mut self,
|
|
|
|
|
mapped: &CosmicMapped,
|
2022-10-24 18:32:53 +02:00
|
|
|
seat: &Seat<State>,
|
|
|
|
|
serial: Serial,
|
|
|
|
|
start_data: PointerGrabStartData<State>,
|
|
|
|
|
edges: ResizeEdge,
|
2022-10-25 14:43:50 +02:00
|
|
|
) -> Option<ResizeSurfaceGrab> {
|
|
|
|
|
if mapped.is_fullscreen() || mapped.is_maximized() {
|
|
|
|
|
return None;
|
2022-10-24 18:32:53 +02:00
|
|
|
}
|
2022-10-25 14:43:50 +02:00
|
|
|
if self.floating_layer.mapped().any(|m| m == mapped) {
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.resize_request(mapped, seat, serial, start_data.clone(), edges)
|
|
|
|
|
} else if self.tiling_layer.mapped().any(|(_, m, _)| m == mapped) {
|
|
|
|
|
//self.tiling_layer.resize_request(mapped, seat, serial, start_data, edges)
|
|
|
|
|
None
|
|
|
|
|
} else {
|
|
|
|
|
None
|
2022-10-24 18:32:53 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-26 15:26:07 +02:00
|
|
|
pub fn move_request(
|
|
|
|
|
&mut self,
|
|
|
|
|
window: &Window,
|
|
|
|
|
seat: &Seat<State>,
|
|
|
|
|
output: &Output,
|
|
|
|
|
_serial: Serial,
|
|
|
|
|
start_data: PointerGrabStartData<State>,
|
|
|
|
|
) -> Option<MoveSurfaceGrab> {
|
|
|
|
|
let pointer = seat.get_pointer().unwrap();
|
|
|
|
|
let pos = pointer.current_location();
|
|
|
|
|
|
|
|
|
|
let mapped = self
|
|
|
|
|
.element_for_surface(window.toplevel().wl_surface())?
|
|
|
|
|
.clone();
|
|
|
|
|
let mut initial_window_location = self.element_geometry(&mapped).unwrap().loc;
|
|
|
|
|
|
|
|
|
|
if mapped.is_fullscreen() || mapped.is_maximized() {
|
|
|
|
|
// If surface is maximized then unmaximize it
|
|
|
|
|
self.unmaximize_request(window);
|
|
|
|
|
let new_size = match window.toplevel() {
|
|
|
|
|
Kind::Xdg(toplevel) => toplevel.with_pending_state(|state| state.size),
|
|
|
|
|
//_ => unreachable!(), // TODO x11
|
|
|
|
|
};
|
|
|
|
|
let ratio = pos.x / output.geometry().size.w as f64;
|
|
|
|
|
|
|
|
|
|
initial_window_location = new_size
|
|
|
|
|
.map(|size| (pos.x - (size.w as f64 * ratio), pos.y).into())
|
|
|
|
|
.unwrap_or_else(|| pos)
|
|
|
|
|
.to_i32_round();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let was_floating = self.floating_layer.unmap(&mapped);
|
|
|
|
|
//let was_tiled = self.tiling_layer.unmap(&mapped);
|
|
|
|
|
//assert!(was_floating != was_tiled);
|
|
|
|
|
|
|
|
|
|
if was_floating {
|
|
|
|
|
Some(MoveSurfaceGrab::new(
|
|
|
|
|
start_data,
|
|
|
|
|
mapped,
|
|
|
|
|
seat,
|
|
|
|
|
pos,
|
|
|
|
|
initial_window_location,
|
|
|
|
|
output.geometry().loc,
|
|
|
|
|
))
|
|
|
|
|
} else {
|
|
|
|
|
None // TODO
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-07 22:41:17 +02:00
|
|
|
pub fn toggle_tiling(&mut self, seat: &Seat<State>) {
|
|
|
|
|
if self.tiling_enabled {
|
2022-09-28 12:01:29 +02:00
|
|
|
for window in self
|
|
|
|
|
.tiling_layer
|
|
|
|
|
.mapped()
|
|
|
|
|
.map(|(_, m, _)| m.clone())
|
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
|
.into_iter()
|
|
|
|
|
{
|
|
|
|
|
self.tiling_layer.unmap(&window);
|
|
|
|
|
self.floating_layer.map(window, seat, None);
|
2022-07-07 22:41:17 +02:00
|
|
|
}
|
|
|
|
|
self.tiling_enabled = false;
|
|
|
|
|
} else {
|
2022-09-28 12:01:29 +02:00
|
|
|
let focus_stack = self.focus_stack.get(seat);
|
|
|
|
|
for window in self
|
|
|
|
|
.floating_layer
|
|
|
|
|
.mapped()
|
|
|
|
|
.cloned()
|
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
|
.into_iter()
|
|
|
|
|
{
|
|
|
|
|
self.floating_layer.unmap(&window);
|
|
|
|
|
self.tiling_layer.map(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 {
|
2022-09-28 12:01:29 +02:00
|
|
|
if let Some(window) = self.focus_stack.get(seat).iter().next().cloned() {
|
|
|
|
|
if self.tiling_layer.mapped().any(|(_, m, _)| m == &window) {
|
|
|
|
|
self.tiling_layer.unmap(&window);
|
|
|
|
|
self.floating_layer.map(window, seat, None);
|
|
|
|
|
} else if self.floating_layer.mapped().any(|w| w == &window) {
|
|
|
|
|
let focus_stack = self.focus_stack.get(seat);
|
|
|
|
|
self.floating_layer.unmap(&window);
|
|
|
|
|
self.tiling_layer.map(window, seat, focus_stack.iter())
|
2022-07-07 22:41:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-09-28 12:01:29 +02:00
|
|
|
|
|
|
|
|
pub fn mapped(&self) -> impl Iterator<Item = &CosmicMapped> {
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.mapped()
|
|
|
|
|
.chain(self.tiling_layer.mapped().map(|(_, w, _)| w))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn windows(&self) -> impl Iterator<Item = Window> + '_ {
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.windows()
|
|
|
|
|
.chain(self.tiling_layer.windows().map(|(_, w, _)| w))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn render_output<R>(
|
|
|
|
|
&self,
|
|
|
|
|
output: &Output,
|
|
|
|
|
) -> Result<Vec<WorkspaceRenderElement<R>>, OutputNotMapped>
|
|
|
|
|
where
|
|
|
|
|
R: Renderer + ImportAll,
|
|
|
|
|
<R as Renderer>::TextureId: 'static,
|
|
|
|
|
{
|
|
|
|
|
let mut render_elements = Vec::new();
|
|
|
|
|
|
|
|
|
|
let output_scale = output.current_scale().fractional_scale();
|
|
|
|
|
let layer_map = layer_map_for_output(output);
|
|
|
|
|
|
|
|
|
|
if let Some(fullscreen) = self.fullscreen.get(output) {
|
|
|
|
|
// overlay layer surfaces
|
|
|
|
|
render_elements.extend(
|
|
|
|
|
layer_map
|
|
|
|
|
.layers()
|
|
|
|
|
.rev()
|
|
|
|
|
.filter(|s| s.layer() == Layer::Overlay)
|
|
|
|
|
.filter_map(|surface| {
|
|
|
|
|
layer_map
|
|
|
|
|
.layer_geometry(surface)
|
|
|
|
|
.map(|geo| (geo.loc, surface))
|
|
|
|
|
})
|
|
|
|
|
.flat_map(|(loc, surface)| {
|
|
|
|
|
AsRenderElements::<R>::render_elements::<WorkspaceRenderElement<R>>(
|
|
|
|
|
surface,
|
|
|
|
|
loc.to_physical_precise_round(output_scale),
|
|
|
|
|
Scale::from(output_scale),
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// fullscreen window
|
|
|
|
|
render_elements.extend(AsRenderElements::<R>::render_elements::<
|
|
|
|
|
WorkspaceRenderElement<R>,
|
|
|
|
|
>(fullscreen, (0, 0).into(), output_scale.into()));
|
|
|
|
|
} else {
|
|
|
|
|
// TODO: Handle modes like
|
|
|
|
|
// - keyboard window swapping
|
|
|
|
|
// - resizing / moving in tiling
|
|
|
|
|
|
|
|
|
|
// overlay and top layer surfaces
|
|
|
|
|
let lower = {
|
|
|
|
|
let (upper, lower): (Vec<&LayerSurface>, Vec<&LayerSurface>) = layer_map
|
|
|
|
|
.layers()
|
|
|
|
|
.rev()
|
|
|
|
|
.partition(|s| matches!(s.layer(), Layer::Background | Layer::Bottom));
|
|
|
|
|
|
|
|
|
|
render_elements.extend(
|
|
|
|
|
upper
|
|
|
|
|
.into_iter()
|
|
|
|
|
.filter_map(|surface| {
|
|
|
|
|
layer_map
|
|
|
|
|
.layer_geometry(surface)
|
|
|
|
|
.map(|geo| (geo.loc, surface))
|
|
|
|
|
})
|
|
|
|
|
.flat_map(|(loc, surface)| {
|
|
|
|
|
AsRenderElements::<R>::render_elements::<WorkspaceRenderElement<R>>(
|
|
|
|
|
surface,
|
|
|
|
|
loc.to_physical_precise_round(output_scale),
|
|
|
|
|
Scale::from(output_scale),
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
lower
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// floating surfaces
|
|
|
|
|
render_elements.extend(
|
|
|
|
|
self.floating_layer
|
|
|
|
|
.render_output::<R>(output)?
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(WorkspaceRenderElement::from),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
//tiling surfaces
|
|
|
|
|
render_elements.extend(
|
|
|
|
|
self.tiling_layer
|
|
|
|
|
.render_output::<R>(output)?
|
|
|
|
|
.into_iter()
|
|
|
|
|
.map(WorkspaceRenderElement::from),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// bottom and background layer surfaces
|
|
|
|
|
{
|
|
|
|
|
render_elements.extend(
|
|
|
|
|
lower
|
|
|
|
|
.into_iter()
|
|
|
|
|
.filter_map(|surface| {
|
|
|
|
|
layer_map
|
|
|
|
|
.layer_geometry(surface)
|
|
|
|
|
.map(|geo| (geo.loc, surface))
|
|
|
|
|
})
|
|
|
|
|
.flat_map(|(loc, surface)| {
|
|
|
|
|
AsRenderElements::<R>::render_elements::<WorkspaceRenderElement<R>>(
|
|
|
|
|
surface,
|
|
|
|
|
loc.to_physical_precise_round(output_scale),
|
|
|
|
|
Scale::from(output_scale),
|
|
|
|
|
)
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(render_elements)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FocusStacks {
|
|
|
|
|
pub fn get<'a>(&'a self, seat: &Seat<State>) -> FocusStack<'a> {
|
|
|
|
|
FocusStack(self.0.get(seat))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_mut<'a>(&'a mut self, seat: &Seat<State>) -> FocusStackMut<'a> {
|
|
|
|
|
FocusStackMut(self.0.entry(seat.clone()).or_default())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct OutputNotMapped;
|
|
|
|
|
|
|
|
|
|
render_elements! {
|
|
|
|
|
pub WorkspaceRenderElement<R> where R: ImportAll;
|
|
|
|
|
Wayland=WaylandSurfaceRenderElement,
|
|
|
|
|
Floating=FloatingRenderElement<R>,
|
|
|
|
|
Tiling=TilingRenderElement<R>,
|
2022-03-24 20:32:31 +01:00
|
|
|
}
|