Skip to content

Commit

Permalink
wayland: implement wp_content_type_manager_v1
Browse files Browse the repository at this point in the history
  • Loading branch information
mahkoh committed Feb 8, 2024
1 parent 2ac3d09 commit d5d141d
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use {
wl_shm::WlShmGlobal,
wl_subcompositor::WlSubcompositorGlobal,
wl_surface::xwayland_shell_v1::XwaylandShellV1Global,
wp_content_type_manager_v1::WpContentTypeManagerV1Global,
wp_cursor_shape_manager_v1::WpCursorShapeManagerV1Global,
wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1Global,
wp_presentation::WpPresentationGlobal,
Expand Down Expand Up @@ -160,6 +161,7 @@ impl Globals {
add_singleton!(WpTearingControlManagerV1Global);
add_singleton!(WpSinglePixelBufferManagerV1Global);
add_singleton!(WpCursorShapeManagerV1Global);
add_singleton!(WpContentTypeManagerV1Global);
}

pub fn add_backend_singletons(&self, backend: &Rc<dyn Backend>) {
Expand Down
2 changes: 2 additions & 0 deletions src/ifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub mod wl_shm;
pub mod wl_shm_pool;
pub mod wl_subcompositor;
pub mod wl_surface;
pub mod wp_content_type_manager_v1;
pub mod wp_content_type_v1;
pub mod wp_cursor_shape_device_v1;
pub mod wp_cursor_shape_manager_v1;
pub mod wp_fractional_scale_manager_v1;
Expand Down
13 changes: 13 additions & 0 deletions src/ifs/wl_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use {
x_surface::XSurface, xdg_surface::XdgSurfaceError,
zwlr_layer_surface_v1::ZwlrLayerSurfaceV1Error,
},
wp_content_type_v1::ContentType,
wp_presentation_feedback::WpPresentationFeedback,
},
leaks::Tracker,
Expand Down Expand Up @@ -256,6 +257,8 @@ pub struct WlSurface {
tearing_control: CloneCell<Option<Rc<WpTearingControlV1>>>,
tearing: Cell<bool>,
version: u32,
pub has_content_type_manager: Cell<bool>,
content_type: Cell<Option<ContentType>>,
}

impl Debug for WlSurface {
Expand Down Expand Up @@ -350,6 +353,7 @@ struct PendingState {
transform: Cell<Option<Transform>>,
xwayland_serial: Cell<Option<u64>>,
tearing: Cell<Option<bool>>,
content_type: Cell<Option<Option<ContentType>>>,
}

#[derive(Default)]
Expand Down Expand Up @@ -405,6 +409,8 @@ impl WlSurface {
tearing_control: Default::default(),
tearing: Cell::new(false),
version,
has_content_type_manager: Default::default(),
content_type: Default::default(),
}
}

Expand Down Expand Up @@ -867,6 +873,9 @@ impl WlSurface {
if let Some(tearing) = self.pending.tearing.take() {
self.tearing.set(tearing);
}
if let Some(content_type) = self.pending.content_type.take() {
self.content_type.set(content_type);
}
if let Some(xwayland_serial) = self.pending.xwayland_serial.take() {
self.xwayland_serial.set(Some(xwayland_serial));
self.client
Expand Down Expand Up @@ -1046,6 +1055,10 @@ impl WlSurface {
self.send_seat_release_events();
self.seat_state.destroy_node(self);
}

pub fn set_content_type(&self, content_type: Option<ContentType>) {
self.pending.content_type.set(Some(content_type));
}
}

object_base! {
Expand Down
116 changes: 116 additions & 0 deletions src/ifs/wp_content_type_manager_v1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use {
crate::{
client::{Client, ClientError},
globals::{Global, GlobalName},
ifs::wp_content_type_v1::WpContentTypeV1,
leaks::Tracker,
object::Object,
utils::buffd::{MsgParser, MsgParserError},
wire::{wp_content_type_manager_v1::*, WpContentTypeManagerV1Id},
},
std::rc::Rc,
thiserror::Error,
};

pub struct WpContentTypeManagerV1Global {
pub name: GlobalName,
}

impl WpContentTypeManagerV1Global {
pub fn new(name: GlobalName) -> Self {
Self { name }
}

fn bind_(
self: Rc<Self>,
id: WpContentTypeManagerV1Id,
client: &Rc<Client>,
version: u32,
) -> Result<(), WpContentTypeManagerV1Error> {
let mgr = Rc::new(WpContentTypeManagerV1 {
id,
client: client.clone(),
tracker: Default::default(),
version,
});
track!(client, mgr);
client.add_client_obj(&mgr)?;
Ok(())
}
}

global_base!(
WpContentTypeManagerV1Global,
WpContentTypeManagerV1,
WpContentTypeManagerV1Error
);

simple_add_global!(WpContentTypeManagerV1Global);

impl Global for WpContentTypeManagerV1Global {
fn singleton(&self) -> bool {
true
}

fn version(&self) -> u32 {
1
}
}

pub struct WpContentTypeManagerV1 {
pub id: WpContentTypeManagerV1Id,
pub client: Rc<Client>,
pub tracker: Tracker<Self>,
pub version: u32,
}

impl WpContentTypeManagerV1 {
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), WpContentTypeManagerV1Error> {
let _req: Destroy = self.client.parse(self, parser)?;
self.client.remove_obj(self)?;
Ok(())
}

fn get_surface_content_type(
&self,
parser: MsgParser<'_, '_>,
) -> Result<(), WpContentTypeManagerV1Error> {
let req: GetSurfaceContentType = self.client.parse(self, parser)?;
let surface = self.client.lookup(req.surface)?;
if surface.has_content_type_manager.replace(true) {
return Err(WpContentTypeManagerV1Error::DuplicateContentType);
}
let device = Rc::new(WpContentTypeV1 {
id: req.id,
client: self.client.clone(),
surface,
tracker: Default::default(),
});
track!(self.client, device);
self.client.add_client_obj(&device)?;
Ok(())
}
}

object_base! {
self = WpContentTypeManagerV1;

DESTROY => destroy,
GET_SURFACE_CONTENT_TYPE => get_surface_content_type,
}

impl Object for WpContentTypeManagerV1 {}

simple_add_obj!(WpContentTypeManagerV1);

#[derive(Debug, Error)]
pub enum WpContentTypeManagerV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error("Surface already has a content type object")]
DuplicateContentType,
}
efrom!(WpContentTypeManagerV1Error, ClientError);
efrom!(WpContentTypeManagerV1Error, MsgParserError);
79 changes: 79 additions & 0 deletions src/ifs/wp_content_type_v1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use {
crate::{
client::{Client, ClientError},
ifs::wl_surface::WlSurface,
leaks::Tracker,
object::Object,
utils::buffd::{MsgParser, MsgParserError},
wire::{wp_content_type_v1::*, WpContentTypeV1Id},
},
std::rc::Rc,
thiserror::Error,
};

