aboutsummaryrefslogtreecommitdiff
path: root/helix-event
diff options
context:
space:
mode:
Diffstat (limited to 'helix-event')
-rw-r--r--helix-event/Cargo.toml15
-rw-r--r--helix-event/src/lib.rs8
-rw-r--r--helix-event/src/redraw.rs49
3 files changed, 72 insertions, 0 deletions
diff --git a/helix-event/Cargo.toml b/helix-event/Cargo.toml
new file mode 100644
index 00000000..5cd95558
--- /dev/null
+++ b/helix-event/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "helix-event"
+version = "0.6.0"
+authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
+edition = "2021"
+license = "MPL-2.0"
+categories = ["editor"]
+repository = "https://github.com/helix-editor/helix"
+homepage = "https://helix-editor.com"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "parking_lot"] }
+parking_lot = { version = "0.12", features = ["send_guard"] }
diff --git a/helix-event/src/lib.rs b/helix-event/src/lib.rs
new file mode 100644
index 00000000..9c082b93
--- /dev/null
+++ b/helix-event/src/lib.rs
@@ -0,0 +1,8 @@
+//! `helix-event` contains systems that allow (often async) communication between
+//! different editor components without strongly coupling them. Currently this
+//! crate only contains some smaller facilities but the intend is to add more
+//! functionality in the future ( like a generic hook system)
+
+pub use redraw::{lock_frame, redraw_requested, request_redraw, start_frame, RenderLockGuard};
+
+mod redraw;
diff --git a/helix-event/src/redraw.rs b/helix-event/src/redraw.rs
new file mode 100644
index 00000000..a9915223
--- /dev/null
+++ b/helix-event/src/redraw.rs
@@ -0,0 +1,49 @@
+//! Signals that control when/if the editor redraws
+
+use std::future::Future;
+
+use parking_lot::{RwLock, RwLockReadGuard};
+use tokio::sync::Notify;
+
+/// A `Notify` instance that can be used to (asynchronously) request
+/// the editor the render a new frame.
+static REDRAW_NOTIFY: Notify = Notify::const_new();
+
+/// A `RwLock` that prevents the next frame from being
+/// drawn until an exclusive (write) lock can be acquired.
+/// This allows asynchsonous tasks to acquire `non-exclusive`
+/// locks (read) to prevent the next frame from being drawn
+/// until a certain computation has finished.
+static RENDER_LOCK: RwLock<()> = RwLock::new(());
+
+pub type RenderLockGuard = RwLockReadGuard<'static, ()>;
+
+/// Requests that the editor is redrawn. The redraws are debounced (currently to
+/// 30FPS) so this can be called many times without causing a ton of frames to
+/// be rendered.
+pub fn request_redraw() {
+ REDRAW_NOTIFY.notify_one();
+}
+
+/// Returns a future that will yield once a redraw has been asynchronously
+/// requested using [`request_redraw`].
+pub fn redraw_requested() -> impl Future<Output = ()> {
+ REDRAW_NOTIFY.notified()
+}
+
+/// Wait until all locks acquired with [`lock_frame`] have been released.
+/// This function is called before rendering and is intended to allow the frame
+/// to wait for async computations that should be included in the current frame.
+pub fn start_frame() {
+ drop(RENDER_LOCK.write());
+ // exhaust any leftover redraw notifications
+ let notify = REDRAW_NOTIFY.notified();
+ tokio::pin!(notify);
+ notify.enable();
+}
+
+/// Acquires the render lock which will prevent the next frame from being drawn
+/// until the returned guard is dropped.
+pub fn lock_frame() -> RenderLockGuard {
+ RENDER_LOCK.read()
+}