[macOS] Récupérer la preview d'une NSFilePromiseReceiver avant la fin de la dragging operation

PyrohPyroh Membre
novembre 2021 modifié dans API AppKit #1

Salut à tous. En préambule, je me doute bien qu'il y a peu de chance d'avoir une réponse tant le topic est obscur. Mais je sais qu'ici certains ont des connaissances obscures, alors...

Pendant une dragging operation j'accepte les file URLs ainsi que les file promises, une URL temporaire générée quand on drag/drop une image (ou autre) qui vient d'un autre processus comme Safari.

Typiquement on doit accepter la promise et fournir un callback qui sera appelé plus tard (idéalement) hors main queue. Ça fonctionne correctement avec ce genre de code :

filePromiseReceiver.receivePromisedFiles(atDestination: self.destinationURL, options: [:], operationQueue: self.workQueue) { (fileURL, error) in
    if let error = error {
        self.handleError(error)
    } else {
        self.handleFile(at: fileURL)
    }
}

Le soucis c'est que le callback n'est appelé qu'une fois la dragging operation complétée. Et ce quel que soit le moment où receivePromisedFiles est appelée. Toute tentative d'obtenir une preview se solde alors par un échec.

J'avais plus ou moins abandonné l'idée jusqu'à ce que par inadvertance je drag une image au dessus de la start page de Safari et que je remarque que là une preview est affichée :

(J'ai entouré en rouge la photo draguée. Oui, j'ai gardé le petit chat en fond depuis)

Me doutant bien que Safari a des passes-droit j'ai lancé mon copain Hopper et je suis allé regarder sous ses jupes. Le résultat est décevant:

Safari doit être fondu dans le système et fouiller risque d'être long.

Pour le moment j'ai trouvé qu'il ne fallait pas trop compter sur NSFilePromiseReceiver vu que ces deux méthodes tendent à prouver qu'il fonctionne tel qu'il a été conçu:

Y'a pas plus de réponse sur le net.

Alors quelqu'un à une idée ? Obscure de préférence !

Mots clés:

Réponses

  • CéroceCéroce Membre, Modérateur

    Une idée vague, n'ayant jamais travaillé avec le glisser-déposer sur iOS. Mais sur Mac, je me souviens qu'on annonce ce qu'on va mettre dans le NSPasteboard et qu'on fournit une image pour la preview de ce qui va être glissé. Je sais que c'est un peu différent sous iOS, mais ça a l'air de s'appuyer sur les mêmes mécanismes.
    Aussi, ça pourrait être intéressant de voir comment on procède sur macOS.

  • Alors c'est sur macOS, je l'ai pas précisé (mais mis dans la section AppKit quand même 😉). J'ajoute un tag.

    Depuis macOS12 NSDraggingImage.draggedImage est déprécié et renvoie nil quelque soit la source —du moins dans mon cas. Le fix-it d'Xcode invite laconiquement à, je-cite, Use NSDraggingItem objects instead.

    J'utilise enumerateDraggingItems de NSDraggingInfo pour itérer les fichiers/promises et il me file des NSDraggingItem justement. Mais même avec ça je suis pas sorti du sable.

    Sur ces objets on retrouve une propriété imageComponents qui est un [NSDraggingImageComponent]?. S'il n'est pas nil il content 1 ou 2 objets NSDraggingImageComponent qui ont une propriété key égale à icon ou label. J'en ai déduit que l'objet icon représente l'image et celui label le nom une image du nom de fichier vu que celui-ci est absent quand on drag une image seule.

    Ces objets ont aussi une propriété contents typée Any mais le debugger me dit qu'en fait c'est _CDSlotProxy. Et personne —du moins Google, donc personne— ne sait ce qu'est un _CDSlotProxy. Ça ne se caste en rien de connu mais par introspection on apprend que c'est un NSObject et qu'il y a une unique propriété _slotID. Autant dire que le mystère est complet. Il reste la piste CGImage mais les types CF ça devient compliqué à caster...

    Maintenant si tu connais une méthode pour récupérer une preview depuis le NSPasteboard je suis preneur !

  • C’est celui que j’ai utilisé pour comprendre le truc et y’a rien vis à vis de mon soucis.

    J’ai trouvé d’autres exemples (antédiluviens) qui montrent comment modifier la drag image mais aucun ne le fait sur base de l’image en cours.

    J’ai continué de creuser et j’arrive dans Carbon et plus précisément HIToolbox. Et puis c’était largement fin de journée, on verra ça demain mais ça pue…
Connectez-vous ou Inscrivez-vous pour répondre.