1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use bevy::ecs::message::Message;
use objc2::rc::Retained;
use objc2_core_foundation::{CFRetained, CGPoint};
use objc2_core_graphics::CGDirectDisplayID;
use std::sync::mpsc::{Receiver, Sender, channel};
use crate::commands::Command;
use crate::config::Config;
use crate::errors::Result;
use crate::platform::{ProcessSerialNumber, WinID, WorkspaceId, WorkspaceObserver};
use crate::util::AXUIWrapper;
/// `Event` represents various system-level and application-specific occurrences that the window manager reacts to.
/// These events drive the core logic of the window manager, from window creation to display changes.
#[allow(dead_code)]
#[derive(Clone, Debug, Message)]
pub enum Event {
/// Signals the application to exit.
Exit,
/// Indicates that the initial set of processes has been loaded.
ProcessesLoaded,
/// Announces the initialy loaded configuration
InitialConfig(Config),
/// Signals that the configuration should be reloaded.
ConfigRefresh(notify::Event),
/// An application has been launched.
ApplicationLaunched {
psn: ProcessSerialNumber,
observer: Retained<WorkspaceObserver>,
},
/// An application has terminated.
ApplicationTerminated { psn: ProcessSerialNumber },
/// The frontmost application has switched.
ApplicationFrontSwitched { psn: ProcessSerialNumber },
/// The application has been activated.
ApplicationActivated,
/// The application has been deactivated.
ApplicationDeactivated,
/// An application has become visible.
ApplicationVisible { pid: i32 },
/// An application has become hidden.
ApplicationHidden { pid: i32 },
/// A window has been created.
WindowCreated { element: CFRetained<AXUIWrapper> },
/// A window has been destroyed.
WindowDestroyed { window_id: WinID },
/// A window has gained focus.
WindowFocused { window_id: WinID },
/// A window has been moved.
WindowMoved { window_id: WinID },
/// A window has been resized.
WindowResized { window_id: WinID },
/// A window has been minimized.
WindowMinimized { window_id: WinID },
/// A window has been de-minimized (restored).
WindowDeminimized { window_id: WinID },
/// A window's title has changed.
WindowTitleChanged { window_id: WinID },
/// A mouse down event has occurred.
MouseDown { point: CGPoint },
/// A mouse up event has occurred.
MouseUp { point: CGPoint },
/// A mouse drag event has occurred.
MouseDragged { point: CGPoint },
/// A mouse move event has occurred.
MouseMoved { point: CGPoint },
/// A swipe gesture has been detected.
Swipe { deltas: Vec<f64> },
/// A vertical trackpad gesture (accumulates delta to threshold before firing).
VerticalSwipe { delta: f64 },
/// A single scroll wheel tick for vertical workspace switching (fires immediately).
VerticalScrollTick { delta: f64 },
/// A mouse scroll has been detected.
Scroll { delta: f64 },
/// A new space (virtual desktop) has been created.
SpaceCreated { space_id: WorkspaceId },
/// A space has been destroyed.
SpaceDestroyed { space_id: WorkspaceId },
/// The active space has changed.
SpaceChanged,
/// A new display has been added.
DisplayAdded { display_id: CGDirectDisplayID },
/// A display has been removed.
DisplayRemoved { display_id: CGDirectDisplayID },
/// A display has been moved.
DisplayMoved { display_id: CGDirectDisplayID },
/// A display has been resized.
DisplayResized { display_id: CGDirectDisplayID },
/// A display's configuration has changed.
DisplayConfigured { display_id: CGDirectDisplayID },
/// The overall display arrangement has changed.
DisplayChanged,
/// Mission Control: Show all windows.
MissionControlShowAllWindows,
/// Mission Control: Show frontmost application windows.
MissionControlShowFrontWindows,
/// Mission Control: Show desktop.
MissionControlShowDesktop,
/// Mission Control: Exit.
MissionControlExit,
/// Dock preferences have changed.
DockDidChangePref { msg: String },
/// The Dock has restarted.
DockDidRestart { msg: String },
/// A menu has been opened.
MenuOpened { window_id: WinID },
/// A menu has been closed.
MenuClosed { window_id: WinID },
/// The visibility of the menu bar has changed.
MenuBarHiddenChanged { msg: String },
/// The system has woken from sleep.
SystemWoke { msg: String },
/// The system appearance (Light/Dark mode) has changed.
ThemeChanged,
/// A command has been issued to the window manager.
Command { command: Command },
}
/// `EventSender` is a thin wrapper around a `std::sync::mpsc::Sender` for `Event`s.
/// It provides a convenient way to send events to the main event loop from various parts of the application.
#[derive(Clone, Debug)]
pub struct EventSender {
tx: Sender<Event>,
}
impl EventSender {
/// Creates a new `EventSender` and its corresponding `Receiver`.
/// This function initializes an MPSC channel.
///
/// # Returns
///
/// A tuple containing the `EventSender` and `Receiver` for the created channel.
pub fn new() -> (Self, Receiver<Event>) {
let (tx, rx) = channel::<Event>();
(Self { tx }, rx)
}
/// Sends an `Event` through the internal channel.
///
/// # Arguments
///
/// * `event` - The `Event` to send.
///
/// # Returns
///
/// `Ok(())` if the event is sent successfully, otherwise `Err(Error)` if the receiver has disconnected.
pub fn send(&self, event: Event) -> Result<()> {
Ok(self.tx.send(event)?)
}
}