Skip to content

Commit

Permalink
fix: prevent commands from still being run during pause state (#927)
Browse files Browse the repository at this point in the history
  • Loading branch information
lars-berger authored Jan 19, 2025
1 parent d8f556a commit c25aed7
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 37 deletions.
7 changes: 0 additions & 7 deletions packages/wm/src/commands/general/platform_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ pub fn platform_sync(
state: &mut WmState,
config: &UserConfig,
) -> anyhow::Result<()> {
// Skip platform sync when the WM is paused.
if state.is_paused {
// Clear containers to redraw to avoid leaking memory.
state.pending_sync.containers_to_redraw.clear();
return Ok(());
}

let focused_container =
state.focused_container().context("No focused container.")?;

Expand Down
10 changes: 4 additions & 6 deletions packages/wm/src/commands/general/toggle_pause.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@ use crate::wm_state::WmState;

/// Pauses or unpauses the WM.
pub fn toggle_pause(state: &mut WmState) {
let new_paused_state = !state.is_paused;
state.is_paused = new_paused_state;
let is_paused = !state.is_paused;
state.is_paused = is_paused;

// Redraw full container tree on unpause.
if !new_paused_state {
if !is_paused {
let root_container = state.root_container.clone();
state
.pending_sync
.containers_to_redraw
.push(root_container.into());
}

state.emit_event(WmEvent::PauseChanged {
is_paused: new_paused_state,
});
state.emit_event(WmEvent::PauseChanged { is_paused });
}
10 changes: 5 additions & 5 deletions packages/wm/src/events/handle_window_moved_or_resized_end.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ pub fn handle_window_moved_or_resized_end(
state: &mut WmState,
config: &UserConfig,
) -> anyhow::Result<()> {
// Don't update state on resize events if the WM is paused.
if state.is_paused {
return Ok(());
}

let found_window = state.window_from_native(native_window);

if let Some(window) = found_window {
Expand All @@ -56,11 +61,6 @@ pub fn handle_window_moved_or_resized_end(
}
}
WindowContainer::TilingWindow(window) => {
// Don't update state on resize events if the WM is paused.
if state.is_paused {
return Ok(());
}

let parent = window.parent().context("No parent.")?;

// Snap window to its original position if it's the only window in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ pub fn handle_window_moved_or_resized_start(
native_window: &NativeWindow,
state: &mut WmState,
) {
// Don't update state on resize events if the WM is paused.
if state.is_paused {
return;
}

let found_window = state.window_from_native(native_window);

if let Some(found_window) = found_window {
Expand Down
45 changes: 29 additions & 16 deletions packages/wm/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,22 +162,7 @@ async fn start_wm(
}
}

// Run shutdown commands.
let shutdown_commands = config.value.general.shutdown_commands.clone();
wm.process_commands(&shutdown_commands, None, &mut config)?;

wm.state.emit_event(WmEvent::ApplicationExiting);

// Emit remaining WM events before exiting.
while let Ok(wm_event) = wm.event_rx.try_recv() {
info!("Emitting WM event before shutting down: {:?}", wm_event);

if let Err(err) = ipc_server.process_event(wm_event) {
warn!("{:?}", err);
}
}

Ok(())
run_cleanup(&mut wm, &mut config, &mut ipc_server)
}

/// Initialize logging with the specified verbosity level.
Expand Down Expand Up @@ -229,3 +214,31 @@ fn start_watcher_process() -> anyhow::Result<tokio::process::Child, Error>
.spawn()
.context("Failed to start watcher process.")
}

/// Runs cleanup tasks when the WM is exiting.
fn run_cleanup(
wm: &mut WindowManager,
config: &mut UserConfig,
ipc_server: &mut IpcServer,
) -> anyhow::Result<()> {
// Ensure that the WM is unpaused, otherwise, shutdown commands won't get
// executed.
wm.state.is_paused = false;

// Run shutdown commands.
let shutdown_commands = config.value.general.shutdown_commands.clone();
wm.process_commands(&shutdown_commands, None, config)?;

wm.state.emit_event(WmEvent::ApplicationExiting);

// Emit remaining WM events before exiting.
while let Ok(wm_event) = wm.event_rx.try_recv() {
info!("Emitting WM event before shutting down: {:?}", wm_event);

if let Err(err) = ipc_server.process_event(wm_event) {
warn!("{:?}", err);
}
}

Ok(())
}
7 changes: 6 additions & 1 deletion packages/wm/src/wm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ impl WindowManager {
}
}?;

if state.pending_sync.has_changes() {
if !state.is_paused && state.pending_sync.has_changes() {
platform_sync(state, config)?;
}

Expand Down Expand Up @@ -191,6 +191,11 @@ impl WindowManager {
state: &mut WmState,
config: &mut UserConfig,
) -> anyhow::Result<()> {
// No-op if WM is currently paused.
if state.is_paused && *command != InvokeCommand::WmTogglePause {
return Ok(());
}

if subject_container.is_detached() {
bail!("Cannot run command because subject container is detached.");
}
Expand Down
3 changes: 1 addition & 2 deletions packages/wm/src/wm_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,7 @@ impl WmState {
/// prepared.
pub fn emit_event(&self, event: WmEvent) {
if self.has_initialized
&& (!self.is_paused
|| matches!(event, WmEvent::PauseChanged { is_paused: _ }))
&& (!self.is_paused || matches!(event, WmEvent::PauseChanged { .. }))
{
if let Err(err) = self.event_tx.send(event) {
warn!("Failed to send event: {}", err);
Expand Down

0 comments on commit c25aed7

Please sign in to comment.