Quickshell / collage : détecter les changements de sélection et expliciter les garanties de contenu #19

Closed
opened 2026-10-24 13:10:05 +00:00 by mathieu · 3 comments
Owner

Limite établie par le code

desktop-bridge.py:337–338 copie une entrée, shell.qml:121–129 attend 150 ms, puis panel-paste.py:55–71 vérifie deux fois la destination avant d’envoyer son raccourci ciblé. Ces protections de fenêtre sont bonnes, mais ni le contenu ni l’identité de la sélection copiée ne sont associés à la demande.

Si l’utilisateur, une application ou la synchronisation remplace le presse-papiers avant sa consommation, la bonne fenêtre peut coller un autre contenu, éventuellement sensible. Ce scénario n’a pas été testé sur le presse-papiers personnel. Une vérification tardive de hash seule n’apporterait pas l’atomicité.

Résultat attendu

Décision approuvée par Mathieu : conserver le collage ciblé en meilleure-effort, annuler sur changement observé et documenter les courses/couvertures restantes ; pas de garantie atomique ni d’attribution de source disponible.

  • Évaluer les signaux d’identité/génération de sélection disponibles avec l’architecture actuelle et annuler une demande en attente si elle a changé.
  • Préserver le ciblage par adresse et l’absence de frappe globale ou de retry d’une action incertaine.
  • Si une garantie atomique de contenu n’est pas disponible, documenter cette limite honnêtement ; ne pas promettre une livraison consommée à partir d’une copie réussie.
  • Ne pas ajouter une seconde base de presse-papiers ni journaliser des contenus/hashes personnels.

Validation

  • Notification native de changement observée après l’acquittement de copie : annulation avant raccourci.
  • Sélection inchangée : collage autorisé ; cible modifiée : toujours refusé.
  • Fermeture/onglet/reload, timeout et événements tardifs ne réarment pas une ancienne demande.
  • Texte et image de démonstration uniquement, sans frappe vers une vraie fenêtre.

Articulation

Le ticket #7 concerne d’autres raccourcis cliphist : lien de contexte seulement. Corriger ce comportement avant ou séparément de l’extraction du contrôleur de collage ; ne pas mêler garantie nouvelle et refactoring mécanique.

Référence

Revue du code au commit 5e350a8, avec Quickshell 0.3.2. Les 18 suites existantes passent ; les cas ci-dessous complètent cette couverture. Chantier : #11.

  • with pi 🥧
## Limite établie par le code `desktop-bridge.py:337–338` copie une entrée, `shell.qml:121–129` attend 150 ms, puis `panel-paste.py:55–71` vérifie deux fois la destination avant d’envoyer son raccourci ciblé. Ces protections de fenêtre sont bonnes, mais ni le contenu ni l’identité de la sélection copiée ne sont associés à la demande. Si l’utilisateur, une application ou la synchronisation remplace le presse-papiers avant sa consommation, la bonne fenêtre peut coller un autre contenu, éventuellement sensible. Ce scénario n’a pas été testé sur le presse-papiers personnel. Une vérification tardive de hash seule n’apporterait pas l’atomicité. ## Résultat attendu **Décision approuvée par Mathieu :** conserver le collage ciblé en meilleure-effort, annuler sur changement observé et documenter les courses/couvertures restantes ; pas de garantie atomique ni d’attribution de source disponible. - Évaluer les signaux d’identité/génération de sélection disponibles avec l’architecture actuelle et annuler une demande en attente si elle a changé. - Préserver le ciblage par adresse et l’absence de frappe globale ou de retry d’une action incertaine. - Si une garantie atomique de contenu n’est pas disponible, documenter cette limite honnêtement ; ne pas promettre une livraison consommée à partir d’une copie réussie. - Ne pas ajouter une seconde base de presse-papiers ni journaliser des contenus/hashes personnels. ## Validation - [x] Notification native de changement observée après l’acquittement de copie : annulation avant raccourci. - [x] Sélection inchangée : collage autorisé ; cible modifiée : toujours refusé. - [x] Fermeture/onglet/reload, timeout et événements tardifs ne réarment pas une ancienne demande. - [x] Texte et image de démonstration uniquement, sans frappe vers une vraie fenêtre. ## Articulation Le ticket #7 concerne d’autres raccourcis cliphist : lien de contexte seulement. Corriger ce comportement avant ou séparément de l’extraction du contrôleur de collage ; ne pas mêler garantie nouvelle et refactoring mécanique. ## Référence Revue du code [au commit `5e350a8`](https://git.2027a.net/mathieu/dotfiles/src/commit/5e350a8945af99e6e6b1c7f472fb7529a26a1826/quickshell/), avec Quickshell 0.3.2. Les 18 suites existantes passent ; les cas ci-dessous complètent cette couverture. Chantier : #11. - with pi 🥧
Author
Owner

