Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions src/actor/reactor/events/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ impl CommandEventHandler {
ReactorCommand::MoveWindowToDisplay { selector, window_id } => {
Self::handle_command_reactor_move_window_to_display(reactor, &selector, window_id);
}
ReactorCommand::MoveEverythingToDisplay { selector } => {
Self::handle_command_reactor_move_everything_to_display(reactor, &selector);
}
}
}

Expand Down Expand Up @@ -506,6 +509,119 @@ impl CommandEventHandler {
let _ = reactor.update_layout_or_warn(false, false);
}

pub fn handle_command_reactor_move_everything_to_display(
reactor: &mut Reactor,
selector: &DisplaySelector,
) {
if reactor.is_in_drag() {
warn!("Ignoring move-window-to-display while a drag is active");
return;
}

let Some(source_space) = reactor.workspace_command_space() else {
warn!("No source_space could be identified!");
return;
};
if !reactor.is_space_active(source_space) {
warn!("Move everything to display ignored: source space is inactive");
return;
}

let origin_screen = reactor.space_manager.screen_by_space(source_space);

let origin_point =
origin_screen.map(|s| s.frame.mid()).or_else(|| reactor.current_screen_center());
let target_screen = reactor.screen_for_selector(selector, origin_point).cloned();

let Some(target_screen) = target_screen else {
warn!(
?selector,
"Move window to display ignored: target display not found"
);
return;
};
let Some(target_space) = target_screen.space else {
warn!(
uuid = ?target_screen.display_uuid,
"Move window to display ignored: display has no active space"
);
return;
};
if !reactor.is_space_active(target_space) {
warn!(
?selector,
?target_space,
"Move window to display ignored: target display space is inactive"
);
return;
}

if target_space == source_space {
return;
}

let windows =
reactor.layout_manager.layout_engine.windows_in_active_workspace(source_space);

for window in windows {
let (window_server_id, window_frame) = match reactor.window_manager.windows.get(&window)
{
Some(state) => (state.info.sys_id, state.frame_monotonic),
None => {
warn!(?window, "Move window to display ignored: unknown window");
continue;
}
};
let mut target_frame = window_frame;
let size = window_frame.size;
let dest_rect = target_screen.frame;
let mut origin = dest_rect.mid();
origin.x -= size.width / 2.0;
origin.y -= size.height / 2.0;
let min = dest_rect.min();
let max = dest_rect.max();
origin.x = origin.x.max(min.x).min(max.x - size.width);
origin.y = origin.y.max(min.y).min(max.y - size.height);
target_frame.origin = origin;

if let Some(app) = reactor.app_manager.apps.get(&window.pid) {
if let Some(wsid) = window_server_id {
let txid = reactor.transaction_manager.generate_next_txid(wsid);
reactor.transaction_manager.set_last_sent_txid(wsid, txid);
let _ = app.handle.send(crate::actor::app::Request::SetWindowFrame(
window,
target_frame,
txid,
true,
));
} else {
let txid = TransactionId::default();
let _ = app.handle.send(crate::actor::app::Request::SetWindowFrame(
window,
target_frame,
txid,
true,
));
}
}

if let Some(state) = reactor.window_manager.windows.get_mut(&window) {
state.frame_monotonic = target_frame;
}

let response = reactor.layout_manager.layout_engine.move_window_to_space(
source_space,
target_space,
target_screen.frame.size,
window,
);

reactor.handle_layout_response(response, None);
}

let _ = reactor.update_layout_or_warn(false, false);
}

pub fn handle_command_reactor_close_window(
reactor: &mut Reactor,
window_server_id: Option<WindowServerId>,
Expand Down
17 changes: 17 additions & 0 deletions src/bin/rift-cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,18 @@ enum DisplayCommands {
#[arg(long)]
window_id: Option<u32>,
},
/// Move all windows of the current workspace to a display by direction, index, or UUID
MoveEverything {
/// Direction relative to the window's current display (left, right, up, down).
#[arg(long)]
direction: Option<String>,
/// Display index (0-based).
#[arg(long)]
index: Option<usize>,
/// Display UUID.
#[arg(long)]
uuid: Option<String>,
},
}

#[derive(Subcommand)]
Expand Down Expand Up @@ -835,6 +847,11 @@ fn map_display_command(cmd: DisplayCommands) -> Result<RiftCommand, String> {
window_id,
},
))),
DisplayCommands::MoveEverything { direction, index, uuid } => Ok(RiftCommand::Reactor(
reactor::Command::Reactor(reactor::ReactorCommand::MoveEverythingToDisplay {
selector: build_display_selector(direction, index, uuid)?,
}),
)),
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/model/reactor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ pub enum ReactorCommand {
selector: DisplaySelector,
window_id: Option<u32>,
},
MoveEverythingToDisplay {
selector: DisplaySelector,
},
}

#[derive(Debug, Clone)]
Expand Down