mirror of
https://github.com/zed-industries/zed.git
synced 2026-08-21 15:04:51 +00:00
gpui_linux: Handle XKB context initialization failure (#62868)
Release Notes: - Added check for XKB context initialization failure
This commit is contained in:
parent
99f4c21c03
commit
c43e2d9734
3 changed files with 46 additions and 5 deletions
|
|
@ -13,6 +13,8 @@ use std::{
|
|||
time::Duration,
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||
use anyhow::ensure;
|
||||
use anyhow::{Context as _, anyhow};
|
||||
use calloop::{LoopSignal, channel::Sender};
|
||||
use futures::channel::oneshot;
|
||||
|
|
@ -832,6 +834,20 @@ pub(super) fn is_within_click_distance(a: Point<Pixels>, b: Point<Pixels>) -> bo
|
|||
diff.x.abs() <= DOUBLE_CLICK_DISTANCE && diff.y.abs() <= DOUBLE_CLICK_DISTANCE
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||
pub(super) fn new_xkb_context() -> anyhow::Result<xkb::Context> {
|
||||
validate_xkb_context(xkb::Context::new(xkb::CONTEXT_NO_FLAGS))
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||
fn validate_xkb_context(context: xkb::Context) -> anyhow::Result<xkb::Context> {
|
||||
ensure!(
|
||||
!context.get_raw_ptr().is_null(),
|
||||
"libxkbcommon failed to create an XKB context"
|
||||
);
|
||||
Ok(context)
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||
pub(super) fn get_xkb_compose_state(cx: &xkb::Context) -> Option<xkb::compose::State> {
|
||||
let mut locales = Vec::default();
|
||||
|
|
@ -1244,6 +1260,23 @@ mod tests {
|
|||
use super::*;
|
||||
use gpui::{Point, px};
|
||||
|
||||
#[cfg(any(feature = "wayland", feature = "x11"))]
|
||||
#[test]
|
||||
fn rejects_null_xkb_context() {
|
||||
let context = unsafe {
|
||||
// libxkbcommon permits unref on null, matching the value returned by Context::new on failure.
|
||||
xkb::Context::from_raw_ptr(std::ptr::null_mut())
|
||||
};
|
||||
let error = validate_xkb_context(context)
|
||||
.err()
|
||||
.expect("null XKB context should be rejected");
|
||||
|
||||
assert_eq!(
|
||||
error.to_string(),
|
||||
"libxkbcommon failed to create an XKB context"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_within_click_distance() {
|
||||
let zero = Point::new(px(0.0), px(0.0));
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ use crate::linux::{
|
|||
DOUBLE_CLICK_INTERVAL, LinuxClient, LinuxCommon, LinuxKeyboardLayout, PIPE_READ_TIMEOUT,
|
||||
SCROLL_LINES, capslock_from_xkb, cursor_style_to_icon_names, get_xkb_compose_state,
|
||||
is_within_click_distance, keystroke_from_xkb, keystroke_underlying_dead_key,
|
||||
modifiers_from_xkb, open_uri_internal, read_fd_with_timeout, reveal_path_internal,
|
||||
modifiers_from_xkb, new_xkb_context, open_uri_internal, read_fd_with_timeout,
|
||||
reveal_path_internal,
|
||||
wayland::{
|
||||
clipboard::{Clipboard, DataOffer, FILE_LIST_MIME_TYPE, TEXT_MIME_TYPES},
|
||||
cursor::Cursor,
|
||||
|
|
@ -1708,7 +1709,13 @@ impl Dispatch<wl_keyboard::WlKeyboard, ()> for WaylandClientStatePtr {
|
|||
log::error!("Received keymap format {:?}, expected XkbV1", format);
|
||||
return;
|
||||
}
|
||||
let xkb_context = xkb::Context::new(xkb::CONTEXT_NO_FLAGS);
|
||||
let xkb_context = match new_xkb_context() {
|
||||
Ok(context) => context,
|
||||
Err(error) => {
|
||||
log::error!("Failed to process Wayland keymap: {error:#}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
let keymap = unsafe {
|
||||
xkb::Keymap::new_from_fd(
|
||||
&xkb_context,
|
||||
|
|
|
|||
|
|
@ -51,7 +51,8 @@ use super::{
|
|||
use crate::linux::{
|
||||
DEFAULT_CURSOR_ICON_NAME, LinuxClient, capslock_from_xkb, cursor_style_to_icon_names,
|
||||
get_xkb_compose_state, is_within_click_distance, keystroke_from_xkb,
|
||||
keystroke_underlying_dead_key, log_cursor_icon_warning, modifiers_from_xkb, open_uri_internal,
|
||||
keystroke_underlying_dead_key, log_cursor_icon_warning, modifiers_from_xkb, new_xkb_context,
|
||||
open_uri_internal,
|
||||
platform::{DOUBLE_CLICK_INTERVAL, SCROLL_LINES},
|
||||
reveal_path_internal,
|
||||
xdg_desktop_portal::{Event as XDPEvent, XDPEventSource},
|
||||
|
|
@ -420,7 +421,7 @@ impl X11Client {
|
|||
),
|
||||
)?;
|
||||
|
||||
let xkb_context = xkbc::Context::new(xkbc::CONTEXT_NO_FLAGS);
|
||||
let xkb_context = new_xkb_context()?;
|
||||
let xkb_device_id = xkbc::x11::get_core_keyboard_device_id(&xcb_connection);
|
||||
let xkb_state = {
|
||||
let xkb_keymap = xkbc::x11::keymap_new_from_device(
|
||||
|
|
@ -2811,7 +2812,7 @@ mod tests {
|
|||
}
|
||||
|
||||
fn test_keymap_with_variant(layouts: &str, variant: &str) -> xkbc::Keymap {
|
||||
let context = xkbc::Context::new(xkbc::CONTEXT_NO_FLAGS);
|
||||
let context = new_xkb_context().expect("test XKB context should initialize");
|
||||
xkbc::Keymap::new_from_names(
|
||||
&context,
|
||||
"",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue