2JZYL7R4OQIZMHTBGZA6HNAC7KLN7DSGZJRE7YILLMTR3WR2XLHAC
42CBEYZTGKPTDFNBTNCBUWWCABZOMBY3FCWWHUILQIGO2M54OJXQC
SMM42WXFAYFMOMUR7DCVCZCK7QMXIE5KUH4GUOIZPVFDDYB4ZMZAC
AWPTZQQYEYW2BMXCWYAWSZAVUE55YOMO7IE4VCXP5J4UOKUMKQFAC
M2FGQSGQITI7FYU3RWY3IGIA4ZLS6JAZMHIO64WNHKS4JIL53OWQC
AGPU6SD7V5FQNI6W54HDRJQCVHWYCZIHDHL6IL5LVVMJ7SVJL7UAC
KWR2TS2D7YN4LCGMQZ35V4WBLQDHAVSZJV3SZAIR5HQRSJAWLWCQC
2DG7PVTZAJ4NMGY2BNODJRLYTOV3MPTH3V6EZMK3WSIUZESLPQXQC
VODZCAIINDFQAU6RUV5VBRGJSMCWNMYAQ3ZE56SNBYU2WOSHFOMAC
BQFOYJRTLAFIBZ3SOERSUB2ZXMXJUAROXOGMGWHJW4CVBRT4R5QAC
LSQ7OPL7Z5WJDO7ZZS3D4UPMEEWUUF2LNQ3FZUWWFUVZEXA7CIOAC
YYUB6HZYSVQSCO7DGF6ETPAXTMG6SG2RQQXLP73NKPLDMZEC3PGAC
AYQYCR7JKWTAZASLQTY5DPVI6A5MN6X4XMPC3GBS5KJRH3EGRPIQC
RPECDMZ4O7MMU32H6Z7EW75GRVEQ6IJYNPWSV54HUPTCX5H7I26QC
K3I54HXNNCTEA7L6UGWIVBFB5TPZVZZXDBRSR2YZDIKREXQVWRIQC
7RMAZDLQ6FEEQGUUAIVEM4X2VME7IUUZMEJMMV3H46U3UKO4BODQC
LKAUS67VU5SLG5O5MTSO6N4VVT5OB2X4VNR6HYLIJ3ZOAXRQ4Q2QC
7MWGEO4D53CRQYELJQJ3PMI3BZJNAJJRX7AESNZ4NMF23XGBFEGAC
JVO3ABY7VTFBUPUEPNXVSGWLCBJLPDHLSLZJEW2LSEOFUR5Z4RIAC
JUNCSETUHRAPHZYVBESYW4LTKL6EW3X4G73ILT736PWDXB45Z6GQC
ZJ22USKSC26EQ25RKGXJCRYR7RG65YNAVZ5TKN5WY6ADVAXB5YJAC
[[package]]
name = "futures"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-executor"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
[[package]]
name = "futures-macro"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39"
dependencies = [
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
name = "futures-sink"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
[[package]]
name = "futures-task"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
dependencies = [
"once_cell",
]
[[package]]
name = "futures-util"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project",
"pin-utils",
"proc-macro-hack",
"proc-macro-nested",
"slab",
]
[[package]]
name = "pin-project"
version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro-hack"
version = "0.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99c605b9a0adc77b7211c6b1f722dcb613d68d66859a44f3d485a6da332b0598"
[[package]]
name = "proc-macro-nested"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a"
[[package]]
pub fn refocus<H>(&mut self, host: &H, focus: Focus) where
H: HostInterface
{
let was_focused = self.locally_focused();
self.private_refocus(host, focus, was_focused);
}
// pub fn refocus<H>(&mut self, host: &H, focus: Focus) where
// H: HostInterface
// {
// let was_focused = self.locally_focused();
// self.private_refocus(host, focus, was_focused);
// }
fn private_refocus<H>(&mut self, host: &H, focus: Focus, was_focused: bool) where
H: HostInterface
{
self.focus = self.normalize_focus(focus);
if self.locally_focused() {
if !was_focused {
host.ungrab_cursor();
host.ungrab_keyboard();
}
// fn private_refocus<H>(&mut self, host: &H, focus: Focus, was_focused: bool) where
// H: HostInterface
// {
// self.focus = self.normalize_focus(focus);
// if self.locally_focused() {
// if !was_focused {
// host.ungrab_cursor();
// host.ungrab_keyboard();
// }
host.send_event(HostEvent::Position(PositionEvent {
x: self.focus.pos.x, y: self.focus.pos.y,
}));
} else {
if was_focused {
host.grab_cursor();
host.grab_keyboard();
}
}
}
// host.send_event(HostEvent::Position(PositionEvent {
// x: self.focus.pos.x, y: self.focus.pos.y,
// }));
// } else {
// if was_focused {
// host.grab_cursor();
// host.grab_keyboard();
// }
// }
// }
use x11_dl::xfixes;
use x11_dl::xinput2;
use x11_dl::xlib;
use x11_dl::xtest;
use tokio::io::PollEvented;
use x11_dl::{
xfixes,
xinput2,
xlib,
xtest,
};
let xlib = xlib::Xlib::open().unwrap();
let xtest = xtest::Xf86vmode::open().unwrap();
let xinput2 = xinput2::XInput2::open().unwrap();
let xfixes = xfixes::XFixes::open().unwrap();
unsafe {
let xlib = xlib::Xlib::open().unwrap();
let display = (xlib.XOpenDisplay)(ptr::null());
if display.is_null() {
panic!("Failed to open display");
}
let io = PollEvented::new(Connection {
fd: (xlib.XConnectionNumber)(display)
}).unwrap();
let root = (xlib.XDefaultRootWindow)(display);
let display = unsafe { (xlib.XOpenDisplay)(ptr::null()) };
if display.is_null() {
panic!("Failed to open display");
}
// Query X
let xfixes = xfixes::XFixes::open().unwrap();
let xfixes_event_base = {
let mut event_base = MaybeUninit::uninit();
if (xfixes.XFixesQueryExtension)(
display,
event_base.as_mut_ptr(),
ptr::null_mut(),
) == xlib::False {
panic!("Failed to query XFixes");
}
// Query XInput2
unsafe {
let mut major_opcode = MaybeUninit::uninit();
let mut first_event = MaybeUninit::uninit();
let mut first_error = MaybeUninit::uninit();
if (xlib.XQueryExtension)(display,
CString::new("XInputExtension").unwrap().as_ptr(),
major_opcode.as_mut_ptr(),
first_event.as_mut_ptr(),
first_error.as_mut_ptr(),
) == xlib::False {
panic!("Failed to query XInputExtension");
event_base.assume_init()
// Query XFixes
let xfixes_event_base = unsafe {
let mut event_base = MaybeUninit::uninit();
let mut error_base = MaybeUninit::uninit();
if (xfixes.XFixesQueryExtension)(display,
event_base.as_mut_ptr(),
error_base.as_mut_ptr(),
) == xlib::False {
panic!("Failed to query XFixes");
}
// Setup selection events
(xfixes.XFixesSelectSelectionInput)(
display,
root,
xlib::XA_PRIMARY,
xfixes::XFixesSetSelectionOwnerNotifyMask);
let root = unsafe { (xlib.XDefaultRootWindow)(display) };
let clipboard = unsafe { (xlib.XInternAtom)(
display, CString::new("CLIPBOARD").unwrap().as_ptr(), 0
) };
(xfixes.XFixesSelectSelectionInput)(
display,
root,
clipboard,
xfixes::XFixesSetSelectionOwnerNotifyMask);
let host = Self {
xlib,
xtest,
xinput2,
xfixes,
xfixes_event_base,
// Query XInput2
let xinput2 = xinput2::XInput2::open().unwrap();
if (xlib.XQueryExtension)(
display,
CString::new("XInputExtension").unwrap().as_ptr(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
) == xlib::False {
panic!("Failed to query XInputExtension");
};
// Setup selection events
self.select_selection_input(self.root, xlib::XA_PRIMARY, xfixes::XFixesSetSelectionOwnerNotifyMask);
self.select_selection_input(self.root, self.clipboard, xfixes::XFixesSetSelectionOwnerNotifyMask);
let host = Self {
xlib,
display,
io,
root,
clipboard,
fn next_event(&self) -> xlib::XEvent {
unsafe {
let mut event = MaybeUninit::uninit();
(self.xlib.XNextEvent)(self.display, event.as_mut_ptr());
event.assume_init()
fn map_button_event(event: xlib::XButtonEvent, state: bool) -> ButtonEvent {
ButtonEvent {
button: event.button,
state,
// xfixes
fn select_selection_input(&self, window: xlib::Window, atom: xlib::Atom, event_mask: u64) {
unsafe { (self.xfixes.XFixesSelectSelectionInput)(
self.display, window, atom, event_mask
) };
fn map_key_event(&self, event: xlib::XKeyEvent, state: bool) -> KeyEvent {
let key = unsafe {
(self.xlib.XKeycodeToKeysym)(self.display, event.keycode as u8, 0)
};
KeyEvent {
key,
state,
}
// xinput2
fn select_events(&self, window: xlib::Window, mask: &mut [xinput2::XIEventMask]) {
unsafe { (self.xinput2.XISelectEvents)(
self.display, window,
&mut mask[0] as *mut xinput2::XIEventMask, mask.len() as i32
) };
fn map_generic_event(&self, cookie: xlib::XGenericEventCookie) -> Option<HostEvent> {
// FIXME: Check XInput2 extension in cookie.extension
match cookie.evtype {
xinput2::XI_RawMotion => Some(HostEvent::Motion(self.map_raw_motion())),
_ => None,
}
fn recv_generic_event(&self, cookie: xlib::XGenericEventCookie) -> Option<HostEvent> {
// FIXME: Assert XInput2 extension in cookie.extension
assert_eq!(cookie.evtype, xinput2::XI_RawMotion);
fn map_raw_motion(&self) -> MotionEvent {
Some(HostEvent::Motion(MotionEvent { dx, dy }))
}
fn recv_button_event(&self, event: xlib::XButtonEvent, state: bool) -> Option<HostEvent> {
Some(HostEvent::Button(ButtonEvent {
button: event.button,
state,
}))
}
fn recv_key_event(&self, event: xlib::XKeyEvent, state: bool) -> Option<HostEvent> {
let key = unsafe { (self.xlib.XKeycodeToKeysym)(self.display, event.keycode as u8, 0) };
Some(HostEvent::Key(KeyEvent {
key,
state,
}))
MotionEvent { dx, dy }
let screen = &*(self.xlib.XDefaultScreenOfDisplay)(self.display);
assert!(screen.width > 0 && screen.height > 0);
(screen.width, screen.height)
(self.xlib.XCloseDisplay)(self.display);
(self.xlib.XQueryPointer)(self.display, self.root,
root.as_mut_ptr(), child.as_mut_ptr(),
root_x.as_mut_ptr(), root_y.as_mut_ptr(),
child_x.as_mut_ptr(), child_y.as_mut_ptr(),
mask.as_mut_ptr());
(self.xlib.XQueryPointer)(
self.display, self.root,
ptr::null_mut(), ptr::null_mut(),
root_x.as_mut_ptr(), root_y.as_mut_ptr(),
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut());
unsafe { (self.xlib.XGrabKeyboard)(
self.display, self.root, xlib::True,
xlib::GrabModeAsync, xlib::GrabModeAsync, xlib::CurrentTime
) };
unsafe {
(self.xlib.XGrabKeyboard)(
self.display, self.root, xlib::True,
xlib::GrabModeAsync, xlib::GrabModeAsync, xlib::CurrentTime);
}
fn recv_event(&self) -> Option<HostEvent> {
impl Stream for Host {
type Item = HostEvent;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
match self.io.poll_read_ready(cx, mio::Ready::readable()) {
Poll::Ready(result) => result.unwrap(),
Poll::Pending => return Poll::Pending,
};
// Standard events
match event_type {
xlib::GenericEvent => return self.recv_generic_event(From::from(event)),
xlib::ButtonPress => return self.recv_button_event(From::from(event), true),
xlib::ButtonRelease => return self.recv_button_event(From::from(event), false),
xlib::KeyPress => return self.recv_key_event(From::from(event), true),
xlib::KeyRelease => return self.recv_key_event(From::from(event), false),
xlib::MappingNotify => return None,
_ => (),
let event = unsafe {
let mut event = MaybeUninit::uninit();
(self.xlib.XNextEvent)(self.display, event.as_mut_ptr());
event.assume_init()
// XFixes selection events
match event_type - self.xfixes_event_base {
xfixes::XFixesSelectionNotify => return self.recv_selection_event(From::from(event)),
_ => (),
let host_event = match event.get_type() {
// Standard events
xlib::ButtonPress => Some(HostEvent::Button(Self::map_button_event(event.into(), true))),
xlib::ButtonRelease => Some(HostEvent::Button(Self::map_button_event(event.into(), false))),
xlib::KeyPress => Some(HostEvent::Key(self.map_key_event(event.into(), true))),
xlib::KeyRelease => Some(HostEvent::Key(self.map_key_event(event.into(), false))),
xlib::MappingNotify => None,
xlib::GenericEvent => self.map_generic_event(event.into()),
// XFixes selection events
event_type if event_type - self.xfixes_event_base == xfixes::XFixesSelectionNotify =>
self.map_selection_event(event.into()),
event_type => {
warn!("Unexpected X11 event: {}", event_type);
None
}
warn!("Unexpected X11 event: {}", event_type);
None
fn poll_ready(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
match self.io.poll_write_ready(cx) {
Poll::Ready(result) => Poll::Ready(result.map(|_| ())),
Poll::Pending => Poll::Pending,
}
event => warn!("Unexpected host event: {:?}", event),
HostEvent::Selection(_event) => todo!(),
}
Ok(())
}
fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
match self.io.poll_write_ready(cx) {
Poll::Ready(result) => Poll::Ready(result.map(|_| unsafe {
(self.xlib.XFlush)(self.display);
})),
Poll::Pending => Poll::Pending,
// /*
// * FIXME(Future):
// * Method delegation: https://github.com/rust-lang/rfcs/pull/1406
// */
// impl Evented for X11Interface {
// fn register(&self, selector: &mut Selector, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
// selector.register(self.connection_number(), token, interest, opts)
// }
struct Connection {
fd: RawFd,
}
// fn reregister(&self, selector: &mut Selector, token: Token, interest: EventSet, opts: PollOpt) -> io::Result<()> {
// selector.reregister(self.connection_number(), token, interest, opts)
// }
impl mio::Evented for Connection {
fn register(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready, opts: mio::PollOpt)
-> io::Result<()>
{
mio::unix::EventedFd(&self.fd).register(poll, token, interest, opts)
}
// fn deregister(&self, selector: &mut Selector) -> io::Result<()> {
// selector.deregister(self.connection_number())
// }
// }
fn reregister(&self, poll: &mio::Poll, token: mio::Token, interest: mio::Ready, opts: mio::PollOpt)
-> io::Result<()>
{
mio::unix::EventedFd(&self.fd).reregister(poll, token, interest, opts)
}
impl Drop for X11Interface {
fn drop(&mut self) {
unsafe { (self.xlib.XCloseDisplay)(self.display) };
fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
mio::unix::EventedFd(&self.fd).deregister(poll)