Compare commits
2 Commits
auto-comma
...
x11_debug
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
804b00c12a | ||
|
|
f724b2c171 |
@@ -463,6 +463,12 @@ codegen-units = 1
|
||||
[profile.release.package]
|
||||
zed = { codegen-units = 16 }
|
||||
|
||||
[profile.profiling]
|
||||
inherits = "release"
|
||||
debug = true
|
||||
lto = false
|
||||
codegen-units = 16
|
||||
|
||||
[workspace.lints.clippy]
|
||||
dbg_macro = "deny"
|
||||
todo = "deny"
|
||||
|
||||
@@ -62,16 +62,16 @@ impl ActivityIndicator {
|
||||
this.update(&mut cx, |this, cx| {
|
||||
this.statuses.retain(|s| s.name != name);
|
||||
this.statuses.push(LspStatus { name, status });
|
||||
cx.notify();
|
||||
cx.notify(); // commented back in
|
||||
})?;
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach();
|
||||
cx.observe(&project, |_, _, cx| cx.notify()).detach();
|
||||
cx.observe(&project, |_, _, cx| cx.notify()).detach(); // commented back in
|
||||
|
||||
if let Some(auto_updater) = auto_updater.as_ref() {
|
||||
cx.observe(auto_updater, |_, _, cx| cx.notify()).detach();
|
||||
cx.observe(auto_updater, |_, _, cx| cx.notify()).detach(); // commented back in
|
||||
}
|
||||
|
||||
Self {
|
||||
|
||||
@@ -735,7 +735,11 @@ impl AppContext {
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
{
|
||||
self.update_window(window, |_, cx| cx.draw()).unwrap();
|
||||
self.update_window(window, |_, cx| {
|
||||
println!("flush_effects. cx.draw()");
|
||||
cx.draw()
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if self.pending_effects.is_empty() {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::ffi::OsString;
|
||||
use std::ops::Deref;
|
||||
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};
|
||||
@@ -16,9 +16,9 @@ use x11rb::connection::{Connection, RequestConnection};
|
||||
use x11rb::cursor;
|
||||
use x11rb::errors::ConnectionError;
|
||||
use x11rb::protocol::randr::ConnectionExt as _;
|
||||
use x11rb::protocol::xinput::ConnectionExt;
|
||||
use x11rb::protocol::xinput::{ConnectionExt, KeyCode};
|
||||
use x11rb::protocol::xkb::ConnectionExt as _;
|
||||
use x11rb::protocol::xproto::{ChangeWindowAttributesAux, ConnectionExt as _};
|
||||
use x11rb::protocol::xproto::{ChangeWindowAttributesAux, ConnectionExt as _, KeyButMask};
|
||||
use x11rb::protocol::{randr, render, xinput, xkb, xproto, Event};
|
||||
use x11rb::resource_manager::Database;
|
||||
use x11rb::xcb_ffi::XCBConnection;
|
||||
@@ -32,7 +32,7 @@ use crate::platform::{LinuxCommon, PlatformWindow};
|
||||
use crate::{
|
||||
modifiers_from_xinput_info, point, px, AnyWindowHandle, Bounds, CursorStyle, DisplayId,
|
||||
Keystroke, Modifiers, ModifiersChangedEvent, Pixels, PlatformDisplay, PlatformInput, Point,
|
||||
ScrollDelta, Size, TouchPhase, WindowParams, X11Window,
|
||||
ScrollDelta, Size, TouchPhase, WindowParams, X11Window, XimXCBConnection,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@@ -96,6 +96,13 @@ impl From<xim::ClientError> for EventHandlerError {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct KeyEvent {
|
||||
time: Instant,
|
||||
state: KeyButMask,
|
||||
code: KeyCode,
|
||||
}
|
||||
|
||||
pub struct X11ClientState {
|
||||
pub(crate) loop_handle: LoopHandle<'static, X11Client>,
|
||||
pub(crate) event_loop: Option<calloop::EventLoop<'static, X11Client>>,
|
||||
@@ -113,7 +120,7 @@ pub struct X11ClientState {
|
||||
pub(crate) windows: HashMap<xproto::Window, WindowRef>,
|
||||
pub(crate) focused_window: Option<xproto::Window>,
|
||||
pub(crate) xkb: xkbc::State,
|
||||
pub(crate) ximc: Option<X11rbClient<Rc<XCBConnection>>>,
|
||||
pub(crate) ximc: Option<X11rbClient<XimXCBConnection>>,
|
||||
pub(crate) xim_handler: Option<XimHandler>,
|
||||
pub modifiers: Modifiers,
|
||||
|
||||
@@ -131,6 +138,8 @@ pub struct X11ClientState {
|
||||
pub(crate) common: LinuxCommon,
|
||||
pub(crate) clipboard: X11ClipboardContext<Clipboard>,
|
||||
pub(crate) primary: X11ClipboardContext<Primary>,
|
||||
|
||||
last_key_event: Option<KeyEvent>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -274,11 +283,11 @@ impl X11Client {
|
||||
|
||||
let xcb_connection = Rc::new(xcb_connection);
|
||||
|
||||
let (xim_tx, xim_rx) = channel::channel::<XimCallbackEvent>();
|
||||
|
||||
let ximc = X11rbClient::init(Rc::clone(&xcb_connection), x_root_index, None).ok();
|
||||
let xim_xcb_connection =
|
||||
XimXCBConnection::new(Rc::clone(&xcb_connection), Rc::new(Cell::new(true)));
|
||||
let ximc = X11rbClient::init(xim_xcb_connection.clone(), x_root_index, None).ok();
|
||||
let xim_handler = if ximc.is_some() {
|
||||
Some(XimHandler::new(xim_tx))
|
||||
Some(XimHandler::new())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -296,15 +305,51 @@ impl X11Client {
|
||||
{
|
||||
let xcb_connection = xcb_connection.clone();
|
||||
move |_readiness, _, client| {
|
||||
// println!("---------------------------------------------------");
|
||||
// let mut events_count = 0;
|
||||
// let start = Instant::now();
|
||||
|
||||
xim_xcb_connection.set_can_flush(false);
|
||||
while let Some(event) = xcb_connection.poll_for_event()? {
|
||||
// events_count += 1;
|
||||
|
||||
// let event_start = Instant::now();
|
||||
// println!(
|
||||
// "--> event {}: {} (sequnce: {:?})",
|
||||
// events_count,
|
||||
// ev_name,
|
||||
// event.wire_sequence_number()
|
||||
// );
|
||||
|
||||
// let _drop = util::defer(move || {
|
||||
// println!(
|
||||
// "<-- event {}: {}, took: {:?}",
|
||||
// events_count,
|
||||
// ev_name,
|
||||
// event_start.elapsed()
|
||||
// );
|
||||
// });
|
||||
|
||||
let mut state = client.0.borrow_mut();
|
||||
|
||||
let last_key_event = match event {
|
||||
Event::KeyPress(ev) | Event::KeyRelease(ev) => {
|
||||
state.last_key_event.replace(KeyEvent { time: Instant::now(), state: ev.state, code: ev.detail });
|
||||
None
|
||||
}
|
||||
_ => state.last_key_event.clone()
|
||||
};
|
||||
// let last_key_event_time = state.last_key_event.clone();
|
||||
|
||||
if state.ximc.is_none() || state.xim_handler.is_none() {
|
||||
drop(state);
|
||||
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) {
|
||||
@@ -314,11 +359,61 @@ impl X11Client {
|
||||
false
|
||||
}
|
||||
};
|
||||
if let Some(xim_event) = xim_handler.last_callback_event.take() {
|
||||
match xim_event {
|
||||
XimCallbackEvent::XimXEvent(
|
||||
event @ Event::KeyPress(key_event),
|
||||
)
|
||||
| XimCallbackEvent::XimXEvent(
|
||||
event @ Event::KeyRelease(key_event),
|
||||
) => {
|
||||
// let ev_name = event_name(&event);
|
||||
// println!("---> XimXEvent: {}", ev_name);
|
||||
|
||||
if let Some(last_key_event) = last_key_event {
|
||||
// println!(
|
||||
// "last_key_event_time: {}",
|
||||
// last_key_event_time
|
||||
// );
|
||||
// println!(
|
||||
// "event.time: {} (sequence: {})",
|
||||
// key_event.time, key_event.sequence
|
||||
// );
|
||||
// let lag_ms = last_key_event_time.saturating_sub(key_event.time);
|
||||
// if lag_ms > 100
|
||||
let lag_ms = last_key_event.time.elapsed();
|
||||
if (lag_ms > Duration::from_millis(100) && last_key_event.state == key_event.state && last_key_event.code == key_event.detail) ||
|
||||
(lag_ms > Duration::from_millis(50) && last_key_event.state != key_event.state && last_key_event.code != key_event.detail)
|
||||
{
|
||||
let name = event_name(&event);
|
||||
println!(">>>>>>>>>>>>>> dropping old event (name: {}, sequence: {}, lag_ms: {:?}) <<<<<<<<<<<<<<<<<<<<<", name, key_event.sequence, lag_ms);
|
||||
// drop(state);
|
||||
// continue;
|
||||
} else {
|
||||
client.handle_event(event);
|
||||
}
|
||||
} else {
|
||||
client.handle_event(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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let mut state = client.0.borrow_mut();
|
||||
state.ximc = Some(ximc);
|
||||
state.xim_handler = Some(xim_handler);
|
||||
drop(state);
|
||||
if xim_filtered {
|
||||
// println!(" -> xim filtered");
|
||||
continue;
|
||||
}
|
||||
if xim_connected {
|
||||
@@ -327,33 +422,46 @@ impl X11Client {
|
||||
client.handle_event(event);
|
||||
}
|
||||
}
|
||||
|
||||
// println!(
|
||||
// "-------------- events_count: {:?}, took: {:?} ----------\n\n",
|
||||
// events_count,
|
||||
// start.elapsed()
|
||||
// );
|
||||
|
||||
xim_xcb_connection.set_can_flush(true);
|
||||
xim_xcb_connection.flush()?;
|
||||
|
||||
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(xim_rx, {
|
||||
// move |chan_event, _, client| match chan_event {
|
||||
// channel::Event::Msg(xim_event) => {
|
||||
// // println!(".......... XimCallBackEvent ...............");
|
||||
// match xim_event {
|
||||
// XimCallbackEvent::XimXEvent(event) => {
|
||||
// println!("--> XimXEvent");
|
||||
// client.handle_event(event);
|
||||
// }
|
||||
// XimCallbackEvent::XimCommitEvent(window, text) => {
|
||||
// client.xim_handle_commit(window, text);
|
||||
// }
|
||||
// XimCallbackEvent::XimPreeditEvent(window, text) => {
|
||||
// client.xim_handle_preedit(window, text);
|
||||
// }
|
||||
// };
|
||||
// // println!("......... DONE: XimCallBackEvent ...............");
|
||||
// }
|
||||
// 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 {
|
||||
@@ -401,6 +509,8 @@ impl X11Client {
|
||||
|
||||
clipboard,
|
||||
primary,
|
||||
|
||||
last_key_event: None,
|
||||
})))
|
||||
}
|
||||
|
||||
@@ -466,6 +576,8 @@ impl X11Client {
|
||||
}
|
||||
|
||||
fn handle_event(&self, event: Event) -> Option<()> {
|
||||
// println!("handle_event: {:?}", event_name(&event));
|
||||
|
||||
match event {
|
||||
Event::ClientMessage(event) => {
|
||||
let window = self.get_window(event.window)?;
|
||||
@@ -498,6 +610,7 @@ impl X11Client {
|
||||
Event::Expose(event) => {
|
||||
let window = self.get_window(event.window)?;
|
||||
window.refresh();
|
||||
std::thread::sleep(Duration::from_millis(20));
|
||||
}
|
||||
Event::FocusIn(event) => {
|
||||
let window = self.get_window(event.event)?;
|
||||
@@ -588,6 +701,7 @@ impl X11Client {
|
||||
keystroke
|
||||
};
|
||||
drop(state);
|
||||
// println!("keydown. keystroke.key: {:?}", keystroke.key);
|
||||
window.handle_input(PlatformInput::KeyDown(crate::KeyDownEvent {
|
||||
keystroke,
|
||||
is_held: false,
|
||||
@@ -794,13 +908,20 @@ impl X11Client {
|
||||
}
|
||||
|
||||
fn xim_handle_event(&self, event: Event) -> Option<()> {
|
||||
let name = event_name(&event);
|
||||
match event {
|
||||
Event::KeyPress(event) | Event::KeyRelease(event) => {
|
||||
let mut state = self.0.borrow_mut();
|
||||
|
||||
let mut ximc = state.ximc.take().unwrap();
|
||||
let mut xim_handler = state.xim_handler.take().unwrap();
|
||||
drop(state);
|
||||
xim_handler.window = event.event;
|
||||
|
||||
println!(
|
||||
"--> ximc.forward_event({}), sequence: {}",
|
||||
name, event.sequence
|
||||
);
|
||||
ximc.forward_event(
|
||||
xim_handler.im_id,
|
||||
xim_handler.ic_id,
|
||||
@@ -1107,3 +1228,111 @@ pub fn mode_refresh_rate(mode: &randr::ModeInfo) -> Duration {
|
||||
fn fp3232_to_f32(value: xinput::Fp3232) -> f32 {
|
||||
value.integral as f32 + value.frac as f32 / u32::MAX as f32
|
||||
}
|
||||
|
||||
fn event_name(event: &Event) -> &'static str {
|
||||
match event {
|
||||
Event::Unknown(_) => "Event::Unknown",
|
||||
Event::Error(_) => "Event::Error",
|
||||
Event::ButtonPress(_) => "Event::ButtonPress",
|
||||
Event::ButtonRelease(_) => "Event::ButtonRelease",
|
||||
Event::CirculateNotify(_) => "Event::CirculateNotify",
|
||||
Event::CirculateRequest(_) => "Event::CirculateRequest",
|
||||
Event::ClientMessage(_) => "Event::ClientMessage",
|
||||
Event::ColormapNotify(_) => "Event::ColormapNotify",
|
||||
Event::ConfigureNotify(_) => "Event::ConfigureNotify",
|
||||
Event::ConfigureRequest(_) => "Event::ConfigureRequest",
|
||||
Event::CreateNotify(_) => "Event::CreateNotify",
|
||||
Event::DestroyNotify(_) => "Event::DestroyNotify",
|
||||
Event::EnterNotify(_) => "Event::EnterNotify",
|
||||
Event::Expose(_) => "Event::Expose",
|
||||
Event::FocusIn(_) => "Event::FocusIn",
|
||||
Event::FocusOut(_) => "Event::FocusOut",
|
||||
Event::GeGeneric(_) => "Event::GeGeneric",
|
||||
Event::GraphicsExposure(_) => "Event::GraphicsExposure",
|
||||
Event::GravityNotify(_) => "Event::GravityNotify",
|
||||
Event::KeyPress(_) => "Event::KeyPress",
|
||||
Event::KeyRelease(_) => "Event::KeyRelease",
|
||||
Event::KeymapNotify(_) => "Event::KeymapNotify",
|
||||
Event::LeaveNotify(_) => "Event::LeaveNotify",
|
||||
Event::MapNotify(_) => "Event::MapNotify",
|
||||
Event::MapRequest(_) => "Event::MapRequest",
|
||||
Event::MappingNotify(_) => "Event::MappingNotify",
|
||||
Event::MotionNotify(_) => "Event::MotionNotify",
|
||||
Event::NoExposure(_) => "Event::NoExposure",
|
||||
Event::PropertyNotify(_) => "Event::PropertyNotify",
|
||||
Event::ReparentNotify(_) => "Event::ReparentNotify",
|
||||
Event::ResizeRequest(_) => "Event::ResizeRequest",
|
||||
Event::SelectionClear(_) => "Event::SelectionClear",
|
||||
Event::SelectionNotify(_) => "Event::SelectionNotify",
|
||||
Event::SelectionRequest(_) => "Event::SelectionRequest",
|
||||
Event::UnmapNotify(_) => "Event::UnmapNotify",
|
||||
Event::VisibilityNotify(_) => "Event::VisibilityNotify",
|
||||
Event::RandrNotify(_) => "Event::RandrNotify",
|
||||
Event::RandrScreenChangeNotify(_) => "Event::RandrScreenChangeNotify",
|
||||
Event::ShapeNotify(_) => "Event::ShapeNotify",
|
||||
Event::XfixesCursorNotify(_) => "Event::XfixesCursorNotify",
|
||||
Event::XfixesSelectionNotify(_) => "Event::XfixesSelectionNotify",
|
||||
Event::XinputBarrierHit(_) => "Event::XinputBarrierHit",
|
||||
Event::XinputBarrierLeave(_) => "Event::XinputBarrierLeave",
|
||||
Event::XinputButtonPress(_) => "Event::XinputButtonPress",
|
||||
Event::XinputButtonRelease(_) => "Event::XinputButtonRelease",
|
||||
Event::XinputChangeDeviceNotify(_) => "Event::XinputChangeDeviceNotify",
|
||||
Event::XinputDeviceButtonPress(_) => "Event::XinputDeviceButtonPress",
|
||||
Event::XinputDeviceButtonRelease(_) => "Event::XinputDeviceButtonRelease",
|
||||
Event::XinputDeviceButtonStateNotify(_) => "Event::XinputDeviceButtonStateNotify",
|
||||
Event::XinputDeviceChanged(_) => "Event::XinputDeviceChanged",
|
||||
Event::XinputDeviceFocusIn(_) => "Event::XinputDeviceFocusIn",
|
||||
Event::XinputDeviceFocusOut(_) => "Event::XinputDeviceFocusOut",
|
||||
Event::XinputDeviceKeyPress(_) => "Event::XinputDeviceKeyPress",
|
||||
Event::XinputDeviceKeyRelease(_) => "Event::XinputDeviceKeyRelease",
|
||||
Event::XinputDeviceKeyStateNotify(_) => "Event::XinputDeviceKeyStateNotify",
|
||||
Event::XinputDeviceMappingNotify(_) => "Event::XinputDeviceMappingNotify",
|
||||
Event::XinputDeviceMotionNotify(_) => "Event::XinputDeviceMotionNotify",
|
||||
Event::XinputDevicePresenceNotify(_) => "Event::XinputDevicePresenceNotify",
|
||||
Event::XinputDevicePropertyNotify(_) => "Event::XinputDevicePropertyNotify",
|
||||
Event::XinputDeviceStateNotify(_) => "Event::XinputDeviceStateNotify",
|
||||
Event::XinputDeviceValuator(_) => "Event::XinputDeviceValuator",
|
||||
Event::XinputEnter(_) => "Event::XinputEnter",
|
||||
Event::XinputFocusIn(_) => "Event::XinputFocusIn",
|
||||
Event::XinputFocusOut(_) => "Event::XinputFocusOut",
|
||||
Event::XinputGesturePinchBegin(_) => "Event::XinputGesturePinchBegin",
|
||||
Event::XinputGesturePinchEnd(_) => "Event::XinputGesturePinchEnd",
|
||||
Event::XinputGesturePinchUpdate(_) => "Event::XinputGesturePinchUpdate",
|
||||
Event::XinputGestureSwipeBegin(_) => "Event::XinputGestureSwipeBegin",
|
||||
Event::XinputGestureSwipeEnd(_) => "Event::XinputGestureSwipeEnd",
|
||||
Event::XinputGestureSwipeUpdate(_) => "Event::XinputGestureSwipeUpdate",
|
||||
Event::XinputHierarchy(_) => "Event::XinputHierarchy",
|
||||
Event::XinputKeyPress(_) => "Event::XinputKeyPress",
|
||||
Event::XinputKeyRelease(_) => "Event::XinputKeyRelease",
|
||||
Event::XinputLeave(_) => "Event::XinputLeave",
|
||||
Event::XinputMotion(_) => "Event::XinputMotion",
|
||||
Event::XinputProperty(_) => "Event::XinputProperty",
|
||||
Event::XinputProximityIn(_) => "Event::XinputProximityIn",
|
||||
Event::XinputProximityOut(_) => "Event::XinputProximityOut",
|
||||
Event::XinputRawButtonPress(_) => "Event::XinputRawButtonPress",
|
||||
Event::XinputRawButtonRelease(_) => "Event::XinputRawButtonRelease",
|
||||
Event::XinputRawKeyPress(_) => "Event::XinputRawKeyPress",
|
||||
Event::XinputRawKeyRelease(_) => "Event::XinputRawKeyRelease",
|
||||
Event::XinputRawMotion(_) => "Event::XinputRawMotion",
|
||||
Event::XinputRawTouchBegin(_) => "Event::XinputRawTouchBegin",
|
||||
Event::XinputRawTouchEnd(_) => "Event::XinputRawTouchEnd",
|
||||
Event::XinputRawTouchUpdate(_) => "Event::XinputRawTouchUpdate",
|
||||
Event::XinputTouchBegin(_) => "Event::XinputTouchBegin",
|
||||
Event::XinputTouchEnd(_) => "Event::XinputTouchEnd",
|
||||
Event::XinputTouchOwnership(_) => "Event::XinputTouchOwnership",
|
||||
Event::XinputTouchUpdate(_) => "Event::XinputTouchUpdate",
|
||||
Event::XkbAccessXNotify(_) => "Event::XkbAccessXNotify",
|
||||
Event::XkbActionMessage(_) => "Event::XkbActionMessage",
|
||||
Event::XkbBellNotify(_) => "Event::XkbBellNotify",
|
||||
Event::XkbCompatMapNotify(_) => "Event::XkbCompatMapNotify",
|
||||
Event::XkbControlsNotify(_) => "Event::XkbControlsNotify",
|
||||
Event::XkbExtensionDeviceNotify(_) => "Event::XkbExtensionDeviceNotify",
|
||||
Event::XkbIndicatorMapNotify(_) => "Event::XkbIndicatorMapNotify",
|
||||
Event::XkbIndicatorStateNotify(_) => "Event::XkbIndicatorStateNotify",
|
||||
Event::XkbMapNotify(_) => "Event::XkbMapNotify",
|
||||
Event::XkbNamesNotify(_) => "Event::XkbNamesNotify",
|
||||
Event::XkbNewKeyboardNotify(_) => "Event::XkbNewKeyboardNotify",
|
||||
Event::XkbStateNotify(_) => "Event::XkbStateNotify",
|
||||
_ => "unknown",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ use std::{
|
||||
ptr::NonNull,
|
||||
rc::Rc,
|
||||
sync::{self, Arc},
|
||||
time::Instant,
|
||||
};
|
||||
|
||||
use super::{X11Display, XINPUT_MASTER_DEVICE};
|
||||
@@ -531,8 +532,15 @@ impl X11WindowStatePtr {
|
||||
}
|
||||
|
||||
pub fn handle_input(&self, input: PlatformInput) {
|
||||
// println!("handle_input called");
|
||||
// let start = Instant::now();
|
||||
if let Some(ref mut fun) = self.callbacks.borrow_mut().input {
|
||||
// println!(
|
||||
// "handle_input. got input callback. elapsed: {:?}",
|
||||
// start.elapsed()
|
||||
// );
|
||||
if !fun(input.clone()).propagate {
|
||||
// println!("handle_input. return here. elapsed: {:?}", start.elapsed());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
use std::default::Default;
|
||||
use std::{cell::Cell, default::Default, rc::Rc};
|
||||
|
||||
use calloop::channel;
|
||||
|
||||
use x11rb::protocol::{xproto, Event};
|
||||
use xim::{AHashMap, AttributeName, Client, ClientError, ClientHandler, InputStyle};
|
||||
use x11rb::{
|
||||
connection::{Connection, RequestConnection},
|
||||
cookie::{CookieWithFds, VoidCookie},
|
||||
protocol::{xproto, Event},
|
||||
xcb_ffi::XCBConnection,
|
||||
};
|
||||
use xim::{
|
||||
x11rb::HasConnection, AHashMap, AttributeName, Client, ClientError, ClientHandler, InputStyle,
|
||||
};
|
||||
|
||||
pub enum XimCallbackEvent {
|
||||
XimXEvent(x11rb::protocol::Event),
|
||||
@@ -14,19 +21,21 @@ pub enum XimCallbackEvent {
|
||||
pub struct XimHandler {
|
||||
pub im_id: u16,
|
||||
pub ic_id: u16,
|
||||
pub xim_tx: channel::Sender<XimCallbackEvent>,
|
||||
// pub xim_tx: channel::Sender<XimCallbackEvent>,
|
||||
pub connected: bool,
|
||||
pub window: xproto::Window,
|
||||
pub last_callback_event: Option<XimCallbackEvent>,
|
||||
}
|
||||
|
||||
impl XimHandler {
|
||||
pub fn new(xim_tx: channel::Sender<XimCallbackEvent>) -> Self {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
im_id: Default::default(),
|
||||
ic_id: Default::default(),
|
||||
xim_tx,
|
||||
// xim_tx,
|
||||
connected: false,
|
||||
window: Default::default(),
|
||||
last_callback_event: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,12 +89,12 @@ impl<C: Client<XEvent = xproto::KeyPressEvent>> ClientHandler<C> for XimHandler
|
||||
_input_context_id: u16,
|
||||
text: &str,
|
||||
) -> Result<(), ClientError> {
|
||||
self.xim_tx
|
||||
.send(XimCallbackEvent::XimCommitEvent(
|
||||
self.last_callback_event
|
||||
.replace(XimCallbackEvent::XimCommitEvent(
|
||||
self.window,
|
||||
String::from(text),
|
||||
))
|
||||
.ok();
|
||||
));
|
||||
// .ok();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -99,14 +108,20 @@ impl<C: Client<XEvent = xproto::KeyPressEvent>> ClientHandler<C> for XimHandler
|
||||
) -> Result<(), ClientError> {
|
||||
match xev.response_type {
|
||||
x11rb::protocol::xproto::KEY_PRESS_EVENT => {
|
||||
self.xim_tx
|
||||
.send(XimCallbackEvent::XimXEvent(Event::KeyPress(xev)))
|
||||
.ok();
|
||||
// println!(
|
||||
// "XimHandler. handle_forward_event(KeyPress). sequence: {}",
|
||||
// xev.sequence
|
||||
// );
|
||||
self.last_callback_event
|
||||
.replace(XimCallbackEvent::XimXEvent(Event::KeyPress(xev)));
|
||||
}
|
||||
x11rb::protocol::xproto::KEY_RELEASE_EVENT => {
|
||||
self.xim_tx
|
||||
.send(XimCallbackEvent::XimXEvent(Event::KeyRelease(xev)))
|
||||
.ok();
|
||||
// println!(
|
||||
// "XimHandler. handle_forward_event(KeyRelease), sequence: {}",
|
||||
// xev.sequence
|
||||
// );
|
||||
self.last_callback_event
|
||||
.replace(XimCallbackEvent::XimXEvent(Event::KeyRelease(xev)));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -145,12 +160,185 @@ impl<C: Client<XEvent = xproto::KeyPressEvent>> ClientHandler<C> 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.last_callback_event
|
||||
.replace(XimCallbackEvent::XimPreeditEvent(
|
||||
self.window,
|
||||
String::from(preedit_string),
|
||||
))
|
||||
.ok();
|
||||
));
|
||||
// self.xim_tx
|
||||
// .send()
|
||||
// .ok();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct XimXCBConnection(Rc<XCBConnection>, Rc<Cell<bool>>);
|
||||
|
||||
impl XimXCBConnection {
|
||||
pub fn new(connection: Rc<XCBConnection>, can_flush: Rc<Cell<bool>>) -> Self {
|
||||
Self(connection, can_flush)
|
||||
}
|
||||
|
||||
pub fn set_can_flush(&self, can_flush: bool) {
|
||||
self.1.set(can_flush);
|
||||
}
|
||||
}
|
||||
|
||||
impl HasConnection for XimXCBConnection {
|
||||
type Connection = Self;
|
||||
|
||||
fn conn(&self) -> &Self::Connection {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Connection for XimXCBConnection {
|
||||
fn wait_for_raw_event_with_sequence(
|
||||
&self,
|
||||
) -> Result<x11rb::connection::RawEventAndSeqNumber<Self::Buf>, x11rb::errors::ConnectionError>
|
||||
{
|
||||
self.0.wait_for_raw_event_with_sequence()
|
||||
}
|
||||
|
||||
fn poll_for_raw_event_with_sequence(
|
||||
&self,
|
||||
) -> Result<
|
||||
Option<x11rb::connection::RawEventAndSeqNumber<Self::Buf>>,
|
||||
x11rb::errors::ConnectionError,
|
||||
> {
|
||||
self.0.poll_for_raw_event_with_sequence()
|
||||
}
|
||||
|
||||
fn flush(&self) -> Result<(), x11rb::errors::ConnectionError> {
|
||||
if self.1.get() {
|
||||
// println!("*real* flush");
|
||||
self.0.flush()
|
||||
} else {
|
||||
// println!("fake flush");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn setup(&self) -> &xproto::Setup {
|
||||
self.0.setup()
|
||||
}
|
||||
|
||||
fn generate_id(&self) -> Result<u32, x11rb::errors::ReplyOrIdError> {
|
||||
self.0.generate_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl RequestConnection for XimXCBConnection {
|
||||
type Buf = <XCBConnection as RequestConnection>::Buf;
|
||||
|
||||
fn send_request_with_reply<R>(
|
||||
&self,
|
||||
bufs: &[std::io::IoSlice<'_>],
|
||||
fds: Vec<x11rb::utils::RawFdContainer>,
|
||||
) -> Result<x11rb::cookie::Cookie<'_, Self, R>, x11rb::errors::ConnectionError>
|
||||
where
|
||||
R: x11rb::x11_utils::TryParse,
|
||||
{
|
||||
self.0
|
||||
.send_request_with_reply::<R>(bufs, fds)
|
||||
.map(|cookie| x11rb::cookie::Cookie::new(self, cookie.sequence_number()))
|
||||
}
|
||||
|
||||
fn send_request_with_reply_with_fds<R>(
|
||||
&self,
|
||||
bufs: &[std::io::IoSlice<'_>],
|
||||
fds: Vec<x11rb::utils::RawFdContainer>,
|
||||
) -> Result<CookieWithFds<'_, Self, R>, x11rb::errors::ConnectionError>
|
||||
where
|
||||
R: x11rb::x11_utils::TryParseFd,
|
||||
{
|
||||
self.0
|
||||
.send_request_with_reply_with_fds::<R>(bufs, fds)
|
||||
.map(|cookie| CookieWithFds::new(self, cookie.sequence_number()))
|
||||
}
|
||||
|
||||
fn send_request_without_reply(
|
||||
&self,
|
||||
bufs: &[std::io::IoSlice<'_>],
|
||||
fds: Vec<x11rb::utils::RawFdContainer>,
|
||||
) -> Result<VoidCookie<'_, Self>, x11rb::errors::ConnectionError> {
|
||||
self.0
|
||||
.send_request_without_reply(bufs, fds)
|
||||
.map(|cookie| VoidCookie::new(self, cookie.sequence_number()))
|
||||
}
|
||||
|
||||
fn discard_reply(
|
||||
&self,
|
||||
sequence: x11rb::connection::SequenceNumber,
|
||||
kind: x11rb::connection::RequestKind,
|
||||
mode: x11rb::connection::DiscardMode,
|
||||
) {
|
||||
self.0.discard_reply(sequence, kind, mode)
|
||||
}
|
||||
|
||||
fn prefetch_extension_information(
|
||||
&self,
|
||||
extension_name: &'static str,
|
||||
) -> Result<(), x11rb::errors::ConnectionError> {
|
||||
self.0.prefetch_extension_information(extension_name)
|
||||
}
|
||||
|
||||
fn extension_information(
|
||||
&self,
|
||||
extension_name: &'static str,
|
||||
) -> Result<Option<x11rb::x11_utils::ExtensionInformation>, x11rb::errors::ConnectionError>
|
||||
{
|
||||
self.0.extension_information(extension_name)
|
||||
}
|
||||
|
||||
fn wait_for_reply_or_raw_error(
|
||||
&self,
|
||||
sequence: x11rb::connection::SequenceNumber,
|
||||
) -> Result<x11rb::connection::ReplyOrError<Self::Buf>, x11rb::errors::ConnectionError> {
|
||||
self.0.wait_for_reply_or_raw_error(sequence)
|
||||
}
|
||||
|
||||
fn wait_for_reply(
|
||||
&self,
|
||||
sequence: x11rb::connection::SequenceNumber,
|
||||
) -> Result<Option<Self::Buf>, x11rb::errors::ConnectionError> {
|
||||
self.0.wait_for_reply(sequence)
|
||||
}
|
||||
|
||||
fn wait_for_reply_with_fds_raw(
|
||||
&self,
|
||||
sequence: x11rb::connection::SequenceNumber,
|
||||
) -> Result<
|
||||
x11rb::connection::ReplyOrError<x11rb::connection::BufWithFds<Self::Buf>, Self::Buf>,
|
||||
x11rb::errors::ConnectionError,
|
||||
> {
|
||||
self.0.wait_for_reply_with_fds_raw(sequence)
|
||||
}
|
||||
|
||||
fn check_for_raw_error(
|
||||
&self,
|
||||
sequence: x11rb::connection::SequenceNumber,
|
||||
) -> Result<Option<Self::Buf>, x11rb::errors::ConnectionError> {
|
||||
self.0.check_for_raw_error(sequence)
|
||||
}
|
||||
|
||||
fn prefetch_maximum_request_bytes(&self) {
|
||||
self.0.prefetch_maximum_request_bytes()
|
||||
}
|
||||
|
||||
fn maximum_request_bytes(&self) -> usize {
|
||||
self.0.maximum_request_bytes()
|
||||
}
|
||||
|
||||
fn parse_error(
|
||||
&self,
|
||||
error: &[u8],
|
||||
) -> Result<x11rb::x11_utils::X11Error, x11rb::errors::ParseError> {
|
||||
self.0.parse_error(error)
|
||||
}
|
||||
|
||||
fn parse_event(&self, event: &[u8]) -> Result<Event, x11rb::errors::ParseError> {
|
||||
self.0.parse_event(event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,8 +691,15 @@ impl Window {
|
||||
measure("frame duration", || {
|
||||
handle
|
||||
.update(&mut cx, |_, cx| {
|
||||
// let start = Instant::now();
|
||||
cx.draw();
|
||||
// let elapsed = start.elapsed();
|
||||
// eprintln!("draw duration: {:?}", elapsed);
|
||||
|
||||
// let start = Instant::now();
|
||||
cx.present();
|
||||
// let elapsed = start.elapsed();
|
||||
// eprintln!("present duration: {:?}", elapsed);
|
||||
})
|
||||
.log_err();
|
||||
})
|
||||
|
||||
118
refreshs.txt
Normal file
118
refreshs.txt
Normal file
@@ -0,0 +1,118 @@
|
||||
Instant { tv_sec: 28071, tv_nsec: 336969 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 16998891 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 33681854 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 50345258 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 67024970 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 83681212 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 100357217 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 117008879 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 133684221 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 150357794 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 167026818 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 183683540 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 200357812 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 217010536 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 233686439 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 250361331 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 267028773 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 283685988 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 300347230 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 317016592 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 333688865 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 350363109 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 367031611 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 383657223 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 400318827 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 416997110 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 433689142 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 450363825 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 467045469 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 483690271 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 500367633 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 517017787 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 533691810 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 550368302 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 567040074 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 583673738 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 600334321 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 617004243 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 633664287 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 650343009 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 667035452 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 683693964 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 700369198 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 717020391 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 733696553 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 750353037 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 767039729 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 783695882 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 800369604 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 817037228 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 833697510 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 850353393 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 867039107 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 883697449 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 900357362 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 917024804 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 933699048 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 950355490 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Instant { tv_sec: 28071, tv_nsec: 967053933 } - expose event
|
||||
X11WindowStatePtr.refresh
|
||||
Reference in New Issue
Block a user