removed old xlib.rs file

This commit is contained in:
Janis 2022-05-07 00:29:28 +02:00
parent 2c6d4fd465
commit b3f586ea6a

View file

@ -1,774 +0,0 @@
use log::info;
use std::ptr::{null, null_mut};
use std::{ffi::CString, rc::Rc};
use x11::xlib::{
self, AnyButton, AnyKey, AnyModifier, Atom, ButtonPressMask,
ButtonReleaseMask, CWEventMask, ControlMask, CurrentTime, EnterWindowMask,
FocusChangeMask, LockMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask,
Mod5Mask, PointerMotionMask, PropertyChangeMask, ShiftMask,
StructureNotifyMask, SubstructureNotifyMask, SubstructureRedirectMask,
Window, XCloseDisplay, XConfigureRequestEvent, XDefaultScreen, XEvent,
XGetTransientForHint, XGrabPointer, XInternAtom, XKillClient, XMapWindow,
XOpenDisplay, XRaiseWindow, XRootWindow, XSetErrorHandler, XSync,
XUngrabButton, XUngrabKey, XUngrabPointer, XWarpPointer, XWindowAttributes,
};
use xlib::GrabModeAsync;
use log::error;
use crate::clients::Client;
pub struct XLib {
display: Display,
root: Window,
_screen: i32,
atoms: Atoms,
global_keybinds: Vec<KeyOrButton>,
}
struct Atoms {
protocols: Atom,
delete_window: Atom,
active_window: Atom,
take_focus: Atom,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum KeyOrButton {
Key(i32, u32),
Button(u32, u32, u64),
}
impl KeyOrButton {
#[allow(dead_code)]
pub fn key(keycode: i32, modmask: u32) -> Self {
Self::Key(keycode, modmask)
}
pub fn button(button: u32, modmask: u32, buttonmask: i64) -> Self {
Self::Button(button, modmask, buttonmask as u64)
}
}
#[derive(Clone)]
pub struct Display(Rc<*mut xlib::Display>);
impl Drop for XLib {
fn drop(&mut self) {
self.close_dpy();
}
}
impl XLib {
pub fn new() -> Self {
let (display, _screen, root) = unsafe {
let display = XOpenDisplay(null());
assert_ne!(display, null_mut());
let display = Display::new(display);
let screen = XDefaultScreen(display.get());
let root = XRootWindow(display.get(), screen);
(display, screen, root)
};
Self {
atoms: Atoms::init(display.clone()),
global_keybinds: Vec::new(),
root,
_screen,
display,
}
}
pub fn init(&mut self) {
unsafe {
let mut window_attributes =
std::mem::MaybeUninit::<xlib::XSetWindowAttributes>::zeroed()
.assume_init();
window_attributes.event_mask = SubstructureRedirectMask
| StructureNotifyMask
| SubstructureNotifyMask
| EnterWindowMask
| PointerMotionMask
| ButtonPressMask;
xlib::XChangeWindowAttributes(
self.dpy(),
self.root,
CWEventMask,
&mut window_attributes,
);
xlib::XSelectInput(
self.dpy(),
self.root,
window_attributes.event_mask,
);
XSetErrorHandler(Some(xlib_error_handler));
XSync(self.dpy(), 0);
}
self.grab_global_keybinds(self.root);
}
pub fn add_global_keybind(&mut self, key: KeyOrButton) {
self.global_keybinds.push(key);
}
#[allow(dead_code)]
fn ungrab_global_keybings(&self, window: Window) {
unsafe {
XUngrabButton(self.dpy(), AnyButton as u32, AnyModifier, window);
XUngrabKey(self.dpy(), AnyKey, AnyModifier, window);
}
}
fn grab_global_keybinds(&self, window: Window) {
for kb in self.global_keybinds.iter() {
self.grab_key_or_button(window, kb);
}
}
#[allow(dead_code)]
pub fn remove_global_keybind(&mut self, key: &KeyOrButton) {
if self.global_keybinds.contains(key) {
self.global_keybinds.retain(|kb| kb != key);
}
}
fn dpy(&self) -> *mut xlib::Display {
self.display.get()
}
#[allow(dead_code)]
pub fn squash_event(&self, event_type: i32) -> XEvent {
unsafe {
let mut event =
std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init();
while xlib::XCheckTypedEvent(self.dpy(), event_type, &mut event)
!= 0
{}
event
}
}
pub fn next_event(&self) -> XEvent {
unsafe {
let mut event =
std::mem::MaybeUninit::<xlib::XEvent>::zeroed().assume_init();
xlib::XNextEvent(self.dpy(), &mut event);
event
}
}
pub fn grab_key_or_button(&self, window: Window, key: &KeyOrButton) {
let numlock_mask = self.get_numlock_mask();
let modifiers =
vec![0, LockMask, numlock_mask, LockMask | numlock_mask];
for modifier in modifiers.iter() {
match key {
&KeyOrButton::Key(keycode, modmask) => {
unsafe {
xlib::XGrabKey(
self.dpy(),
keycode,
modmask | modifier,
window,
1, /* true */
GrabModeAsync,
GrabModeAsync,
);
}
}
&KeyOrButton::Button(button, modmask, buttonmask) => {
unsafe {
xlib::XGrabButton(
self.dpy(),
button,
modmask | modifier,
window,
1, /*true */
buttonmask as u32,
GrabModeAsync,
GrabModeAsync,
0,
0,
);
}
}
}
}
}
pub fn focus_client(&self, client: &Client) {
unsafe {
xlib::XSetInputFocus(
self.dpy(),
client.window,
xlib::RevertToPointerRoot,
xlib::CurrentTime,
);
let screen = xlib::XDefaultScreenOfDisplay(self.dpy()).as_ref();
if let Some(screen) = screen {
xlib::XSetWindowBorder(
self.dpy(),
client.window,
screen.white_pixel,
);
}
xlib::XChangeProperty(
self.dpy(),
self.root,
self.atoms.active_window,
xlib::XA_WINDOW,
32,
xlib::PropModeReplace,
&client.window as *const u64 as *const _,
1,
);
}
self.send_protocol(client, self.atoms.take_focus);
}
pub fn unfocus_client(&self, client: &Client) {
//info!("unfocusing client: {:?}", client);
unsafe {
xlib::XSetInputFocus(
self.dpy(),
self.root,
xlib::RevertToPointerRoot,
xlib::CurrentTime,
);
let screen = xlib::XDefaultScreenOfDisplay(self.dpy()).as_ref();
if let Some(screen) = screen {
xlib::XSetWindowBorder(
self.dpy(),
client.window,
screen.black_pixel,
);
}
// xlib::XDeleteProperty(
// self.dpy(),
// self.root,
// self.atoms.active_window,
// );
}
}
pub fn move_resize_client(&self, client: &Client) {
let mut windowchanges = xlib::XWindowChanges {
x: client.position.x,
y: client.position.y,
width: client.size.x,
height: client.size.y,
border_width: 0,
sibling: 0,
stack_mode: 0,
};
if client.size.x < 1 || client.size.y < 1 {
error!("client {:?} size is less than 1 pixel!", client);
} else {
unsafe {
xlib::XConfigureWindow(
self.dpy(),
client.window,
(xlib::CWY | xlib::CWX | xlib::CWHeight | xlib::CWWidth)
as u32,
&mut windowchanges,
);
// I don't think I have to call this ~
//self.configure_client(client);
}
}
}
pub fn move_client(&self, client: &Client) {
let mut wc = xlib::XWindowChanges {
x: client.position.x,
y: client.position.y,
width: client.size.x,
height: client.size.y,
border_width: 0,
sibling: 0,
stack_mode: 0,
};
if client.size.x < 1 || client.size.y < 1 {
error!("client {:?} size is less than 1 pixel!", client);
} else {
unsafe {
xlib::XConfigureWindow(
self.dpy(),
client.window,
(xlib::CWX | xlib::CWY) as u32,
&mut wc,
);
}
}
}
pub fn resize_client(&self, client: &Client) {
let mut wc = xlib::XWindowChanges {
x: client.position.x,
y: client.position.y,
width: client.size.x,
height: client.size.y,
border_width: 0,
sibling: 0,
stack_mode: 0,
};
if client.size.x < 1 || client.size.y < 1 {
error!("client {:?} size is less than 1 pixel!", client);
} else {
unsafe {
xlib::XConfigureWindow(
self.dpy(),
client.window,
(xlib::CWWidth | xlib::CWHeight) as u32,
&mut wc,
);
}
}
}
pub fn hide_client(&self, client: &Client) {
let mut wc = xlib::XWindowChanges {
x: client.size.x * -2,
y: client.position.y,
width: client.size.x,
height: client.size.y,
border_width: 0,
sibling: 0,
stack_mode: 0,
};
if client.size.x < 1 || client.size.y < 1 {
error!("client {:?} size is less than 1 pixel!", client);
} else {
unsafe {
xlib::XConfigureWindow(
self.dpy(),
client.window,
(xlib::CWX | xlib::CWY) as u32,
&mut wc,
);
}
}
}
pub fn raise_client(&self, client: &Client) {
unsafe {
XRaiseWindow(self.dpy(), client.window);
}
}
pub fn get_window_size(&self, window: Window) -> Option<(i32, i32)> {
let mut wa = unsafe {
std::mem::MaybeUninit::<xlib::XWindowAttributes>::zeroed()
.assume_init()
};
if unsafe {
xlib::XGetWindowAttributes(self.dpy(), window, &mut wa) != 0
} {
Some((wa.width, wa.height))
} else {
None
}
}
#[allow(dead_code)]
fn get_window_attributes(
&self,
window: Window,
) -> Option<XWindowAttributes> {
let mut wa = unsafe {
std::mem::MaybeUninit::<xlib::XWindowAttributes>::zeroed()
.assume_init()
};
if unsafe {
xlib::XGetWindowAttributes(self.dpy(), window, &mut wa) != 0
} {
Some(wa)
} else {
None
}
}
pub fn get_transient_for_window(&self, window: Window) -> Option<Window> {
let mut transient_for: Window = 0;
if unsafe {
XGetTransientForHint(self.dpy(), window, &mut transient_for) != 0
} {
Some(transient_for)
} else {
None
}
}
#[allow(dead_code)]
pub fn expose_client(&self, client: &Client) {
self.expose_window(client.window);
}
#[allow(dead_code)]
fn expose_window(&self, window: Window) {
if let Some(wa) = self.get_window_attributes(window) {
unsafe {
xlib::XClearArea(
self.dpy(),
window,
0,
0,
wa.width as u32,
wa.height as u32,
1,
);
}
}
}
pub fn configure_window(&self, event: &XConfigureRequestEvent) {
let mut wc = xlib::XWindowChanges {
x: event.x,
y: event.y,
width: event.width,
height: event.height,
border_width: event.border_width,
sibling: event.above,
stack_mode: event.detail,
};
unsafe {
xlib::XConfigureWindow(
self.dpy(),
event.window,
event.value_mask as u32,
&mut wc,
);
}
}
pub fn configure_client(&self, client: &Client, border: i32) {
let mut event = xlib::XConfigureEvent {
type_: xlib::ConfigureNotify,
display: self.dpy(),
event: client.window,
window: client.window,
x: client.position.x,
y: client.position.y,
width: client.size.x,
height: client.size.y,
border_width: border,
override_redirect: 0,
send_event: 0,
serial: 0,
above: 0,
};
unsafe {
xlib::XSetWindowBorderWidth(
self.dpy(),
event.window,
event.border_width as u32,
);
xlib::XSendEvent(
self.dpy(),
event.window,
0,
StructureNotifyMask,
&mut event as *mut _ as *mut XEvent,
);
}
}
pub fn map_window(&self, window: Window) {
unsafe {
XMapWindow(self.dpy(), window);
xlib::XSelectInput(
self.dpy(),
window,
EnterWindowMask
| FocusChangeMask
| PropertyChangeMask
| StructureNotifyMask,
);
}
self.grab_global_keybinds(window);
}
pub fn dimensions(&self) -> (i32, i32) {
unsafe {
let mut wa =
std::mem::MaybeUninit::<xlib::XWindowAttributes>::zeroed()
.assume_init();
xlib::XGetWindowAttributes(self.dpy(), self.root, &mut wa);
info!("Root window dimensions: {}, {}", wa.width, wa.height);
(wa.width, wa.height)
}
}
fn close_dpy(&self) {
unsafe {
XCloseDisplay(self.dpy());
}
}
pub fn kill_client(&self, client: &Client) {
if !self.send_protocol(client, self.atoms.delete_window) {
unsafe {
XKillClient(self.dpy(), client.window);
}
}
}
pub fn grab_cursor(&self) {
unsafe {
XGrabPointer(
self.dpy(),
self.root,
0,
(ButtonPressMask | ButtonReleaseMask | PointerMotionMask)
as u32,
GrabModeAsync,
GrabModeAsync,
0,
0,
CurrentTime,
);
}
}
pub fn release_cursor(&self) {
unsafe {
XUngrabPointer(self.dpy(), CurrentTime);
}
}
pub fn move_cursor(&self, window: Option<Window>, position: (i32, i32)) {
unsafe {
XWarpPointer(
self.dpy(),
0,
window.unwrap_or(self.root),
0,
0,
0,
0,
position.0,
position.1,
);
}
}
fn check_for_protocol(&self, client: &Client, proto: xlib::Atom) -> bool {
let mut protos: *mut xlib::Atom = null_mut();
let mut num_protos: i32 = 0;
unsafe {
if xlib::XGetWMProtocols(
self.dpy(),
client.window,
&mut protos,
&mut num_protos,
) != 0
{
for i in 0..num_protos {
if *protos.offset(i as isize) == proto {
return true;
}
}
}
}
return false;
}
fn send_protocol(&self, client: &Client, proto: xlib::Atom) -> bool {
if self.check_for_protocol(client, proto) {
let mut data = xlib::ClientMessageData::default();
data.set_long(0, proto as i64);
let mut event = XEvent {
client_message: xlib::XClientMessageEvent {
type_: xlib::ClientMessage,
serial: 0,
display: self.dpy(),
send_event: 0,
window: client.window,
format: 32,
message_type: self.atoms.protocols,
data,
},
};
unsafe {
xlib::XSendEvent(
self.dpy(),
client.window,
0,
xlib::NoEventMask,
&mut event,
);
}
true
} else {
false
}
}
pub fn make_key<S>(&self, key: S, modmask: u32) -> KeyOrButton
where
S: AsRef<str>,
{
let key = self.keycode(key);
KeyOrButton::Key(key, modmask)
}
fn keycode<S>(&self, string: S) -> i32
where
S: AsRef<str>,
{
let c_string = CString::new(string.as_ref()).unwrap();
unsafe {
let keysym = xlib::XStringToKeysym(c_string.as_ptr());
xlib::XKeysymToKeycode(self.dpy(), keysym) as i32
}
}
fn get_numlock_mask(&self) -> u32 {
unsafe {
let modmap = xlib::XGetModifierMapping(self.dpy());
let max_keypermod = (*modmap).max_keypermod;
for i in 0..8 {
for j in 0..max_keypermod {
if *(*modmap)
.modifiermap
.offset((i * max_keypermod + j) as isize)
== xlib::XKeysymToKeycode(
self.dpy(),
x11::keysym::XK_Num_Lock as u64,
)
{
return 1 << i;
}
}
}
}
0
}
pub fn get_clean_mask(&self) -> u32 {
!(self.get_numlock_mask() | LockMask)
& (ShiftMask
| ControlMask
| Mod1Mask
| Mod2Mask
| Mod3Mask
| Mod4Mask
| Mod5Mask)
}
#[allow(dead_code)]
pub fn clean_mask(&self, mask: u32) -> u32 {
mask & self.get_clean_mask()
}
pub fn are_masks_equal(&self, rhs: u32, lhs: u32) -> bool {
let clean = self.get_clean_mask();
rhs & clean == lhs & clean
}
}
impl Display {
pub fn new(display: *mut x11::xlib::Display) -> Self {
Self {
0: Rc::new(display),
}
}
pub fn get(&self) -> *mut x11::xlib::Display {
*self.0
}
}
impl Atoms {
fn init(display: Display) -> Self {
unsafe {
Self {
protocols: {
let name = CString::new("WM_PROTOCOLS").unwrap();
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
},
delete_window: {
let name = CString::new("WM_DELETE_WINDOW").unwrap();
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
},
active_window: {
let name = CString::new("WM_ACTIVE_WINDOW").unwrap();
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
},
take_focus: {
let name = CString::new("WM_TAKE_FOCUS").unwrap();
XInternAtom(display.get(), name.as_c_str().as_ptr(), 0)
},
}
}
}
}
#[allow(dead_code)]
unsafe extern "C" fn xlib_error_handler(
_dpy: *mut x11::xlib::Display,
ee: *mut x11::xlib::XErrorEvent,
) -> std::os::raw::c_int {
let err = ee.as_ref().unwrap();
if err.error_code == x11::xlib::BadWindow
|| err.error_code == x11::xlib::BadDrawable
|| err.error_code == x11::xlib::BadAccess
|| err.error_code == x11::xlib::BadMatch
{
0
} else {
error!(
"wm: fatal error:\nrequest_code: {}\nerror_code: {}",
err.request_code, err.error_code
);
std::process::exit(1);
}
}