1
0
Fork 0
forked from wry/wry

autocommit 2022-02-21 23:21:13 CET

This commit is contained in:
Julian Orth 2022-02-21 23:21:13 +01:00
parent 1cbc7a6445
commit 145d1c15b7
31 changed files with 1455 additions and 252 deletions

View file

@ -663,11 +663,8 @@ fn write_message<W: Write>(f: &mut W, obj: &BStr, message: &Message) -> Result<(
writeln!(f, " fn id(&self) -> ObjectId {{")?; writeln!(f, " fn id(&self) -> ObjectId {{")?;
writeln!(f, " self.self_id.into()")?; writeln!(f, " self.self_id.into()")?;
writeln!(f, " }}")?; writeln!(f, " }}")?;
writeln!( writeln!(f, " fn interface(&self) -> Interface {{")?;
f, writeln!(f, " {}", obj)?;
" fn interface(&self) -> crate::object::Interface {{"
)?;
writeln!(f, " crate::object::Interface::{}", obj)?;
writeln!(f, " }}")?; writeln!(f, " }}")?;
writeln!(f, " }}")?; writeln!(f, " }}")?;
Ok(()) Ok(())
@ -681,6 +678,12 @@ fn write_file<W: Write>(f: &mut W, file: &DirEntry) -> Result<()> {
let camel_obj_name = to_camel(obj_name); let camel_obj_name = to_camel(obj_name);
writeln!(f)?; writeln!(f)?;
writeln!(f, "id!({}Id);", camel_obj_name)?; writeln!(f, "id!({}Id);", camel_obj_name)?;
writeln!(f)?;
writeln!(
f,
"pub const {}: Interface = Interface(\"{}\");",
camel_obj_name, obj_name
)?;
let contents = std::fs::read(file.path())?; let contents = std::fs::read(file.path())?;
let messages = parse_messages(&contents)?; let messages = parse_messages(&contents)?;
if messages.is_empty() { if messages.is_empty() {
@ -703,7 +706,7 @@ pub fn main() -> Result<()> {
writeln!(f, "use bstr::BStr;")?; writeln!(f, "use bstr::BStr;")?;
writeln!(f, "use crate::fixed::Fixed;")?; writeln!(f, "use crate::fixed::Fixed;")?;
writeln!(f, "use crate::client::{{EventFormatter, RequestParser}};")?; writeln!(f, "use crate::client::{{EventFormatter, RequestParser}};")?;
writeln!(f, "use crate::object::ObjectId;")?; writeln!(f, "use crate::object::{{ObjectId, Interface}};")?;
writeln!( writeln!(
f, f,
"use crate::utils::buffd::{{MsgFormatter, MsgParser, MsgParserError}};" "use crate::utils::buffd::{{MsgFormatter, MsgParser, MsgParserError}};"

View file

@ -3,6 +3,7 @@ use crate::ifs::ipc::wl_data_source::WlDataSource;
use crate::ifs::ipc::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1; use crate::ifs::ipc::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1;
use crate::ifs::wl_buffer::WlBuffer; use crate::ifs::wl_buffer::WlBuffer;
use crate::ifs::wl_display::WlDisplay; use crate::ifs::wl_display::WlDisplay;
use crate::ifs::wl_output::WlOutput;
use crate::ifs::wl_region::WlRegion; use crate::ifs::wl_region::WlRegion;
use crate::ifs::wl_registry::WlRegistry; use crate::ifs::wl_registry::WlRegistry;
use crate::ifs::wl_seat::WlSeat; use crate::ifs::wl_seat::WlSeat;
@ -16,8 +17,8 @@ use crate::tree::Node;
use crate::utils::clonecell::CloneCell; use crate::utils::clonecell::CloneCell;
use crate::utils::copyhashmap::CopyHashMap; use crate::utils::copyhashmap::CopyHashMap;
use crate::wire::{ use crate::wire::{
WlBufferId, WlDataSourceId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId, WlBufferId, WlDataSourceId, WlOutputId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId,
XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwpPrimarySelectionSourceV1Id, XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwpPrimarySelectionSourceV1Id,
}; };
use ahash::AHashMap; use ahash::AHashMap;
use std::cell::{RefCell, RefMut}; use std::cell::{RefCell, RefMut};
@ -29,6 +30,7 @@ pub struct Objects {
pub display: CloneCell<Option<Rc<WlDisplay>>>, pub display: CloneCell<Option<Rc<WlDisplay>>>,
registry: CopyHashMap<ObjectId, Rc<dyn Object>>, registry: CopyHashMap<ObjectId, Rc<dyn Object>>,
registries: CopyHashMap<WlRegistryId, Rc<WlRegistry>>, registries: CopyHashMap<WlRegistryId, Rc<WlRegistry>>,
pub outputs: CopyHashMap<WlOutputId, Rc<WlOutput>>,
pub surfaces: CopyHashMap<WlSurfaceId, Rc<WlSurface>>, pub surfaces: CopyHashMap<WlSurfaceId, Rc<WlSurface>>,
pub xdg_surfaces: CopyHashMap<XdgSurfaceId, Rc<XdgSurface>>, pub xdg_surfaces: CopyHashMap<XdgSurfaceId, Rc<XdgSurface>>,
pub xdg_toplevel: CopyHashMap<XdgToplevelId, Rc<XdgToplevel>>, pub xdg_toplevel: CopyHashMap<XdgToplevelId, Rc<XdgToplevel>>,
@ -52,6 +54,7 @@ impl Objects {
display: CloneCell::new(None), display: CloneCell::new(None),
registry: Default::default(), registry: Default::default(),
registries: Default::default(), registries: Default::default(),
outputs: Default::default(),
surfaces: Default::default(), surfaces: Default::default(),
xdg_surfaces: Default::default(), xdg_surfaces: Default::default(),
xdg_toplevel: Default::default(), xdg_toplevel: Default::default(),
@ -83,6 +86,7 @@ impl Objects {
} }
self.display.set(None); self.display.set(None);
self.registries.clear(); self.registries.clear();
self.outputs.clear();
self.surfaces.clear(); self.surfaces.clear();
self.xdg_surfaces.clear(); self.xdg_surfaces.clear();
self.wl_data_source.clear(); self.wl_data_source.clear();

View file

@ -6,6 +6,7 @@ use crate::ifs::wl_drm::WlDrmGlobal;
use crate::ifs::wl_output::WlOutputGlobal; use crate::ifs::wl_output::WlOutputGlobal;
use crate::ifs::wl_registry::WlRegistry; use crate::ifs::wl_registry::WlRegistry;
use crate::ifs::wl_seat::WlSeatGlobal; use crate::ifs::wl_seat::WlSeatGlobal;
use crate::ifs::zwlr_layer_shell_v1::ZwlrLayerShellV1Global;
use crate::object::{Interface, ObjectId}; use crate::object::{Interface, ObjectId};
use crate::utils::copyhashmap::CopyHashMap; use crate::utils::copyhashmap::CopyHashMap;
use crate::{ use crate::{
@ -18,6 +19,7 @@ use std::error::Error;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use crate::ifs::zxdg_output_manager_v1::ZxdgOutputManagerV1Global;
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum GlobalsError { pub enum GlobalsError {
@ -103,6 +105,8 @@ impl Globals {
add_singleton!(ZxdgDecorationManagerV1Global); add_singleton!(ZxdgDecorationManagerV1Global);
add_singleton!(OrgKdeKwinServerDecorationManagerGlobal); add_singleton!(OrgKdeKwinServerDecorationManagerGlobal);
add_singleton!(ZwpPrimarySelectionDeviceManagerV1Global); add_singleton!(ZwpPrimarySelectionDeviceManagerV1Global);
add_singleton!(ZwlrLayerShellV1Global);
add_singleton!(ZxdgOutputManagerV1Global);
slf slf
} }

View file

@ -16,7 +16,10 @@ pub mod wl_subcompositor;
pub mod wl_surface; pub mod wl_surface;
pub mod xdg_positioner; pub mod xdg_positioner;
pub mod xdg_wm_base; pub mod xdg_wm_base;
pub mod zwlr_layer_shell_v1;
pub mod zwp_linux_buffer_params_v1; pub mod zwp_linux_buffer_params_v1;
pub mod zwp_linux_dmabuf_v1; pub mod zwp_linux_dmabuf_v1;
pub mod zxdg_decoration_manager_v1; pub mod zxdg_decoration_manager_v1;
pub mod zxdg_toplevel_decoration_v1; pub mod zxdg_toplevel_decoration_v1;
pub mod zxdg_output_manager_v1;
pub mod zxdg_output_v1;

View file

@ -6,12 +6,17 @@ use crate::object::Object;
use crate::utils::buffd::MsgParser; use crate::utils::buffd::MsgParser;
use crate::utils::buffd::MsgParserError; use crate::utils::buffd::MsgParserError;
use crate::wire::wl_output::*; use crate::wire::wl_output::*;
use crate::wire::WlOutputId; use crate::wire::{WlOutputId, ZxdgOutputV1Id};
use ahash::AHashMap; use ahash::AHashMap;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use crate::CloneCell;
use crate::ifs::zxdg_output_v1::ZxdgOutputV1;
use crate::rect::Rect;
use crate::tree::OutputNode;
use crate::utils::copyhashmap::CopyHashMap;
const SP_UNKNOWN: i32 = 0; const SP_UNKNOWN: i32 = 0;
#[allow(dead_code)] #[allow(dead_code)]
@ -48,10 +53,8 @@ const MODE_PREFERRED: u32 = 2;
pub struct WlOutputGlobal { pub struct WlOutputGlobal {
name: GlobalName, name: GlobalName,
output: Rc<dyn Output>, output: Rc<dyn Output>,
pub x: Cell<i32>, pos: Cell<Rect>,
pub y: Cell<i32>, pub node: CloneCell<Option<Rc<OutputNode>>>,
width: Cell<i32>,
height: Cell<i32>,
pub bindings: RefCell<AHashMap<ClientId, AHashMap<WlOutputId, Rc<WlOutput>>>>, pub bindings: RefCell<AHashMap<ClientId, AHashMap<WlOutputId, Rc<WlOutput>>>>,
} }
@ -60,23 +63,27 @@ impl WlOutputGlobal {
Self { Self {
name, name,
output: output.clone(), output: output.clone(),
x: Cell::new(0), pos: Cell::new(Rect::new_sized(0, 0, output.width(), output.height()).unwrap()),
y: Cell::new(0), node: Default::default(),
width: Cell::new(output.width()),
height: Cell::new(output.height()),
bindings: Default::default(), bindings: Default::default(),
} }
} }
pub fn position(&self) -> Rect {
self.pos.get()
}
pub fn update_properties(&self) { pub fn update_properties(&self) {
let width = self.output.width(); let width = self.output.width();
let height = self.output.height(); let height = self.output.height();
let mut changed = false; let pos = self.pos.get();
changed |= self.width.replace(width) != width; let old_width = pos.width();
changed |= self.height.replace(height) != height; let old_height = pos.height();
let changed = old_width != width || old_height != height;
if changed { if changed {
self.pos.set(Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap());
let bindings = self.bindings.borrow_mut(); let bindings = self.bindings.borrow_mut();
for binding in bindings.values() { for binding in bindings.values() {
for binding in binding.values() { for binding in binding.values() {
@ -85,6 +92,10 @@ impl WlOutputGlobal {
binding.send_scale(); binding.send_scale();
binding.send_done(); binding.send_done();
binding.client.flush(); binding.client.flush();
let xdg = binding.xdg_outputs.lock();
for xdg in xdg.values() {
xdg.send_updates();
}
} }
} }
} }
@ -99,6 +110,7 @@ impl WlOutputGlobal {
let obj = Rc::new(WlOutput { let obj = Rc::new(WlOutput {
global: self.clone(), global: self.clone(),
id, id,
xdg_outputs: Default::default(),
client: client.clone(), client: client.clone(),
version, version,
tracker: Default::default(), tracker: Default::default(),
@ -141,10 +153,11 @@ impl Global for WlOutputGlobal {
dedicated_add_global!(WlOutputGlobal, outputs); dedicated_add_global!(WlOutputGlobal, outputs);
pub struct WlOutput { pub struct WlOutput {
global: Rc<WlOutputGlobal>, pub global: Rc<WlOutputGlobal>,
pub id: WlOutputId, pub id: WlOutputId,
pub xdg_outputs: CopyHashMap<ZxdgOutputV1Id, Rc<ZxdgOutputV1>>,
client: Rc<Client>, client: Rc<Client>,
version: u32, pub version: u32,
tracker: Tracker<Self>, tracker: Tracker<Self>,
} }
@ -153,12 +166,13 @@ pub const SEND_SCALE_SINCE: u32 = 2;
impl WlOutput { impl WlOutput {
fn send_geometry(&self) { fn send_geometry(&self) {
let pos = self.global.pos.get();
let event = Geometry { let event = Geometry {
self_id: self.id, self_id: self.id,
x: 0, x: pos.x1(),
y: 0, y: pos.y1(),
physical_width: self.global.width.get() as _, physical_width: pos.width(),
physical_height: self.global.height.get() as _, physical_height: pos.height(),
subpixel: SP_UNKNOWN, subpixel: SP_UNKNOWN,
make: "i4", make: "i4",
model: "i4", model: "i4",
@ -168,11 +182,12 @@ impl WlOutput {
} }
fn send_mode(&self) { fn send_mode(&self) {
let pos = self.global.pos.get();
let event = Mode { let event = Mode {
self_id: self.id, self_id: self.id,
flags: MODE_CURRENT, flags: MODE_CURRENT,
width: self.global.width.get() as _, width: pos.width(),
height: self.global.height.get() as _, height: pos.height(),
refresh: 60_000_000, refresh: 60_000_000,
}; };
self.client.event(event); self.client.event(event);
@ -186,7 +201,7 @@ impl WlOutput {
self.client.event(event); self.client.event(event);
} }
fn send_done(&self) { pub fn send_done(&self) {
let event = Done { self_id: self.id }; let event = Done { self_id: self.id };
self.client.event(event); self.client.event(event);
} }
@ -202,6 +217,7 @@ impl WlOutput {
fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> { fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> {
let _req: Release = self.client.parse(self, parser)?; let _req: Release = self.client.parse(self, parser)?;
self.xdg_outputs.clear();
self.remove_binding(); self.remove_binding();
self.client.remove_obj(self)?; self.client.remove_obj(self)?;
Ok(()) Ok(())
@ -224,11 +240,12 @@ impl Object for WlOutput {
} }
fn break_loops(&self) { fn break_loops(&self) {
self.xdg_outputs.clear();
self.remove_binding(); self.remove_binding();
} }
} }
simple_add_obj!(WlOutput); dedicated_add_obj!(WlOutput, WlOutputId, outputs);
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum WlOutputError { pub enum WlOutputError {

View file

@ -3,6 +3,7 @@ mod pointer_owner;
pub mod wl_keyboard; pub mod wl_keyboard;
pub mod wl_pointer; pub mod wl_pointer;
pub mod wl_touch; pub mod wl_touch;
mod kb_owner;
use crate::async_engine::SpawnedFuture; use crate::async_engine::SpawnedFuture;
use crate::client::{Client, ClientError, ClientId}; use crate::client::{Client, ClientError, ClientId};
@ -43,10 +44,12 @@ use i4config::Direction;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::mem; use std::mem;
use std::ops::DerefMut; use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use uapi::{c, Errno, OwnedFd}; use uapi::{c, Errno, OwnedFd};
use crate::ifs::wl_output::{WlOutputGlobal};
use crate::ifs::wl_seat::kb_owner::KbOwnerHolder;
const POINTER: u32 = 1; const POINTER: u32 = 1;
const KEYBOARD: u32 = 2; const KEYBOARD: u32 = 2;
@ -112,6 +115,7 @@ pub struct WlSeatGlobal {
selection: CloneCell<Option<Rc<WlDataSource>>>, selection: CloneCell<Option<Rc<WlDataSource>>>,
primary_selection: CloneCell<Option<Rc<ZwpPrimarySelectionSourceV1>>>, primary_selection: CloneCell<Option<Rc<ZwpPrimarySelectionSourceV1>>>,
pointer_owner: PointerOwnerHolder, pointer_owner: PointerOwnerHolder,
kb_owner: KbOwnerHolder,
dropped_dnd: RefCell<Option<DroppedDnd>>, dropped_dnd: RefCell<Option<DroppedDnd>>,
shortcuts: CopyHashMap<(u32, u32), Modifiers>, shortcuts: CopyHashMap<(u32, u32), Modifiers>,
queue_link: Cell<Option<LinkedNode<Rc<Self>>>>, queue_link: Cell<Option<LinkedNode<Rc<Self>>>>,
@ -146,6 +150,7 @@ impl WlSeatGlobal {
selection: Default::default(), selection: Default::default(),
primary_selection: Default::default(), primary_selection: Default::default(),
pointer_owner: Default::default(), pointer_owner: Default::default(),
kb_owner: Default::default(),
dropped_dnd: RefCell::new(None), dropped_dnd: RefCell::new(None),
shortcuts: Default::default(), shortcuts: Default::default(),
queue_link: Cell::new(None), queue_link: Cell::new(None),
@ -162,6 +167,17 @@ impl WlSeatGlobal {
slf slf
} }
pub fn get_output(&self) -> Option<Rc<WlOutputGlobal>> {
let ps = self.pointer_stack.borrow_mut();
for node in ps.deref() {
if node.is_output() {
let on = node.clone().into_output().unwrap();
return Some(on.global.clone());
}
}
None
}
pub fn mark_last_active(self: &Rc<Self>) { pub fn mark_last_active(self: &Rc<Self>) {
self.queue_link self.queue_link
.set(Some(self.state.seat_queue.add_last(self.clone()))); .set(Some(self.state.seat_queue.add_last(self.clone())));

View file

@ -75,6 +75,22 @@ impl NodeSeatState {
self.kb_foci.len() > 0 self.kb_foci.len() > 0
} }
pub fn release_kb_grab(&self) {
for (_, seat) in &self.kb_foci {
seat.ungrab_kb();
}
}
pub fn release_kb_focus(&self) {
while let Some((_, seat)) = self.kb_foci.pop() {
seat.ungrab_kb();
seat.keyboard_node.set(seat.state.root.clone());
if let Some(tl) = seat.toplevel_focus_history.last() {
seat.focus_xdg_surface(&tl.xdg);
}
}
}
pub fn destroy_node(&self, node: &dyn Node) { pub fn destroy_node(&self, node: &dyn Node) {
while let Some((_, seat)) = self.grabs.pop() { while let Some((_, seat)) = self.grabs.pop() {
seat.pointer_owner.revert_to_default(&seat); seat.pointer_owner.revert_to_default(&seat);
@ -94,12 +110,7 @@ impl NodeSeatState {
} }
seat.state.tree_changed(); seat.state.tree_changed();
} }
while let Some((_, seat)) = self.kb_foci.pop() { self.release_kb_focus();
seat.keyboard_node.set(seat.state.root.clone());
if let Some(tl) = seat.toplevel_focus_history.last() {
seat.focus_xdg_surface(&tl.xdg);
}
}
} }
} }
@ -124,8 +135,9 @@ impl WlSeatGlobal {
Some(o) => o, Some(o) => o,
_ => return, _ => return,
}; };
x += Fixed::from_int(output.x.get()); let pos = output.position();
y += Fixed::from_int(output.y.get()); x += Fixed::from_int(pos.x1());
y += Fixed::from_int(pos.y1());
self.set_new_position(x, y); self.set_new_position(x, y);
} }
@ -216,21 +228,16 @@ impl WlSeatGlobal {
self.focus_node(xdg.focus_surface(self)); self.focus_node(xdg.focus_surface(self));
} }
pub fn focus_node(self: &Rc<Self>, node: Rc<dyn Node>) { fn ungrab_kb(self: &Rc<Self>) {
let old = self.keyboard_node.get(); self.kb_owner.ungrab(self);
if old.id() == node.id() { }
return;
}
old.unfocus(self);
if old.seat_state().unfocus(self) {
old.active_changed(false);
}
if node.seat_state().focus(self) { pub fn grab(self: &Rc<Self>, node: Rc<dyn Node>) {
node.active_changed(true); self.kb_owner.grab(self, node);
} }
node.clone().focus(self);
self.keyboard_node.set(node.clone()); pub fn focus_node(self: &Rc<Self>, node: Rc<dyn Node>) {
self.kb_owner.set_kb_node(self, node);
} }
fn offer_selection<T: ipc::Vtable>( fn offer_selection<T: ipc::Vtable>(
@ -380,7 +387,7 @@ impl WlSeatGlobal {
let serial = self.serial.fetch_add(1); let serial = self.serial.fetch_add(1);
self.surface_pointer_event(0, surface, |p| p.send_button(serial, 0, button, state)); self.surface_pointer_event(0, surface, |p| p.send_button(serial, 0, button, state));
self.surface_pointer_frame(surface); self.surface_pointer_frame(surface);
if pressed && surface.belongs_to_toplevel() { if pressed && surface.accepts_kb_focus() {
self.focus_node(surface.clone()); self.focus_node(surface.clone());
} }
} }

View file

@ -0,0 +1,85 @@
use std::rc::Rc;
use crate::CloneCell;
use crate::ifs::wl_seat::WlSeatGlobal;
use crate::tree::Node;
pub struct KbOwnerHolder {
default: Rc<DefaultKbOwner>,
owner: CloneCell<Rc<dyn KbOwner>>,
}
impl Default for KbOwnerHolder {
fn default() -> Self {
Self {
default: Rc::new(DefaultKbOwner),
owner: CloneCell::new(Rc::new(DefaultKbOwner)),
}
}
}
impl KbOwnerHolder {
pub fn grab(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>) -> bool {
self.owner.get().grab(seat, node)
}
pub fn ungrab(&self, seat: &Rc<WlSeatGlobal>) {
self.owner.get().ungrab(seat)
}
pub fn set_kb_node(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>) {
self.owner.get().set_kb_node(seat, node);
}
}
struct DefaultKbOwner;
struct GrabKbOwner;
trait KbOwner {
fn grab(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>) -> bool;
fn ungrab(&self, seat: &Rc<WlSeatGlobal>);
fn set_kb_node(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>);
}
impl KbOwner for DefaultKbOwner {
fn grab(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>) -> bool {
self.set_kb_node(seat, node);
seat.kb_owner.owner.set(Rc::new(GrabKbOwner));
true
}
fn ungrab(&self, _seat: &Rc<WlSeatGlobal>) {
// nothing
}
fn set_kb_node(&self, seat: &Rc<WlSeatGlobal>, node: Rc<dyn Node>) {
let old = seat.keyboard_node.get();
if old.id() == node.id() {
return;
}
old.unfocus(seat);
if old.seat_state().unfocus(seat) {
old.active_changed(false);
}
if node.seat_state().focus(seat) {
node.active_changed(true);
}
node.clone().focus(seat);
seat.keyboard_node.set(node.clone());
}
}
impl KbOwner for GrabKbOwner {
fn grab(&self, _seat: &Rc<WlSeatGlobal>, _node: Rc<dyn Node>) -> bool {
false
}
fn ungrab(&self, seat: &Rc<WlSeatGlobal>) {
seat.kb_owner.owner.set(seat.kb_owner.default.clone());
}
fn set_kb_node(&self, _seat: &Rc<WlSeatGlobal>, _node: Rc<dyn Node>) {
// nothing
}
}

View file

@ -147,9 +147,11 @@ impl PointerOwner for DefaultPointerOwner {
} }
if (stack.len(), found_tree.len()) == (divergence, divergence) { if (stack.len(), found_tree.len()) == (divergence, divergence) {
if let Some(node) = found_tree.last() { if let Some(node) = found_tree.last() {
node.node node.node.clone().pointer_motion(
.clone() seat,
.pointer_motion(seat, x.apply_fract(node.x), y.apply_fract(node.y)); x.apply_fract(node.x),
y.apply_fract(node.y),
);
} }
} else { } else {
if let Some(last) = stack.last() { if let Some(last) = stack.last() {
@ -161,16 +163,20 @@ impl PointerOwner for DefaultPointerOwner {
} }
if found_tree.len() == divergence { if found_tree.len() == divergence {
if let Some(node) = found_tree.last() { if let Some(node) = found_tree.last() {
node.node node.node.clone().pointer_motion(
.clone() seat,
.pointer_motion(seat, x.apply_fract(node.x), y.apply_fract(node.y)); x.apply_fract(node.x),
y.apply_fract(node.y),
);
} }
} else { } else {
for new in found_tree.drain(divergence..) { for new in found_tree.drain(divergence..) {
new.node.seat_state().enter(seat); new.node.seat_state().enter(seat);
new.node new.node.clone().pointer_enter(
.clone() seat,
.pointer_enter(seat, x.apply_fract(new.x), y.apply_fract(new.y)); x.apply_fract(new.x),
y.apply_fract(new.y),
);
stack.push(new.node); stack.push(new.node);
} }
} }

View file

@ -1,6 +1,7 @@
pub mod cursor; pub mod cursor;
pub mod wl_subsurface; pub mod wl_subsurface;
pub mod xdg_surface; pub mod xdg_surface;
pub mod zwlr_layer_surface_v1;
use crate::backend::{KeyState, ScrollAxis}; use crate::backend::{KeyState, ScrollAxis};
use crate::client::{Client, ClientError, RequestParser}; use crate::client::{Client, ClientError, RequestParser};
@ -34,6 +35,7 @@ use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::rc::Rc; use std::rc::Rc;
use thiserror::Error; use thiserror::Error;
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error;
#[allow(dead_code)] #[allow(dead_code)]
const INVALID_SCALE: u32 = 0; const INVALID_SCALE: u32 = 0;
@ -49,6 +51,7 @@ pub enum SurfaceRole {
XdgSurface, XdgSurface,
Cursor, Cursor,
DndIcon, DndIcon,
ZwlrLayerSurface,
} }
impl SurfaceRole { impl SurfaceRole {
@ -59,6 +62,7 @@ impl SurfaceRole {
SurfaceRole::XdgSurface => "xdg_surface", SurfaceRole::XdgSurface => "xdg_surface",
SurfaceRole::Cursor => "cursor", SurfaceRole::Cursor => "cursor",
SurfaceRole::DndIcon => "dnd_icon", SurfaceRole::DndIcon => "dnd_icon",
SurfaceRole::ZwlrLayerSurface => "zwlr_layer_surface",
} }
} }
} }
@ -111,7 +115,7 @@ trait SurfaceExt {
Ok(CommitAction::ContinueCommit) Ok(CommitAction::ContinueCommit)
} }
fn post_commit(&self) { fn post_commit(self: Rc<Self>) {
// nothing // nothing
} }
@ -134,6 +138,10 @@ trait SurfaceExt {
fn into_subsurface(self: Rc<Self>) -> Option<Rc<WlSubsurface>> { fn into_subsurface(self: Rc<Self>) -> Option<Rc<WlSubsurface>> {
None None
} }
fn accepts_kb_focus(&self) -> bool {
true
}
} }
pub struct NoneSurfaceExt; pub struct NoneSurfaceExt;
@ -222,11 +230,11 @@ impl WlSurface {
Ok(cursor) Ok(cursor)
} }
pub fn belongs_to_toplevel(&self) -> bool { pub fn accepts_kb_focus(&self) -> bool {
if let Some(xdg) = self.xdg.get() { if let Some(xdg) = self.xdg.get() {
return xdg.role() == XdgSurfaceRole::XdgToplevel; return xdg.role() == XdgSurfaceRole::XdgToplevel;
} }
false self.ext.get().accepts_kb_focus()
} }
fn send_enter(&self, output: WlOutputId) { fn send_enter(&self, output: WlOutputId) {
@ -747,6 +755,8 @@ pub enum WlSurfaceError {
#[error(transparent)] #[error(transparent)]
ClientError(Box<ClientError>), ClientError(Box<ClientError>),
#[error(transparent)] #[error(transparent)]
ZwlrLayerSurfaceV1Error(Box<ZwlrLayerSurfaceV1Error>),
#[error(transparent)]
XdgSurfaceError(Box<XdgSurfaceError>), XdgSurfaceError(Box<XdgSurfaceError>),
#[error("Could not process `destroy` request")] #[error("Could not process `destroy` request")]
DestroyError(#[source] Box<DestroyError>), DestroyError(#[source] Box<DestroyError>),
@ -784,13 +794,10 @@ efrom!(WlSurfaceError, FrameError);
efrom!(WlSurfaceError, SetOpaqueRegionError); efrom!(WlSurfaceError, SetOpaqueRegionError);
efrom!(WlSurfaceError, SetInputRegionError); efrom!(WlSurfaceError, SetInputRegionError);
efrom!(WlSurfaceError, CommitError); efrom!(WlSurfaceError, CommitError);
efrom!( efrom!(WlSurfaceError, SetBufferTransformError);
WlSurfaceError,
SetBufferTransformError,
SetBufferTransformError
);
efrom!(WlSurfaceError, SetBufferScaleError); efrom!(WlSurfaceError, SetBufferScaleError);
efrom!(WlSurfaceError, DamageBufferError); efrom!(WlSurfaceError, DamageBufferError);
efrom!(WlSurfaceError, ZwlrLayerSurfaceV1Error);
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum DestroyError { pub enum DestroyError {

View file

@ -263,9 +263,8 @@ impl SurfaceExt for WlSubsurface {
Ok(CommitAction::ContinueCommit) Ok(CommitAction::ContinueCommit)
} }
fn post_commit(&self) { fn post_commit(self: Rc<Self>) {
if let Some(v) = self.pending.node.take() { if let Some(v) = self.pending.node.take() {
log::info!("post commit");
v.pending.set(false); v.pending.set(false);
self.node.borrow_mut().replace(v); self.node.borrow_mut().replace(v);
} }

View file

@ -443,7 +443,7 @@ impl SurfaceExt for XdgSurface {
Ok(CommitAction::ContinueCommit) Ok(CommitAction::ContinueCommit)
} }
fn post_commit(&self) { fn post_commit(self: Rc<Self>) {
if let Some(ext) = self.ext.get() { if let Some(ext) = self.ext.get() {
ext.post_commit(); ext.post_commit();
} }

View file

@ -27,6 +27,7 @@ use std::fmt::{Debug, Formatter};
use std::mem; use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use backtrace::Backtrace;
use thiserror::Error; use thiserror::Error;
#[derive(Copy, Clone, Debug, FromPrimitive)] #[derive(Copy, Clone, Debug, FromPrimitive)]

View file

@ -0,0 +1,533 @@
use std::cell::Cell;
use std::ops::Deref;
use crate::client::{Client, ClientError, ClientId};
use crate::ifs::wl_output::{WlOutput, WlOutputGlobal};
use crate::ifs::wl_surface::{CommitAction, CommitContext, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError};
use crate::ifs::zwlr_layer_shell_v1::{OVERLAY, ZwlrLayerShellV1};
use crate::leaks::Tracker;
use crate::object::Object;
use crate::utils::buffd::MsgParser;
use crate::utils::buffd::MsgParserError;
use crate::wire::zwlr_layer_surface_v1::*;
use crate::wire::{WlSurfaceId, ZwlrLayerSurfaceV1Id};
use std::rc::Rc;
use thiserror::Error;
use i4config::Direction;
use crate::ifs::wl_surface::wl_subsurface::WlSubsurface;
use crate::{CloneCell, NumCell};
use crate::backend::{KeyState, ScrollAxis};
use crate::fixed::Fixed;
use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal};
use crate::rect::Rect;
use crate::render::Renderer;
use crate::tree::{ContainerNode, ContainerSplit, FindTreeResult, FloatNode, FoundNode, Node, NodeId, OutputNode, WorkspaceNode};
use crate::tree::walker::NodeVisitor;
use crate::utils::bitflags::BitflagsExt;
use crate::utils::linkedlist::LinkedNode;
const KI_NONE: u32 = 0;
#[allow(dead_code)]
const KI_EXCLUSIVE: u32 = 1;
const KI_ON_DEMAND: u32 = 2;
const TOP: u32 = 1;
const BOTTOM: u32 = 2;
const LEFT: u32 = 4;
const RIGHT: u32 = 8;
tree_id!(ZwlrLayerSurfaceV1NodeId);
pub struct ZwlrLayerSurfaceV1 {
pub id: ZwlrLayerSurfaceV1Id,
node_id: ZwlrLayerSurfaceV1NodeId,
pub shell: Rc<ZwlrLayerShellV1>,
pub client: Rc<Client>,
pub surface: Rc<WlSurface>,
pub output: Rc<OutputNode>,
pub namespace: String,
pub tracker: Tracker<Self>,
pos: Cell<Rect>,
mapped: Cell<bool>,
layer: Cell<u32>,
pending: Pending,
requested_serial: NumCell<u32>,
acked_serial: Cell<Option<u32>>,
size: Cell<(i32, i32)>,
anchor: Cell<u32>,
exclusive_zone: Cell<i32>,
margin: Cell<(i32, i32, i32, i32)>,
keyboard_interactivity: Cell<u32>,
link: Cell<Option<LinkedNode<Rc<Self>>>>,
seat_state: NodeSeatState,
}
#[derive(Default)]
struct Pending {
size: Cell<Option<(i32, i32)>>,
anchor: Cell<Option<u32>>,
exclusive_zone: Cell<Option<i32>>,
margin: Cell<Option<(i32, i32, i32, i32)>>,
keyboard_interactivity: Cell<Option<u32>>,
layer: Cell<Option<u32>>,
}
impl ZwlrLayerSurfaceV1 {
pub fn new(
id: ZwlrLayerSurfaceV1Id,
shell: &Rc<ZwlrLayerShellV1>,
surface: &Rc<WlSurface>,
output: &Rc<OutputNode>,
layer: u32,
namespace: &str,
) -> Self {
Self {
id,
node_id: shell.client.state.node_ids.next(),
shell: shell.clone(),
client: shell.client.clone(),
surface: surface.clone(),
output: output.clone(),
namespace: namespace.to_string(),
tracker: Default::default(),
pos: Cell::new(Default::default()),
mapped: Cell::new(false),
layer: Cell::new(layer),
pending: Default::default(),
requested_serial: Default::default(),
acked_serial: Cell::new(None),
size: Cell::new((0, 0)),
anchor: Cell::new(0),
exclusive_zone: Cell::new(0),
margin: Cell::new((0, 0, 0, 0)),
keyboard_interactivity: Cell::new(0),
link: Cell::new(None),
seat_state: Default::default()
}
}
pub fn install(self: &Rc<Self>) -> Result<(), ZwlrLayerSurfaceV1Error> {
self.surface.set_role(SurfaceRole::ZwlrLayerSurface)?;
if self.surface.ext.get().is_some() {
return Err(ZwlrLayerSurfaceV1Error::AlreadyAttached(self.surface.id));
}
self.surface.ext.set(self.clone());
Ok(())
}
fn send_configure(&self, serial: u32, width: u32, height: u32) {
self.client.event(Configure {
self_id: self.id,
serial,
width,
height,
});
}
#[allow(dead_code)]
fn send_closed(&self) {
self.client.event(Closed { self_id: self.id });
}
fn set_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSizeError> {
let req: SetSize = self.client.parse(self, parser)?;
if req.width > u16::MAX as u32 || req.height > u16::MAX as u32 {
return Err(SetSizeError::ExcessiveSize);
}
self.pending.size.set(Some((req.width as _, req.height as _)));
Ok(())
}
fn set_anchor(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAnchorError> {
let req: SetAnchor = self.client.parse(self, parser)?;
if req.anchor & !(LEFT | RIGHT | TOP | BOTTOM) != 0 {
return Err(SetAnchorError::UnknownAnchor(req.anchor));
}
self.pending.anchor.set(Some(req.anchor));
Ok(())
}
fn set_exclusive_zone(&self, parser: MsgParser<'_, '_>) -> Result<(), SetExclusiveZoneError> {
let req: SetExclusiveZone = self.client.parse(self, parser)?;
self.pending.exclusive_zone.set(Some(req.zone));
Ok(())
}
fn set_margin(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMarginError> {
let req: SetMargin = self.client.parse(self, parser)?;
self.pending.margin.set(Some((req.top, req.right, req.bottom, req.left)));
Ok(())
}
fn set_keyboard_interactivity(&self, parser: MsgParser<'_, '_>) -> Result<(), SetKeyboardInteractivityError> {
let req: SetKeyboardInteractivity = self.client.parse(self, parser)?;
if req.keyboard_interactivity > KI_ON_DEMAND {
return Err(SetKeyboardInteractivityError::UnknownKi(req.keyboard_interactivity));
}
self.pending.keyboard_interactivity.set(Some(req.keyboard_interactivity));
Ok(())
}
fn get_popup(&self, parser: MsgParser<'_, '_>) -> Result<(), GetPopupError> {
let _req: GetPopup = self.client.parse(self, parser)?;
Ok(())
}
fn ack_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), AckConfigureError> {
let req: AckConfigure = self.client.parse(self, parser)?;
self.acked_serial.set(Some(req.serial));
Ok(())
}
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, parser)?;
self.destroy_node(true);
self.client.remove_obj(self)?;
self.surface.unset_ext();
Ok(())
}
fn set_layer(&self, parser: MsgParser<'_, '_>) -> Result<(), SetLayerError> {
let req: SetLayer = self.client.parse(self, parser)?;
if req.layer > OVERLAY {
return Err(SetLayerError::UnknownLayer(req.layer));
}
self.pending.layer.set(Some(req.layer));
Ok(())
}
fn pre_commit(&self) -> Result<(), ZwlrLayerSurfaceV1Error> {
let mut send_configure = false;
if let Some(size) = self.pending.size.take() {
self.size.set(size);
}
if let Some(anchor) = self.pending.anchor.take() {
self.anchor.set(anchor);
}
if let Some(ez) = self.pending.exclusive_zone.take() {
self.exclusive_zone.set(ez);
}
if let Some(margin) = self.pending.margin.take() {
self.margin.set(margin);
}
if let Some(ki) = self.pending.keyboard_interactivity.take() {
self.keyboard_interactivity.set(ki);
}
if let Some(layer) = self.pending.layer.take() {
self.layer.set(layer);
}
{
let (mut width, mut height) = self.size.get();
let anchor = self.anchor.get();
if width == 0 {
if !anchor.contains(LEFT | RIGHT) {
return Err(ZwlrLayerSurfaceV1Error::WidthZero);
}
send_configure = true;
width = self.output.global.position().width();
}
if height == 0 {
if !anchor.contains(TOP | BOTTOM) {
return Err(ZwlrLayerSurfaceV1Error::HeightZero);
}
send_configure = true;
height = self.output.global.position().height();
}
self.size.set((width, height));
}
if self.acked_serial.get().is_none() {
send_configure = true;
}
if send_configure {
let (width, height) = self.size.get();
let serial = self.requested_serial.fetch_add(1) + 1;
self.send_configure(serial, width as _, height as _);
}
Ok(())
}
pub fn position(&self) -> Rect {
self.pos.get()
}
fn compute_position(&self) {
let (width, height) = self.size.get();
let mut anchor = self.anchor.get();
if anchor == 0 {
anchor = LEFT | RIGHT | TOP | BOTTOM;
}
let opos = self.output.position.get();
let mut x1 = opos.x1();
let mut y1 = opos.y1();
if anchor.contains(LEFT) {
if anchor.contains(RIGHT) {
x1 += (opos.width() - width) / 2;
}
} else if anchor.contains(RIGHT) {
x1 += opos.width() - width;
}
if anchor.contains(TOP) {
if anchor.contains(BOTTOM) {
y1 += (opos.height() - height) / 2;
}
} else if anchor.contains(BOTTOM) {
y1 += opos.height() - height;
}
self.pos.set(Rect::new_sized(x1, y1, width, height).unwrap());
self.client.state.tree_changed();
}
}
impl SurfaceExt for ZwlrLayerSurfaceV1 {
fn pre_commit(self: Rc<Self>, _ctx: CommitContext) -> Result<CommitAction, WlSurfaceError> {
self.deref().pre_commit()?;
Ok(CommitAction::ContinueCommit)
}
fn post_commit(self: Rc<Self>) {
let buffer = self.surface.buffer.get();
if self.mapped.get() {
if buffer.is_none() {
self.destroy_node(true);
} else {
let pos = self.pos.get();
let (width, height) = self.size.get();
if width != pos.width() || height != pos.height() {
self.compute_position();
}
}
} else if buffer.is_some() {
let layer = &self.output.layers[self.layer.get() as usize];
self.link.set(Some(layer.add_last(self.clone())));
self.mapped.set(true);
self.compute_position();
}
if self.mapped.get() {
match self.keyboard_interactivity.get() {
KI_NONE => {
let was_active = self.surface.seat_state.is_active();
self.surface.seat_state.release_kb_focus();
if was_active {
self.surface.active_changed(false);
}
},
KI_ON_DEMAND => self.surface.seat_state.release_kb_grab(),
KI_EXCLUSIVE => {
let seats = self.client.state.globals.seats.lock();
for seat in seats.values() {
seat.grab(self.surface.clone());
}
}
_ => unreachable!(),
}
}
}
fn accepts_kb_focus(&self) -> bool {
self.keyboard_interactivity.get() != KI_NONE
}
}
impl Node for ZwlrLayerSurfaceV1 {
fn id(&self) -> NodeId {
self.node_id.into()
}
fn seat_state(&self) -> &NodeSeatState {
&self.seat_state
}
fn destroy_node(&self, _detach: bool) {
self.link.set(None);
self.mapped.set(false);
self.surface.destroy_node(false);
self.seat_state.destroy_node(self);
}
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
visitor.visit_layer_surface(&self);
}
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
self.surface.clone().visit(visitor);
}
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
renderer.render_layer_surface(self, x, y);
}
fn absolute_position(&self) -> Rect {
self.pos.get()
}
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
tree.push(FoundNode {
node: self.surface.clone(),
x,
y
});
self.surface.find_tree_at(x, y, tree)
}
fn change_extents(self: Rc<Self>, _rect: &Rect) {
self.compute_position();
}
}
object_base! {
ZwlrLayerSurfaceV1, ZwlrLayerSurfaceV1Error;
SET_SIZE => set_size,
SET_ANCHOR => set_anchor,
SET_EXCLUSIVE_ZONE => set_exclusive_zone,
SET_MARGIN => set_margin,
SET_KEYBOARD_INTERACTIVITY => set_keyboard_interactivity,
GET_POPUP => get_popup,
ACK_CONFIGURE => ack_configure,
DESTROY => destroy,
SET_LAYER => set_layer,
}
impl Object for ZwlrLayerSurfaceV1 {
fn num_requests(&self) -> u32 {
let last_req = match self.shell.version {
0..=1 => DESTROY,
_ => SET_LAYER,
};
last_req + 1
}
fn break_loops(&self) {
self.destroy_node(true);
self.link.set(None);
}
}
simple_add_obj!(ZwlrLayerSurfaceV1);
#[derive(Debug, Error)]
pub enum ZwlrLayerSurfaceV1Error {
#[error("Could not process `set_size` request")]
SetSizeError(#[from] SetSizeError),
#[error("Could not process `set_anchor` request")]
SetAnchorError(#[from] SetAnchorError),
#[error("Could not process `set_exclusive_zone` request")]
SetExclusiveZoneError(#[from] SetExclusiveZoneError),
#[error("Could not process `set_margin` request")]
SetMarginError(#[from] SetMarginError),
#[error("Could not process `set_keyboard_interactivity` request")]
SetKeyboardInteractivityError(#[from] SetKeyboardInteractivityError),
#[error("Could not process `get_popup` request")]
GetPopupError(#[from] GetPopupError),
#[error("Could not process `ack_configure` request")]
AckConfigureError(#[from] AckConfigureError),
#[error("Could not process `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process `set_layer` request")]
SetLayerError(#[from] SetLayerError),
#[error("Surface {0} cannot be turned into a zwlr_layer_surface because it already has an attached zwlr_layer_surface")]
AlreadyAttached(WlSurfaceId),
#[error("Width was set to 0 but anchor did not contain LEFT and RIGHT")]
WidthZero,
#[error("Height was set to 0 but anchor did not contain TOP and BOTTOM")]
HeightZero,
#[error(transparent)]
WlSurfaceError(Box<WlSurfaceError>),
}
efrom!(ZwlrLayerSurfaceV1Error, WlSurfaceError);
#[derive(Debug, Error)]
pub enum SetSizeError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Surface size must not be larger than 65535x65535")]
ExcessiveSize,
}
efrom!(SetSizeError, MsgParserError);
efrom!(SetSizeError, ClientError);
#[derive(Debug, Error)]
pub enum SetAnchorError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Unknown anchor {0}")]
UnknownAnchor(u32),
}
efrom!(SetAnchorError, MsgParserError);
efrom!(SetAnchorError, ClientError);
#[derive(Debug, Error)]
pub enum SetExclusiveZoneError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetExclusiveZoneError, MsgParserError);
efrom!(SetExclusiveZoneError, ClientError);
#[derive(Debug, Error)]
pub enum SetMarginError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(SetMarginError, MsgParserError);
efrom!(SetMarginError, ClientError);
#[derive(Debug, Error)]
pub enum SetKeyboardInteractivityError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Unknown keyboard interactivity {0}")]
UnknownKi(u32),
}
efrom!(SetKeyboardInteractivityError, MsgParserError);
efrom!(SetKeyboardInteractivityError, ClientError);
#[derive(Debug, Error)]
pub enum GetPopupError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(GetPopupError, MsgParserError);
efrom!(GetPopupError, ClientError);
#[derive(Debug, Error)]
pub enum AckConfigureError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(AckConfigureError, MsgParserError);
efrom!(AckConfigureError, ClientError);
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, MsgParserError);
efrom!(DestroyError, ClientError);
#[derive(Debug, Error)]
pub enum SetLayerError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Unknown layer {0}")]
UnknownLayer(u32),
}
efrom!(SetLayerError, MsgParserError);
efrom!(SetLayerError, ClientError);

View file

@ -0,0 +1,176 @@
use crate::client::{Client, ClientError};
use crate::globals::{Global, GlobalName};
use crate::ifs::wl_surface::zwlr_layer_surface_v1::{ZwlrLayerSurfaceV1, ZwlrLayerSurfaceV1Error};
use crate::leaks::Tracker;
use crate::object::Object;
use crate::utils::buffd::MsgParser;
use crate::utils::buffd::MsgParserError;
use crate::wire::zwlr_layer_shell_v1::*;
use crate::wire::ZwlrLayerShellV1Id;
use std::rc::Rc;
use thiserror::Error;
#[allow(dead_code)]
pub const BACKGROUND: u32 = 0;
#[allow(dead_code)]
pub const BOTTOM: u32 = 1;
#[allow(dead_code)]
pub const TOP: u32 = 2;
pub const OVERLAY: u32 = 3;
pub struct ZwlrLayerShellV1Global {
name: GlobalName,
}
pub struct ZwlrLayerShellV1 {
pub id: ZwlrLayerShellV1Id,
pub client: Rc<Client>,
pub version: u32,
pub tracker: Tracker<Self>,
}
impl ZwlrLayerShellV1Global {
pub fn new(name: GlobalName) -> Self {
Self { name }
}
fn bind_(
self: Rc<Self>,
id: ZwlrLayerShellV1Id,
client: &Rc<Client>,
version: u32,
) -> Result<(), ZwlrLayerShellV1Error> {
let obj = Rc::new(ZwlrLayerShellV1 {
id,
client: client.clone(),
version,
tracker: Default::default(),
});
track!(client, obj);
client.add_client_obj(&obj)?;
Ok(())
}
}
impl ZwlrLayerShellV1 {
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, parser)?;
self.client.remove_obj(self)?;
Ok(())
}
fn get_layer_surface(
self: &Rc<Self>,
parser: MsgParser<'_, '_>,
) -> Result<(), GetLayerSurfaceError> {
let req: GetLayerSurface = self.client.parse(&**self, parser)?;
let surface = self.client.lookup(req.surface)?;
let output = 'get_output: {
if req.output.is_some() {
self.client.lookup(req.output)?.global.node.get().unwrap()
} else {
for seat in self.client.state.seat_queue.rev_iter() {
if let Some(output) = seat.get_output() {
break 'get_output output.node.get().unwrap();
}
}
let outputs = self.client.state.outputs.lock();
match outputs.values().next() {
Some(ou) => ou.node.get().unwrap(),
_ => return Err(GetLayerSurfaceError::NoOutputs),
}
}
};
if req.layer > OVERLAY {
return Err(GetLayerSurfaceError::UnknownLayer(req.layer));
}
let surface = Rc::new(ZwlrLayerSurfaceV1::new(
req.id,
self,
&surface,
&output,
req.layer,
req.namespace,
));
track!(self.client, surface);
self.client.add_client_obj(&surface)?;
surface.install()?;
Ok(())
}
}
global_base!(
ZwlrLayerShellV1Global,
ZwlrLayerShellV1,
ZwlrLayerShellV1Error
);
impl Global for ZwlrLayerShellV1Global {
fn singleton(&self) -> bool {
true
}
fn version(&self) -> u32 {
4
}
}
simple_add_global!(ZwlrLayerShellV1Global);
object_base! {
ZwlrLayerShellV1, ZwlrLayerShellV1Error;
GET_LAYER_SURFACE => get_layer_surface,
DESTROY => destroy,
}
simple_add_obj!(ZwlrLayerShellV1);
impl Object for ZwlrLayerShellV1 {
fn num_requests(&self) -> u32 {
let last_request = if self.version >= 3 {
DESTROY
} else {
GET_LAYER_SURFACE
};
last_request + 1
}
}
#[derive(Debug, Error)]
pub enum ZwlrLayerShellV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Could not process a `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process a `get_layer_surface` request")]
GetLayerSurfaceError(#[from] GetLayerSurfaceError),
}
efrom!(ZwlrLayerShellV1Error, ClientError);
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseError, MsgParserError);
efrom!(DestroyError, ClientError);
#[derive(Debug, Error)]
pub enum GetLayerSurfaceError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Unknown layer {0}")]
UnknownLayer(u32),
#[error("There are no outputs")]
NoOutputs,
#[error(transparent)]
ZwlrLayerSurfaceV1Error(Box<ZwlrLayerSurfaceV1Error>),
}
efrom!(GetLayerSurfaceError, ParseError, MsgParserError);
efrom!(GetLayerSurfaceError, ClientError);
efrom!(GetLayerSurfaceError, ZwlrLayerSurfaceV1Error);

View file

@ -0,0 +1,137 @@
use crate::client::{Client, ClientError};
use crate::globals::{Global, GlobalName};
use crate::leaks::Tracker;
use crate::object::Object;
use crate::utils::buffd::MsgParser;
use crate::utils::buffd::MsgParserError;
use crate::wire::zxdg_output_manager_v1::*;
use crate::wire::{ZxdgOutputManagerV1Id};
use std::rc::Rc;
use thiserror::Error;
use crate::ifs::zxdg_output_v1::ZxdgOutputV1;
pub struct ZxdgOutputManagerV1Global {
name: GlobalName,
}
pub struct ZxdgOutputManagerV1 {
pub id: ZxdgOutputManagerV1Id,
pub client: Rc<Client>,
pub version: u32,
pub tracker: Tracker<Self>,
}
impl ZxdgOutputManagerV1Global {
pub fn new(name: GlobalName) -> Self {
Self { name }
}
fn bind_(
self: Rc<Self>,
id: ZxdgOutputManagerV1Id,
client: &Rc<Client>,
version: u32,
) -> Result<(), ZxdgOutputManagerV1Error> {
let obj = Rc::new(ZxdgOutputManagerV1 {
id,
client: client.clone(),
version,
tracker: Default::default(),
});
track!(client, obj);
client.add_client_obj(&obj)?;
Ok(())
}
}
impl ZxdgOutputManagerV1 {
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, parser)?;
self.client.remove_obj(self)?;
Ok(())
}
fn get_xdg_output(
self: &Rc<Self>,
parser: MsgParser<'_, '_>,
) -> Result<(), GetXdgOutputError> {
let req: GetXdgOutput = self.client.parse(&**self, parser)?;
let output = self.client.lookup(req.output)?;
let xdg_output = Rc::new(ZxdgOutputV1 {
id: req.id,
version: self.version,
client: self.client.clone(),
output: output.clone(),
tracker: Default::default()
});
track!(self.client, xdg_output);
self.client.add_client_obj(&xdg_output)?;
xdg_output.send_updates();
output.xdg_outputs.set(req.id, xdg_output);
Ok(())
}
}
global_base!(
ZxdgOutputManagerV1Global,
ZxdgOutputManagerV1,
ZxdgOutputManagerV1Error
);
impl Global for ZxdgOutputManagerV1Global {
fn singleton(&self) -> bool {
true
}
fn version(&self) -> u32 {
3
}
}
simple_add_global!(ZxdgOutputManagerV1Global);
object_base! {
ZxdgOutputManagerV1, ZxdgOutputManagerV1Error;
DESTROY => destroy,
GET_XDG_OUTPUT => get_xdg_output,
}
simple_add_obj!(ZxdgOutputManagerV1);
impl Object for ZxdgOutputManagerV1 {
fn num_requests(&self) -> u32 {
GET_XDG_OUTPUT + 1
}
}
#[derive(Debug, Error)]
pub enum ZxdgOutputManagerV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Could not process a `destroy` request")]
DestroyError(#[from] DestroyError),
#[error("Could not process a `get_xdg_output` request")]
GetXdgOutputError(#[from] GetXdgOutputError),
}
efrom!(ZxdgOutputManagerV1Error, ClientError);
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, ParseError, MsgParserError);
efrom!(DestroyError, ClientError);
#[derive(Debug, Error)]
pub enum GetXdgOutputError {
#[error("Parsing failed")]
ParseError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(GetXdgOutputError, ParseError, MsgParserError);
efrom!(GetXdgOutputError, ClientError);

107
src/ifs/zxdg_output_v1.rs Normal file
View file

@ -0,0 +1,107 @@
use std::rc::Rc;
use thiserror::Error;
use crate::client::{Client, ClientError};
use crate::ifs::wl_output::{SEND_DONE_SINCE, WlOutput};
use crate::leaks::Tracker;
use crate::object::Object;
use crate::utils::buffd::{MsgParser, MsgParserError};
use crate::wire::ZxdgOutputV1Id;
use crate::wire::zxdg_output_v1::*;
pub const NAME_SINCE: u32 = 2;
pub const DESCRIPTION_SINCE: u32 = 2;
pub const NO_DONE_SINCE: u32 = 3;
pub struct ZxdgOutputV1 {
pub id: ZxdgOutputV1Id,
pub version: u32,
pub client: Rc<Client>,
pub output: Rc<WlOutput>,
pub tracker: Tracker<Self>,
}
impl ZxdgOutputV1 {
pub fn send_logical_position(&self, x: i32, y: i32) {
self.client.event(LogicalPosition {
self_id: self.id,
x,
y,
});
}
pub fn send_logical_size(&self, width: i32, height: i32) {
self.client.event(LogicalSize {
self_id: self.id,
width,
height,
});
}
pub fn send_done(&self) {
self.client.event(Done {
self_id: self.id,
});
}
pub fn send_name(&self, name: &str) {
self.client.event(Name {
self_id: self.id,
name,
});
}
pub fn send_description(&self, description: &str) {
self.client.event(Description {
self_id: self.id,
description,
});
}
pub fn send_updates(&self) {
let pos = self.output.global.position();
self.send_logical_position(pos.x1(), pos.y1());
self.send_logical_size(pos.width(), pos.height());
if self.version >= NO_DONE_SINCE || self.output.version < SEND_DONE_SINCE {
self.output.send_done();
} else {
self.send_done();
}
}
pub fn destroy(&self, msg: MsgParser) -> Result<(), DestroyError> {
let _req: Destroy = self.client.parse(self, msg)?;
self.output.xdg_outputs.remove(&self.id);
self.client.remove_obj(self)?;
Ok(())
}
}
object_base! {
ZxdgOutputV1, ZxdgOutputV1Error;
DESTROY => destroy,
}
impl Object for ZxdgOutputV1 {
fn num_requests(&self) -> u32 {
DESTROY + 1
}
}
simple_add_obj!(ZxdgOutputV1);
#[derive(Debug, Error)]
pub enum ZxdgOutputV1Error {
#[error("Could not process a `destroy` request")]
DestroyError(#[from] DestroyError),
}
#[derive(Debug, Error)]
pub enum DestroyError {
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)]
ClientError(Box<ClientError>),
}
efrom!(DestroyError, MsgParserError);
efrom!(DestroyError, ClientError);

View file

@ -44,14 +44,14 @@ macro_rules! object_base {
} }
fn interface(&self) -> crate::object::Interface { fn interface(&self) -> crate::object::Interface {
crate::object::Interface::$oname crate::wire::$oname
} }
} }
impl From<$ename> for crate::client::ObjectError { impl From<$ename> for crate::client::ObjectError {
fn from(v: $ename) -> Self { fn from(v: $ename) -> Self {
Self { Self {
interface: crate::object::Interface::$oname, interface: crate::wire::$oname,
error: Box::new(v), error: Box::new(v),
} }
} }
@ -79,14 +79,14 @@ macro_rules! global_base {
} }
fn interface(&self) -> crate::object::Interface { fn interface(&self) -> crate::object::Interface {
crate::object::Interface::$ifname crate::wire::$ifname
} }
} }
impl From<$ename> for crate::globals::GlobalError { impl From<$ename> for crate::globals::GlobalError {
fn from(e: $ename) -> Self { fn from(e: $ename) -> Self {
Self { Self {
interface: crate::object::Interface::$ifname, interface: crate::wire::$ifname,
error: Box::new(e), error: Box::new(e),
} }
} }
@ -281,7 +281,7 @@ macro_rules! dedicated_add_obj {
impl crate::client::WaylandObjectLookup for $idname { impl crate::client::WaylandObjectLookup for $idname {
type Object = $oname; type Object = $oname;
const INTERFACE: crate::object::Interface = crate::object::Interface::$oname; const INTERFACE: crate::object::Interface = crate::wire::$oname;
fn lookup(client: &crate::client::Client, id: Self) -> Option<Rc<$oname>> { fn lookup(client: &crate::client::Client, id: Self) -> Option<Rc<$oname>> {
client.objects.$field.get(&id) client.objects.$field.get(&id)

View file

@ -42,91 +42,11 @@ pub trait Object: ObjectBase + 'static {
fn break_loops(&self) {} fn break_loops(&self) {}
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug)]
pub enum Interface { pub struct Interface(pub &'static str);
WlDisplay,
WlCallback,
WlCompositor,
WlOutput,
WlRegistry,
WlShm,
WlShmPool,
WlTouch,
WlPointer,
WlKeyboard,
WlSubcompositor,
WlDataDeviceManager,
WlDataDevice,
WlDataSource,
WlDataOffer,
XdgWmBase,
XdgPositioner,
WlSurface,
WlSubsurface,
XdgSurface,
XdgPopup,
XdgToplevel,
WlRegion,
WlBuffer,
WlSeat,
WlDrm,
ZwpLinuxDmabufV1,
ZwpLinuxDmabufFeedbackV1,
ZwpLinuxBufferParamsV1,
ZxdgDecorationManagerV1,
ZxdgToplevelDecorationV1,
OrgKdeKwinServerDecorationManager,
OrgKdeKwinServerDecoration,
ZwpPrimarySelectionDeviceManagerV1,
ZwpPrimarySelectionDeviceV1,
ZwpPrimarySelectionSourceV1,
ZwpPrimarySelectionOfferV1,
}
impl Interface { impl Interface {
pub fn name(self) -> &'static str { pub fn name(self) -> &'static str {
match self { self.0
Interface::WlDisplay => "wl_display",
Interface::WlCallback => "wl_callback",
Interface::WlCompositor => "wl_compositor",
Interface::WlRegistry => "wl_registry",
Interface::WlShm => "wl_shm",
Interface::WlSubcompositor => "wl_subcompositor",
Interface::XdgWmBase => "xdg_wm_base",
Interface::WlSurface => "wl_surface",
Interface::WlSubsurface => "wl_subsurface",
Interface::WlShmPool => "wl_shm_pool",
Interface::WlRegion => "wl_region",
Interface::XdgSurface => "xdg_surface",
Interface::XdgPositioner => "xdg_positioner",
Interface::XdgPopup => "xdg_popup",
Interface::XdgToplevel => "xdg_toplevel",
Interface::WlBuffer => "wl_buffer",
Interface::WlOutput => "wl_output",
Interface::WlSeat => "wl_seat",
Interface::WlTouch => "wl_touch",
Interface::WlPointer => "wl_pointer",
Interface::WlKeyboard => "wl_keyboard",
Interface::WlDataDeviceManager => "wl_data_device_manager",
Interface::WlDataDevice => "wl_data_device",
Interface::WlDataSource => "wl_data_source",
Interface::WlDataOffer => "wl_data_offer",
Interface::ZwpLinuxDmabufV1 => "zwp_linux_dmabuf_v1",
Interface::ZwpLinuxDmabufFeedbackV1 => "zwp_linux_dmabuf_feedback_v1",
Interface::ZwpLinuxBufferParamsV1 => "zwp_linux_buffer_params_v1",
Interface::WlDrm => "wl_drm",
Interface::ZxdgDecorationManagerV1 => "zxdg_decoration_manager_v1",
Interface::ZxdgToplevelDecorationV1 => "zxdg_toplevel_decoration_v1",
Interface::OrgKdeKwinServerDecorationManager => {
"org_kde_kwin_server_decoration_manager"
}
Interface::OrgKdeKwinServerDecoration => "org_kde_kwin_server_decoration",
Interface::ZwpPrimarySelectionDeviceManagerV1 => {
"zwp_primary_selection_device_manager_v1"
}
Interface::ZwpPrimarySelectionDeviceV1 => "zwp_primary_selection_device_v1",
Interface::ZwpPrimarySelectionSourceV1 => "zwp_primary_selection_source_v1",
Interface::ZwpPrimarySelectionOfferV1 => "zwp_primary_selection_offer_v1",
}
} }
} }

View file

@ -21,6 +21,7 @@ use crate::State;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use std::slice; use std::slice;
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
const NON_COLOR: Color = Color::from_rgbaf(0.2, 0.2, 0.2, 1.0); const NON_COLOR: Color = Color::from_rgbaf(0.2, 0.2, 0.2, 1.0);
const CHILD_COLOR: Color = Color::from_rgbaf(0.8, 0.8, 0.8, 1.0); const CHILD_COLOR: Color = Color::from_rgbaf(0.8, 0.8, 0.8, 1.0);
@ -42,9 +43,21 @@ pub struct Renderer<'a> {
impl Renderer<'_> { impl Renderer<'_> {
pub fn render_output(&mut self, output: &OutputNode, x: i32, y: i32) { pub fn render_output(&mut self, output: &OutputNode, x: i32, y: i32) {
macro_rules! render_layer {
($layer:expr) => {
for ls in $layer.iter() {
let pos = ls.position();
self.render_layer_surface(ls.deref(), pos.x1(), pos.y1());
}
}
}
render_layer!(output.layers[0]);
render_layer!(output.layers[1]);
if let Some(ws) = output.workspace.get() { if let Some(ws) = output.workspace.get() {
self.render_workspace(&ws, x, y); self.render_workspace(&ws, x, y);
} }
render_layer!(output.layers[2]);
render_layer!(output.layers[3]);
} }
pub fn render_workspace(&mut self, workspace: &WorkspaceNode, x: i32, y: i32) { pub fn render_workspace(&mut self, workspace: &WorkspaceNode, x: i32, y: i32) {
@ -392,4 +405,13 @@ impl Renderer<'_> {
}); });
} }
} }
pub fn render_layer_surface(&mut self, surface: &ZwlrLayerSurfaceV1, x: i32, y: i32) {
unsafe {
let body = surface.position();
with_scissor(&body, || {
self.render_surface(&surface.surface, x, y);
});
}
}
} }

View file

@ -30,7 +30,9 @@ impl OutputHandler {
workspace: CloneCell::new(None), workspace: CloneCell::new(None),
seat_state: Default::default(), seat_state: Default::default(),
global: global.clone(), global: global.clone(),
layers: Default::default(),
}); });
global.node.set(Some(on.clone()));
let workspace = Rc::new(WorkspaceNode { let workspace = Rc::new(WorkspaceNode {
id: self.state.node_ids.next(), id: self.state.node_ids.next(),
output: CloneCell::new(on.clone()), output: CloneCell::new(on.clone()),
@ -60,6 +62,7 @@ impl OutputHandler {
global.update_properties(); global.update_properties();
ae.triggered().await; ae.triggered().await;
} }
global.node.set(None);
self.state.outputs.remove(&self.output.id()); self.state.outputs.remove(&self.output.id());
let _ = self.state.remove_global(&*global); let _ = self.state.remove_global(&*global);
self.state self.state

View file

@ -345,7 +345,13 @@ impl ContainerNode {
} }
_ => { _ => {
let height = body.height() + add; let height = body.height() + add;
(0, pos + title_height + 1, other_content_size, height, height) (
0,
pos + title_height + 1,
other_content_size,
height,
height,
)
} }
}; };
body = Rect::new_sized(x1, y1, width, height).unwrap(); body = Rect::new_sized(x1, y1, width, height).unwrap();

View file

@ -2,13 +2,11 @@ use crate::backend::{KeyState, OutputId, ScrollAxis};
use crate::client::{Client, ClientId}; use crate::client::{Client, ClientId};
use crate::cursor::KnownCursor; use crate::cursor::KnownCursor;
use crate::fixed::Fixed; use crate::fixed::Fixed;
use crate::ifs::wl_output::WlOutputGlobal;
use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal}; use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal};
use crate::ifs::wl_surface::WlSurface; use crate::ifs::wl_surface::WlSurface;
use crate::rect::Rect; use crate::rect::Rect;
use crate::render::Renderer; use crate::render::Renderer;
use crate::tree::walker::NodeVisitor; use crate::tree::walker::NodeVisitor;
use crate::utils::clonecell::CloneCell;
use crate::utils::copyhashmap::CopyHashMap; use crate::utils::copyhashmap::CopyHashMap;
use crate::utils::linkedlist::LinkedList; use crate::utils::linkedlist::LinkedList;
use crate::xkbcommon::ModifierState; use crate::xkbcommon::ModifierState;
@ -16,16 +14,17 @@ use crate::NumCell;
pub use container::*; pub use container::*;
pub use float::*; pub use float::*;
use i4config::Direction; use i4config::Direction;
use std::cell::{Cell, RefCell}; use std::fmt::{Debug, Display};
use std::fmt::{Debug, Display, Formatter};
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
pub use workspace::*; pub use workspace::*;
pub use output::*;
mod container; mod container;
mod float; mod float;
pub mod walker; pub mod walker;
mod workspace; mod workspace;
mod output;
pub struct NodeIds { pub struct NodeIds {
next: NumCell<u32>, next: NumCell<u32>,
@ -254,6 +253,14 @@ pub trait Node {
false false
} }
fn is_output(&self) -> bool {
false
}
fn into_output(self: Rc<Self>) -> Option<Rc<OutputNode>> {
None
}
fn accepts_child(&self, node: &dyn Node) -> bool { fn accepts_child(&self, node: &dyn Node) -> bool {
let _ = node; let _ = node;
false false
@ -422,87 +429,3 @@ impl Node for DisplayNode {
seat.set_known_cursor(KnownCursor::Default); seat.set_known_cursor(KnownCursor::Default);
} }
} }
tree_id!(OutputNodeId);
pub struct OutputNode {
pub display: Rc<DisplayNode>,
pub id: OutputNodeId,
pub position: Cell<Rect>,
pub global: Rc<WlOutputGlobal>,
pub workspaces: RefCell<Vec<Rc<WorkspaceNode>>>,
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
pub seat_state: NodeSeatState,
}
impl Debug for OutputNode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OutputNode").finish_non_exhaustive()
}
}
impl Node for OutputNode {
fn id(&self) -> NodeId {
self.id.into()
}
fn seat_state(&self) -> &NodeSeatState {
&self.seat_state
}
fn destroy_node(&self, detach: bool) {
if detach {
self.display.clone().remove_child(self);
}
let mut workspaces = self.workspaces.borrow_mut();
for workspace in workspaces.drain(..) {
workspace.destroy_node(false);
}
self.seat_state.destroy_node(self);
}
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
visitor.visit_output(&self);
}
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
let ws = self.workspaces.borrow_mut();
for ws in ws.deref() {
visitor.visit_workspace(ws);
}
}
fn absolute_position(&self) -> Rect {
self.position.get()
}
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
if let Some(ws) = self.workspace.get() {
tree.push(FoundNode {
node: ws.clone(),
x,
y,
});
ws.find_tree_at(x, y, tree);
}
FindTreeResult::AcceptsInput
}
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
self.workspace.set(None);
}
fn pointer_focus(&self, seat: &Rc<WlSeatGlobal>) {
seat.set_known_cursor(KnownCursor::Default);
}
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
renderer.render_output(self, x, y);
}
fn change_extents(self: Rc<Self>, rect: &Rect) {
self.position.set(*rect);
if let Some(c) = self.workspace.get() {
c.change_extents(rect);
}
}
}

117
src/tree/output.rs Normal file
View file

@ -0,0 +1,117 @@
use std::cell::{Cell, RefCell};
use std::fmt::{Debug, Formatter};
use std::ops::Deref;
use std::rc::Rc;
use crate::{CloneCell, DisplayNode};
use crate::cursor::KnownCursor;
use crate::ifs::wl_output::WlOutputGlobal;
use crate::ifs::wl_seat::{NodeSeatState, WlSeatGlobal};
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
use crate::rect::Rect;
use crate::render::Renderer;
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
use crate::tree::walker::NodeVisitor;
use crate::utils::linkedlist::LinkedList;
tree_id!(OutputNodeId);
pub struct OutputNode {
pub display: Rc<DisplayNode>,
pub id: OutputNodeId,
pub position: Cell<Rect>,
pub global: Rc<WlOutputGlobal>,
pub workspaces: RefCell<Vec<Rc<WorkspaceNode>>>,
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
pub seat_state: NodeSeatState,
pub layers: [LinkedList<Rc<ZwlrLayerSurfaceV1>>; 4],
}
impl Debug for OutputNode {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("OutputNode").finish_non_exhaustive()
}
}
impl Node for OutputNode {
fn id(&self) -> NodeId {
self.id.into()
}
fn seat_state(&self) -> &NodeSeatState {
&self.seat_state
}
fn destroy_node(&self, detach: bool) {
if detach {
self.display.clone().remove_child(self);
}
let mut workspaces = self.workspaces.borrow_mut();
for workspace in workspaces.drain(..) {
workspace.destroy_node(false);
}
self.seat_state.destroy_node(self);
}
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
visitor.visit_output(&self);
}
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
let ws = self.workspaces.borrow_mut();
for ws in ws.deref() {
visitor.visit_workspace(ws);
}
for layers in &self.layers {
for surface in layers.iter() {
visitor.visit_layer_surface(surface.deref());
}
}
}
fn absolute_position(&self) -> Rect {
self.position.get()
}
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
if let Some(ws) = self.workspace.get() {
tree.push(FoundNode {
node: ws.clone(),
x,
y,
});
ws.find_tree_at(x, y, tree);
}
FindTreeResult::AcceptsInput
}
fn remove_child(self: Rc<Self>, _child: &dyn Node) {
self.workspace.set(None);
}
fn pointer_focus(&self, seat: &Rc<WlSeatGlobal>) {
seat.set_known_cursor(KnownCursor::Default);
}
fn render(&self, renderer: &mut Renderer, x: i32, y: i32) {
renderer.render_output(self, x, y);
}
fn is_output(&self) -> bool {
true
}
fn into_output(self: Rc<Self>) -> Option<Rc<OutputNode>> {
Some(self)
}
fn change_extents(self: Rc<Self>, rect: &Rect) {
self.position.set(*rect);
if let Some(c) = self.workspace.get() {
c.change_extents(rect);
}
for layer in &self.layers {
for surface in layer.iter() {
surface.deref().clone().change_extents(rect);
}
}
}
}

View file

@ -4,6 +4,7 @@ use crate::ifs::wl_surface::WlSurface;
use crate::tree::{ContainerNode, FloatNode, Node, OutputNode, WorkspaceNode}; use crate::tree::{ContainerNode, FloatNode, Node, OutputNode, WorkspaceNode};
use crate::DisplayNode; use crate::DisplayNode;
use std::rc::Rc; use std::rc::Rc;
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
pub trait NodeVisitorBase: Sized { pub trait NodeVisitorBase: Sized {
fn visit_surface(&mut self, node: &Rc<WlSurface>) { fn visit_surface(&mut self, node: &Rc<WlSurface>) {
@ -37,6 +38,10 @@ pub trait NodeVisitorBase: Sized {
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) { fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
node.visit_children(self); node.visit_children(self);
} }
fn visit_layer_surface(&mut self, node: &Rc<ZwlrLayerSurfaceV1>) {
node.visit_children(self);
}
} }
pub trait NodeVisitor { pub trait NodeVisitor {
@ -48,6 +53,7 @@ pub trait NodeVisitor {
fn visit_output(&mut self, node: &Rc<OutputNode>); fn visit_output(&mut self, node: &Rc<OutputNode>);
fn visit_float(&mut self, node: &Rc<FloatNode>); fn visit_float(&mut self, node: &Rc<FloatNode>);
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>); fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>);
fn visit_layer_surface(&mut self, node: &Rc<ZwlrLayerSurfaceV1>);
} }
impl<T: NodeVisitorBase> NodeVisitor for T { impl<T: NodeVisitorBase> NodeVisitor for T {
@ -82,6 +88,10 @@ impl<T: NodeVisitorBase> NodeVisitor for T {
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) { fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
<T as NodeVisitorBase>::visit_workspace(self, node) <T as NodeVisitorBase>::visit_workspace(self, node)
} }
fn visit_layer_surface(&mut self, node: &Rc<ZwlrLayerSurfaceV1>) {
<T as NodeVisitorBase>::visit_layer_surface(self, node)
}
} }
// pub fn visit_containers<F: FnMut(&Rc<ContainerNode>)>(f: F) -> impl NodeVisitor { // pub fn visit_containers<F: FnMut(&Rc<ContainerNode>)>(f: F) -> impl NodeVisitor {

View file

@ -1 +1,3 @@
#![allow(non_upper_case_globals)]
include!(concat!(env!("OUT_DIR"), "/wire.rs")); include!(concat!(env!("OUT_DIR"), "/wire.rs"));

View file

@ -5,10 +5,11 @@
- presentation time - presentation time
- viewporter - viewporter
- session lock - session lock
- layer shell - xwayland
# done # done
- layer shell
- Float moving - Float moving
- Float toggle - Float toggle
- Container moving (kb) - Container moving (kb)

View file

@ -0,0 +1,12 @@
# requests
msg get_layer_surface = 0 {
id: id(zwlr_layer_surface_v1),
surface: id(wl_surface),
output: id(wl_output),
layer: u32,
namespace: str,
}
msg destroy = 1 {
}

View file

@ -0,0 +1,49 @@
# requests
msg set_size = 0 {
width: u32,
height: u32,
}
msg set_anchor = 1 {
anchor: u32,
}
msg set_exclusive_zone = 2 {
zone: i32,
}
msg set_margin = 3 {
top: i32,
right: i32,
bottom: i32,
left: i32,
}
msg set_keyboard_interactivity = 4 {
keyboard_interactivity: u32,
}
msg get_popup = 5 {
popup: id(xdg_popup),
}
msg ack_configure = 6 {
serial: u32,
}
msg destroy = 7 { }
msg set_layer = 8 {
layer: u32,
}
# events
msg configure = 0 {
serial: u32,
width: u32,
height: u32,
}
msg closed = 1 { }

View file

@ -0,0 +1,8 @@
# requests
msg destroy = 0 { }
msg get_xdg_output = 1 {
id: id(zxdg_output_v1),
output: id(wl_output),
}

25
wire/zxdg_output_v1.txt Normal file
View file

@ -0,0 +1,25 @@
# requests
msg destroy = 0 { }
# events
msg logical_position = 0 {
x: i32,
y: i32,
}
msg logical_size = 1 {
width: i32,
height: i32,
}
msg done = 2 { }
msg name = 3 {
name: str,
}
msg description = 4 {
description: str,
}