Investigation sans accès au presse-papiers réel : Quickshell0.3.2 expose clipboardTextChanged, émis sur l’événement Qt sans lire forcément le texte. On peut compter ces signaux sans appeler le getter. Il ne fournit ni identité de source, ni génération attribuable à wl-copy, ni santé du canal. Qt6.12 peut recevoir des événements hors focus avec opt-in data-control et support du compositeur, non activés/testés ici. wl-paste --watch demanderait au contraire les données de la sélection, même si son enfant ignore stdin ; ce n’est pas un simple observateur de métadonnées.

Sources officielles versionnées : Quickshell qmlglobal, wl-clipboard watch. Le succès de wl-copy ordonne une requête de sélection via un roundtrip ; il ne donne pas une propriété durable de la sélection ni une preuve de consommation.

Choix à faire avant implémentation : conserver le collage ciblé en meilleure-effort avec annulation sur changements observés et documentation de la course résiduelle (recommandation parent pour préserver l’usage existant), ou imposer une garantie stricte que la pile actuelle ne fournit pas, donc repli sur Copier seulement. Aucun hash tardif ni simple compteur ne sera présenté comme atomicité/attribution certaine. Pas de nouveau démon ni lecture de contenu pour surveiller. Le parent soumet cet arbitrage dans la conversation.

  • with pi 🥧
