diff --git a/README.md b/README.md index 4b9f607..8fcb61d 100644 --- a/README.md +++ b/README.md @@ -188,9 +188,26 @@ correspond » ; elles sont maintenant séparées : | Symptôme | Cause | | --- | --- | | `Authorization required` / `Invalid MIT-MAGIC-COOKIE-1 key` | cookie X introuvable ou périmé | -| `Aucune fenêtre visible sur DISPLAY=:0` | session Wayland, ou navigateur hors session | +| `Session Wayland : seule la fenêtre technique du compositeur est visible` | voir ci-dessous | +| `Aucune fenêtre visible sur DISPLAY=:0` | navigateur lancé hors de la session de l'agent | | Liste des fenêtres ouvertes | titre mal renseigné — recopier un fragment de la liste | +### Wayland + +Ubuntu démarre en session Wayland par défaut, et Firefox y tourne en client Wayland natif. +Une telle fenêtre est **invisible à xdotool** : ni activation, ni envoi de touche. Le +symptôme est net — côté X11, seule `mutter guard window` apparaît, la fenêtre technique du +compositeur. L'agent reconnaît cette signature et le dit explicitement. + +Deux issues : + +- **Rester en Wayland, passer Firefox sous XWayland.** L'agent pose `MOZ_ENABLE_WAYLAND=0` + en lançant le navigateur, ce qui suffit — *à condition qu'aucune instance Firefox ne + tourne déjà*. Firefox délègue l'URL à l'instance existante, qui garde ses propres + variables d'environnement : ferme toutes ses fenêtres avant de lancer la capture. +- **Ouvrir une session Xorg.** Sur l'écran de connexion GDM, roue dentée en bas à droite → + « Ubuntu sur Xorg ». Tout redevient pilotable, y compris une fenêtre ouverte à la main. + Si le rappel du plein écran s'avère fragile sur ta VM, l'alternative sans clavier est de lancer le navigateur en mode kiosque (`chromium --kiosk`) : il n'y a alors plus de plein écran à restaurer. diff --git a/packages/agent/src/browser.ts b/packages/agent/src/browser.ts index 726d31e..113aa21 100644 --- a/packages/agent/src/browser.ts +++ b/packages/agent/src/browser.ts @@ -48,7 +48,12 @@ export async function openUrl( const child = spawn(settings.command, args, { detached: true, stdio: 'ignore', - env: x11Env(), + // Sous une session Wayland, une fenêtre Firefox native est invisible à + // xdotool : ni activation, ni touche, donc pas de plein écran. XWayland la + // rend pilotable, sans rien changer à la lecture vidéo. Sans effet sur une + // session X11, et sans effet non plus si une instance Firefox tourne déjà — + // elle récupérerait l'URL avec ses propres variables d'environnement. + env: { ...x11Env(), MOZ_ENABLE_WAYLAND: '0' }, }); return new Promise((resolve, reject) => { diff --git a/packages/agent/src/doctor.ts b/packages/agent/src/doctor.ts index 42a80f2..8ed3ca6 100644 --- a/packages/agent/src/doctor.ts +++ b/packages/agent/src/doctor.ts @@ -3,6 +3,7 @@ import net from 'node:net'; import { promisify } from 'node:util'; import { WebSocket } from 'ws'; import { CONFIG_PATH, type AgentConfig } from './config.ts'; +import { looksLikeWayland } from './hotkey.ts'; import { resolveDisplay, resolveXauthority, x11Env } from './x11.ts'; const run = promisify(execFile); @@ -140,6 +141,16 @@ async function reportVisibleWindows(display: string): Promise { } } + if (looksLikeWayland(titles.map((title) => ({ id: '', title })))) { + line( + 'warn', + 'fenêtres', + `${ids.length} visible(s), toutes techniques (${titles.join(', ')}) — session Wayland : ` + + 'les fenêtres applicatives sont invisibles à xdotool', + ); + return; + } + line('ok', 'fenêtres', `${ids.length} visible(s)`); for (const title of titles) console.log(` · ${title}`); } diff --git a/packages/agent/src/hotkey.ts b/packages/agent/src/hotkey.ts index da8bd24..1a3775e 100644 --- a/packages/agent/src/hotkey.ts +++ b/packages/agent/src/hotkey.ts @@ -66,6 +66,22 @@ interface VisibleWindow { title: string; } +/** + * Fenêtres techniques des compositeurs. Sous Wayland, le serveur XWayland n'en + * expose qu'elles : les applications, elles, sont des clients Wayland natifs, + * invisibles à xdotool. N'avoir qu'elles à l'écran est donc une signature, pas + * un hasard — et le diagnostic doit le dire plutôt que de laisser croire à un + * titre de fenêtre mal renseigné. + */ +const COMPOSITOR_WINDOWS = [/^mutter guard window$/i, /^gnome-shell$/i, /^kwin/i, /^plasmashell$/i]; + +export function looksLikeWayland(windows: VisibleWindow[]): boolean { + return ( + windows.length > 0 && + windows.every((window) => COMPOSITOR_WINDOWS.some((pattern) => pattern.test(window.title))) + ); +} + /** * Traduit un échec de xdotool en cause identifiable. * @@ -171,9 +187,20 @@ function describeNoMatch(match: string, windows: VisibleWindow[]): string { if (windows.length === 0) { return ( `Aucune fenêtre visible sur DISPLAY=${display}. L'agent ne voit pas ta session ` + - 'graphique : soit le navigateur tourne dans une autre session, soit la session est ' + - 'en Wayland — une fenêtre Wayland native est invisible à xdotool. ' + - 'Lance Firefox avec MOZ_ENABLE_WAYLAND=0, ou ouvre une session Xorg.' + "graphique : le navigateur tourne-t-il bien sur cette machine, dans la session de " + + "l'utilisateur qui exécute l'agent ?" + ); + } + + if (looksLikeWayland(windows)) { + const only = windows.map((window) => `« ${window.title} »`).join(', '); + return ( + `Session Wayland : côté X11, seule la fenêtre technique du compositeur est visible ` + + `(${only}). Firefox y tourne en client Wayland natif — xdotool ne peut ni le voir ni ` + + 'lui envoyer de touche. Deux issues : relancer Firefox sous XWayland (ferme toutes ses ' + + "fenêtres d'abord, l'agent pose MOZ_ENABLE_WAYLAND=0 au lancement ; une instance déjà " + + "ouverte en Wayland récupérerait l'URL et le réglage resterait sans effet), ou ouvrir " + + 'une session Xorg depuis l\'écran de connexion GDM.' ); }