Skip to content
Merged
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
30 changes: 11 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -429,25 +429,17 @@ jobs:
- name: cargo test -p roost-linux
run: cargo test -p roost-linux

# Regression guard: tab + project reorder were converted from GtkDnD to
# GtkGestureDrag because the DnD drag-icon surface aborts the process on
# Wayland (gdksurface-wayland.c:348:frame_callback), and synthetic input
# can't reliably reproduce that in CI. clippy's disallowed-types (see
# clippy.toml) forbids the DnD transport types semantically — it resolves
# real references, so it ignores the comments that name those types and
# catches builder/glob-import forms a text grep would miss. Only
# disallowed_types is denied, so roost-linux's other (un-linted) clippy
# warnings don't fail the build; rust-lint excludes roost-linux because it
# needs the GTK toolchain that this job already has.
- name: No GtkDnD reorder + no raw grab_focus (clippy disallowed-types/methods)
# `-A warnings` first: roost-linux is NOT clippy-clean (that's exactly
# why rust-lint excludes it), and the toolchain action sets
# RUSTFLAGS=-D warnings — so without allowing the rest, every
# pre-existing clippy lint would error here. We deny ONLY the
# disallowed_types (GtkDnD #236) + disallowed_methods (raw grab_focus
# #234) guards (they survive the `-A warnings` as later, more-specific
# flags).
run: cargo clippy -p roost-linux --all-targets -- -A warnings -D clippy::disallowed_types -D clippy::disallowed_methods
# roost-linux is clippy-clean (issue #283 closed out the last
# type_complexity holdout), so this runs the same full gate as
# rust-lint / Iced's "Test and lint Iced" step below — no more
# `-A warnings` narrow denylist. disallowed_types (GtkDnD #236) and
# disallowed_methods (raw grab_focus #234) are warn-by-default clippy
# lints, so `-D warnings` still catches regressions on both; clippy.toml
# stays the source of truth for which types/methods are disallowed.
# rust-lint excludes roost-linux because it needs the GTK toolchain
# that only this job has.
- name: cargo clippy -p roost-linux
run: cargo clippy -p roost-linux --all-targets -- -D warnings

# Iced walking skeleton: exact released Iced + libghostty-vt on both host
# platforms, with the common IPC harness driving a real PTY-backed window.
Expand Down
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,11 @@ fmt-check: ## Check formatting (what CI's rust-lint runs)
clippy: ## Lint Rust at CI parity (warnings are errors)
# `-D warnings` matches the `rust-lint` CI job. Without it `make check`
# passed while CI failed, which is worse than no local gate at all.
# roost-linux is linted separately (it needs GTK), mirroring CI's split.
# roost-linux is linted separately (it needs GTK), mirroring CI's split;
# it's clippy-clean (issue #283) so it gets the same full `-D warnings`
# gate, not a narrow denylist.
cargo clippy --workspace --exclude roost-linux --all-targets -- -D warnings
cargo clippy -p roost-linux --all-targets -- -A warnings -D clippy::disallowed_types -D clippy::disallowed_methods
cargo clippy -p roost-linux --all-targets -- -D warnings