Investigation sans accès au presse-papiers réel : Quickshell0.3.2 expose `clipboardTextChanged`, émis sur l’événement Qt sans lire forcément le texte. On peut compter ces signaux sans appeler le getter. Il ne fournit ni identité de source, ni génération attribuable à `wl-copy`, ni santé du canal. Qt6.12 peut recevoir des événements hors focus avec opt-in data-control et support du compositeur, non activés/testés ici. `wl-paste --watch` demanderait au contraire les données de la sélection, même si son enfant ignore stdin ; ce n’est pas un simple observateur de métadonnées. Sources officielles versionnées : [Quickshell qmlglobal](https://github.com/quickshell-mirror/quickshell/blob/4f508be500dea6e5732cc3d50382a0048b17e7b1/src/core/qmlglobal.cpp#L229), [wl-clipboard watch](https://github.com/bugaevc/wl-clipboard/blob/67a7b937895bceec1ae5ccebb10216f63f70ca1b/src/wl-paste.c#L248). Le succès de `wl-copy` ordonne une requête de sélection via un roundtrip ; il ne donne pas une propriété durable de la sélection ni une preuve de consommation. **Choix à faire avant implémentation :** conserver le collage ciblé en meilleure-effort avec annulation sur changements observés et documentation de la course résiduelle (recommandation parent pour préserver l’usage existant), ou imposer une garantie stricte que la pile actuelle ne fournit pas, donc repli sur Copier seulement. Aucun hash tardif ni simple compteur ne sera présenté comme atomicité/attribution certaine. Pas de nouveau démon ni lecture de contenu pour surveiller. Le parent soumet cet arbitrage dans la conversation. - with pi 🥧
Author
Owner

Mathieu a explicitement validé le maintien du collage ciblé en meilleure-effort, sans garantie d’atomicité. L’implémentation ajoutera une invalidation passive sur changements observés sans lire le texte/contenu et sans attribuer une génération à notre copie. Pas de wl-paste watch, nouveau démon, hash de contenu ou opt-in data-control global ; couverture Qt/compositeur et courses résiduelles documentées. Tests privés uniquement, pas de touche vers une vraie fenêtre.

  • with pi 🥧
Mathieu a explicitement validé le maintien du collage ciblé en meilleure-effort, sans garantie d’atomicité. L’implémentation ajoutera une invalidation passive sur changements observés sans lire le texte/contenu et sans attribuer une génération à notre copie. Pas de wl-paste watch, nouveau démon, hash de contenu ou opt-in data-control global ; couverture Qt/compositeur et courses résiduelles documentées. Tests privés uniquement, pas de touche vers une vraie fenêtre. - with pi 🥧
Author
Owner

Intégré et contenu distant vérifié sur main 65fa842 : productif3740955 et testcorrectife671788. Gate parent combiné24/24 suites passent, dont15 tests natifs du garde et11 du helper. Revue indépendante propre après correction d’une assertion regex inefficace : le nouveau contrôle positif échoue bien avec l’ancienne regex, puis passe corrigé ; retour de revue sans constat restant.

Conformément au choix de Mathieu, collage ciblé meilleure-effort, pas propriété/identité de sélection ni atomicité. Seule la notification native clipboardTextChanged est écoutée après acquittement de copie ; aucun getter, contenu, MIME, hash, démon, wl-paste watch, activation globale data-control ou configuration privée. Notification observée avant départ → timer annulé ; si helper lancé → annulation incertaine (TERM, escalade bornée, PID strictement positif, pas de retry). Les deux vérifications exactes de fenêtre sont conservées. Réinitialisation avant callback/réouverture et révisions locales UI rejettent les anciennes réponses ; pas de promesse « contenu toujours copié ».

Limites assumées et documentées : événements pré-acquittement non attribuables, signal de notre copie reçu tardivement pouvant annuler prudemment, couverture Qt possiblement absente hors focus, course après le dernier événement ou entre raccourci et lecture par l’application. Pas de notification ≠ sélection inchangée. Un arrêt/reload n’est pas un rollback d’un raccourci déjà envoyé ; le destructeur natif peut court-circuiter la grâce du helper. Ni consommation ni absence de touches après lancement ne sont garanties.

Preuve comportementale RED : neutraliser uniquement l’annulation sur notification dans une copie privée produit réellement started puis dispatch vers la fausse cible ; le test attend zéro envoi et échoue. Source corrigée : chemin normal envoie exactement une fois, événements après ack annulent, fausses notifications même-texte/image et événements tardifs/reload testés sans payload. Aucun presse-papiers/compositeur personnel ni vraie touche/appareil utilisé. Le checkout actif n’est pas avancé.

L’acceptation ci-dessous précise « notification observée » plutôt que génération de compositeur, indisponible dans cette architecture ; c’est le compromis approuvé, pas une identité inventée. #23 peut maintenant extraire mécaniquement ce comportement.

  • with pi 🥧
Intégré et contenu distant vérifié sur main [65fa842](https://git.2027a.net/mathieu/dotfiles/commit/65fa842ba11bc682778c039f86d3efdcbfd5918a) : productif3740955 et testcorrectife671788. **Gate parent combiné24/24 suites passent**, dont15 tests natifs du garde et11 du helper. Revue indépendante propre après correction d’une assertion regex inefficace : le nouveau contrôle positif échoue bien avec l’ancienne regex, puis passe corrigé ; retour de revue sans constat restant. Conformément au choix de Mathieu, collage ciblé **meilleure-effort**, pas propriété/identité de sélection ni atomicité. Seule la notification native `clipboardTextChanged` est écoutée après acquittement de copie ; aucun getter, contenu, MIME, hash, démon, `wl-paste watch`, activation globale data-control ou configuration privée. Notification observée avant départ → timer annulé ; si helper lancé → annulation incertaine (TERM, escalade bornée, PID strictement positif, pas de retry). Les deux vérifications exactes de fenêtre sont conservées. Réinitialisation avant callback/réouverture et révisions locales UI rejettent les anciennes réponses ; pas de promesse « contenu toujours copié ». **Limites assumées et documentées :** événements pré-acquittement non attribuables, signal de notre copie reçu tardivement pouvant annuler prudemment, couverture Qt possiblement absente hors focus, course après le dernier événement ou entre raccourci et lecture par l’application. Pas de notification ≠ sélection inchangée. Un arrêt/reload n’est pas un rollback d’un raccourci déjà envoyé ; le destructeur natif peut court-circuiter la grâce du helper. Ni consommation ni absence de touches après lancement ne sont garanties. Preuve comportementale RED : neutraliser uniquement l’annulation sur notification dans une copie privée produit réellement `started` puis `dispatch` vers la fausse cible ; le test attend zéro envoi et échoue. Source corrigée : chemin normal envoie exactement une fois, événements après ack annulent, fausses notifications même-texte/image et événements tardifs/reload testés sans payload. Aucun presse-papiers/compositeur personnel ni vraie touche/appareil utilisé. Le checkout actif n’est pas avancé. L’acceptation ci-dessous précise « notification observée » plutôt que génération de compositeur, indisponible dans cette architecture ; c’est le compromis approuvé, pas une identité inventée. #23 peut maintenant extraire mécaniquement ce comportement. - with pi 🥧
mathieu 2026-10-24 17:39:39 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
mathieu/dotfiles#19
No description provided.