swayfx-mosaic/docs/STEP20A.md

9.9 KiB

STEP20A — fondation Spatial Canvas native

Base et provenance

  • Installation protégée : paquet Arch swayfx 0.6-1, binaire /usr/bin/sway, swayfx version 0.6 (based on sway 1.12.0). pacman -Qkk swayfx : 58 fichiers, aucun altéré.
  • Source amont : https://github.com/WillPower3309/swayfx, tag 0.6, commit fd71a6bdc061bd633b488ae7b83e8a6981d22f86 ; la branche master courante n'a pas été utilisée.
  • Bibliothèques installées : wlroots0.20 0.20.2-1 (pkg-config wlroots-0.20 : 0.20.2), scenefx 0.5-1 (pkg-config scenefx-0.5 : 0.5.0). Le tag demande wlroots-0.20 >=0.20,<0.21 et scenefx-0.5.
  • Le cache AUR local contient un PKGBUILD 0.5.3-4. Le dépôt AUR distant, commit 55c2e27f83e54eadd9d811bc123b868e6ba56866, contient 0.6-0, alors que le paquet local est 0.6-1 ; celui-ci a donc une recette ou révision locale qui n'est plus disponible ici. Les métadonnées du paquet ne contiennent pas son archive source ni son commit. La correspondance binaire exacte au commit du tag n'est donc pas démontrable. Le tag 0.6 est la base vérifiable qui reproduit la version annoncée et se compile avec les dépendances installées.
  • Options Arch pertinentes reprises : -Dwerror=false -Dsd-bus-provider=libsystemd, avec les bibliothèques système ci-dessus. -Dwerror=true échoue aussi sur une incompatibilité amont avec libinput 1.32.0 : le switch de sway/ipc-json.c ne traite pas LIBINPUT_CONFIG_SCROLL_CIRCULAR.

Baseline avant modification

meson setup build-baseline -Dwerror=false -Dsd-bus-provider=libsystemd
meson compile -C build-baseline -j 8
meson test -C build-baseline --print-errorlogs
build-baseline/sway/sway --version

Résultat : build PASS, binaire répond swayfx version 0.6-fd71a6b ... (based on sway 1.12.0). Meson indique No tests defined. pour l'amont. Aucune installation système. La baseline binaire reste dans build-baseline/sway/sway, SHA-256 5c377fdd5b6f72d343699dd1949956dfa73fe08b7c5dd305c45a5bb020bd8ccb ; elle a été construite avant la première modification fonctionnelle et n'a pas été reconstruite depuis.

Validation du fork

meson setup build-mosaic -Dwerror=false -Dsd-bus-provider=libsystemd \
  -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
meson install -C build-mosaic --destdir /tmp/step20a-stage
git diff --check

Résultat : build PASS ; modèle 1/1 PASS ; headless IPC et six fenêtres Kitty PASS ; installation de staging limitée au binaire ; git diff --check PASS. La validation de la configuration quotidienne par /usr/bin/sway -C -c /home/fy59/.config/sway/config retourne 0 ; wlroots y écrit deux diagnostics EGL EGL_BAD_ALLOC, sans démarrer de session ni invalider la configuration.

Carte des points d'insertion

Couche Fichier/fonction Rôle et point d'insertion
Arbre include/sway/tree/container.h, workspace.h Enum de layout, workspace et listes tiling/floating ; état Mosaic attaché au workspace.
Insertion/suppression sway/tree/workspace.c:workspace_add_tiling, sway/tree/view.c:view_map, sway/tree/container.c:container_detach L'ordre de workspace->tiling fait autorité pour Row0. Insertion après le dernier actif, nettoyage de la référence de focus à la sortie.
Géométrie logique sway/tree/arrange.c:arrange_workspace, apply_horiz_layout Calcule pending et les tailles des enfants. En STEP20A, Mosaic emprunte le calcul horizontal standard.
Transaction/scène sway/desktop/transaction.c:arrange_children, arrange_workspace_tiling Applique l'état current, reparent les scènes et positionne les containers. Le nouvel enum doit passer ici également.
Output/rendu sway/desktop/output.c (wlr_scene_output_build_state) Composition de la scène dans le buffer d'output.
Clipping sway/tree/view.c:view_center_and_clip_surface, sway/desktop/transaction.c:arrange_container Clip de contenu au rectangle d'une vue, pas un clip général du viewport Mosaic.
Hit testing sway/input/cursor.c:node_at_coords Interroge wlr_scene_node_at ; toute translation de caméra devra conserver la correspondance avec la scène interactive.
Focus/move sway/commands/focus.c, move.c, sway/input/seat.c:seat_set_workspace_focus Navigation directionnelle, réorganisation et dernier focus par ligne ; aucune nouvelle touche n'est câblée ici.
IPC sway/ipc-json.c:ipc_json_describe_workspace, ipc_json_layout_description, sway/ipc-server.c get_tree publie layout: "mosaic" ; get_workspaces et les événements continuent par les chemins Sway existants.
Parser sway/commands/layout.c:cmd_layout layout mosaic active explicitement le mode sur le workspace ; les layouts classiques restent disponibles.

État réalisé

Workspace 1 (layout=mosaic, opt-in)
└── Row0 (children emprunte workspace->tiling)
    ├── A
    ├── B
    └── C
    scroll_x = 1200 (coordonnée logique, non rendue en STEP20A)
    focused = B
active_row = 0

mosaic_workspace_state possède les objets mosaic_row, jamais les containers Sway. Row0 emprunte workspace->tiling, sans copie de l'ordre. Les autres lignes ont leur propre liste dans le modèle et sont vérifiées par test unitaire ; leur branchement à l'arbre, aux transactions et à l'IPC attend une tranche ultérieure. Un scroll_x négatif ou non fini est refusé. Changer le focus ou scroll_x ne réordonne pas les enfants. L'état est libéré avec le workspace et reste dormant si l'on repasse à un layout classique.

La première ligne reste tiled et non flottante. Le test headless a observé A B C, puis A X B C après focus de A et création de X, puis A X B après fermeture de C. Un move right suivi de move left garde Mosaic actif et permet ensuite d'insérer Y immédiatement après X. Après retour à splith, Mosaic peut être réactivé sur un workspace occupé et la nouvelle fenêtre s'insère encore après A. Le test vérifie aussi des rectangles sans chevauchement et floating_nodes=[]. Ce n'est pas encore une ligne plus large que le viewport ni un POC graphique scrollable : aucun ratio de largeur de cellule n'a été fixé.

Exécution et coexistence

Le fork produit build-mosaic/sway/swayfx-mosaic. L'option Meson mosaic-package=true installe seulement ce binaire. La vérification meson install -C build-mosaic --destdir /tmp/step20a-stage n'a produit que /tmp/step20a-stage/usr/bin/swayfx-mosaic. Le paquet Arch futur pourra dépendre des bibliothèques communes et déclarer ce seul chemin ; il ne doit déclarer ni provides=sway, ni conflicts=swayfx, ni installer les fichiers /etc/sway, swaymsg, swaybar, les complétions ou la session sway.desktop déjà possédés par SwayFX. Une session dédiée, sous un autre nom, sera une étape ultérieure. Aucun fichier de /usr n'a été modifié ici.

Activation dans le seul processus du fork : swaymsg -s <socket-du-fork> 'layout mosaic'. Le socket explicite est essentiel en test : une commande envoyée à la session quotidienne n'active rien dans le fork. La session actuelle n'a pas été relancée ou rechargée.

Compatibilité et limites

  • IPC : get_tree annonce mosaic sur le workspace, en conservant les noeuds Sway et leurs identités. get_workspaces et les événements utilisent les chemins existants. Les clients qui traitent les layouts comme un enum fermé doivent ajouter mosaic avant de restaurer ce workspace.
  • QuickShell : les vues générales IPC peuvent lire l'arbre ; session_v2/schema.py limite explicitement LAYOUTS à splith, splitv, tabbed, stacked, et session_v2/snapshot.py a aussi une condition sur les layouts à un enfant. STEP20E devra représenter les lignes, l'ordre, active_row, scroll_x et le focus de chaque ligne, avec des identités stables de fenêtres et un ordre de restauration défini. Aucun fichier QuickShell n'a été modifié dans STEP20A.
  • Scratchpad, floating et fullscreen : les chemins Sway existants sont conservés. Le test vérifie le tiling normal, mais ne constitue pas encore une validation exhaustive des transitions scratchpad, floating et fullscreen sous Mosaic.
  • Clavier : $mod+Alt+m ouvre Applications. $mod+Alt+l est libre et réservé au futur sélecteur de layout, sans commande factice. Son ancien usage Applications a été retiré. Le bind limusic-app qui occupait $mod+Alt+m a été supprimé ; son autostart reste en place. $mod+s, $mod+Shift+w, $mod+e restent inchangés. Aucun reload de la session actuelle n'a été déclenché.

Risques et STEP20B

La scène wlroots peut positionner les noeuds indépendamment de leur ordre logique. Le moteur d'output compose déjà la partie visible dans le buffer physique, mais un vrai viewport Mosaic doit définir une translation de caméra et un clip par workspace/ligne pour éviter qu'une portion hors viewport apparaisse sur un autre output. Le clip existant des surfaces ne fournit pas cette frontière. Le hit testing utilise la scène ; l'offset visuel et les rectangles des commandes focus/move doivent rester cohérents. La transaction distingue pending et current et possède des animations : le déplacement de caméra doit être appliqué au bon instant, sans saut ni divergence IPC. Les changements d'output, de taille et de workspace doivent recalculer le viewport sans perdre scroll_x.

STEP20B doit livrer une première ligne réellement plus large que son viewport, scrollable par une commande native explicite, avec largeur temporaire isolée et configurable sans imposer de politique UX finale. Il doit relier géométrie logique, translation de scène, clip, input et focus directionnel ; couvrir les transactions et les changements de workspace/output par tests headless. Le modèle des lignes supplémentaires sera raccordé après la preuve d'une ligne utilisable.