mirror of
https://github.com/wez/wezterm.git
synced 2024-11-27 12:23:46 +03:00
x11: coalesce resize and repaint events
The thesis is that some WM's might send a whole bunch of events that cause us to over draw/over resize. I'm not convinced that this is a righteous change, but it can't hurt to try. refs: #1051
This commit is contained in:
parent
3d227d27cc
commit
367797c1ae
@ -286,7 +286,11 @@ impl XConnection {
|
||||
|
||||
loop {
|
||||
match self.conn.poll_for_queued_event() {
|
||||
None => return Ok(()),
|
||||
None => {
|
||||
self.dispatch_pending_events()?;
|
||||
self.conn.flush();
|
||||
return Ok(());
|
||||
}
|
||||
Some(event) => self.process_xcb_event_ime(&event)?,
|
||||
}
|
||||
self.conn.flush();
|
||||
@ -327,6 +331,15 @@ impl XConnection {
|
||||
self.windows.borrow().get(&window_id).map(Arc::clone)
|
||||
}
|
||||
|
||||
fn dispatch_pending_events(&self) -> anyhow::Result<()> {
|
||||
for window in self.windows.borrow().values() {
|
||||
let mut inner = window.lock().unwrap();
|
||||
inner.dispatch_pending_events()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn process_window_event(
|
||||
&self,
|
||||
window_id: xcb::xproto::Window,
|
||||
|
@ -69,6 +69,7 @@ pub(crate) struct XWindowInner {
|
||||
last_cursor_position: Rect,
|
||||
invalidated: bool,
|
||||
paint_throttled: bool,
|
||||
pending: Vec<WindowEvent>,
|
||||
}
|
||||
|
||||
impl Drop for XWindowInner {
|
||||
@ -129,7 +130,7 @@ impl XWindowInner {
|
||||
/// it to encompass both. This avoids bloating the list with a series
|
||||
/// of increasing rectangles when resizing larger or smaller.
|
||||
fn expose(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
|
||||
self.events.dispatch(WindowEvent::NeedRepaint);
|
||||
self.queue_pending(WindowEvent::NeedRepaint);
|
||||
}
|
||||
|
||||
fn do_mouse_event(&mut self, event: MouseEvent) -> anyhow::Result<()> {
|
||||
@ -163,6 +164,69 @@ impl XWindowInner {
|
||||
}
|
||||
}
|
||||
|
||||
fn queue_pending(&mut self, event: WindowEvent) {
|
||||
self.pending.push(event);
|
||||
}
|
||||
|
||||
pub fn dispatch_pending_events(&mut self) -> anyhow::Result<()> {
|
||||
if self.pending.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut need_paint = false;
|
||||
let mut resize = None;
|
||||
|
||||
for event in self.pending.drain(..) {
|
||||
match event {
|
||||
WindowEvent::NeedRepaint => {
|
||||
if need_paint {
|
||||
log::info!("coalesce a repaint");
|
||||
}
|
||||
need_paint = true;
|
||||
}
|
||||
e @ WindowEvent::Resized { .. } => {
|
||||
if resize.is_some() {
|
||||
log::info!("coalesce a resize");
|
||||
}
|
||||
resize.replace(e);
|
||||
}
|
||||
e => {
|
||||
self.events.dispatch(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(resize) = resize.take() {
|
||||
self.events.dispatch(resize);
|
||||
}
|
||||
|
||||
if need_paint {
|
||||
if self.paint_throttled {
|
||||
self.invalidated = true;
|
||||
} else {
|
||||
self.invalidated = false;
|
||||
self.events.dispatch(WindowEvent::NeedRepaint);
|
||||
|
||||
self.paint_throttled = true;
|
||||
let window_id = self.window_id;
|
||||
promise::spawn::spawn(async move {
|
||||
// Don't try to paint more frequently than 30 fps
|
||||
async_io::Timer::after(std::time::Duration::from_millis(1000 / 30)).await;
|
||||
XConnection::with_window_inner(window_id, |inner| {
|
||||
inner.paint_throttled = false;
|
||||
if inner.invalidated {
|
||||
inner.invalidate();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn dispatch_event(&mut self, event: &xcb::GenericEvent) -> anyhow::Result<()> {
|
||||
let r = event.response_type() & 0x7f;
|
||||
let conn = self.conn();
|
||||
@ -195,7 +259,7 @@ impl XWindowInner {
|
||||
dpi: self.dpi as usize,
|
||||
};
|
||||
|
||||
self.events.dispatch(WindowEvent::Resized {
|
||||
self.queue_pending(WindowEvent::Resized {
|
||||
dimensions,
|
||||
window_state: self.get_window_state().unwrap_or(WindowState::default()),
|
||||
});
|
||||
@ -786,6 +850,7 @@ impl XWindow {
|
||||
last_cursor_position: Rect::default(),
|
||||
paint_throttled: false,
|
||||
invalidated: false,
|
||||
pending: vec![],
|
||||
}))
|
||||
};
|
||||
|
||||
@ -835,27 +900,7 @@ impl XWindowInner {
|
||||
}
|
||||
|
||||
fn invalidate(&mut self) {
|
||||
if self.paint_throttled {
|
||||
self.invalidated = true;
|
||||
return;
|
||||
}
|
||||
self.invalidated = false;
|
||||
self.events.dispatch(WindowEvent::NeedRepaint);
|
||||
|
||||
self.paint_throttled = true;
|
||||
let window_id = self.window_id;
|
||||
promise::spawn::spawn(async move {
|
||||
// Don't try to paint more frequently than 30 fps
|
||||
async_io::Timer::after(std::time::Duration::from_millis(1000 / 30)).await;
|
||||
XConnection::with_window_inner(window_id, |inner| {
|
||||
inner.paint_throttled = false;
|
||||
if inner.invalidated {
|
||||
inner.invalidate();
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
})
|
||||
.detach();
|
||||
self.queue_pending(WindowEvent::NeedRepaint);
|
||||
}
|
||||
|
||||
fn toggle_fullscreen(&mut self) {
|
||||
|
Loading…
Reference in New Issue
Block a user