diff --git a/src/backends/mod.rs b/src/backends/mod.rs index 5ba995e..ceb8dec 100644 --- a/src/backends/mod.rs +++ b/src/backends/mod.rs @@ -4,299 +4,27 @@ pub mod keycodes; pub mod window_event; pub mod xlib; -pub trait WindowServerBackend { - fn next_event(&self) -> window_event::WindowEvent; - fn add_keybind(&mut self, keybind: KeyBind, window: Option); - fn remove_keybind(&mut self, keybind: KeyBind, window: Option); - fn add_mousebind(&mut self, keybind: KeyBind, window: Option); - fn remove_mousebind(&mut self, keybind: KeyBind, window: Option); - fn focus_window(&self, window: Window); - fn unfocus_window(&self, window: Window); - fn move_window(&self, window: Window, pos: i32); - fn resize_window(&self, window: Window, pos: i32); - fn hide_window(&self, window: Window); +pub trait WindowServerBackend { + type Window; + + fn next_event(&self) -> window_event::WindowEvent; + fn add_keybind(&mut self, keybind: KeyBind, window: Option); + fn remove_keybind( + &mut self, + keybind: KeyBind, + window: Option, + ); + fn add_mousebind(&mut self, keybind: KeyBind, window: Option); + fn remove_mousebind( + &mut self, + keybind: KeyBind, + window: Option, + ); + fn focus_window(&self, window: Self::Window); + fn unfocus_window(&self, window: Self::Window); + fn move_window(&self, window: Self::Window, pos: i32); + fn resize_window(&self, window: Self::Window, pos: i32); + fn hide_window(&self, window: Self::Window); fn screen_size(&self) -> (i32, i32); - fn kill_window(&self, window: Window); + fn kill_window(&self, window: Self::Window); } - -// pub mod xlib { -// use log::{error, warn}; -// use std::{ -// borrow::Borrow, -// convert::{TryFrom, TryInto}, -// ffi::CString, -// rc::Rc, -// }; -// use thiserror::Error; - -// use x11::xlib::{self, Atom, Window, XEvent, XInternAtom}; - -// use super::{window_event::WindowEvent, WindowServerBackend}; - -// #[derive(Clone)] -// pub struct Display(Rc<*mut x11::xlib::Display>); - -// #[derive(Debug, Error)] -// pub enum XlibError { -// #[error("BadAccess")] -// BadAccess, -// #[error("BadAlloc")] -// BadAlloc, -// #[error("BadAtom")] -// BadAtom, -// #[error("BadColor")] -// BadColor, -// #[error("BadCursor")] -// BadCursor, -// #[error("BadDrawable")] -// BadDrawable, -// #[error("BadFont")] -// BadFont, -// #[error("BadGC")] -// BadGC, -// #[error("BadIDChoice")] -// BadIDChoice, -// #[error("BadImplementation")] -// BadImplementation, -// #[error("BadLength")] -// BadLength, -// #[error("BadMatch")] -// BadMatch, -// #[error("BadName")] -// BadName, -// #[error("BadPixmap")] -// BadPixmap, -// #[error("BadRequest")] -// BadRequest, -// #[error("BadValue")] -// BadValue, -// #[error("BadWindow")] -// BadWindow, -// #[error("Invalid XError: {0}")] -// InvalidError(u8), -// } - -// impl From for XlibError { -// fn from(value: u8) -> Self { -// match value { -// xlib::BadAccess => XlibError::BadAccess, -// xlib::BadAlloc => XlibError::BadAlloc, -// xlib::BadAtom => XlibError::BadAtom, -// xlib::BadColor => XlibError::BadColor, -// xlib::BadCursor => XlibError::BadCursor, -// xlib::BadDrawable => XlibError::BadDrawable, -// xlib::BadFont => XlibError::BadFont, -// xlib::BadGC => XlibError::BadGC, -// xlib::BadIDChoice => XlibError::BadIDChoice, -// xlib::BadImplementation => XlibError::BadImplementation, -// xlib::BadLength => XlibError::BadLength, -// xlib::BadMatch => XlibError::BadMatch, -// xlib::BadName => XlibError::BadName, -// xlib::BadPixmap => XlibError::BadPixmap, -// xlib::BadRequest => XlibError::BadRequest, -// xlib::BadValue => XlibError::BadValue, -// xlib::BadWindow => XlibError::BadWindow, -// any => XlibError::InvalidError(any), -// } -// } -// } - -// // impl Into for XlibError { -// // fn into(self) -> i32 { -// // match self { -// // XlibError::BadAccess => xlib::BadAccess.into(), -// // XlibError::BadAlloc => xlib::BadAlloc.into(), -// // XlibError::BadAtom => xlib::BadAtom.into(), -// // XlibError::BadColor => xlib::BadColor.into(), -// // XlibError::BadCursor => xlib::BadCursor.into(), -// // XlibError::BadDrawable => xlib::BadDrawable.into(), -// // XlibError::BadFont => xlib::BadFont.into(), -// // XlibError::BadGC => xlib::BadGC.into(), -// // XlibError::BadIDChoice => xlib::BadIDChoice.into(), -// // XlibError::BadImplementation => xlib::BadImplementation.into(), -// // XlibError::BadLength => xlib::BadLength.into(), -// // XlibError::BadMatch => xlib::BadMatch.into(), -// // XlibError::BadName => xlib::BadName.into(), -// // XlibError::BadPixmap => xlib::BadPixmap.into(), -// // XlibError::BadRequest => xlib::BadRequest.into(), -// // XlibError::BadValue => xlib::BadValue.into(), -// // XlibError::BadWindow => xlib::BadWindow.into(), -// // XlibError::InvalidError(err) => err, -// // } -// // } -// // } - -// 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 -// } -// } - -// pub struct XLib { -// display: Display, -// root: Window, -// screen: i32, -// atoms: XLibAtoms, -// keybinds: Vec<()>, -// } - -// impl XLib { -// fn dpy(&self) -> *mut xlib::Display { -// self.display.get() -// } - -// fn next_xevent(&self) -> XEvent { -// unsafe { -// let mut event = std::mem::MaybeUninit::::zeroed() -// .assume_init(); -// xlib::XNextEvent(self.dpy(), &mut event); - -// event -// } -// } -// } - -// impl TryFrom for WindowEvent { -// type Error = crate::error::Error; - -// fn try_from(event: XEvent) -> Result { -// match event.get_type() { -// xlib::MapRequest => Ok(Self::MapRequestEvent { -// window: event.map_request.window, -// event: todo!(), -// }), -// _ => Err(Self::Error::UnknownEvent), -// } -// } -// } - -// impl WindowServerBackend for XLib { -// fn next_event(&self) -> super::window_event::WindowEvent { -// self.next_xevent().try_into().unwrap() -// } - -// fn add_keybind( -// &mut self, -// keybind: super::window_event::KeyBind, -// window: Option, -// ) { -// todo!() -// } - -// fn remove_keybind( -// &mut self, -// keybind: super::window_event::KeyBind, -// window: Option, -// ) { -// todo!() -// } - -// fn add_mousebind( -// &mut self, -// keybind: super::window_event::KeyBind, -// window: Option, -// ) { -// todo!() -// } - -// fn remove_mousebind( -// &mut self, -// keybind: super::window_event::KeyBind, -// window: Option, -// ) { -// todo!() -// } - -// fn focus_window(&self, window: u64) { -// todo!() -// } - -// fn unfocus_window(&self, window: u64) { -// todo!() -// } - -// fn move_window(&self, window: u64, pos: i32) { -// todo!() -// } - -// fn resize_window(&self, window: u64, pos: i32) { -// todo!() -// } - -// fn hide_window(&self, window: u64) { -// todo!() -// } - -// fn screen_size(&self) -> (i32, i32) { -// todo!() -// } - -// fn kill_window(&self, window: u64) { -// todo!() -// } -// } - -// struct XLibAtoms { -// protocols: Atom, -// delete_window: Atom, -// active_window: Atom, -// take_focus: Atom, -// } - -// impl XLibAtoms { -// 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_event = ee.as_ref().unwrap(); -// let err = XlibError::from(err_event.error_code); - -// match err { -// err @ XlibError::BadAccess -// | err @ XlibError::BadMatch -// | err @ XlibError::BadWindow -// | err @ XlibError::BadDrawable => { -// warn!("{:?}", err); -// 0 -// } -// _ => { -// error!( -// "wm: fatal error:\nrequest_code: {}\nerror_code: {}", -// err_event.request_code, err_event.error_code -// ); -// std::process::exit(1) -// } -// } -// } -// } diff --git a/src/backends/window_event.rs b/src/backends/window_event.rs index 6e0aaef..801dabc 100644 --- a/src/backends/window_event.rs +++ b/src/backends/window_event.rs @@ -4,51 +4,18 @@ use super::keycodes::{MouseButton, VirtualKeyCode}; #[derive(Debug)] -pub enum WindowEvent { - KeyEvent { - window: Window, - event: KeyEvent, - }, - ButtonEvent { - window: Window, - event: ButtonEvent, - }, - MotionEvent { - window: Window, - event: MotionEvent, - }, - MapRequestEvent { - window: Window, - event: MapEvent, - }, - MapEvent { - window: Window, - event: MapEvent, - }, - UnmapEvent { - window: Window, - event: UnmapEvent, - }, - CreateEvent { - window: Window, - event: CreateEvent, - }, - DestroyEvent { - window: Window, - event: DestroyEvent, - }, - EnterEvent { - window: Window, - event: EnterEvent, - }, - ConfigureEvent { - window: Window, - event: ConfigureEvent, - }, - FullscreenEvent { - window: Window, - event: FullscreenEvent, - }, //1 { window: Window, event: 1 }, +pub enum WindowEvent { + KeyEvent(KeyEvent), + ButtonEvent(ButtonEvent), + MotionEvent(MotionEvent), + MapRequestEvent(MapEvent), + MapEvent(MapEvent), + UnmapEvent(UnmapEvent), + CreateEvent(CreateEvent), + DestroyEvent(DestroyEvent), + EnterEvent(EnterEvent), + ConfigureEvent(ConfigureEvent), + FullscreenEvent(FullscreenEvent), //1 { window: Window, event: 1 }, } #[derive(Debug)] @@ -94,19 +61,22 @@ impl ModifierState { } #[derive(Debug)] -pub struct KeyEvent { +pub struct KeyEvent { + pub window: Window, pub state: KeyState, pub keycode: VirtualKeyCode, pub modifierstate: ModifierState, } -impl KeyEvent { +impl KeyEvent { pub fn new( + window: Window, state: KeyState, keycode: VirtualKeyCode, modifierstate: ModifierState, ) -> Self { Self { + window, state, keycode, modifierstate, @@ -115,19 +85,22 @@ impl KeyEvent { } #[derive(Debug)] -pub struct ButtonEvent { +pub struct ButtonEvent { + pub window: Window, pub state: KeyState, pub keycode: MouseButton, pub modifierstate: ModifierState, } -impl ButtonEvent { +impl ButtonEvent { pub fn new( + window: Window, state: KeyState, keycode: MouseButton, modifierstate: ModifierState, ) -> Self { Self { + window, state, keycode, modifierstate, @@ -136,60 +109,51 @@ impl ButtonEvent { } #[derive(Debug)] -pub struct MotionEvent { +pub struct MotionEvent { pub position: [i32; 2], + pub window: Window, } -impl MotionEvent { - pub fn new(position: [i32; 2]) -> Self { - Self { position } +impl MotionEvent { + pub fn new(position: [i32; 2], window: Window) -> Self { + Self { position, window } } } #[derive(Debug)] -pub struct MapEvent { +pub struct MapEvent { pub window: Window, } -impl MapEvent { +#[derive(Debug)] +pub struct UnmapEvent { + pub window: Window, +} + +#[derive(Debug)] +pub struct EnterEvent { + pub window: Window, +} + +#[derive(Debug)] +pub struct DestroyEvent { + pub window: Window, +} + +impl DestroyEvent { pub fn new(window: Window) -> Self { Self { window } } } #[derive(Debug)] -pub struct UnmapEvent { - pub window: Window, -} - -impl UnmapEvent { - pub fn new(window: Window) -> Self { - Self { window } - } -} - -#[derive(Debug)] -pub struct EnterEvent {} - -#[derive(Debug)] -pub struct DestroyEvent { - pub window: Window, -} - -impl DestroyEvent { - pub fn new(window: Window) -> Self { - Self { window } - } -} - -#[derive(Debug)] -pub struct CreateEvent { +pub struct CreateEvent { pub window: Window, pub position: [i32; 2], pub size: [i32; 2], } -impl CreateEvent { +impl CreateEvent { pub fn new(window: Window, position: [i32; 2], size: [i32; 2]) -> Self { Self { window, @@ -200,13 +164,13 @@ impl CreateEvent { } #[derive(Debug)] -pub struct ConfigureEvent { +pub struct ConfigureEvent { pub window: Window, pub position: [i32; 2], pub size: [i32; 2], } -impl ConfigureEvent { +impl ConfigureEvent { pub fn new(window: Window, position: [i32; 2], size: [i32; 2]) -> Self { Self { window, @@ -217,13 +181,17 @@ impl ConfigureEvent { } #[derive(Debug)] -pub struct FullscreenEvent { +pub struct FullscreenEvent { + window: Window, new_fullscreen: bool, } -impl FullscreenEvent { - pub fn new(new_fullscreen: bool) -> Self { - Self { new_fullscreen } +impl FullscreenEvent { + pub fn new(window: Window, new_fullscreen: bool) -> Self { + Self { + window, + new_fullscreen, + } } } diff --git a/src/backends/xlib/keysym.rs b/src/backends/xlib/keysym.rs index 804713c..c483443 100644 --- a/src/backends/xlib/keysym.rs +++ b/src/backends/xlib/keysym.rs @@ -1,7 +1,8 @@ -use crate::backends::{ - keycodes::{MouseButton, VirtualKeyCode}, - window_event::ModifierKey, -}; +use std::{borrow::Borrow, ops::Deref}; + +use x11::xlib::XKeyReleasedEvent; + +use crate::backends::keycodes::{MouseButton, VirtualKeyCode}; pub fn xev_to_mouse_button( button: &x11::xlib::XButtonEvent, @@ -34,10 +35,42 @@ pub fn mouse_button_to_xbutton(button: MouseButton) -> i32 { } } +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)] +pub struct XKeysym(u32); + +impl Borrow for XKeysym { + fn borrow(&self) -> &u32 { + &self.0 + } +} + +impl AsRef for XKeysym { + fn as_ref(&self) -> &u32 { + &self.0 + } +} + +impl Deref for XKeysym { + type Target = u32; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for VirtualKeyCode { + fn from(value: XKeysym) -> Self { + keysym_to_virtual_keycode(*value).unwrap() + } +} +impl From for XKeysym { + fn from(value: VirtualKeyCode) -> Self { + Self(virtual_keycode_to_keysym(value).unwrap()) + } +} + /// from winit -pub fn keysym_to_virtual_keycode( - keysym: u32, -) -> Option { +pub fn keysym_to_virtual_keycode(keysym: u32) -> Option { Some(match keysym { x11::keysym::XK_BackSpace => VirtualKeyCode::Back, x11::keysym::XK_Tab => VirtualKeyCode::Tab, @@ -1034,9 +1067,7 @@ pub fn keysym_to_virtual_keycode( //x11::keysym::XK_hebrew_taf => VirtualKeyCode::Hebrew_taf, //x11::keysym::XK_Hebrew_switch => VirtualKeyCode::Hebrew_switch, x11::keysym::XF86XK_Back => VirtualKeyCode::NavigateBackward, - x11::keysym::XF86XK_Forward => { - VirtualKeyCode::NavigateForward - } + x11::keysym::XF86XK_Forward => VirtualKeyCode::NavigateForward, x11::keysym::XF86XK_Copy => VirtualKeyCode::Copy, x11::keysym::XF86XK_Paste => VirtualKeyCode::Paste, x11::keysym::XF86XK_Cut => VirtualKeyCode::Cut, @@ -1044,9 +1075,7 @@ pub fn keysym_to_virtual_keycode( }) } -pub fn virtual_keycode_to_keysym( - keycode: VirtualKeyCode, -) -> Option { +pub fn virtual_keycode_to_keysym(keycode: VirtualKeyCode) -> Option { Some(match keycode { VirtualKeyCode::Back => x11::keysym::XK_BackSpace, VirtualKeyCode::Tab => x11::keysym::XK_Tab, @@ -2043,12 +2072,28 @@ pub fn virtual_keycode_to_keysym( //VirtualKeyCode::Hebrew_taf => x11::keysym::XK_hebrew_taf, //VirtualKeyCode::Hebrew_switch => x11::keysym::XK_Hebrew_switch, VirtualKeyCode::NavigateBackward => x11::keysym::XF86XK_Back, - VirtualKeyCode::NavigateForward => { - x11::keysym::XF86XK_Forward - } + VirtualKeyCode::NavigateForward => x11::keysym::XF86XK_Forward, VirtualKeyCode::Copy => x11::keysym::XF86XK_Copy, VirtualKeyCode::Paste => x11::keysym::XF86XK_Paste, VirtualKeyCode::Cut => x11::keysym::XF86XK_Cut, _ => return None, }) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_keysym_to_vkc() { + let keysym: XKeysym = VirtualKeyCode::W.into(); + let keycode: VirtualKeyCode = keysym.into(); + + assert_eq!(keycode, VirtualKeyCode::W); + + let keysym2: XKeysym = keycode.into(); + + assert_eq!(keysym2, keysym); + assert_eq!(&x11::keysym::XK_W, keysym.as_ref()); + } +} diff --git a/src/backends/xlib/mod.rs b/src/backends/xlib/mod.rs index 703887e..67224c8 100644 --- a/src/backends/xlib/mod.rs +++ b/src/backends/xlib/mod.rs @@ -1,6 +1,5 @@ use log::{error, warn}; use std::{ - borrow::Borrow, convert::{TryFrom, TryInto}, ffi::CString, rc::Rc, @@ -9,7 +8,16 @@ use thiserror::Error; use x11::xlib::{self, Atom, Window, XEvent, XInternAtom}; -use super::{window_event::WindowEvent, WindowServerBackend}; +use self::keysym::xev_to_mouse_button; + +use super::{ + keycodes::{MouseButton, VirtualKeyCode}, + window_event::{ + ButtonEvent, ConfigureEvent, DestroyEvent, EnterEvent, KeyState, + MapEvent, ModifierState, UnmapEvent, WindowEvent, + }, + WindowServerBackend, +}; pub mod keysym; @@ -142,29 +150,69 @@ impl XLib { } } -impl TryFrom for WindowEvent { +impl TryFrom for WindowEvent { type Error = crate::error::Error; fn try_from(event: XEvent) -> Result { match event.get_type() { - xlib::MapRequest => Ok(Self::MapRequestEvent { - window: event.map_request.window, - event: todo!(), - }), + xlib::MapRequest => { + let ev = unsafe { &event.map_request }; + Ok(Self::MapRequestEvent(MapEvent { window: ev.window })) + } + xlib::UnmapNotify => { + let ev = unsafe { &event.unmap }; + Ok(Self::UnmapEvent(UnmapEvent { window: ev.window })) + } + xlib::ConfigureRequest => { + let ev = unsafe { &event.configure_request }; + Ok(Self::ConfigureEvent(ConfigureEvent { + window: ev.window, + position: [ev.x, ev.y], + size: [ev.width, ev.height], + })) + } + xlib::EnterNotify => { + let ev = unsafe { &event.crossing }; + Ok(Self::EnterEvent(EnterEvent { window: ev.window })) + } + xlib::DestroyNotify => { + let ev = unsafe { &event.destroy_window }; + Ok(Self::DestroyEvent(DestroyEvent { window: ev.window })) + } + xlib::ButtonPress | xlib::ButtonRelease => { + let ev = unsafe { &event.button }; + let keycode = xev_to_mouse_button(ev).unwrap(); + let state = if ev.state as i32 == xlib::ButtonPress { + KeyState::Pressed + } else { + KeyState::Released + }; + + let modifierstate = ModifierState::new(); + + Ok(Self::ButtonEvent(ButtonEvent::new( + ev.window, + state, + keycode, + modifierstate, + ))) + } _ => Err(Self::Error::UnknownEvent), } } } impl WindowServerBackend for XLib { - fn next_event(&self) -> super::window_event::WindowEvent { + type Window = xlib::Window; + + fn next_event(&self) -> super::window_event::WindowEvent { self.next_xevent().try_into().unwrap() } fn add_keybind( &mut self, keybind: super::window_event::KeyBind, - window: Option, + window: Option, ) { todo!() } @@ -172,7 +220,7 @@ impl WindowServerBackend for XLib { fn remove_keybind( &mut self, keybind: super::window_event::KeyBind, - window: Option, + window: Option, ) { todo!() } @@ -180,7 +228,7 @@ impl WindowServerBackend for XLib { fn add_mousebind( &mut self, keybind: super::window_event::KeyBind, - window: Option, + window: Option, ) { todo!() } @@ -188,28 +236,28 @@ impl WindowServerBackend for XLib { fn remove_mousebind( &mut self, keybind: super::window_event::KeyBind, - window: Option, + window: Option, ) { todo!() } - fn focus_window(&self, window: u64) { + fn focus_window(&self, window: Self::Window) { todo!() } - fn unfocus_window(&self, window: u64) { + fn unfocus_window(&self, window: Self::Window) { todo!() } - fn move_window(&self, window: u64, pos: i32) { + fn move_window(&self, window: Self::Window, pos: i32) { todo!() } - fn resize_window(&self, window: u64, pos: i32) { + fn resize_window(&self, window: Self::Window, pos: i32) { todo!() } - fn hide_window(&self, window: u64) { + fn hide_window(&self, window: Self::Window) { todo!() } @@ -217,7 +265,7 @@ impl WindowServerBackend for XLib { todo!() } - fn kill_window(&self, window: u64) { + fn kill_window(&self, window: Self::Window) { todo!() } } diff --git a/src/main.rs b/src/main.rs index 971d7f7..c48a205 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,6 +23,8 @@ pub mod error { NonError, #[error("Unknown Event")] UnknownEvent, + #[error("Unhandled VirtualKeyCode")] + UnhandledVirtualKeyCode, #[error(transparent)] IoError(#[from] std::io::Error), #[error(transparent)]