mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-04-25 01:58:51 +02:00
think this still leaves us with inconsistent state
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -794,6 +794,7 @@ dependencies = [
|
|||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"serde",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-targets 0.52.5",
|
"windows-targets 0.52.5",
|
||||||
]
|
]
|
||||||
@@ -2304,6 +2305,7 @@ name = "komorebi"
|
|||||||
version = "0.1.27-dev.0"
|
version = "0.1.27-dev.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
@@ -3734,6 +3736,7 @@ version = "0.8.21"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92"
|
checksum = "09c024468a378b7e36765cd36702b7a90cc3cba11654f6685c8f233408e89e92"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
"dyn-clone",
|
"dyn-clone",
|
||||||
"schemars_derive",
|
"schemars_derive",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
@@ -40,5 +40,7 @@ features = [
|
|||||||
"Win32_UI_Shell",
|
"Win32_UI_Shell",
|
||||||
"Win32_UI_Shell_Common",
|
"Win32_UI_Shell_Common",
|
||||||
"Win32_UI_WindowsAndMessaging",
|
"Win32_UI_WindowsAndMessaging",
|
||||||
"Win32_System_SystemServices"
|
"Win32_System",
|
||||||
|
"Win32_System_SystemServices",
|
||||||
|
"Win32_System_SystemInformation"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ color-eyre = { workspace = true }
|
|||||||
crossbeam-channel = "0.5"
|
crossbeam-channel = "0.5"
|
||||||
crossbeam-utils = "0.8"
|
crossbeam-utils = "0.8"
|
||||||
ctrlc = { version = "3", features = ["termination"] }
|
ctrlc = { version = "3", features = ["termination"] }
|
||||||
|
chrono = { version = "0.4", features = ["serde"] }
|
||||||
dirs = { workspace = true }
|
dirs = { workspace = true }
|
||||||
getset = "0.1"
|
getset = "0.1"
|
||||||
hex_color = { version = "3", features = ["serde"] }
|
hex_color = { version = "3", features = ["serde"] }
|
||||||
@@ -31,7 +32,7 @@ os_info = "3.8"
|
|||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
paste = "1"
|
paste = "1"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
schemars = "0.8"
|
schemars = { version = "0.8", features = ["chrono"] }
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
strum = { version = "0.26", features = ["derive"] }
|
strum = { version = "0.26", features = ["derive"] }
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use chrono::DateTime;
|
||||||
|
use chrono::Utc;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -70,6 +72,13 @@ impl WindowManager {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let now: DateTime<Utc> = Utc::now();
|
||||||
|
let difference = now - event.timestamp();
|
||||||
|
if difference > chrono::Duration::seconds(2) {
|
||||||
|
tracing::warn!("ignoring event more than two seconds old: {}", event);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let mut rule_debug = RuleDebug::default();
|
let mut rule_debug = RuleDebug::default();
|
||||||
|
|
||||||
let should_manage = event.window().should_manage(Some(event), &mut rule_debug)?;
|
let should_manage = event.window().should_manage(Some(event), &mut rule_debug)?;
|
||||||
@@ -119,9 +128,9 @@ impl WindowManager {
|
|||||||
|
|
||||||
// Make sure we have the most recently focused monitor from any event
|
// Make sure we have the most recently focused monitor from any event
|
||||||
match event {
|
match event {
|
||||||
WindowManagerEvent::FocusChange(_, window)
|
WindowManagerEvent::FocusChange(_, window, _)
|
||||||
| WindowManagerEvent::Show(_, window)
|
| WindowManagerEvent::Show(_, window, _)
|
||||||
| WindowManagerEvent::MoveResizeEnd(_, window) => {
|
| WindowManagerEvent::MoveResizeEnd(_, window, _) => {
|
||||||
if let Some(monitor_idx) = self.monitor_idx_from_window(window) {
|
if let Some(monitor_idx) = self.monitor_idx_from_window(window) {
|
||||||
// This is a hidden window apparently associated with COM support mechanisms (based
|
// This is a hidden window apparently associated with COM support mechanisms (based
|
||||||
// on a post from http://www.databaseteam.org/1-ms-sql-server/a5bb344836fb889c.htm)
|
// on a post from http://www.databaseteam.org/1-ms-sql-server/a5bb344836fb889c.htm)
|
||||||
@@ -151,7 +160,7 @@ impl WindowManager {
|
|||||||
|
|
||||||
for monitor in self.monitors_mut() {
|
for monitor in self.monitors_mut() {
|
||||||
for workspace in monitor.workspaces_mut() {
|
for workspace in monitor.workspaces_mut() {
|
||||||
if let WindowManagerEvent::FocusChange(_, window) = event {
|
if let WindowManagerEvent::FocusChange(_, window, _) = event {
|
||||||
let _ = workspace.focus_changed(window.hwnd);
|
let _ = workspace.focus_changed(window.hwnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,11 +176,11 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
WindowManagerEvent::Raise(window) => {
|
WindowManagerEvent::Raise(window, _) => {
|
||||||
window.focus(false)?;
|
window.focus(false)?;
|
||||||
self.has_pending_raise_op = false;
|
self.has_pending_raise_op = false;
|
||||||
}
|
}
|
||||||
WindowManagerEvent::Destroy(_, window) | WindowManagerEvent::Unmanage(window) => {
|
WindowManagerEvent::Destroy(_, window, _) | WindowManagerEvent::Unmanage(window, _) => {
|
||||||
if self.focused_workspace()?.contains_window(window.hwnd) {
|
if self.focused_workspace()?.contains_window(window.hwnd) {
|
||||||
self.focused_workspace_mut()?.remove_window(window.hwnd)?;
|
self.focused_workspace_mut()?.remove_window(window.hwnd)?;
|
||||||
self.update_focused_workspace(false, false)?;
|
self.update_focused_workspace(false, false)?;
|
||||||
@@ -181,7 +190,7 @@ impl WindowManager {
|
|||||||
already_moved_window_handles.remove(&window.hwnd);
|
already_moved_window_handles.remove(&window.hwnd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowManagerEvent::Minimize(_, window) => {
|
WindowManagerEvent::Minimize(_, window, _) => {
|
||||||
let mut hide = false;
|
let mut hide = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -196,7 +205,7 @@ impl WindowManager {
|
|||||||
self.update_focused_workspace(false, false)?;
|
self.update_focused_workspace(false, false)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowManagerEvent::Hide(_, window) => {
|
WindowManagerEvent::Hide(_, window, _) => {
|
||||||
let mut hide = false;
|
let mut hide = false;
|
||||||
// Some major applications unfortunately send the HIDE signal when they are being
|
// Some major applications unfortunately send the HIDE signal when they are being
|
||||||
// minimized or destroyed. Applications that close to the tray also do the same,
|
// minimized or destroyed. Applications that close to the tray also do the same,
|
||||||
@@ -242,7 +251,7 @@ impl WindowManager {
|
|||||||
|
|
||||||
already_moved_window_handles.remove(&window.hwnd);
|
already_moved_window_handles.remove(&window.hwnd);
|
||||||
}
|
}
|
||||||
WindowManagerEvent::FocusChange(_, window) => {
|
WindowManagerEvent::FocusChange(_, window, _) => {
|
||||||
self.update_focused_workspace(self.mouse_follows_focus, false)?;
|
self.update_focused_workspace(self.mouse_follows_focus, false)?;
|
||||||
|
|
||||||
let workspace = self.focused_workspace_mut()?;
|
let workspace = self.focused_workspace_mut()?;
|
||||||
@@ -267,9 +276,9 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowManagerEvent::Show(_, window)
|
WindowManagerEvent::Show(_, window, _)
|
||||||
| WindowManagerEvent::Manage(window)
|
| WindowManagerEvent::Manage(window, _)
|
||||||
| WindowManagerEvent::Uncloak(_, window) => {
|
| WindowManagerEvent::Uncloak(_, window, _) => {
|
||||||
let focused_monitor_idx = self.focused_monitor_idx();
|
let focused_monitor_idx = self.focused_monitor_idx();
|
||||||
let focused_workspace_idx =
|
let focused_workspace_idx =
|
||||||
self.focused_workspace_idx_for_monitor_idx(focused_monitor_idx)?;
|
self.focused_workspace_idx_for_monitor_idx(focused_monitor_idx)?;
|
||||||
@@ -366,7 +375,7 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowManagerEvent::MoveResizeStart(_, window) => {
|
WindowManagerEvent::MoveResizeStart(_, window, _) => {
|
||||||
if *self.focused_workspace()?.tile() {
|
if *self.focused_workspace()?.tile() {
|
||||||
let monitor_idx = self.focused_monitor_idx();
|
let monitor_idx = self.focused_monitor_idx();
|
||||||
let workspace_idx = self
|
let workspace_idx = self
|
||||||
@@ -386,7 +395,7 @@ impl WindowManager {
|
|||||||
Option::from((monitor_idx, workspace_idx, container_idx));
|
Option::from((monitor_idx, workspace_idx, container_idx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WindowManagerEvent::MoveResizeEnd(_, window) => {
|
WindowManagerEvent::MoveResizeEnd(_, window, _) => {
|
||||||
// We need this because if the event ends on a different monitor,
|
// We need this because if the event ends on a different monitor,
|
||||||
// that monitor will already have been focused and updated in the state
|
// that monitor will already have been focused and updated in the state
|
||||||
let pending = self.pending_move_op;
|
let pending = self.pending_move_op;
|
||||||
@@ -599,7 +608,7 @@ impl WindowManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// If we unmanaged a window, it shouldn't be immediately hidden behind managed windows
|
// If we unmanaged a window, it shouldn't be immediately hidden behind managed windows
|
||||||
if let WindowManagerEvent::Unmanage(window) = event {
|
if let WindowManagerEvent::Unmanage(window, _) = event {
|
||||||
window.center(&self.focused_monitor_work_area()?)?;
|
window.center(&self.focused_monitor_work_area()?)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,7 +646,7 @@ impl WindowManager {
|
|||||||
// Too many spammy OBJECT_NAMECHANGE events from JetBrains IDEs
|
// Too many spammy OBJECT_NAMECHANGE events from JetBrains IDEs
|
||||||
if !matches!(
|
if !matches!(
|
||||||
event,
|
event,
|
||||||
WindowManagerEvent::Show(WinEvent::ObjectNameChange, _)
|
WindowManagerEvent::Show(WinEvent::ObjectNameChange, _, _)
|
||||||
) {
|
) {
|
||||||
tracing::info!("processed: {}", event.window().to_string());
|
tracing::info!("processed: {}", event.window().to_string());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ impl Window {
|
|||||||
if let Some(event) = event {
|
if let Some(event) = event {
|
||||||
if matches!(
|
if matches!(
|
||||||
event,
|
event,
|
||||||
WindowManagerEvent::Hide(_, _) | WindowManagerEvent::Cloak(_, _)
|
WindowManagerEvent::Hide(_, _, _) | WindowManagerEvent::Cloak(_, _, _)
|
||||||
) {
|
) {
|
||||||
allow_cloaked = true;
|
allow_cloaked = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use chrono::Utc;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
@@ -598,14 +599,14 @@ impl WindowManager {
|
|||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn manage_focused_window(&mut self) -> Result<()> {
|
pub fn manage_focused_window(&mut self) -> Result<()> {
|
||||||
let hwnd = WindowsApi::foreground_window()?;
|
let hwnd = WindowsApi::foreground_window()?;
|
||||||
let event = WindowManagerEvent::Manage(Window::from(hwnd));
|
let event = WindowManagerEvent::Manage(Window::from(hwnd), Utc::now());
|
||||||
Ok(winevent_listener::event_tx().send(event)?)
|
Ok(winevent_listener::event_tx().send(event)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
pub fn unmanage_focused_window(&mut self) -> Result<()> {
|
pub fn unmanage_focused_window(&mut self) -> Result<()> {
|
||||||
let hwnd = WindowsApi::foreground_window()?;
|
let hwnd = WindowsApi::foreground_window()?;
|
||||||
let event = WindowManagerEvent::Unmanage(Window::from(hwnd));
|
let event = WindowManagerEvent::Unmanage(Window::from(hwnd), Utc::now());
|
||||||
Ok(winevent_listener::event_tx().send(event)?)
|
Ok(winevent_listener::event_tx().send(event)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,7 +663,7 @@ impl WindowManager {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let event = WindowManagerEvent::Raise(Window::from(hwnd));
|
let event = WindowManagerEvent::Raise(Window::from(hwnd), Utc::now());
|
||||||
self.has_pending_raise_op = true;
|
self.has_pending_raise_op = true;
|
||||||
winevent_listener::event_tx().send(event)?;
|
winevent_listener::event_tx().send(event)?;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use chrono::DateTime;
|
||||||
|
use chrono::Utc;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
|
|
||||||
@@ -14,68 +16,68 @@ use crate::REGEX_IDENTIFIERS;
|
|||||||
#[derive(Debug, Copy, Clone, Serialize, Deserialize, JsonSchema)]
|
#[derive(Debug, Copy, Clone, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(tag = "type", content = "content")]
|
#[serde(tag = "type", content = "content")]
|
||||||
pub enum WindowManagerEvent {
|
pub enum WindowManagerEvent {
|
||||||
Destroy(WinEvent, Window),
|
Destroy(WinEvent, Window, DateTime<Utc>),
|
||||||
FocusChange(WinEvent, Window),
|
FocusChange(WinEvent, Window, DateTime<Utc>),
|
||||||
Hide(WinEvent, Window),
|
Hide(WinEvent, Window, DateTime<Utc>),
|
||||||
Cloak(WinEvent, Window),
|
Cloak(WinEvent, Window, DateTime<Utc>),
|
||||||
Minimize(WinEvent, Window),
|
Minimize(WinEvent, Window, DateTime<Utc>),
|
||||||
Show(WinEvent, Window),
|
Show(WinEvent, Window, DateTime<Utc>),
|
||||||
Uncloak(WinEvent, Window),
|
Uncloak(WinEvent, Window, DateTime<Utc>),
|
||||||
MoveResizeStart(WinEvent, Window),
|
MoveResizeStart(WinEvent, Window, DateTime<Utc>),
|
||||||
MoveResizeEnd(WinEvent, Window),
|
MoveResizeEnd(WinEvent, Window, DateTime<Utc>),
|
||||||
MouseCapture(WinEvent, Window),
|
MouseCapture(WinEvent, Window, DateTime<Utc>),
|
||||||
Manage(Window),
|
Manage(Window, DateTime<Utc>),
|
||||||
Unmanage(Window),
|
Unmanage(Window, DateTime<Utc>),
|
||||||
Raise(Window),
|
Raise(Window, DateTime<Utc>),
|
||||||
TitleUpdate(WinEvent, Window),
|
TitleUpdate(WinEvent, Window, DateTime<Utc>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for WindowManagerEvent {
|
impl Display for WindowManagerEvent {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Manage(window) => {
|
Self::Manage(window, _) => {
|
||||||
write!(f, "Manage (Window: {window})")
|
write!(f, "Manage (Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Unmanage(window) => {
|
Self::Unmanage(window, _) => {
|
||||||
write!(f, "Unmanage (Window: {window})")
|
write!(f, "Unmanage (Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Destroy(winevent, window) => {
|
Self::Destroy(winevent, window, _) => {
|
||||||
write!(f, "Destroy (WinEvent: {winevent}, Window: {window})")
|
write!(f, "Destroy (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::FocusChange(winevent, window) => {
|
Self::FocusChange(winevent, window, _) => {
|
||||||
write!(f, "FocusChange (WinEvent: {winevent}, Window: {window})",)
|
write!(f, "FocusChange (WinEvent: {winevent}, Window: {window})",)
|
||||||
}
|
}
|
||||||
Self::Hide(winevent, window) => {
|
Self::Hide(winevent, window, _) => {
|
||||||
write!(f, "Hide (WinEvent: {winevent}, Window: {window})")
|
write!(f, "Hide (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Cloak(winevent, window) => {
|
Self::Cloak(winevent, window, _) => {
|
||||||
write!(f, "Cloak (WinEvent: {winevent}, Window: {window})")
|
write!(f, "Cloak (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Minimize(winevent, window) => {
|
Self::Minimize(winevent, window, _) => {
|
||||||
write!(f, "Minimize (WinEvent: {winevent}, Window: {window})")
|
write!(f, "Minimize (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Show(winevent, window) => {
|
Self::Show(winevent, window, _) => {
|
||||||
write!(f, "Show (WinEvent: {winevent}, Window: {window})")
|
write!(f, "Show (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Uncloak(winevent, window) => {
|
Self::Uncloak(winevent, window, _) => {
|
||||||
write!(f, "Uncloak (WinEvent: {winevent}, Window: {window})")
|
write!(f, "Uncloak (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::MoveResizeStart(winevent, window) => {
|
Self::MoveResizeStart(winevent, window, _) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"MoveResizeStart (WinEvent: {winevent}, Window: {window})",
|
"MoveResizeStart (WinEvent: {winevent}, Window: {window})",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Self::MoveResizeEnd(winevent, window) => {
|
Self::MoveResizeEnd(winevent, window, _) => {
|
||||||
write!(f, "MoveResizeEnd (WinEvent: {winevent}, Window: {window})",)
|
write!(f, "MoveResizeEnd (WinEvent: {winevent}, Window: {window})",)
|
||||||
}
|
}
|
||||||
Self::MouseCapture(winevent, window) => {
|
Self::MouseCapture(winevent, window, _) => {
|
||||||
write!(f, "MouseCapture (WinEvent: {winevent}, Window: {window})",)
|
write!(f, "MouseCapture (WinEvent: {winevent}, Window: {window})",)
|
||||||
}
|
}
|
||||||
Self::Raise(window) => {
|
Self::Raise(window, _) => {
|
||||||
write!(f, "Raise (Window: {window})")
|
write!(f, "Raise (Window: {window})")
|
||||||
}
|
}
|
||||||
Self::TitleUpdate(winevent, window) => {
|
Self::TitleUpdate(winevent, window, _) => {
|
||||||
write!(f, "TitleUpdate (WinEvent: {winevent}, Window: {window})")
|
write!(f, "TitleUpdate (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,47 +85,75 @@ impl Display for WindowManagerEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WindowManagerEvent {
|
impl WindowManagerEvent {
|
||||||
|
pub const fn timestamp(self) -> DateTime<Utc> {
|
||||||
|
match self {
|
||||||
|
WindowManagerEvent::Destroy(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::FocusChange(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::Hide(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::Cloak(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::Minimize(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::Show(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::Uncloak(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::MoveResizeStart(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::MoveResizeEnd(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::MouseCapture(_, _, timestamp)
|
||||||
|
| WindowManagerEvent::Manage(_, timestamp)
|
||||||
|
| WindowManagerEvent::Unmanage(_, timestamp)
|
||||||
|
| WindowManagerEvent::Raise(_, timestamp)
|
||||||
|
| WindowManagerEvent::TitleUpdate(_, _, timestamp) => timestamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub const fn window(self) -> Window {
|
pub const fn window(self) -> Window {
|
||||||
match self {
|
match self {
|
||||||
Self::Destroy(_, window)
|
Self::Destroy(_, window, _)
|
||||||
| Self::FocusChange(_, window)
|
| Self::FocusChange(_, window, _)
|
||||||
| Self::Hide(_, window)
|
| Self::Hide(_, window, _)
|
||||||
| Self::Cloak(_, window)
|
| Self::Cloak(_, window, _)
|
||||||
| Self::Minimize(_, window)
|
| Self::Minimize(_, window, _)
|
||||||
| Self::Show(_, window)
|
| Self::Show(_, window, _)
|
||||||
| Self::Uncloak(_, window)
|
| Self::Uncloak(_, window, _)
|
||||||
| Self::MoveResizeStart(_, window)
|
| Self::MoveResizeStart(_, window, _)
|
||||||
| Self::MoveResizeEnd(_, window)
|
| Self::MoveResizeEnd(_, window, _)
|
||||||
| Self::MouseCapture(_, window)
|
| Self::MouseCapture(_, window, _)
|
||||||
| Self::Raise(window)
|
| Self::Raise(window, _)
|
||||||
| Self::Manage(window)
|
| Self::Manage(window, _)
|
||||||
| Self::Unmanage(window)
|
| Self::Unmanage(window, _)
|
||||||
| Self::TitleUpdate(_, window) => window,
|
| Self::TitleUpdate(_, window, _) => window,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_win_event(winevent: WinEvent, window: Window) -> Option<Self> {
|
pub fn from_win_event(
|
||||||
|
winevent: WinEvent,
|
||||||
|
window: Window,
|
||||||
|
timestamp: DateTime<Utc>,
|
||||||
|
) -> Option<Self> {
|
||||||
match winevent {
|
match winevent {
|
||||||
WinEvent::ObjectDestroy => Option::from(Self::Destroy(winevent, window)),
|
WinEvent::ObjectDestroy => Option::from(Self::Destroy(winevent, window, timestamp)),
|
||||||
|
|
||||||
WinEvent::ObjectHide => Option::from(Self::Hide(winevent, window)),
|
WinEvent::ObjectHide => Option::from(Self::Hide(winevent, window, timestamp)),
|
||||||
WinEvent::ObjectCloaked => Option::from(Self::Cloak(winevent, window)),
|
WinEvent::ObjectCloaked => Option::from(Self::Cloak(winevent, window, timestamp)),
|
||||||
|
|
||||||
WinEvent::SystemMinimizeStart => Option::from(Self::Minimize(winevent, window)),
|
WinEvent::SystemMinimizeStart => {
|
||||||
|
Option::from(Self::Minimize(winevent, window, timestamp))
|
||||||
|
}
|
||||||
|
|
||||||
WinEvent::ObjectShow | WinEvent::SystemMinimizeEnd => {
|
WinEvent::ObjectShow | WinEvent::SystemMinimizeEnd => {
|
||||||
Option::from(Self::Show(winevent, window))
|
Option::from(Self::Show(winevent, window, timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
WinEvent::ObjectUncloaked => Option::from(Self::Uncloak(winevent, window)),
|
WinEvent::ObjectUncloaked => Option::from(Self::Uncloak(winevent, window, timestamp)),
|
||||||
|
|
||||||
WinEvent::ObjectFocus | WinEvent::SystemForeground => {
|
WinEvent::ObjectFocus | WinEvent::SystemForeground => {
|
||||||
Option::from(Self::FocusChange(winevent, window))
|
Option::from(Self::FocusChange(winevent, window, timestamp))
|
||||||
|
}
|
||||||
|
WinEvent::SystemMoveSizeStart => {
|
||||||
|
Option::from(Self::MoveResizeStart(winevent, window, timestamp))
|
||||||
|
}
|
||||||
|
WinEvent::SystemMoveSizeEnd => {
|
||||||
|
Option::from(Self::MoveResizeEnd(winevent, window, timestamp))
|
||||||
}
|
}
|
||||||
WinEvent::SystemMoveSizeStart => Option::from(Self::MoveResizeStart(winevent, window)),
|
|
||||||
WinEvent::SystemMoveSizeEnd => Option::from(Self::MoveResizeEnd(winevent, window)),
|
|
||||||
WinEvent::SystemCaptureStart | WinEvent::SystemCaptureEnd => {
|
WinEvent::SystemCaptureStart | WinEvent::SystemCaptureEnd => {
|
||||||
Option::from(Self::MouseCapture(winevent, window))
|
Option::from(Self::MouseCapture(winevent, window, timestamp))
|
||||||
}
|
}
|
||||||
WinEvent::ObjectNameChange => {
|
WinEvent::ObjectNameChange => {
|
||||||
// Some apps like Firefox don't send ObjectCreate or ObjectShow on launch
|
// Some apps like Firefox don't send ObjectCreate or ObjectShow on launch
|
||||||
@@ -152,9 +182,9 @@ impl WindowManagerEvent {
|
|||||||
.is_some();
|
.is_some();
|
||||||
|
|
||||||
if should_trigger_show {
|
if should_trigger_show {
|
||||||
Option::from(Self::Show(winevent, window))
|
Option::from(Self::Show(winevent, window, timestamp))
|
||||||
} else {
|
} else {
|
||||||
Option::from(Self::TitleUpdate(winevent, window))
|
Option::from(Self::TitleUpdate(winevent, window, timestamp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|||||||
@@ -1061,4 +1061,8 @@ impl WindowsApi {
|
|||||||
pub fn wts_register_session_notification(hwnd: isize) -> Result<()> {
|
pub fn wts_register_session_notification(hwnd: isize) -> Result<()> {
|
||||||
unsafe { WTSRegisterSessionNotification(HWND(hwnd), 1) }.process()
|
unsafe { WTSRegisterSessionNotification(HWND(hwnd), 1) }.process()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tick_count() -> u64 {
|
||||||
|
unsafe { windows::Win32::System::SystemInformation::GetTickCount64() }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
|
use chrono::TimeZone;
|
||||||
|
use chrono::Utc;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
use std::ops::Sub;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::time::UNIX_EPOCH;
|
||||||
|
|
||||||
use windows::Win32::Foundation::BOOL;
|
use windows::Win32::Foundation::BOOL;
|
||||||
use windows::Win32::Foundation::HWND;
|
use windows::Win32::Foundation::HWND;
|
||||||
@@ -67,13 +72,25 @@ pub extern "system" fn win_event_hook(
|
|||||||
id_object: i32,
|
id_object: i32,
|
||||||
_id_child: i32,
|
_id_child: i32,
|
||||||
_id_event_thread: u32,
|
_id_event_thread: u32,
|
||||||
_dwms_event_time: u32,
|
dwms_event_time: u32,
|
||||||
) {
|
) {
|
||||||
// OBJID_WINDOW
|
// OBJID_WINDOW
|
||||||
if id_object != 0 {
|
if id_object != 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let millis_since_boot = WindowsApi::tick_count();
|
||||||
|
let system_time_now = std::time::SystemTime::now();
|
||||||
|
|
||||||
|
let boot_time = system_time_now
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.sub(Duration::from_millis(millis_since_boot))
|
||||||
|
.as_secs();
|
||||||
|
|
||||||
|
let boot_time_utc = Utc.timestamp_opt(boot_time as i64, 0).unwrap();
|
||||||
|
let timestamp = boot_time_utc + Duration::from_millis(dwms_event_time as u64);
|
||||||
|
|
||||||
let window = Window::from(hwnd);
|
let window = Window::from(hwnd);
|
||||||
|
|
||||||
let winevent = match WinEvent::try_from(event) {
|
let winevent = match WinEvent::try_from(event) {
|
||||||
@@ -81,7 +98,7 @@ pub extern "system" fn win_event_hook(
|
|||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let event_type = match WindowManagerEvent::from_win_event(winevent, window) {
|
let event_type = match WindowManagerEvent::from_win_event(winevent, window, timestamp) {
|
||||||
None => {
|
None => {
|
||||||
tracing::trace!(
|
tracing::trace!(
|
||||||
"Unhandled WinEvent: {winevent} (hwnd: {}, exe: {}, title: {}, class: {})",
|
"Unhandled WinEvent: {winevent} (hwnd: {}, exe: {}, title: {}, class: {})",
|
||||||
|
|||||||
Reference in New Issue
Block a user