anvil: Implement wlr_layer_shell
This commit is contained in:
parent
84d3d6e609
commit
115403633b
|
@ -20,6 +20,7 @@ use smithay::{
|
|||
SurfaceAttributes, TraversalAction,
|
||||
},
|
||||
seat::CursorImageAttributes,
|
||||
shell::wlr_layer::Layer,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -241,6 +242,59 @@ where
|
|||
result
|
||||
}
|
||||
|
||||
pub fn draw_layers<R, E, F, T>(
|
||||
renderer: &mut R,
|
||||
frame: &mut F,
|
||||
window_map: &WindowMap,
|
||||
layer: Layer,
|
||||
output_rect: Rectangle<i32, Logical>,
|
||||
output_scale: f32,
|
||||
log: &::slog::Logger,
|
||||
) -> Result<(), SwapBuffersError>
|
||||
where
|
||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||
F: Frame<Error = E, TextureId = T>,
|
||||
E: std::error::Error + Into<SwapBuffersError>,
|
||||
T: Texture + 'static,
|
||||
{
|
||||
let mut result = Ok(());
|
||||
|
||||
window_map
|
||||
.layers
|
||||
.with_layers_from_bottom_to_top(&layer, |layer_surface| {
|
||||
// skip layers that do not overlap with a given output
|
||||
if !output_rect.overlaps(layer_surface.bbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut initial_place: Point<i32, Logical> = layer_surface.location;
|
||||
initial_place.x -= output_rect.loc.x;
|
||||
|
||||
if let Some(wl_surface) = layer_surface.surface.get_surface() {
|
||||
// this surface is a root of a subsurface tree that needs to be drawn
|
||||
if let Err(err) =
|
||||
draw_surface_tree(renderer, frame, wl_surface, initial_place, output_scale, log)
|
||||
{
|
||||
result = Err(err);
|
||||
}
|
||||
|
||||
window_map.with_child_popups(wl_surface, |popup| {
|
||||
let location = popup.location();
|
||||
let draw_location = initial_place + location;
|
||||
if let Some(wl_surface) = popup.get_surface() {
|
||||
if let Err(err) =
|
||||
draw_surface_tree(renderer, frame, wl_surface, draw_location, output_scale, log)
|
||||
{
|
||||
result = Err(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn draw_dnd_icon<R, E, F, T>(
|
||||
renderer: &mut R,
|
||||
frame: &mut F,
|
||||
|
|
|
@ -211,6 +211,11 @@ impl AnvilState<WinitData> {
|
|||
},
|
||||
crate::winit::OUTPUT_NAME,
|
||||
);
|
||||
|
||||
let output_mut = self.output_map.borrow();
|
||||
let output = output_mut.find_by_name(crate::winit::OUTPUT_NAME).unwrap();
|
||||
|
||||
self.window_map.borrow_mut().layers.arange_layers(output);
|
||||
}
|
||||
_ => {
|
||||
// other events are not handled in anvil (yet)
|
||||
|
|
|
@ -4,7 +4,10 @@ use smithay::{
|
|||
reexports::{
|
||||
wayland_protocols::xdg_shell::server::xdg_toplevel,
|
||||
wayland_server::{
|
||||
protocol::{wl_output, wl_surface::WlSurface},
|
||||
protocol::{
|
||||
wl_output,
|
||||
wl_surface::{self, WlSurface},
|
||||
},
|
||||
Display, Global, UserDataMap,
|
||||
},
|
||||
},
|
||||
|
@ -22,6 +25,7 @@ pub struct Output {
|
|||
output: output::Output,
|
||||
global: Option<Global<wl_output::WlOutput>>,
|
||||
surfaces: Vec<WlSurface>,
|
||||
layer_surfaces: RefCell<Vec<wl_surface::WlSurface>>,
|
||||
current_mode: Mode,
|
||||
scale: f32,
|
||||
output_scale: i32,
|
||||
|
@ -60,6 +64,7 @@ impl Output {
|
|||
output,
|
||||
location,
|
||||
surfaces: Vec::new(),
|
||||
layer_surfaces: Default::default(),
|
||||
current_mode: mode,
|
||||
scale,
|
||||
output_scale,
|
||||
|
@ -101,6 +106,16 @@ impl Output {
|
|||
pub fn current_mode(&self) -> Mode {
|
||||
self.current_mode
|
||||
}
|
||||
|
||||
/// Add a layer surface to this output
|
||||
pub fn add_layer_surface(&self, layer: wl_surface::WlSurface) {
|
||||
self.layer_surfaces.borrow_mut().push(layer);
|
||||
}
|
||||
|
||||
/// Get all layer surfaces assigned to this output
|
||||
pub fn layer_surfaces(&self) -> Vec<wl_surface::WlSurface> {
|
||||
self.layer_surfaces.borrow().iter().cloned().collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Output {
|
||||
|
@ -171,6 +186,7 @@ impl OutputMap {
|
|||
// and move them to the primary output
|
||||
let primary_output_location = self.with_primary().map(|o| o.location()).unwrap_or_default();
|
||||
let mut window_map = self.window_map.borrow_mut();
|
||||
|
||||
// TODO: This is a bit unfortunate, we save the windows in a temp vector
|
||||
// cause we can not call window_map.set_location within the closure.
|
||||
let mut windows_to_move = Vec::new();
|
||||
|
@ -218,6 +234,10 @@ impl OutputMap {
|
|||
for (window, location) in windows_to_move.drain(..) {
|
||||
window_map.set_location(&window, location);
|
||||
}
|
||||
|
||||
for output in self.outputs.iter() {
|
||||
window_map.layers.arange_layers(output);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add<N>(&mut self, name: N, physical: PhysicalProperties, mode: Mode) -> &Output
|
||||
|
@ -293,6 +313,15 @@ impl OutputMap {
|
|||
self.find(|o| o.output.owns(output))
|
||||
}
|
||||
|
||||
pub fn find_by_layer_surface(&self, surface: &wl_surface::WlSurface) -> Option<&Output> {
|
||||
self.find(|o| {
|
||||
o.layer_surfaces
|
||||
.borrow()
|
||||
.iter()
|
||||
.any(|s| s.as_ref().equals(surface.as_ref()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn find_by_name<N>(&self, name: N) -> Option<&Output>
|
||||
where
|
||||
N: AsRef<str>,
|
||||
|
@ -388,9 +417,10 @@ impl OutputMap {
|
|||
|
||||
pub fn refresh(&mut self) {
|
||||
// Clean-up dead surfaces
|
||||
self.outputs
|
||||
.iter_mut()
|
||||
.for_each(|o| o.surfaces.retain(|s| s.as_ref().is_alive()));
|
||||
self.outputs.iter_mut().for_each(|o| {
|
||||
o.surfaces.retain(|s| s.as_ref().is_alive());
|
||||
o.layer_surfaces.borrow_mut().retain(|s| s.as_ref().is_alive());
|
||||
});
|
||||
|
||||
let window_map = self.window_map.clone();
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ use smithay::{
|
|||
seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat},
|
||||
shell::{
|
||||
legacy::{wl_shell_init, ShellRequest, ShellState as WlShellState, ShellSurfaceKind},
|
||||
wlr_layer::{LayerShellRequest, LayerSurfaceAttributes},
|
||||
xdg::{
|
||||
xdg_shell_init, Configure, ShellState as XdgShellState, SurfaceCachedState,
|
||||
XdgPopupSurfaceRoleAttributes, XdgRequest, XdgToplevelSurfaceRoleAttributes,
|
||||
|
@ -329,7 +330,8 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
|
|||
move |surface, mut ddata| {
|
||||
let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();
|
||||
let window_map = anvil_state.window_map.as_ref();
|
||||
surface_commit(&surface, &*window_map)
|
||||
let output_map = anvil_state.output_map.as_ref();
|
||||
surface_commit(&surface, &*window_map, &*output_map)
|
||||
},
|
||||
log.clone(),
|
||||
);
|
||||
|
@ -822,6 +824,38 @@ pub fn init_shell<BackendData: 'static>(display: Rc<RefCell<Display>>, log: ::sl
|
|||
log.clone(),
|
||||
);
|
||||
|
||||
let layer_window_map = window_map.clone();
|
||||
let layer_output_map = output_map.clone();
|
||||
smithay::wayland::shell::wlr_layer::wlr_layer_shell_init(
|
||||
&mut *display.borrow_mut(),
|
||||
move |event, mut ddata| match event {
|
||||
LayerShellRequest::NewLayerSurface {
|
||||
surface,
|
||||
output,
|
||||
layer,
|
||||
..
|
||||
} => {
|
||||
let output_map = layer_output_map.borrow();
|
||||
let anvil_state = ddata.get::<AnvilState<BackendData>>().unwrap();
|
||||
|
||||
let output = output.and_then(|output| output_map.find_by_output(&output));
|
||||
let output = output.unwrap_or_else(|| {
|
||||
output_map
|
||||
.find_by_position(anvil_state.pointer_location.to_i32_round())
|
||||
.unwrap_or_else(|| output_map.with_primary().unwrap())
|
||||
});
|
||||
|
||||
if let Some(wl_surface) = surface.get_surface() {
|
||||
output.add_layer_surface(wl_surface.clone());
|
||||
|
||||
layer_window_map.borrow_mut().layers.insert(surface, layer);
|
||||
}
|
||||
}
|
||||
LayerShellRequest::AckConfigure { .. } => {}
|
||||
},
|
||||
log.clone(),
|
||||
);
|
||||
|
||||
ShellHandles {
|
||||
xdg_state: xdg_shell_state,
|
||||
wl_state: wl_shell_state,
|
||||
|
@ -937,7 +971,11 @@ impl SurfaceData {
|
|||
}
|
||||
}
|
||||
|
||||
fn surface_commit(surface: &wl_surface::WlSurface, window_map: &RefCell<WindowMap>) {
|
||||
fn surface_commit(
|
||||
surface: &wl_surface::WlSurface,
|
||||
window_map: &RefCell<WindowMap>,
|
||||
output_map: &RefCell<OutputMap>,
|
||||
) {
|
||||
#[cfg(feature = "xwayland")]
|
||||
super::xwayland::commit_hook(surface);
|
||||
|
||||
|
@ -1055,4 +1093,25 @@ fn surface_commit(surface: &wl_surface::WlSurface, window_map: &RefCell<WindowMa
|
|||
popup.send_configure();
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(layer) = window_map.layers.find(surface) {
|
||||
// send the initial configure if relevant
|
||||
let initial_configure_sent = with_states(surface, |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<Mutex<LayerSurfaceAttributes>>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
})
|
||||
.unwrap();
|
||||
if !initial_configure_sent {
|
||||
layer.surface.send_configure();
|
||||
}
|
||||
|
||||
if let Some(output) = output_map.borrow().find_by_layer_surface(surface) {
|
||||
window_map.layers.arange_layers(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ use smithay::{
|
|||
wayland::{
|
||||
output::{Mode, PhysicalProperties},
|
||||
seat::CursorImageStatus,
|
||||
shell::wlr_layer::Layer,
|
||||
},
|
||||
};
|
||||
#[cfg(feature = "egl")]
|
||||
|
@ -744,9 +745,34 @@ fn render_surface(
|
|||
Transform::Flipped180, // Scanout is rotated
|
||||
|renderer, frame| {
|
||||
frame.clear([0.8, 0.8, 0.9, 1.0])?;
|
||||
|
||||
for layer in [Layer::Background, Layer::Bottom] {
|
||||
draw_layers(
|
||||
renderer,
|
||||
frame,
|
||||
window_map,
|
||||
layer,
|
||||
output_geometry,
|
||||
output_scale,
|
||||
logger,
|
||||
)?;
|
||||
}
|
||||
|
||||
// draw the surfaces
|
||||
draw_windows(renderer, frame, window_map, output_geometry, output_scale, logger)?;
|
||||
|
||||
for layer in [Layer::Top, Layer::Overlay] {
|
||||
draw_layers(
|
||||
renderer,
|
||||
frame,
|
||||
window_map,
|
||||
layer,
|
||||
output_geometry,
|
||||
output_scale,
|
||||
logger,
|
||||
)?;
|
||||
}
|
||||
|
||||
// set cursor
|
||||
if output_geometry.to_f64().contains(pointer_location) {
|
||||
let (ptr_x, ptr_y) = pointer_location.into();
|
||||
|
|
|
@ -8,6 +8,7 @@ use smithay::{
|
|||
compositor::{with_states, with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
|
||||
shell::{
|
||||
legacy::ShellSurface,
|
||||
wlr_layer::Layer,
|
||||
xdg::{PopupSurface, SurfaceCachedState, ToplevelSurface, XdgPopupSurfaceRoleAttributes},
|
||||
},
|
||||
},
|
||||
|
@ -17,6 +18,9 @@ use crate::shell::SurfaceData;
|
|||
#[cfg(feature = "xwayland")]
|
||||
use crate::xwayland::X11Surface;
|
||||
|
||||
mod layer_map;
|
||||
pub use layer_map::{LayerMap, LayerSurface};
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum Kind {
|
||||
Xdg(ToplevelSurface),
|
||||
|
@ -242,6 +246,8 @@ pub struct Popup {
|
|||
pub struct WindowMap {
|
||||
windows: Vec<Window>,
|
||||
popups: Vec<Popup>,
|
||||
|
||||
pub layers: LayerMap,
|
||||
}
|
||||
|
||||
impl WindowMap {
|
||||
|
@ -268,11 +274,26 @@ impl WindowMap {
|
|||
&self,
|
||||
point: Point<f64, Logical>,
|
||||
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)> {
|
||||
if let Some(res) = self.layers.get_surface_under(&Layer::Overlay, point) {
|
||||
return Some(res);
|
||||
}
|
||||
if let Some(res) = self.layers.get_surface_under(&Layer::Top, point) {
|
||||
return Some(res);
|
||||
}
|
||||
|
||||
for w in &self.windows {
|
||||
if let Some(surface) = w.matching(point) {
|
||||
return Some(surface);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(res) = self.layers.get_surface_under(&Layer::Bottom, point) {
|
||||
return Some(res);
|
||||
}
|
||||
if let Some(res) = self.layers.get_surface_under(&Layer::Background, point) {
|
||||
return Some(res);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -330,6 +351,7 @@ impl WindowMap {
|
|||
pub fn refresh(&mut self) {
|
||||
self.windows.retain(|w| w.toplevel.alive());
|
||||
self.popups.retain(|p| p.popup.alive());
|
||||
self.layers.refresh();
|
||||
for w in &mut self.windows {
|
||||
w.self_update();
|
||||
}
|
||||
|
@ -404,5 +426,6 @@ impl WindowMap {
|
|||
for window in &self.windows {
|
||||
window.send_frame(time);
|
||||
}
|
||||
self.layers.send_frames(time);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
use std::cell::RefCell;
|
||||
|
||||
use smithay::{
|
||||
reexports::wayland_server::protocol::wl_surface,
|
||||
utils::{Logical, Point, Rectangle},
|
||||
wayland::{
|
||||
compositor::{with_states, with_surface_tree_downward, SubsurfaceCachedState, TraversalAction},
|
||||
shell::wlr_layer::{self, Anchor, LayerSurfaceCachedState},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{output_map::Output, shell::SurfaceData};
|
||||
|
||||
pub struct LayerSurface {
|
||||
pub surface: wlr_layer::LayerSurface,
|
||||
pub location: Point<i32, Logical>,
|
||||
pub bbox: Rectangle<i32, Logical>,
|
||||
pub layer: wlr_layer::Layer,
|
||||
}
|
||||
|
||||
impl LayerSurface {
|
||||
/// Finds the topmost surface under this point if any and returns it together with the location of this
|
||||
/// surface.
|
||||
fn matching(&self, point: Point<f64, Logical>) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)> {
|
||||
if !self.bbox.to_f64().contains(point) {
|
||||
return None;
|
||||
}
|
||||
// need to check more carefully
|
||||
let found = RefCell::new(None);
|
||||
if let Some(wl_surface) = self.surface.get_surface() {
|
||||
with_surface_tree_downward(
|
||||
wl_surface,
|
||||
self.location,
|
||||
|wl_surface, states, location| {
|
||||
let mut location = *location;
|
||||
let data = states.data_map.get::<RefCell<SurfaceData>>();
|
||||
|
||||
if states.role == Some("subsurface") {
|
||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||
location += current.location;
|
||||
}
|
||||
|
||||
let contains_the_point = data
|
||||
.map(|data| {
|
||||
data.borrow()
|
||||
.contains_point(&*states.cached_state.current(), point - location.to_f64())
|
||||
})
|
||||
.unwrap_or(false);
|
||||
if contains_the_point {
|
||||
*found.borrow_mut() = Some((wl_surface.clone(), location));
|
||||
}
|
||||
|
||||
TraversalAction::DoChildren(location)
|
||||
},
|
||||
|_, _, _| {},
|
||||
|_, _, _| {
|
||||
// only continue if the point is not found
|
||||
found.borrow().is_none()
|
||||
},
|
||||
);
|
||||
}
|
||||
found.into_inner()
|
||||
}
|
||||
|
||||
fn self_update(&mut self) {
|
||||
let mut bounding_box = Rectangle::from_loc_and_size(self.location, (0, 0));
|
||||
if let Some(wl_surface) = self.surface.get_surface() {
|
||||
with_surface_tree_downward(
|
||||
wl_surface,
|
||||
self.location,
|
||||
|_, states, &loc| {
|
||||
let mut loc = loc;
|
||||
let data = states.data_map.get::<RefCell<SurfaceData>>();
|
||||
|
||||
if let Some(size) = data.and_then(|d| d.borrow().size()) {
|
||||
if states.role == Some("subsurface") {
|
||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||
loc += current.location;
|
||||
}
|
||||
|
||||
// Update the bounding box.
|
||||
bounding_box = bounding_box.merge(Rectangle::from_loc_and_size(loc, size));
|
||||
|
||||
TraversalAction::DoChildren(loc)
|
||||
} else {
|
||||
// If the parent surface is unmapped, then the child surfaces are hidden as
|
||||
// well, no need to consider them here.
|
||||
TraversalAction::SkipChildren
|
||||
}
|
||||
},
|
||||
|_, _, _| {},
|
||||
|_, _, _| true,
|
||||
);
|
||||
}
|
||||
self.bbox = bounding_box;
|
||||
|
||||
if let Some(surface) = self.surface.get_surface() {
|
||||
self.layer = with_states(surface, |states| {
|
||||
let current = states.cached_state.current::<LayerSurfaceCachedState>();
|
||||
current.layer
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends the frame callback to all the subsurfaces in this
|
||||
/// window that requested it
|
||||
fn send_frame(&self, time: u32) {
|
||||
if let Some(wl_surface) = self.surface.get_surface() {
|
||||
with_surface_tree_downward(
|
||||
wl_surface,
|
||||
(),
|
||||
|_, _, &()| TraversalAction::DoChildren(()),
|
||||
|_, states, &()| {
|
||||
// the surface may not have any user_data if it is a subsurface and has not
|
||||
// yet been commited
|
||||
SurfaceData::send_frame(&mut *states.cached_state.current(), time)
|
||||
},
|
||||
|_, _, &()| true,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LayerMap {
|
||||
surfaces: Vec<LayerSurface>,
|
||||
}
|
||||
|
||||
impl LayerMap {
|
||||
pub fn insert(&mut self, surface: wlr_layer::LayerSurface, layer: wlr_layer::Layer) {
|
||||
let mut layer = LayerSurface {
|
||||
location: Default::default(),
|
||||
bbox: Rectangle::default(),
|
||||
surface,
|
||||
layer,
|
||||
};
|
||||
layer.self_update();
|
||||
self.surfaces.insert(0, layer);
|
||||
}
|
||||
|
||||
pub fn get_surface_under(
|
||||
&self,
|
||||
layer: &wlr_layer::Layer,
|
||||
point: Point<f64, Logical>,
|
||||
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)> {
|
||||
for l in self.surfaces.iter().filter(|s| &s.layer == layer) {
|
||||
if let Some(surface) = l.matching(point) {
|
||||
return Some(surface);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn with_layers_from_bottom_to_top<Func>(&self, layer: &wlr_layer::Layer, mut f: Func)
|
||||
where
|
||||
Func: FnMut(&LayerSurface),
|
||||
{
|
||||
for l in self.surfaces.iter().filter(|s| &s.layer == layer).rev() {
|
||||
f(l)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn refresh(&mut self) {
|
||||
self.surfaces.retain(|l| l.surface.alive());
|
||||
|
||||
for l in self.surfaces.iter_mut() {
|
||||
l.self_update();
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the layer corresponding to the given `WlSurface`.
|
||||
pub fn find(&self, surface: &wl_surface::WlSurface) -> Option<&LayerSurface> {
|
||||
self.surfaces.iter().find_map(|l| {
|
||||
if l.surface
|
||||
.get_surface()
|
||||
.map(|s| s.as_ref().equals(surface.as_ref()))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
Some(l)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn arange_layers(&mut self, output: &Output) {
|
||||
let output_rect = output.geometry();
|
||||
|
||||
// Get all layer surfaces assigned to this output
|
||||
let surfaces: Vec<_> = output
|
||||
.layer_surfaces()
|
||||
.into_iter()
|
||||
.map(|s| s.as_ref().clone())
|
||||
.collect();
|
||||
|
||||
// Find layers for this output
|
||||
let filtered_layers = self.surfaces.iter_mut().filter(|l| {
|
||||
l.surface
|
||||
.get_surface()
|
||||
.map(|s| surfaces.contains(s.as_ref()))
|
||||
.unwrap_or(false)
|
||||
});
|
||||
|
||||
for layer in filtered_layers {
|
||||
let surface = if let Some(surface) = layer.surface.get_surface() {
|
||||
surface
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let data = with_states(surface, |states| {
|
||||
*states.cached_state.current::<LayerSurfaceCachedState>()
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let x = if data.size.w == 0 || data.anchor.contains(Anchor::LEFT) {
|
||||
output_rect.loc.x
|
||||
} else if data.anchor.contains(Anchor::RIGHT) {
|
||||
output_rect.loc.x + (output_rect.size.w - data.size.w)
|
||||
} else {
|
||||
output_rect.loc.x + ((output_rect.size.w / 2) - (data.size.w / 2))
|
||||
};
|
||||
|
||||
let y = if data.size.h == 0 || data.anchor.contains(Anchor::TOP) {
|
||||
output_rect.loc.y
|
||||
} else if data.anchor.contains(Anchor::BOTTOM) {
|
||||
output_rect.loc.y + (output_rect.size.h - data.size.h)
|
||||
} else {
|
||||
output_rect.loc.y + ((output_rect.size.h / 2) - (data.size.h / 2))
|
||||
};
|
||||
|
||||
let location: Point<i32, Logical> = (x, y).into();
|
||||
|
||||
layer
|
||||
.surface
|
||||
.with_pending_state(|state| {
|
||||
state.size = Some(output_rect.size);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
layer.surface.send_configure();
|
||||
|
||||
layer.location = location;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_frames(&self, time: u32) {
|
||||
for layer in &self.surfaces {
|
||||
layer.send_frame(time);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ use smithay::{
|
|||
wayland::{
|
||||
output::{Mode, PhysicalProperties},
|
||||
seat::CursorImageStatus,
|
||||
shell::wlr_layer::Layer,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -144,15 +145,34 @@ pub fn run_winit(log: Logger) {
|
|||
.render(|renderer, frame| {
|
||||
frame.clear([0.8, 0.8, 0.9, 1.0])?;
|
||||
|
||||
// draw the windows
|
||||
draw_windows(
|
||||
let window_map = &*state.window_map.borrow();
|
||||
|
||||
for layer in [Layer::Background, Layer::Bottom] {
|
||||
draw_layers(
|
||||
renderer,
|
||||
frame,
|
||||
&*state.window_map.borrow(),
|
||||
window_map,
|
||||
layer,
|
||||
output_geometry,
|
||||
output_scale,
|
||||
&log,
|
||||
)?;
|
||||
}
|
||||
|
||||
// draw the windows
|
||||
draw_windows(renderer, frame, window_map, output_geometry, output_scale, &log)?;
|
||||
|
||||
for layer in [Layer::Top, Layer::Overlay] {
|
||||
draw_layers(
|
||||
renderer,
|
||||
frame,
|
||||
window_map,
|
||||
layer,
|
||||
output_geometry,
|
||||
output_scale,
|
||||
&log,
|
||||
)?;
|
||||
}
|
||||
|
||||
let (x, y) = state.pointer_location.into();
|
||||
// draw the dnd icon if any
|
||||
|
|
Loading…
Reference in New Issue