autocommit 2022-01-06 19:08:32 CET
This commit is contained in:
parent
cbbc41a463
commit
4a939477a2
51 changed files with 3438 additions and 207 deletions
|
|
@ -1 +1,223 @@
|
|||
mod types;
|
||||
|
||||
use crate::backend::Output;
|
||||
use crate::client::{AddObj, Client, ClientId, DynEventFormatter, WlEvent};
|
||||
use crate::globals::{Global, GlobalName};
|
||||
use crate::object::{Interface, Object, ObjectId};
|
||||
use crate::utils::buffd::MsgParser;
|
||||
use crate::utils::copyhashmap::CopyHashMap;
|
||||
use ahash::AHashMap;
|
||||
use std::cell::Cell;
|
||||
use std::iter;
|
||||
use std::rc::Rc;
|
||||
pub use types::*;
|
||||
|
||||
id!(WlOutputId);
|
||||
|
||||
const RELEASE: u32 = 0;
|
||||
|
||||
const GEOMETRY: u32 = 0;
|
||||
const MODE: u32 = 1;
|
||||
const DONE: u32 = 2;
|
||||
const SCALE: u32 = 3;
|
||||
|
||||
const SP_UNKNOWN: i32 = 0;
|
||||
const SP_NONE: i32 = 1;
|
||||
const SP_HORIZONTAL_RGB: i32 = 2;
|
||||
const SP_HORIZONTAL_BGR: i32 = 3;
|
||||
const SP_VERTICAL_RGB: i32 = 4;
|
||||
const SP_VERTICAL_BGR: i32 = 5;
|
||||
|
||||
const TF_NORMAL: i32 = 0;
|
||||
const TF_90: i32 = 1;
|
||||
const TF_180: i32 = 2;
|
||||
const TF_270: i32 = 3;
|
||||
const TF_FLIPPED: i32 = 4;
|
||||
const TF_FLIPPED_90: i32 = 5;
|
||||
const TF_FLIPPED_180: i32 = 6;
|
||||
const TF_FLIPPED_270: i32 = 7;
|
||||
|
||||
const MODE_CURRENT: u32 = 1;
|
||||
const MODE_PREFERRED: u32 = 2;
|
||||
|
||||
pub struct WlOutputGlobal {
|
||||
name: GlobalName,
|
||||
output: Rc<dyn Output>,
|
||||
width: Cell<u32>,
|
||||
height: Cell<u32>,
|
||||
bindings: CopyHashMap<(ClientId, WlOutputId), Rc<WlOutputObj>>,
|
||||
}
|
||||
|
||||
impl WlOutputGlobal {
|
||||
pub fn new(name: GlobalName, output: &Rc<dyn Output>) -> Self {
|
||||
Self {
|
||||
name,
|
||||
output: output.clone(),
|
||||
width: Cell::new(output.width()),
|
||||
height: Cell::new(output.height()),
|
||||
bindings: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update_properties(&self) {
|
||||
let width = self.output.width();
|
||||
let height = self.output.height();
|
||||
|
||||
let mut changed = false;
|
||||
changed |= self.width.replace(width) != width;
|
||||
changed |= self.height.replace(height) != height;
|
||||
|
||||
if changed {
|
||||
let mut clients = AHashMap::new();
|
||||
{
|
||||
let bindings = self.bindings.lock();
|
||||
for binding in bindings.values() {
|
||||
let events = [
|
||||
binding.geometry(),
|
||||
binding.mode(),
|
||||
binding.scale(),
|
||||
binding.done(),
|
||||
];
|
||||
let events = events
|
||||
.into_iter()
|
||||
.map(|e| WlEvent::Event(e))
|
||||
.chain(iter::once(WlEvent::Flush));
|
||||
for event in events {
|
||||
if binding.client.event2_locked(event) {
|
||||
clients.insert(binding.client.id, binding.client.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for client in clients.values() {
|
||||
let _ = client.check_queue_size().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn bind_(
|
||||
self: Rc<Self>,
|
||||
id: WlOutputId,
|
||||
client: &Rc<Client>,
|
||||
version: u32,
|
||||
) -> Result<(), WlOutputError> {
|
||||
let obj = Rc::new(WlOutputObj {
|
||||
global: self.clone(),
|
||||
id,
|
||||
client: client.clone(),
|
||||
});
|
||||
client.add_client_obj(&obj)?;
|
||||
self.bindings.set((client.id, id), obj.clone());
|
||||
client.event(obj.geometry()).await?;
|
||||
client.event(obj.mode()).await?;
|
||||
client.event(obj.scale()).await?;
|
||||
client.event(obj.done()).await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
bind!(WlOutputGlobal);
|
||||
|
||||
impl Global for WlOutputGlobal {
|
||||
fn name(&self) -> GlobalName {
|
||||
self.name
|
||||
}
|
||||
|
||||
fn interface(&self) -> Interface {
|
||||
Interface::WlOutput
|
||||
}
|
||||
|
||||
fn version(&self) -> u32 {
|
||||
3
|
||||
}
|
||||
|
||||
fn pre_remove(&self) {
|
||||
//
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.bindings.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WlOutputObj {
|
||||
global: Rc<WlOutputGlobal>,
|
||||
id: WlOutputId,
|
||||
client: Rc<Client>,
|
||||
}
|
||||
|
||||
impl WlOutputObj {
|
||||
fn geometry(self: &Rc<Self>) -> DynEventFormatter {
|
||||
Box::new(Geometry {
|
||||
obj: self.clone(),
|
||||
x: 0,
|
||||
y: 0,
|
||||
physical_width: self.global.width.get() as _,
|
||||
physical_height: self.global.height.get() as _,
|
||||
subpixel: SP_UNKNOWN,
|
||||
make: String::new(),
|
||||
model: String::new(),
|
||||
transform: TF_NORMAL,
|
||||
})
|
||||
}
|
||||
|
||||
fn mode(self: &Rc<Self>) -> DynEventFormatter {
|
||||
Box::new(Mode {
|
||||
obj: self.clone(),
|
||||
flags: MODE_CURRENT,
|
||||
width: self.global.width.get() as _,
|
||||
height: self.global.height.get() as _,
|
||||
refresh: 60_000_000,
|
||||
})
|
||||
}
|
||||
|
||||
fn scale(self: &Rc<Self>) -> DynEventFormatter {
|
||||
Box::new(Scale {
|
||||
obj: self.clone(),
|
||||
factor: 1,
|
||||
})
|
||||
}
|
||||
|
||||
fn done(self: &Rc<Self>) -> DynEventFormatter {
|
||||
Box::new(Done { obj: self.clone() })
|
||||
}
|
||||
|
||||
async fn release(&self, parser: MsgParser<'_, '_>) -> Result<(), ReleaseError> {
|
||||
let _req: Release = self.client.parse(self, parser)?;
|
||||
self.global.bindings.remove(&(self.client.id, self.id));
|
||||
self.client.remove_obj(self).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn handle_request_(
|
||||
&self,
|
||||
request: u32,
|
||||
parser: MsgParser<'_, '_>,
|
||||
) -> Result<(), WlOutputError> {
|
||||
match request {
|
||||
RELEASE => self.release(parser).await?,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
handle_request!(WlOutputObj);
|
||||
|
||||
impl Object for WlOutputObj {
|
||||
fn id(&self) -> ObjectId {
|
||||
self.id.into()
|
||||
}
|
||||
|
||||
fn interface(&self) -> Interface {
|
||||
Interface::WlOutput
|
||||
}
|
||||
|
||||
fn num_requests(&self) -> u32 {
|
||||
RELEASE + 1
|
||||
}
|
||||
|
||||
fn break_loops(&self) {
|
||||
self.global.bindings.remove(&(self.client.id, self.id));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
136
src/ifs/wl_output/types.rs
Normal file
136
src/ifs/wl_output/types.rs
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
use crate::client::{ClientError, EventFormatter, RequestParser};
|
||||
use crate::ifs::wl_output::{WlOutputObj, DONE, GEOMETRY, MODE, SCALE};
|
||||
use crate::object::Object;
|
||||
use crate::utils::buffd::{MsgFormatter, MsgParser, MsgParserError};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum WlOutputError {
|
||||
#[error("Could not handle `release` request")]
|
||||
ReleaseError(#[from] ReleaseError),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(WlOutputError, ClientError, ClientError);
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ReleaseError {
|
||||
#[error("Parsing failed")]
|
||||
ParseError(#[source] Box<MsgParserError>),
|
||||
#[error(transparent)]
|
||||
ClientError(Box<ClientError>),
|
||||
}
|
||||
efrom!(ReleaseError, ClientError, ClientError);
|
||||
efrom!(ReleaseError, ParseError, MsgParserError);
|
||||
|
||||
pub(super) struct Release;
|
||||
impl RequestParser<'_> for Release {
|
||||
fn parse(_parser: &mut MsgParser<'_, '_>) -> Result<Self, MsgParserError> {
|
||||
Ok(Self)
|
||||
}
|
||||
}
|
||||
impl Debug for Release {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "release()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Geometry {
|
||||
pub obj: Rc<WlOutputObj>,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
pub physical_width: i32,
|
||||
pub physical_height: i32,
|
||||
pub subpixel: i32,
|
||||
pub make: String,
|
||||
pub model: String,
|
||||
pub transform: i32,
|
||||
}
|
||||
impl EventFormatter for Geometry {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, GEOMETRY)
|
||||
.int(self.x)
|
||||
.int(self.y)
|
||||
.int(self.physical_width)
|
||||
.int(self.physical_height)
|
||||
.int(self.subpixel)
|
||||
.string(&self.make)
|
||||
.string(&self.model)
|
||||
.int(self.transform);
|
||||
}
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Geometry {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "geometry(x: {}, y: {}, physical_width: {}, physical_height: {}, subpixel: {}, make: {}, model: {}, transform: {})",
|
||||
self.x, self.y, self.physical_width, self.physical_height, self.subpixel, self.make, self.model, self.transform)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Mode {
|
||||
pub obj: Rc<WlOutputObj>,
|
||||
pub flags: u32,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub refresh: i32,
|
||||
}
|
||||
impl EventFormatter for Mode {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, MODE)
|
||||
.uint(self.flags)
|
||||
.int(self.width)
|
||||
.int(self.height)
|
||||
.int(self.refresh);
|
||||
}
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Mode {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"mode(flags: 0x{:x}, width: {}, height: {}, refresh: {})",
|
||||
self.flags, self.width, self.height, self.refresh
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Done {
|
||||
pub obj: Rc<WlOutputObj>,
|
||||
}
|
||||
impl EventFormatter for Done {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, DONE);
|
||||
}
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Done {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "done()")
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct Scale {
|
||||
pub obj: Rc<WlOutputObj>,
|
||||
pub factor: i32,
|
||||
}
|
||||
impl EventFormatter for Scale {
|
||||
fn format(self: Box<Self>, fmt: &mut MsgFormatter<'_>) {
|
||||
fmt.header(self.obj.id, SCALE).int(self.factor);
|
||||
}
|
||||
fn obj(&self) -> &dyn Object {
|
||||
&*self.obj
|
||||
}
|
||||
}
|
||||
impl Debug for Scale {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "scale(factor: {})", self.factor)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue