autocommit 2022-02-24 16:30:11 CET
This commit is contained in:
parent
666e475032
commit
7d28d30666
39 changed files with 1670 additions and 209 deletions
|
|
@ -20,6 +20,6 @@ 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;
|
||||
pub mod zxdg_toplevel_decoration_v1;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use crate::wire::wl_compositor::*;
|
|||
use crate::wire::WlCompositorId;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::xwayland::XWaylandEvent;
|
||||
|
||||
pub struct WlCompositorGlobal {
|
||||
name: GlobalName,
|
||||
|
|
@ -51,6 +52,9 @@ impl WlCompositor {
|
|||
let surface = Rc::new(WlSurface::new(surface.id, &self.client));
|
||||
track!(self.client, surface);
|
||||
self.client.add_client_obj(&surface)?;
|
||||
if let Some(queue) = &self.client.xwayland_queue {
|
||||
queue.push(XWaylandEvent::SurfaceCreated(surface.clone()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,10 @@ use bstr::ByteSlice;
|
|||
use std::ffi::CString;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::drm::dma::{DmaBuf, DmaBufPlane};
|
||||
use crate::drm::INVALID_MODIFIER;
|
||||
use crate::ifs::wl_buffer::WlBuffer;
|
||||
use crate::RenderError;
|
||||
|
||||
const PRIME: u32 = 1;
|
||||
|
||||
|
|
@ -52,7 +56,7 @@ impl Global for WlDrmGlobal {
|
|||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
1
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +106,60 @@ impl WlDrm {
|
|||
let _req: CreatePlanarBuffer = self.client.parse(&**self, parser)?;
|
||||
Err(CreatePlanarBufferError::Unsupported)
|
||||
}
|
||||
|
||||
fn create_prime_buffer(
|
||||
self: &Rc<Self>,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), CreatePrimeBufferError> {
|
||||
let req: CreatePrimeBuffer = self.client.parse(&**self, parser)?;
|
||||
let ctx = match self.client.state.render_ctx.get() {
|
||||
Some(ctx) => ctx,
|
||||
None => return Err(CreatePrimeBufferError::NoRenderContext),
|
||||
};
|
||||
let formats = ctx.formats();
|
||||
let format = match formats.get(&req.format) {
|
||||
Some(f) => *f,
|
||||
None => return Err(CreatePrimeBufferError::InvalidFormat(req.format)),
|
||||
};
|
||||
let mut dmabuf = DmaBuf {
|
||||
width: req.width,
|
||||
height: req.height,
|
||||
format,
|
||||
modifier: INVALID_MODIFIER,
|
||||
planes: vec![],
|
||||
};
|
||||
if req.stride0 > 0 {
|
||||
dmabuf.planes.push(DmaBufPlane {
|
||||
offset: req.offset0 as _,
|
||||
stride: req.stride0 as _,
|
||||
fd: req.name.clone(),
|
||||
});
|
||||
if req.stride1 > 0 {
|
||||
dmabuf.planes.push(DmaBufPlane {
|
||||
offset: req.offset1 as _,
|
||||
stride: req.stride1 as _,
|
||||
fd: req.name.clone(),
|
||||
});
|
||||
if req.stride2 > 0 {
|
||||
dmabuf.planes.push(DmaBufPlane {
|
||||
offset: req.offset2 as _,
|
||||
stride: req.stride2 as _,
|
||||
fd: req.name.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
let img = ctx.dmabuf_img(&dmabuf)?;
|
||||
let buffer = Rc::new(WlBuffer::new_dmabuf(
|
||||
req.id,
|
||||
&self.client,
|
||||
format,
|
||||
&img,
|
||||
));
|
||||
track!(self.client, buffer);
|
||||
self.client.add_client_obj(&buffer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
object_base! {
|
||||
|
|
@ -110,11 +168,12 @@ object_base! {
|
|||
AUTHENTICATE => authenticate,
|
||||
CREATE_BUFFER => create_buffer,
|
||||
CREATE_PLANAR_BUFFER => create_planar_buffer,
|
||||
CREATE_PRIME_BUFFER => create_prime_buffer,
|
||||
}
|
||||
|
||||
impl Object for WlDrm {
|
||||
fn num_requests(&self) -> u32 {
|
||||
CREATE_PLANAR_BUFFER + 1
|
||||
CREATE_PRIME_BUFFER + 1
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -128,6 +187,8 @@ pub enum WlDrmError {
|
|||
CreateBufferError(#[from] CreateBufferError),
|
||||
#[error("Could not process a `create_planar_buffer` request")]
|
||||
CreatePlanarBufferError(#[from] CreatePlanarBufferError),
|
||||
#[error("Could not process a `create_prime_buffer` request")]
|
||||
CreatePrimeBufferError(#[from] CreatePrimeBufferError),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
|
|
@ -157,3 +218,19 @@ pub enum CreatePlanarBufferError {
|
|||
Unsupported,
|
||||
}
|
||||
efrom!(CreatePlanarBufferError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CreatePrimeBufferError {
|
||||
#[error("Parsing failed")]
|
||||
MsgParserError(#[source] Box<MsgParserError>),
|
||||
#[error("The compositor has no render context attached")]
|
||||
NoRenderContext,
|
||||
#[error("The format {0} is not supported")]
|
||||
InvalidFormat(u32),
|
||||
#[error("Could not import the buffer")]
|
||||
ImportError(#[from] RenderError),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(CreatePrimeBufferError, MsgParserError);
|
||||
efrom!(CreatePrimeBufferError, ClientError);
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
use crate::backend::Output;
|
||||
use crate::client::{Client, ClientError, ClientId};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::zxdg_output_v1::ZxdgOutputV1;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::rect::Rect;
|
||||
use crate::tree::OutputNode;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use crate::wire::wl_output::*;
|
||||
use crate::wire::{WlOutputId, ZxdgOutputV1Id};
|
||||
use crate::CloneCell;
|
||||
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)]
|
||||
|
|
@ -83,7 +83,8 @@ impl WlOutputGlobal {
|
|||
let changed = old_width != width || old_height != height;
|
||||
|
||||
if changed {
|
||||
self.pos.set(Rect::new_sized(pos.x1(), pos.y1(), width, height).unwrap());
|
||||
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() {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
mod event_handling;
|
||||
mod kb_owner;
|
||||
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};
|
||||
|
|
@ -16,11 +16,12 @@ use crate::ifs::ipc::wl_data_source::WlDataSource;
|
|||
use crate::ifs::ipc::zwp_primary_selection_device_v1::ZwpPrimarySelectionDeviceV1;
|
||||
use crate::ifs::ipc::zwp_primary_selection_source_v1::ZwpPrimarySelectionSourceV1;
|
||||
use crate::ifs::ipc::IpcError;
|
||||
use crate::ifs::wl_output::WlOutputGlobal;
|
||||
use crate::ifs::wl_seat::kb_owner::KbOwnerHolder;
|
||||
use crate::ifs::wl_seat::pointer_owner::PointerOwnerHolder;
|
||||
use crate::ifs::wl_seat::wl_keyboard::{WlKeyboard, WlKeyboardError, REPEAT_INFO_SINCE};
|
||||
use crate::ifs::wl_seat::wl_pointer::WlPointer;
|
||||
use crate::ifs::wl_seat::wl_touch::WlTouch;
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::{Object, ObjectId};
|
||||
|
|
@ -48,8 +49,7 @@ 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;
|
||||
use crate::tree::toplevel::ToplevelNode;
|
||||
|
||||
const POINTER: u32 = 1;
|
||||
const KEYBOARD: u32 = 2;
|
||||
|
|
@ -95,7 +95,7 @@ pub struct WlSeatGlobal {
|
|||
pos: Cell<(Fixed, Fixed)>,
|
||||
pointer_stack: RefCell<Vec<Rc<dyn Node>>>,
|
||||
found_tree: RefCell<Vec<FoundNode>>,
|
||||
toplevel_focus_history: LinkedList<Rc<XdgToplevel>>,
|
||||
toplevel_focus_history: LinkedList<Rc<dyn ToplevelNode>>,
|
||||
keyboard_node: CloneCell<Rc<dyn Node>>,
|
||||
pressed_keys: RefCell<AHashSet<u32>>,
|
||||
bindings: RefCell<AHashMap<ClientId, AHashMap<WlSeatId, Rc<WlSeat>>>>,
|
||||
|
|
|
|||
|
|
@ -8,8 +8,6 @@ use crate::ifs::wl_seat::wl_keyboard::WlKeyboard;
|
|||
use crate::ifs::wl_seat::wl_pointer::{WlPointer, POINTER_FRAME_SINCE_VERSION};
|
||||
use crate::ifs::wl_seat::{wl_keyboard, wl_pointer, Dnd, SeatId, WlSeat, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_popup::XdgPopup;
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
|
||||
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::object::ObjectId;
|
||||
use crate::tree::{FloatNode, Node};
|
||||
|
|
@ -23,6 +21,7 @@ use i4config::keyboard::ModifiedKeySym;
|
|||
use smallvec::SmallVec;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use crate::tree::toplevel::ToplevelNode;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NodeSeatState {
|
||||
|
|
@ -86,7 +85,7 @@ impl NodeSeatState {
|
|||
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);
|
||||
seat.focus_node(tl.focus_surface(&seat));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -201,7 +200,7 @@ impl WlSeatGlobal {
|
|||
self.pointer_stack.borrow().last().cloned()
|
||||
}
|
||||
|
||||
pub fn last_tiled_keyboard_toplevel(&self, new: &dyn Node) -> Option<Rc<XdgToplevel>> {
|
||||
pub fn last_tiled_keyboard_toplevel(&self, new: &dyn Node) -> Option<Rc<dyn ToplevelNode>> {
|
||||
let is_container = new.is_container();
|
||||
for tl in self.toplevel_focus_history.rev_iter() {
|
||||
if !tl.parent_is_float() && (!is_container || !tl.is_contained_in(new.id())) {
|
||||
|
|
@ -218,14 +217,10 @@ impl WlSeatGlobal {
|
|||
self.extents_start_pos.set((ex.x1(), ex.y1()));
|
||||
}
|
||||
|
||||
pub fn focus_toplevel(self: &Rc<Self>, n: &Rc<XdgToplevel>) {
|
||||
pub fn focus_toplevel(self: &Rc<Self>, n: Rc<dyn ToplevelNode>) {
|
||||
let node = self.toplevel_focus_history.add_last(n.clone());
|
||||
n.toplevel_history.insert(self.id(), node);
|
||||
self.focus_xdg_surface(&n.xdg);
|
||||
}
|
||||
|
||||
fn focus_xdg_surface(self: &Rc<Self>, xdg: &Rc<XdgSurface>) {
|
||||
self.focus_node(xdg.focus_surface(self));
|
||||
n.set_focus_history_link(self, node);
|
||||
self.focus_node(n.focus_surface(self));
|
||||
}
|
||||
|
||||
fn ungrab_kb(self: &Rc<Self>) {
|
||||
|
|
@ -415,7 +410,7 @@ impl WlSeatGlobal {
|
|||
|
||||
// Enter callbacks
|
||||
impl WlSeatGlobal {
|
||||
pub fn enter_toplevel(self: &Rc<Self>, n: &Rc<XdgToplevel>) {
|
||||
pub fn enter_toplevel(self: &Rc<Self>, n: Rc<dyn ToplevelNode>) {
|
||||
self.focus_toplevel(n);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::rc::Rc;
|
||||
use crate::CloneCell;
|
||||
use crate::ifs::wl_seat::WlSeatGlobal;
|
||||
use crate::tree::Node;
|
||||
use crate::CloneCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct KbOwnerHolder {
|
||||
default: Rc<DefaultKbOwner>,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ pub mod cursor;
|
|||
pub mod wl_subsurface;
|
||||
pub mod xdg_surface;
|
||||
pub mod zwlr_layer_surface_v1;
|
||||
pub mod xwindow;
|
||||
|
||||
use crate::backend::{KeyState, ScrollAxis};
|
||||
use crate::client::{Client, ClientError, RequestParser};
|
||||
|
|
@ -12,6 +13,7 @@ use crate::ifs::wl_seat::{Dnd, NodeSeatState, SeatId, WlSeatGlobal};
|
|||
use crate::ifs::wl_surface::cursor::CursorSurface;
|
||||
use crate::ifs::wl_surface::wl_subsurface::WlSubsurface;
|
||||
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, XdgSurfaceError, XdgSurfaceRole};
|
||||
use crate::ifs::wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error;
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::pixman::Region;
|
||||
|
|
@ -35,7 +37,6 @@ 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;
|
||||
|
|
@ -52,6 +53,7 @@ pub enum SurfaceRole {
|
|||
Cursor,
|
||||
DndIcon,
|
||||
ZwlrLayerSurface,
|
||||
XSurface,
|
||||
}
|
||||
|
||||
impl SurfaceRole {
|
||||
|
|
@ -63,6 +65,7 @@ impl SurfaceRole {
|
|||
SurfaceRole::Cursor => "cursor",
|
||||
SurfaceRole::DndIcon => "dnd_icon",
|
||||
SurfaceRole::ZwlrLayerSurface => "zwlr_layer_surface",
|
||||
SurfaceRole::XSurface => "xwayland surface",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -123,6 +126,14 @@ trait SurfaceExt {
|
|||
true
|
||||
}
|
||||
|
||||
fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> {
|
||||
if self.is_some() {
|
||||
Err(WlSurfaceError::ReloObjectStillExists)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn update_subsurface_parent_extents(&self) {
|
||||
// nothing
|
||||
}
|
||||
|
|
@ -343,10 +354,8 @@ impl WlSurface {
|
|||
let _req: Destroy = self.parse(parser)?;
|
||||
self.unset_dnd_icons();
|
||||
self.unset_cursors();
|
||||
self.ext.get().on_surface_destroy()?;
|
||||
self.destroy_node(true);
|
||||
if self.ext.get().is_some() {
|
||||
return Err(DestroyError::ReloObjectStillExists);
|
||||
}
|
||||
{
|
||||
let mut children = self.children.borrow_mut();
|
||||
if let Some(children) = &mut *children {
|
||||
|
|
@ -784,6 +793,8 @@ pub enum WlSurfaceError {
|
|||
old: SurfaceRole,
|
||||
new: SurfaceRole,
|
||||
},
|
||||
#[error("Cannot destroy a `wl_surface` before its role object")]
|
||||
ReloObjectStillExists,
|
||||
}
|
||||
efrom!(WlSurfaceError, ClientError);
|
||||
efrom!(WlSurfaceError, XdgSurfaceError);
|
||||
|
|
@ -805,11 +816,12 @@ pub enum DestroyError {
|
|||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error("Cannot destroy a `wl_surface` before its role object")]
|
||||
ReloObjectStillExists,
|
||||
#[error(transparent)]
|
||||
WlSurfaceError(Box<WlSurfaceError>),
|
||||
}
|
||||
efrom!(DestroyError, ParseFailed, MsgParserError);
|
||||
efrom!(DestroyError, ClientError);
|
||||
efrom!(DestroyError, WlSurfaceError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AttachError {
|
||||
|
|
|
|||
|
|
@ -231,12 +231,6 @@ impl XdgSurface {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn focus_surface(&self, seat: &WlSeatGlobal) -> Rc<WlSurface> {
|
||||
self.focus_surface
|
||||
.get(&seat.id())
|
||||
.unwrap_or_else(|| self.surface.clone())
|
||||
}
|
||||
|
||||
fn destroy_node(&self) {
|
||||
self.workspace.set(None);
|
||||
self.surface.destroy_node(false);
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ use std::fmt::{Debug, Formatter};
|
|||
use std::mem;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use backtrace::Backtrace;
|
||||
|
||||
use thiserror::Error;
|
||||
use crate::ifs::wl_surface::WlSurface;
|
||||
use crate::tree::toplevel::ToplevelNode;
|
||||
|
||||
#[derive(Copy, Clone, Debug, FromPrimitive)]
|
||||
pub enum ResizeEdge {
|
||||
|
|
@ -75,7 +77,7 @@ pub struct XdgToplevel {
|
|||
pub parent: CloneCell<Option<Rc<XdgToplevel>>>,
|
||||
pub children: RefCell<AHashMap<XdgToplevelId, Rc<XdgToplevel>>>,
|
||||
states: RefCell<AHashSet<u32>>,
|
||||
pub toplevel_history: SmallMap<SeatId, LinkedNode<Rc<XdgToplevel>>, 1>,
|
||||
pub toplevel_history: SmallMap<SeatId, LinkedNode<Rc<dyn ToplevelNode>>, 1>,
|
||||
active_surfaces: NumCell<u32>,
|
||||
pub decoration: Cell<Decoration>,
|
||||
bugs: Cell<&'static Bugs>,
|
||||
|
|
@ -139,13 +141,6 @@ impl XdgToplevel {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parent_is_float(&self) -> bool {
|
||||
if let Some(parent) = self.parent_node.get() {
|
||||
return parent.is_float();
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn send_configure_checked(&self, mut width: i32, mut height: i32) {
|
||||
width = width.max(1);
|
||||
height = height.max(1);
|
||||
|
|
@ -429,7 +424,7 @@ impl Node for XdgToplevel {
|
|||
}
|
||||
|
||||
fn do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
||||
seat.focus_toplevel(&self);
|
||||
seat.focus_toplevel(self);
|
||||
}
|
||||
|
||||
fn absolute_position(&self) -> Rect {
|
||||
|
|
@ -441,7 +436,7 @@ impl Node for XdgToplevel {
|
|||
}
|
||||
|
||||
fn pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _x: Fixed, _y: Fixed) {
|
||||
seat.enter_toplevel(&self);
|
||||
seat.enter_toplevel(self);
|
||||
}
|
||||
|
||||
fn pointer_focus(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
|
|
@ -478,6 +473,27 @@ impl Node for XdgToplevel {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToplevelNode for XdgToplevel {
|
||||
fn parent(&self) -> Option<Rc<dyn Node>> {
|
||||
self.parent_node.get()
|
||||
}
|
||||
|
||||
fn focus_surface(&self, seat: &WlSeatGlobal) -> Rc<WlSurface> {
|
||||
self.xdg
|
||||
.focus_surface
|
||||
.get(&seat.id())
|
||||
.unwrap_or_else(|| self.xdg.surface.clone())
|
||||
}
|
||||
|
||||
fn set_focus_history_link(&self, seat: &WlSeatGlobal, link: LinkedNode<Rc<dyn ToplevelNode>>) {
|
||||
self.toplevel_history.insert(seat.id(), link);
|
||||
}
|
||||
|
||||
fn as_node(&self) -> &dyn Node {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl XdgSurfaceExt for XdgToplevel {
|
||||
fn focus_parent(&self, seat: &Rc<WlSeatGlobal>) {
|
||||
self.parent_node.get().map(|p| p.focus_self(seat));
|
||||
|
|
@ -564,7 +580,7 @@ impl XdgSurfaceExt for XdgToplevel {
|
|||
{
|
||||
let seats = surface.client.state.globals.lock_seats();
|
||||
for seat in seats.values() {
|
||||
seat.focus_toplevel(&self);
|
||||
seat.focus_toplevel(self.clone());
|
||||
}
|
||||
}
|
||||
surface.client.state.tree_changed();
|
||||
|
|
|
|||
247
src/ifs/wl_surface/xwindow.rs
Normal file
247
src/ifs/wl_surface/xwindow.rs
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use x11rb::protocol::xproto::Window;
|
||||
use i4config::Direction;
|
||||
use crate::client::Client;
|
||||
use crate::{AsyncQueue, CloneCell, State};
|
||||
use crate::cursor::KnownCursor;
|
||||
use crate::fixed::Fixed;
|
||||
use crate::ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal};
|
||||
use crate::ifs::wl_surface::{SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError};
|
||||
use crate::rect::Rect;
|
||||
use crate::render::Renderer;
|
||||
use crate::tree::{FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode};
|
||||
use crate::tree::toplevel::ToplevelNode;
|
||||
use crate::tree::walker::NodeVisitor;
|
||||
use crate::utils::linkedlist::LinkedNode;
|
||||
use crate::utils::smallmap::SmallMap;
|
||||
use crate::wire::WlSurfaceId;
|
||||
use crate::xwayland::XWaylandEvent;
|
||||
|
||||
pub struct XwindowData {
|
||||
pub state: Rc<State>,
|
||||
pub window_id: Window,
|
||||
pub client: Rc<Client>,
|
||||
pub surface_id: Cell<Option<WlSurfaceId>>,
|
||||
pub window: CloneCell<Option<Rc<Xwindow>>>,
|
||||
}
|
||||
|
||||
tree_id!(XwindowId);
|
||||
pub struct Xwindow {
|
||||
pub id: XwindowId,
|
||||
pub seat_state: NodeSeatState,
|
||||
pub data: Rc<XwindowData>,
|
||||
pub surface: Rc<WlSurface>,
|
||||
pub parent: CloneCell<Option<Rc<dyn Node>>>,
|
||||
pub focus_history: SmallMap<SeatId, LinkedNode<Rc<dyn ToplevelNode>>, 1>,
|
||||
pub events: Rc<AsyncQueue<XWaylandEvent>>,
|
||||
pub extents: Cell<Rect>,
|
||||
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
|
||||
}
|
||||
|
||||
impl XwindowData {
|
||||
pub fn new(state: &Rc<State>, window_id: Window, client: &Rc<Client>) -> Self {
|
||||
Self {
|
||||
state: state.clone(),
|
||||
window_id,
|
||||
client: client.clone(),
|
||||
surface_id: Cell::new(None),
|
||||
window: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Xwindow {
|
||||
pub fn new(data: &Rc<XwindowData>, surface: &Rc<WlSurface>, events: &Rc<AsyncQueue<XWaylandEvent>>) -> Self {
|
||||
Self {
|
||||
id: data.state.node_ids.next(),
|
||||
seat_state: Default::default(),
|
||||
data: data.clone(),
|
||||
surface: surface.clone(),
|
||||
parent: Default::default(),
|
||||
focus_history: Default::default(),
|
||||
events: events.clone(),
|
||||
extents: Default::default(),
|
||||
workspace: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn destroy(&self) {
|
||||
self.break_loops();
|
||||
self.data.window.take();
|
||||
}
|
||||
|
||||
pub fn break_loops(&self) {
|
||||
self.destroy_node(true);
|
||||
}
|
||||
|
||||
pub fn install(self: &Rc<Self>) -> Result<(), XWindowError> {
|
||||
self.surface.set_role(SurfaceRole::XSurface)?;
|
||||
if self.surface.ext.get().is_some() {
|
||||
return Err(XWindowError::AlreadyAttached);
|
||||
}
|
||||
self.surface.ext.set(self.clone());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn notify_parent(&self) {
|
||||
let parent = match self.parent.get() {
|
||||
Some(p) => p,
|
||||
_ => return,
|
||||
};
|
||||
let extents = self.surface.extents.get();
|
||||
// let extents = self.xdg.extents.get();
|
||||
// parent.child_active_changed(self, self.active_surfaces.get() > 0);
|
||||
parent.child_size_changed(self, extents.width(), extents.height());
|
||||
// parent.child_title_changed(self, self.title.borrow_mut().deref());
|
||||
}
|
||||
}
|
||||
|
||||
impl SurfaceExt for Xwindow {
|
||||
fn post_commit(self: Rc<Self>) {
|
||||
let parent = self.parent.get();
|
||||
if self.surface.buffer.get().is_some() {
|
||||
if parent.is_none() {
|
||||
self.data.state.map_tiled(self.clone());
|
||||
}
|
||||
} else {
|
||||
if parent.is_some() {
|
||||
self.destroy_node(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn on_surface_destroy(&self) -> Result<(), WlSurfaceError> {
|
||||
self.destroy_node(true);
|
||||
self.surface.unset_ext();
|
||||
self.data.window.set(None);
|
||||
self.data.surface_id.set(None);
|
||||
self.events.push(XWaylandEvent::SurfaceDestroyed(self.surface.id));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extents_changed(&self) {
|
||||
self.notify_parent();
|
||||
}
|
||||
}
|
||||
|
||||
impl Node for Xwindow {
|
||||
fn id(&self) -> NodeId {
|
||||
self.id.into()
|
||||
}
|
||||
|
||||
fn seat_state(&self) -> &NodeSeatState {
|
||||
&self.seat_state
|
||||
}
|
||||
|
||||
fn destroy_node(&self, _detach: bool) {
|
||||
self.workspace.take();
|
||||
self.focus_history.clear();
|
||||
if let Some(parent) = self.parent.take() {
|
||||
parent.remove_child(self);
|
||||
}
|
||||
self.surface.destroy_node(false);
|
||||
self.seat_state.destroy_node(self);
|
||||
}
|
||||
|
||||
fn visit(self: Rc<Self>, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_xwindow(&self);
|
||||
}
|
||||
|
||||
fn visit_children(&self, visitor: &mut dyn NodeVisitor) {
|
||||
visitor.visit_surface(&self.surface);
|
||||
}
|
||||
|
||||
fn is_contained_in(&self, other: NodeId) -> bool {
|
||||
if let Some(parent) = self.parent.get() {
|
||||
if parent.id() == other {
|
||||
return true;
|
||||
}
|
||||
return parent.is_contained_in(other);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn do_focus(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _direction: Direction) {
|
||||
seat.focus_toplevel(self);
|
||||
}
|
||||
|
||||
fn absolute_position(&self) -> Rect {
|
||||
self.extents.get()
|
||||
}
|
||||
|
||||
fn find_tree_at(&self, x: i32, y: i32, tree: &mut Vec<FoundNode>) -> FindTreeResult {
|
||||
if let Some(buffer) = self.surface.buffer.get() {
|
||||
if x < buffer.rect.width() && y < buffer.rect.height() {
|
||||
tree.push(FoundNode {
|
||||
node: self.surface.clone(),
|
||||
x,
|
||||
y,
|
||||
});
|
||||
return FindTreeResult::AcceptsInput;
|
||||
}
|
||||
}
|
||||
FindTreeResult::Other
|
||||
}
|
||||
|
||||
fn pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, _x: Fixed, _y: Fixed) {
|
||||
seat.enter_toplevel(self);
|
||||
}
|
||||
|
||||
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_surface(&self.surface, x, y)
|
||||
}
|
||||
|
||||
fn change_extents(self: Rc<Self>, rect: &Rect) {
|
||||
let nw = rect.width();
|
||||
let nh = rect.height();
|
||||
let de = self.extents.replace(*rect);
|
||||
if de.width() != nw || de.height() != nh {
|
||||
self.events.push(XWaylandEvent::Configure(self.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
fn set_workspace(self: Rc<Self>, ws: &Rc<WorkspaceNode>) {
|
||||
self.workspace.set(Some(ws.clone()));
|
||||
}
|
||||
|
||||
fn set_parent(self: Rc<Self>, parent: Rc<dyn Node>) {
|
||||
self.parent.set(Some(parent));
|
||||
self.notify_parent();
|
||||
}
|
||||
|
||||
fn client(&self) -> Option<Rc<Client>> {
|
||||
Some(self.data.client.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToplevelNode for Xwindow {
|
||||
fn parent(&self) -> Option<Rc<dyn Node>> {
|
||||
self.parent.get()
|
||||
}
|
||||
|
||||
fn focus_surface(&self, _seat: &WlSeatGlobal) -> Rc<WlSurface> {
|
||||
self.surface.clone()
|
||||
}
|
||||
|
||||
fn set_focus_history_link(&self, seat: &WlSeatGlobal, link: LinkedNode<Rc<dyn ToplevelNode>>) {
|
||||
self.focus_history.insert(seat.id(), link);
|
||||
}
|
||||
|
||||
fn as_node(&self) -> &dyn Node {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XWindowError {
|
||||
#[error("The surface is already attached")]
|
||||
AlreadyAttached,
|
||||
#[error(transparent)]
|
||||
WlSurfaceError(#[from] WlSurfaceError),
|
||||
}
|
||||
|
|
@ -1,29 +1,26 @@
|
|||
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::client::{Client, ClientError};
|
||||
use crate::ifs::wl_seat::NodeSeatState;
|
||||
use crate::ifs::wl_surface::{
|
||||
CommitAction, CommitContext, SurfaceExt, SurfaceRole, WlSurface, WlSurfaceError,
|
||||
};
|
||||
use crate::ifs::zwlr_layer_shell_v1::{ZwlrLayerShellV1, OVERLAY};
|
||||
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::tree::{FindTreeResult, FoundNode, Node, NodeId, OutputNode};
|
||||
use crate::utils::bitflags::BitflagsExt;
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::buffd::MsgParserError;
|
||||
use crate::utils::linkedlist::LinkedNode;
|
||||
use crate::wire::zwlr_layer_surface_v1::*;
|
||||
use crate::wire::{WlSurfaceId, ZwlrLayerSurfaceV1Id};
|
||||
use crate::NumCell;
|
||||
use std::cell::Cell;
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
const KI_NONE: u32 = 0;
|
||||
#[allow(dead_code)]
|
||||
|
|
@ -100,7 +97,7 @@ impl ZwlrLayerSurfaceV1 {
|
|||
margin: Cell::new((0, 0, 0, 0)),
|
||||
keyboard_interactivity: Cell::new(0),
|
||||
link: Cell::new(None),
|
||||
seat_state: Default::default()
|
||||
seat_state: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +129,9 @@ impl ZwlrLayerSurfaceV1 {
|
|||
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 _)));
|
||||
self.pending
|
||||
.size
|
||||
.set(Some((req.width as _, req.height as _)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -153,16 +152,25 @@ impl ZwlrLayerSurfaceV1 {
|
|||
|
||||
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)));
|
||||
self.pending
|
||||
.margin
|
||||
.set(Some((req.top, req.right, req.bottom, req.left)));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_keyboard_interactivity(&self, parser: MsgParser<'_, '_>) -> Result<(), SetKeyboardInteractivityError> {
|
||||
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));
|
||||
return Err(SetKeyboardInteractivityError::UnknownKi(
|
||||
req.keyboard_interactivity,
|
||||
));
|
||||
}
|
||||
self.pending.keyboard_interactivity.set(Some(req.keyboard_interactivity));
|
||||
self.pending
|
||||
.keyboard_interactivity
|
||||
.set(Some(req.keyboard_interactivity));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +279,8 @@ impl ZwlrLayerSurfaceV1 {
|
|||
} else if anchor.contains(BOTTOM) {
|
||||
y1 += opos.height() - height;
|
||||
}
|
||||
self.pos.set(Rect::new_sized(x1, y1, width, height).unwrap());
|
||||
self.pos
|
||||
.set(Rect::new_sized(x1, y1, width, height).unwrap());
|
||||
self.client.state.tree_changed();
|
||||
}
|
||||
}
|
||||
|
|
@ -308,7 +317,7 @@ impl SurfaceExt for ZwlrLayerSurfaceV1 {
|
|||
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();
|
||||
|
|
@ -362,7 +371,7 @@ impl Node for ZwlrLayerSurfaceV1 {
|
|||
tree.push(FoundNode {
|
||||
node: self.surface.clone(),
|
||||
x,
|
||||
y
|
||||
y,
|
||||
});
|
||||
self.surface.find_tree_at(x, y, tree)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
use crate::client::{Client, ClientError};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::zxdg_output_v1::ZxdgOutputV1;
|
||||
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 crate::wire::ZxdgOutputManagerV1Id;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::ifs::zxdg_output_v1::ZxdgOutputV1;
|
||||
|
||||
pub struct ZxdgOutputManagerV1Global {
|
||||
name: GlobalName,
|
||||
|
|
@ -51,10 +51,7 @@ impl ZxdgOutputManagerV1 {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn get_xdg_output(
|
||||
self: &Rc<Self>,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), GetXdgOutputError> {
|
||||
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 {
|
||||
|
|
@ -62,7 +59,7 @@ impl ZxdgOutputManagerV1 {
|
|||
version: self.version,
|
||||
client: self.client.clone(),
|
||||
output: output.clone(),
|
||||
tracker: Default::default()
|
||||
tracker: Default::default(),
|
||||
});
|
||||
track!(self.client, xdg_output);
|
||||
self.client.add_client_obj(&xdg_output)?;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::client::{Client, ClientError};
|
||||
use crate::ifs::wl_output::{SEND_DONE_SINCE, WlOutput};
|
||||
use crate::ifs::wl_output::{WlOutput, SEND_DONE_SINCE};
|
||||
use crate::leaks::Tracker;
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::wire::ZxdgOutputV1Id;
|
||||
use crate::wire::zxdg_output_v1::*;
|
||||
use crate::wire::ZxdgOutputV1Id;
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub const NAME_SINCE: u32 = 2;
|
||||
#[allow(dead_code)]
|
||||
pub const DESCRIPTION_SINCE: u32 = 2;
|
||||
pub const NO_DONE_SINCE: u32 = 3;
|
||||
|
||||
|
|
@ -38,11 +40,10 @@ impl ZxdgOutputV1 {
|
|||
}
|
||||
|
||||
pub fn send_done(&self) {
|
||||
self.client.event(Done {
|
||||
self_id: self.id,
|
||||
});
|
||||
self.client.event(Done { self_id: self.id });
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn send_name(&self, name: &str) {
|
||||
self.client.event(Name {
|
||||
self_id: self.id,
|
||||
|
|
@ -50,6 +51,7 @@ impl ZxdgOutputV1 {
|
|||
});
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn send_description(&self, description: &str) {
|
||||
self.client.event(Description {
|
||||
self_id: self.id,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue