From 170bc7796be78025288bf5e021f288e9debf96fb Mon Sep 17 00:00:00 2001 From: fy59 Date: Sat, 10 Oct 2026 06:22:12 +0200 Subject: [PATCH] docs(repo): establish mosaic project contract --- .gitignore | 7 ++ CHANGELOG.md | 31 +++++ CONTRIBUTING.md | 263 ++++++------------------------------------ NOTICE.md | 14 +++ README.md | 268 +++++++++++++++++++++---------------------- docs/ARCHITECTURE.md | 133 +++++++++++++++++++++ docs/DEVELOPMENT.md | 120 +++++++++++++++++++ docs/ROADMAP.md | 94 +++++++++++++++ docs/UPSTREAM.md | 50 ++++++++ 9 files changed, 617 insertions(+), 363 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 NOTICE.md create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/DEVELOPMENT.md create mode 100644 docs/ROADMAP.md create mode 100644 docs/UPSTREAM.md diff --git a/.gitignore b/.gitignore index 446beea..a037e1e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,10 @@ result # ignore the build output from build.sh opt/ + +# Arch package build output +/pkg/ +/src/ +*.pkg.tar.* +.SRCINFO.tmp +.SRCINFO diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..171dc65 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,31 @@ +# Changelog + +## Unreleased + +### Added + +- native Mosaic / Spatial Canvas layout foundation; +- workspace-local Mosaic state; +- real tiled Row 0 backed by the Sway tree; +- insertion/reflow/focus model tests; +- `layout mosaic` support; +- workspace-local `layout toggle mosaic`; +- logical row scrolling and first viewport translation; +- Mosaic IPC state in `get_tree`; +- headless compositor validation; +- isolated Arch packaging path for `/usr/bin/swayfx-mosaic`; +- architecture, development, upstream and roadmap documentation. + +### Safety + +- ordinary SwayFX remains installed separately and untouched; +- no automatic session replacement; +- no package `conflicts`, `replaces` or `provides` against SwayFX. + +### Known limitations + +- multi-output viewport clipping is not yet production-ready; +- multi-row Canvas behavior is not implemented; +- camera animation is not final; +- Session V2 does not yet restore Mosaic state; +- the final cell sizing/reflow policy is not frozen. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4f043f7..45cbf97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,245 +1,54 @@ -# Contributing to sway +# Contributing -Contributing just involves sending a pull request. You will probably be more -successful with your contribution if you visit #sway-devel on Libera Chat -upfront and discuss your plans. +SwayFX Mosaic is experimental compositor work. Changes should stay narrowly focused on the Mosaic / Spatial Canvas layout and its packaging/tests. -Note: rules are made to be broken. Adjust or ignore any/all of these as you see -fit, but be prepared to justify it to your peers. +## Before changing code -## Scope of future changes to sway +Read: +- `README.md` +- `docs/ARCHITECTURE.md` +- `docs/DEVELOPMENT.md` +- `docs/UPSTREAM.md` -**Important**: Sway has completed its core value proposition: it is a fully -featured Wayland-compatible replacement for i3. It is not our intention to -expand on the scope of what i3 aims to accomplish. Our priorities now are -increasing the stability, reliability, and performance of sway within its -current scope. For this reason, most new window management feature requests are -not accepted, even if accompanied by a patch. +## Scope -## Pull Requests +Appropriate contributions include: +- Mosaic layout model; +- geometry, viewport and scene behavior; +- focus/input behavior required by Mosaic; +- IPC additions required to expose Mosaic state; +- Mosaic tests; +- patch maintenance and packaging. -If you already have your own pull request habits, feel free to use them. If you -don't, however, allow me to make a suggestion: feature branches pulled from -upstream. Try this: +Desktop shell features, themes, personal key bindings and unrelated SwayFX customizations belong elsewhere. -1. Fork sway -2. `git clone https://github.com/username/sway && cd sway` -3. `git remote add upstream https://github.com/swaywm/sway` +## Required checks -You only need to do this once. You're never going to use your fork's master -branch. Instead, when you start working on a feature, do this: +At minimum: -1. `git fetch upstream` -2. `git checkout -b add-so-and-so-feature upstream/master` -3. Add and commit your changes -4. `git push -u origin add-so-and-so-feature` -5. Make a pull request from your feature branch - -When you submit your pull request, your commit log should do most of the talking -when it comes to describing your changes and their motivation. In addition to -this, your pull request's comments will ideally include a test plan that the -reviewers can use to (1) demonstrate the problem on master, if applicable and -(2) verify that the problem no longer exists with your changes applied (or that -your new features work correctly). Document all of the edge cases you're aware -of so we can adequately test them - then verify the test plan yourself before -submitting. - -## Commit Messages - -Please strive to write good commit messages. Here's some guidelines to follow: - -The first line should be limited to 50 characters and should be a sentence that -completes the thought [When applied, this commit will...] *"Implement -cmd_move"* or *"Fix #742"* or *"Improve performance of arrange_windows on ARM"* -or similar. - -The subsequent lines should be separated from the subject line by a single -blank line, and include optional details. In this you can give justification -for the change, [reference Github -issues](https://help.github.com/articles/closing-issues-via-commit-messages/), -or explain some of the subtler details of your patch. This is important because -when someone finds a line of code they don't understand later, they can use the -`git blame` command to find out what the author was thinking when they wrote -it. It's also easier to review your pull requests if they're separated into -logical commits that have good commit messages and justify themselves in the -extended commit description. - -As a good rule of thumb, anything you might put into the pull request -description on Github is probably fair game for going into the extended commit -message as well. - -See [here](https://chris.beams.io/posts/git-commit/) for more details. - -## Code Review - -When your changes are submitted for review, one or more core committers will -look over them. Smaller changes might be merged with little fanfare, but larger -changes will typically see review from several people. Be prepared to receive -some feedback - you may be asked to make changes to your work. Our code review -process is: - -1. **Triage** the pull request. Do the commit messages make sense? Is a test - plan necessary and/or present? Add anyone as reviewers that you think should - be there (using the relevant GitHub feature, if you have the permissions, or - with an @mention if necessary). -2. **Review** the code. Look for code style violations, naming convention - violations, buffer overflows, memory leaks, logic errors, non-portable code - (including GNU-isms), etc. For significant changes to the public API, loop in - a couple more people for discussion. -3. **Execute** the test plan, if present. -4. **Merge** the pull request when all reviewers approve. -5. **File** follow-up tickets if appropriate. - -## Style Reference - -Sway is written in C with a style similar to the [kernel -style](https://www.kernel.org/doc/Documentation/process/coding-style.rst), but -with a few notable differences. - -Try to keep your code conforming to C11 and POSIX as much as possible, and do -not use GNU extensions. - -### Brackets - -Brackets always go on the same line, including in functions. -Always include brackets for if/while/for, even if it's a single statement. -```c -void function(void) { - if (condition1) { - do_thing1(); - } - - if (condition2) { - do_thing2(); - } else { - do_thing3(); - } -} +```sh +meson compile -C build-mosaic -j 8 +meson test -C build-mosaic --print-errorlogs +python tests/headless-ipc.py +git diff --check ``` -### Indentation +For upstream rebases, also rebuild the pristine baseline and validate the standard Sway layouts. -Indentations are a single tab. +## Compatibility -For long lines that need to be broken, the continuation line should be indented -with an additional tab. +Do not introduce a package conflict with ordinary `swayfx`. -If the line being broken is opening a new block (functions, if, while, etc.), -the continuation line should be indented with two tabs, so they can't be -misread as being part of the block. +Do not install over `/usr/bin/sway`. -```c -really_long_function(argument1, argument2, ..., - argument3, argument4); +Do not treat QuickShell or an external daemon as the authoritative Mosaic state store. -if (condition1 && condition2 && ... - condition3 && condition4) { - do_thing(); -} -``` +## Commits -Try to break the line in the place which you think is the most appropriate to -balance the lines. +Keep commits reviewable and explain: +- the compositor invariant being changed; +- why the change belongs in Mosaic; +- the validation performed; +- any known limitation. -### Line Length - -Try to keep your lines under 80 columns, assuming a tab width equal to 4 spaces, -but you can go up to 100 if it improves readability. Don't break lines -indiscriminately, try to find nice breaking points so your code is easy to read. - -### Names - -Global function and type names should be prefixed with `sway_submodule_` (e.g. -`struct sway_output`, `sway_output_destroy`). For static functions and -types local to a file, the names chosen aren't as important. Static functions -shouldn't have a `sway_` prefix. - -For include guards, use the header's filename relative to include. Uppercase -all of the characters, and replace any invalid characters with an underscore. - -### Construction/Destruction Functions - -For functions that are responsible for constructing and destructing an object, -they should be written as a pair of one of two forms: - -* `init`/`finish`: These initialize/deinitialize a type, but are **NOT** - responsible for allocating it. They should accept a pointer to some - pre-allocated memory (e.g. a member of a struct). -* `create`/`destroy`: These also initialize/deinitialize, but will return a - pointer to a `malloc`ed chunk of memory, and will `free` it in `destroy`. - -A destruction function should always be able to accept a NULL pointer or a -zeroed value and exit cleanly; this simplifies error handling a lot. - -### Error Codes - -For functions not returning a value, they should return a (stdbool.h) bool to -indicated if they succeeded or not. - -### Macros - -Keep the use of macros to a minimum, especially if a function can do the job. If -you do need to use them, try to keep them close to where they're being used and -`#undef` them after. - -### Example - -```c -struct wlr_backend *wlr_backend_autocreate(struct wl_display *display) { - struct wlr_backend *backend; - if (getenv("WAYLAND_DISPLAY") || getenv("_WAYLAND_DISPLAY")) { - backend = attempt_wl_backend(display); - if (backend) { - return backend; - } - } - - const char *x11_display = getenv("DISPLAY"); - if (x11_display) { - return wlr_x11_backend_create(display, x11_display); - } - - // Attempt DRM+libinput - - struct wlr_session *session = wlr_session_create(display); - if (!session) { - wlr_log(WLR_ERROR, "Failed to start a DRM session"); - return NULL; - } - - int gpu = wlr_session_find_gpu(session); - if (gpu == -1) { - wlr_log(WLR_ERROR, "Failed to open DRM device"); - goto error_session; - } - - backend = wlr_multi_backend_create(session); - if (!backend) { - goto error_gpu; - } - - struct wlr_backend *libinput = wlr_libinput_backend_create(display, session); - if (!libinput) { - goto error_multi; - } - - struct wlr_backend *drm = wlr_drm_backend_create(display, session, gpu); - if (!drm) { - goto error_libinput; - } - - wlr_multi_backend_add(backend, libinput); - wlr_multi_backend_add(backend, drm); - return backend; - -error_libinput: - wlr_backend_destroy(libinput); -error_multi: - wlr_backend_destroy(backend); -error_gpu: - wlr_session_close_file(session, gpu); -error_session: - wlr_session_destroy(session); - return NULL; -} -``` +Never hide failed tests or force-apply the Mosaic patch to an unvalidated upstream revision. diff --git a/NOTICE.md b/NOTICE.md new file mode 100644 index 0000000..5c09edb --- /dev/null +++ b/NOTICE.md @@ -0,0 +1,14 @@ +# Notice + +SwayFX Mosaic is a derivative development project based on SwayFX and Sway. + +- SwayFX: https://github.com/WillPower3309/swayfx +- Sway: https://github.com/swaywm/sway + +The repository retains the upstream MIT license in `LICENSE`. + +The Mosaic-specific work adds an experimental Spatial Canvas layout, associated IPC/state handling, tests and packaging. It does not claim ownership of the Sway/SwayFX codebase or assets inherited from upstream. + +Project repositories: +- https://git.labfytools.com/fy59/swayfx-mosaic +- https://github.com/labfytools/swayfx-mosaic diff --git a/README.md b/README.md index 21e8000..904bdcf 100644 --- a/README.md +++ b/README.md @@ -1,166 +1,162 @@ -

