mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-06-08 11:42:47 +02:00
feat(wm): add focus-workspaces cmd
This commit adds a new command, focus-workspaces, to allow the user to change workspaces across all monitors at the same time. I'm not convinced of the stability of this command and I would strongly discourage using komorebi in this manner. resolve #426
This commit is contained in:
@@ -24,31 +24,19 @@ impl ApplicationOptions {
|
|||||||
pub fn raw_cfgen(&self, kind: &ApplicationIdentifier, id: &str) -> String {
|
pub fn raw_cfgen(&self, kind: &ApplicationIdentifier, id: &str) -> String {
|
||||||
match self {
|
match self {
|
||||||
ApplicationOptions::ObjectNameChange => {
|
ApplicationOptions::ObjectNameChange => {
|
||||||
format!(
|
format!("komorebic.exe identify-object-name-change-application {kind} \"{id}\"",)
|
||||||
"komorebic.exe identify-object-name-change-application {} \"{}\"",
|
|
||||||
kind, id
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ApplicationOptions::Layered => {
|
ApplicationOptions::Layered => {
|
||||||
format!(
|
format!("komorebic.exe identify-layered-application {kind} \"{id}\"",)
|
||||||
"komorebic.exe identify-layered-application {} \"{}\"",
|
|
||||||
kind, id
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ApplicationOptions::BorderOverflow => {
|
ApplicationOptions::BorderOverflow => {
|
||||||
format!(
|
format!("komorebic.exe identify-border-overflow-application {kind} \"{id}\"",)
|
||||||
"komorebic.exe identify-border-overflow-application {} \"{}\"",
|
|
||||||
kind, id
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ApplicationOptions::TrayAndMultiWindow => {
|
ApplicationOptions::TrayAndMultiWindow => {
|
||||||
format!(
|
format!("komorebic.exe identify-tray-application {kind} \"{id}\"",)
|
||||||
"komorebic.exe identify-tray-application {} \"{}\"",
|
|
||||||
kind, id
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
ApplicationOptions::Force => {
|
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));
|
lines.push(format!("# {}", app.name));
|
||||||
if let Some(options) = app.options {
|
if let Some(options) = app.options {
|
||||||
for opt in 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"));
|
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());
|
float_rules.push(float_rule.clone());
|
||||||
|
|
||||||
if let Some(comment) = float.comment {
|
if let Some(comment) = float.comment {
|
||||||
lines.push(format!("# {}", comment));
|
lines.push(format!("# {comment}"));
|
||||||
};
|
};
|
||||||
|
|
||||||
lines.push(float_rule);
|
lines.push(float_rule);
|
||||||
@@ -192,7 +180,7 @@ impl ApplicationConfigurationGenerator {
|
|||||||
lines.push(format!("; {}", app.name));
|
lines.push(format!("; {}", app.name));
|
||||||
if let Some(options) = app.options {
|
if let Some(options) = app.options {
|
||||||
for opt in 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"));
|
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());
|
float_rules.push(float_rule.clone());
|
||||||
|
|
||||||
if let Some(comment) = float.comment {
|
if let Some(comment) = float.comment {
|
||||||
lines.push(format!("; {}", comment));
|
lines.push(format!("; {comment}"));
|
||||||
};
|
};
|
||||||
|
|
||||||
lines.push(float_rule);
|
lines.push(float_rule);
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ pub enum SocketMessage {
|
|||||||
CycleFocusWorkspace(CycleDirection),
|
CycleFocusWorkspace(CycleDirection),
|
||||||
FocusMonitorNumber(usize),
|
FocusMonitorNumber(usize),
|
||||||
FocusWorkspaceNumber(usize),
|
FocusWorkspaceNumber(usize),
|
||||||
|
FocusWorkspaceNumbers(usize),
|
||||||
FocusMonitorWorkspaceNumber(usize, usize),
|
FocusMonitorWorkspaceNumber(usize, usize),
|
||||||
FocusNamedWorkspace(String),
|
FocusNamedWorkspace(String),
|
||||||
ContainerPadding(usize, usize, i32),
|
ContainerPadding(usize, usize, i32),
|
||||||
|
|||||||
@@ -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
|
; 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")
|
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
|
; ArmCord
|
||||||
RunWait('komorebic.exe identify-border-overflow-application exe "ArmCord.exe"', , "Hide")
|
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
|
; 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 identify-border-overflow-application exe "Obsidian.exe"', , "Hide")
|
||||||
RunWait('komorebic.exe manage-rule exe "Obsidian.exe"', , "Hide")
|
RunWait('komorebic.exe manage-rule exe "Obsidian.exe"', , "Hide")
|
||||||
|
|
||||||
|
; OneDrive
|
||||||
|
RunWait('komorebic.exe float-rule class "OneDriveReactNativeWin32WindowClass"', , "Hide")
|
||||||
|
|
||||||
; OpenRGB
|
; OpenRGB
|
||||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
; 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")
|
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")
|
RunWait('komorebic.exe float-rule exe "PowerToys.ColorPickerUI.exe"', , "Hide")
|
||||||
; Target image resizer dialog
|
; Target image resizer dialog
|
||||||
RunWait('komorebic.exe float-rule exe "PowerToys.ImageResizer.exe"', , "Hide")
|
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
|
; Process Hacker
|
||||||
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
; 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
|
; 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")
|
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
|
; Unreal Editor
|
||||||
RunWait('komorebic.exe identify-border-overflow-application exe "UnrealEditor.exe"', , "Hide")
|
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
|
; 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
|
; Visual Studio Code
|
||||||
RunWait('komorebic.exe identify-border-overflow-application exe "Code.exe"', , "Hide")
|
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
|
; Voice.ai
|
||||||
RunWait('komorebic.exe identify-border-overflow-application exe "VoiceAI.exe"', , "Hide")
|
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
|
; If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||||
|
|||||||
@@ -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
|
# 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"
|
komorebic.exe identify-tray-application exe "Akiflow.exe"
|
||||||
|
|
||||||
|
# Android Studio
|
||||||
|
komorebic.exe identify-object-name-change-application exe "studio64.exe"
|
||||||
|
|
||||||
# ArmCord
|
# ArmCord
|
||||||
komorebic.exe identify-border-overflow-application exe "ArmCord.exe"
|
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
|
# 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 identify-border-overflow-application exe "Obsidian.exe"
|
||||||
komorebic.exe manage-rule exe "Obsidian.exe"
|
komorebic.exe manage-rule exe "Obsidian.exe"
|
||||||
|
|
||||||
|
# OneDrive
|
||||||
|
komorebic.exe float-rule class "OneDriveReactNativeWin32WindowClass"
|
||||||
|
|
||||||
# OpenRGB
|
# OpenRGB
|
||||||
# If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
# 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"
|
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"
|
komorebic.exe float-rule exe "PowerToys.ColorPickerUI.exe"
|
||||||
# Target image resizer dialog
|
# Target image resizer dialog
|
||||||
komorebic.exe float-rule exe "PowerToys.ImageResizer.exe"
|
komorebic.exe float-rule exe "PowerToys.ImageResizer.exe"
|
||||||
|
# Target Peek popup
|
||||||
|
komorebic.exe float-rule exe "PowerToys.Peek.UI.exe"
|
||||||
|
|
||||||
# Process Hacker
|
# Process Hacker
|
||||||
# If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
# 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
|
# 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"
|
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
|
# Unreal Editor
|
||||||
komorebic.exe identify-border-overflow-application exe "UnrealEditor.exe"
|
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
|
# 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
|
# Visual Studio Code
|
||||||
komorebic.exe identify-border-overflow-application exe "Code.exe"
|
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
|
# Voice.ai
|
||||||
komorebic.exe identify-border-overflow-application exe "VoiceAI.exe"
|
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
|
# If you have disabled minimize/close to tray for this application, you can delete/comment out the next line
|
||||||
|
|||||||
@@ -122,8 +122,7 @@ lazy_static! {
|
|||||||
home
|
home
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"$Env:KOMOREBI_CONFIG_HOME is set to '{}', which is not a valid directory",
|
"$Env:KOMOREBI_CONFIG_HOME is set to '{home_path}', which is not a valid directory",
|
||||||
home_path
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -344,7 +343,7 @@ pub fn notify_subscribers(notification: &str) -> Result<()> {
|
|||||||
let mut stale_subscriptions = vec![];
|
let mut stale_subscriptions = vec![];
|
||||||
let mut subscriptions = SUBSCRIPTION_PIPES.lock();
|
let mut subscriptions = SUBSCRIPTION_PIPES.lock();
|
||||||
for (subscriber, pipe) in subscriptions.iter_mut() {
|
for (subscriber, pipe) in subscriptions.iter_mut() {
|
||||||
match writeln!(pipe, "{}", notification) {
|
match writeln!(pipe, "{notification}") {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
tracing::debug!("pushed notification to subscriber: {}", subscriber);
|
tracing::debug!("pushed notification to subscriber: {}", subscriber);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
|
|||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub fn listen_for_commands_tcp(wm: Arc<Mutex<WindowManager>>, port: usize) {
|
pub fn listen_for_commands_tcp(wm: Arc<Mutex<WindowManager>>, port: usize) {
|
||||||
let listener =
|
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 || {
|
std::thread::spawn(move || {
|
||||||
tracing::info!("listening on 0.0.0.0:43663");
|
tracing::info!("listening on 0.0.0.0:43663");
|
||||||
@@ -557,6 +557,29 @@ impl WindowManager {
|
|||||||
self.show_border()?;
|
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) => {
|
SocketMessage::FocusMonitorWorkspaceNumber(monitor_idx, workspace_idx) => {
|
||||||
self.focus_monitor(monitor_idx)?;
|
self.focus_monitor(monitor_idx)?;
|
||||||
self.focus_workspace(workspace_idx)?;
|
self.focus_workspace(workspace_idx)?;
|
||||||
@@ -688,8 +711,8 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise proceed with the resizing logic for individual window containers in the
|
// Otherwise proceed with the resizing logic for individual window containers in the
|
||||||
// assumed BSP layout
|
// assumed BSP layout
|
||||||
} else {
|
} else {
|
||||||
match axis {
|
match axis {
|
||||||
Axis::Horizontal => {
|
Axis::Horizontal => {
|
||||||
@@ -773,9 +796,10 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FocusFollowsMouseImplementation::Windows => {
|
FocusFollowsMouseImplementation::Windows => {
|
||||||
if let Some(FocusFollowsMouseImplementation::Komorebi) =
|
if matches!(
|
||||||
self.focus_follows_mouse
|
self.focus_follows_mouse,
|
||||||
{
|
Some(FocusFollowsMouseImplementation::Komorebi)
|
||||||
|
) {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"the windows implementation of focus follows mouse cannot be enabled while the komorebi implementation is enabled"
|
"the windows implementation of focus follows mouse cannot be enabled while the komorebi implementation is enabled"
|
||||||
);
|
);
|
||||||
@@ -820,9 +844,10 @@ impl WindowManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
FocusFollowsMouseImplementation::Windows => {
|
FocusFollowsMouseImplementation::Windows => {
|
||||||
if let Some(FocusFollowsMouseImplementation::Komorebi) =
|
if matches!(
|
||||||
self.focus_follows_mouse
|
self.focus_follows_mouse,
|
||||||
{
|
Some(FocusFollowsMouseImplementation::Komorebi)
|
||||||
|
) {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
"the windows implementation of focus follows mouse cannot be toggled while the komorebi implementation is enabled"
|
"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) => {
|
SocketMessage::AddSubscriber(ref subscriber) => {
|
||||||
let mut pipes = SUBSCRIPTION_PIPES.lock();
|
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(|_| {
|
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)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
Ok(size) => {
|
Ok(size) => {
|
||||||
let message = if let Ok(message) =
|
let Ok(message) = SocketMessage::from_str(&String::from_utf8_lossy(&buf[..size])) else {
|
||||||
SocketMessage::from_str(&String::from_utf8_lossy(&buf[..size]))
|
|
||||||
{
|
|
||||||
message
|
|
||||||
} else {
|
|
||||||
tracing::warn!("client sent an invalid message, disconnecting: {addr}");
|
tracing::warn!("client sent an invalid message, disconnecting: {addr}");
|
||||||
let mut connections = TCP_CONNECTIONS.lock();
|
let mut connections = TCP_CONNECTIONS.lock();
|
||||||
connections.remove(addr);
|
connections.remove(addr);
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ pub fn listen_for_movements(wm: Arc<Mutex<WindowManager>>) {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
let focus_follows_mouse = wm.lock().focus_follows_mouse;
|
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() {
|
match receiver.next_event() {
|
||||||
// Don't want to send any raise events while we are dragging or resizing
|
// Don't want to send any raise events while we are dragging or resizing
|
||||||
Event::MouseButton { action, .. } => match action {
|
Event::MouseButton { action, .. } => match action {
|
||||||
|
|||||||
@@ -45,20 +45,20 @@ impl Display for Window {
|
|||||||
let mut display = format!("(hwnd: {}", self.hwnd);
|
let mut display = format!("(hwnd: {}", self.hwnd);
|
||||||
|
|
||||||
if let Ok(title) = self.title() {
|
if let Ok(title) = self.title() {
|
||||||
write!(display, ", title: {}", title)?;
|
write!(display, ", title: {title}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(exe) = self.exe() {
|
if let Ok(exe) = self.exe() {
|
||||||
write!(display, ", exe: {}", exe)?;
|
write!(display, ", exe: {exe}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(class) = self.class() {
|
if let Ok(class) = self.class() {
|
||||||
write!(display, ", class: {}", class)?;
|
write!(display, ", class: {class}")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
write!(display, ")")?;
|
write!(display, ")")?;
|
||||||
|
|
||||||
write!(f, "{}", display)
|
write!(f, "{display}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -984,7 +984,10 @@ impl WindowManager {
|
|||||||
|
|
||||||
#[tracing::instrument(skip(self))]
|
#[tracing::instrument(skip(self))]
|
||||||
fn handle_unmanaged_window_behaviour(&self) -> Result<()> {
|
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 workspace = self.focused_workspace()?;
|
||||||
let focused_hwnd = WindowsApi::foreground_window()?;
|
let focused_hwnd = WindowsApi::foreground_window()?;
|
||||||
if !workspace.contains_managed_window(focused_hwnd) {
|
if !workspace.contains_managed_window(focused_hwnd) {
|
||||||
|
|||||||
@@ -31,62 +31,49 @@ 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: {}, Window: {})", winevent, window)
|
write!(f, "Destroy (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::FocusChange(winevent, window) => {
|
Self::FocusChange(winevent, window) => {
|
||||||
write!(
|
write!(f, "FocusChange (WinEvent: {winevent}, Window: {window})",)
|
||||||
f,
|
|
||||||
"FocusChange (WinEvent: {}, Window: {})",
|
|
||||||
winevent, window
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Self::Hide(winevent, window) => {
|
Self::Hide(winevent, window) => {
|
||||||
write!(f, "Hide (WinEvent: {}, Window: {})", winevent, window)
|
write!(f, "Hide (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Cloak(winevent, window) => {
|
Self::Cloak(winevent, window) => {
|
||||||
write!(f, "Cloak (WinEvent: {}, Window: {})", winevent, window)
|
write!(f, "Cloak (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Minimize(winevent, window) => {
|
Self::Minimize(winevent, window) => {
|
||||||
write!(f, "Minimize (WinEvent: {}, Window: {})", winevent, window)
|
write!(f, "Minimize (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Show(winevent, window) => {
|
Self::Show(winevent, window) => {
|
||||||
write!(f, "Show (WinEvent: {}, Window: {})", winevent, window)
|
write!(f, "Show (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::Uncloak(winevent, window) => {
|
Self::Uncloak(winevent, window) => {
|
||||||
write!(f, "Uncloak (WinEvent: {}, Window: {})", winevent, window)
|
write!(f, "Uncloak (WinEvent: {winevent}, Window: {window})")
|
||||||
}
|
}
|
||||||
Self::MoveResizeStart(winevent, window) => {
|
Self::MoveResizeStart(winevent, window) => {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"MoveResizeStart (WinEvent: {}, Window: {})",
|
"MoveResizeStart (WinEvent: {winevent}, Window: {window})",
|
||||||
winevent, window
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Self::MoveResizeEnd(winevent, window) => {
|
Self::MoveResizeEnd(winevent, window) => {
|
||||||
write!(
|
write!(f, "MoveResizeEnd (WinEvent: {winevent}, Window: {window})",)
|
||||||
f,
|
|
||||||
"MoveResizeEnd (WinEvent: {}, Window: {})",
|
|
||||||
winevent, window
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Self::MouseCapture(winevent, window) => {
|
Self::MouseCapture(winevent, window) => {
|
||||||
write!(
|
write!(f, "MouseCapture (WinEvent: {winevent}, Window: {window})",)
|
||||||
f,
|
|
||||||
"MouseCapture (WinEvent: {}, Window: {})",
|
|
||||||
winevent, window
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
Self::Raise(window) => {
|
Self::Raise(window) => {
|
||||||
write!(f, "Raise (Window: {})", window)
|
write!(f, "Raise (Window: {window})")
|
||||||
}
|
}
|
||||||
Self::DisplayChange(window) => {
|
Self::DisplayChange(window) => {
|
||||||
write!(f, "DisplayChange (Window: {})", window)
|
write!(f, "DisplayChange (Window: {window})")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ pub extern "system" fn border_window(
|
|||||||
lparam: LPARAM,
|
lparam: LPARAM,
|
||||||
) -> LRESULT {
|
) -> LRESULT {
|
||||||
unsafe {
|
unsafe {
|
||||||
match message as u32 {
|
match message {
|
||||||
WM_PAINT => {
|
WM_PAINT => {
|
||||||
let border_rect = *BORDER_RECT.lock();
|
let border_rect = *BORDER_RECT.lock();
|
||||||
let mut ps = PAINTSTRUCT::default();
|
let mut ps = PAINTSTRUCT::default();
|
||||||
@@ -194,7 +194,7 @@ pub extern "system" fn hidden_window(
|
|||||||
lparam: LPARAM,
|
lparam: LPARAM,
|
||||||
) -> LRESULT {
|
) -> LRESULT {
|
||||||
unsafe {
|
unsafe {
|
||||||
match message as u32 {
|
match message {
|
||||||
WM_DISPLAYCHANGE => {
|
WM_DISPLAYCHANGE => {
|
||||||
let event_type = WindowManagerEvent::DisplayChange(Window { hwnd: window.0 });
|
let event_type = WindowManagerEvent::DisplayChange(Window { hwnd: window.0 });
|
||||||
WINEVENT_CALLBACK_CHANNEL
|
WINEVENT_CALLBACK_CHANNEL
|
||||||
|
|||||||
+21
-15
@@ -60,8 +60,7 @@ lazy_static! {
|
|||||||
home
|
home
|
||||||
} else {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"$Env:KOMOREBI_CONFIG_HOME is set to '{}', which is not a valid directory",
|
"$Env:KOMOREBI_CONFIG_HOME is set to '{home_path}', which is not a valid directory",
|
||||||
home_path
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -153,6 +152,7 @@ gen_target_subcommand_args! {
|
|||||||
SendToWorkspace,
|
SendToWorkspace,
|
||||||
FocusMonitor,
|
FocusMonitor,
|
||||||
FocusWorkspace,
|
FocusWorkspace,
|
||||||
|
FocusWorkspaces,
|
||||||
MoveWorkspaceToMonitor,
|
MoveWorkspaceToMonitor,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -789,6 +789,9 @@ enum SubCommand {
|
|||||||
/// Focus the specified workspace on the focused monitor
|
/// Focus the specified workspace on the focused monitor
|
||||||
#[clap(arg_required_else_help = true)]
|
#[clap(arg_required_else_help = true)]
|
||||||
FocusWorkspace(FocusWorkspace),
|
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
|
/// Focus the specified workspace on the target monitor
|
||||||
#[clap(arg_required_else_help = true)]
|
#[clap(arg_required_else_help = true)]
|
||||||
FocusMonitorWorkspace(FocusMonitorWorkspace),
|
FocusMonitorWorkspace(FocusMonitorWorkspace),
|
||||||
@@ -1019,7 +1022,7 @@ enum SubCommand {
|
|||||||
|
|
||||||
pub fn send_message(bytes: &[u8]) -> Result<()> {
|
pub fn send_message(bytes: &[u8]) -> Result<()> {
|
||||||
let socket = DATA_DIR.join("komorebi.sock");
|
let socket = DATA_DIR.join("komorebi.sock");
|
||||||
let mut stream = UnixStream::connect(&socket)?;
|
let mut stream = UnixStream::connect(socket)?;
|
||||||
Ok(stream.write_all(bytes)?)
|
Ok(stream.write_all(bytes)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1103,7 +1106,7 @@ fn main() -> Result<()> {
|
|||||||
let locked = file.lock();
|
let locked = file.lock();
|
||||||
#[allow(clippy::significant_drop_in_scrutinee)]
|
#[allow(clippy::significant_drop_in_scrutinee)]
|
||||||
for line in locked.lines().flatten() {
|
for line in locked.lines().flatten() {
|
||||||
println!("{}", line);
|
println!("{line}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SubCommand::Focus(arg) => {
|
SubCommand::Focus(arg) => {
|
||||||
@@ -1404,13 +1407,13 @@ fn main() -> Result<()> {
|
|||||||
"'--await-configuration'".to_string()
|
"'--await-configuration'".to_string()
|
||||||
},
|
},
|
||||||
|port| if arg.ffm {
|
|port| if arg.ffm {
|
||||||
format!("'--ffm','--tcp-port={}'", port)
|
format!("'--ffm','--tcp-port={port}'")
|
||||||
} else if arg.await_configuration {
|
} else if arg.await_configuration {
|
||||||
format!("'--await-configuration','--tcp-port={}'", port)
|
format!("'--await-configuration','--tcp-port={port}'")
|
||||||
} else if arg.ffm && arg.await_configuration {
|
} else if arg.ffm && arg.await_configuration {
|
||||||
format!("'--ffm','--await-configuration','--tcp-port={}'", port)
|
format!("'--ffm','--await-configuration','--tcp-port={port}'")
|
||||||
} else {
|
} else {
|
||||||
format!("'--tcp-port={}'", port)
|
format!("'--tcp-port={port}'")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -1432,18 +1435,18 @@ fn main() -> Result<()> {
|
|||||||
"'--await-configuration'".to_string()
|
"'--await-configuration'".to_string()
|
||||||
},
|
},
|
||||||
|port| if arg.ffm {
|
|port| if arg.ffm {
|
||||||
format!("'--ffm','--tcp-port={}'", port)
|
format!("'--ffm','--tcp-port={port}'")
|
||||||
} else if arg.await_configuration {
|
} else if arg.await_configuration {
|
||||||
format!("'--await-configuration','--tcp-port={}'", port)
|
format!("'--await-configuration','--tcp-port={port}'")
|
||||||
} else if arg.ffm && arg.await_configuration {
|
} else if arg.ffm && arg.await_configuration {
|
||||||
format!("'--ffm','--await-configuration','--tcp-port={}'", port)
|
format!("'--ffm','--await-configuration','--tcp-port={port}'")
|
||||||
} else {
|
} else {
|
||||||
format!("'--tcp-port={}'", port)
|
format!("'--tcp-port={port}'")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
format!("Start-Process '{}' -WindowStyle hidden", exec)
|
format!("Start-Process '{exec}' -WindowStyle hidden")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -1453,10 +1456,10 @@ fn main() -> Result<()> {
|
|||||||
while !running {
|
while !running {
|
||||||
match powershell_script::run(&script) {
|
match powershell_script::run(&script) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("{}", script);
|
println!("{script}");
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
println!("Error: {}", error);
|
println!("Error: {error}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1538,6 +1541,9 @@ fn main() -> Result<()> {
|
|||||||
SubCommand::FocusWorkspace(arg) => {
|
SubCommand::FocusWorkspace(arg) => {
|
||||||
send_message(&SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?;
|
send_message(&SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?;
|
||||||
}
|
}
|
||||||
|
SubCommand::FocusWorkspaces(arg) => {
|
||||||
|
send_message(&SocketMessage::FocusWorkspaceNumbers(arg.target).as_bytes()?)?;
|
||||||
|
}
|
||||||
SubCommand::FocusMonitorWorkspace(arg) => {
|
SubCommand::FocusMonitorWorkspace(arg) => {
|
||||||
send_message(
|
send_message(
|
||||||
&SocketMessage::FocusMonitorWorkspaceNumber(
|
&SocketMessage::FocusMonitorWorkspaceNumber(
|
||||||
|
|||||||
Reference in New Issue
Block a user