Browse / github.com/storytold/soundcraft / patch
Remember the native window and add GNOME Wayland caption buttons
Remember the native window and add GNOME Wayland caption buttons Windows should reopen at their last normal size, or maximized, at any interface size (150% included), and Restore after a maximized restart should return to the last normal size. On GNOME Wayland, where the compositor draws no frame, a native Wayland window (`SOUNDCRAFT_WAYLAND=1`; by default SoundCraft opens through XWayland, where GNOME draws the frame) also needs caption buttons. Changes: - Pin the Craft egui family to storytold/egui#3 (`69750b7`, on the 0.37 migration branch). That change stores the interface zoom with the saved geometry, keeps the last normal rectangle while the window i
- Status
- open
- Score
- 0.00
- Adopters
- 0 other operators
- Author
- abdallah-shehawey (imported from pull request #1108, open)
- Base
7dc56a4dbeebf57eacece09536726c57844fc59d- Size
- +247 −45 in 10 files
- Review
- pending
- Shared
- 2026-10-28
- Id
b87d3d145814f6763ac7df7f
How it went
No other operator has reported using it yet.
Diff
raw · ATTRIBUTION.md Cargo.lock Cargo.toml NOTICE ROADMAP.md apps/soundcraft/Cargo.toml apps/soundcraft/src/config.rs apps/soundcraft/src/main.rs contributors/people.toml docs/ui-parity.md
@@ -32,8 +32,8 @@ here. The subset uses default_fonts; the parent face uses monochrome_emoji_fonts | Asset | Author | Source | Licence | |---|---|---|---|-| `epaint_default_fonts/fonts/egui-icons.ttf` | John Slegers (emoji-icon-font) | https://github.com/storytold/egui/blob/6d518fc799681571963842f95b55a6b68431b15a/crates/epaint_default_fonts/fonts/egui-icons.txt; original https://github.com/jslegers/emoji-icon-font | MIT (complete copyright and permission text in NOTICE) |-| `epaint_default_fonts/fonts/emoji-icon-font.ttf` | John Slegers | https://github.com/storytold/egui/blob/6d518fc799681571963842f95b55a6b68431b15a/crates/epaint_default_fonts/fonts/emoji-icon-font-mit-license.txt; original https://github.com/jslegers/emoji-icon-font | MIT (complete copyright and permission text in NOTICE) |+| `epaint_default_fonts/fonts/egui-icons.ttf` | John Slegers (emoji-icon-font) | https://github.com/storytold/egui/blob/69750b71a97dc4672e2fbb70863b838e6795c910/crates/epaint_default_fonts/fonts/egui-icons.txt; original https://github.com/jslegers/emoji-icon-font | MIT (complete copyright and permission text in NOTICE) |+| `epaint_default_fonts/fonts/emoji-icon-font.ttf` | John Slegers | https://github.com/storytold/egui/blob/69750b71a97dc4672e2fbb70863b838e6795c910/crates/epaint_default_fonts/fonts/emoji-icon-font-mit-license.txt; original https://github.com/jslegers/emoji-icon-font | MIT (complete copyright and permission text in NOTICE) | ## Files @@ -8,6 +8,8 @@ version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e883d1d28c5fd5568c79ed2d2bd48d9f2fd3945c8974ed0f53690ceddb051be" dependencies = [+ "enumn",+ "serde", "uuid", ] @@ -125,6 +127,7 @@ dependencies = [ "cfg-if", "getrandom 0.3.4", "once_cell",+ "serde", "version_check", "zerocopy", ]@@ -227,6 +230,12 @@ dependencies = [ "x11rb", ] +[[package]]+name = "arrayref"+version = "0.3.9"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"+ [[package]] name = "arrayvec" version = "0.7.8"@@ -512,6 +521,9 @@ name = "bitflags" version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06"+dependencies = [+ "serde_core",+] [[package]] name = "block-buffer"@@ -1150,16 +1162,17 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "ecolor" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "bytemuck", "emath",+ "serde", ] [[package]] name = "eframe" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "ahash", "bytemuck",@@ -1181,7 +1194,9 @@ dependencies = [ "pollster 1.0.1", "profiling", "raw-window-handle",+ "ron", "send_wrapper",+ "serde", "static_assertions", "wasm-bindgen", "web-sys",@@ -1194,7 +1209,7 @@ dependencies = [ [[package]] name = "egui" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "accesskit", "ahash",@@ -1205,6 +1220,8 @@ dependencies = [ "log", "nohash-hasher", "profiling",+ "ron",+ "serde", "smallvec", "unicode-segmentation", "web-sys",@@ -1213,7 +1230,7 @@ dependencies = [ [[package]] name = "egui-wgpu" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "ahash", "bytemuck",@@ -1232,7 +1249,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "accesskit_winit", "arboard",@@ -1248,6 +1265,7 @@ dependencies = [ "parking_lot", "profiling", "raw-window-handle",+ "serde", "smithay-clipboard", "web-time", "webbrowser",@@ -1258,7 +1276,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "bytemuck", "egui",@@ -1271,7 +1289,7 @@ dependencies = [ [[package]] name = "egui_kittest" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "dify", "eframe",@@ -1297,9 +1315,10 @@ checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" [[package]] name = "emath" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "bytemuck",+ "serde", ] [[package]]@@ -1329,10 +1348,21 @@ dependencies = [ "syn 2.0.119", ] +[[package]]+name = "enumn"+version = "0.1.14"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"+dependencies = [+ "proc-macro2",+ "quote",+ "syn 2.0.119",+]+ [[package]] name = "epaint" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" dependencies = [ "ahash", "bytemuck",@@ -1346,6 +1376,7 @@ dependencies = [ "parking_lot", "profiling", "self_cell",+ "serde", "skrifa", "smallvec", "unicode-bidi",@@ -1358,7 +1389,7 @@ dependencies = [ [[package]] name = "epaint_default_fonts" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" [[package]] name = "equivalent"@@ -1502,6 +1533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "835ae9d781464a79026cde387f9cbc650c9a4909d7cf7e658b127e3c35d2f35d" dependencies = [ "bytemuck",+ "serde", ] [[package]]@@ -3518,6 +3550,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]]+name = "ron"+version = "0.12.2"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "81116b9531d61eabc41aeb228e4b6b2435bcca3233b98cf3b3077d4e6e9debb3"+dependencies = [+ "bitflags 2.13.2",+ "once_cell",+ "serde",+ "serde_derive",+ "typeid",+ "unicode-ident",+]+ [[package]] name = "rustc-hash" version = "1.1.0"@@ -3701,6 +3747,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]]+name = "sctk-adwaita"+version = "0.10.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec"+dependencies = [+ "log",+ "smithay-client-toolkit 0.19.2",+ "tiny-skia",+]+ [[package]] name = "security-framework" version = "3.7.0"@@ -3900,6 +3957,9 @@ name = "smallvec" version = "1.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0d5d4b1981b8bbbb7aed204cae5726d683d5d6ac7e74ec54122ea28f315e7c8"+dependencies = [+ "serde",+] [[package]] name = "smithay-client-toolkit"@@ -4251,6 +4311,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" +[[package]]+name = "strict-num"+version = "0.1.1"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"+ [[package]] name = "subtle" version = "2.6.1"@@ -4603,6 +4669,31 @@ dependencies = [ "time-core", ] +[[package]]+name = "tiny-skia"+version = "0.11.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab"+dependencies = [+ "arrayref",+ "arrayvec",+ "bytemuck",+ "cfg-if",+ "log",+ "tiny-skia-path",+]++[[package]]+name = "tiny-skia-path"+version = "0.11.4"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93"+dependencies = [+ "arrayref",+ "bytemuck",+ "strict-num",+]+ [[package]] name = "tinystr" version = "0.8.5"@@ -4741,6 +4832,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ce898823d8cd0f028662d2f349694b1af0a5cc9be83f1d213a00d3147445e1e" +[[package]]+name = "typeid"+version = "1.0.3"+source = "registry+https://github.com/rust-lang/crates.io-index"+checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"+ [[package]] name = "typenum" version = "1.20.1"@@ -5623,6 +5720,7 @@ dependencies = [ "raw-window-handle", "redox_syscall 0.4.1", "rustix 0.38.44",+ "sctk-adwaita", "smithay-client-toolkit 0.19.2", "smol_str", "tracing",@@ -6085,19 +6183,19 @@ dependencies = [ [[patch.unused]] name = "egui_demo_lib" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" [[patch.unused]] name = "egui_extras" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" [[patch.unused]] name = "egui_inspection" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910" [[patch.unused]] name = "egui_system_font_provider" version = "0.37.0"-source = "git+https://github.com/storytold/egui.git?rev=6d518fc799681571963842f95b55a6b68431b15a#6d518fc799681571963842f95b55a6b68431b15a"+source = "git+https://github.com/storytold/egui.git?rev=69750b71a97dc4672e2fbb70863b838e6795c910#69750b71a97dc4672e2fbb70863b838e6795c910"@@ -86,18 +86,18 @@ debug = 0 # Keep the complete egui family and native event bridge on reviewed fork commits. [patch.crates-io]-ecolor = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-emath = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-epaint = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-epaint_default_fonts = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui-winit = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui-wgpu = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui_glow = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui_extras = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui_kittest = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui_system_font_provider = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-eframe = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui_demo_lib = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }-egui_inspection = { git = "https://github.com/storytold/egui.git", rev = "6d518fc799681571963842f95b55a6b68431b15a" }+ecolor = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+emath = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+epaint = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+epaint_default_fonts = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui-winit = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui-wgpu = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui_glow = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui_extras = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui_kittest = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui_system_font_provider = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+eframe = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui_demo_lib = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" }+egui_inspection = { git = "https://github.com/storytold/egui.git", rev = "69750b71a97dc4672e2fbb70863b838e6795c910" } winit = { git = "https://github.com/storytold/winit.git", rev = "a517b3846ee8457d84ee4975110bfda6797c44dc" }@@ -20,7 +20,7 @@ Default egui fonts (dependency assets) The pinned egui 0.37 dependency embeds these faces through `default_fonts` and `monochrome_emoji_fonts`:-https://github.com/storytold/egui/tree/6d518fc799681571963842f95b55a6b68431b15a/crates/epaint_default_fonts/fonts+https://github.com/storytold/egui/tree/69750b71a97dc4672e2fbb70863b838e6795c910/crates/epaint_default_fonts/fonts No font file is copied into this repository. The full upstream notices follow. egui icon font subset (dependency asset)@@ -42,7 +42,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI Noto Emoji font (dependency asset) ---------------------------------- epaint_default_fonts 0.37, pinned with egui 0.37 at-https://github.com/storytold/egui/tree/6d518fc799681571963842f95b55a6b68431b15a/crates/epaint_default_fonts/fonts,+https://github.com/storytold/egui/tree/69750b71a97dc4672e2fbb70863b838e6795c910/crates/epaint_default_fonts/fonts, embeds NotoEmoji-Regular.ttf, the monochrome emoji fallback used when egui's `monochrome_emoji_fonts` feature is enabled. The font's copyright notice and the upstream SIL Open Font License 1.1 text follow unchanged.@@ -145,7 +145,7 @@ OTHER DEALINGS IN THE FONT SOFTWARE. Ubuntu Light font (dependency asset) ------------------------------------ epaint_default_fonts 0.37, pinned with egui 0.37 at-https://github.com/storytold/egui/tree/6d518fc799681571963842f95b55a6b68431b15a/crates/epaint_default_fonts/fonts,+https://github.com/storytold/egui/tree/69750b71a97dc4672e2fbb70863b838e6795c910/crates/epaint_default_fonts/fonts, embeds Ubuntu-Light.ttf as a default fallback. The font's copyright notice and the upstream Ubuntu Font Licence 1.0 text follow unchanged. @@ -251,7 +251,7 @@ DEALINGS IN THE FONT SOFTWARE. Hack font (dependency asset) ---------------------------- epaint_default_fonts 0.37, pinned with egui 0.37 at-https://github.com/storytold/egui/tree/6d518fc799681571963842f95b55a6b68431b15a/crates/epaint_default_fonts/fonts,+https://github.com/storytold/egui/tree/69750b71a97dc4672e2fbb70863b838e6795c910/crates/epaint_default_fonts/fonts, embeds Hack-Regular.ttf as the default monospace fallback. The upstream notice and licences follow unchanged. @@ -286,3 +286,29 @@ The Font Software may be sold as part of a larger software package but no copy o THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.++sctk-adwaita 0.10.1 — Wayland client window decorations+https://crates.io/crates/sctk-adwaita/0.10.1+Built without title fonts; caption controls are drawn as vectors.++MIT License++Copyright (c) 2022 Bartłomiej Maryńczak++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.@@ -1,8 +1,10 @@ # SoundCraft roadmap +> **Review follow-up (2026-10-26):** Control-channel runs start at the default window size and preserve the user's saved window geometry when saving other preferences. Regression coverage added; parity scores and estimates unchanged.+ **Stage: pre-alpha** · next: alpha, ~5% and ~110–180 h away (the alpha gate's three failing workflows) -> **Last reviewed:** 2026-10-24 · **Last updated:** 2026-10-25 · **Change:** trivial (side panels in dock columns, Auto Pan stereo balance, Clip List Auto Rename, Strip Silence rectangles, Strip Silence Rename, Strip Silence Extract and Separate, Clip Looping dialog, AudioSuite Vari-Fi speed ramps, Auto Pan plugin, Subharmonic plugin, Ring Modulator plugin, Float32 file headroom) · **Target:** Avid Pro Tools Ultimate 2026.4.1+> **Last reviewed:** 2026-10-24 · **Last updated:** 2026-10-26 · **Change:** trivial (windows reopen at their last size or maximized at any interface size (storytold/egui#3), side panels in dock columns, Auto Pan stereo balance, Clip List Auto Rename, Strip Silence rectangles, Strip Silence Rename, Strip Silence Extract and Separate, Clip Looping dialog, AudioSuite Vari-Fi speed ramps, Auto Pan plugin, Subharmonic plugin, Ring Modulator plugin, Float32 file headroom) · **Target:** Avid Pro Tools Ultimate 2026.4.1 SoundCraft is a clean-room, pure-Rust digital audio workstation that aims at full parity with Avid Pro Tools, and then beyond it: faster, open, scriptable and agent-controllable. This page is@@ -122,6 +124,9 @@ mutated and truncated movies. Field reports from the first public week are track ## Progress log +- 2026-10-26: Control-channel runs start at the default window size and preserve the user's saved window geometry when saving other preferences. Regression coverage added; scores and estimates unchanged.++- **2026-10-26:** Windows reopen at their last size, or maximized, at any interface size (such as 150%), and Restore after a maximized restart returns to the last normal size. On GNOME Wayland, where the compositor draws no frame, a native Wayland window (`SOUNDCRAFT_WAYLAND=1`; by default SoundCraft opens through XWayland, where GNOME draws the frame) gets standard minimize, maximize and close buttons. Shared change: storytold/egui#3; checked on Linux only. - **2026-10-25:** Tracks and Groups and the Clip List sit in dock columns that run the Edit window's full height at its left and right edges, with the MIDI Editor under the session view between them; Mix docks Tracks and Groups at its left edge. A panel dragged onto a dock group joins it as a tab, stacks above or below it, or makes a new column; one dragged to an empty window edge makes a dock there. A list with no saved place reopens in its dock, and makes the dock again when it is gone. Preferences and window configurations saved with the earlier split-frame layouts load with the new default layouts and keep their other settings. No readiness percentage change. - **2026-10-25:** Auto Pan moves the balance of a stereo track: the left channel's level falls as the position moves right and the right channel's as it moves left, at constant power, and each channel stays on its own side. At the center the track passes unchanged, so a wide or out-of-phase stereo image keeps its width, and the envelope follower follows the louder channel. No readiness percentage change. - **2026-10-24:** Clip List › Auto Rename (`clip.auto_rename`) sets the names that editing gives the clips it separates from the selected clips: a name, a starting number, a number of places (zeros before the number) and a suffix. The piece after each cut takes the next name, the piece before it keeps its name, and all the pieces count up one number sequence. Pieces that Strip Silence names with its own Rename fields, or removes, take no Auto Rename name. Copied clips keep their scheme when they are pasted, saved sessions hold the schemes, and Import Session Data brings them along. No readiness percentage change.@@ -176,6 +181,8 @@ mutated and truncated movies. Field reports from the first public week are track | Date | Change | Summary | |---|---|---|+| 2026-10-26 | trivial | Control-channel runs start at the default window size and preserve the user's saved window geometry when saving other preferences. Scores and estimates unchanged. |+| 2026-10-26 | trivial | Progress log: windows reopen at their last size or maximized at any interface size; standard caption buttons on native GNOME Wayland windows, `SOUNDCRAFT_WAYLAND=1` (storytold/egui#3) | | 2026-10-25 | trivial | Progress log: side panels in dock columns; readiness estimates unchanged | | 2026-10-25 | trivial | Progress log: Auto Pan stereo balance; readiness estimates unchanged | | 2026-10-24 | trivial | Progress log: Clip List Auto Rename; readiness estimates unchanged |@@ -18,7 +18,7 @@ asio = ["soundcraft-playback/asio"] soundcraft-engine.workspace = true soundcraft-ui-egui.workspace = true soundcraft-playback.workspace = true-eframe = { workspace = true, features = ["default_fonts", "wgpu", "accesskit", "wayland", "x11", "links", "clipboard"] }+eframe = { workspace = true, features = ["persistence", "default_fonts", "wgpu", "accesskit", "wayland", "x11", "links", "clipboard"] } egui = { workspace = true, features = ["default_fonts", "monochrome_emoji_fonts"] } serde_json.workspace = true log.workspace = true@@ -108,6 +108,18 @@ fn read_ui(path: &std::path::Path, recover_docking: bool) -> Result<Option<sound const MAX_UI_BYTES: u64 = 4 * 1024 * 1024; +/// Control sessions can save other preferences, but must preserve the user's window geometry.+pub fn save_ui_with_window_policy(path: &Path, ui: &soundcraft_ui_egui::UiState, persist_window: bool) -> Result<(), String> {+ if persist_window {+ return save_ui(path, ui);+ }+ let previous = load_ui(path)?.unwrap_or_default();+ let mut saved = ui.clone();+ saved.window_size = previous.window_size;+ saved.window_maximized = previous.window_maximized;+ save_ui(path, &saved)+}+ /// Write settings atomically. Preserve an unreadable or malformed existing file for recovery. pub fn save_ui(path: &std::path::Path, ui: &soundcraft_ui_egui::UiState) -> Result<(), String> { use std::io::Write as _;@@ -145,6 +157,28 @@ pub fn save_ui(path: &std::path::Path, ui: &soundcraft_ui_egui::UiState) -> Resu mod config_tests { use super::*; + #[test]+ fn control_run_saves_preserve_the_users_geometry_and_other_preference_changes() {+ use soundcraft_ui_egui::UiState;+ let directory = std::env::temp_dir().join(format!("soundcraft-control-window-prefs-{}", std::process::id()));+ let path = directory.join("ui.json");+ let _ = std::fs::remove_dir_all(&directory);+ let saved = UiState { window_size: [1100.0, 700.0], window_maximized: true, ..Default::default() };+ save_ui(&path, &saved).unwrap();+ let control = UiState { window_size: [1900.0, 1050.0], window_maximized: false, ui_scale: 1.5, ..Default::default() };+ save_ui_with_window_policy(&path, &control, false).unwrap();+ let reloaded = load_ui(&path).unwrap().unwrap();+ assert_eq!((reloaded.window_size, reloaded.window_maximized, reloaded.ui_scale), ([1100.0, 700.0], true, 1.5));+ save_ui_with_window_policy(&path, &control, true).unwrap();+ let reloaded = load_ui(&path).unwrap().unwrap();+ assert_eq!((reloaded.window_size, reloaded.window_maximized), ([1900.0, 1050.0], false));+ std::fs::remove_file(&path).unwrap();+ save_ui_with_window_policy(&path, &control, false).unwrap();+ let reloaded = load_ui(&path).unwrap().unwrap();+ assert_eq!((reloaded.window_size, reloaded.window_maximized), ([1600.0, 1000.0], false));+ std::fs::remove_dir_all(directory).unwrap();+ }+ #[test] fn native_file_reload_preserves_edit_mix_and_hidden_floating_panels() { use soundcraft_ui_egui::{MainWindow, Services, SoundApp, docking::Panel};@@ -23,7 +23,7 @@ use soundcraft_engine::Engine; use soundcraft_ui_egui::{Services, SoundApp, UiState, dialogs}; use std::sync::Arc; -struct App(SoundApp, Option<&'static logging::AppLogger>, #[cfg(target_os = "macos")] Option<native_menu::NativeMenu>);+struct App(SoundApp, Option<&'static logging::AppLogger>, bool, #[cfg(target_os = "macos")] Option<native_menu::NativeMenu>); /// Sends the title only when it changes, remembered here as X11 and Wayland can't read it back. fn set_title(ctx: &egui::Context, title: String) {@@ -35,6 +35,11 @@ fn set_title(ctx: &egui::Context, title: String) { } impl eframe::App for App {+ // Preferences have their own store; eframe persists only the native window.+ fn persist_egui_memory(&self) -> bool {+ false+ }+ /// Per-frame app logic: report audio-thread logs, run the shared app logic with the macOS menu driven around it, /// then handle dropped paths, quit/close requests, window geometry, recent-list persistence and the window title. fn logic(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {@@ -43,12 +48,12 @@ impl eframe::App for App { logger.report_audio_thread(); } #[cfg(target_os = "macos")]- if let Some(menu) = &mut self.2 {+ if let Some(menu) = &mut self.3 { menu.process(&mut self.0); } self.0.guarded(|app| app.logic(ctx)); #[cfg(target_os = "macos")]- if let Some(menu) = &mut self.2 {+ if let Some(menu) = &mut self.3 { menu.sync(&self.0); } // Files dropped on the window: audio on an instrument track or a Sampler window loads@@ -72,7 +77,7 @@ impl eframe::App for App { self.0.ui.ui_scale = self.0.extra.ui_scale; // Saved now rather than at exit: the recent list matters most after a crash. if self.0.take_recent_changed() {- save_prefs(&self.0.ui);+ save_prefs(&self.0.ui, self.2); } // With the system menu bar there is no egui bar showing the window and dirty state, so the // title carries them; elsewhere the egui menu bar already does.@@ -98,7 +103,7 @@ impl eframe::App for App { } fn on_exit(&mut self) { self.0.close_autosave();- save_prefs(&self.0.ui);+ save_prefs(&self.0.ui, self.2); if let Some(logger) = self.1 { logger.report_audio_thread(); }@@ -154,12 +159,13 @@ fn load_prefs() -> Option<UiState> { } } -fn save_prefs(ui: &UiState) {+/// Save preferences while keeping control-run geometry out of the user's window settings.+fn save_prefs(ui: &UiState, persist_window: bool) { if !prefs_enabled() { return; } if let Some(path) = prefs_path()- && let Err(error) = config::save_ui(&path, ui)+ && let Err(error) = config::save_ui_with_window_policy(&path, ui, persist_window) { log::warn!("{error}"); }@@ -257,7 +263,8 @@ fn main() -> eframe::Result { } let engine = if demo { soundcraft_engine::demo::demo_engine() } else { Engine::default() };- let prefs = load_prefs().unwrap_or_default();+ let persist_window = prefs_enabled() && control_port.is_none();+ let prefs = starting_prefs(load_prefs().unwrap_or_default(), persist_window); let mut options = eframe::NativeOptions { viewport: egui::ViewportBuilder::default() .with_title("SoundCraft")@@ -266,6 +273,9 @@ fn main() -> eframe::Result { .with_min_inner_size([960.0, 600.0]) .with_drag_and_drop(true) .with_app_id("ai.storyteller.soundcraft"),+ // No-preferences and control-channel runs neither restore nor save the native window, so+ // control-channel screenshots start from the same window every time.+ persist_window, ..Default::default() }; if let Some(icon) = app_icon() {@@ -319,6 +329,7 @@ fn main() -> eframe::Result { Ok(Box::new(App( app, logger,+ persist_window, #[cfg(target_os = "macos")] menu, )))@@ -326,6 +337,16 @@ fn main() -> eframe::Result { ) } +/// Automation starts from fixed geometry while retaining the other interface preferences.+fn starting_prefs(mut prefs: UiState, persist_window: bool) -> UiState {+ if !persist_window {+ let defaults = UiState::default();+ prefs.window_size = defaults.window_size;+ prefs.window_maximized = defaults.window_maximized;+ }+ prefs+}+ /// A saved window size, or the default when the prefs file holds nonsense (NaN, negative, tiny). fn sane_window_size([w, h]: [f32; 2]) -> [f32; 2] { if w.is_finite() && h.is_finite() && w >= 960.0 && h >= 600.0 { [w.min(16_384.0), h.min(16_384.0)] } else { [1600.0, 1000.0] }@@ -335,6 +356,15 @@ fn sane_window_size([w, h]: [f32; 2]) -> [f32; 2] { mod tests { use super::set_title; + #[test]+ fn control_runs_start_at_the_default_geometry_without_losing_other_preferences() {+ let saved = super::UiState { window_size: [1100.0, 700.0], window_maximized: true, ui_scale: 1.5, ..Default::default() };+ let normal = super::starting_prefs(saved.clone(), true);+ assert_eq!((normal.window_size, normal.window_maximized, normal.ui_scale), ([1100.0, 700.0], true, 1.5));+ let controlled = super::starting_prefs(saved, false);+ assert_eq!((controlled.window_size, controlled.window_maximized, controlled.ui_scale), ([1600.0, 1000.0], false, 1.5));+ }+ #[test] fn the_title_is_sent_only_when_it_changes() { let ctx = egui::Context::default();@@ -61,3 +61,6 @@ display_name = "Matt Smith-Burlage" [people.ProdByBuddha] sync_github_name = true++[people.abdallah-shehawey]+sync_github_name = true@@ -1,6 +1,8 @@ # UI parity -> **Last reviewed:** 2026-10-25 · **Last updated:** 2026-10-25 · **Change:** minor (Tracks and Groups and Clips in dock columns) · **Target:** Avid Pro Tools Ultimate 2026.4.1+> **Review follow-up (2026-10-26):** Control-channel runs start at the default window size and preserve the user's saved window geometry when saving other preferences. Regression coverage added; parity scores and estimates unchanged.+>+> **Last reviewed:** 2026-10-25 · **Last updated:** 2026-10-26 · **Change:** minor (window size and maximized state survive restarts at any interface size; caption buttons on native GNOME Wayland windows, `SOUNDCRAFT_WAYLAND=1`, storytold/egui#3; Tracks and Groups and Clips in dock columns) · **Target:** Avid Pro Tools Ultimate 2026.4.1 How SoundCraft feels in the hands of a Pro Tools user: tools, modes, modifiers, shortcuts, windows, meters. Measured from `crates/model/src/session.rs` (tools, modes), the command@@ -69,6 +71,8 @@ Legend: ✅ matches · 🟡 partial · ❌ missing. | Date | Change | Summary | |---|---|---|+| 2026-10-26 | trivial | Control-channel runs start at the default window size and preserve the user's saved window geometry when saving other preferences. Scores and estimates unchanged. |+| 2026-10-26 | trivial | Window size and maximized state survive restarts at any interface size; standard caption buttons on native GNOME Wayland windows, `SOUNDCRAFT_WAYLAND=1` (storytold/egui#3) | | 2026-10-25 | minor | Edit and Mix windows: Tracks and Groups and Clips in full-height dock columns. Readiness estimate unchanged | | 2026-10-16 | minor | Track name menu: Scroll Into View brings the track to the top of the Edit window and the left of the Mix. Readiness estimate unchanged | | 2026-10-13 | minor | A plugin opens when it's inserted (#486) |