use super::WindowHandle;
use crate::XWrap;
use leftwm_core::models::TagId;
use std::ffi::CString;
use std::os::raw::{c_long, c_ulong};
use x11_dl::xlib;
impl XWrap {
pub fn append_property_long(
&self,
window: xlib::Window,
property: xlib::Atom,
r#type: xlib::Atom,
data: &[c_long],
) {
unsafe {
(self.xlib.XChangeProperty)(
self.display,
window,
property,
r#type,
32,
xlib::PropModeAppend,
data.as_ptr().cast::<u8>(),
data.len() as i32,
);
}
}
pub fn replace_property_long(
&self,
window: xlib::Window,
property: xlib::Atom,
r#type: xlib::Atom,
data: &[c_long],
) {
unsafe {
(self.xlib.XChangeProperty)(
self.display,
window,
property,
r#type,
32,
xlib::PropModeReplace,
data.as_ptr().cast::<u8>(),
data.len() as i32,
);
}
}
pub fn set_client_list(&self) {
unsafe {
(self.xlib.XDeleteProperty)(self.display, self.root, self.atoms.NetClientList);
}
for w in &self.managed_windows {
let list = vec![*w as c_long];
self.append_property_long(self.root, self.atoms.NetClientList, xlib::XA_WINDOW, &list);
}
}
pub fn set_current_desktop(&self, current_tag: Option<TagId>) {
let indexes: Vec<u32> = match current_tag {
Some(tag) => vec![tag as u32 - 1],
None => vec![0],
};
self.set_desktop_prop(&indexes, self.atoms.NetCurrentDesktop);
}
pub fn set_desktop_prop(&self, data: &[u32], atom: c_ulong) {
let x_data: Vec<c_long> = data.iter().map(|x| *x as c_long).collect();
self.replace_property_long(self.root, atom, xlib::XA_CARDINAL, &x_data);
}
pub fn set_desktop_prop_c_ulong(&self, value: c_ulong, atom: c_ulong, r#type: c_ulong) {
let data = vec![value as c_long];
self.replace_property_long(self.root, atom, r#type, &data);
}
pub fn set_desktop_prop_string(&self, value: &str, atom: c_ulong, encoding: xlib::Atom) {
if let Ok(cstring) = CString::new(value) {
unsafe {
(self.xlib.XChangeProperty)(
self.display,
self.root,
atom,
encoding,
8,
xlib::PropModeReplace,
cstring.as_ptr().cast::<u8>(),
value.len() as i32,
);
std::mem::forget(cstring);
}
}
}
pub fn set_state(&self, handle: WindowHandle, toggle_to: bool, atom: xlib::Atom) {
if let WindowHandle::XlibHandle(h) = handle {
let mut states = self.get_window_states_atoms(h);
if toggle_to {
if states.contains(&atom) {
return;
}
states.push(atom);
} else {
let Some(index) = states.iter().position(|s| s == &atom) else { return };
states.remove(index);
}
self.set_window_states_atoms(h, &states);
}
}
pub fn set_window_border_color(&self, window: xlib::Window, mut color: c_ulong) {
unsafe {
let mut bytes = color.to_le_bytes();
bytes[3] = 0xff;
color = c_ulong::from_le_bytes(bytes);
(self.xlib.XSetWindowBorder)(self.display, window, color);
}
}
pub fn set_background_color(&self, mut color: c_ulong) {
unsafe {
let mut bytes = color.to_le_bytes();
bytes[3] = 0xff;
color = c_ulong::from_le_bytes(bytes);
(self.xlib.XSetWindowBackground)(self.display, self.root, color);
(self.xlib.XClearWindow)(self.display, self.root);
(self.xlib.XFlush)(self.display);
(self.xlib.XSync)(self.display, 0);
}
}
pub fn set_window_config(
&self,
window: xlib::Window,
mut window_changes: xlib::XWindowChanges,
unlock: u32,
) {
unsafe { (self.xlib.XConfigureWindow)(self.display, window, unlock, &mut window_changes) };
self.sync();
}
pub fn set_window_desktop(&self, window: xlib::Window, current_tag: &TagId) {
let mut indexes: Vec<c_long> = vec![*current_tag as c_long - 1];
if indexes.is_empty() {
indexes.push(0);
}
self.replace_property_long(window, self.atoms.NetWMDesktop, xlib::XA_CARDINAL, &indexes);
}
pub fn set_window_states_atoms(&self, window: xlib::Window, states: &[xlib::Atom]) {
let data: Vec<c_long> = states.iter().map(|x| *x as c_long).collect();
self.replace_property_long(window, self.atoms.NetWMState, xlib::XA_ATOM, &data);
}
pub fn set_window_urgency(&self, window: xlib::Window, is_urgent: bool) {
if let Some(mut wmh) = self.get_wmhints(window) {
if ((wmh.flags & xlib::XUrgencyHint) != 0) == is_urgent {
return;
}
wmh.flags = if is_urgent {
wmh.flags | xlib::XUrgencyHint
} else {
wmh.flags & !xlib::XUrgencyHint
};
self.set_wmhints(window, &mut wmh);
}
}
pub fn set_wmhints(&self, window: xlib::Window, wmh: &mut xlib::XWMHints) {
unsafe { (self.xlib.XSetWMHints)(self.display, window, wmh) };
}
pub fn set_wm_states(&self, window: xlib::Window, states: &[c_long]) {
self.replace_property_long(window, self.atoms.WMState, self.atoms.WMState, states);
}
}