1
0
Fork 0
forked from wry/wry

layer-shell: implement exclusive zones

This commit is contained in:
Julian Orth 2024-05-07 20:19:41 +02:00
parent 8dc31110b9
commit 8a91c070be
9 changed files with 300 additions and 90 deletions

View file

@ -18,8 +18,8 @@ use {
},
wl_surface::{
ext_session_lock_surface_v1::ExtSessionLockSurfaceV1,
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, SurfaceSendPreferredScaleVisitor,
SurfaceSendPreferredTransformVisitor,
zwlr_layer_surface_v1::{ExclusiveSize, ZwlrLayerSurfaceV1},
SurfaceSendPreferredScaleVisitor, SurfaceSendPreferredTransformVisitor,
},
zwlr_layer_shell_v1::{BACKGROUND, BOTTOM, OVERLAY, TOP},
zwlr_screencopy_frame_v1::ZwlrScreencopyFrameV1,
@ -47,7 +47,7 @@ use {
std::{
cell::{Cell, RefCell},
fmt::{Debug, Formatter},
ops::{Deref, Sub},
ops::Deref,
rc::Rc,
},
};
@ -61,6 +61,10 @@ pub struct OutputNode {
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
pub seat_state: NodeSeatState,
pub layers: [LinkedList<Rc<ZwlrLayerSurfaceV1>>; 4],
pub exclusive_zones: Cell<ExclusiveSize>,
pub workspace_rect: Cell<Rect>,
pub non_exclusive_rect: Cell<Rect>,
pub non_exclusive_rect_rel: Cell<Rect>,
pub render_data: RefCell<OutputRenderData>,
pub state: Rc<State>,
pub is_dummy: bool,
@ -94,6 +98,26 @@ pub async fn output_render_data(state: Rc<State>) {
}
impl OutputNode {
pub fn update_exclusive_zones(self: &Rc<Self>) {
let mut exclusive = ExclusiveSize::default();
for layer in &self.layers {
for surface in layer.iter() {
exclusive = exclusive.max(&surface.exclusive_size());
}
}
if self.exclusive_zones.replace(exclusive) != exclusive {
self.update_rects();
for layer in &self.layers {
for surface in layer.iter() {
surface.exclusive_zones_changed();
}
}
if let Some(c) = self.workspace.get() {
c.change_extents(&self.workspace_rect.get());
}
}
}
pub fn add_screencast(&self, sc: &Rc<JayScreencast>) {
self.screencasts.set((sc.client.id, sc.id), sc.clone());
self.screencast_changed();
@ -222,9 +246,9 @@ impl OutputNode {
}
pub fn on_spaces_changed(self: &Rc<Self>) {
self.schedule_update_render_data();
self.update_rects();
if let Some(c) = self.workspace.get() {
c.change_extents(&self.workspace_rect());
c.change_extents(&self.workspace_rect.get());
}
}
@ -281,7 +305,7 @@ impl OutputNode {
texture_height = (th as f64 * scale).round() as _;
}
let active_id = self.workspace.get().map(|w| w.id);
let output_width = self.global.pos.get().width();
let output_width = self.non_exclusive_rect.get().width();
rd.underline = Rect::new_sized(0, th, output_width, 1).unwrap();
for ws in self.workspaces.iter() {
let old_tex = ws.title_texture.take();
@ -430,7 +454,7 @@ impl OutputNode {
if let Some(fs) = ws.fullscreen.get() {
fs.tl_change_extents(&self.global.pos.get());
}
ws.change_extents(&self.workspace_rect());
ws.change_extents(&self.workspace_rect.get());
for seat in seats {
ws.clone().node_do_focus(&seat, Direction::Unspecified);
}
@ -478,16 +502,29 @@ impl OutputNode {
ws
}
fn workspace_rect(&self) -> Rect {
pub fn update_rects(self: &Rc<Self>) {
let rect = self.global.pos.get();
let th = self.state.theme.sizes.title_height.get();
Rect::new_sized(
rect.x1(),
rect.y1() + th + 1,
rect.width(),
rect.height().sub(th + 1).max(0),
)
.unwrap()
let exclusive = self.exclusive_zones.get();
let y1 = rect.y1() + exclusive.top;
let x2 = rect.x2() - exclusive.right;
let y2 = rect.y2() - exclusive.bottom;
let x1 = rect.x1() + exclusive.left;
let width = (x2 - x1).max(0);
let height = (y2 - y1).max(0);
self.non_exclusive_rect
.set(Rect::new_sized_unchecked(x1, y1, width, height));
self.non_exclusive_rect_rel.set(Rect::new_sized_unchecked(
exclusive.left,
exclusive.top,
width,
height,
));
let y1 = y1 + th + 1;
let height = (y2 - y1).max(0);
self.workspace_rect
.set(Rect::new_sized_unchecked(x1, y1, width, height));
self.schedule_update_render_data();
}
pub fn set_position(self: &Rc<Self>, x: i32, y: i32) {
@ -546,7 +583,7 @@ impl OutputNode {
self.global.persistent.pos.set((rect.x1(), rect.y1()));
self.global.pos.set(*rect);
self.state.root.update_extents();
self.schedule_update_render_data();
self.update_rects();
if let Some(ls) = self.lock_surface.get() {
ls.change_extents(*rect);
}
@ -554,7 +591,7 @@ impl OutputNode {
if let Some(fs) = c.fullscreen.get() {
fs.tl_change_extents(rect);
}
c.change_extents(&self.workspace_rect());
c.change_extents(&self.workspace_rect.get());
}
for layer in &self.layers {
for surface in layer.iter() {
@ -657,6 +694,7 @@ impl OutputNode {
Some(p) => p,
_ => return,
};
let (x, y) = self.non_exclusive_rect_rel.get().translate(x, y);
if y >= self.state.theme.sizes.title_height.get() {
return;
}
@ -844,21 +882,25 @@ impl Node for OutputNode {
fs.tl_as_node().node_find_tree_at(x, y, tree, usecase)
} else {
let mut search_layers = true;
if y < bar_height {
search_layers = false;
} else {
if let Some(ws) = self.workspace.get() {
let y = y - bar_height;
let len = tree.len();
tree.push(FoundNode {
node: ws.clone(),
x,
y,
});
match ws.node_find_tree_at(x, y, tree, usecase) {
FindTreeResult::AcceptsInput => search_layers = false,
FindTreeResult::Other => {
tree.truncate(len);
let non_exclusive_rect = self.non_exclusive_rect_rel.get();
if non_exclusive_rect.contains(x, y) {
let (x, y) = non_exclusive_rect.translate(x, y);
if y < bar_height {
search_layers = false;
} else {
if let Some(ws) = self.workspace.get() {
let y = y - bar_height;
let len = tree.len();
tree.push(FoundNode {
node: ws.clone(),
x,
y,
});
match ws.node_find_tree_at(x, y, tree, usecase) {
FindTreeResult::AcceptsInput => search_layers = false,
FindTreeResult::Other => {
tree.truncate(len);
}
}
}
}