use crate::{
core::{
bindings::{KeyBindings, MouseBindings},
data_types::{Point, Region},
manager::WindowManager,
screen::Screen,
xconnection::{
Atom, ClientAttr, ClientConfig, ClientMessage, ClientMessageKind, Prop, Result,
WindowState, XConn, XEvent, XEventHandler, Xid,
},
},
xcb::{Api, XcbError},
};
use std::collections::HashMap;
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct XcbConnection {
check_win: Xid,
api: Api,
}
impl XcbConnection {
pub fn new() -> Result<Self> {
let api = Api::new()?;
let check_win = api.check_window();
api.set_randr_notify_mask()?;
Ok(Self { check_win, api })
}
pub fn xcb_connection(&self) -> &xcb::Connection {
&self.api.conn()
}
pub fn api(&self) -> &Api {
&self.api
}
pub fn api_mut(&mut self) -> &mut Api {
&mut self.api
}
pub fn known_atoms(&self) -> &HashMap<Atom, u32> {
&self.api.known_atoms()
}
}
impl WindowManager<XcbConnection> {
pub fn xcb_connection(&self) -> &xcb::Connection {
&self.conn().xcb_connection()
}
pub fn known_atoms(&self) -> &HashMap<Atom, u32> {
&self.conn().known_atoms()
}
}
crate::__xcb_impl_xatom_querier!(XcbConnection);
crate::__xcb_impl_xclientconfig!(XcbConnection);
crate::__xcb_impl_xclienthandler!(XcbConnection);
crate::__xcb_impl_xclientproperties!(XcbConnection);
crate::__xcb_impl_xeventhandler!(XcbConnection);
crate::__xcb_impl_xstate!(XcbConnection);
impl XConn for XcbConnection {
#[cfg(feature = "serde")]
fn hydrate(&mut self) -> Result<()> {
Ok(self.api.hydrate()?)
}
fn init(&self) -> Result<()> {
Ok(self
.api
.set_client_attributes(self.api.root(), &[ClientAttr::RootEventMask])
.map_err(|e| XcbError::Raw(format!("Unable to set root window event mask: {}", e)))?)
}
fn check_window(&self) -> Xid {
self.check_win
}
fn cleanup(&self) -> Result<()> {
self.api.ungrab_keys()?;
self.api.ungrab_mouse_buttons()?;
let net_name = Atom::NetActiveWindow.as_ref();
self.api.delete_prop(self.api.root(), net_name)?;
self.api.destroy_client(self.check_win)?;
self.api.flush();
Ok(())
}
fn grab_keys(
&self,
key_bindings: &KeyBindings<Self>,
mouse_bindings: &MouseBindings<Self>,
) -> Result<()> {
self.api
.grab_keys(&key_bindings.keys().collect::<Vec<_>>())?;
self.api.grab_mouse_buttons(
&mouse_bindings
.keys()
.map(|(_, state)| state)
.collect::<Vec<_>>(),
)?;
self.flush();
Ok(())
}
}