Merge pull request #84 from mahkoh/jorth/content-type
wayland: implement wp_content_type_manager_v1
This commit is contained in:
commit
f702bf98d7
7 changed files with 229 additions and 0 deletions
|
|
@ -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>) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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! {
|
||||
|
|
|
|||
116
src/ifs/wp_content_type_manager_v1.rs
Normal file
116
src/ifs/wp_content_type_manager_v1.rs
Normal 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);
|
||||
79
src/ifs/wp_content_type_v1.rs
Normal file
79
src/ifs/wp_content_type_v1.rs
Normal 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);
|
||||
9
wire/wp_content_type_manager_v1.txt
Normal file
9
wire/wp_content_type_manager_v1.txt
Normal 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),
|
||||
}
|
||||
8
wire/wp_content_type_v1.txt
Normal file
8
wire/wp_content_type_v1.txt
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# requests
|
||||
|
||||
msg destroy = 0 {
|
||||
}
|
||||
|
||||
msg set_content_type = 1 {
|
||||
content_type: u32,
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue