mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 12:38:02 +00:00
Improve key handling on x11, sharing wayland implementation (#8094)
Makes keyboard shortcuts work on x11. Release Notes: - N/A
This commit is contained in:
parent
c97ecc7326
commit
cd640a87a9
5 changed files with 53 additions and 45 deletions
|
@ -3,6 +3,7 @@ mod client_dispatcher;
|
|||
mod dispatcher;
|
||||
mod platform;
|
||||
mod text_system;
|
||||
mod util;
|
||||
mod wayland;
|
||||
mod x11;
|
||||
|
||||
|
|
28
crates/gpui/src/platform/linux/util.rs
Normal file
28
crates/gpui/src/platform/linux/util.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use xkbcommon::xkb::{self, Keycode, Keysym, State};
|
||||
|
||||
use crate::{Keystroke, Modifiers};
|
||||
|
||||
impl Keystroke {
|
||||
pub(super) fn from_xkb(state: &State, modifiers: Modifiers, keycode: Keycode) -> Self {
|
||||
let key_utf32 = state.key_get_utf32(keycode);
|
||||
let key_utf8 = state.key_get_utf8(keycode);
|
||||
let key_sym = state.key_get_one_sym(keycode);
|
||||
|
||||
let key = match key_sym {
|
||||
Keysym::Return => "enter".to_owned(),
|
||||
Keysym::Prior => "pageup".to_owned(),
|
||||
Keysym::Next => "pagedown".to_owned(),
|
||||
_ => xkb::keysym_get_name(key_sym).to_lowercase(),
|
||||
};
|
||||
|
||||
// Ignore control characters (and DEL) for the purposes of ime_key,
|
||||
// but if key_utf32 is 0 then assume it isn't one
|
||||
let ime_key = (key_utf32 == 0 || (key_utf32 >= 32 && key_utf32 != 127)).then_some(key_utf8);
|
||||
|
||||
Keystroke {
|
||||
modifiers,
|
||||
key,
|
||||
ime_key,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,8 +24,7 @@ use wayland_protocols::xdg::decoration::zv1::client::{
|
|||
};
|
||||
use wayland_protocols::xdg::shell::client::{xdg_surface, xdg_toplevel, xdg_wm_base};
|
||||
use xkbcommon::xkb::ffi::XKB_KEYMAP_FORMAT_TEXT_V1;
|
||||
use xkbcommon::xkb::{self, Keysym};
|
||||
use xkbcommon::xkb::{Keycode, KEYMAP_COMPILE_NO_FLAGS};
|
||||
use xkbcommon::xkb::{self, Keycode, KEYMAP_COMPILE_NO_FLAGS};
|
||||
|
||||
use crate::platform::linux::client::Client;
|
||||
use crate::platform::linux::wayland::window::{WaylandDecorationState, WaylandWindow};
|
||||
|
@ -453,41 +452,27 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientState {
|
|||
} => {
|
||||
let keymap_state = state.keymap_state.as_ref().unwrap();
|
||||
let keycode = Keycode::from(key + MIN_KEYCODE);
|
||||
let key_utf32 = keymap_state.key_get_utf32(keycode);
|
||||
let key_utf8 = keymap_state.key_get_utf8(keycode);
|
||||
let key_sym = keymap_state.key_get_one_sym(keycode);
|
||||
let key = match key_sym {
|
||||
Keysym::Return => "enter".to_owned(),
|
||||
Keysym::Prior => "pageup".to_owned(),
|
||||
Keysym::Next => "pagedown".to_owned(),
|
||||
_ => xkb::keysym_get_name(key_sym).to_lowercase(),
|
||||
};
|
||||
|
||||
// Ignore control characters (and DEL) for the purposes of ime_key,
|
||||
// but if key_utf32 is 0 then assume it isn't one
|
||||
let ime_key =
|
||||
(key_utf32 == 0 || (key_utf32 >= 32 && key_utf32 != 127)).then_some(key_utf8);
|
||||
|
||||
let focused_window = &state.keyboard_focused_window;
|
||||
if let Some(focused_window) = focused_window {
|
||||
match key_state {
|
||||
wl_keyboard::KeyState::Pressed => {
|
||||
focused_window.handle_input(PlatformInput::KeyDown(KeyDownEvent {
|
||||
keystroke: Keystroke {
|
||||
modifiers: state.modifiers,
|
||||
key,
|
||||
ime_key,
|
||||
},
|
||||
keystroke: Keystroke::from_xkb(
|
||||
keymap_state,
|
||||
state.modifiers,
|
||||
keycode,
|
||||
),
|
||||
is_held: false, // todo!(linux)
|
||||
}));
|
||||
}
|
||||
wl_keyboard::KeyState::Released => {
|
||||
focused_window.handle_input(PlatformInput::KeyUp(KeyUpEvent {
|
||||
keystroke: Keystroke {
|
||||
modifiers: state.modifiers,
|
||||
key,
|
||||
ime_key,
|
||||
},
|
||||
keystroke: Keystroke::from_xkb(
|
||||
keymap_state,
|
||||
state.modifiers,
|
||||
keycode,
|
||||
),
|
||||
}));
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -118,39 +118,31 @@ impl Client for X11Client {
|
|||
xcb::Event::X(x::Event::KeyPress(ev)) => {
|
||||
let window = self.get_window(ev.event());
|
||||
let modifiers = super::modifiers_from_state(ev.state());
|
||||
let key = {
|
||||
let keystroke = {
|
||||
let code = ev.detail().into();
|
||||
let mut state = self.state.lock();
|
||||
let key = state.xkb.key_get_utf8(code);
|
||||
let keystroke = crate::Keystroke::from_xkb(&state.xkb, modifiers, code);
|
||||
state.xkb.update_key(code, xkb::KeyDirection::Down);
|
||||
key
|
||||
keystroke
|
||||
};
|
||||
|
||||
window.handle_input(PlatformInput::KeyDown(crate::KeyDownEvent {
|
||||
keystroke: crate::Keystroke {
|
||||
modifiers,
|
||||
key,
|
||||
ime_key: None,
|
||||
},
|
||||
keystroke,
|
||||
is_held: false,
|
||||
}));
|
||||
}
|
||||
xcb::Event::X(x::Event::KeyRelease(ev)) => {
|
||||
let window = self.get_window(ev.event());
|
||||
let modifiers = super::modifiers_from_state(ev.state());
|
||||
let key = {
|
||||
let keystroke = {
|
||||
let code = ev.detail().into();
|
||||
let mut state = self.state.lock();
|
||||
let key = state.xkb.key_get_utf8(code);
|
||||
let keystroke = crate::Keystroke::from_xkb(&state.xkb, modifiers, code);
|
||||
state.xkb.update_key(code, xkb::KeyDirection::Up);
|
||||
key
|
||||
keystroke
|
||||
};
|
||||
window.handle_input(PlatformInput::KeyUp(crate::KeyUpEvent {
|
||||
keystroke: crate::Keystroke {
|
||||
modifiers,
|
||||
key,
|
||||
ime_key: None,
|
||||
},
|
||||
}));
|
||||
|
||||
window.handle_input(PlatformInput::KeyUp(crate::KeyUpEvent { keystroke }));
|
||||
}
|
||||
xcb::Event::X(x::Event::ButtonPress(ev)) => {
|
||||
let window = self.get_window(ev.event());
|
||||
|
|
|
@ -338,7 +338,9 @@ impl X11WindowState {
|
|||
if let PlatformInput::KeyDown(event) = input {
|
||||
let mut inner = self.inner.lock();
|
||||
if let Some(ref mut input_handler) = inner.input_handler {
|
||||
input_handler.replace_text_in_range(None, &event.keystroke.key);
|
||||
if let Some(ime_key) = &event.keystroke.ime_key {
|
||||
input_handler.replace_text_in_range(None, ime_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue