diff --git a/crates/gpui/src/platform/linux/x11/client.rs b/crates/gpui/src/platform/linux/x11/client.rs index 57295ee77261b7502b6e305c3e3ee47e7001ce74..bd3d3e3e6bbff3a887101ef8193717896cfd939b 100644 --- a/crates/gpui/src/platform/linux/x11/client.rs +++ b/crates/gpui/src/platform/linux/x11/client.rs @@ -5,7 +5,7 @@ use std::rc::{Rc, Weak}; use std::time::{Duration, Instant}; use calloop::generic::{FdWrapper, Generic}; -use calloop::{channel, EventLoop, LoopHandle, RegistrationToken}; +use calloop::{EventLoop, LoopHandle, RegistrationToken}; use collections::HashMap; use copypasta::x11_clipboard::{Clipboard, Primary, X11ClipboardContext}; @@ -282,11 +282,9 @@ impl X11Client { let xcb_connection = Rc::new(xcb_connection); - let (xim_tx, xim_rx) = channel::channel::(); - let ximc = X11rbClient::init(Rc::clone(&xcb_connection), x_root_index, None).ok(); let xim_handler = if ximc.is_some() { - Some(XimHandler::new(xim_tx)) + Some(XimHandler::new()) } else { None }; @@ -311,10 +309,12 @@ impl X11Client { client.handle_event(event); continue; } + let mut ximc = state.ximc.take().unwrap(); let mut xim_handler = state.xim_handler.take().unwrap(); let xim_connected = xim_handler.connected; drop(state); + let xim_filtered = match ximc.filter_event(&event, &mut xim_handler) { Ok(handled) => handled, Err(err) => { @@ -322,46 +322,34 @@ impl X11Client { false } }; + let xim_callback_event = xim_handler.last_callback_event.take(); + let mut state = client.0.borrow_mut(); state.ximc = Some(ximc); state.xim_handler = Some(xim_handler); drop(state); + + if let Some(event) = xim_callback_event { + client.handle_xim_callback_event(event); + } + if xim_filtered { continue; } + if xim_connected { client.xim_handle_event(event); } else { client.handle_event(event); } } + Ok(calloop::PostAction::Continue) } }, ) .expect("Failed to initialize x11 event source"); - handle - .insert_source(xim_rx, { - move |chan_event, _, client| match chan_event { - channel::Event::Msg(xim_event) => { - match xim_event { - XimCallbackEvent::XimXEvent(event) => { - client.handle_event(event); - } - XimCallbackEvent::XimCommitEvent(window, text) => { - client.xim_handle_commit(window, text); - } - XimCallbackEvent::XimPreeditEvent(window, text) => { - client.xim_handle_preedit(window, text); - } - }; - } - channel::Event::Closed => { - log::error!("XIM Event Sender dropped") - } - } - }) - .expect("Failed to initialize XIM event source"); + handle .insert_source(XDPEventSource::new(&common.background_executor), { move |event, _, client| match event { @@ -801,6 +789,20 @@ impl X11Client { Some(()) } + fn handle_xim_callback_event(&self, event: XimCallbackEvent) { + match event { + XimCallbackEvent::XimXEvent(event) => { + self.handle_event(event); + } + XimCallbackEvent::XimCommitEvent(window, text) => { + self.xim_handle_commit(window, text); + } + XimCallbackEvent::XimPreeditEvent(window, text) => { + self.xim_handle_preedit(window, text); + } + }; + } + fn xim_handle_event(&self, event: Event) -> Option<()> { match event { Event::KeyPress(event) | Event::KeyRelease(event) => { diff --git a/crates/gpui/src/platform/linux/x11/xim_handler.rs b/crates/gpui/src/platform/linux/x11/xim_handler.rs index 5900a190204cdb8763c6c6ab9baefbec2bb277f3..89b1ec3feb0e05fec9c3d9e4df32b43066aa04e8 100644 --- a/crates/gpui/src/platform/linux/x11/xim_handler.rs +++ b/crates/gpui/src/platform/linux/x11/xim_handler.rs @@ -1,7 +1,5 @@ use std::default::Default; -use calloop::channel; - use x11rb::protocol::{xproto, Event}; use xim::{AHashMap, AttributeName, Client, ClientError, ClientHandler, InputStyle}; @@ -14,19 +12,19 @@ pub enum XimCallbackEvent { pub struct XimHandler { pub im_id: u16, pub ic_id: u16, - pub xim_tx: channel::Sender, pub connected: bool, pub window: xproto::Window, + pub last_callback_event: Option, } impl XimHandler { - pub fn new(xim_tx: channel::Sender) -> Self { + pub fn new() -> Self { Self { im_id: Default::default(), ic_id: Default::default(), - xim_tx, connected: false, window: Default::default(), + last_callback_event: None, } } } @@ -80,12 +78,10 @@ impl> ClientHandler for XimHandler _input_context_id: u16, text: &str, ) -> Result<(), ClientError> { - self.xim_tx - .send(XimCallbackEvent::XimCommitEvent( - self.window, - String::from(text), - )) - .ok(); + self.last_callback_event = Some(XimCallbackEvent::XimCommitEvent( + self.window, + String::from(text), + )); Ok(()) } @@ -99,14 +95,11 @@ impl> ClientHandler for XimHandler ) -> Result<(), ClientError> { match xev.response_type { x11rb::protocol::xproto::KEY_PRESS_EVENT => { - self.xim_tx - .send(XimCallbackEvent::XimXEvent(Event::KeyPress(xev))) - .ok(); + self.last_callback_event = Some(XimCallbackEvent::XimXEvent(Event::KeyPress(xev))); } x11rb::protocol::xproto::KEY_RELEASE_EVENT => { - self.xim_tx - .send(XimCallbackEvent::XimXEvent(Event::KeyRelease(xev))) - .ok(); + self.last_callback_event = + Some(XimCallbackEvent::XimXEvent(Event::KeyRelease(xev))); } _ => {} } @@ -145,12 +138,10 @@ impl> ClientHandler for XimHandler // XIMPrimary, XIMHighlight, XIMSecondary, XIMTertiary are not specified, // but interchangeable as above // Currently there's no way to support these. - self.xim_tx - .send(XimCallbackEvent::XimPreeditEvent( - self.window, - String::from(preedit_string), - )) - .ok(); + self.last_callback_event = Some(XimCallbackEvent::XimPreeditEvent( + self.window, + String::from(preedit_string), + )); Ok(()) } }