const NONE: u32 = 0;
const PHOTO: u32 = 1;
const VIDEO: u32 = 2;
const GAME: u32 = 3;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ContentType {
Photo,
Video,
Game,
}

pub struct WpContentTypeV1 {
pub id: WpContentTypeV1Id,
pub client: Rc<Client>,
pub surface: Rc<WlSurface>,
pub tracker: Tracker<Self>,
}

impl WpContentTypeV1 {
fn destroy(&self, parser: MsgParser<'_, '_>) -> Result<(), WpContentTypeV1Error> {
let _req: Destroy = self.client.parse(self, parser)?;
self.surface.has_content_type_manager.set(false);
self.client.remove_obj(self)?;
Ok(())
}

fn set_content_type(&self, parser: MsgParser<'_, '_>) -> Result<(), WpContentTypeV1Error> {
let req: SetContentType = self.client.parse(self, parser)?;
if req.content_type == NONE {
self.surface.set_content_type(None);
return Ok(());
}
let ct = match req.content_type {
PHOTO => ContentType::Photo,
VIDEO => ContentType::Video,
GAME => ContentType::Game,
_ => return Err(WpContentTypeV1Error::UnknownContentType(req.content_type)),
};
self.surface.set_content_type(Some(ct));
Ok(())
}
}

object_base! {
self = WpContentTypeV1;

DESTROY => destroy,
SET_CONTENT_TYPE => set_content_type,
}

impl Object for WpContentTypeV1 {}

simple_add_obj!(WpContentTypeV1);

#[derive(Debug, Error)]
pub enum WpContentTypeV1Error {
#[error(transparent)]
ClientError(Box<ClientError>),
#[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>),
#[error("Content type {0} is unknown")]
UnknownContentType(u32),
}
efrom!(WpContentTypeV1Error, ClientError);
efrom!(WpContentTypeV1Error, MsgParserError);
9 changes: 9 additions & 0 deletions wire/wp_content_type_manager_v1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# requests

msg destroy = 0 {
}

msg get_surface_content_type = 1 {
id: id(wp_content_type_v1),
surface: id(wl_surface),
}
8 changes: 8 additions & 0 deletions wire/wp_content_type_v1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# requests

msg destroy = 0 {
}

msg set_content_type = 1 {
content_type: u32,
}

0 comments on commit d5d141d

Please sign in to comment.