Implement keycode translation for windows (#54)

closes #48 
closes #16
This commit is contained in:
Ferdinand Schober
2023-12-18 18:08:10 +01:00
committed by GitHub
parent 6766886377
commit 8de6c9bb87
14 changed files with 828 additions and 42 deletions

View File

@@ -1,5 +1,9 @@
use crate::{
client::{ClientEvent, ClientHandle},
consumer::EventConsumer,
event::Event,
};
use async_trait::async_trait;
use crate::{consumer::EventConsumer, event::Event, client::{ClientHandle, ClientEvent}};
pub struct DummyConsumer;

View File

@@ -209,7 +209,7 @@ impl EventConsumer for MacOSConsumer {
}
KeyboardEvent::Modifiers { .. } => {}
},
_ => ()
_ => (),
}
}

View File

@@ -1,8 +1,7 @@
use crate::{
consumer::EventConsumer,
event::{KeyboardEvent, PointerEvent},
};
use anyhow::Result;
use crate::{consumer::EventConsumer, event::{KeyboardEvent, PointerEvent}, scancode};
use async_trait::async_trait;
use winapi::um::winuser::{KEYEVENTF_EXTENDEDKEY, SendInput};
use winapi::{
self,
um::winuser::{
@@ -21,8 +20,8 @@ use crate::{
pub struct WindowsConsumer {}
impl WindowsConsumer {
pub fn new() -> Self {
Self {}
pub fn new() -> Result<Self> {
Ok(Self {})
}
}
@@ -76,7 +75,7 @@ fn send_mouse_input(mi: MOUSEINPUT) {
u: std::mem::transmute(mi),
};
winapi::um::winuser::SendInput(
SendInput(
1 as u32,
&mut input as LPINPUT,
std::mem::size_of::<INPUT>() as i32,
@@ -141,10 +140,17 @@ fn scroll(axis: u8, value: f64) {
}
fn key_event(key: u32, state: u8) {
let scancode = match linux_keycode_to_windows_scancode(key) {
Some(code) => code,
None => return,
};
let extended = scancode > 0xff;
let scancode = scancode & 0xff;
let ki = KEYBDINPUT {
wVk: 0,
wScan: key as u16,
wScan: scancode,
dwFlags: KEYEVENTF_SCANCODE
| if extended { KEYEVENTF_EXTENDEDKEY } else { 0 }
| match state {
0 => KEYEVENTF_KEYUP,
1 => 0u32,
@@ -163,6 +169,26 @@ fn send_keyboard_input(ki: KEYBDINPUT) {
u: std::mem::zeroed(),
};
*input.u.ki_mut() = ki;
winapi::um::winuser::SendInput(1 as u32, &mut input, std::mem::size_of::<INPUT>() as i32);
SendInput(1 as u32, &mut input, std::mem::size_of::<INPUT>() as i32);
}
}
fn linux_keycode_to_windows_scancode(linux_keycode: u32) -> Option<u16> {
let linux_scancode = match scancode::Linux::try_from(linux_keycode) {
Ok(s) => s,
Err(_) => {
log::warn!("unknown keycode: {linux_keycode}");
return None;
},
};
log::trace!("linux code: {linux_scancode:?}");
let windows_scancode = match scancode::Windows::try_from(linux_scancode) {
Ok(s) => s,
Err(_) => {
log::warn!("failed to translate linux code into windows scancode: {linux_scancode:?}");
return None;
}
};
log::trace!("windows code: {windows_scancode:?}");
Some(windows_scancode as u16)
}

View File

@@ -100,7 +100,7 @@ impl State {
panic!("no keymap");
}
let vinput = VirtualInput{ pointer, keyboard };
let vinput = VirtualInput { pointer, keyboard };
self.input_for_client.insert(client, vinput);
}
@@ -191,15 +191,16 @@ impl VirtualInput {
Event::Keyboard(e) => match e {
KeyboardEvent::Key { time, key, state } => {
self.keyboard.key(time, key, state as u32);
},
}
KeyboardEvent::Modifiers {
mods_depressed,
mods_latched,
mods_locked,
group,
} => {
self.keyboard.modifiers(mods_depressed, mods_latched, mods_locked, group);
},
self.keyboard
.modifiers(mods_depressed, mods_latched, mods_locked, group);
}
},
_ => {}
}

View File

@@ -1,9 +1,18 @@
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use std::ptr;
use x11::{xlib::{self, XCloseDisplay}, xtest};
use x11::{
xlib::{self, XCloseDisplay},
xtest,
};
use crate::{client::ClientHandle, consumer::EventConsumer, event::{Event, PointerEvent, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK, KeyboardEvent}};
use crate::{
client::ClientHandle,
consumer::EventConsumer,
event::{
Event, KeyboardEvent, PointerEvent, BTN_BACK, BTN_FORWARD, BTN_LEFT, BTN_MIDDLE, BTN_RIGHT,
},
};
pub struct X11Consumer {
display: *mut xlib::Display,
@@ -50,8 +59,20 @@ impl X11Consumer {
fn emulate_scroll(&self, axis: u8, value: f64) {
let direction = match axis {
1 => if value < 0.0 { Self::SCROLL_LEFT } else { Self::SCROLL_RIGHT },
_ => if value < 0.0 { Self::SCROLL_UP } else { Self::SCROLL_DOWN },
1 => {
if value < 0.0 {
Self::SCROLL_LEFT
} else {
Self::SCROLL_RIGHT
}
}
_ => {
if value < 0.0 {
Self::SCROLL_UP
} else {
Self::SCROLL_DOWN
}
}
};
unsafe {
@@ -89,15 +110,27 @@ impl EventConsumer for X11Consumer {
} => {
self.relative_motion(relative_x as i32, relative_y as i32);
}
PointerEvent::Button { time: _, button, state } => {
PointerEvent::Button {
time: _,
button,
state,
} => {
self.emulate_mouse_button(button, state);
}
PointerEvent::Axis { time: _, axis, value } => {
PointerEvent::Axis {
time: _,
axis,
value,
} => {
self.emulate_scroll(axis, value);
}
PointerEvent::Frame {} => {}
},
Event::Keyboard(KeyboardEvent::Key { time: _, key, state }) => {
Event::Keyboard(KeyboardEvent::Key {
time: _,
key,
state,
}) => {
self.emulate_key(key, state);
}
_ => {}

View File

@@ -8,7 +8,14 @@ use ashpd::{
};
use async_trait::async_trait;
use crate::{consumer::EventConsumer, event::{Event::{Keyboard, Pointer}, PointerEvent, KeyboardEvent}, client::ClientEvent};
use crate::{
client::ClientEvent,
consumer::EventConsumer,
event::{
Event::{Keyboard, Pointer},
KeyboardEvent, PointerEvent,
},
};
pub struct DesktopPortalConsumer<'a> {
proxy: RemoteDesktop<'a>,

View File

@@ -1,6 +1,6 @@
use std::io;
use std::pin::Pin;
use std::task::{Poll, Context};
use std::task::{Context, Poll};
use futures_core::Stream;
@@ -32,10 +32,7 @@ impl EventProducer for DummyProducer {
impl Stream for DummyProducer {
type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(
self: Pin<&mut Self>,
_cx: &mut Context<'_>,
) -> Poll<Option<Self::Item>> {
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Poll::Pending
}
}

View File

@@ -1,7 +1,7 @@
use anyhow::{anyhow, Result};
use core::task::{Context, Poll};
use futures::Stream;
use std::io::Result;
use std::pin::Pin;
use std::{io, pin::Pin};
use crate::{
client::{ClientEvent, ClientHandle},
@@ -18,13 +18,13 @@ impl EventProducer for WindowsProducer {
}
impl WindowsProducer {
pub(crate) fn new() -> Self {
Self {}
pub(crate) fn new() -> Result<Self> {
Err(anyhow!("not implemented"))
}
}
impl Stream for WindowsProducer {
type Item = Result<(ClientHandle, Event)>;
type Item = io::Result<(ClientHandle, Event)>;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
Poll::Pending
}