X11: Fix handling of key remapping (#32780)
Closes #27384 I wrote #32771 before seeing #27384, and hoped that change would fix it. It didn't because `XkbSelectNotify` wants a mask of which types of `XkbMapNotify` to deliver, and otherwise won't send them. I noticed quite a few events are sent just for remapping a single keycode, so I updated the event loop to deduplicate these events (since the handler does not attempt to apply them and instead just re-queries keyboard info). Also adds a missing call of `keyboard_layout_change` on `XkbMapNotify` and `XkbNewKeyboardNotify`. Release Notes: - x11: Fixed handling of key remapping occurring while Zed is running (e.g. xmodmap)
This commit is contained in:
parent
3bed5b767f
commit
6150c26bd2
1 changed files with 53 additions and 6 deletions
|
@ -369,13 +369,21 @@ impl X11Client {
|
||||||
let events = xkb::EventType::STATE_NOTIFY
|
let events = xkb::EventType::STATE_NOTIFY
|
||||||
| xkb::EventType::MAP_NOTIFY
|
| xkb::EventType::MAP_NOTIFY
|
||||||
| xkb::EventType::NEW_KEYBOARD_NOTIFY;
|
| xkb::EventType::NEW_KEYBOARD_NOTIFY;
|
||||||
|
let map_notify_parts = xkb::MapPart::KEY_TYPES
|
||||||
|
| xkb::MapPart::KEY_SYMS
|
||||||
|
| xkb::MapPart::MODIFIER_MAP
|
||||||
|
| xkb::MapPart::EXPLICIT_COMPONENTS
|
||||||
|
| xkb::MapPart::KEY_ACTIONS
|
||||||
|
| xkb::MapPart::KEY_BEHAVIORS
|
||||||
|
| xkb::MapPart::VIRTUAL_MODS
|
||||||
|
| xkb::MapPart::VIRTUAL_MOD_MAP;
|
||||||
xcb_connection
|
xcb_connection
|
||||||
.xkb_select_events(
|
.xkb_select_events(
|
||||||
xkb::ID::USE_CORE_KBD.into(),
|
xkb::ID::USE_CORE_KBD.into(),
|
||||||
0u8.into(),
|
0u8.into(),
|
||||||
events,
|
events,
|
||||||
0u8.into(),
|
map_notify_parts,
|
||||||
0u8.into(),
|
map_notify_parts,
|
||||||
&xkb::SelectEventsAux::new(),
|
&xkb::SelectEventsAux::new(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -512,6 +520,10 @@ impl X11Client {
|
||||||
let mut last_key_release = None;
|
let mut last_key_release = None;
|
||||||
let mut last_key_press: Option<KeyPressEvent> = None;
|
let mut last_key_press: Option<KeyPressEvent> = None;
|
||||||
|
|
||||||
|
// event handlers for new keyboard / remapping refresh the state without using event
|
||||||
|
// details, this deduplicates them.
|
||||||
|
let mut last_keymap_change_event: Option<Event> = None;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match xcb_connection.poll_for_event() {
|
match xcb_connection.poll_for_event() {
|
||||||
Ok(Some(event)) => {
|
Ok(Some(event)) => {
|
||||||
|
@ -520,9 +532,29 @@ impl X11Client {
|
||||||
windows_to_refresh.insert(expose_event.window);
|
windows_to_refresh.insert(expose_event.window);
|
||||||
}
|
}
|
||||||
Event::KeyRelease(_) => {
|
Event::KeyRelease(_) => {
|
||||||
|
if let Some(last_keymap_change_event) =
|
||||||
|
last_keymap_change_event.take()
|
||||||
|
{
|
||||||
|
if let Some(last_key_release) = last_key_release.take() {
|
||||||
|
events.push(last_key_release);
|
||||||
|
}
|
||||||
|
last_key_press = None;
|
||||||
|
events.push(last_keymap_change_event);
|
||||||
|
}
|
||||||
|
|
||||||
last_key_release = Some(event);
|
last_key_release = Some(event);
|
||||||
}
|
}
|
||||||
Event::KeyPress(key_press) => {
|
Event::KeyPress(key_press) => {
|
||||||
|
if let Some(last_keymap_change_event) =
|
||||||
|
last_keymap_change_event.take()
|
||||||
|
{
|
||||||
|
if let Some(last_key_release) = last_key_release.take() {
|
||||||
|
events.push(last_key_release);
|
||||||
|
}
|
||||||
|
last_key_press = None;
|
||||||
|
events.push(last_keymap_change_event);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(last_press) = last_key_press.as_ref() {
|
if let Some(last_press) = last_key_press.as_ref() {
|
||||||
if last_press.detail == key_press.detail {
|
if last_press.detail == key_press.detail {
|
||||||
continue;
|
continue;
|
||||||
|
@ -543,6 +575,12 @@ impl X11Client {
|
||||||
events.push(Event::KeyPress(key_press));
|
events.push(Event::KeyPress(key_press));
|
||||||
last_key_press = Some(key_press);
|
last_key_press = Some(key_press);
|
||||||
}
|
}
|
||||||
|
Event::XkbNewKeyboardNotify(_) | Event::XkbMapNotify(_) => {
|
||||||
|
if let Some(release_event) = last_key_release.take() {
|
||||||
|
events.push(release_event);
|
||||||
|
}
|
||||||
|
last_keymap_change_event = Some(event);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if let Some(release_event) = last_key_release.take() {
|
if let Some(release_event) = last_key_release.take() {
|
||||||
events.push(release_event);
|
events.push(release_event);
|
||||||
|
@ -552,10 +590,6 @@ impl X11Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
// Add any remaining stored KeyRelease event
|
|
||||||
if let Some(release_event) = last_key_release.take() {
|
|
||||||
events.push(release_event);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -565,6 +599,13 @@ impl X11Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(release_event) = last_key_release.take() {
|
||||||
|
events.push(release_event);
|
||||||
|
}
|
||||||
|
if let Some(keymap_change_event) = last_keymap_change_event.take() {
|
||||||
|
events.push(keymap_change_event);
|
||||||
|
}
|
||||||
|
|
||||||
if events.is_empty() && windows_to_refresh.is_empty() {
|
if events.is_empty() && windows_to_refresh.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -890,6 +931,12 @@ impl X11Client {
|
||||||
locked_layout,
|
locked_layout,
|
||||||
};
|
};
|
||||||
state.xkb = xkb_state;
|
state.xkb = xkb_state;
|
||||||
|
if let Some(mut callback) = state.common.callbacks.keyboard_layout_change.take() {
|
||||||
|
drop(state);
|
||||||
|
callback();
|
||||||
|
state = self.0.borrow_mut();
|
||||||
|
state.common.callbacks.keyboard_layout_change = Some(callback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::XkbStateNotify(event) => {
|
Event::XkbStateNotify(event) => {
|
||||||
let mut state = self.0.borrow_mut();
|
let mut state = self.0.borrow_mut();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue