diff --git a/.czrc b/.czrc new file mode 100644 index 00000000..d48bc66a --- /dev/null +++ b/.czrc @@ -0,0 +1,3 @@ +{: + "path": "cz-conventional-changelog" +} diff --git a/komorebi-core/src/config_generation.rs b/komorebi-core/src/config_generation.rs index 5279dc80..62689dc1 100644 --- a/komorebi-core/src/config_generation.rs +++ b/komorebi-core/src/config_generation.rs @@ -24,31 +24,19 @@ impl ApplicationOptions { pub fn raw_cfgen(&self, kind: &ApplicationIdentifier, id: &str) -> String { match self { ApplicationOptions::ObjectNameChange => { - format!( - "komorebic.exe identify-object-name-change-application {} \"{}\"", - kind, id - ) + format!("komorebic.exe identify-object-name-change-application {kind} \"{id}\"",) } ApplicationOptions::Layered => { - format!( - "komorebic.exe identify-layered-application {} \"{}\"", - kind, id - ) + format!("komorebic.exe identify-layered-application {kind} \"{id}\"",) } ApplicationOptions::BorderOverflow => { - format!( - "komorebic.exe identify-border-overflow-application {} \"{}\"", - kind, id - ) + format!("komorebic.exe identify-border-overflow-application {kind} \"{id}\"",) } ApplicationOptions::TrayAndMultiWindow => { - format!( - "komorebic.exe identify-tray-application {} \"{}\"", - kind, id - ) + format!("komorebic.exe identify-tray-application {kind} \"{id}\"",) } ApplicationOptions::Force => { - format!("komorebic.exe manage-rule {} \"{}\"", kind, id) + format!("komorebic.exe manage-rule {kind} \"{id}\"") } } } @@ -143,7 +131,7 @@ impl ApplicationConfigurationGenerator { lines.push(format!("# {}", app.name)); if let Some(options) = app.options { for opt in options { - if let ApplicationOptions::TrayAndMultiWindow = opt { + if matches!(opt, ApplicationOptions::TrayAndMultiWindow) { lines.push(String::from("# If you have disabled minimize/close to tray for this application, you can delete/comment out the next line")); } @@ -161,7 +149,7 @@ impl ApplicationConfigurationGenerator { float_rules.push(float_rule.clone()); if let Some(comment) = float.comment { - lines.push(format!("# {}", comment)); + lines.push(format!("# {comment}")); }; lines.push(float_rule); @@ -192,7 +180,7 @@ impl ApplicationConfigurationGenerator { lines.push(format!("; {}", app.name)); if let Some(options) = app.options { for opt in options { - if let ApplicationOptions::TrayAndMultiWindow = opt { + if matches!(opt, ApplicationOptions::TrayAndMultiWindow) { lines.push(String::from("; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line")); } @@ -212,7 +200,7 @@ impl ApplicationConfigurationGenerator { float_rules.push(float_rule.clone()); if let Some(comment) = float.comment { - lines.push(format!("; {}", comment)); + lines.push(format!("; {comment}")); }; lines.push(float_rule); diff --git a/komorebi-core/src/lib.rs b/komorebi-core/src/lib.rs index fcdc7cee..bfa6bbae 100644 --- a/komorebi-core/src/lib.rs +++ b/komorebi-core/src/lib.rs @@ -95,6 +95,7 @@ pub enum SocketMessage { CycleFocusWorkspace(CycleDirection), FocusMonitorNumber(usize), FocusWorkspaceNumber(usize), + FocusWorkspaceNumbers(usize), FocusMonitorWorkspaceNumber(usize, usize), FocusNamedWorkspace(String), ContainerPadding(usize, usize, i32), diff --git a/komorebi.generated.ahk b/komorebi.generated.ahk index b485f7ac..6f6c917c 100644 --- a/komorebi.generated.ahk +++ b/komorebi.generated.ahk @@ -20,6 +20,9 @@ RunWait('komorebic.exe identify-border-overflow-application class "Photoshop"', ; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line RunWait('komorebic.exe identify-tray-application exe "Akiflow.exe"', , "Hide") +; Android Studio +RunWait('komorebic.exe identify-object-name-change-application exe "studio64.exe"', , "Hide") + ; ArmCord RunWait('komorebic.exe identify-border-overflow-application exe "ArmCord.exe"', , "Hide") ; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line @@ -274,6 +277,9 @@ RunWait('komorebic.exe identify-tray-application class "DocEditorsWindowClass"', RunWait('komorebic.exe identify-border-overflow-application exe "Obsidian.exe"', , "Hide") RunWait('komorebic.exe manage-rule exe "Obsidian.exe"', , "Hide") +; OneDrive +RunWait('komorebic.exe float-rule class "OneDriveReactNativeWin32WindowClass"', , "Hide") + ; OpenRGB ; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line RunWait('komorebic.exe identify-tray-application exe "OpenRGB.exe"', , "Hide") @@ -289,6 +295,8 @@ RunWait('komorebic.exe identify-border-overflow-application exe "Plexamp.exe"', RunWait('komorebic.exe float-rule exe "PowerToys.ColorPickerUI.exe"', , "Hide") ; Target image resizer dialog RunWait('komorebic.exe float-rule exe "PowerToys.ImageResizer.exe"', , "Hide") +; Target Peek popup +RunWait('komorebic.exe float-rule exe "PowerToys.Peek.UI.exe"', , "Hide") ; Process Hacker ; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line @@ -420,6 +428,10 @@ RunWait('komorebic.exe float-rule exe "TranslucentTB.exe"', , "Hide") ; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line RunWait('komorebic.exe identify-tray-application exe "TranslucentTB.exe"', , "Hide") +; Unity Hub +; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line +RunWait('komorebic.exe identify-tray-application exe "Unity Hub.exe"', , "Hide") + ; Unreal Editor RunWait('komorebic.exe identify-border-overflow-application exe "UnrealEditor.exe"', , "Hide") ; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line @@ -435,6 +447,9 @@ RunWait('komorebic.exe identify-object-name-change-application exe "devenv.exe"' ; Visual Studio Code RunWait('komorebic.exe identify-border-overflow-application exe "Code.exe"', , "Hide") +; Visual Studio Code - Insiders +RunWait('komorebic.exe identify-border-overflow-application exe "Code - Insiders.exe"', , "Hide") + ; Voice.ai RunWait('komorebic.exe identify-border-overflow-application exe "VoiceAI.exe"', , "Hide") ; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line diff --git a/komorebi.generated.ps1 b/komorebi.generated.ps1 index 00d2aaa6..276da7bf 100644 --- a/komorebi.generated.ps1 +++ b/komorebi.generated.ps1 @@ -20,6 +20,9 @@ komorebic.exe identify-border-overflow-application class "Photoshop" # If you have disabled minimize/close to tray for this application, you can delete/comment out the next line komorebic.exe identify-tray-application exe "Akiflow.exe" +# Android Studio +komorebic.exe identify-object-name-change-application exe "studio64.exe" + # ArmCord komorebic.exe identify-border-overflow-application exe "ArmCord.exe" # If you have disabled minimize/close to tray for this application, you can delete/comment out the next line @@ -274,6 +277,9 @@ komorebic.exe identify-tray-application class "DocEditorsWindowClass" komorebic.exe identify-border-overflow-application exe "Obsidian.exe" komorebic.exe manage-rule exe "Obsidian.exe" +# OneDrive +komorebic.exe float-rule class "OneDriveReactNativeWin32WindowClass" + # OpenRGB # If you have disabled minimize/close to tray for this application, you can delete/comment out the next line komorebic.exe identify-tray-application exe "OpenRGB.exe" @@ -289,6 +295,8 @@ komorebic.exe identify-border-overflow-application exe "Plexamp.exe" komorebic.exe float-rule exe "PowerToys.ColorPickerUI.exe" # Target image resizer dialog komorebic.exe float-rule exe "PowerToys.ImageResizer.exe" +# Target Peek popup +komorebic.exe float-rule exe "PowerToys.Peek.UI.exe" # Process Hacker # If you have disabled minimize/close to tray for this application, you can delete/comment out the next line @@ -420,6 +428,10 @@ komorebic.exe float-rule exe "TranslucentTB.exe" # If you have disabled minimize/close to tray for this application, you can delete/comment out the next line komorebic.exe identify-tray-application exe "TranslucentTB.exe" +# Unity Hub +# If you have disabled minimize/close to tray for this application, you can delete/comment out the next line +komorebic.exe identify-tray-application exe "Unity Hub.exe" + # Unreal Editor komorebic.exe identify-border-overflow-application exe "UnrealEditor.exe" # If you have disabled minimize/close to tray for this application, you can delete/comment out the next line @@ -435,6 +447,9 @@ komorebic.exe identify-object-name-change-application exe "devenv.exe" # Visual Studio Code komorebic.exe identify-border-overflow-application exe "Code.exe" +# Visual Studio Code - Insiders +komorebic.exe identify-border-overflow-application exe "Code - Insiders.exe" + # Voice.ai komorebic.exe identify-border-overflow-application exe "VoiceAI.exe" # If you have disabled minimize/close to tray for this application, you can delete/comment out the next line diff --git a/komorebi/src/main.rs b/komorebi/src/main.rs index ac6a45e4..d90f948c 100644 --- a/komorebi/src/main.rs +++ b/komorebi/src/main.rs @@ -122,8 +122,7 @@ lazy_static! { home } else { panic!( - "$Env:KOMOREBI_CONFIG_HOME is set to '{}', which is not a valid directory", - home_path + "$Env:KOMOREBI_CONFIG_HOME is set to '{home_path}', which is not a valid directory", ); } }) @@ -344,7 +343,7 @@ pub fn notify_subscribers(notification: &str) -> Result<()> { let mut stale_subscriptions = vec![]; let mut subscriptions = SUBSCRIPTION_PIPES.lock(); for (subscriber, pipe) in subscriptions.iter_mut() { - match writeln!(pipe, "{}", notification) { + match writeln!(pipe, "{notification}") { Ok(_) => { tracing::debug!("pushed notification to subscriber: {}", subscriber); } diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index d08f1865..74792995 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -97,7 +97,7 @@ pub fn listen_for_commands(wm: Arc>) { #[tracing::instrument] pub fn listen_for_commands_tcp(wm: Arc>, port: usize) { let listener = - TcpListener::bind(format!("0.0.0.0:{}", port)).expect("could not start tcp server"); + TcpListener::bind(format!("0.0.0.0:{port}")).expect("could not start tcp server"); std::thread::spawn(move || { tracing::info!("listening on 0.0.0.0:43663"); @@ -557,6 +557,29 @@ impl WindowManager { self.show_border()?; }; } + SocketMessage::FocusWorkspaceNumbers(workspace_idx) => { + // This is to ensure that even on an empty workspace on a secondary monitor, the + // secondary monitor where the cursor is focused will be used as the target for + // the workspace switch op + if let Some(monitor_idx) = self.monitor_idx_from_current_pos() { + self.focus_monitor(monitor_idx)?; + } + + let focused_monitor_idx = self.focused_monitor_idx(); + + for (i, monitor) in self.monitors_mut().iter_mut().enumerate() { + if i != focused_monitor_idx { + monitor.focus_workspace(workspace_idx)?; + monitor.load_focused_workspace(false)?; + } + } + + self.focus_workspace(workspace_idx)?; + + if BORDER_ENABLED.load(Ordering::SeqCst) { + self.show_border()?; + }; + } SocketMessage::FocusMonitorWorkspaceNumber(monitor_idx, workspace_idx) => { self.focus_monitor(monitor_idx)?; self.focus_workspace(workspace_idx)?; @@ -688,8 +711,8 @@ impl WindowManager { } } } - // Otherwise proceed with the resizing logic for individual window containers in the - // assumed BSP layout + // Otherwise proceed with the resizing logic for individual window containers in the + // assumed BSP layout } else { match axis { Axis::Horizontal => { @@ -773,9 +796,10 @@ impl WindowManager { } } FocusFollowsMouseImplementation::Windows => { - if let Some(FocusFollowsMouseImplementation::Komorebi) = - self.focus_follows_mouse - { + if matches!( + self.focus_follows_mouse, + Some(FocusFollowsMouseImplementation::Komorebi) + ) { tracing::warn!( "the windows implementation of focus follows mouse cannot be enabled while the komorebi implementation is enabled" ); @@ -820,9 +844,10 @@ impl WindowManager { } } FocusFollowsMouseImplementation::Windows => { - if let Some(FocusFollowsMouseImplementation::Komorebi) = - self.focus_follows_mouse - { + if matches!( + self.focus_follows_mouse, + Some(FocusFollowsMouseImplementation::Komorebi) + ) { tracing::warn!( "the windows implementation of focus follows mouse cannot be toggled while the komorebi implementation is enabled" ); @@ -958,7 +983,7 @@ impl WindowManager { } SocketMessage::AddSubscriber(ref subscriber) => { let mut pipes = SUBSCRIPTION_PIPES.lock(); - let pipe_path = format!(r"\\.\pipe\{}", subscriber); + let pipe_path = format!(r"\\.\pipe\{subscriber}"); let pipe = connect(&pipe_path).map_err(|_| { anyhow!("the named pipe '{}' has not yet been created; please create it before running this command", pipe_path) })?; @@ -1286,11 +1311,7 @@ pub fn read_commands_tcp( break; } Ok(size) => { - let message = if let Ok(message) = - SocketMessage::from_str(&String::from_utf8_lossy(&buf[..size])) - { - message - } else { + let Ok(message) = SocketMessage::from_str(&String::from_utf8_lossy(&buf[..size])) else { tracing::warn!("client sent an invalid message, disconnecting: {addr}"); let mut connections = TCP_CONNECTIONS.lock(); connections.remove(addr); diff --git a/komorebi/src/process_movement.rs b/komorebi/src/process_movement.rs index 2e3cda10..c1082ef1 100644 --- a/komorebi/src/process_movement.rs +++ b/komorebi/src/process_movement.rs @@ -18,7 +18,10 @@ pub fn listen_for_movements(wm: Arc>) { loop { let focus_follows_mouse = wm.lock().focus_follows_mouse; - if let Some(FocusFollowsMouseImplementation::Komorebi) = focus_follows_mouse { + if matches!( + focus_follows_mouse, + Some(FocusFollowsMouseImplementation::Komorebi) + ) { match receiver.next_event() { // Don't want to send any raise events while we are dragging or resizing Event::MouseButton { action, .. } => match action { diff --git a/komorebi/src/window.rs b/komorebi/src/window.rs index 8a6878bb..3835ac0c 100644 --- a/komorebi/src/window.rs +++ b/komorebi/src/window.rs @@ -45,20 +45,20 @@ impl Display for Window { let mut display = format!("(hwnd: {}", self.hwnd); if let Ok(title) = self.title() { - write!(display, ", title: {}", title)?; + write!(display, ", title: {title}")?; } if let Ok(exe) = self.exe() { - write!(display, ", exe: {}", exe)?; + write!(display, ", exe: {exe}")?; } if let Ok(class) = self.class() { - write!(display, ", class: {}", class)?; + write!(display, ", class: {class}")?; } write!(display, ")")?; - write!(f, "{}", display) + write!(f, "{display}") } } diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index d69f96dc..a86ac905 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -984,7 +984,10 @@ impl WindowManager { #[tracing::instrument(skip(self))] fn handle_unmanaged_window_behaviour(&self) -> Result<()> { - if let OperationBehaviour::NoOp = self.unmanaged_window_operation_behaviour { + if matches!( + self.unmanaged_window_operation_behaviour, + OperationBehaviour::NoOp + ) { let workspace = self.focused_workspace()?; let focused_hwnd = WindowsApi::foreground_window()?; if !workspace.contains_managed_window(focused_hwnd) { diff --git a/komorebi/src/window_manager_event.rs b/komorebi/src/window_manager_event.rs index 59697ddf..af9cdbe4 100644 --- a/komorebi/src/window_manager_event.rs +++ b/komorebi/src/window_manager_event.rs @@ -31,62 +31,49 @@ impl Display for WindowManagerEvent { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { Self::Manage(window) => { - write!(f, "Manage (Window: {})", window) + write!(f, "Manage (Window: {window})") } Self::Unmanage(window) => { - write!(f, "Unmanage (Window: {})", window) + write!(f, "Unmanage (Window: {window})") } Self::Destroy(winevent, window) => { - write!(f, "Destroy (WinEvent: {}, Window: {})", winevent, window) + write!(f, "Destroy (WinEvent: {winevent}, Window: {window})") } Self::FocusChange(winevent, window) => { - write!( - f, - "FocusChange (WinEvent: {}, Window: {})", - winevent, window - ) + write!(f, "FocusChange (WinEvent: {winevent}, Window: {window})",) } Self::Hide(winevent, window) => { - write!(f, "Hide (WinEvent: {}, Window: {})", winevent, window) + write!(f, "Hide (WinEvent: {winevent}, Window: {window})") } Self::Cloak(winevent, window) => { - write!(f, "Cloak (WinEvent: {}, Window: {})", winevent, window) + write!(f, "Cloak (WinEvent: {winevent}, Window: {window})") } Self::Minimize(winevent, window) => { - write!(f, "Minimize (WinEvent: {}, Window: {})", winevent, window) + write!(f, "Minimize (WinEvent: {winevent}, Window: {window})") } Self::Show(winevent, window) => { - write!(f, "Show (WinEvent: {}, Window: {})", winevent, window) + write!(f, "Show (WinEvent: {winevent}, Window: {window})") } Self::Uncloak(winevent, window) => { - write!(f, "Uncloak (WinEvent: {}, Window: {})", winevent, window) + write!(f, "Uncloak (WinEvent: {winevent}, Window: {window})") } Self::MoveResizeStart(winevent, window) => { write!( f, - "MoveResizeStart (WinEvent: {}, Window: {})", - winevent, window + "MoveResizeStart (WinEvent: {winevent}, Window: {window})", ) } Self::MoveResizeEnd(winevent, window) => { - write!( - f, - "MoveResizeEnd (WinEvent: {}, Window: {})", - winevent, window - ) + write!(f, "MoveResizeEnd (WinEvent: {winevent}, Window: {window})",) } Self::MouseCapture(winevent, window) => { - write!( - f, - "MouseCapture (WinEvent: {}, Window: {})", - winevent, window - ) + write!(f, "MouseCapture (WinEvent: {winevent}, Window: {window})",) } Self::Raise(window) => { - write!(f, "Raise (Window: {})", window) + write!(f, "Raise (Window: {window})") } Self::DisplayChange(window) => { - write!(f, "DisplayChange (Window: {})", window) + write!(f, "DisplayChange (Window: {window})") } } } diff --git a/komorebi/src/windows_callbacks.rs b/komorebi/src/windows_callbacks.rs index 94b5843b..6b1529eb 100644 --- a/komorebi/src/windows_callbacks.rs +++ b/komorebi/src/windows_callbacks.rs @@ -158,7 +158,7 @@ pub extern "system" fn border_window( lparam: LPARAM, ) -> LRESULT { unsafe { - match message as u32 { + match message { WM_PAINT => { let border_rect = *BORDER_RECT.lock(); let mut ps = PAINTSTRUCT::default(); @@ -194,7 +194,7 @@ pub extern "system" fn hidden_window( lparam: LPARAM, ) -> LRESULT { unsafe { - match message as u32 { + match message { WM_DISPLAYCHANGE => { let event_type = WindowManagerEvent::DisplayChange(Window { hwnd: window.0 }); WINEVENT_CALLBACK_CHANNEL diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 66e9fb63..364cc7ed 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -60,8 +60,7 @@ lazy_static! { home } else { panic!( - "$Env:KOMOREBI_CONFIG_HOME is set to '{}', which is not a valid directory", - home_path + "$Env:KOMOREBI_CONFIG_HOME is set to '{home_path}', which is not a valid directory", ); } }, @@ -153,6 +152,7 @@ gen_target_subcommand_args! { SendToWorkspace, FocusMonitor, FocusWorkspace, + FocusWorkspaces, MoveWorkspaceToMonitor, } @@ -789,6 +789,9 @@ enum SubCommand { /// Focus the specified workspace on the focused monitor #[clap(arg_required_else_help = true)] FocusWorkspace(FocusWorkspace), + /// Focus the specified workspace on all monitors + #[clap(arg_required_else_help = true)] + FocusWorkspaces(FocusWorkspaces), /// Focus the specified workspace on the target monitor #[clap(arg_required_else_help = true)] FocusMonitorWorkspace(FocusMonitorWorkspace), @@ -1019,7 +1022,7 @@ enum SubCommand { pub fn send_message(bytes: &[u8]) -> Result<()> { let socket = DATA_DIR.join("komorebi.sock"); - let mut stream = UnixStream::connect(&socket)?; + let mut stream = UnixStream::connect(socket)?; Ok(stream.write_all(bytes)?) } @@ -1103,7 +1106,7 @@ fn main() -> Result<()> { let locked = file.lock(); #[allow(clippy::significant_drop_in_scrutinee)] for line in locked.lines().flatten() { - println!("{}", line); + println!("{line}"); } } SubCommand::Focus(arg) => { @@ -1404,13 +1407,13 @@ fn main() -> Result<()> { "'--await-configuration'".to_string() }, |port| if arg.ffm { - format!("'--ffm','--tcp-port={}'", port) + format!("'--ffm','--tcp-port={port}'") } else if arg.await_configuration { - format!("'--await-configuration','--tcp-port={}'", port) + format!("'--await-configuration','--tcp-port={port}'") } else if arg.ffm && arg.await_configuration { - format!("'--ffm','--await-configuration','--tcp-port={}'", port) + format!("'--ffm','--await-configuration','--tcp-port={port}'") } else { - format!("'--tcp-port={}'", port) + format!("'--tcp-port={port}'") } ) ) @@ -1432,18 +1435,18 @@ fn main() -> Result<()> { "'--await-configuration'".to_string() }, |port| if arg.ffm { - format!("'--ffm','--tcp-port={}'", port) + format!("'--ffm','--tcp-port={port}'") } else if arg.await_configuration { - format!("'--await-configuration','--tcp-port={}'", port) + format!("'--await-configuration','--tcp-port={port}'") } else if arg.ffm && arg.await_configuration { - format!("'--ffm','--await-configuration','--tcp-port={}'", port) + format!("'--ffm','--await-configuration','--tcp-port={port}'") } else { - format!("'--tcp-port={}'", port) + format!("'--tcp-port={port}'") } ) ) } else { - format!("Start-Process '{}' -WindowStyle hidden", exec) + format!("Start-Process '{exec}' -WindowStyle hidden") } }, ); @@ -1453,10 +1456,10 @@ fn main() -> Result<()> { while !running { match powershell_script::run(&script) { Ok(_) => { - println!("{}", script); + println!("{script}"); } Err(error) => { - println!("Error: {}", error); + println!("Error: {error}"); } } @@ -1538,6 +1541,9 @@ fn main() -> Result<()> { SubCommand::FocusWorkspace(arg) => { send_message(&SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?; } + SubCommand::FocusWorkspaces(arg) => { + send_message(&SocketMessage::FocusWorkspaceNumbers(arg.target).as_bytes()?)?; + } SubCommand::FocusMonitorWorkspace(arg) => { send_message( &SocketMessage::FocusMonitorWorkspaceNumber(