Skip to content

Commit

Permalink
fix(monitors): fix app crashing on connecting a monitor
Browse files Browse the repository at this point in the history
  • Loading branch information
eythaann committed Oct 9, 2024
1 parent ec758ea commit f26e26c
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 40 deletions.
1 change: 1 addition & 0 deletions lib/src/handlers/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export enum SeelenEvent {

GlobalFocusChanged = 'global-focus-changed',
GlobalMouseMove = 'global-mouse-move',
GlobalMonitorsChanged = 'global-monitors-changed',

HandleLayeredHitboxes = 'handle-layered',

Expand Down
2 changes: 2 additions & 0 deletions lib/src/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ impl SeelenEvent {

pub const GlobalFocusChanged: &str = "global-focus-changed";
pub const GlobalMouseMove: &str = "global-mouse-move";
pub const GlobalMonitorsChanged: &str = "global-monitors-changed";


pub const HandleLayeredHitboxes: &str = "handle-layered";

Expand Down
2 changes: 2 additions & 0 deletions src/apps/seelen_wall/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export function App() {
const [currentBg, setCurrentBg] = useState(0);
const [scope, animate] = useAnimate<HTMLDivElement>();

const version = useSelector(Selectors.version);
const { backgrounds, interval } = useSelector(Selectors.settings);

useInterval(() => {
Expand All @@ -32,6 +33,7 @@ export function App() {
}
return (
<Wallpaper
key={version}
path={background.path}
containerRef={scope}
onLoad={() => {
Expand Down
1 change: 1 addition & 0 deletions src/apps/seelen_wall/modules/shared/store/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { RootState } from './domain';
import { StateBuilder } from '../../../../shared/StateBuilder';

const initialState: RootState = {
version: 0,
settings: new SeelenWallSettings(),
colors: UIColors.default(),
stop: false,
Expand Down
1 change: 1 addition & 0 deletions src/apps/seelen_wall/modules/shared/store/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { IRootState } from 'src/shared.interfaces';

export interface RootState extends IRootState<SeelenWallSettings> {
stop: boolean;
version: number;
}
5 changes: 5 additions & 0 deletions src/apps/seelen_wall/modules/shared/store/infra.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@ export async function initStore() {
store.dispatch(Actions.setStop(payload));
});

webview.listen(SeelenEvent.GlobalMonitorsChanged, () => {
let version = store.getState().version;
store.dispatch(Actions.setVersion(version + 1));
});

StartThemingTool();
}
63 changes: 30 additions & 33 deletions src/background/modules/monitors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use windows::{

use crate::{
error_handler::Result,
trace_lock,
log_error, trace_lock,
utils::spawn_named_thread,
windows_api::{MonitorEnumerator, WindowsApi},
};
Expand All @@ -39,31 +39,30 @@ pub enum MonitorManagerEvent {
type OnMonitorsChange = Box<dyn Fn(MonitorManagerEvent) + Send + Sync>;

pub struct MonitorManager {
_hwnd: HWND,
pub monitors: Vec<(String, HMONITOR)>,
callbacks: Vec<OnMonitorsChange>,
}

unsafe impl Send for MonitorManager {}

impl MonitorManager {
pub extern "system" fn window_proc(
unsafe extern "system" fn window_proc(
window: HWND,
message: u32,
wparam: WPARAM,
lparam: LPARAM,
) -> LRESULT {
unsafe {
match message {
// Added based on this https://stackoverflow.com/a/33762334
WM_DISPLAYCHANGE | WM_SETTINGCHANGE | WM_DEVICECHANGE => {
// log::debug!("Dispatching {}, {:?}, {:?}", message, wparam, lparam);
match message {
// Added based on this https://stackoverflow.com/a/33762334
WM_DISPLAYCHANGE | WM_SETTINGCHANGE | WM_DEVICECHANGE => {
// log::debug!("Dispatching {}, {:?}, {:?}", message, wparam, lparam);
std::thread::spawn(move || {
let mut manager = trace_lock!(MONITOR_MANAGER);

let mut old_list = manager.monitors.clone();
let new_list = match Self::get_monitors() {
Ok(monitors) => monitors,
Err(_) => return LRESULT(0),
Err(_) => return,
};

for (name, id) in &new_list {
Expand All @@ -89,14 +88,14 @@ impl MonitorManager {
}

manager.monitors = new_list.into_iter().collect();
LRESULT(0)
}
_ => DefWindowProcW(window, message, wparam, lparam),
});
LRESULT(0)
}
_ => DefWindowProcW(window, message, wparam, lparam),
}
}

pub fn new() -> Result<Self> {
unsafe fn create_background_window() -> Result<()> {
let wide_name: Vec<u16> = "Seelen Monitor Manager"
.encode_utf16()
.chain(Some(0))
Expand All @@ -115,9 +114,7 @@ impl MonitorManager {
..Default::default()
};

unsafe {
RegisterClassW(&wnd_class);
}
RegisterClassW(&wnd_class);

let hwnd = unsafe {
CreateWindowExW(
Expand All @@ -144,27 +141,27 @@ impl MonitorManager {
dbcc_name: [0; 1],
};

unsafe {
RegisterDeviceNotificationW(
hwnd,
&mut notification_filter as *mut _ as *mut _,
DEVICE_NOTIFY_WINDOW_HANDLE,
)?
};
RegisterDeviceNotificationW(
hwnd,
&mut notification_filter as *mut _ as *mut _,
DEVICE_NOTIFY_WINDOW_HANDLE,
)?;

let addr = hwnd.0 as isize;
spawn_named_thread("Monitor Manager Message Loop", move || unsafe {
let mut msg = MSG::default();
let hwnd = HWND(addr as _);
while GetMessageW(&mut msg, hwnd, 0, 0).into() {
let _ = TranslateMessage(&msg);
DispatchMessageW(&msg);
std::thread::sleep(std::time::Duration::from_millis(10));
}
let mut msg = MSG::default();
while GetMessageW(&mut msg, hwnd, 0, 0).as_bool() {
let _ = TranslateMessage(&msg);
DispatchMessageW(&msg);
}

Ok(())
}

pub fn new() -> Result<Self> {
spawn_named_thread("Monitor Manager", || unsafe {
log_error!(Self::create_background_window());
})?;

Ok(Self {
_hwnd: hwnd,
callbacks: Vec::new(),
monitors: Self::get_monitors()?,
})
Expand Down
18 changes: 11 additions & 7 deletions src/background/seelen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use std::{
use getset::{Getters, MutGetters};
use lazy_static::lazy_static;
use parking_lot::Mutex;
use tauri::{path::BaseDirectory, AppHandle, Manager, Wry};
use seelen_core::handlers::SeelenEvent;
use tauri::{path::BaseDirectory, AppHandle, Emitter, Manager, Wry};
use tauri_plugin_shell::ShellExt;
use windows::Win32::Graphics::Gdi::HMONITOR;

Expand Down Expand Up @@ -103,7 +104,9 @@ impl Seelen {
wall.update_position()?;
}
for monitor in &mut self.monitors {
monitor.ensure_positions()?;
if WindowsApi::monitor_info(*monitor.handle()).is_ok() {
monitor.ensure_positions()?;
}
}
Ok(())
}
Expand Down Expand Up @@ -159,21 +162,20 @@ impl Seelen {
}

fn on_monitor_event(event: MonitorManagerEvent) {
log::trace!("Monitor event: {:?}", event);
let mut seelen = trace_lock!(SEELEN);
match event {
MonitorManagerEvent::Added(_name, id) => {
log_error!(seelen.add_monitor(id));
log_error!(trace_lock!(SEELEN).add_monitor(id));
}
MonitorManagerEvent::Removed(_name, id) => {
log_error!(seelen.remove_monitor(id));
log_error!(trace_lock!(SEELEN).remove_monitor(id));
}
MonitorManagerEvent::Updated(name, id) => {
if let Some(m) = seelen.monitor_by_name_mut(&name) {
if let Some(m) = trace_lock!(SEELEN).monitor_by_name_mut(&name) {
m.update_handle(id);
}
}
}
log_error!(get_app_handle().emit(SeelenEvent::GlobalMonitorsChanged, ()));
}

async fn start_async() -> Result<()> {
Expand Down Expand Up @@ -240,11 +242,13 @@ impl Seelen {
fn add_monitor(&mut self, hmonitor: HMONITOR) -> Result<()> {
self.monitors
.push(SeelenInstanceContainer::new(hmonitor, &self.state())?);
self.refresh_windows_positions()?;
Ok(())
}

fn remove_monitor(&mut self, hmonitor: HMONITOR) -> Result<()> {
self.monitors.retain(|m| m.handle() != &hmonitor);
self.refresh_windows_positions()?;
Ok(())
}

Expand Down

0 comments on commit f26e26c

Please sign in to comment.