Workaround FocusProxy

pull/39/head
Takashi Kokubun 2 years ago
parent bcc4598069
commit 387c29d355
No known key found for this signature in database
GPG Key ID: 6FFC433B12EE23DD

@ -0,0 +1 @@
fn_call_width = 80

@ -45,10 +45,24 @@ impl X11Client {
res_name: std::ptr::null_mut(),
res_class: std::ptr::null_mut(),
};
let mut wm_class = String::new();
loop {
unsafe {
if x11::xlib::XGetClassHint(display, focused_window, &mut x_class_hint) == 1 {
break;
if !x_class_hint.res_name.is_null() {
x11::xlib::XFree(x_class_hint.res_name as *mut std::ffi::c_void);
}
if !x_class_hint.res_class.is_null() {
// Note: into_string() seems to free `x_class_hint.res_class`. So XFree isn't needed.
wm_class = std::ffi::CString::from_raw(x_class_hint.res_class as *mut i8)
.into_string()
.unwrap();
// Workaround: https://github.com/JetBrains/jdk8u_jdk/blob/master/src/solaris/classes/sun/awt/X11/XFocusProxyWindow.java#L35
if &wm_class != "FocusProxy" {
break;
}
}
}
}
@ -82,27 +96,11 @@ impl X11Client {
focused_window = parent;
}
if !x_class_hint.res_name.is_null() {
unsafe {
x11::xlib::XFree(x_class_hint.res_name as *mut std::ffi::c_void);
}
}
if !x_class_hint.res_class.is_null() {
let wm_class = unsafe {
// Note: This seems to free `x_class_hint.res_class`. So XFree on it would double-free it.
std::ffi::CString::from_raw(x_class_hint.res_class as *mut i8)
.into_string()
.unwrap()
};
if &self.last_wm_class != &wm_class {
self.last_wm_class = wm_class.clone();
println!("wm_class: {}", &wm_class);
}
Some(wm_class)
} else {
None
if &self.last_wm_class != &wm_class {
self.last_wm_class = wm_class.clone();
println!("wm_class: {}", &wm_class);
}
Some(wm_class)
}
fn display(&mut self) -> *mut x11::xlib::Display {

@ -15,7 +15,7 @@ pub struct KeyPress {
pub windows: bool,
}
pub enum Modifier {
enum Modifier {
Shift,
Control,
Alt,

@ -1,6 +1,6 @@
use crate::client::x11_client::X11Client;
use crate::config::action::Action;
use crate::config::key_press::{KeyPress, Modifier};
use crate::config::key_press::KeyPress;
use crate::config::wm_class::WMClass;
use crate::Config;
use evdev::uinput::VirtualDevice;
@ -14,10 +14,10 @@ pub struct EventHandler {
x11_client: X11Client,
override_remap: Option<HashMap<KeyPress, Vec<Action>>>,
wm_class_cache: Option<String>,
shift: bool,
control: bool,
alt: bool,
windows: bool,
shift: PressState,
control: PressState,
alt: PressState,
windows: PressState,
}
impl EventHandler {
@ -27,10 +27,10 @@ impl EventHandler {
x11_client: X11Client::new(),
override_remap: None,
wm_class_cache: None,
shift: false,
control: false,
alt: false,
windows: false,
shift: PressState::new(false),
control: PressState::new(false),
alt: PressState::new(false),
windows: PressState::new(false),
}
}
@ -38,7 +38,7 @@ impl EventHandler {
pub fn on_event(&mut self, event: InputEvent, config: &Config) -> Result<(), Box<dyn Error>> {
self.wm_class_cache = None; // expire cache
let mut key = Key::new(event.code());
// println!("=> {}: {:?}", event.value(), &key);
println!("=> {}: {:?}", event.value(), &key);
// Apply modmap
for modmap in &config.modmap {
@ -54,8 +54,8 @@ impl EventHandler {
}
// Apply keymap
if let Some(modifier) = MODIFIER_KEYS.get(&key.code()) {
self.update_modifier(modifier, event.value());
if MODIFIER_KEYS.contains(&key.code()) {
self.update_modifier(key.code(), event.value());
} else if let Some(actions) = self.find_keymap(config, &key, event.value()) {
for action in &actions {
self.dispatch_action(action)?;
@ -68,7 +68,9 @@ impl EventHandler {
}
pub fn send_event(&mut self, event: InputEvent) -> std::io::Result<()> {
// if event.event_type() == EventType::KEY { println!("{}: {:?}", event.value(), Key::new(event.code())); }
if event.event_type() == EventType::KEY {
println!("{}: {:?}", event.value(), Key::new(event.code()));
}
self.device.emit(&[event])
}
@ -84,10 +86,10 @@ impl EventHandler {
let key_press = KeyPress {
key: key.clone(),
shift: self.shift,
control: self.control,
alt: self.alt,
windows: self.windows,
shift: self.shift.left || self.shift.right,
control: self.control.left || self.control.right,
alt: self.alt.left || self.control.right,
windows: self.windows.left || self.windows.right,
};
if let Some(override_remap) = &self.override_remap {
let override_remap = override_remap.clone();
@ -111,27 +113,49 @@ impl EventHandler {
fn dispatch_action(&mut self, action: &Action) -> Result<(), Box<dyn Error>> {
match action {
Action::KeyPress(key_press) => {
self.send_modifier(self.shift, key_press.shift, &SHIFT_KEY)?;
self.send_modifier(self.control, key_press.control, &CONTROL_KEY)?;
self.send_modifier(self.alt, key_press.alt, &ALT_KEY)?;
self.send_modifier(self.windows, key_press.windows, &WINDOWS_KEY)?;
self.send_key(&key_press.key, PRESS)?;
self.send_key(&key_press.key, RELEASE)?;
self.send_modifier(key_press.windows, self.windows, &WINDOWS_KEY)?;
self.send_modifier(key_press.alt, self.alt, &ALT_KEY)?;
self.send_modifier(key_press.control, self.control, &CONTROL_KEY)?;
self.send_modifier(key_press.shift, self.shift, &SHIFT_KEY)?;
Action::KeyPress(press) => {
self.send_modifier(
&self.shift.clone(),
&PressState::new(press.shift),
&SHIFT_KEYS,
)?;
self.send_modifier(
&self.control.clone(),
&PressState::new(press.control),
&CTRL_KEYS,
)?;
self.send_modifier(&self.alt.clone(), &PressState::new(press.alt), &ALT_KEYS)?;
self.send_modifier(
&self.windows.clone(),
&PressState::new(press.windows),
&WIN_KEYS,
)?;
self.send_key(&press.key, PRESS)?;
self.send_key(&press.key, RELEASE)?;
self.send_modifier(
&PressState::new(press.windows),
&self.windows.clone(),
&WIN_KEYS,
)?;
self.send_modifier(&PressState::new(press.alt), &self.alt.clone(), &ALT_KEYS)?;
self.send_modifier(
&PressState::new(press.control),
&self.control.clone(),
&CTRL_KEYS,
)?;
self.send_modifier(
&PressState::new(press.shift),
&self.shift.clone(),
&SHIFT_KEYS,
)?;
}
Action::Remap(remap) => {
let mut override_remap: HashMap<KeyPress, Vec<Action>> = HashMap::new();
for (key_press, actions) in remap.iter() {
override_remap.insert(
key_press.clone(),
actions.iter().map(|a| a.clone()).collect(),
);
override_remap
.insert(key_press.clone(), actions.iter().map(|a| a.clone()).collect());
}
self.override_remap = Some(override_remap)
}
@ -139,12 +163,26 @@ impl EventHandler {
Ok(())
}
fn send_modifier(&mut self, from: bool, to: bool, key: &Key) -> Result<(), Box<dyn Error>> {
if !from && to {
self.send_key(key, PRESS)?;
fn send_modifier(
&mut self,
from: &PressState,
to: &PressState,
keys: &[Key; 2],
) -> Result<(), Box<dyn Error>> {
let left_key = &keys[0];
if !from.left && to.left {
self.send_key(left_key, PRESS)?;
}
if from && !to {
self.send_key(key, RELEASE)?;
if from.left && !to.left {
self.send_key(left_key, RELEASE)?;
}
let right_key = &keys[1];
if !from.right && to.right {
self.send_key(right_key, PRESS)?;
}
if from.right && !to.right {
self.send_key(right_key, RELEASE)?;
}
Ok(())
}
@ -169,12 +207,40 @@ impl EventHandler {
false
}
fn update_modifier(&mut self, modifier: &Modifier, value: i32) {
match modifier {
Modifier::Shift => self.shift = is_pressed(value),
Modifier::Control => self.control = is_pressed(value),
Modifier::Alt => self.alt = is_pressed(value),
Modifier::Windows => self.windows = is_pressed(value),
fn update_modifier(&mut self, code: u16, value: i32) {
if code == Key::KEY_LEFTSHIFT.code() {
self.shift.left = is_pressed(value)
} else if code == Key::KEY_RIGHTSHIFT.code() {
self.shift.right = is_pressed(value)
} else if code == Key::KEY_LEFTCTRL.code() {
self.control.left = is_pressed(value)
} else if code == Key::KEY_RIGHTCTRL.code() {
self.control.right = is_pressed(value)
} else if code == Key::KEY_LEFTALT.code() {
self.alt.left = is_pressed(value)
} else if code == Key::KEY_RIGHTALT.code() {
self.alt.right = is_pressed(value)
} else if code == Key::KEY_LEFTMETA.code() {
self.windows.left = is_pressed(value)
} else if code == Key::KEY_RIGHTMETA.code() {
self.windows.right = is_pressed(value)
} else {
panic!("unexpected key {:?} at update_modifier", Key::new(code));
}
}
}
#[derive(Clone)]
struct PressState {
left: bool,
right: bool,
}
impl PressState {
fn new(pressed: bool) -> PressState {
PressState {
left: pressed,
right: pressed,
}
}
}
@ -189,23 +255,35 @@ static PRESS: i32 = 1;
static REPEAT: i32 = 2;
lazy_static! {
static ref MODIFIER_KEYS: HashMap<u16, Modifier> = vec![
static ref MODIFIER_KEYS: [u16; 8] = [
// Shift
(Key::KEY_LEFTSHIFT.code(), Modifier::Shift),
(Key::KEY_RIGHTSHIFT.code(), Modifier::Shift),
Key::KEY_LEFTSHIFT.code(),
Key::KEY_RIGHTSHIFT.code(),
// Control
(Key::KEY_LEFTCTRL.code(), Modifier::Control),
(Key::KEY_RIGHTCTRL.code(), Modifier::Control),
Key::KEY_LEFTCTRL.code(),
Key::KEY_RIGHTCTRL.code(),
// Alt
(Key::KEY_LEFTALT.code(), Modifier::Alt),
(Key::KEY_RIGHTALT.code(), Modifier::Alt),
Key::KEY_LEFTALT.code(),
Key::KEY_RIGHTALT.code(),
// Windows
(Key::KEY_LEFTMETA.code(), Modifier::Windows),
(Key::KEY_RIGHTMETA.code(), Modifier::Windows),
].into_iter().collect();
static ref SHIFT_KEY: Key = Key::new(Key::KEY_RIGHTSHIFT.code());
static ref CONTROL_KEY: Key = Key::new(Key::KEY_RIGHTCTRL.code());
static ref ALT_KEY: Key = Key::new(Key::KEY_RIGHTALT.code());
static ref WINDOWS_KEY: Key = Key::new(Key::KEY_RIGHTMETA.code());
Key::KEY_LEFTMETA.code(),
Key::KEY_RIGHTMETA.code(),
];
static ref SHIFT_KEYS: [Key; 2] = [
Key::new(Key::KEY_LEFTSHIFT.code()),
Key::new(Key::KEY_RIGHTSHIFT.code()),
];
static ref CTRL_KEYS: [Key; 2] = [
Key::new(Key::KEY_LEFTCTRL.code()),
Key::new(Key::KEY_RIGHTCTRL.code()),
];
static ref ALT_KEYS: [Key; 2] = [
Key::new(Key::KEY_LEFTALT.code()),
Key::new(Key::KEY_RIGHTALT.code()),
];
static ref WIN_KEYS: [Key; 2] = [
Key::new(Key::KEY_LEFTMETA.code()),
Key::new(Key::KEY_RIGHTMETA.code()),
];
}

Loading…
Cancel
Save