1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-10 06:34:17 +03:00

x11/wayland: reduce frequency of core event loop

In an earlier incarnation we needed to wake up more often to paint,
but we now should have reliable event sources for all of the
invalidation cases and we can thus sleep for much longer in
the main event loop.

refs: #770
This commit is contained in:
Wez Furlong 2021-05-08 12:59:33 -07:00
parent a884021074
commit 7d301b91a7
3 changed files with 8 additions and 64 deletions

View File

@ -227,7 +227,7 @@ impl ConnectionOps for WaylandConnection {
// there may be others to deal with
Duration::new(0, 0)
} else {
Duration::from_millis(2500)
Duration::from_secs(86400)
};
self.flush()?;
{

View File

@ -11,7 +11,7 @@ use std::collections::HashMap;
use std::os::unix::io::AsRawFd;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use std::time::Duration;
use xcb_util::ffi::keysyms::{xcb_key_symbols_alloc, xcb_key_symbols_free, xcb_key_symbols_t};
pub struct XConnection {
@ -169,20 +169,7 @@ impl ConnectionOps for XConnection {
PollOpt::level(),
)?;
let paint_interval = Duration::from_millis(25);
let mut last_interval = Instant::now();
while !*self.should_terminate.borrow() {
let now = Instant::now();
let diff = now - last_interval;
let period = if diff >= paint_interval {
self.do_paint();
last_interval = now;
paint_interval
} else {
paint_interval - diff
};
// Process any events that might have accumulated in the local
// buffer (eg: due to a flush) before we potentially go to sleep.
// The locally queued events won't mark the fd as ready, so we
@ -199,7 +186,7 @@ impl ConnectionOps for XConnection {
// there may be others to deal with
Duration::new(0, 0)
} else {
period
Duration::from_secs(86400)
};
match poll.poll(&mut events, Some(period)) {
@ -425,14 +412,6 @@ impl XConnection {
self.atom_delete
}
/// Run through all of the windows and cause them to paint if they need it.
fn do_paint(&self) {
for window in self.windows.borrow().values() {
window.lock().unwrap().paint().unwrap();
}
self.conn.flush();
}
pub(crate) fn with_window_inner<
R,
F: FnOnce(&mut XWindowInner) -> anyhow::Result<R> + Send + 'static,

View File

@ -5,8 +5,8 @@ use crate::os::xkeysyms;
use crate::os::{Connection, Window};
use crate::{
Clipboard, Dimensions, MouseButtons, MouseCursor, MouseEvent, MouseEventKind, MousePress,
Point, Rect, ScreenPoint, Size, WindowDecorations, WindowEvent, WindowEventReceiver,
WindowEventSender, WindowOps,
Point, ScreenPoint, WindowDecorations, WindowEvent, WindowEventReceiver, WindowEventSender,
WindowOps,
};
use anyhow::{anyhow, Context as _};
use async_trait::async_trait;
@ -15,7 +15,6 @@ use promise::{Future, Promise};
use raw_window_handle::unix::XcbHandle;
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
use std::any::Any;
use std::collections::VecDeque;
use std::convert::TryInto;
use std::rc::{Rc, Weak};
use std::sync::{Arc, Mutex};
@ -59,8 +58,6 @@ pub(crate) struct XWindowInner {
width: u16,
height: u16,
dpi: f64,
expose: VecDeque<Rect>,
paint_all: bool,
cursors: CursorInfo,
copy_and_paste: CopyAndPaste,
config: ConfigHandle,
@ -68,16 +65,6 @@ pub(crate) struct XWindowInner {
resize_promises: Vec<Promise<Dimensions>>,
}
fn enclosing_boundary_with(a: &Rect, b: &Rect) -> Rect {
let left = a.min_x().min(b.min_x());
let right = a.max_x().max(b.max_x());
let top = a.min_y().min(b.min_y());
let bottom = a.max_y().max(b.max_y());
Rect::new(Point::new(left, top), Size::new(right - left, bottom - top))
}
impl Drop for XWindowInner {
fn drop(&mut self) {
if let Some(conn) = self.conn.upgrade() {
@ -131,33 +118,13 @@ impl XWindowInner {
Ok(gl_state)
}
pub fn paint(&mut self) -> anyhow::Result<()> {
if !self.paint_all && self.expose.is_empty() {
return Ok(());
}
self.paint_all = false;
self.expose.clear();
self.events.try_send(WindowEvent::NeedRepaint).ok();
Ok(())
}
/// Add a region to the list of exposed/damaged/dirty regions.
/// Note that a window resize will likely invalidate the entire window.
/// If the new region intersects with the prior region, then we expand
/// 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) {
let expose = Rect::new(
Point::new(x as isize, y as isize),
Size::new(width as isize, height as isize),
);
if let Some(prior) = self.expose.back_mut() {
if prior.intersects(&expose) {
*prior = enclosing_boundary_with(&prior, &expose);
return;
}
}
self.expose.push_back(expose);
fn expose(&mut self, _x: u16, _y: u16, _width: u16, _height: u16) {
self.events.try_send(WindowEvent::NeedRepaint).ok();
}
fn do_mouse_event(&mut self, event: MouseEvent) -> anyhow::Result<()> {
@ -767,8 +734,6 @@ impl XWindow {
width: width.try_into()?,
height: height.try_into()?,
dpi: conn.default_dpi(),
expose: VecDeque::new(),
paint_all: true,
copy_and_paste: CopyAndPaste::default(),
cursors: CursorInfo::new(&conn),
gl_state: None,
@ -817,7 +782,7 @@ impl XWindowInner {
xcb::map_window(self.conn().conn(), self.window_id);
}
fn invalidate(&mut self) {
self.paint_all = true;
self.events.try_send(WindowEvent::NeedRepaint).ok();
}
fn toggle_fullscreen(&mut self) {