autocommit 2022-02-21 23:21:13 CET
This commit is contained in:
parent
1cbc7a6445
commit
145d1c15b7
31 changed files with 1455 additions and 252 deletions
|
|
@ -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::wl_buffer::WlBuffer;
|
||||
use crate::ifs::wl_display::WlDisplay;
|
||||
use crate::ifs::wl_output::WlOutput;
|
||||
use crate::ifs::wl_region::WlRegion;
|
||||
use crate::ifs::wl_registry::WlRegistry;
|
||||
use crate::ifs::wl_seat::WlSeat;
|
||||
|
|
@ -16,8 +17,8 @@ use crate::tree::Node;
|
|||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::wire::{
|
||||
WlBufferId, WlDataSourceId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId, XdgPositionerId,
|
||||
XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwpPrimarySelectionSourceV1Id,
|
||||
WlBufferId, WlDataSourceId, WlOutputId, WlRegionId, WlRegistryId, WlSeatId, WlSurfaceId,
|
||||
XdgPositionerId, XdgSurfaceId, XdgToplevelId, XdgWmBaseId, ZwpPrimarySelectionSourceV1Id,
|
||||
};
|
||||
use ahash::AHashMap;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
|
|
@ -29,6 +30,7 @@ pub struct Objects {
|
|||
pub display: CloneCell<Option<Rc<WlDisplay>>>,
|
||||
registry: CopyHashMap<ObjectId, Rc<dyn Object>>,
|
||||
registries: CopyHashMap<WlRegistryId, Rc<WlRegistry>>,
|
||||
pub outputs: CopyHashMap<WlOutputId, Rc<WlOutput>>,
|
||||
pub surfaces: CopyHashMap<WlSurfaceId, Rc<WlSurface>>,
|
||||
pub xdg_surfaces: CopyHashMap<XdgSurfaceId, Rc<XdgSurface>>,
|
||||
pub xdg_toplevel: CopyHashMap<XdgToplevelId, Rc<XdgToplevel>>,
|
||||
|
|
@ -52,6 +54,7 @@ impl Objects {
|
|||
display: CloneCell::new(None),
|
||||
registry: Default::default(),
|
||||
registries: Default::default(),
|
||||
outputs: Default::default(),
|
||||
surfaces: Default::default(),
|
||||
xdg_surfaces: Default::default(),
|
||||
xdg_toplevel: Default::default(),
|
||||
|
|
@ -83,6 +86,7 @@ impl Objects {
|
|||
}
|
||||
self.display.set(None);
|
||||
self.registries.clear();
|
||||
self.outputs.clear();
|
||||
self.surfaces.clear();
|
||||
self.xdg_surfaces.clear();
|
||||
self.wl_data_source.clear();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use crate::ifs::wl_drm::WlDrmGlobal;
|
|||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::ifs::wl_registry::WlRegistry;
|
||||
use crate::ifs::wl_seat::WlSeatGlobal;
|
||||
use crate::ifs::zwlr_layer_shell_v1::ZwlrLayerShellV1Global;
|
||||
use crate::object::{Interface, ObjectId};
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::{
|
||||
|
|
@ -18,6 +19,7 @@ use std::error::Error;
|
|||
use std::fmt::{Display, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::ifs::zxdg_output_manager_v1::ZxdgOutputManagerV1Global;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GlobalsError {
|
||||
|
|
@ -103,6 +105,8 @@ impl Globals {
|
|||
add_singleton!(ZxdgDecorationManagerV1Global);
|
||||
add_singleton!(OrgKdeKwinServerDecorationManagerGlobal);
|
||||
add_singleton!(ZwpPrimarySelectionDeviceManagerV1Global);
|
||||
add_singleton!(ZwlrLayerShellV1Global);
|
||||
add_singleton!(ZxdgOutputManagerV1Global);
|
||||
slf
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,10 @@ pub mod wl_subcompositor;
|
|||
pub mod wl_surface;
|
||||
pub mod xdg_positioner;
|
||||
pub mod xdg_wm_base;
|
||||
pub mod zwlr_layer_shell_v1;
|
||||
pub mod zwp_linux_buffer_params_v1;
|
||||
pub mod zwp_linux_dmabuf_v1;
|
||||
pub mod zxdg_decoration_manager_v1;
|
||||
pub mod zxdg_toplevel_decoration_v1;
|
||||
pub mod zxdg_output_manager_v1;
|
||||
pub mod zxdg_output_v1;
|
||||
|
|
|
|||
|
|
@ -6,12 +6,17 @@ use crate::object::Object;
|
|||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
use crate::wire::wl_output::*;
|
||||
use crate::wire::WlOutputId;
|
||||
use crate::wire::{WlOutputId, ZxdgOutputV1Id};
|
||||
use ahash::AHashMap;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::rc::Rc;
|
||||
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;
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -48,10 +53,8 @@ const MODE_PREFERRED: u32 = 2;
|
|||
pub struct WlOutputGlobal {
|
||||
name: GlobalName,
|
||||
output: Rc<dyn Output>,
|
||||
pub x: Cell<i32>,
|
||||
pub y: Cell<i32>,
|
||||
width: Cell<i32>,
|
||||
height: Cell<i32>,
|
||||
pos: Cell<Rect>,
|
||||
pub node: CloneCell<Option<Rc<OutputNode>>>,
|
||||
pub bindings: RefCell<AHashMap<ClientId, AHashMap<WlOutputId, Rc<WlOutput>>>>,
|
||||
}
|
||||
|
||||
|
|
@ -60,23 +63,27 @@ impl WlOutputGlobal {
|
|||
Self {
|
||||
name,
|
||||
output: output.clone(),
|
||||
x: Cell::new(0),
|
||||
y: Cell::new(0),
|
||||
width: Cell::new(output.width()),
|
||||
height: Cell::new(output.height()),
|
||||
pos: Cell::new(Rect::new_sized(0, 0, output.width(), output.height()).unwrap()),
|
||||
node: Default::default(),
|
||||
bindings: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Rect {
|
||||
self.pos.get()
|
||||
}
|
||||
|
||||
pub fn update_properties(&self) {
|
||||
let width = self.output.width();
|
||||
let height = self.output.height();
|
||||
|
||||
let mut changed = false;
|
||||
changed |= self.width.replace(width) != width;
|
||||
changed |= self.height.replace(height) != height;
|
||||
let pos = self.pos.get();
|
||||
let old_width = pos.width();
|
||||
let old_height = pos.height();
|
||||
let changed = old_width != width || old_height != height;
|
||||
|
||||
if changed {
|
||||
self.pos.set(Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap());
|
||||
let bindings = self.bindings.borrow_mut();
|
||||
for binding in bindings.values() {
|
||||
for binding in binding.values() {
|
||||
|
|
@ -85,6 +92,10 @@ impl WlOutputGlobal {
|
|||
binding.send_scale();
|
||||
binding.send_done();
|
||||
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 {
|
||||
global: self.clone(),
|
||||
id,
|
||||
xdg_outputs: Default::default(),
|
||||
client: client.clone(),
|
||||
version,
|
||||
tracker: Default::default(),
|
||||
|
|
@ -141,10 +153,11 @@ impl Global for WlOutputGlobal {
|
|||
dedicated_add_global!(WlOutputGlobal, outputs);
|
||||
|
||||
pub struct WlOutput {
|
||||
global: Rc<WlOutputGlobal>,
|
||||
pub global: Rc<WlOutputGlobal>,
|
||||
pub id: WlOutputId,
|
||||
pub xdg_outputs: CopyHashMap<ZxdgOutputV1Id, Rc<ZxdgOutputV1>>,
|
||||
client: Rc<Client>,
|
||||
version: u32,
|
||||
pub version: u32,
|
||||
tracker: Tracker<Self>,
|
||||
}
|
||||
|
||||
|
|
@ -153,12 +166,13 @@ pub const SEND_SCALE_SINCE: u32 = 2;
|
|||
|
||||
impl WlOutput {
|
||||
fn send_geometry(&self) {
|
||||
let pos = self.global.pos.get();
|
||||
let event = Geometry {
|
||||
self_id: self.id,
|
||||
x: 0,
|
||||
y: 0,
|
||||
physical_width: self.global.width.get() as _,
|
||||
physical_height: self.global.height.get() as _,
|
||||
x: pos.x1(),
|
||||
y: pos.y1(),
|
||||
physical_width: pos.width(),
|
||||
physical_height: pos.height(),
|
||||
subpixel: SP_UNKNOWN,
|
||||
make: "i4",
|
||||
model: "i4",
|
||||
|
|
@ -168,11 +182,12 @@ impl WlOutput {
|
|||
}
|
||||
|
||||
fn send_mode(&self) {
|
||||
let pos = self.global.pos.get();
|
||||
let event = Mode {
|
||||
self_id: self.id,
|
||||
flags: MODE_CURRENT,
|
||||
width: self.global.width.get() as _,
|
||||
height: self.global.height.get() as _,
|
||||
width: pos.width(),
|
||||
height: pos.height(),
|
||||
refresh: 60_000_000,
|
||||
};
|
||||
self.client.event(event);
|
||||
|
|
@ -186,7 +201,7 @@ impl WlOutput {
|
|||
self.client.event(event);
|
||||
}
|
||||
|
||||
fn send_done(&self) {
|
||||
pub fn send_done(&self) {
|
||||
let event = Done { self_id: self.id };
|
||||
self.client.event(event);
|
||||
}
|
||||
|
|
@ -202,6 +217,7 @@ impl WlOutput {
|
|||
|
||||
fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> {
|
||||
let _req: Release = self.client.parse(self, parser)?;
|
||||
self.xdg_outputs.clear();
|
||||
self.remove_binding();
|
||||
self.client.remove_obj(self)?;
|
||||
Ok(())
|
||||
|
|
@ -224,11 +240,12 @@ impl Object for WlOutput {
|
|||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.xdg_outputs.clear();
|
||||
self.remove_binding();
|
||||
}
|
||||
}
|
||||
|
||||
simple_add_obj!(WlOutput);
|
||||
dedicated_add_obj!(WlOutput, WlOutputId, outputs);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WlOutputError {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ mod pointer_owner;
|
|||
pub mod wl_keyboard;
|
||||
pub mod wl_pointer;
|
||||
pub mod wl_touch;
|
||||
mod kb_owner;
|
||||
|
||||
use crate::async_engine::SpawnedFuture;
|
||||
use crate::client::{Client, ClientError, ClientId};
|
||||
|
|
@ -43,10 +44,12 @@ use i4config::Direction;
|
|||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::mem;
|
||||
use std::ops::DerefMut;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use uapi::{c, Errno, OwnedFd};
|
||||
use crate::ifs::wl_output::{WlOutputGlobal};
|
||||
use crate::ifs::wl_seat::kb_owner::KbOwnerHolder;
|
||||
|
||||
const POINTER: u32 = 1;
|
||||
const KEYBOARD: u32 = 2;
|
||||
|
|
@ -112,6 +115,7 @@ pub struct WlSeatGlobal {
|
|||
selection: CloneCell<Option<Rc<WlDataSource>>>,
|
||||
primary_selection: CloneCell<Option<Rc<ZwpPrimarySelectionSourceV1>>>,
|
||||
pointer_owner: PointerOwnerHolder,
|
||||
kb_owner: KbOwnerHolder,
|
||||
dropped_dnd: RefCell<Option<DroppedDnd>>,
|
||||
shortcuts: CopyHashMap<(u32, u32), Modifiers>,
|
||||
queue_link: Cell<Option<LinkedNode<Rc<Self>>>>,
|
||||
|
|
@ -146,6 +150,7 @@ impl WlSeatGlobal {
|
|||
selection: Default::default(),
|
||||
primary_selection: Default::default(),
|
||||
pointer_owner: Default::default(),
|
||||
kb_owner: Default::default(),
|
||||
dropped_dnd: RefCell::new(None),
|
||||
shortcuts: Default::default(),
|
||||
queue_link: Cell::new(None),
|
||||
|
|
@ -162,6 +167,17 @@ impl WlSeatGlobal {
|
|||
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>) {
|
||||
self.queue_link
|
||||
.set(Some(self.state.seat_queue.add_last(self.clone())));
|
||||
|
|
|
|||
|
|
@ -75,6 +75,22 @@ impl NodeSeatState {
|
|||
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) {
|
||||
while let Some((_, seat)) = self.grabs.pop() {
|
||||
seat.pointer_owner.revert_to_default(&seat);
|
||||
|
|
@ -94,12 +110,7 @@ impl NodeSeatState {
|
|||
}
|
||||
seat.state.tree_changed();
|
||||
}
|
||||
while let Some((_, seat)) = self.kb_foci.pop() {
|
||||
seat.keyboard_node.set(seat.state.root.clone());
|
||||
if let Some(tl) = seat.toplevel_focus_history.last() {
|
||||
seat.focus_xdg_surface(&tl.xdg);
|
||||
}
|
||||
}
|
||||
self.release_kb_focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -124,8 +135,9 @@ impl WlSeatGlobal {
|
|||
Some(o) => o,
|
||||
_ => return,
|
||||
};
|
||||
x += Fixed::from_int(output.x.get());
|
||||
y += Fixed::from_int(output.y.get());
|
||||
let pos = output.position();
|
||||
x += Fixed::from_int(pos.x1());
|
||||
y += Fixed::from_int(pos.y1());
|
||||
self.set_new_position(x, y);
|
||||
}
|
||||
|
||||
|
|
@ -216,21 +228,16 @@ impl WlSeatGlobal {
|
|||
self.focus_node(xdg.focus_surface(self));
|
||||
}
|
||||
|
||||
pub fn focus_node(self: &Rc<Self>, node: Rc<dyn Node>) {
|
||||
let old = self.keyboard_node.get();
|
||||
if old.id() == node.id() {
|
||||
return;
|
||||
}
|
||||
old.unfocus(self);
|
||||
if old.seat_state().unfocus(self) {
|
||||
old.active_changed(false);
|
||||
}
|
||||
fn ungrab_kb(self: &Rc<Self>) {
|
||||
self.kb_owner.ungrab(self);
|
||||
}
|
||||
|
||||
if node.seat_state().focus(self) {
|
||||
node.active_changed(true);
|
||||
}
|
||||
node.clone().focus(self);
|
||||
self.keyboard_node.set(node.clone());
|
||||
pub fn grab(self: &Rc<Self>, node: Rc<dyn Node>) {
|
||||
self.kb_owner.grab(self, node);
|
||||
}
|
||||
|
||||
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>(
|
||||
|
|
@ -380,7 +387,7 @@ impl WlSeatGlobal {
|
|||
let serial = self.serial.fetch_add(1);
|
||||
self.surface_pointer_event(0, surface, |p| p.send_button(serial, 0, button, state));
|
||||
self.surface_pointer_frame(surface);
|
||||
if pressed && surface.belongs_to_toplevel() {
|
||||
if pressed && surface.accepts_kb_focus() {
|
||||
self.focus_node(surface.clone());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
85
src/ifs/wl_seat/kb_owner.rs
Normal file
85
src/ifs/wl_seat/kb_owner.rs
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -147,9 +147,11 @@ impl PointerOwner for DefaultPointerOwner {
|
|||
}
|
||||
if (stack.len(), found_tree.len()) == (divergence, divergence) {
|
||||
if let Some(node) = found_tree.last() {
|
||||
node.node
|
||||
.clone()
|
||||
.pointer_motion(seat, x.apply_fract(node.x), y.apply_fract(node.y));
|
||||
node.node.clone().pointer_motion(
|
||||
seat,
|
||||
x.apply_fract(node.x),
|
||||
y.apply_fract(node.y),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if let Some(last) = stack.last() {
|
||||
|
|
@ -161,16 +163,20 @@ impl PointerOwner for DefaultPointerOwner {
|
|||
}
|
||||
if found_tree.len() == divergence {
|
||||
if let Some(node) = found_tree.last() {
|
||||
node.node
|
||||
.clone()
|
||||
.pointer_motion(seat, x.apply_fract(node.x), y.apply_fract(node.y));
|
||||
node.node.clone().pointer_motion(
|
||||
seat,
|
||||
x.apply_fract(node.x),
|
||||
y.apply_fract(node.y),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
for new in found_tree.drain(divergence..) {
|
||||
new.node.seat_state().enter(seat);
|
||||
new.node
|
||||
.clone()
|
||||
.pointer_enter(seat, x.apply_fract(new.x), y.apply_fract(new.y));
|
||||
new.node.clone().pointer_enter(
|
||||
seat,
|
||||
x.apply_fract(new.x),
|
||||
y.apply_fract(new.y),
|
||||
);
|
||||
stack.push(new.node);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
pub mod cursor;
|
||||
pub mod wl_subsurface;
|
||||
pub mod xdg_surface;
|
||||
pub mod zwlr_layer_surface_v1;
|
||||
|
||||
use crate::backend::{KeyState, ScrollAxis};
|
||||
use crate::client::{Client, ClientError, RequestParser};
|
||||
|
|
@ -34,6 +35,7 @@ use std::mem;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error;
|
||||
|
||||
#[allow(dead_code)]
|
||||
const INVALID_SCALE: u32 = 0;
|
||||
|
|
@ -49,6 +51,7 @@ pub enum SurfaceRole {
|
|||
XdgSurface,
|
||||
Cursor,
|
||||
DndIcon,
|
||||
ZwlrLayerSurface,
|
||||
}
|
||||
|
||||
impl SurfaceRole {
|
||||
|
|
@ -59,6 +62,7 @@ impl SurfaceRole {
|
|||
SurfaceRole::XdgSurface => "xdg_surface",
|
||||
SurfaceRole::Cursor => "cursor",
|
||||
SurfaceRole::DndIcon => "dnd_icon",
|
||||
SurfaceRole::ZwlrLayerSurface => "zwlr_layer_surface",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,7 +115,7 @@ trait SurfaceExt {
|
|||
Ok(CommitAction::ContinueCommit)
|
||||
}
|
||||
|
||||
fn post_commit(&self) {
|
||||
fn post_commit(self: Rc<Self>) {
|
||||
// nothing
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +138,10 @@ trait SurfaceExt {
|
|||
fn into_subsurface(self: Rc<Self>) -> Option<Rc<WlSubsurface>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn accepts_kb_focus(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NoneSurfaceExt;
|
||||
|
|
@ -222,11 +230,11 @@ impl WlSurface {
|
|||
Ok(cursor)
|
||||
}
|
||||
|
||||
pub fn belongs_to_toplevel(&self) -> bool {
|
||||
pub fn accepts_kb_focus(&self) -> bool {
|
||||
if let Some(xdg) = self.xdg.get() {
|
||||
return xdg.role() == XdgSurfaceRole::XdgToplevel;
|
||||
}
|
||||
false
|
||||
self.ext.get().accepts_kb_focus()
|
||||
}
|
||||
|
||||
fn send_enter(&self, output: WlOutputId) {
|
||||
|
|
@ -747,6 +755,8 @@ pub enum WlSurfaceError {
|
|||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error(transparent)]
|
||||
ZwlrLayerSurfaceV1Error(Box<ZwlrLayerSurfaceV1Error>),
|
||||
#[error(transparent)]
|
||||
XdgSurfaceError(Box<XdgSurfaceError>),
|
||||
#[error("Could not process `destroy` request")]
|
||||
DestroyError(#[source] Box<DestroyError>),
|
||||
|
|
@ -784,13 +794,10 @@ efrom!(WlSurfaceError, FrameError);
|
|||
efrom!(WlSurfaceError, SetOpaqueRegionError);
|
||||
efrom!(WlSurfaceError, SetInputRegionError);
|
||||
efrom!(WlSurfaceError, CommitError);
|
||||
efrom!(
|
||||
WlSurfaceError,
|
||||
SetBufferTransformError,
|
||||
SetBufferTransformError
|
||||
);
|
||||
efrom!(WlSurfaceError, SetBufferTransformError);
|
||||
efrom!(WlSurfaceError, SetBufferScaleError);
|
||||
efrom!(WlSurfaceError, DamageBufferError);
|
||||
efrom!(WlSurfaceError, ZwlrLayerSurfaceV1Error);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DestroyError {
|
||||
|
|
|
|||
|
|
@ -263,9 +263,8 @@ impl SurfaceExt for WlSubsurface {
|
|||
Ok(CommitAction::ContinueCommit)
|
||||
}
|
||||
|
||||
fn post_commit(&self) {
|
||||
fn post_commit(self: Rc<Self>) {
|
||||
if let Some(v) = self.pending.node.take() {
|
||||
log::info!("post commit");
|
||||
v.pending.set(false);
|
||||
self.node.borrow_mut().replace(v);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ impl SurfaceExt for XdgSurface {
|
|||
Ok(CommitAction::ContinueCommit)
|
||||
}
|
||||
|
||||
fn post_commit(&self) {
|
||||
fn post_commit(self: Rc<Self>) {
|
||||
if let Some(ext) = self.ext.get() {
|
||||
ext.post_commit();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use std::fmt::{Debug, Formatter};
|
|||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use backtrace::Backtrace;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Copy, Clone, Debug, FromPrimitive)]
|
||||
|
|
|
|||
533
src/ifs/wl_surface/zwlr_layer_surface_v1.rs
Normal file
533
src/ifs/wl_surface/zwlr_layer_surface_v1.rs
Normal 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);
|
||||
176
src/ifs/zwlr_layer_shell_v1.rs
Normal file
176
src/ifs/zwlr_layer_shell_v1.rs
Normal 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);
|
||||
137
src/ifs/zxdg_output_manager_v1.rs
Normal file
137
src/ifs/zxdg_output_manager_v1.rs
Normal 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
107
src/ifs/zxdg_output_v1.rs
Normal 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);
|
||||
|
|
@ -44,14 +44,14 @@ macro_rules! object_base {
|
|||
}
|
||||
|
||||
fn interface(&self) -> crate::object::Interface {
|
||||
crate::object::Interface::$oname
|
||||
crate::wire::$oname
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$ename> for crate::client::ObjectError {
|
||||
fn from(v: $ename) -> Self {
|
||||
Self {
|
||||
interface: crate::object::Interface::$oname,
|
||||
interface: crate::wire::$oname,
|
||||
error: Box::new(v),
|
||||
}
|
||||
}
|
||||
|
|
@ -79,14 +79,14 @@ macro_rules! global_base {
|
|||
}
|
||||
|
||||
fn interface(&self) -> crate::object::Interface {
|
||||
crate::object::Interface::$ifname
|
||||
crate::wire::$ifname
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$ename> for crate::globals::GlobalError {
|
||||
fn from(e: $ename) -> Self {
|
||||
Self {
|
||||
interface: crate::object::Interface::$ifname,
|
||||
interface: crate::wire::$ifname,
|
||||
error: Box::new(e),
|
||||
}
|
||||
}
|
||||
|
|
@ -281,7 +281,7 @@ macro_rules! dedicated_add_obj {
|
|||
|
||||
impl crate::client::WaylandObjectLookup for $idname {
|
||||
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>> {
|
||||
client.objects.$field.get(&id)
|
||||
|
|
|
|||
|
|
@ -42,91 +42,11 @@ pub trait Object: ObjectBase + 'static {
|
|||
fn break_loops(&self) {}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Interface {
|
||||
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,
|
||||
}
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Interface(pub &'static str);
|
||||
|
||||
impl Interface {
|
||||
pub fn name(self) -> &'static str {
|
||||
match self {
|
||||
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",
|
||||
}
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use crate::State;
|
|||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
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 CHILD_COLOR: Color = Color::from_rgbaf(0.8, 0.8, 0.8, 1.0);
|
||||
|
|
@ -42,9 +43,21 @@ pub struct Renderer<'a> {
|
|||
|
||||
impl Renderer<'_> {
|
||||
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() {
|
||||
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) {
|
||||
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ impl OutputHandler {
|
|||
workspace: CloneCell::new(None),
|
||||
seat_state: Default::default(),
|
||||
global: global.clone(),
|
||||
layers: Default::default(),
|
||||
});
|
||||
global.node.set(Some(on.clone()));
|
||||
let workspace = Rc::new(WorkspaceNode {
|
||||
id: self.state.node_ids.next(),
|
||||
output: CloneCell::new(on.clone()),
|
||||
|
|
@ -60,6 +62,7 @@ impl OutputHandler {
|
|||
global.update_properties();
|
||||
ae.triggered().await;
|
||||
}
|
||||
global.node.set(None);
|
||||
self.state.outputs.remove(&self.output.id());
|
||||
let _ = self.state.remove_global(&*global);
|
||||
self.state
|
||||
|
|
|
|||
|
|
@ -345,7 +345,13 @@ impl ContainerNode {
|
|||
}
|
||||
_ => {
|
||||
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();
|
||||
|
|
|
|||
|
|
@ -2,13 +2,11 @@ use crate::backend::{KeyState, OutputId, ScrollAxis};
|
|||
use crate::client::{Client, ClientId};
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::ifs::wl_seat::{Dnd, NodeSeatState, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::rect::Rect;
|
||||
use crate::render::Renderer;
|
||||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::utils::clonecell::CloneCell;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::utils::linkedlist::LinkedList;
|
||||
use crate::xkbcommon::ModifierState;
|
||||
|
|
@ -16,16 +14,17 @@ use crate::NumCell;
|
|||
pub use container::*;
|
||||
pub use float::*;
|
||||
use i4config::Direction;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
pub use workspace::*;
|
||||
pub use output::*;
|
||||
|
||||
mod container;
|
||||
mod float;
|
||||
pub mod walker;
|
||||
mod workspace;
|
||||
mod output;
|
||||
|
||||
pub struct NodeIds {
|
||||
next: NumCell<u32>,
|
||||
|
|
@ -254,6 +253,14 @@ pub trait Node {
|
|||
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 {
|
||||
let _ = node;
|
||||
false
|
||||
|
|
@ -422,87 +429,3 @@ impl Node for DisplayNode {
|
|||
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
117
src/tree/output.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ use crate::ifs::wl_surface::WlSurface;
|
|||
use crate::tree::{ContainerNode, FloatNode, Node, OutputNode, WorkspaceNode};
|
||||
use crate::DisplayNode;
|
||||
use std::rc::Rc;
|
||||
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1;
|
||||
|
||||
pub trait NodeVisitorBase: Sized {
|
||||
fn visit_surface(&mut self, node: &Rc<WlSurface>) {
|
||||
|
|
@ -37,6 +38,10 @@ pub trait NodeVisitorBase: Sized {
|
|||
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
|
||||
node.visit_children(self);
|
||||
}
|
||||
|
||||
fn visit_layer_surface(&mut self, node: &Rc<ZwlrLayerSurfaceV1>) {
|
||||
node.visit_children(self);
|
||||
}
|
||||
}
|
||||
|
||||
pub trait NodeVisitor {
|
||||
|
|
@ -48,6 +53,7 @@ pub trait NodeVisitor {
|
|||
fn visit_output(&mut self, node: &Rc<OutputNode>);
|
||||
fn visit_float(&mut self, node: &Rc<FloatNode>);
|
||||
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>);
|
||||
fn visit_layer_surface(&mut self, node: &Rc<ZwlrLayerSurfaceV1>);
|
||||
}
|
||||
|
||||
impl<T: NodeVisitorBase> NodeVisitor for T {
|
||||
|
|
@ -82,6 +88,10 @@ impl<T: NodeVisitorBase> NodeVisitor for T {
|
|||
fn visit_workspace(&mut self, node: &Rc<WorkspaceNode>) {
|
||||
<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 {
|
||||
|
|
|
|||
|
|
@ -1 +1,3 @@
|
|||
#![allow(non_upper_case_globals)]
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/wire.rs"));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue