autocommit 2022-01-03 18:56:52 CET
This commit is contained in:
parent
fc887b339e
commit
30376c595c
39 changed files with 3157 additions and 309 deletions
|
|
@ -7,4 +7,5 @@ pub mod wl_shm;
|
|||
pub mod wl_shm_pool;
|
||||
pub mod wl_subcompositor;
|
||||
pub mod wl_surface;
|
||||
pub mod xdg_positioner;
|
||||
pub mod xdg_wm_base;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
mod types;
|
||||
|
||||
use crate::client::{AddObj, Client, ClientError, DynEventFormatter};
|
||||
use crate::client::{AddObj, Client, DynEventFormatter};
|
||||
use crate::ifs::wl_callback::WlCallback;
|
||||
use crate::ifs::wl_registry::WlRegistry;
|
||||
use crate::object::{Interface, Object, ObjectId, WL_DISPLAY_ID};
|
||||
|
|
@ -64,7 +64,7 @@ impl WlDisplay {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn error(
|
||||
pub fn error(
|
||||
self: &Rc<Self>,
|
||||
object_id: ObjectId,
|
||||
code: u32,
|
||||
|
|
@ -120,8 +120,4 @@ impl Object for WlDisplay {
|
|||
fn num_requests(&self) -> u32 {
|
||||
GET_REGISTRY + 1
|
||||
}
|
||||
|
||||
fn into_display(self: Rc<Self>) -> Result<Rc<WlDisplay>, ClientError> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ impl WlShmGlobal {
|
|||
client: client.clone(),
|
||||
});
|
||||
client.add_client_obj(&obj)?;
|
||||
for &format in Format::formats() {
|
||||
for &format in client.state.formats.values() {
|
||||
client
|
||||
.event(Box::new(FormatE {
|
||||
obj: obj.clone(),
|
||||
|
|
@ -80,25 +80,6 @@ impl WlShmObj {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Format {
|
||||
Argb8888,
|
||||
Xrgb8888,
|
||||
}
|
||||
|
||||
impl Format {
|
||||
fn uint(self) -> u32 {
|
||||
match self {
|
||||
Format::Argb8888 => 0,
|
||||
Format::Xrgb8888 => 1,
|
||||
}
|
||||
}
|
||||
|
||||
fn formats() -> &'static [Format] {
|
||||
&[Format::Argb8888, Format::Xrgb8888]
|
||||
}
|
||||
}
|
||||
|
||||
bind!(WlShmGlobal);
|
||||
|
||||
impl Global for WlShmGlobal {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::client::{ClientError, EventFormatter, RequestParser};
|
||||
use crate::ifs::wl_shm::{Format, WlShmObj, FORMAT};
|
||||
use crate::format::Format;
|
||||
use crate::ifs::wl_shm::{WlShmObj, FORMAT};
|
||||
use crate::ifs::wl_shm_pool::WlShmPoolError;
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
|
||||
|
|
@ -60,11 +61,11 @@ impl Debug for CreatePool {
|
|||
|
||||
pub(super) struct FormatE {
|
||||
pub obj: Rc<WlShmObj>,
|
||||
pub format: Format,
|
||||
pub format: &'static Format,
|
||||
}
|
||||
impl EventFormatter for FormatE {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, FORMAT).uint(self.format.uint());
|
||||
fmt.header(self.obj.id, FORMAT).uint(self.format.id);
|
||||
}
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
|
|
@ -72,6 +73,10 @@ impl EventFormatter for FormatE {
|
|||
}
|
||||
impl Debug for FormatE {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "format(format: {:?})", self.format)
|
||||
write!(
|
||||
f,
|
||||
"format(format: \"{}\" (0x{:x}))",
|
||||
self.format.name, self.format.id
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,26 +36,26 @@ impl WlShmPool {
|
|||
}
|
||||
|
||||
async fn create_buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), CreateBufferError> {
|
||||
let create: CreateBuffer = self.client.parse(self, parser)?;
|
||||
let req: CreateBuffer = self.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _destroy: Destroy = self.client.parse(self, parser)?;
|
||||
let _req: Destroy = self.client.parse(self, parser)?;
|
||||
self.client.remove_obj(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn resize(&self, parser: MsgParser<'_, '_>) -> Result<(), ResizeError> {
|
||||
let resize: Resize = self.client.parse(self, parser)?;
|
||||
let req: Resize = self.client.parse(self, parser)?;
|
||||
let mut mem = self.mem.borrow_mut();
|
||||
if resize.size < 0 {
|
||||
if req.size < 0 {
|
||||
return Err(ResizeError::NegativeSize);
|
||||
}
|
||||
if (resize.size as usize) < mem.len() {
|
||||
if (req.size as usize) < mem.len() {
|
||||
return Err(ResizeError::CannotShrink);
|
||||
}
|
||||
*mem = Rc::new(ClientMem::new(self.fd.raw(), resize.size as usize)?);
|
||||
*mem = Rc::new(ClientMem::new(self.fd.raw(), req.size as usize)?);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,9 +55,9 @@ impl WlSubcompositorObj {
|
|||
let req: GetSubsurface = self.client.parse(self, parser)?;
|
||||
let surface = self.client.get_surface(req.surface)?;
|
||||
let parent = self.client.get_surface(req.parent)?;
|
||||
let subsurface = Rc::new(WlSubsurface::new(req.id, &surface));
|
||||
let subsurface = Rc::new(WlSubsurface::new(req.id, &surface, &parent));
|
||||
self.client.add_client_obj(&subsurface)?;
|
||||
subsurface.install(&parent)?;
|
||||
subsurface.install()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
mod types;
|
||||
pub mod wl_subsurface;
|
||||
pub mod xdg_surface;
|
||||
|
||||
use crate::client::{Client, RequestParser};
|
||||
use crate::client::{AddObj, Client, RequestParser};
|
||||
use crate::ifs::wl_surface::wl_subsurface::WlSubsurface;
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::pixman::Region;
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use crate::utils::linkedlist::{LinkedList, Node};
|
||||
use ahash::AHashMap;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
|
||||
|
||||
const DESTROY: u32 = 0;
|
||||
const ATTACH: u32 = 1;
|
||||
|
|
@ -30,18 +33,41 @@ const INVALID_TRANSFORM: u32 = 1;
|
|||
const INVALID_SIZE: u32 = 2;
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum SurfaceType {
|
||||
pub enum SurfaceRole {
|
||||
None,
|
||||
Subsurface,
|
||||
XdgSurface,
|
||||
}
|
||||
|
||||
impl SurfaceRole {
|
||||
fn name(self) -> &'static str {
|
||||
match self {
|
||||
SurfaceRole::None => "none",
|
||||
SurfaceRole::Subsurface => "subsurface",
|
||||
SurfaceRole::XdgSurface => "xdg_surface",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WlSurface {
|
||||
id: ObjectId,
|
||||
client: Rc<Client>,
|
||||
ty: Cell<SurfaceType>,
|
||||
role: Cell<SurfaceRole>,
|
||||
pending: PendingState,
|
||||
children: RefCell<Option<Box<ParentData>>>,
|
||||
subsurface_data: RefCell<Option<Box<SubsurfaceData>>>,
|
||||
role_data: RefCell<RoleData>,
|
||||
}
|
||||
|
||||
enum RoleData {
|
||||
None,
|
||||
Subsurface(Box<SubsurfaceData>),
|
||||
XdgSurface(Box<XdgSurfaceData>),
|
||||
}
|
||||
|
||||
impl RoleData {
|
||||
fn is_some(&self) -> bool {
|
||||
!matches!(self, RoleData::None)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
|
@ -50,18 +76,52 @@ struct PendingState {
|
|||
input_region: Cell<Option<Region>>,
|
||||
}
|
||||
|
||||
struct XdgSurfaceData {
|
||||
xdg_surface: Rc<XdgSurface>,
|
||||
role: XdgSurfaceRole,
|
||||
}
|
||||
|
||||
enum XdgSurfaceRole {
|
||||
None,
|
||||
Popup(XdgPopupData),
|
||||
Toplevel(XdgToplevelData),
|
||||
}
|
||||
|
||||
struct XdgPopupData {
|
||||
|
||||
}
|
||||
|
||||
struct XdgToplevelData {
|
||||
|
||||
}
|
||||
|
||||
struct SubsurfaceData {
|
||||
subsurface: Rc<WlSubsurface>,
|
||||
parent: Rc<WlSurface>,
|
||||
x: i32,
|
||||
y: i32,
|
||||
sync_requested: bool,
|
||||
sync_ancestor: bool,
|
||||
pending: bool,
|
||||
node: Node<StackElement>,
|
||||
depth: u32,
|
||||
pending: PendingSubsurfaceData,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct PendingSubsurfaceData {
|
||||
node: Option<Node<StackElement>>,
|
||||
position: Option<(i32, i32)>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ParentData {
|
||||
subsurfaces: AHashMap<ObjectId, Rc<WlSurface>>,
|
||||
pending_subsurfaces: AHashMap<ObjectId, Rc<WlSurface>>,
|
||||
below: LinkedList<StackElement>,
|
||||
above: LinkedList<StackElement>,
|
||||
}
|
||||
|
||||
struct StackElement {
|
||||
pending: Cell<bool>,
|
||||
surface: Rc<WlSurface>,
|
||||
}
|
||||
|
||||
impl WlSurface {
|
||||
|
|
@ -69,26 +129,26 @@ impl WlSurface {
|
|||
Self {
|
||||
id,
|
||||
client: client.clone(),
|
||||
ty: Cell::new(SurfaceType::None),
|
||||
role: Cell::new(SurfaceRole::None),
|
||||
pending: Default::default(),
|
||||
children: Default::default(),
|
||||
subsurface_data: Default::default(),
|
||||
role_data: RefCell::new(RoleData::None),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn break_loops(&self) {
|
||||
*self.children.borrow_mut() = None;
|
||||
*self.subsurface_data.borrow_mut() = None;
|
||||
*self.role_data.borrow_mut() = RoleData::None;
|
||||
}
|
||||
|
||||
pub fn get_root(self: &Rc<Self>) -> Rc<WlSurface> {
|
||||
let mut root = self.clone();
|
||||
loop {
|
||||
let tmp = root;
|
||||
let data = tmp.subsurface_data.borrow();
|
||||
match data.as_ref() {
|
||||
Some(d) => root = d.parent.clone(),
|
||||
None => {
|
||||
let data = tmp.role_data.borrow();
|
||||
match &*data {
|
||||
RoleData::Subsurface(d) => root = d.subsurface.parent.clone(),
|
||||
_ => {
|
||||
drop(data);
|
||||
return tmp;
|
||||
}
|
||||
|
|
@ -104,22 +164,25 @@ impl WlSurface {
|
|||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let destroy: Destroy = self.parse(parser)?;
|
||||
let _req: Destroy = self.parse(parser)?;
|
||||
*self.children.borrow_mut() = None;
|
||||
*self.role_data.borrow_mut() = RoleData::None;
|
||||
self.client.remove_obj(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn attach(&self, parser: MsgParser<'_, '_>) -> Result<(), AttachError> {
|
||||
let attach: Attach = self.parse(parser)?;
|
||||
let req: Attach = self.parse(parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn damage(&self, parser: MsgParser<'_, '_>) -> Result<(), DamageError> {
|
||||
let damage: Damage = self.parse(parser)?;
|
||||
let req: Damage = self.parse(parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn frame(&self, parser: MsgParser<'_, '_>) -> Result<(), FrameError> {
|
||||
let frame: Frame = self.parse(parser)?;
|
||||
let req: Frame = self.parse(parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -134,14 +197,14 @@ impl WlSurface {
|
|||
}
|
||||
|
||||
async fn set_input_region(&self, parser: MsgParser<'_, '_>) -> Result<(), SetInputRegionError> {
|
||||
let region: SetInputRegion = self.parse(parser)?;
|
||||
let region = self.client.get_region(region.region)?;
|
||||
let req: SetInputRegion = self.parse(parser)?;
|
||||
let region = self.client.get_region(req.region)?;
|
||||
self.pending.input_region.set(Some(region.region()));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn commit(&self, parser: MsgParser<'_, '_>) -> Result<(), CommitError> {
|
||||
let commit: Commit = self.parse(parser)?;
|
||||
let req: Commit = self.parse(parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -149,17 +212,17 @@ impl WlSurface {
|
|||
&self,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), SetBufferTransformError> {
|
||||
let transform: SetBufferTransform = self.parse(parser)?;
|
||||
let req: SetBufferTransform = self.parse(parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_buffer_scale(&self, parser: MsgParser<'_, '_>) -> Result<(), SetBufferScaleError> {
|
||||
let scale: SetBufferScale = self.parse(parser)?;
|
||||
let req: SetBufferScale = self.parse(parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn damage_buffer(&self, parser: MsgParser<'_, '_>) -> Result<(), DamageBufferError> {
|
||||
let damage: DamageBuffer = self.parse(parser)?;
|
||||
let req: DamageBuffer = self.parse(parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,8 +46,11 @@ efrom!(WlSurfaceError, DamageBufferError, DamageBufferError);
|
|||
pub enum DestroyError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(DestroyError, ParseFailed, MsgParserError);
|
||||
efrom!(DestroyError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AttachError {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
mod types;
|
||||
|
||||
use crate::ifs::wl_surface::{SubsurfaceData, SurfaceType, WlSurface};
|
||||
use crate::client::AddObj;
|
||||
use crate::ifs::wl_surface::{RoleData, StackElement, SubsurfaceData, SurfaceRole, WlSurface};
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use std::cell::Cell;
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
|
||||
|
|
@ -15,85 +17,211 @@ const SET_DESYNC: u32 = 5;
|
|||
|
||||
const BAD_SURFACE: u32 = 0;
|
||||
|
||||
const MAX_SUBSURFACE_DEPTH: u32 = 100;
|
||||
|
||||
pub struct WlSubsurface {
|
||||
id: ObjectId,
|
||||
surface: Rc<WlSurface>,
|
||||
pub(super) parent: Rc<WlSurface>,
|
||||
}
|
||||
|
||||
fn update_children_sync(surface: &Rc<WlSurface>, sync: bool) -> Result<(), WlSubsurfaceError> {
|
||||
let children = surface.children.borrow();
|
||||
if let Some(children) = &*children {
|
||||
for child in children.subsurfaces.values() {
|
||||
let mut data = child.role_data.borrow_mut();
|
||||
if let RoleData::Subsurface(data) = &mut *data {
|
||||
let was_sync = data.sync_ancestor || data.sync_requested;
|
||||
data.sync_ancestor = sync;
|
||||
let is_sync = data.sync_ancestor || data.sync_requested;
|
||||
if was_sync != is_sync {
|
||||
update_children_sync(child, sync);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_children_attach(
|
||||
surface: &Rc<WlSurface>,
|
||||
sync: bool,
|
||||
depth: u32,
|
||||
) -> Result<(), WlSubsurfaceError> {
|
||||
let children = surface.children.borrow();
|
||||
if let Some(children) = &*children {
|
||||
for child in children.subsurfaces.values() {
|
||||
let mut data = child.role_data.borrow_mut();
|
||||
if let RoleData::Subsurface(data) = &mut *data {
|
||||
data.depth = depth + 1;
|
||||
if data.depth > MAX_SUBSURFACE_DEPTH {
|
||||
return Err(WlSubsurfaceError::MaxDepthExceeded);
|
||||
}
|
||||
data.sync_ancestor = sync;
|
||||
let sync = data.sync_ancestor || data.sync_requested;
|
||||
update_children_attach(child, sync, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl WlSubsurface {
|
||||
pub fn new(id: ObjectId, surface: &Rc<WlSurface>) -> Self {
|
||||
pub fn new(id: ObjectId, surface: &Rc<WlSurface>, parent: &Rc<WlSurface>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
surface: surface.clone(),
|
||||
parent: parent.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install(self: &Rc<Self>, parent: &Rc<WlSurface>) -> Result<(), WlSubsurfaceError> {
|
||||
let old_ty = self.surface.ty.get();
|
||||
if !matches!(old_ty, SurfaceType::None | SurfaceType::Subsurface) {
|
||||
return Err(WlSubsurfaceError::IncompatibleType(self.surface.id, old_ty));
|
||||
}
|
||||
self.surface.ty.set(SurfaceType::Subsurface);
|
||||
let mut data = self.surface.subsurface_data.borrow_mut();
|
||||
if data.is_some() {
|
||||
return Err(WlSubsurfaceError::AlreadyAttached(self.surface.id));
|
||||
}
|
||||
if self.surface.id == parent.id {
|
||||
pub fn install(self: &Rc<Self>) -> Result<(), WlSubsurfaceError> {
|
||||
if self.surface.id == self.parent.id {
|
||||
return Err(WlSubsurfaceError::OwnParent(self.surface.id));
|
||||
}
|
||||
if self.surface.id == parent.get_root().id {
|
||||
return Err(WlSubsurfaceError::Ancestor(self.surface.id, parent.id));
|
||||
let old_ty = self.surface.role.get();
|
||||
if !matches!(old_ty, SurfaceRole::None | SurfaceRole::Subsurface) {
|
||||
return Err(WlSubsurfaceError::IncompatibleType(self.surface.id, old_ty));
|
||||
}
|
||||
self.surface.role.set(SurfaceRole::Subsurface);
|
||||
let mut data = self.surface.role_data.borrow_mut();
|
||||
if matches!(*data, RoleData::Subsurface(_)) {
|
||||
return Err(WlSubsurfaceError::AlreadyAttached(self.surface.id));
|
||||
}
|
||||
if self.surface.id == self.parent.get_root().id {
|
||||
return Err(WlSubsurfaceError::Ancestor(self.surface.id, self.parent.id));
|
||||
}
|
||||
let mut sync_ancestor = false;
|
||||
let mut depth = 1;
|
||||
{
|
||||
let data = parent.subsurface_data.borrow();
|
||||
if let Some(data) = data.as_ref() {
|
||||
let data = self.parent.role_data.borrow();
|
||||
if let RoleData::Subsurface(data) = &*data {
|
||||
sync_ancestor = data.sync_requested || data.sync_ancestor;
|
||||
depth = data.depth + 1;
|
||||
if depth >= MAX_SUBSURFACE_DEPTH {
|
||||
return Err(WlSubsurfaceError::MaxDepthExceeded);
|
||||
}
|
||||
}
|
||||
}
|
||||
*data = Some(Box::new(SubsurfaceData {
|
||||
let node = {
|
||||
let mut data = self.parent.children.borrow_mut();
|
||||
let data = data.get_or_insert_with(|| Default::default());
|
||||
data.subsurfaces
|
||||
.insert(self.surface.id, self.surface.clone());
|
||||
data.above.prepend(StackElement {
|
||||
pending: Cell::new(true),
|
||||
surface: self.surface.clone(),
|
||||
})
|
||||
};
|
||||
*data = RoleData::Subsurface(Box::new(SubsurfaceData {
|
||||
subsurface: self.clone(),
|
||||
parent: parent.clone(),
|
||||
x: 0,
|
||||
y: 0,
|
||||
sync_requested: false,
|
||||
sync_ancestor,
|
||||
pending: true,
|
||||
depth,
|
||||
node,
|
||||
pending: Default::default(),
|
||||
}));
|
||||
{
|
||||
let mut data = parent.children.borrow_mut();
|
||||
let data = data.get_or_insert_with(|| Default::default());
|
||||
data.pending_subsurfaces
|
||||
.insert(self.surface.id, self.surface.clone());
|
||||
}
|
||||
update_children_attach(&self.surface, sync_ancestor, depth)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.surface.client.parse(self, parser)?;
|
||||
*self.surface.role_data.borrow_mut() = RoleData::None;
|
||||
{
|
||||
let mut children = self.parent.children.borrow_mut();
|
||||
if let Some(children) = &mut *children {
|
||||
children.subsurfaces.remove(&self.surface.id);
|
||||
}
|
||||
}
|
||||
self.surface.client.remove_obj(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_position(&self, parser: MsgParser<'_, '_>) -> Result<(), SetPositionError> {
|
||||
let req: SetPosition = self.surface.client.parse(self, parser)?;
|
||||
let mut data = self.surface.role_data.borrow_mut();
|
||||
if let RoleData::Subsurface(data) = &mut *data {
|
||||
data.pending.position = Some((req.x, req.y));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn place(&self, sibling: ObjectId, above: bool) -> Result<(), PlacementError> {
|
||||
if sibling == self.surface.id {
|
||||
return Err(PlacementError::AboveSelf(sibling));
|
||||
}
|
||||
let mut data = self.surface.role_data.borrow_mut();
|
||||
let pdata = self.parent.children.borrow();
|
||||
if let (RoleData::Subsurface(data), Some(pdata)) = (&mut *data, &*pdata) {
|
||||
let element = StackElement {
|
||||
pending: Cell::new(true),
|
||||
surface: self.surface.clone(),
|
||||
};
|
||||
if sibling == self.parent.id {
|
||||
let node = match above {
|
||||
true => pdata.above.prepend(element),
|
||||
_ => pdata.below.append(element),
|
||||
};
|
||||
data.pending.node = Some(node);
|
||||
} else {
|
||||
let sibling = match pdata.subsurfaces.get(&sibling) {
|
||||
Some(s) => s,
|
||||
_ => return Err(PlacementError::NotASibling(sibling, self.surface.id)),
|
||||
};
|
||||
let sdata = sibling.role_data.borrow();
|
||||
if let RoleData::Subsurface(p) = &*sdata {
|
||||
let node = match &p.pending.node {
|
||||
Some(n) => n,
|
||||
_ => &p.node,
|
||||
};
|
||||
let node = match above {
|
||||
true => node.append(element),
|
||||
_ => node.prepend(element),
|
||||
};
|
||||
data.pending.node = Some(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn place_above(&self, parser: MsgParser<'_, '_>) -> Result<(), PlaceAboveError> {
|
||||
let req: PlaceAbove = self.surface.client.parse(self, parser)?;
|
||||
self.place(req.sibling, true)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn place_below(&self, parser: MsgParser<'_, '_>) -> Result<(), PlaceBelowError> {
|
||||
let req: PlaceBelow = self.surface.client.parse(self, parser)?;
|
||||
self.place(req.sibling, false)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_sync(&self, sync: bool) {
|
||||
let mut data = self.surface.role_data.borrow_mut();
|
||||
if let RoleData::Subsurface(data) = &mut *data {
|
||||
let was_sync = data.sync_requested || data.sync_ancestor;
|
||||
data.sync_requested = sync;
|
||||
let is_sync = data.sync_requested || data.sync_ancestor;
|
||||
if was_sync != is_sync {
|
||||
update_children_sync(&self.surface, is_sync);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn set_sync(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSyncError> {
|
||||
let _req: SetSync = self.surface.client.parse(self, parser)?;
|
||||
self.update_sync(true);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_desync(&self, parser: MsgParser<'_, '_>) -> Result<(), SetDesyncError> {
|
||||
let _req: SetDesync = self.surface.client.parse(self, parser)?;
|
||||
self.update_sync(false);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::client::{RequestParser};
|
||||
use crate::ifs::wl_surface::SurfaceType;
|
||||
use crate::client::{ClientError, RequestParser};
|
||||
use crate::ifs::wl_surface::SurfaceRole;
|
||||
use crate::object::ObjectId;
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
|
@ -20,21 +20,26 @@ pub enum WlSubsurfaceError {
|
|||
#[error("Could not process `set_desync` request")]
|
||||
SetDesync(#[from] SetDesyncError),
|
||||
#[error("Surface {0} cannot be assigned the role `Subsurface` because it already has the role `{1:?}`")]
|
||||
IncompatibleType(ObjectId, SurfaceType),
|
||||
IncompatibleType(ObjectId, SurfaceRole),
|
||||
#[error("Surface {0} already has an attached `wl_subsurface`")]
|
||||
AlreadyAttached(ObjectId),
|
||||
#[error("Surface {0} cannot be made its own parent")]
|
||||
OwnParent(ObjectId),
|
||||
#[error("Surface {0} cannot be made a subsurface of {1} because it's an ancestor of {1}")]
|
||||
Ancestor(ObjectId, ObjectId),
|
||||
#[error("Subsurfaces cannot be nested deeper than 100 levels")]
|
||||
MaxDepthExceeded,
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DestroyError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(DestroyError, ParseFailed, MsgParserError);
|
||||
efrom!(DestroyError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetPositionError {
|
||||
|
|
@ -47,13 +52,25 @@ efrom!(SetPositionError, ParseFailed, MsgParserError);
|
|||
pub enum PlaceAboveError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
PlacementError(#[from] PlacementError),
|
||||
}
|
||||
efrom!(PlaceAboveError, ParseFailed, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PlacementError {
|
||||
#[error("Cannot place {0} above/below itself")]
|
||||
AboveSelf(ObjectId),
|
||||
#[error("{0} is not a sibling of {1}")]
|
||||
NotASibling(ObjectId, ObjectId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PlaceBelowError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
PlacementError(#[from] PlacementError),
|
||||
}
|
||||
efrom!(PlaceBelowError, ParseFailed, MsgParserError);
|
||||
|
||||
|
|
|
|||
119
src/ifs/wl_surface/xdg_surface/mod.rs
Normal file
119
src/ifs/wl_surface/xdg_surface/mod.rs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
mod types;
|
||||
pub mod xdg_popup;
|
||||
pub mod xdg_toplevel;
|
||||
|
||||
use crate::ifs::wl_surface::{RoleData, SurfaceRole, WlSurface, XdgSurfaceData};
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
use crate::client::AddObj;
|
||||
use crate::ifs::xdg_wm_base::XdgWmBaseObj;
|
||||
|
||||
const DESTROY: u32 = 0;
|
||||
const GET_TOPLEVEL: u32 = 1;
|
||||
const GET_POPUP: u32 = 2;
|
||||
const SET_WINDOW_GEOMETRY: u32 = 3;
|
||||
const ACK_CONFIGURE: u32 = 4;
|
||||
|
||||
const CONFIGURE: u32 = 0;
|
||||
|
||||
const NOT_CONSTRUCTED: u32 = 1;
|
||||
const ALREADY_CONSTRUCTED: u32 = 2;
|
||||
const UNCONFIGURED_BUFFER: u32 = 3;
|
||||
|
||||
pub struct XdgSurface {
|
||||
id: ObjectId,
|
||||
wm_base: Rc<XdgWmBaseObj>,
|
||||
surface: Rc<WlSurface>,
|
||||
version: u32,
|
||||
}
|
||||
|
||||
impl XdgSurface {
|
||||
pub fn new(wm_base: &Rc<XdgWmBaseObj>, id: ObjectId, surface: &Rc<WlSurface>, version: u32) -> Self {
|
||||
Self {
|
||||
id,
|
||||
wm_base: wm_base.clone(),
|
||||
surface: surface.clone(),
|
||||
version,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn install(self: &Rc<Self>) -> Result<(), XdgSurfaceError> {
|
||||
let old_role = self.surface.role.get();
|
||||
if !matches!(old_role, SurfaceRole::None | SurfaceRole::XdgSurface) {
|
||||
return Err(XdgSurfaceError::IncompatibleRole(self.surface.id, old_role));
|
||||
}
|
||||
let mut data = self.surface.role_data.borrow_mut();
|
||||
if data.is_some() {
|
||||
return Err(XdgSurfaceError::AlreadyAttached(self.surface.id));
|
||||
}
|
||||
*data = RoleData::XdgSurface(Box::new(XdgSurfaceData {
|
||||
xdg_surface: self.clone(),
|
||||
}));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.surface.client.parse(self, parser)?;
|
||||
*self.surface.role_data.borrow_mut() = RoleData::None;
|
||||
self.wm_base.surfaces.remove(&self.id);
|
||||
self.surface.client.remove_obj(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_toplevel(&self, parser: MsgParser<'_, '_>) -> Result<(), GetToplevelError> {
|
||||
let _req: GetToplevel = self.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_popup(&self, parser: MsgParser<'_, '_>) -> Result<(), GetPopupError> {
|
||||
let _req: GetPopup = self.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_window_geometry(
|
||||
&self,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), SetWindowGeometryError> {
|
||||
let _req: SetWindowGeometry = self.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn ack_configure(&self, parser: MsgParser<'_, '_>) -> Result<(), AckConfigureError> {
|
||||
let _req: AckConfigure = self.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_request_(
|
||||
&self,
|
||||
request: u32,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), XdgSurfaceError> {
|
||||
match request {
|
||||
DESTROY => self.destroy(parser).await?,
|
||||
GET_TOPLEVEL => self.get_toplevel(parser).await?,
|
||||
GET_POPUP => self.get_popup(parser).await?,
|
||||
SET_WINDOW_GEOMETRY => self.set_window_geometry(parser).await?,
|
||||
ACK_CONFIGURE => self.ack_configure(parser).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
handle_request!(XdgSurface);
|
||||
|
||||
impl Object for XdgSurface {
|
||||
fn id(&self) -> ObjectId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn interface(&self) -> Interface {
|
||||
Interface::XdgSurface
|
||||
}
|
||||
|
||||
fn num_requests(&self) -> u32 {
|
||||
ACK_CONFIGURE + 1
|
||||
}
|
||||
}
|
||||
189
src/ifs/wl_surface/xdg_surface/types.rs
Normal file
189
src/ifs/wl_surface/xdg_surface/types.rs
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
use crate::client::{ClientError, EventFormatter, RequestParser};
|
||||
use crate::ifs::wl_surface::xdg_surface::{XdgSurface, CONFIGURE};
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::ifs::wl_surface::SurfaceRole;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XdgSurfaceError {
|
||||
#[error("Could not process `destroy` request")]
|
||||
DestroyError(#[from] DestroyError),
|
||||
#[error("Could not process `get_toplevel` request")]
|
||||
GetToplevelError(#[from] GetToplevelError),
|
||||
#[error("Could not process `get_popup` request")]
|
||||
GetPopupError(#[from] GetPopupError),
|
||||
#[error("Could not process `set_window_geometry` request")]
|
||||
SetWindowGeometryError(#[from] SetWindowGeometryError),
|
||||
#[error("Could not process `ack_configure` request")]
|
||||
AckConfigureError(#[from] AckConfigureError),
|
||||
#[error("Surface {0} cannot be turned into a xdg_surface because it already has the role {}", .1.name())]
|
||||
IncompatibleRole(ObjectId, SurfaceRole),
|
||||
#[error("Surface {0} cannot be turned into a xdg_surface because it already has an attached xdg_surface")]
|
||||
AlreadyAttached(ObjectId),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DestroyError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(DestroyError, ParseFailed, MsgParserError);
|
||||
efrom!(DestroyError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GetToplevelError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(GetToplevelError, ParseFailed, MsgParserError);
|
||||
efrom!(GetToplevelError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GetPopupError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(GetPopupError, ParseFailed, MsgParserError);
|
||||
efrom!(GetPopupError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetWindowGeometryError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetWindowGeometryError, ParseFailed, MsgParserError);
|
||||
efrom!(SetWindowGeometryError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AckConfigureError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(AckConfigureError, ParseFailed, MsgParserError);
|
||||
efrom!(AckConfigureError, ClientError, ClientError);
|
||||
|
||||
pub(super) struct Destroy;
|
||||
impl RequestParser<'_> for Destroy {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for Destroy {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "destroy()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct GetToplevel {
|
||||
pub id: ObjectId,
|
||||
}
|
||||
impl RequestParser<'_> for GetToplevel {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
id: parser.object()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for GetToplevel {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "get_toplevel(id: {})", self.id)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct GetPopup {
|
||||
pub id: ObjectId,
|
||||
pub parent: ObjectId,
|
||||
pub positioner: ObjectId,
|
||||
}
|
||||
impl RequestParser<'_> for GetPopup {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
id: parser.object()?,
|
||||
parent: parser.object()?,
|
||||
positioner: parser.object()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for GetPopup {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"get_popup(id: {}, parent: {}, positioner: {})",
|
||||
self.id, self.parent, self.positioner
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetWindowGeometry {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
impl RequestParser<'_> for SetWindowGeometry {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
x: parser.int()?,
|
||||
y: parser.int()?,
|
||||
width: parser.int()?,
|
||||
height: parser.int()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetWindowGeometry {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"set_window_geometry(x: {}, y: {}, width: {}, height: {})",
|
||||
self.x, self.y, self.width, self.height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct AckConfigure {
|
||||
pub serial: u32,
|
||||
}
|
||||
impl RequestParser<'_> for AckConfigure {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
serial: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for AckConfigure {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "ack_configure(serial: {})", self.serial)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Configure {
|
||||
pub obj: Rc<XdgSurface>,
|
||||
pub serial: u32,
|
||||
}
|
||||
impl EventFormatter for Configure {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, CONFIGURE).uint(self.serial);
|
||||
}
|
||||
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Configure {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "configure(serial: {})", self.serial)
|
||||
}
|
||||
}
|
||||
78
src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs
Normal file
78
src/ifs/wl_surface/xdg_surface/xdg_popup/mod.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
mod types;
|
||||
|
||||
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
|
||||
const DESTROY: u32 = 0;
|
||||
const GRAB: u32 = 1;
|
||||
const REPOSITION: u32 = 2;
|
||||
|
||||
const CONFIGURE: u32 = 0;
|
||||
const POPUP_DONE: u32 = 1;
|
||||
const REPOSITIONED: u32 = 2;
|
||||
|
||||
const INVALID_GRAB: u32 = 1;
|
||||
|
||||
pub struct XdgPopup {
|
||||
id: ObjectId,
|
||||
surface: Rc<XdgSurface>,
|
||||
version: u32,
|
||||
}
|
||||
|
||||
impl XdgPopup {
|
||||
pub fn new(id: ObjectId, surface: &Rc<XdgSurface>, version: u32) -> Self {
|
||||
Self {
|
||||
id,
|
||||
surface: surface.clone(),
|
||||
version,
|
||||
}
|
||||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn grab(&self, parser: MsgParser<'_, '_>) -> Result<(), GrabError> {
|
||||
let _req: Grab = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn reposition(&self, parser: MsgParser<'_, '_>) -> Result<(), RepositionError> {
|
||||
let _req: Reposition = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_request_(
|
||||
&self,
|
||||
request: u32,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), XdgPopupError> {
|
||||
match request {
|
||||
DESTROY => self.destroy(parser).await?,
|
||||
GRAB => self.grab(parser).await?,
|
||||
REPOSITION => self.reposition(parser).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
handle_request!(XdgPopup);
|
||||
|
||||
impl Object for XdgPopup {
|
||||
fn id(&self) -> ObjectId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn interface(&self) -> Interface {
|
||||
Interface::XdgPopup
|
||||
}
|
||||
|
||||
fn num_requests(&self) -> u32 {
|
||||
REPOSITION + 1
|
||||
}
|
||||
}
|
||||
168
src/ifs/wl_surface/xdg_surface/xdg_popup/types.rs
Normal file
168
src/ifs/wl_surface/xdg_surface/xdg_popup/types.rs
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
use crate::client::{ClientError, EventFormatter, RequestParser};
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_popup::{
|
||||
XdgPopup, CONFIGURE, POPUP_DONE, REPOSITIONED,
|
||||
};
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XdgPopupError {
|
||||
#[error("Could not process `destroy` request")]
|
||||
DestroyError(#[from] DestroyError),
|
||||
#[error("Could not process `grab` request")]
|
||||
GrabError(#[from] GrabError),
|
||||
#[error("Could not process `reposition` request")]
|
||||
RepositionError(#[from] RepositionError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DestroyError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(DestroyError, ParseFailed, MsgParserError);
|
||||
efrom!(DestroyError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GrabError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(GrabError, ParseFailed, MsgParserError);
|
||||
efrom!(GrabError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum RepositionError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(RepositionError, ParseFailed, MsgParserError);
|
||||
efrom!(RepositionError, ClientError, ClientError);
|
||||
|
||||
pub(super) struct Destroy;
|
||||
impl RequestParser<'_> for Destroy {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for Destroy {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "destroy()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Grab {
|
||||
pub seat: ObjectId,
|
||||
pub serial: u32,
|
||||
}
|
||||
impl RequestParser<'_> for Grab {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
seat: parser.object()?,
|
||||
serial: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for Grab {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "grab(seat: {}, serial: {})", self.seat, self.serial)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Reposition {
|
||||
pub positioner: ObjectId,
|
||||
pub token: u32,
|
||||
}
|
||||
impl RequestParser<'_> for Reposition {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
positioner: parser.object()?,
|
||||
token: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for Reposition {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"reposition(positioner: {}, token: {})",
|
||||
self.positioner, self.token,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Configure {
|
||||
pub obj: Rc<XdgPopup>,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
impl EventFormatter for Configure {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, CONFIGURE)
|
||||
.int(self.x)
|
||||
.int(self.y)
|
||||
.int(self.width)
|
||||
.int(self.height);
|
||||
}
|
||||
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Configure {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"configure(x: {}, y: {}, width: {}, height: {})",
|
||||
self.x, self.y, self.width, self.height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct PopupDone {
|
||||
pub obj: Rc<XdgPopup>,
|
||||
}
|
||||
impl EventFormatter for PopupDone {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, POPUP_DONE);
|
||||
}
|
||||
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for PopupDone {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "popup_done()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Repositioned {
|
||||
pub obj: Rc<XdgPopup>,
|
||||
pub token: u32,
|
||||
}
|
||||
impl EventFormatter for Repositioned {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, REPOSITIONED).uint(self.token);
|
||||
}
|
||||
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Repositioned {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "repositioned(token: {})", self.token)
|
||||
}
|
||||
}
|
||||
178
src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs
Normal file
178
src/ifs/wl_surface/xdg_surface/xdg_toplevel/mod.rs
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
mod types;
|
||||
|
||||
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use num_derive::FromPrimitive;
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
|
||||
const DESTROY: u32 = 0;
|
||||
const SET_PARENT: u32 = 1;
|
||||
const SET_TITLE: u32 = 2;
|
||||
const SET_APP_ID: u32 = 3;
|
||||
const SHOW_WINDOW_MENU: u32 = 4;
|
||||
const MOVE: u32 = 5;
|
||||
const RESIZE: u32 = 6;
|
||||
const SET_MAX_SIZE: u32 = 7;
|
||||
const SET_MIN_SIZE: u32 = 8;
|
||||
const SET_MAXIMIZED: u32 = 9;
|
||||
const UNSET_MAXIMIZED: u32 = 10;
|
||||
const SET_FULLSCREEN: u32 = 11;
|
||||
const UNSET_FULLSCREEN: u32 = 12;
|
||||
const SET_MINIMIZED: u32 = 13;
|
||||
|
||||
const CONFIGURE: u32 = 0;
|
||||
const CLOSE: u32 = 1;
|
||||
|
||||
#[derive(Copy, Clone, Debug, FromPrimitive)]
|
||||
pub enum ResizeEdge {
|
||||
None = 0,
|
||||
Top = 1,
|
||||
Bottom = 2,
|
||||
Left = 4,
|
||||
TopLeft = 5,
|
||||
BottomLeft = 6,
|
||||
Right = 8,
|
||||
TopRight = 9,
|
||||
BottomRight = 10,
|
||||
}
|
||||
|
||||
const STATE_MAXIMIZED: u32 = 1;
|
||||
const STATE_FULLSCREEN: u32 = 2;
|
||||
const STATE_RESIZING: u32 = 3;
|
||||
const STATE_ACTIVATED: u32 = 4;
|
||||
const STATE_TILED_LEFT: u32 = 5;
|
||||
const STATE_TILED_RIGHT: u32 = 6;
|
||||
const STATE_TILED_TOP: u32 = 7;
|
||||
const STATE_TILED_BOTTOM: u32 = 8;
|
||||
|
||||
pub struct XdgToplevel {
|
||||
id: ObjectId,
|
||||
surface: Rc<XdgSurface>,
|
||||
version: u32,
|
||||
}
|
||||
|
||||
impl XdgToplevel {
|
||||
pub fn new(id: ObjectId, surface: &Rc<XdgSurface>, version: u32) -> Self {
|
||||
Self {
|
||||
id,
|
||||
surface: surface.clone(),
|
||||
version,
|
||||
}
|
||||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_parent(&self, parser: MsgParser<'_, '_>) -> Result<(), SetParentError> {
|
||||
let _req: SetParent = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_title(&self, parser: MsgParser<'_, '_>) -> Result<(), SetTitleError> {
|
||||
let _req: SetTitle = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_app_id(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAppIdError> {
|
||||
let _req: SetAppId = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn show_window_menu(&self, parser: MsgParser<'_, '_>) -> Result<(), ShowWindowMenuError> {
|
||||
let _req: ShowWindowMenu = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn move_(&self, parser: MsgParser<'_, '_>) -> Result<(), MoveError> {
|
||||
let _req: Move = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn resize(&self, parser: MsgParser<'_, '_>) -> Result<(), ResizeError> {
|
||||
let _req: Resize = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_max_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMaxSizeError> {
|
||||
let _req: SetMaxSize = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_min_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMinSizeError> {
|
||||
let _req: SetMinSize = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_maximized(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMaximizedError> {
|
||||
let _req: SetMaximized = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn unset_maximized(&self, parser: MsgParser<'_, '_>) -> Result<(), UnsetMaximizedError> {
|
||||
let _req: UnsetMaximized = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_fullscreen(&self, parser: MsgParser<'_, '_>) -> Result<(), SetFullscreenError> {
|
||||
let _req: SetFullscreen = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn unset_fullscreen(
|
||||
&self,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), UnsetFullscreenError> {
|
||||
let _req: UnsetFullscreen = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_minimized(&self, parser: MsgParser<'_, '_>) -> Result<(), SetMinimizedError> {
|
||||
let _req: SetMinimized = self.surface.surface.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_request_(
|
||||
&self,
|
||||
request: u32,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), XdgToplevelError> {
|
||||
match request {
|
||||
DESTROY => self.destroy(parser).await?,
|
||||
SET_PARENT => self.set_parent(parser).await?,
|
||||
SET_TITLE => self.set_title(parser).await?,
|
||||
SET_APP_ID => self.set_app_id(parser).await?,
|
||||
SHOW_WINDOW_MENU => self.show_window_menu(parser).await?,
|
||||
MOVE => self.move_(parser).await?,
|
||||
RESIZE => self.resize(parser).await?,
|
||||
SET_MAX_SIZE => self.set_max_size(parser).await?,
|
||||
SET_MIN_SIZE => self.set_min_size(parser).await?,
|
||||
SET_MAXIMIZED => self.set_maximized(parser).await?,
|
||||
UNSET_MAXIMIZED => self.unset_maximized(parser).await?,
|
||||
SET_FULLSCREEN => self.set_fullscreen(parser).await?,
|
||||
UNSET_FULLSCREEN => self.unset_fullscreen(parser).await?,
|
||||
SET_MINIMIZED => self.set_minimized(parser).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
handle_request!(XdgToplevel);
|
||||
|
||||
impl Object for XdgToplevel {
|
||||
fn id(&self) -> ObjectId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn interface(&self) -> Interface {
|
||||
Interface::XdgToplevel
|
||||
}
|
||||
|
||||
fn num_requests(&self) -> u32 {
|
||||
SET_MINIMIZED + 1
|
||||
}
|
||||
}
|
||||
433
src/ifs/wl_surface/xdg_surface/xdg_toplevel/types.rs
Normal file
433
src/ifs/wl_surface/xdg_surface/xdg_toplevel/types.rs
Normal file
|
|
@ -0,0 +1,433 @@
|
|||
use super::CONFIGURE;
|
||||
use crate::client::{ClientError, EventFormatter, RequestParser};
|
||||
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::{XdgToplevel, CLOSE};
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XdgToplevelError {
|
||||
#[error("Could not process `destroy` request")]
|
||||
DestroyError(#[from] DestroyError),
|
||||
#[error("Could not process `set_parent` request")]
|
||||
SetParentError(#[from] SetParentError),
|
||||
#[error("Could not process `set_title` request")]
|
||||
SetTitleError(#[from] SetTitleError),
|
||||
#[error("Could not process `set_app_id` request")]
|
||||
SetAppIdError(#[from] SetAppIdError),
|
||||
#[error("Could not process `show_window_menu` request")]
|
||||
ShowWindowMenuError(#[from] ShowWindowMenuError),
|
||||
#[error("Could not process `move` request")]
|
||||
MoveError(#[from] MoveError),
|
||||
#[error("Could not process `resize` request")]
|
||||
ResizeError(#[from] ResizeError),
|
||||
#[error("Could not process `set_max_size` request")]
|
||||
SetMaxSizeError(#[from] SetMaxSizeError),
|
||||
#[error("Could not process `set_min_size` request")]
|
||||
SetMinSizeError(#[from] SetMinSizeError),
|
||||
#[error("Could not process `set_maximized` request")]
|
||||
SetMaximizedError(#[from] SetMaximizedError),
|
||||
#[error("Could not process `unset_maximized` request")]
|
||||
UnsetMaximizedError(#[from] UnsetMaximizedError),
|
||||
#[error("Could not process `set_fullscreen` request")]
|
||||
SetFullscreenError(#[from] SetFullscreenError),
|
||||
#[error("Could not process `unset_fullscreen` request")]
|
||||
UnsetFullscreenError(#[from] UnsetFullscreenError),
|
||||
#[error("Could not process `set_minimized` request")]
|
||||
SetMinimizedError(#[from] SetMinimizedError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DestroyError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(DestroyError, ParseFailed, MsgParserError);
|
||||
efrom!(DestroyError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetParentError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetParentError, ParseFailed, MsgParserError);
|
||||
efrom!(SetParentError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetTitleError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetTitleError, ParseFailed, MsgParserError);
|
||||
efrom!(SetTitleError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetAppIdError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetAppIdError, ParseFailed, MsgParserError);
|
||||
efrom!(SetAppIdError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ShowWindowMenuError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(ShowWindowMenuError, ParseFailed, MsgParserError);
|
||||
efrom!(ShowWindowMenuError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MoveError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(MoveError, ParseFailed, MsgParserError);
|
||||
efrom!(MoveError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ResizeError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(ResizeError, ParseFailed, MsgParserError);
|
||||
efrom!(ResizeError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetMaxSizeError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetMaxSizeError, ParseFailed, MsgParserError);
|
||||
efrom!(SetMaxSizeError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetMinSizeError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetMinSizeError, ParseFailed, MsgParserError);
|
||||
efrom!(SetMinSizeError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetMaximizedError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetMaximizedError, ParseFailed, MsgParserError);
|
||||
efrom!(SetMaximizedError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UnsetMaximizedError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(UnsetMaximizedError, ParseFailed, MsgParserError);
|
||||
efrom!(UnsetMaximizedError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetFullscreenError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetFullscreenError, ParseFailed, MsgParserError);
|
||||
efrom!(SetFullscreenError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum UnsetFullscreenError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(UnsetFullscreenError, ParseFailed, MsgParserError);
|
||||
efrom!(UnsetFullscreenError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetMinimizedError {
|
||||
#[error("Parsing failed")]
|
||||
ParseFailed(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(SetMinimizedError, ParseFailed, MsgParserError);
|
||||
efrom!(SetMinimizedError, ClientError, ClientError);
|
||||
|
||||
pub(super) struct Destroy;
|
||||
impl RequestParser<'_> for Destroy {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for Destroy {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "destroy()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetParent {
|
||||
pub parent: ObjectId,
|
||||
}
|
||||
impl RequestParser<'_> for SetParent {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self { parent: parser.object()? })
|
||||
}
|
||||
}
|
||||
impl Debug for SetParent {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_parent(parent: {})", self.parent)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetTitle<'a> {
|
||||
pub title: &'a str,
|
||||
}
|
||||
impl<'a> RequestParser<'a> for SetTitle<'a> {
|
||||
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self { title: parser.string()? })
|
||||
}
|
||||
}
|
||||
impl<'a> Debug for SetTitle<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_title(title: {:?})", self.title)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetAppId<'a> {
|
||||
pub app_id: &'a str,
|
||||
}
|
||||
impl<'a> RequestParser<'a> for SetAppId<'a> {
|
||||
fn parse(parser: &mut MsgParser<'_, 'a>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self { app_id: parser.string()? })
|
||||
}
|
||||
}
|
||||
impl<'a> Debug for SetAppId<'a> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_app_id(app_id: {:?})", self.app_id)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct ShowWindowMenu {
|
||||
pub seat: ObjectId,
|
||||
pub serial: u32,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
impl RequestParser<'_> for ShowWindowMenu {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
seat: parser.object()?,
|
||||
serial: parser.uint()?,
|
||||
x: parser.int()?,
|
||||
y: parser.int()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for ShowWindowMenu {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "show_window_menu(seat: {}, serial: {}, x: {}, y: {})", self.seat, self.serial, self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Move {
|
||||
pub seat: ObjectId,
|
||||
pub serial: u32,
|
||||
}
|
||||
impl RequestParser<'_> for Move {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self { seat: parser.object()?, serial: parser.uint()? })
|
||||
}
|
||||
}
|
||||
impl Debug for Move {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "move(seat: {}, serial: {})", self.seat, self.serial)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Resize {
|
||||
pub seat: ObjectId,
|
||||
pub serial: u32,
|
||||
pub edges: u32,
|
||||
}
|
||||
impl RequestParser<'_> for Resize {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
seat: parser.object()?,
|
||||
serial: parser.uint()?,
|
||||
edges: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for Resize {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "resize(seat: {}, serial: {}, edges: {})", self.seat, self.serial, self.edges)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetMaxSize {
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
impl RequestParser<'_> for SetMaxSize {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self { width: parser.int()?, height: parser.int()? })
|
||||
}
|
||||
}
|
||||
impl Debug for SetMaxSize {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_max_size(width: {}, height: {})", self.width, self.height)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetMinSize {
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
impl RequestParser<'_> for SetMinSize {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self { width: parser.int()?, height: parser.int()? })
|
||||
}
|
||||
}
|
||||
impl Debug for SetMinSize {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_min_size(width: {}, height: {})", self.width, self.height)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetMaximized;
|
||||
impl RequestParser<'_> for SetMaximized {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for SetMaximized {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_maximized()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct UnsetMaximized;
|
||||
impl RequestParser<'_> for UnsetMaximized {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for UnsetMaximized {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "unset_maximized()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetFullscreen {
|
||||
pub output: ObjectId,
|
||||
}
|
||||
impl RequestParser<'_> for SetFullscreen {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self { output: parser.object()? })
|
||||
}
|
||||
}
|
||||
impl Debug for SetFullscreen {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_fullscreen(output: {})", self.output)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct UnsetFullscreen;
|
||||
impl RequestParser<'_> for UnsetFullscreen {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for UnsetFullscreen {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "unset_fullscreen()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetMinimized;
|
||||
impl RequestParser<'_> for SetMinimized {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for SetMinimized {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_minimized()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Configure {
|
||||
pub obj: Rc<XdgToplevel>,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub states: Vec<u32>,
|
||||
}
|
||||
impl EventFormatter for Configure {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, CONFIGURE)
|
||||
.int(self.width)
|
||||
.int(self.height)
|
||||
.array(|fmt| {
|
||||
for &state in &self.states {
|
||||
fmt.uint(state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Configure {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"configure(width: {}, height: {}, states: {:?})",
|
||||
self.width, self.height, self.states
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Close {
|
||||
pub obj: Rc<XdgToplevel>,
|
||||
}
|
||||
impl EventFormatter for Close {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, CLOSE);
|
||||
}
|
||||
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Close {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "close()")
|
||||
}
|
||||
}
|
||||
269
src/ifs/xdg_positioner/mod.rs
Normal file
269
src/ifs/xdg_positioner/mod.rs
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
mod types;
|
||||
|
||||
use crate::client::{AddObj, Client};
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use bitflags::bitflags;
|
||||
use num_derive::FromPrimitive;
|
||||
use num_traits::FromPrimitive;
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
|
||||
const DESTROY: u32 = 0;
|
||||
const SET_SIZE: u32 = 1;
|
||||
const SET_ANCHOR_RECT: u32 = 2;
|
||||
const SET_ANCHOR: u32 = 3;
|
||||
const SET_GRAVITY: u32 = 4;
|
||||
const SET_CONSTRAINT_ADJUSTMENT: u32 = 5;
|
||||
const SET_OFFSET: u32 = 6;
|
||||
const SET_REACTIVE: u32 = 7;
|
||||
const SET_PARENT_SIZE: u32 = 8;
|
||||
const SET_PARENT_CONFIGURE: u32 = 9;
|
||||
|
||||
const INVALID_INPUT: u32 = 0;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, FromPrimitive)]
|
||||
pub enum Anchor {
|
||||
None = 0,
|
||||
Top = 1,
|
||||
Bottom = 2,
|
||||
Left = 3,
|
||||
Right = 4,
|
||||
TopLeft = 5,
|
||||
BottomLeft = 6,
|
||||
TopRight = 7,
|
||||
BottomRight = 8,
|
||||
}
|
||||
|
||||
impl Default for Anchor {
|
||||
fn default() -> Self {
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone, FromPrimitive)]
|
||||
pub enum Gravity {
|
||||
None = 0,
|
||||
Top = 1,
|
||||
Bottom = 2,
|
||||
Left = 3,
|
||||
Right = 4,
|
||||
TopLeft = 5,
|
||||
BottomLeft = 6,
|
||||
TopRight = 7,
|
||||
BottomRight = 8,
|
||||
}
|
||||
|
||||
impl Default for Gravity {
|
||||
fn default() -> Self {
|
||||
Self::None
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Default)]
|
||||
pub struct CA: u32 {
|
||||
const NONE = 0;
|
||||
const SLIDE_X = 1;
|
||||
const SLIDE_Y = 2;
|
||||
const FLIP_X = 4;
|
||||
const FLIP_Y = 8;
|
||||
const RESIZE_X = 16;
|
||||
const RESIZE_Y = 32;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct XdgPositioner {
|
||||
id: ObjectId,
|
||||
client: Rc<Client>,
|
||||
version: u32,
|
||||
position: RefCell<XdgPositioned>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct XdgPositioned {
|
||||
pub size_width: u32,
|
||||
pub size_height: u32,
|
||||
pub ar_x: i32,
|
||||
pub ar_y: i32,
|
||||
pub ar_width: u32,
|
||||
pub ar_height: u32,
|
||||
pub anchor: Anchor,
|
||||
pub gravity: Gravity,
|
||||
pub ca: CA,
|
||||
pub off_x: i32,
|
||||
pub off_y: i32,
|
||||
pub reactive: bool,
|
||||
pub parent_width: u32,
|
||||
pub parent_height: u32,
|
||||
pub parent_serial: u32,
|
||||
}
|
||||
|
||||
impl XdgPositioner {
|
||||
pub fn new(id: ObjectId, client: &Rc<Client>, version: u32) -> Self {
|
||||
Self {
|
||||
id,
|
||||
client: client.clone(),
|
||||
version,
|
||||
position: RefCell::new(Default::default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clone(&self) -> Box<XdgPositioned> {
|
||||
Box::new(*self.position.borrow())
|
||||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.client.parse(self, parser)?;
|
||||
self.client.remove_obj(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetSizeError> {
|
||||
let req: SetSize = self.client.parse(self, parser)?;
|
||||
if req.width <= 0 || req.height <= 0 {
|
||||
self.client.protocol_error(
|
||||
self,
|
||||
INVALID_INPUT,
|
||||
format!("Cannot set a non-positive size"),
|
||||
);
|
||||
return Err(SetSizeError::NonPositiveSize);
|
||||
}
|
||||
let mut position = self.position.borrow_mut();
|
||||
position.size_width = req.width as u32;
|
||||
position.size_height = req.height as u32;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_anchor_rect(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAnchorRectError> {
|
||||
let req: SetAnchorRect = self.client.parse(self, parser)?;
|
||||
if req.width < 0 || req.height < 0 {
|
||||
self.client.protocol_error(
|
||||
self,
|
||||
INVALID_INPUT,
|
||||
format!("Cannot set an anchor rect with negative size"),
|
||||
);
|
||||
return Err(SetAnchorRectError::NegativeAnchorRect);
|
||||
}
|
||||
let mut position = self.position.borrow_mut();
|
||||
position.ar_x = req.x;
|
||||
position.ar_y = req.y;
|
||||
position.ar_width = req.width as u32;
|
||||
position.ar_height = req.height as u32;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_anchor(&self, parser: MsgParser<'_, '_>) -> Result<(), SetAnchorError> {
|
||||
let req: SetAnchor = self.client.parse(self, parser)?;
|
||||
let anchor = match Anchor::from_u32(req.anchor) {
|
||||
Some(a) => a,
|
||||
_ => return Err(SetAnchorError::UnknownAnchor(req.anchor)),
|
||||
};
|
||||
self.position.borrow_mut().anchor = anchor;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_gravity(&self, parser: MsgParser<'_, '_>) -> Result<(), SetGravityError> {
|
||||
let req: SetGravity = self.client.parse(self, parser)?;
|
||||
let gravity = match Gravity::from_u32(req.gravity) {
|
||||
Some(a) => a,
|
||||
_ => return Err(SetGravityError::UnknownGravity(req.gravity)),
|
||||
};
|
||||
self.position.borrow_mut().gravity = gravity;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_constraint_adjustment(
|
||||
&self,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), SetConstraintAdjustmentError> {
|
||||
let req: SetConstraintAdjustment = self.client.parse(self, parser)?;
|
||||
let ca = match CA::from_bits(req.constraint_adjustment) {
|
||||
Some(c) => c,
|
||||
_ => {
|
||||
return Err(SetConstraintAdjustmentError::UnknownCa(
|
||||
req.constraint_adjustment,
|
||||
))
|
||||
}
|
||||
};
|
||||
self.position.borrow_mut().ca = ca;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_offset(&self, parser: MsgParser<'_, '_>) -> Result<(), SetOffsetError> {
|
||||
let req: SetOffset = self.client.parse(self, parser)?;
|
||||
let mut position = self.position.borrow_mut();
|
||||
position.off_x = req.x;
|
||||
position.off_y = req.y;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_reactive(&self, parser: MsgParser<'_, '_>) -> Result<(), SetReactiveError> {
|
||||
let _req: SetReactive = self.client.parse(self, parser)?;
|
||||
self.position.borrow_mut().reactive = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_parent_size(&self, parser: MsgParser<'_, '_>) -> Result<(), SetParentSizeError> {
|
||||
let req: SetParentSize = self.client.parse(self, parser)?;
|
||||
if req.parent_width < 0 || req.parent_height < 0 {
|
||||
self.client.protocol_error(
|
||||
self,
|
||||
INVALID_INPUT,
|
||||
format!("Cannot set a negative parent size"),
|
||||
);
|
||||
return Err(SetParentSizeError::NegativeParentSize);
|
||||
}
|
||||
let mut position = self.position.borrow_mut();
|
||||
position.parent_width = req.parent_width as u32;
|
||||
position.parent_height = req.parent_height as u32;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn set_parent_configure(
|
||||
&self,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), SetParentConfigureError> {
|
||||
let req: SetParentConfigure = self.client.parse(self, parser)?;
|
||||
self.position.borrow_mut().parent_serial = req.serial;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_request_(
|
||||
&self,
|
||||
request: u32,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), XdgPositionerError> {
|
||||
match request {
|
||||
DESTROY => self.destroy(parser).await?,
|
||||
SET_SIZE => self.set_size(parser).await?,
|
||||
SET_ANCHOR_RECT => self.set_anchor_rect(parser).await?,
|
||||
SET_ANCHOR => self.set_anchor(parser).await?,
|
||||
SET_GRAVITY => self.set_gravity(parser).await?,
|
||||
SET_CONSTRAINT_ADJUSTMENT => self.set_constraint_adjustment(parser).await?,
|
||||
SET_OFFSET => self.set_offset(parser).await?,
|
||||
SET_REACTIVE => self.set_reactive(parser).await?,
|
||||
SET_PARENT_SIZE => self.set_parent_size(parser).await?,
|
||||
SET_PARENT_CONFIGURE => self.set_parent_configure(parser).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
handle_request!(XdgPositioner);
|
||||
|
||||
impl Object for XdgPositioner {
|
||||
fn id(&self) -> ObjectId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn interface(&self) -> Interface {
|
||||
Interface::XdgPositioner
|
||||
}
|
||||
|
||||
fn num_requests(&self) -> u32 {
|
||||
SET_PARENT_CONFIGURE + 1
|
||||
}
|
||||
}
|
||||
293
src/ifs/xdg_positioner/types.rs
Normal file
293
src/ifs/xdg_positioner/types.rs
Normal file
|
|
@ -0,0 +1,293 @@
|
|||
use crate::client::{ClientError, RequestParser};
|
||||
use crate::utils::buffd::{MsgParser, MsgParserError};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XdgPositionerError {
|
||||
#[error("Could not process a `destroy` request")]
|
||||
DestroyError(#[from] DestroyError),
|
||||
#[error("Could not process a `set_size` request")]
|
||||
SetSizeError(#[from] SetSizeError),
|
||||
#[error("Could not process a `set_anchor_rect` request")]
|
||||
SetAnchorRectError(#[from] SetAnchorRectError),
|
||||
#[error("Could not process a `set_anchor` request")]
|
||||
SetAnchorError(#[from] SetAnchorError),
|
||||
#[error("Could not process a `set_gravity` request")]
|
||||
SetGravityError(#[from] SetGravityError),
|
||||
#[error("Could not process a `set_constraint_adjustment` request")]
|
||||
SetConstraintAdjustmentError(#[from] SetConstraintAdjustmentError),
|
||||
#[error("Could not process a `set_offset` request")]
|
||||
SetOffsetError(#[from] SetOffsetError),
|
||||
#[error("Could not process a `set_reactive` request")]
|
||||
SetReactiveError(#[from] SetReactiveError),
|
||||
#[error("Could not process a `set_parent_size` request")]
|
||||
SetParentSizeError(#[from] SetParentSizeError),
|
||||
#[error("Could not process a `set_parent_configure` request")]
|
||||
SetParentConfigureError(#[from] SetParentConfigureError),
|
||||
}
|
||||
|
||||
#[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, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetSizeError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error("Cannot set a non-positive size")]
|
||||
NonPositiveSize,
|
||||
}
|
||||
efrom!(SetSizeError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetAnchorRectError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error("Cannot set an anchor rect with a negative size")]
|
||||
NegativeAnchorRect,
|
||||
}
|
||||
efrom!(SetAnchorRectError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetAnchorError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error("Unknown anchor {0}")]
|
||||
UnknownAnchor(u32),
|
||||
}
|
||||
efrom!(SetAnchorError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetGravityError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error("Unknown gravity {0}")]
|
||||
UnknownGravity(u32),
|
||||
}
|
||||
efrom!(SetGravityError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetConstraintAdjustmentError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error("Unknown constraint adjustment {0}")]
|
||||
UnknownCa(u32),
|
||||
}
|
||||
efrom!(SetConstraintAdjustmentError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetOffsetError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
}
|
||||
efrom!(SetOffsetError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetReactiveError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
}
|
||||
efrom!(SetReactiveError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetParentSizeError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error("Cannot set a negative parent size")]
|
||||
NegativeParentSize,
|
||||
}
|
||||
efrom!(SetParentSizeError, ParseError, MsgParserError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum SetParentConfigureError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
}
|
||||
efrom!(SetParentConfigureError, ParseError, MsgParserError);
|
||||
|
||||
pub(super) struct Destroy;
|
||||
impl RequestParser<'_> for Destroy {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for Destroy {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "destroy()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetSize {
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
impl RequestParser<'_> for SetSize {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
width: parser.int()?,
|
||||
height: parser.int()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetSize {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"set_size(width: {}, height: {})",
|
||||
self.width, self.height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetAnchorRect {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
impl RequestParser<'_> for SetAnchorRect {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
x: parser.int()?,
|
||||
y: parser.int()?,
|
||||
width: parser.int()?,
|
||||
height: parser.int()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetAnchorRect {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"set_anchor_rect(x: {}, y: {}, width: {}, height: {})",
|
||||
self.x, self.y, self.width, self.height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetAnchor {
|
||||
pub anchor: u32,
|
||||
}
|
||||
impl RequestParser<'_> for SetAnchor {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
anchor: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetAnchor {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_anchor(anchor: {})", self.anchor)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetGravity {
|
||||
pub gravity: u32,
|
||||
}
|
||||
impl RequestParser<'_> for SetGravity {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
gravity: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetGravity {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_gravity(gravity: {})", self.gravity)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetConstraintAdjustment {
|
||||
pub constraint_adjustment: u32,
|
||||
}
|
||||
impl RequestParser<'_> for SetConstraintAdjustment {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
constraint_adjustment: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetConstraintAdjustment {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"set_constraint_adjustment(constraint_adjustment: {})",
|
||||
self.constraint_adjustment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetOffset {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
impl RequestParser<'_> for SetOffset {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
x: parser.int()?,
|
||||
y: parser.int()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetOffset {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_offset(x: {}, y: {})", self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetReactive;
|
||||
impl RequestParser<'_> for SetReactive {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for SetReactive {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_reactive()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetParentSize {
|
||||
pub parent_width: i32,
|
||||
pub parent_height: i32,
|
||||
}
|
||||
impl RequestParser<'_> for SetParentSize {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
parent_width: parser.int()?,
|
||||
parent_height: parser.int()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetParentSize {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"set_parent_size(parent_width: {}, parent_height: {})",
|
||||
self.parent_width, self.parent_height
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct SetParentConfigure {
|
||||
pub serial: u32,
|
||||
}
|
||||
impl RequestParser<'_> for SetParentConfigure {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
serial: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for SetParentConfigure {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "set_parent_configure(serial: {})", self.serial)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,29 @@
|
|||
mod types;
|
||||
|
||||
use crate::client::{AddObj, Client, ClientError};
|
||||
use crate::client::{AddObj, Client};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::ifs::wl_surface::xdg_surface::XdgSurface;
|
||||
use crate::ifs::xdg_positioner::XdgPositioner;
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
|
||||
const DESTROY: u32 = 0;
|
||||
const CREATE_POSITIONER: u32 = 1;
|
||||
const GET_XDG_SURFACE: u32 = 2;
|
||||
const PONG: u32 = 3;
|
||||
|
||||
const PING: u32 = 0;
|
||||
|
||||
const ROLE: u32 = 0;
|
||||
const DEFUNCT_SURFACES: u32 = 1;
|
||||
const NOT_THE_TOPMOST_POPUP: u32 = 2;
|
||||
const INVALID_POPUP_PARENT: u32 = 3;
|
||||
const INVALID_SURFACE_STATE: u32 = 4;
|
||||
const INVALID_POSITIONER: u32 = 5;
|
||||
|
||||
pub struct XdgWmBaseGlobal {
|
||||
name: GlobalName,
|
||||
}
|
||||
|
|
@ -14,7 +31,9 @@ pub struct XdgWmBaseGlobal {
|
|||
pub struct XdgWmBaseObj {
|
||||
global: Rc<XdgWmBaseGlobal>,
|
||||
id: ObjectId,
|
||||
client: Rc<Client>,
|
||||
version: u32,
|
||||
pub(super) surfaces: CopyHashMap<ObjectId, Rc<XdgSurface>>,
|
||||
}
|
||||
|
||||
impl XdgWmBaseGlobal {
|
||||
|
|
@ -25,13 +44,15 @@ impl XdgWmBaseGlobal {
|
|||
async fn bind_(
|
||||
self: Rc<Self>,
|
||||
id: ObjectId,
|
||||
client: &Client,
|
||||
client: &Rc<Client>,
|
||||
version: u32,
|
||||
) -> Result<(), XdgWmBaseError> {
|
||||
let obj = Rc::new(XdgWmBaseObj {
|
||||
global: self,
|
||||
id,
|
||||
client: client.clone(),
|
||||
version,
|
||||
surfaces: Default::default(),
|
||||
});
|
||||
client.add_client_obj(&obj)?;
|
||||
Ok(())
|
||||
|
|
@ -39,12 +60,65 @@ impl XdgWmBaseGlobal {
|
|||
}
|
||||
|
||||
impl XdgWmBaseObj {
|
||||
async fn handle_request_(
|
||||
pub fn break_loops(&self) {
|
||||
self.surfaces.clear();
|
||||
}
|
||||
|
||||
async fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), DestroyError> {
|
||||
let _req: Destroy = self.client.parse(self, parser)?;
|
||||
if !self.surfaces.is_empty() {
|
||||
self.client.protocol_error(
|
||||
self,
|
||||
DEFUNCT_SURFACES,
|
||||
format!(
|
||||
"Cannot destroy xdg_wm_base object {} before destroying its surfaces",
|
||||
self.id
|
||||
),
|
||||
);
|
||||
return Err(DestroyError::DefunctSurfaces);
|
||||
}
|
||||
self.client.remove_obj(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_positioner(
|
||||
&self,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), CreatePositionerError> {
|
||||
let req: CreatePositioner = self.client.parse(self, parser)?;
|
||||
let pos = Rc::new(XdgPositioner::new(req.id, &self.client, 3));
|
||||
self.client.add_client_obj(&pos)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_xdg_surface(self: &Rc<Self>, parser: MsgParser<'_, '_>) -> Result<(), GetXdgSurfaceError> {
|
||||
let req: GetXdgSurface = self.client.parse(&**self, parser)?;
|
||||
let surface = self.client.get_surface(req.surface)?;
|
||||
let xdg_surface = Rc::new(XdgSurface::new(self, req.id, &surface, 3));
|
||||
self.client.add_client_obj(&xdg_surface)?;
|
||||
xdg_surface.install()?;
|
||||
self.surfaces.set(req.id, xdg_surface);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn pong(&self, parser: MsgParser<'_, '_>) -> Result<(), PongError> {
|
||||
let _req: Pong = self.client.parse(self, parser)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_request_(
|
||||
self: &Rc<Self>,
|
||||
request: u32,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), ClientError> {
|
||||
unreachable!();
|
||||
) -> Result<(), XdgWmBaseError> {
|
||||
match request {
|
||||
DESTROY => self.destroy(parser).await?,
|
||||
CREATE_POSITIONER => self.create_positioner(parser).await?,
|
||||
GET_XDG_SURFACE => self.get_xdg_surface(parser).await?,
|
||||
PONG => self.pong(parser).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,6 +154,6 @@ impl Object for XdgWmBaseObj {
|
|||
}
|
||||
|
||||
fn num_requests(&self) -> u32 {
|
||||
0
|
||||
PONG + 1
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,149 @@
|
|||
use crate::client::ClientError;
|
||||
use crate::client::{ClientError, EventFormatter, RequestParser};
|
||||
use crate::ifs::xdg_wm_base::{XdgWmBaseObj, PING};
|
||||
use crate::object::{Object, ObjectId};
|
||||
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
use crate::ifs::wl_surface::xdg_surface::XdgSurfaceError;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum XdgWmBaseError {
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error("Could not process a `destroy` request")]
|
||||
DestroyError(#[from] DestroyError),
|
||||
#[error("Could not process a `create_positioner` request")]
|
||||
CreatePositionerError(#[from] CreatePositionerError),
|
||||
#[error("Could not process a `get_xdg_surface` request")]
|
||||
GetXdgSurfaceError(#[from] GetXdgSurfaceError),
|
||||
#[error("Could not process a `pong` request")]
|
||||
PongError(#[from] PongError),
|
||||
}
|
||||
efrom!(XdgWmBaseError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DestroyError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error("Tried to destroy xdg_wm_base object before destroying its surfaces")]
|
||||
DefunctSurfaces,
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(DestroyError, ParseError, MsgParserError);
|
||||
efrom!(DestroyError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CreatePositionerError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(CreatePositionerError, ParseError, MsgParserError);
|
||||
efrom!(CreatePositionerError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum GetXdgSurfaceError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
#[error(transparent)]
|
||||
XdgSurfaceError(Box<XdgSurfaceError>),
|
||||
}
|
||||
efrom!(GetXdgSurfaceError, ParseError, MsgParserError);
|
||||
efrom!(GetXdgSurfaceError, ClientError, ClientError);
|
||||
efrom!(GetXdgSurfaceError, XdgSurfaceError, XdgSurfaceError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum PongError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
}
|
||||
efrom!(PongError, ParseError, MsgParserError);
|
||||
|
||||
pub(super) struct Destroy;
|
||||
impl RequestParser<'_> for Destroy {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for Destroy {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "destroy()",)
|
||||
}
|
||||
}
|
||||
|
||||
efrom!(XdgWmBaseError, ClientError, ClientError);
|
||||
pub(super) struct CreatePositioner {
|
||||
pub id: ObjectId,
|
||||
}
|
||||
impl RequestParser<'_> for CreatePositioner {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
id: parser.object()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for CreatePositioner {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "create_positioner(id: {})", self.id,)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct GetXdgSurface {
|
||||
pub id: ObjectId,
|
||||
pub surface: ObjectId,
|
||||
}
|
||||
impl RequestParser<'_> for GetXdgSurface {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
id: parser.object()?,
|
||||
surface: parser.object()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for GetXdgSurface {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"get_xdg_surface(id: {}, surface: {})",
|
||||
self.id, self.surface,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Pong {
|
||||
pub serial: u32,
|
||||
}
|
||||
impl RequestParser<'_> for Pong {
|
||||
fn parse(parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self {
|
||||
serial: parser.uint()?,
|
||||
})
|
||||
}
|
||||
}
|
||||
impl Debug for Pong {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "pong(serial: {})", self.serial,)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Ping {
|
||||
pub obj: Rc<XdgWmBaseObj>,
|
||||
pub serial: u32,
|
||||
}
|
||||
impl EventFormatter for Ping {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, PING).uint(self.serial);
|
||||
}
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Ping {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "ping(serial: {})", self.serial)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue