Auto-applied suggestions on libcosmic-yoda lib only: unused imports,
unused-by-name params (prefixed with _), redundant mutability. From 113
warnings down to 14 (the 14 remaining are real signals: never-read
fields, unreachable patterns, etc., to be reviewed manually).
Leyoda 2026 – GPLv3
Two perf + correctness wins packaged as +yoda-v2 (version bump 0.1.0-yoda
-> 0.1.0-yoda.2):
1. color_picker::draw() — use the theme: &Theme parameter already passed
to draw() instead of THEME.lock().unwrap().clone() which cloned the
whole Theme on every redraw (src/widget/color_picker/mod.rs:622).
Upstreamable.
2. Dropped feature = "winit" from 21 combined cfg attrs in context_menu.rs,
menu/menu_bar.rs, menu/menu_inner.rs. These triple-gates (wayland +
winit + surface-message) were silently disabling all context-menu and
menubar popup creation in yoda apps (which don't activate the winit
feature). Now the code only gates on wayland + surface-message, which
is our actual runtime path. Matches the ungate we already did on
surface/action.rs in Phase 3d.
cargo check --lib passes. All 4 consumer apps rebuilt + installed as
+yoda-v2 (backup of previous yoda binaries in .pre-yoda-v2 siblings).
During Phase 3d it surfaced that several widgets keep a three-clause
cfg `#[cfg(all(feature = "winit", feature = "wayland", target_os = "linux"))]`
(e.g. dropdown::widget::with_popup, widget/mod.rs menu bits,
theme/style/mod.rs). Since the yoda fork is wayland-only the "winit"
clause is vestigial — dropping it unhides these methods for Wayland
consumers (cosmic-settings needs Dropdown::with_popup on the wallpaper
page).
Also fixed a cfg asymmetry in responsive_menu_bar.rs: the fallback
block was gated `cfg(not(all(winit, wayland, linux)))` while the
primary block was `cfg(all(wayland, linux))`. With winit removed both
blocks were active and we got E0308 expected-() — aligned the cfgs so
exactly one branch compiles.
Adds a new public enum `WindowControlsPosition { Start, End }` and a
matching field on `HeaderBar`, allowing window controls (close / minimize
/ maximize) to be packed on the start side of the headerbar (macOS
style, icon order close → minimize → maximize) instead of the default
end side (Linux / GNOME style, minimize → maximize → close).
Wiring:
- `crate::widget::WindowControlsPosition` re-exported alongside
`HeaderBar`.
- `HeaderBar::controls_position(Option<WindowControlsPosition>)` setter;
when left unset, falls back to `crate::config::window_controls_position()`
(reads `CosmicTk.window_controls_position`), mirroring how `density`
falls back to `header_size()`.
- New `CosmicTk.window_controls_position` field with default `End` for
backwards compatibility; serde-friendly enum so existing configs keep
working via `#[serde(default)]` semantics.
Tested with cosmic-yoterm, cosmic-settings, cosmic-edit, cosmic-files
rebuilt against this libcosmic via a local `[patch]` override. Config
changes picked up live through the existing cosmic-config subscription.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two independent bugs prevented tab drag-and-drop reorder from working
on cosmic-comp (and likely other compositors):
1. allow_reorder required DndAction::Move to be negotiated via
OfferEvent::SelectedAction, which cosmic-comp does not always emit
for self-drops (the SelectedAction event either never arrives or
arrives with DndAction::empty()). Add a fallback: accept self-drops
whenever state.dragging_tab is set. dragging_tab is only populated
by start_tab_drag on this same widget, so this is safe; mime match
and on_reorder presence are checked below.
2. reorder_event_for_drop preferred drop_hint.side over positional
swap, producing counter-intuitive no-ops: dropping A (pos 0) on the
left half of B (pos 1) resolved to "Before B" which, after removing
A, lands at pos 0 again — the tab appeared not to move. Always use
default_insert_position, which derives direction from dragged vs
target positions (Konsole/Firefox/Chrome-style swap semantics).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fires in addition to on_activate when the same entity is left-clicked
twice within 400 ms. Lets applications bind quick actions (e.g. rename
a tab) without blocking the normal single-click activation path.
- New Widget::on_double_click builder mirroring on_activate/on_close.
- last_click field on LocalState for timestamp tracking.
- Detection branch in the mouse handler after on_activate fires, so the
target entity is already focused when the callback runs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Model::clear() cloned the entire order VecDeque to iterate while
remove() mutated it, producing an O(n) allocation proportional to the
number of items — needless on a clear() which is going to drop all of
them anyway.
Replace the clone with std::mem::take(&mut self.order): we iterate the
taken VecDeque (transferring ownership), and the inner self.order.remove(index)
in each remove() call now finds position()==None and no-ops, since
self.order has been swapped with an empty default.
Same semantics, zero allocation. Noticeable on large nav/table models
(>100 items) and on apps that reset state frequently (settings pages,
file lists, context menus).
adds a feature to select from the start of the sentence until the last
occurrence of a character. This can be used to select until the
extension in cosmic-files save dialog or rename pop up.
Also, it adds a feature to select until the last occurrence of a
character on double-click.