mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-06-12 05:24:27 +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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ pub fn listen_for_commands(wm: Arc<Mutex<WindowManager>>) {
|
||||
#[tracing::instrument]
|
||||
pub fn listen_for_commands_tcp(wm: Arc<Mutex<WindowManager>>, 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);
|
||||
|
||||
@@ -18,7 +18,10 @@ pub fn listen_for_movements(wm: Arc<Mutex<WindowManager>>) {
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user