refactor(mac): use EventChannel for the window events

Same change as the KDE revision: the OnceLock channel, the try_send with the drop warning and the ResizeStep claim/release flag in window_manager_event_listener.rs are now a komorebi_transport::EventChannel<WindowManagerEvent> (capacity 20, predicate matches!(.., ResizeStep(_, _, _))), behind the same three functions. The overflow flag exists and nothing reads it. The macOS keeps its early resize_step_taken call in process_event.rs untouched. The three macOS unit tests of the coalescing (claim/release helpers) moved to the transport crate as tests of EventChannel (D23); the helper functions they tested no longer exist here. The Cargo.lock of the macOS workspace gets the crossbeam-channel dependency of the transport crate. Logs use the target komorebi::transport (D29).

Verified: macOS fake-CC cargo check --locked --target aarch64-apple-darwin --workspace --all-targets: 0 errors. macOS unit tests cannot run on Linux (the 3 moved tests run in the transport crate).
This commit is contained in:
LGUG2Z committed 2026-10-31 01:37:54 -07:00
1 parent 36ed4b9b29
commit 5cc38da61d
2 files changed
+16 -76

No files matched your search

+1
View File
@@ -3311,6 +3311,7 @@ name = "komorebi-transport"
version = "0.1.42"
dependencies = [
"color-eyre",
"crossbeam-channel",
"komorebi-protocol",
"tracing",
"uds_windows",
@@ -1,39 +1,24 @@
use crate::window_manager_event::WindowManagerEvent;
use crossbeam_channel::Receiver;
use crossbeam_channel::Sender;
use komorebi_transport::EventChannel;
use std::sync::OnceLock;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering;
static CHANNEL: OnceLock<(Sender<WindowManagerEvent>, Receiver<WindowManagerEvent>)> =
OnceLock::new();
static CHANNEL: OnceLock<EventChannel<WindowManagerEvent>> = OnceLock::new();
/// Whether a step of a drag is waiting in the channel for the window manager to take it
static RESIZE_STEP_WAITING: AtomicBool = AtomicBool::new(false);
fn channel() -> &'static (Sender<WindowManagerEvent>, Receiver<WindowManagerEvent>) {
CHANNEL.get_or_init(|| crossbeam_channel::bounded(20))
}
fn event_tx() -> Sender<WindowManagerEvent> {
channel().0.clone()
fn channel() -> &'static EventChannel<WindowManagerEvent> {
// A step of a drag is only a signal that the window has moved, and what is done about it is to
// look at where the window is, which is the newest of what any number of them would have said.
// So one that waits is enough, and the channel is not filled with the ones that come faster
// than they are handled.
CHANNEL.get_or_init(|| {
EventChannel::coalescing(20, |event| {
matches!(event, WindowManagerEvent::ResizeStep(_, _, _))
})
})
}
pub fn event_rx() -> Receiver<WindowManagerEvent> {
channel().1.clone()
}
/// Whether a step of a drag may be sent, which it may if none is waiting. Says that one is.
///
/// A step is only a signal that the window has moved, and what is done about it is to look at where
/// the window is, which is the newest of what any number of them would have said. So one that waits
/// is enough, and the channel is not filled with the ones that come faster than they are handled.
fn claim_resize_step(waiting: &AtomicBool) -> bool {
!waiting.swap(true, Ordering::AcqRel)
}
fn release_resize_step(waiting: &AtomicBool) {
waiting.store(false, Ordering::Release);
channel().receiver()
}
/// Say that a step of a drag is being taken, so the next one that comes is let through.
@@ -41,55 +26,9 @@ fn release_resize_step(waiting: &AtomicBool) {
/// This is for the start of a step and not the end of it: one that comes while a step is being
/// taken waits for the next, and the last frame of a drag is never lost.
pub fn resize_step_taken() {
release_resize_step(&RESIZE_STEP_WAITING);
channel().coalesced_taken();
}
pub fn send_notification(notification: WindowManagerEvent) {
let is_step = matches!(notification, WindowManagerEvent::ResizeStep(_, _, _));
if is_step && !claim_resize_step(&RESIZE_STEP_WAITING) {
return;
}
if event_tx().try_send(notification).is_err() {
// there is nothing in the channel for a step that was not sent to wait for
if is_step {
resize_step_taken();
}
tracing::warn!("channel is full; dropping notification")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_step_is_let_through_when_none_is_waiting() {
let waiting = AtomicBool::new(false);
assert!(claim_resize_step(&waiting));
}
#[test]
fn only_one_step_waits_however_many_come() {
let waiting = AtomicBool::new(false);
assert!(claim_resize_step(&waiting));
assert!(!claim_resize_step(&waiting));
assert!(!claim_resize_step(&waiting));
}
#[test]
fn a_step_that_comes_while_one_is_being_taken_is_let_through_for_after() {
let waiting = AtomicBool::new(false);
assert!(claim_resize_step(&waiting));
// the handler says that it has begun, and what comes after is the next one
release_resize_step(&waiting);
assert!(claim_resize_step(&waiting));
assert!(!claim_resize_step(&waiting));
}
channel().send(notification);
}