mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-07-09 22:52:51 +02:00
feat(wm): notify subscribers of monitor events
This commit allows notifying the subscribers of any monitor events like display connection change or work area change.
This commit is contained in:
@@ -34,6 +34,7 @@ pub use komorebi::core::StackbarMode;
|
|||||||
pub use komorebi::core::StateQuery;
|
pub use komorebi::core::StateQuery;
|
||||||
pub use komorebi::core::WindowKind;
|
pub use komorebi::core::WindowKind;
|
||||||
pub use komorebi::monitor::Monitor;
|
pub use komorebi::monitor::Monitor;
|
||||||
|
pub use komorebi::monitor_reconciliator::MonitorNotification;
|
||||||
pub use komorebi::ring::Ring;
|
pub use komorebi::ring::Ring;
|
||||||
pub use komorebi::window::Window;
|
pub use komorebi::window::Window;
|
||||||
pub use komorebi::window_manager_event::WindowManagerEvent;
|
pub use komorebi::window_manager_event::WindowManagerEvent;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ pub mod workspace;
|
|||||||
pub mod workspace_reconciliator;
|
pub mod workspace_reconciliator;
|
||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
use monitor_reconciliator::MonitorNotification;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -283,6 +284,7 @@ pub fn current_virtual_desktop() -> Option<Vec<u8>> {
|
|||||||
pub enum NotificationEvent {
|
pub enum NotificationEvent {
|
||||||
WindowManager(WindowManagerEvent),
|
WindowManager(WindowManagerEvent),
|
||||||
Socket(SocketMessage),
|
Socket(SocketMessage),
|
||||||
|
Monitor(MonitorNotification),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ impl Hidden {
|
|||||||
"WM_POWERBROADCAST event received - resume from suspend"
|
"WM_POWERBROADCAST event received - resume from suspend"
|
||||||
);
|
);
|
||||||
monitor_reconciliator::send_notification(
|
monitor_reconciliator::send_notification(
|
||||||
monitor_reconciliator::Notification::ResumingFromSuspendedState,
|
monitor_reconciliator::MonitorNotification::ResumingFromSuspendedState,
|
||||||
);
|
);
|
||||||
LRESULT(0)
|
LRESULT(0)
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ impl Hidden {
|
|||||||
"WM_POWERBROADCAST event received - entering suspended state"
|
"WM_POWERBROADCAST event received - entering suspended state"
|
||||||
);
|
);
|
||||||
monitor_reconciliator::send_notification(
|
monitor_reconciliator::send_notification(
|
||||||
monitor_reconciliator::Notification::EnteringSuspendedState,
|
monitor_reconciliator::MonitorNotification::EnteringSuspendedState,
|
||||||
);
|
);
|
||||||
LRESULT(0)
|
LRESULT(0)
|
||||||
}
|
}
|
||||||
@@ -137,14 +137,14 @@ impl Hidden {
|
|||||||
tracing::debug!("WM_WTSSESSION_CHANGE event received with WTS_SESSION_LOCK - screen locked");
|
tracing::debug!("WM_WTSSESSION_CHANGE event received with WTS_SESSION_LOCK - screen locked");
|
||||||
|
|
||||||
monitor_reconciliator::send_notification(
|
monitor_reconciliator::send_notification(
|
||||||
monitor_reconciliator::Notification::SessionLocked,
|
monitor_reconciliator::MonitorNotification::SessionLocked,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
WTS_SESSION_UNLOCK => {
|
WTS_SESSION_UNLOCK => {
|
||||||
tracing::debug!("WM_WTSSESSION_CHANGE event received with WTS_SESSION_UNLOCK - screen unlocked");
|
tracing::debug!("WM_WTSSESSION_CHANGE event received with WTS_SESSION_UNLOCK - screen unlocked");
|
||||||
|
|
||||||
monitor_reconciliator::send_notification(
|
monitor_reconciliator::send_notification(
|
||||||
monitor_reconciliator::Notification::SessionUnlocked,
|
monitor_reconciliator::MonitorNotification::SessionUnlocked,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -165,7 +165,7 @@ impl Hidden {
|
|||||||
);
|
);
|
||||||
|
|
||||||
monitor_reconciliator::send_notification(
|
monitor_reconciliator::send_notification(
|
||||||
monitor_reconciliator::Notification::ResolutionScalingChanged,
|
monitor_reconciliator::MonitorNotification::ResolutionScalingChanged,
|
||||||
);
|
);
|
||||||
LRESULT(0)
|
LRESULT(0)
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ impl Hidden {
|
|||||||
);
|
);
|
||||||
|
|
||||||
monitor_reconciliator::send_notification(
|
monitor_reconciliator::send_notification(
|
||||||
monitor_reconciliator::Notification::WorkAreaChanged,
|
monitor_reconciliator::MonitorNotification::WorkAreaChanged,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
LRESULT(0)
|
LRESULT(0)
|
||||||
@@ -193,7 +193,7 @@ impl Hidden {
|
|||||||
"WM_DEVICECHANGE event received with DBT_DEVNODES_CHANGED - display added or removed"
|
"WM_DEVICECHANGE event received with DBT_DEVNODES_CHANGED - display added or removed"
|
||||||
);
|
);
|
||||||
monitor_reconciliator::send_notification(
|
monitor_reconciliator::send_notification(
|
||||||
monitor_reconciliator::Notification::DisplayConnectionChange,
|
monitor_reconciliator::MonitorNotification::DisplayConnectionChange,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,13 +5,20 @@ use crate::core::Rect;
|
|||||||
use crate::monitor;
|
use crate::monitor;
|
||||||
use crate::monitor::Monitor;
|
use crate::monitor::Monitor;
|
||||||
use crate::monitor_reconciliator::hidden::Hidden;
|
use crate::monitor_reconciliator::hidden::Hidden;
|
||||||
|
use crate::notify_subscribers;
|
||||||
use crate::MonitorConfig;
|
use crate::MonitorConfig;
|
||||||
|
use crate::Notification;
|
||||||
|
use crate::NotificationEvent;
|
||||||
|
use crate::State;
|
||||||
use crate::WindowManager;
|
use crate::WindowManager;
|
||||||
use crate::WindowsApi;
|
use crate::WindowsApi;
|
||||||
use crossbeam_channel::Receiver;
|
use crossbeam_channel::Receiver;
|
||||||
use crossbeam_channel::Sender;
|
use crossbeam_channel::Sender;
|
||||||
use crossbeam_utils::atomic::AtomicConsume;
|
use crossbeam_utils::atomic::AtomicConsume;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::Serialize;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
@@ -20,7 +27,9 @@ use std::sync::OnceLock;
|
|||||||
|
|
||||||
pub mod hidden;
|
pub mod hidden;
|
||||||
|
|
||||||
pub enum Notification {
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize, JsonSchema)]
|
||||||
|
#[serde(tag = "type", content = "content")]
|
||||||
|
pub enum MonitorNotification {
|
||||||
ResolutionScalingChanged,
|
ResolutionScalingChanged,
|
||||||
WorkAreaChanged,
|
WorkAreaChanged,
|
||||||
DisplayConnectionChange,
|
DisplayConnectionChange,
|
||||||
@@ -32,23 +41,24 @@ pub enum Notification {
|
|||||||
|
|
||||||
static ACTIVE: AtomicBool = AtomicBool::new(true);
|
static ACTIVE: AtomicBool = AtomicBool::new(true);
|
||||||
|
|
||||||
static CHANNEL: OnceLock<(Sender<Notification>, Receiver<Notification>)> = OnceLock::new();
|
static CHANNEL: OnceLock<(Sender<MonitorNotification>, Receiver<MonitorNotification>)> =
|
||||||
|
OnceLock::new();
|
||||||
|
|
||||||
static MONITOR_CACHE: OnceLock<Mutex<HashMap<String, MonitorConfig>>> = OnceLock::new();
|
static MONITOR_CACHE: OnceLock<Mutex<HashMap<String, MonitorConfig>>> = OnceLock::new();
|
||||||
|
|
||||||
pub fn channel() -> &'static (Sender<Notification>, Receiver<Notification>) {
|
pub fn channel() -> &'static (Sender<MonitorNotification>, Receiver<MonitorNotification>) {
|
||||||
CHANNEL.get_or_init(|| crossbeam_channel::bounded(1))
|
CHANNEL.get_or_init(|| crossbeam_channel::bounded(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event_tx() -> Sender<Notification> {
|
fn event_tx() -> Sender<MonitorNotification> {
|
||||||
channel().0.clone()
|
channel().0.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event_rx() -> Receiver<Notification> {
|
fn event_rx() -> Receiver<MonitorNotification> {
|
||||||
channel().1.clone()
|
channel().1.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_notification(notification: Notification) {
|
pub fn send_notification(notification: MonitorNotification) {
|
||||||
if event_tx().try_send(notification).is_err() {
|
if event_tx().try_send(notification).is_err() {
|
||||||
tracing::warn!("channel is full; dropping notification")
|
tracing::warn!("channel is full; dropping notification")
|
||||||
}
|
}
|
||||||
@@ -125,7 +135,8 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
|||||||
if !ACTIVE.load_consume() {
|
if !ACTIVE.load_consume() {
|
||||||
if matches!(
|
if matches!(
|
||||||
notification,
|
notification,
|
||||||
Notification::ResumingFromSuspendedState | Notification::SessionUnlocked
|
MonitorNotification::ResumingFromSuspendedState
|
||||||
|
| MonitorNotification::SessionUnlocked
|
||||||
) {
|
) {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"reactivating reconciliator - system has resumed from suspended state or session has been unlocked"
|
"reactivating reconciliator - system has resumed from suspended state or session has been unlocked"
|
||||||
@@ -140,17 +151,20 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
|||||||
|
|
||||||
let mut wm = wm.lock();
|
let mut wm = wm.lock();
|
||||||
|
|
||||||
|
let initial_state = State::from(wm.as_ref());
|
||||||
|
|
||||||
match notification {
|
match notification {
|
||||||
Notification::EnteringSuspendedState | Notification::SessionLocked => {
|
MonitorNotification::EnteringSuspendedState | MonitorNotification::SessionLocked => {
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"deactivating reconciliator until system resumes from suspended state or session is unlocked"
|
"deactivating reconciliator until system resumes from suspended state or session is unlocked"
|
||||||
);
|
);
|
||||||
ACTIVE.store(false, Ordering::SeqCst);
|
ACTIVE.store(false, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
Notification::ResumingFromSuspendedState | Notification::SessionUnlocked => {
|
MonitorNotification::ResumingFromSuspendedState
|
||||||
|
| MonitorNotification::SessionUnlocked => {
|
||||||
// this is only handled above if the reconciliator is paused
|
// this is only handled above if the reconciliator is paused
|
||||||
}
|
}
|
||||||
Notification::WorkAreaChanged => {
|
MonitorNotification::WorkAreaChanged => {
|
||||||
tracing::debug!("handling work area changed notification");
|
tracing::debug!("handling work area changed notification");
|
||||||
let offset = wm.work_area_offset;
|
let offset = wm.work_area_offset;
|
||||||
for monitor in wm.monitors_mut() {
|
for monitor in wm.monitors_mut() {
|
||||||
@@ -182,7 +196,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Notification::ResolutionScalingChanged => {
|
MonitorNotification::ResolutionScalingChanged => {
|
||||||
tracing::debug!("handling resolution/scaling changed notification");
|
tracing::debug!("handling resolution/scaling changed notification");
|
||||||
let offset = wm.work_area_offset;
|
let offset = wm.work_area_offset;
|
||||||
for monitor in wm.monitors_mut() {
|
for monitor in wm.monitors_mut() {
|
||||||
@@ -229,7 +243,7 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Notification::DisplayConnectionChange => {
|
MonitorNotification::DisplayConnectionChange => {
|
||||||
tracing::debug!("handling display connection change notification");
|
tracing::debug!("handling display connection change notification");
|
||||||
let mut monitor_cache = MONITOR_CACHE
|
let mut monitor_cache = MONITOR_CACHE
|
||||||
.get_or_init(|| Mutex::new(HashMap::new()))
|
.get_or_init(|| Mutex::new(HashMap::new()))
|
||||||
@@ -411,6 +425,14 @@ pub fn handle_notifications(wm: Arc<Mutex<WindowManager>>) -> color_eyre::Result
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notify_subscribers(
|
||||||
|
Notification {
|
||||||
|
event: NotificationEvent::Monitor(notification),
|
||||||
|
state: wm.as_ref().into(),
|
||||||
|
},
|
||||||
|
initial_state.has_been_modified(&wm),
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user