aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-08-10 09:58:26 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-08-10 14:50:51 +0400
commit9b073b2350d00dfdb32a4983a102c4bde843c92c (patch)
tree4144883e824f80f4ffa1aa1509128a6371ffab4e
parented6132645a4cb5eefafe39333bc7d8d8abd2acf6 (diff)
downloadniri-9b073b2350d00dfdb32a4983a102c4bde843c92c.tar.gz
niri-9b073b2350d00dfdb32a4983a102c4bde843c92c.tar.bz2
niri-9b073b2350d00dfdb32a4983a102c4bde843c92c.zip
Redraw on demand rather than continuously
-rw-r--r--src/handlers/compositor.rs2
-rw-r--r--src/input.rs6
-rw-r--r--src/niri.rs35
-rw-r--r--src/tty.rs28
-rw-r--r--src/winit.rs17
5 files changed, 57 insertions, 31 deletions
diff --git a/src/handlers/compositor.rs b/src/handlers/compositor.rs
index b5f6291d..b2666f7f 100644
--- a/src/handlers/compositor.rs
+++ b/src/handlers/compositor.rs
@@ -41,6 +41,8 @@ impl CompositorHandler for Niri {
xdg_shell::handle_commit(&self.space, surface);
resize_grab::handle_commit(&mut self.space, surface);
+
+ self.queue_redraw();
}
}
diff --git a/src/input.rs b/src/input.rs
index 011378db..a8f85b3a 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -89,6 +89,9 @@ impl Niri {
utime: event.time(),
},
);
+
+ // Redraw to update the cursor position.
+ self.queue_redraw();
}
InputEvent::PointerMotionAbsolute { event, .. } => {
let output = self.space.outputs().next().unwrap();
@@ -112,6 +115,9 @@ impl Niri {
time: event.time_msec(),
},
);
+
+ // Redraw to update the cursor position.
+ self.queue_redraw();
}
InputEvent::PointerButton { event, .. } => {
let pointer = self.seat.get_pointer().unwrap();
diff --git a/src/niri.rs b/src/niri.rs
index 8a0d0f03..9f0d3210 100644
--- a/src/niri.rs
+++ b/src/niri.rs
@@ -12,6 +12,7 @@ use smithay::input::keyboard::XkbConfig;
use smithay::input::{Seat, SeatState};
use smithay::output::Output;
use smithay::reexports::calloop::generic::Generic;
+use smithay::reexports::calloop::timer::{TimeoutAction, Timer};
use smithay::reexports::calloop::{Interest, LoopHandle, LoopSignal, Mode, PostAction};
use smithay::reexports::wayland_server::backend::{ClientData, ClientId, DisconnectReason};
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
@@ -45,6 +46,11 @@ pub struct Niri {
pub seat: Seat<Self>,
pub output: Option<Output>,
+
+ // Set to `true` if there's a redraw queued on the event loop. Reset to `false` in redraw()
+ // which means that you cannot queue more than one redraw at once.
+ pub redraw_queued: bool,
+ pub waiting_for_vblank: bool,
}
impl Niri {
@@ -119,6 +125,8 @@ impl Niri {
seat,
output: None,
+ redraw_queued: false,
+ waiting_for_vblank: false,
}
}
@@ -135,7 +143,32 @@ impl Niri {
})
}
- pub fn redraw(&mut self, backend: &mut dyn Backend) {
+ /// Schedules an immediate redraw if one is not already scheduled.
+ pub fn queue_redraw(&mut self) {
+ if self.redraw_queued || self.waiting_for_vblank {
+ return;
+ }
+
+ self.redraw_queued = true;
+
+ self.event_loop
+ .insert_source(Timer::immediate(), |_, _, data| {
+ let backend: &mut dyn Backend = if let Some(tty) = &mut data.tty {
+ tty
+ } else {
+ data.winit.as_mut().unwrap()
+ };
+ data.niri.redraw(backend);
+ TimeoutAction::Drop
+ })
+ .unwrap();
+ }
+
+ fn redraw(&mut self, backend: &mut dyn Backend) {
+ assert!(self.redraw_queued);
+ assert!(!self.waiting_for_vblank);
+ self.redraw_queued = false;
+
let elements = space_render_elements(
backend.renderer(),
[&self.space],
diff --git a/src/tty.rs b/src/tty.rs
index b286bd36..5a81205c 100644
--- a/src/tty.rs
+++ b/src/tty.rs
@@ -1,6 +1,5 @@
use std::os::fd::FromRawFd;
use std::path::PathBuf;
-use std::time::Duration;
use anyhow::anyhow;
use smithay::backend::allocator::dmabuf::Dmabuf;
@@ -17,7 +16,6 @@ use smithay::backend::session::libseat::LibSeatSession;
use smithay::backend::session::{Event as SessionEvent, Session};
use smithay::backend::udev::{self, UdevBackend, UdevEvent};
use smithay::output::{Mode, Output, OutputModeSource, PhysicalProperties, Subpixel};
-use smithay::reexports::calloop::timer::{TimeoutAction, Timer};
use smithay::reexports::calloop::{LoopHandle, RegistrationToken};
use smithay::reexports::drm::control::connector::{
Interface as ConnectorInterface, State as ConnectorState,
@@ -83,7 +81,7 @@ impl Backend for Tty {
assert!(!res.needs_sync());
if res.damage.is_some() {
match output_device.drm_compositor.queue_frame(()) {
- Ok(()) => return,
+ Ok(()) => niri.waiting_for_vblank = true,
Err(err) => {
error!("error queueing frame: {err}");
}
@@ -95,17 +93,6 @@ impl Backend for Tty {
error!("error rendering frame: {err}");
}
}
-
- // FIXME: render on demand instead of busy looping.
- niri.event_loop
- .insert_source(
- Timer::from_duration(Duration::from_millis(6)),
- |_, _, data| {
- data.niri.redraw(data.tty.as_mut().unwrap());
- TimeoutAction::Drop
- },
- )
- .unwrap();
}
}
@@ -157,7 +144,7 @@ impl Tty {
output_device.drm_compositor.reset_buffers();
}
- niri.redraw(tty);
+ niri.queue_redraw();
}
}
})
@@ -190,7 +177,7 @@ impl Tty {
if let Err(err) = tty.device_added(device_id, path, niri) {
warn!("error adding device: {err:?}");
}
- niri.redraw(tty);
+ niri.queue_redraw();
}
UdevEvent::Changed { device_id } => tty.device_changed(device_id, niri),
UdevEvent::Removed { device_id } => tty.device_removed(device_id, niri),
@@ -198,7 +185,7 @@ impl Tty {
})
.unwrap();
- niri.redraw(self);
+ niri.queue_redraw();
}
fn device_added(
@@ -250,11 +237,8 @@ impl Tty {
// .windows
// .mark_presented(&output_device.last_render_states, metadata);
- // Request redraw before the next VBlank.
- // let frame_interval = catacomb.windows.output().frame_interval();
- // let duration = frame_interval - RENDER_TIME_OFFSET;
- // catacomb.backend.schedule_redraw(duration);
- data.niri.redraw(tty);
+ data.niri.waiting_for_vblank = false;
+ data.niri.queue_redraw();
}
DrmEvent::Error(error) => error!("DRM error: {error}"),
};
diff --git a/src/winit.rs b/src/winit.rs
index 51d86c20..458ff95a 100644
--- a/src/winit.rs
+++ b/src/winit.rs
@@ -115,16 +115,17 @@ impl Winit {
);
}
WinitEvent::Input(event) => niri.process_input_event(&mut |_| (), event),
- _ => (),
+ WinitEvent::Focus(_) => (),
+ WinitEvent::Refresh => niri.queue_redraw(),
});
- if let Err(WinitError::WindowClosed) = res {
- niri.stop_signal.stop();
- return;
- } else {
- res.unwrap();
+ // I want this to stop compiling if more errors are added.
+ #[allow(clippy::single_match)]
+ match res {
+ Err(WinitError::WindowClosed) => {
+ niri.stop_signal.stop();
+ }
+ Ok(()) => (),
}
-
- niri.redraw(self);
}
}