1
0
Fork 0
forked from wry/wry

Merge pull request #84 from mahkoh/jorth/content-type

wayland: implement wp_content_type_manager_v1
This commit is contained in:
mahkoh 2024-02-08 15:23:48 +01:00 committed by GitHub
commit f702bf98d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 229 additions and 0 deletions

View file

@ -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,
@ -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>) {

View file

@ -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;

View file

@ -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,
@ -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 {
@ -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)]
@ -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(),
}
}
@ -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
@ -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! {

View file

@ -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);

View file

@ -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);

View file

@ -0,0 +1,9 @@
# requests
msg destroy = 0 {
}
msg get_surface_content_type = 1 {
id: id(wp_content_type_v1),
surface: id(wl_surface),
}

View file

@ -0,0 +1,8 @@
# requests
msg destroy = 0 {
}
msg set_content_type = 1 {
content_type: u32,
}