- swayfx logo -

+# SwayFX Mosaic +**SwayFX Mosaic** is an experimental SwayFX variant that adds a native **Mosaic / Spatial Canvas** tiling layout. -Sway is an incredible window manager, and certainly one of the most well established wayland window managers. However, it is restricted to only include the functionality that existed in i3. This fork ditches the simple wlr_renderer, and replaces it with our fx_renderer, capable of rendering with fancy GLES2 effects. This, along with a couple of minor changes, expands sway's featureset to include the following: +The goal is not to replace SwayFX, reimplement tiling in userspace, or turn the desktop into a floating-window canvas. Mosaic stays inside the compositor and keeps real Sway containers, workspaces, IPC, fullscreen, floating windows and scratchpad semantics. -+ **Blur** -+ **Anti-aliased rounded corners, borders, and titlebars** -+ **Shadows** -+ **Dim unfocused windows** -+ **Scratchpad treated as minimize**: Allows docks, or panels with a taskbar, to correctly interpret minimize / unminimize requests ([thanks to LCBCrion](https://github.com/swaywm/sway/issues/6457)) -+ **nixify the repo**: Allows nixos users to easily contribute to and test this project +> Status: active development. The compositor is not installed as the daily SwayFX session yet. -

- - -

+## Why Mosaic? -For Fedora users, SwayFX is also available in [copr](https://copr.fedorainfracloud.org/coprs/swayfx/swayfx/) or in the [Terra repository](https://terra.fyralabs.com). +Classic tiling is constrained by the physical viewport. Mosaic introduces a logical canvas made of horizontal rows that may extend beyond the visible output. -[Join our Discord](https://discord.gg/qsSx397rkh) - -## New Configuration Options - -+ Window blur: - - `blur enable|disable` - - `blur_xray enable|disable`: this will set floating windows to blur based on the background, not the windows below. You probably want to set this to `disable` :) - - `blur_passes ` - - `blur_radius ` - - `blur_noise ` - - `blur_brightness ` - - `blur_contrast ` - - `blur_saturation ` -+ Corner radius: `corner_radius ` -+ Window shadows: - - `shadows enable|disable` - - `shadows_on_csd enable|disable` (**Note**: The shadow might not fit some windows) - - `shadow_blur_radius ` - - `shadow_color ex, #0000007F` - - `shadow_offset ` - - `shadow_inactive_color ex, #0000007F` -+ LayerShell effects (to blur panels / notifications etc): - - `layer_effects ` - - The current layer namespaces can be shown with `swaymsg -r -t get_outputs | jq '.[0].layer_shell_surfaces | .[] | .namespace'` - - Example: `layer_effects "waybar" blur enable; shadows enable; corner_radius 6` - - Note: If an application uses gtk, its namespace is likely to be "gtk-layer-shell" - - SwayIPC Example: `swaymsg layer_effects "waybar" "blur enable"` (you can only set one effect at a time through `swaymsg`) - - Config Example: - ``` - layer_effects "waybar" { - blur enable; - blur_xray enable; - blur_ignore_transparent enable; - shadows enable; - corner_radius 20; - } - ``` - - Available Effects: - - `blur ` - - `blur_xray ` - - `blur_ignore_transparent ` - - `shadows ` - - `corner_radius ` - - `reset`: To reset/disable all previously applied effects to the layer application -+ Dim unfocused windows: - - `default_dim_inactive ` - - `for_window [CRITERIA_HERE] dim_inactive ` - - `dim_inactive_colors.unfocused ex, #000000FF` - - `dim_inactive_colors.urgent ex, #900000FF` -+ Keep/remove separator border between titlebar and content: `titlebar_separator enable|disable` -+ Treat Scratchpad as minimized: `scratchpad_minimize enable|disable`: **we recommend keeping this setting off, as there are many kinks to iron out here** - -## Roadmap - -+ fade in / out animations -+ window movement animations - -## Compiling From Source - -### Nix - -If you have Nix installed, you can build and run SwayFX easily: - -``` -nix build -./result/bin/sway +```text +Workspace +└── Mosaic Canvas + ├── Row 0: [A][B][C][D]... + ├── Row 1: [E][F][G]... + └── ... ``` -You can also bring up a development shell and follow the build instructions below, without installing all of the dependencies manually: +Each row owns its viewport position and last focused container. The compositor remains the source of truth for order, geometry, focus and scrolling. -``` -nix develop -``` -### Debian +## Core rules -Check [INSTALL-deb.md](/INSTALL-deb.md) +- real tiled Sway containers; no floating-window simulation; +- Mosaic is opt-in per workspace; +- standard Sway/SwayFX layouts remain available; +- workspaces continue to exist normally; +- Mosaic state lives in the compositor, not in QuickShell; +- the standard `swayfx` package must remain untouched and independently updatable; +- the Mosaic package installs a separate `/usr/bin/swayfx-mosaic` binary; +- our production artifact is a minimal, reviewable patch on a pinned SwayFX upstream revision. -### Container (Docker) +## Package model -To build SwayFX inside a container, install Docker and run the following commands from inside this repository: +```text +swayfx +└── /usr/bin/sway -```bash -# build the container and run it (which builds SwayFX) -docker compose up --build - -# become root to install the previously built files -sudo bash - -# copy all files into the host file system at /usr/local/ -while read -r FILE; do - NEW_FILE=/usr/local${FILE#opt} - NEW_DIR=$(dirname "${NEW_FILE}") - [[ -d ${NEW_DIR} ]] || mkdir -p "${NEW_DIR}" - - echo "Creating '${NEW_FILE}'" - cp "${FILE}" "${NEW_FILE}" -done < <(command find opt/ -type f) +swayfx-mosaic +└── /usr/bin/swayfx-mosaic ``` -### Manual Steps +`swayfx-mosaic` must not declare `provides`, `conflicts` or `replaces` against SwayFX. An upstream SwayFX update must never be blocked by this project. -Install dependencies: +The Arch packaging path is intentionally patch-based: -* meson \* -* wlroots -* wayland -* wayland-protocols \* -* pcre2 -* json-c -* pango -* cairo -* [scenefx](https://github.com/wlrfx/scenefx) -* gdk-pixbuf2 (optional: additional image formats for system tray) -* [swaybg] (optional: wallpaper) -* [scdoc] (optional: man pages) \* -* git (optional: version info) \* +```text +pinned SwayFX upstream + + +Mosaic patch set + ↓ +/usr/bin/swayfx-mosaic +``` -_\* Compile-time dep_ +See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) and [docs/UPSTREAM.md](docs/UPSTREAM.md). -Run these commands: +## Layout switching - meson build/ - ninja -C build/ - sudo ninja -C build/ install +The target desktop contract is: -On systems without logind nor seatd, you need to suid the sway binary: +```text +Super + Alt + M → Applications +Super + Alt + L → Standard layout ↔ Mosaic +``` - sudo chmod a+s /usr/local/bin/sway +The compositor command is: -SwayFX will drop root permissions shortly after startup. +```text +layout toggle mosaic +``` -## Contributing +Each workspace remembers its previous standard layout, so a toggle behaves conceptually like: -SwayFX would love to receive any new features that you're willing to build! Generally, we'd like to focus on eye-candy type improvements to keep our scope appropriate. If you'd like to build something that you think may be out of that focus, please raise an issue and we can discuss whether or not it will fit within this project. +```text +tabbed → mosaic → tabbed +splith → mosaic → splith +``` -## Acknowledgements +The key binding itself belongs to the user's dotfiles, not to this package. -The SwayFX team would like to first and foremost thank the maintainers and contributors of the Sway window manager. We are but a humble group of Sway enthusiasts who wanted to expand upon your creation. +## Current implementation -We would also like to thank the talented artists in our community for contibuting the visual assets that give this project charm: -+ pkdesuwu and honchokomodo for creating the swayfx mascot: https://twitter.com/pkdesuwu/status/1664517033017368576 -+ spooky_skeleton for the swayfx logo, and [Basil](https://basil.cafe) for making some fine adjustments to it +The current development tree contains the native Mosaic foundation and the first single-row viewport work: -Lastly, we would like to thank you, the community, for enjoying and using window manager that we have spent so much time maintaining. +- native `L_MOSAIC` layout; +- workspace-local Mosaic state; +- ordered Row 0 backed by real `workspace->tiling` containers; +- insertion after the active container; +- workspace-local previous-layout memory; +- `layout toggle mosaic`; +- logical `scroll_x`; +- first scene translation / single-row viewport implementation; +- IPC exposure through `get_tree`; +- model and headless compositor tests; +- Arch package staging limited to `swayfx-mosaic`. +Multi-row behavior, robust multi-output clipping, final sizing policy, camera animation and session restore integration are still development work. + +Technical reports: +- [STEP20A — native foundation](docs/STEP20A.md) +- [STEP20B — first scrollable row](docs/STEP20B.md) + +## Development + +Baseline: + +```sh +meson setup build-baseline -Dwerror=false -Dsd-bus-provider=libsystemd +meson compile -C build-baseline +``` + +Mosaic build: + +```sh +meson setup build-mosaic \ + -Dwerror=false \ + -Dsd-bus-provider=libsystemd \ + -Dmosaic-package=true \ + -Dprefix=/usr -Dbindir=bin \ + -Dswaybar=false -Dswaynag=false \ + -Dman-pages=disabled -Ddefault-wallpaper=false + +meson compile -C build-mosaic +meson test -C build-mosaic --print-errorlogs +python tests/headless-ipc.py +``` + +See [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) for the full workflow. + +## Repository layout + +```text +docs/ design, roadmap and validation reports +patches/ production delta against pinned SwayFX +tests/ Mosaic model and headless compositor tests +tooling/ patch/export maintenance helpers +PKGBUILD coexistence-oriented Arch package +``` + +The full SwayFX source remains in the development tree for compositor work. The patch set is the reviewable production delta. + +## Upstream and license + +SwayFX Mosaic is derived from [SwayFX](https://github.com/WillPower3309/swayfx), itself based on [Sway](https://github.com/swaywm/sway). + +Current base: +- SwayFX tag `0.6`; +- commit `fd71a6bdc061bd633b488ae7b83e8a6981d22f86`; +- Sway 1.12.0 base; +- wlroots 0.20 series; +- SceneFX 0.5 series. + +The project keeps the upstream MIT license. See [LICENSE](LICENSE) and [NOTICE.md](NOTICE.md). + +## Mirrors + +Canonical development repository: +- Forgejo: `https://git.labfytools.com/fy59/swayfx-mosaic` + +Public mirror: +- GitHub: `https://github.com/labfytools/swayfx-mosaic` diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..f895ad8 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,133 @@ +# Architecture + +## Scope + +Mosaic / Spatial Canvas is an additional native SwayFX layout. It is not a separate window manager model layered above IPC and it is not a QuickShell feature. + +The compositor owns: +- container order; +- row membership; +- logical geometry; +- active row; +- per-row scroll position; +- per-row focus memory; +- scene translation; +- hit testing consistency. + +QuickShell may display this state later, but must not duplicate or authoritatively store it. + +## Logical model + +```text +MosaicWorkspaceState +├── active_row +├── previous_standard_layout +└── rows[] + ├── ordered children + ├── scroll_x + └── focused child +``` + +The first row directly borrows `workspace->tiling`, keeping the existing Sway tree authoritative. + +Four concepts must remain separate: + +1. logical order; +2. calculated geometry; +3. viewport/camera; +4. focus. + +Changing the camera must not reorder containers. Changing focus must not change logical order. + +## Layout semantics + +Mosaic is opt-in per workspace through: + +```text +layout mosaic +``` + +The bidirectional UX command is: + +```text +layout toggle mosaic +``` + +Entering Mosaic records the current standard layout. Leaving Mosaic restores that layout for the same workspace. + +Standard layouts continue to work inside `swayfx-mosaic`; changing process or restarting the compositor is not part of layout switching. + +## Tiling invariants + +- containers remain Sway tiled nodes; +- no overlaps in the logical tiling geometry; +- no internal holes after insertion/removal; +- insertion occurs next to the active logical container; +- deletion triggers reflow; +- a row can extend beyond the physical viewport; +- `scroll_x` is bounded to the logical row extent; +- focusing an off-screen cell may bring it into view; +- floating, fullscreen and scratchpad use normal Sway paths and are not reimplemented as Mosaic concepts. + +## Scene and viewport + +The logical row may be wider than the output. Mosaic therefore needs a camera transform between logical tiled geometry and visible scene coordinates. + +The output viewport is not the layout itself. + +STEP20B currently proves the single-row translation path. Multi-output correctness still requires explicit clipping or an equivalent SceneFX/wlroots strategy so content from one workspace viewport cannot leak onto an adjacent output. + +Hit testing must remain aligned with the translated scene. + +## IPC + +Existing Sway IPC contracts remain primary: +- `get_tree`; +- `get_workspaces`; +- window events; +- workspace events. + +A Mosaic workspace exposes `layout: "mosaic"` and may expose an additional Mosaic object describing rows, focus and scroll state. + +Consumers that treat layouts as a closed enum must explicitly add Mosaic support. + +## Package isolation + +The normal package owns the normal compositor: + +```text +swayfx → /usr/bin/sway +``` + +This project owns only the alternate binary and project-specific files: + +```text +swayfx-mosaic → /usr/bin/swayfx-mosaic +``` + +No file owned by `swayfx` may be overwritten. + +The package must not declare itself a replacement for SwayFX. + +## Patch maintenance + +The installed Mosaic build is produced from: +1. a pinned, known SwayFX upstream commit; +2. the Mosaic patch set; +3. Mosaic tests; +4. a package recipe that checks the expected upstream commit. + +A new SwayFX version is never accepted implicitly. The patch must be rebased/reviewed and all standard-layout plus Mosaic tests rerun. + +## Session restore + +The existing external Session V2 system will eventually need to persist: +- Mosaic activation; +- ordered rows; +- row membership; +- active row; +- each row's `scroll_x`; +- each row's remembered focus; +- stable window identities. + +That integration belongs to a later step and must not turn Session V2 into the runtime source of truth. diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md new file mode 100644 index 0000000..8534e3a --- /dev/null +++ b/docs/DEVELOPMENT.md @@ -0,0 +1,120 @@ +# Development workflow + +## Safety rule + +Development must not replace the daily SwayFX installation or reload the active desktop session. + +Use separate build directories and headless compositor tests. + +## Upstream + +The initial supported base is SwayFX 0.6 at: + +```text +fd71a6bdc061bd633b488ae7b83e8a6981d22f86 +``` + +The `upstream` remote must point to the SwayFX repository. + +## Baseline build + +```sh +meson setup build-baseline \ + -Dwerror=false \ + -Dsd-bus-provider=libsystemd + +meson compile -C build-baseline -j 8 +meson test -C build-baseline --print-errorlogs +``` + +The upstream base currently defines no Meson tests. + +## Mosaic build + +```sh +meson setup build-mosaic \ + -Dwerror=false \ + -Dsd-bus-provider=libsystemd \ + -Dmosaic-package=true \ + -Dprefix=/usr \ + -Dbindir=bin \ + -Dswaybar=false \ + -Dswaynag=false \ + -Dman-pages=disabled \ + -Ddefault-wallpaper=false + +meson compile -C build-mosaic -j 8 +meson test -C build-mosaic --print-errorlogs +python tests/headless-ipc.py +git diff --check +``` + +## Package staging + +Never install to the live system as part of routine validation. + +```sh +rm -rf /tmp/swayfx-mosaic-stage +meson install -C build-mosaic --destdir /tmp/swayfx-mosaic-stage +find /tmp/swayfx-mosaic-stage -type f -print +``` + +The staging manifest must remain limited to the Mosaic-owned artifact(s), currently `/usr/bin/swayfx-mosaic`. + +## Patch export + +The development tree contains the full source because compositor work is easier there. The distributable delta lives under `patches/`. + +Use the project tooling to regenerate the patch after source changes, then verify: + +```sh +git apply --check patches/0001-mosaic-layout-viewport.patch +``` + +The patch must correspond to the pinned upstream commit used by `PKGBUILD`. + +## Arch package + +```sh +makepkg --printsrcinfo +makepkg --verifysource +``` + +A full package build is expected before a release, not necessarily after every edit. + +The package must not: +- replace `swayfx`; +- conflict with `swayfx`; +- provide `sway`; +- install `/usr/bin/sway`; +- install the user's QuickShell configuration or personal dotfiles. + +## Updating upstream + +When SwayFX publishes a new version: + +1. fetch `upstream`; +2. inspect relevant compositor changes; +3. create a dedicated rebase/update branch; +4. update the pinned source revision; +5. reapply or rewrite the Mosaic patch; +6. build the new upstream baseline; +7. build Mosaic; +8. run model/headless tests; +9. test standard Sway layouts; +10. only then bump the Mosaic package version. + +If the patch does not apply cleanly, stop and adapt it manually. + +## Daily-session integration + +The final package is intentionally independent from the user's desktop configuration. + +The user's dotfiles may launch `swayfx-mosaic` in a dedicated session and bind: + +```text +Super+Alt+M → Applications +Super+Alt+L → layout toggle mosaic +``` + +Those bindings are not packaged here. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..82d8b8f --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,94 @@ +# Roadmap + +## STEP20A — compositor foundation + +Status: implemented. + +- identify exact SwayFX baseline; +- native Mosaic layout enum/parser; +- workspace-local state; +- real tiled containers; +- insertion/removal/focus invariants; +- IPC exposure; +- isolated build and headless tests; +- package staging without replacing SwayFX. + +See [STEP20A.md](STEP20A.md). + +## STEP20B — first scrollable row + +Status: experimental implementation present in the development tree. + +- single logical row wider than the viewport; +- workspace-local standard ↔ Mosaic toggle; +- logical `scroll_x`; +- scene translation; +- focus visibility; +- headless rendering/IPC validation; +- package patch export. + +See [STEP20B.md](STEP20B.md). + +## STEP20C — viewport correctness + +Planned. + +- robust clipping at workspace/output boundaries; +- multi-output validation; +- resize/output migration tests; +- pointer/hit-testing validation; +- camera animation without transaction divergence. + +## STEP20D — multi-row Spatial Canvas + +Planned. + +- multiple native rows; +- active-row navigation; +- row-local scroll/focus memory; +- move/reorder within a row; +- move containers between rows; +- deterministic reflow. + +Target interaction model: + +```text +Super + arrows navigation +Super + Ctrl + ... reorder/modify within row +Super + Shift + Up/Down move between rows +``` + +Exact bindings remain subject to validation before they become permanent. + +## STEP20E — Session V2 persistence + +Planned. + +Persist and restore: +- Mosaic layout state; +- ordered rows; +- active row; +- scroll positions; +- row focus; +- stable window identities. + +The compositor remains the runtime source of truth. + +## STEP20F — QuickShell integration + +Planned. + +- expose Mosaic state visually; +- adapt workspace overview; +- optional layout state indication; +- no duplicate Mosaic state in QML. + +## STEP20G — packaging and daily use + +Planned. + +- final Arch package; +- dedicated desktop/session entry if useful; +- standard SwayFX fallback preserved; +- update/rebase procedure proven against a newer upstream SwayFX release; +- documentation for installation, rollback and troubleshooting. diff --git a/docs/UPSTREAM.md b/docs/UPSTREAM.md new file mode 100644 index 0000000..cd36c71 --- /dev/null +++ b/docs/UPSTREAM.md @@ -0,0 +1,50 @@ +# Upstream relationship + +SwayFX Mosaic is intentionally maintained as a small feature delta above SwayFX. + +## Initial base + +- Project: SwayFX +- Upstream: https://github.com/WillPower3309/swayfx +- Tag: `0.6` +- Commit: `fd71a6bdc061bd633b488ae7b83e8a6981d22f86` +- Sway base reported by SwayFX: 1.12.0 +- wlroots ABI used by this base: 0.20 +- SceneFX ABI used by this base: 0.5 + +The original local Arch package was `swayfx 0.6-1`. Its exact build-source commit could not be reconstructed, so the signed/verifiable project base is the public upstream 0.6 tag commit rather than a claim of byte-for-byte equivalence with that package. + +## Remote policy + +Local development uses: + +```text +upstream → SwayFX upstream +origin → Forgejo canonical repository +github → GitHub mirror +``` + +Only the project remotes receive Mosaic commits. + +Do not push Mosaic branches to `upstream`. + +## Version policy + +Mosaic versions follow the SwayFX base explicitly. + +Example: + +```text +swayfx 0.6 +swayfx-mosaic 0.6+mosaic.1 +``` + +A future SwayFX 0.7 does not automatically imply a working Mosaic 0.7 package. The patch must be rebased and validated first. + +## Why a separate binary? + +SwayFX does not expose a stable runtime plugin ABI for injecting a new layout. Mosaic therefore cannot be shipped as a small external `.so` while leaving the running `/usr/bin/sway` binary unchanged. + +The package instead builds the compositor with the Mosaic delta but installs it under a different executable name. + +This preserves the operational requirement that ordinary SwayFX can continue to update and remain a safe fallback.