check-iced: fmt-check test-iced ## Iced formatting, lint, tests, and dependency boundaries
cargo clippy -p roost-iced --all-targets -- -D warnings
Expand Down
11 changes: 7 additions & 4 deletions clippy.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
# types so a reorder can't regress back onto that crash. clippy resolves real
# type references, so this (unlike a text grep) ignores the comments that name
# these types to explain their removal, and catches builder/glob-import forms.
# Enforced by `cargo clippy -p roost-linux -- -D clippy::disallowed_types` in the
# gtk-build CI job (rust-lint excludes roost-linux — it needs the GTK toolchain).
# Enforced by the full `cargo clippy -p roost-linux --all-targets -- -D
# warnings` gate in the
# gtk-build CI job (disallowed-types is warn-by-default, so `-D warnings` catches
# it; rust-lint excludes roost-linux — it needs the GTK toolchain).
disallowed-types = [
{ path = "gtk4::DragSource", reason = "reorder must use GtkGestureDrag — GtkDnD's drag-icon surface aborts on Wayland (#236)" },
{ path = "gtk4::DropTarget", reason = "reorder must use GtkGestureDrag — GtkDnD's drag-icon surface aborts on Wayland (#236)" },
Expand All @@ -16,8 +18,9 @@ disallowed-types = [
# widget (mid attach / tab switch) walks a dead focus chain and trips
# `gtk_widget_get_parent: GTK_IS_WIDGET` — the #234 storm/crash. Sites that must
# always focus (the palette / rename entries, where a *missed* focus is the bug)
# opt out with a local `#[allow]`. Enforced by `-D clippy::disallowed_methods`
# in the gtk-build CI job alongside the disallowed-types guard above.
# opt out with a local `#[allow]`. Enforced by the same full `-D warnings` gate
# in the gtk-build CI job (disallowed-methods is warn-by-default) alongside the
# disallowed-types guard above.
disallowed-methods = [
{ path = "gtk4::prelude::WidgetExt::grab_focus", reason = "use crate::focus::safe_grab_focus — a raw grab on an un-rooted widget walks a dead focus chain (#234)" },
]
23 changes: 6 additions & 17 deletions crates/roost-engine/src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,12 @@ pub struct DumpData {
/// on success, an error message on failure.
type ScreenshotReply = tokio::sync::oneshot::Sender<Result<(Vec<u8>, u32, u32), String>>;

/// Reply for a [`UiRequest::WindowMetrics`]:
/// `(window_width, window_height, sidebar_width, sidebar_collapsed,
/// terminal_top, terminal_font_family)`
/// in logical points. The `Result<_, String>` envelope shape matches
/// every sibling reply (so the shared `ui_call` helper works), but
/// Reply for a [`UiRequest::WindowMetrics`]: the window/sidebar/terminal
/// geometry in logical points. The `Result<_, String>` envelope shape
/// matches every sibling reply (so the shared `ui_call` helper works), but
/// the UI side always answers `Ok` — UI adapter widget/state queries
/// never fail.
type WindowMetricsReply = tokio::sync::oneshot::Sender<
Result<(f64, f64, f64, bool, Option<f64>, Option<String>), String>,
>;
type WindowMetricsReply = tokio::sync::oneshot::Sender<Result<WindowMetricsResult, String>>;

/// Reply for [`UiRequest::SidebarDump`]. Read-only: always answers
/// `Ok`, matching `WindowMetricsReply`.
Expand Down Expand Up @@ -679,18 +675,11 @@ async fn dispatch(
}
ops::WINDOW_METRICS => {
let _p: WindowMetricsParams = decode(params)?;
let (w, h_, sw, collapsed, terminal_top, terminal_font_family) = h
let result = h
.ui_call(|reply| UiRequest::WindowMetrics { reply })
.await?
.map_err(|m| HandlerError::new("internal", m))?;
encode(&WindowMetricsResult {
window_width: w,
window_height: h_,
sidebar_width: sw,
sidebar_collapsed: collapsed,
terminal_top,
terminal_font_family,
})
encode(&result)
}
ops::SIDEBAR_DUMP => {
let _p: SidebarDumpParams = decode(params)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/roost-iced/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use roost_engine::{
use roost_ipc::agent;
use roost_ipc::messages::{
PaletteItemView, PalettePresentResult, PaletteStateResult, Project, SidebarDumpAgentRow,
SidebarDumpProject, SidebarDumpResult,
SidebarDumpProject, SidebarDumpResult, WindowMetricsResult,
};
use roost_ipc::paths::BundleProfile;
use roost_ipc::IpcServer;
Expand Down
2 changes: 1 addition & 1 deletion crates/roost-iced/src/app/interactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1491,7 +1491,7 @@ fn dispatch_file_drop_batch(
if !origin_live {
return FileDropDisposition::ClosedOrigin;
}
let Some(text) = roost_ui_model::drop_content::resolve(batch.paths, None) else {
let Some(text) = roost_ui_model::drop_content::resolve(batch.paths, None, None) else {
return FileDropDisposition::Invalid;
};
paste(&text);
Expand Down
16 changes: 8 additions & 8 deletions crates/roost-iced/src/app/servicing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -720,14 +720,14 @@ impl App {
.resolve(self.typography.effective_family())
.name
.to_string();
let _ = reply.send(Ok((
f64::from(self.window_size.width),
f64::from(self.window_size.height),
f64::from(self.effective_sidebar_width()),
collapsed,
Some(f64::from(chrome::BAND_HEIGHT)),
Some(resolved_family),
)));
let _ = reply.send(Ok(WindowMetricsResult {
window_width: f64::from(self.window_size.width),
window_height: f64::from(self.window_size.height),
sidebar_width: f64::from(self.effective_sidebar_width()),
sidebar_collapsed: collapsed,
terminal_top: Some(f64::from(chrome::BAND_HEIGHT)),
terminal_font_family: Some(resolved_family),
}));
}
UiRequest::WindowResize {
width,
Expand Down
Loading
Loading