i genuinely have no idea what i changed. i probably added stuff.

This commit is contained in:
Schrottkatze 2022-10-22 20:47:53 +02:00
parent 52a61e070d
commit 8dd78c66b7
6 changed files with 301 additions and 61 deletions

View file

@ -81,7 +81,11 @@ impl EvCallbackData {
} }
} }
fn calculate_delay(server_time: xlib::Time, last_event: xlib::Time, max_delay: Option<xlib::Time>) -> xlib::Time { fn calculate_delay(
server_time: xlib::Time,
last_event: xlib::Time,
max_delay: Option<xlib::Time>,
) -> xlib::Time {
if let Some(max) = max_delay { if let Some(max) = max_delay {
let max = max as u64; let max = max as u64;
let delay = server_time - last_event; let delay = server_time - last_event;

View file

@ -1,5 +1,5 @@
use crate::Instructions; use crate::Instructions;
use std::{io, fs}; use std::{fs, io};
pub struct MacroWriter { pub struct MacroWriter {
outfile: Box<dyn io::Write>, outfile: Box<dyn io::Write>,
@ -9,19 +9,18 @@ pub struct MacroWriter {
impl MacroWriter { impl MacroWriter {
pub fn new(outfile: Option<std::path::PathBuf>, ignore_delay_capturing: bool) -> Self { pub fn new(outfile: Option<std::path::PathBuf>, ignore_delay_capturing: bool) -> Self {
Self { Self {
outfile: outfile: if let Some(outfile) = outfile {
if let Some(outfile) = outfile { Box::new(fs::File::create(outfile).expect("Failed to create output file"))
Box::new(fs::File::create(outfile).expect("Failed to create output file")) } else {
} else { Box::new(io::stdout())
Box::new(io::stdout()) },
},
ignore_delay_capturing, ignore_delay_capturing,
} }
} }
pub fn write(&mut self, instruction: Instructions) { pub fn write(&mut self, instruction: Instructions) {
if self.ignore_delay_capturing { if self.ignore_delay_capturing {
if let Instructions::Delay(_) = instruction { } if let Instructions::Delay(_) = instruction {}
} }
writeln!(&mut self.outfile, "{}", instruction) writeln!(&mut self.outfile, "{}", instruction)

View file

@ -1,4 +1,4 @@
use std::{env, ffi, ptr, ops}; use std::{env, ffi, ops, ptr};
use x11::xlib::{self, BadGC}; use x11::xlib::{self, BadGC};
@ -26,7 +26,7 @@ pub enum Grabbables {
Pointer, Pointer,
} }
impl std::fmt::Display for Grabbables{ impl std::fmt::Display for Grabbables {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Grabbables::Keyboard => write!(f, "keyboard"), Grabbables::Keyboard => write!(f, "keyboard"),
@ -50,6 +50,33 @@ impl From<GrabMode> for i32 {
} }
} }
/// The event mode for XAllowEvents
pub enum EventMode {
AsyncPointer,
SyncPointer,
AsyncKeyboard,
SyncKeyboard,
ReplayPointer,
ReplayKeyboard,
AsyncBoth,
SyncBoth
}
impl From<EventMode> for i32 {
fn from(event_mode: EventMode) -> Self {
match event_mode {
EventMode::AsyncPointer => xlib::AsyncPointer,
EventMode::SyncPointer => xlib::SyncPointer,
EventMode::AsyncKeyboard => xlib::AsyncKeyboard,
EventMode::SyncKeyboard => xlib::SyncKeyboard,
EventMode::ReplayPointer => xlib::ReplayPointer,
EventMode::ReplayKeyboard => xlib::ReplayKeyboard,
EventMode::AsyncBoth => xlib::AsyncBoth,
EventMode::SyncBoth => xlib::SyncBoth,
}
}
}
impl Display { impl Display {
/// Call XOpenDisplay to open a connection to the X Server. /// Call XOpenDisplay to open a connection to the X Server.
/// If `display_name` is `None`, the value of the `DISPLAY` environment variable will be used. /// If `display_name` is `None`, the value of the `DISPLAY` environment variable will be used.
@ -87,7 +114,7 @@ impl Display {
// TODO: Figure out how to properly handle errors // TODO: Figure out how to properly handle errors
/// Calls XSync to flush the output buffer and then wait until all events have been received and processed /// Calls XSync to flush the output buffer and then wait until all events have been received and processed
/// by the server. /// by the server.
/// The `discard` parameter specifies, whether to discard all events in the queue. /// The `discard` parameter specifies, whether to discard all events in the queue.
pub fn sync(&self, discard: bool) { pub fn sync(&self, discard: bool) {
unsafe { unsafe {
@ -95,30 +122,24 @@ impl Display {
} }
} }
/// Calls xlib::XDefaultScreen to get the default screen number referenced by Display::open. /// Calls xlib::XDefaultScreen to get the default screen number referenced by Display::open.
/// This should be used to retrieve the screen number in applications that'll only use a single /// This should be used to retrieve the screen number in applications that'll only use a single
/// screen. /// screen.
pub fn default_screen_nr(&self) -> i32 { pub fn default_screen_nr(&self) -> i32 {
unsafe { unsafe { xlib::XDefaultScreen(self.ptr) }
xlib::XDefaultScreen(self.ptr)
}
} }
/// Gets the default screen /// Gets the default screen
pub fn default_screen(&self) -> screen::Screen { pub fn default_screen(&self) -> screen::Screen {
screen::Screen { screen::Screen {
ptr: unsafe { ptr: unsafe { xlib::XDefaultScreenOfDisplay(self.ptr) },
xlib::XDefaultScreenOfDisplay(self.ptr)
}
} }
} }
/// Gets the root window of the default screen /// Gets the root window of the default screen
pub fn default_root_window(&self) -> window::Window { pub fn default_root_window(&self) -> window::Window {
window::Window { window::Window {
wid: unsafe { wid: unsafe { xlib::XDefaultRootWindow(self.ptr) },
xlib::XDefaultRootWindow(self.ptr)
}
} }
} }
@ -133,35 +154,69 @@ impl Display {
} }
} }
pub fn grab_keyboard( &mut self, grab_window: window::Window, owner_events: bool, pointer_mode: GrabMode, keyboard_mode: GrabMode, time:xlib::Time) -> Result<()> { /// Performs an active Grab on the keyboard. Further key events are only reported to the
match unsafe { /// grabbing client.
xlib::XGrabKeyboard( pub fn grab_keyboard(
self.ptr, &mut self,
grab_window.wid, grab_window: window::Window,
owner_events.into(), owner_events: bool,
pointer_mode.into(), pointer_mode: GrabMode,
keyboard_mode.into(), keyboard_mode: GrabMode,
time time: xlib::Time,
) ) -> Result<()> {
} { if let None = self.keyboard_grab {
xlib::GrabSuccess => { match unsafe {
self.keyboard_grab = Some(GrabbablesModes { xlib::XGrabKeyboard(
keyboard_mode, self.ptr,
pointer_mode grab_window.wid,
}); owner_events.into(),
pointer_mode.into(),
keyboard_mode.into(),
time,
)
} {
xlib::GrabSuccess => {
self.keyboard_grab = Some(GrabbablesModes {
keyboard_mode,
pointer_mode,
});
Ok(())
}
xlib::AlreadyGrabbed =>
Err(error::XError::XAlreadyGrabbed(Grabbables::Keyboard).into()),
xlib::GrabInvalidTime =>
Err(error::XError::XGrabInvalidTime.into()),
xlib::GrabNotViewable =>
Err(error::XError::XGrabNotViewable.into()),
xlib::GrabFrozen =>
Err(error::XError::XGrabFrozen(Grabbables::Keyboard).into()),
code => Err(error::XError::UnknownError(code).into()),
}
} else {
Err(error::XError::AlreadyGrabbed(Grabbables::Keyboard).into())
}
}
/// Ends the active keyboard grab.
pub fn ungrab_keyboard(&self, time: xlib::Time) -> Result<()>{
if let Some(_) = self.keyboard_grab {
unsafe {
xlib::XUngrabKeyboard(self.ptr, time);
Ok(()) Ok(())
}, }
xlib::AlreadyGrabbed => todo!(), } else {
xlib::GrabInvalidTime => todo!(), Err(error::XError::NotGrabbed(Grabbables::Keyboard).into())
xlib::GrabNotViewable => todo!(), }
xlib::GrabFrozen => todo!(), }
_ => todo!()
pub fn allow_events(&self, event_mode: EventMode, time: xlib::Time) {
unsafe {
xlib::XAllowEvents(self.ptr, event_mode.into(), time);
} }
} }
} }
impl Drop for Display { impl Drop for Display {
fn drop(&mut self) { fn drop(&mut self) {
if unsafe { xlib::XCloseDisplay(self.ptr) } == BadGC.into() { if unsafe { xlib::XCloseDisplay(self.ptr) } == BadGC.into() {

View file

@ -11,10 +11,13 @@ pub enum XError {
DisplayKeycodesError, DisplayKeycodesError,
InvalidKeycodeError(xlib::KeyCode, ops::Range<i32>), InvalidKeycodeError(xlib::KeyCode, ops::Range<i32>),
AlreadyGrabbed(display::Grabbables), AlreadyGrabbed(display::Grabbables),
NotGrabbed(display::Grabbables),
XAlreadyGrabbed(display::Grabbables), XAlreadyGrabbed(display::Grabbables),
XGrabFrozen(display::Grabbables), XGrabFrozen(display::Grabbables),
XGrabInvalidTime, XGrabInvalidTime,
XGrabNotViewable, XGrabNotViewable,
XEventConversionError { event_type: i32 },
UnknownError(i32),
} }
impl std::fmt::Display for XError { impl std::fmt::Display for XError {
@ -25,20 +28,32 @@ impl std::fmt::Display for XError {
match self { match self {
XError::OpenDisplayError(display_name) => XError::OpenDisplayError(display_name) =>
format!("error when opening display '{}'", display_name), format!("error when opening display '{}'", display_name),
XError::DisplayKeycodesError => XError::DisplayKeycodesError => String::from("error when running XDisplayKeycodes"),
String::from("error when running XDisplayKeycodes"), XError::InvalidKeycodeError(code, range) =>
XError::InvalidKeycodeError(code, range) => format!("keycode {} outside of range {:?}", code, range),
format!("keycode {} outside of range {:?}", code, range), XError::AlreadyGrabbed(thing_attempted_to_grab) => format!(
XError::AlreadyGrabbed(thing_attempted_to_grab) => "this display already grabbed the {}",
format!("this display already grabbed the {}", thing_attempted_to_grab), thing_attempted_to_grab
XError::XAlreadyGrabbed(thing_attempted_to_grab) => ),
format!("{} is already actively grabbed by another client", thing_attempted_to_grab), XError::NotGrabbed(thing_attempted_to_ungrab) => format!(
XError::XGrabFrozen(thing_attempted_to_grab) => "couldn't ungrab the {} because it wasn't grabbed",
format!("{} is frozen by an active grab of another client", thing_attempted_to_grab), thing_attempted_to_ungrab
XError::XGrabInvalidTime => ),
String::from("invalid grab time"), XError::XAlreadyGrabbed(thing_attempted_to_grab) => format!(
XError::XGrabNotViewable => "{} is already actively grabbed by another client",
String::from("grab_window is not viewable"), thing_attempted_to_grab
),
XError::XGrabFrozen(thing_attempted_to_grab) => format!(
"{} is frozen by an active grab of another client",
thing_attempted_to_grab
),
XError::XGrabInvalidTime => String::from("invalid grab time"),
XError::XGrabNotViewable => String::from("grab_window is not viewable"),
XError::XEventConversionError { event_type } => format!(
"invalid event type: {}",
event_type
),
XError::UnknownError(code) => format!("unknown error code was returned: {}", code),
} }
) )
} }

166
src/xwrap/event.rs Normal file
View file

@ -0,0 +1,166 @@
use x11::xlib::{self, XKeyEvent};
use anyhow::Result;
use super::{display, window, key, error};
pub type Vec2<T> = (T, T);
pub enum Event {
// only for now relevant event types
KeyPressEvent(KeyEvent),
KeyReleaseEvent(KeyEvent),
ButtonPressEvent(ButtonEvent),
ButtonReleaseEvent(ButtonEvent),
MotionEvent(MotionEvent),
ErrorEvent(ErrorEvent),
CrossingEvent(CrossingEvent),
FocusChangeEvent(FocusChangeEvent),
ExposeEvent(ExposeEvent),
GraphicsExposeEvent(GraphicsExposeEvent),
NoExposeEvent(NoExposeEvent),
VisibilityEvent(VisibilityEvent),
CreateWindowEvent(CreateWindowEvent),
DestroyWindowEvent(DestroyWindowEvent),
UnmapEvent(UnmapEvent),
MapEvent(MapEvent),
MapRequestEvent(MapRequestEvent),
ReparentEvent(ReparentEvent),
ConfigureEvent(ConfigureEvent),
GravityEvent(GravityEvent),
ResizeRequestEvent(ResizeRequestEvent),
ConfigureRequestEvent(ConfigureRequestEvent),
CirculateEvent(CirculateEvent),
CirculateRequestEvent(CirculateRequestEvent),
PropertyEvent(PropertyEvent),
SelectionClearEvent(SelectionClearEvent),
SelectionRequestEvent(SelectionRequestEvent),
SelectionEvent(SelectionEvent),
ColormapEvent(ColormapEvent),
ClientMessageEvent(ClientMessageEvent),
MappingEvent(MappingEvent),
KeymapEvent(KeymapEvent),
}
impl TryFrom<xlib::XEvent> for Event {
type Error = error::XError;
fn try_from(ev_union: xlib::XEvent) -> Result<Self, Self::Error> {
match ev_union.get_type() {
xlib::KeyPress => ,
xlib::KeyRelease => ,
xlib::ButtonPress => ,
xlib::ButtonRelease => ,
xlib::MotionNotify => ,
}
}
}
struct GenericEventData {
serial_nr: u64,
sent_by_different_client: bool,
source_display_ptr: *mut xlib::_XDisplay,
window: window::Window,
}
pub enum SwitchState {
Pressed,
Released
}
pub struct KeyEvent {
generic: GenericEventData,
root: window::Window,
subwindow: window::Window,
time: xlib::Time,
pointer_pos: Vec2<i32>,
pointer_pos_root: Vec2<i32>,
state: SwitchState,
key: key::Key,
same_screen: bool
}
impl TryFrom<xlib::XEvent> for KeyEvent {
type Error = error::XError;
fn try_from(raw_ev: xlib::XEvent) -> Result<Self, Self::Error> {
let state = match raw_ev.get_type() {
xlib::KeyPress => SwitchState::Pressed,
xlib::KeyRelease => SwitchState::Released,
ev_type => return Err(error::XError::XEventConversionError { event_type: ev_type })
};
let raw_ev = XKeyEvent::from(raw_ev);
Ok(Self {
generic: GenericEventData {
serial_nr: raw_ev.serial,
sent_by_different_client: raw_ev.send_event != 0,
// make conversion method for display from ptr that maybe should try to check???
// how would i even do this safely
source_display_ptr: raw_ev.display,
window: window::Window { wid: raw_ev.window },
},
root: window::Window { wid: raw_ev.root },
subwindow: window::Window { wid: raw_ev.subwindow } ,
time: raw_ev.time,
pointer_pos: (raw_ev.x, raw_ev.y),
pointer_pos_root: (raw_ev.x_root, raw_ev.y_root),
state: raw_ev.state,
key: key::Key { code: raw_ev.keycode },
same_screen: raw_ev.same_screen != 0
})
}
}
pub struct ButtonEvent {
generic: GenericEventData,
root: window::Window,
time: xlib::Time,
pointer_pos: Vec2<i32>,
pointer_pos_root: Vec2<i32>,
button: u32,
state: SwitchState,
same_screen: bool
}
// change fields and data for this and other events according to xlib doc p. 188-189
pub struct MotionEvent {
generic: GenericEventData,
root: window::Window,
subwindow: window::Window,
time: xlib::Time,
pointer_pos: Vec2<i32>,
pointer_pos_root: Vec2<i32>,
state: u32,
is_hint: u32,
same_screen: bool,
}
// TODO: make these into cool event stuff too
pub struct ErrorEvent {}
pub struct CrossingEvent {}
pub struct FocusChangeEvent {}
pub struct ExposeEvent {}
pub struct GraphicsExposeEvent {}
pub struct NoExposeEvent {}
pub struct VisibilityEvent {}
pub struct CreateWindowEvent {}
pub struct DestroyWindowEvent {}
pub struct UnmapEvent {}
pub struct MapEvent {}
pub struct MapRequestEvent {}
pub struct ReparentEvent {}
pub struct ConfigureEvent {}
pub struct GravityEvent {}
pub struct ResizeRequestEvent {}
pub struct ConfigureRequestEvent {}
pub struct CirculateEvent {}
pub struct CirculateRequestEvent {}
pub struct PropertyEvent {}
pub struct SelectionClearEvent {}
pub struct SelectionRequestEvent {}
pub struct SelectionEvent {}
pub struct ColormapEvent {}
pub struct ClientMessageEvent {}
pub struct MappingEvent {}
pub struct KeymapEvent {}

View file

@ -1,5 +1,6 @@
pub mod display; pub mod display;
pub mod screen;
pub mod window;
pub mod error; pub mod error;
pub mod key; pub mod key;
pub mod screen;
pub mod window;
pub mod event;