Skip to content

Commit

Permalink
refactor(events): improve event managers
Browse files Browse the repository at this point in the history
  • Loading branch information
eythaann committed Dec 9, 2024
1 parent 5740b1c commit 78f4816
Show file tree
Hide file tree
Showing 16 changed files with 313 additions and 294 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

### fix
- window manager not working properly.
- resolution, scale changes not refreshing the UI.

## [2.0.8]
### enhancements
Expand Down
2 changes: 1 addition & 1 deletion src/background/hook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ impl HookManager {
log_error_event("Wall Instance", wall.process_win_event(event, &window));
}

for monitor in seelen.monitors_mut() {
for monitor in seelen.instances_mut() {
if let Some(toolbar) = monitor.toolbar_mut() {
log_error_event("Toolbar Instance", toolbar.process_win_event(event, origin));
}
Expand Down
31 changes: 12 additions & 19 deletions src/background/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use seelen_core::state::WidgetId;

use crate::{
error_handler::Result,
log_error,
seelen_bar::FancyToolbar,
seelen_weg::SeelenWeg,
seelen_wm_v2::instance::WindowManagerV2,
Expand All @@ -19,9 +18,8 @@ use windows::Win32::Graphics::Gdi::HMONITOR;
#[derive(Getters, MutGetters)]
#[getset(get = "pub", get_mut = "pub")]
pub struct SeelenInstanceContainer {
handle: HMONITOR,
monitor: Monitor,
name: String,
id: String,
toolbar: Option<FancyToolbar>,
weg: Option<SeelenWeg>,
wm: Option<WindowManagerV2>,
Expand All @@ -33,13 +31,9 @@ unsafe impl Send for SeelenInstanceContainer {}

impl SeelenInstanceContainer {
pub fn new(hmonitor: HMONITOR, settings: &FullState) -> Result<Self> {
if hmonitor.is_invalid() {
return Err("Invalid Monitor".into());
}
let monitor = Monitor::from(hmonitor);
let mut instance = Self {
handle: hmonitor,
name: monitor.display_device()?.id,
id: monitor.device_id()?,
monitor,
toolbar: None,
weg: None,
Expand All @@ -51,42 +45,41 @@ impl SeelenInstanceContainer {
Ok(instance)
}

pub fn update_handle(&mut self, id: HMONITOR) {
self.handle = id;
self.monitor = Monitor::from(id);
log_error!(self.ensure_positions());
pub fn update_handle(&mut self, handle: HMONITOR) {
self.monitor = Monitor::from(handle);
}

pub fn ensure_positions(&mut self) -> Result<()> {
if let Some(bar) = &mut self.toolbar {
bar.set_position(self.handle)?;
bar.set_position(self.monitor.handle())?;
}
if let Some(weg) = &mut self.weg {
weg.set_position(self.handle)?;
weg.set_position(self.monitor.handle())?;
}
if let Some(wm) = &mut self.wm {
wm.set_position(self.handle)?;
wm.set_position(self.monitor.handle())?;
WindowManagerV2::force_retiling()?;
}
Ok(())
}

fn add_toolbar(&mut self) -> Result<()> {
if self.toolbar.is_none() {
self.toolbar = Some(FancyToolbar::new(&self.name)?);
self.toolbar = Some(FancyToolbar::new(&self.id)?);
}
Ok(())
}

fn add_weg(&mut self) -> Result<()> {
if self.weg.is_none() {
self.weg = Some(SeelenWeg::new(&self.name)?);
self.weg = Some(SeelenWeg::new(&self.id)?);
}
Ok(())
}

fn add_wm(&mut self) -> Result<()> {
if self.wm.is_none() {
self.wm = Some(WindowManagerV2::new(&self.name)?)
self.wm = Some(WindowManagerV2::new(&self.id)?)
}
Ok(())
}
Expand Down Expand Up @@ -124,6 +117,6 @@ impl SeelenInstanceContainer {

pub fn is_focused(&self) -> bool {
let hwnd = WindowsApi::get_foreground_window();
self.handle == WindowsApi::monitor_from_window(hwnd)
self.monitor.handle() == WindowsApi::monitor_from_window(hwnd)
}
}
4 changes: 2 additions & 2 deletions src/background/modules/cli/application/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,15 @@ pub fn handle_cli_events(matches: &clap::ArgMatches) -> Result<()> {
}
FancyToolbar::CLI_IDENTIFIER => {
let mut seelen = trace_lock!(SEELEN);
for monitor in seelen.monitors_mut() {
for monitor in seelen.instances_mut() {
if let Some(toolbar) = monitor.toolbar_mut() {
toolbar.process(matches)?;
}
}
}
SeelenWeg::CLI_IDENTIFIER => {
let mut seelen = trace_lock!(SEELEN);
for monitor in seelen.monitors_mut() {
for monitor in seelen.instances_mut() {
if let Some(weg) = monitor.weg_mut() {
weg.process(matches)?;
}
Expand Down
56 changes: 26 additions & 30 deletions src/background/modules/media/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ use crate::{
event_manager, log_error,
seelen_weg::icon_extractor::{extract_and_save_icon_from_file, extract_and_save_icon_umid},
trace_lock,
utils::{pcwstr, spawn_named_thread},
utils::pcwstr,
windows_api::{Com, WindowEnumerator, WindowsApi},
};

Expand All @@ -53,7 +53,7 @@ lazy_static! {

event_manager!(MediaManager, MediaEvent);

#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum MediaEvent {
DeviceAdded(String),
DeviceRemoved(String),
Expand Down Expand Up @@ -457,8 +457,8 @@ impl MediaManager {
self.update_recommended_player();
self.media_player_manager
.SessionsChanged(&self.media_player_manager_event_handler)?;

Self::start_event_loop()
Self::start_event_loop();
Ok(())
}

unsafe fn load_device(&mut self, device: &IMMDevice) -> Result<()> {
Expand Down Expand Up @@ -646,34 +646,30 @@ impl MediaManager {
}
}

fn start_event_loop() -> Result<()> {
spawn_named_thread("Media Events", || {
let rx = Self::event_rx();
while let Ok(event) = rx.recv() {
let is_changing_players = matches!(
event,
MediaEvent::MediaPlayerAdded(_)
| MediaEvent::MediaPlayerRemoved(_)
| MediaEvent::MediaPlayerPropertiesChanged { .. }
| MediaEvent::MediaPlayerPlaybackStatusChanged { .. }
);

let mut media_manager = trace_lock!(MEDIA_MANAGER);
log_error!(media_manager.process_event(event));

if is_changing_players {
media_manager.update_recommended_player();
for callback in &media_manager.registered_players_callbacks {
callback(media_manager.playing());
}
} else {
for callback in &media_manager.registered_devices_callbacks {
callback(media_manager.inputs(), media_manager.outputs());
}
fn start_event_loop() {
Self::subscribe(|event| {
let is_changing_players = matches!(
event,
MediaEvent::MediaPlayerAdded(_)
| MediaEvent::MediaPlayerRemoved(_)
| MediaEvent::MediaPlayerPropertiesChanged { .. }
| MediaEvent::MediaPlayerPlaybackStatusChanged { .. }
);

let mut media_manager = trace_lock!(MEDIA_MANAGER);
log_error!(media_manager.process_event(event));

if is_changing_players {
media_manager.update_recommended_player();
for callback in &media_manager.registered_players_callbacks {
callback(media_manager.playing());
}
} else {
for callback in &media_manager.registered_devices_callbacks {
callback(media_manager.inputs(), media_manager.outputs());
}
}
})?;
Ok(())
});
}

fn process_event(&mut self, event: MediaEvent) -> Result<()> {
Expand Down
40 changes: 37 additions & 3 deletions src/background/modules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ macro_rules! event_manager {
crossbeam_channel::Receiver<$event>,
)> = std::sync::OnceLock::new();

static CHANNEL_THREAD: std::sync::OnceLock<std::thread::JoinHandle<()>> =
std::sync::OnceLock::new();

static SUBSCRIBERS: std::sync::OnceLock<
std::sync::Arc<parking_lot::Mutex<Vec<Box<dyn FnMut($event) + Send + 'static>>>>,
> = std::sync::OnceLock::new();

impl $name {
pub fn channel() -> &'static (
fn channel() -> &'static (
crossbeam_channel::Sender<$event>,
crossbeam_channel::Receiver<$event>,
) {
Expand All @@ -30,8 +37,35 @@ macro_rules! event_manager {
Self::channel().0.clone()
}

pub fn event_rx() -> crossbeam_channel::Receiver<$event> {
Self::channel().1.clone()
fn subscribers() -> &'static std::sync::Arc<
parking_lot::Mutex<Vec<Box<dyn FnMut($event) + Send + 'static>>>,
> {
SUBSCRIBERS.get_or_init(|| std::sync::Arc::new(parking_lot::Mutex::new(Vec::new())))
}

/// Add a new subscriber to the event manager and start the event processing thread
pub fn subscribe<F>(callback: F)
where
F: FnMut($event) + Send + 'static,
{
let mut subs = Self::subscribers().lock();
subs.push(Box::new(callback));
if subs.len() != 1 {
return;
}
// Start the event processing thread on the first subscriber
CHANNEL_THREAD.get_or_init(|| {
let rx = Self::channel().1.clone();
let subscribers = Self::subscribers().clone();
std::thread::spawn(move || {
for event in rx {
let mut subs = subscribers.lock();
for subscriber in subs.iter_mut() {
subscriber(event.clone());
}
}
})
});
}
}
};
Expand Down
Loading

0 comments on commit 78f4816

Please sign in to comment.