use super::{Connection, PendingRequest, PendingRequestFlags, RequestWorkaround};
use crate::{event::Event, util::cycled_zeroes, Fd, XID};
use alloc::{boxed::Box, vec, vec::Vec};
use core::iter;
use tinyvec::TinyVec;
#[cfg(feature = "async")]
use super::AsyncConnection;
const TYPE_ERROR: u8 = 0;
const TYPE_REPLY: u8 = 1;
const GENERIC_EVENT: u8 = 35;
const GE_MASK: u8 = 0x7f;
impl<Conn> super::Display<Conn> {
#[inline]
fn process_bytes(&mut self, mut bytes: TinyVec<[u8; 32]>, fds: Box<[Fd]>) -> crate::Result {
let sequence = u16::from_ne_bytes([bytes[2], bytes[3]]);
#[cfg(debug_assertions)]
log::trace!("Found response bytes: {}", &bytes);
if bytes[0] == TYPE_REPLY {
log::debug!("Received bytes of type REPLY");
let pereq = self
.pending_requests
.remove(&sequence)
.ok_or(crate::BreadError::NoMatchingRequest(sequence))?;
if pereq.flags.discard_reply {
log::debug!("Discarding input for request");
} else {
bytes.move_to_the_heap();
let bytes = match bytes {
TinyVec::Heap(v) => v.into_boxed_slice(),
TinyVec::Inline(_) => unreachable!(),
};
self.pending_replies.insert(sequence, (bytes, fds));
}
} else if bytes[0] == TYPE_ERROR {
if !bytes.iter().copied().any(|x| x != 0) {
return Err(crate::BreadError::ClosedConnection);
}
let err = crate::BreadError::from_x_error(bytes);
match self.pending_requests.remove(&sequence) {
Some(_) => {
if self.pending_errors.insert(sequence, err).is_some() {
panic!("Sequence number overflow - there are too many requests");
}
}
None => return Err(err),
}
} else {
log::debug!("Received bytes of type EVENT");
let event = Event::from_bytes(bytes)?;
if let Err(event) = self.filter_into_special_event(event) {
self.event_queue.push_back(event);
}
}
Ok(())
}
#[inline]
fn fix_glx_workaround(&self, bytes: &mut TinyVec<[u8; 32]>) -> crate::Result<()> {
if bytes[0] == TYPE_REPLY {
let sequence = u16::from_ne_bytes([bytes[2], bytes[3]]);
let pereq = self
.pending_requests
.get(&sequence)
.ok_or(crate::BreadError::NoMatchingRequest(sequence))?;
if let RequestWorkaround::GlxFbconfigBug = pereq.flags.workaround {
log::debug!("Applying GLX FbConfig workaround to reply");
let (mut visuals, mut props): ([u8; 4], [u8; 4]) = ([0; 4], [0; 4]);
visuals.copy_from_slice(&bytes[8..12]);
props.copy_from_slice(&bytes[12..16]);
let (visuals, props) = (u32::from_ne_bytes(visuals), u32::from_ne_bytes(props));
let length = (visuals * props * 2).to_ne_bytes();
(&mut bytes[4..8]).copy_from_slice(&length);
}
}
Ok(())
}
#[inline]
pub(crate) fn expect_reply(&mut self, req: u64, flags: PendingRequestFlags) {
let pereq = PendingRequest {
request: req,
flags,
};
if self.pending_requests.insert(req as _, pereq).is_some() {
panic!("Sequence number overlap; too many requests!");
}
}
#[inline]
fn filter_into_special_event(&mut self, event: Event) -> Result<XID, Event> {
let evbytes = match event.as_byte_slice() {
Some(evbytes) => evbytes,
None => return Err(event),
};
if evbytes[0] & 0x7F != GENERIC_EVENT as _ {
return Err(event);
}
let mut eid_bytes: [u8; 4] = [0; 4];
eid_bytes.copy_from_slice(&evbytes[12..16]);
let my_eid = u32::from_ne_bytes(eid_bytes);
let mut event = Some(event);
self.special_event_queues
.iter_mut()
.find_map(|(eid, queue)| {
if *eid == my_eid {
queue.push_back(event.take().expect("Infallible!"));
Some(*eid)
} else {
None
}
})
.ok_or_else(|| event.unwrap())
}
}
impl<Conn: Connection> super::Display<Conn> {
#[inline]
pub(crate) fn wait(&mut self) -> crate::Result {
log::debug!("Running wait cycle");
let mut bytes: TinyVec<[u8; 32]> = cycled_zeroes(32);
let mut fds: Vec<Fd> = vec![];
self.connection()?.read_packet(&mut bytes, &mut fds)?;
self.fix_glx_workaround(&mut bytes)?;
if let Some(ab) = additional_bytes(&bytes[..8]) {
if ab != 0 {
bytes.extend(iter::repeat(0).take(ab * 4));
log::debug!("Waiting for {} additional bytes", ab * 4);
self.connection()?.read_packet(&mut bytes[32..], &mut fds)?;
log::debug!("Ending wait with {} additional bytes", ab * 4);
}
}
self.process_bytes(bytes, fds.into_boxed_slice())
}
}
#[cfg(feature = "async")]
impl<Conn: AsyncConnection + Send> super::Display<Conn> {
#[inline]
pub(crate) async fn wait_async(&mut self) -> crate::Result {
#[cfg(debug_assertions)]
log::debug!("Beginning wait cycle.");
let mut bytes: TinyVec<[u8; 32]> = cycled_zeroes(32);
let mut fds: Vec<Fd> = vec![];
self.connection()?.read_packet(&mut bytes, &mut fds).await?;
self.fix_glx_workaround(&mut bytes)?;
if let Some(ab) = additional_bytes(&bytes[..8]) {
bytes.extend(iter::repeat(0).take(ab * 4));
self.connection()?
.read_packet(&mut bytes[32..], &mut fds)
.await?;
}
self.process_bytes(bytes, fds.into_boxed_slice())
}
}
#[inline]
fn additional_bytes(bytes: &[u8]) -> Option<usize> {
if bytes[0] == TYPE_REPLY || bytes[0] & GE_MASK == GENERIC_EVENT {
let mut len_bytes = [0; 4];
len_bytes.copy_from_slice(&bytes[4..8]);
Some(u32::from_ne_bytes(len_bytes) as usize)
} else {
None
}
}