feat: add window management (list, minimize-all, focus, maximize)

This commit is contained in:
Helios 2026-03-02 20:00:41 +01:00
parent c9643c8543
commit 9f06d84f28
No known key found for this signature in database
GPG key ID: C8259547CD8309B5
7 changed files with 277 additions and 1 deletions

View file

@ -233,6 +233,80 @@ pub async fn request_type(
}
}
/// GET /sessions/:id/windows
pub async fn list_windows(
Path(session_id): Path<String>,
State(state): State<AppState>,
) -> impl IntoResponse {
match dispatch(&state, &session_id, "list_windows", |rid| {
ServerMessage::ListWindowsRequest { request_id: rid }
})
.await
{
Ok(ClientMessage::ListWindowsResponse { windows, .. }) => (
StatusCode::OK,
Json(serde_json::json!({ "windows": windows })),
)
.into_response(),
Ok(ClientMessage::Error { message, .. }) => (
StatusCode::INTERNAL_SERVER_ERROR,
Json(serde_json::json!({ "error": message })),
)
.into_response(),
Ok(_) => (
StatusCode::BAD_GATEWAY,
Json(serde_json::json!({ "error": "Unexpected response from client" })),
)
.into_response(),
Err(e) => e.into_response(),
}
}
/// POST /sessions/:id/windows/minimize-all
pub async fn minimize_all(
Path(session_id): Path<String>,
State(state): State<AppState>,
) -> impl IntoResponse {
match dispatch(&state, &session_id, "minimize_all", |rid| {
ServerMessage::MinimizeAllRequest { request_id: rid }
})
.await
{
Ok(_) => (StatusCode::OK, Json(serde_json::json!({ "ok": true }))).into_response(),
Err(e) => e.into_response(),
}
}
/// POST /sessions/:id/windows/:window_id/focus
pub async fn focus_window(
Path((session_id, window_id)): Path<(String, u64)>,
State(state): State<AppState>,
) -> impl IntoResponse {
match dispatch(&state, &session_id, "focus_window", |rid| {
ServerMessage::FocusWindowRequest { request_id: rid, window_id }
})
.await
{
Ok(_) => (StatusCode::OK, Json(serde_json::json!({ "ok": true }))).into_response(),
Err(e) => e.into_response(),
}
}
/// POST /sessions/:id/windows/:window_id/maximize
pub async fn maximize_and_focus(
Path((session_id, window_id)): Path<(String, u64)>,
State(state): State<AppState>,
) -> impl IntoResponse {
match dispatch(&state, &session_id, "maximize_and_focus", |rid| {
ServerMessage::MaximizeAndFocusRequest { request_id: rid, window_id }
})
.await
{
Ok(_) => (StatusCode::OK, Json(serde_json::json!({ "ok": true }))).into_response(),
Err(e) => e.into_response(),
}
}
/// POST /sessions/:id/label
#[derive(Deserialize)]
pub struct LabelBody {

View file

@ -48,6 +48,10 @@ async fn main() -> anyhow::Result<()> {
.route("/sessions/:id/click", post(api::request_click))
.route("/sessions/:id/type", post(api::request_type))
.route("/sessions/:id/label", post(api::set_label))
.route("/sessions/:id/windows", get(api::list_windows))
.route("/sessions/:id/windows/minimize-all", post(api::minimize_all))
.route("/sessions/:id/windows/:window_id/focus", post(api::focus_window))
.route("/sessions/:id/windows/:window_id/maximize", post(api::maximize_and_focus))
.layer(middleware::from_fn_with_state(state.clone(), require_api_key));
let app = Router::new()

View file

@ -88,6 +88,7 @@ async fn handle_client_message(session_id: Uuid, msg: ClientMessage, state: &App
}
ClientMessage::ScreenshotResponse { request_id, .. }
| ClientMessage::ExecResponse { request_id, .. }
| ClientMessage::ListWindowsResponse { request_id, .. }
| ClientMessage::Ack { request_id }
| ClientMessage::Error { request_id, .. } => {
let rid = *request_id;