From 5cc38da61d91966b2f2b2b16bca54e72db412815 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Fri, 30 Oct 2026 22:26:45 -0700 Subject: [PATCH] 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 (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). --- komorebi-for-mac/Cargo.lock | 1 + .../src/window_manager_event_listener.rs | 91 +++---------------- 2 files changed, 16 insertions(+), 76 deletions(-) diff --git a/komorebi-for-mac/Cargo.lock b/komorebi-for-mac/Cargo.lock index ecf125b5..9274a9c8 100644 --- a/komorebi-for-mac/Cargo.lock +++ b/komorebi-for-mac/Cargo.lock @@ -3311,6 +3311,7 @@ name = "komorebi-transport" version = "0.1.42" dependencies = [ "color-eyre", + "crossbeam-channel", "komorebi-protocol", "tracing", "uds_windows", diff --git a/komorebi-for-mac/komorebi/src/window_manager_event_listener.rs b/komorebi-for-mac/komorebi/src/window_manager_event_listener.rs index 3e1a8f2f..dcfef4a2 100644 --- a/komorebi-for-mac/komorebi/src/window_manager_event_listener.rs +++ b/komorebi-for-mac/komorebi/src/window_manager_event_listener.rs @@ -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, Receiver)> = - OnceLock::new(); +static CHANNEL: OnceLock> = 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, Receiver) { - CHANNEL.get_or_init(|| crossbeam_channel::bounded(20)) -} - -fn event_tx() -> Sender { - channel().0.clone() +fn channel() -> &'static EventChannel { + // 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 { - 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); }