Depuis un prog cocoa, je peux charger le eco18 pour le jouer dans une fenêtre. Je peux aussi lui passer des paramètres (ça s'appelle input splitter dans Quartz Composer).
J'ai modifié (légèrement) le eco18 en ajoutant un input splitter de type Image. Cet input a été relié à la première image (celle de TextEdit je crois) de la Macro "windows" (et remplace le input Image Importer "TextEdit")
Dans le prog, j'ai récupéré une image d'une fenêtre à l'écran, et je l'ai passé en paramètre à l'input.
J'ai ensuite lancé l'animation.
Résultat : j'ai bien une image de ma fenêtre qui danse dans l'animation.
Conclusion : pas besoin de récupérer le contenu des fenêtres en fichier. Tout peut rester en mémoire.
Maintenant, messieurs les grapheux, à vous de jouer, sachant que les programmeux vous fourniront des données de type image, des numeriques (position x & y et taille largeur & hauteur de la fenêtre à l'écran).
Pour les images, il y aura l'image de fond, et les quelques images (5 j'ai cru lire plus haut) des fenêtres standards présentes à l'écran.
Ben chez moi, WindowGrab plante (voir fichier de log)... G5 Bi 2.5, 2 Go RAM, Os X 10.4.2, 2 écrans, ....
Le petit test que je vous ai joint fait le strict minimum. Il n'y a aucun test, ni contrôle des valeurs de retour des appels des différentes fonctions du Core Graphics.
Or, certaines fenêtres ont des configs très bizarres du style taille à 0 ou profondeur de couleur à 1 bit (au lieu de 32 bits usuellement). Ces fenêtres sont mal capturées, et peuvent provoquer des plantages. Il faut normalement les éliminer de la liste des fenêtres visibles (ce que je n'ai pas fait).
Oui ! Géant ! Nous les grapheux, on va essayez de préparer la 19
MAIS, qu'en est-il de la récupération de la profondeur ? Première fenêtre jusqu'à dernière fenêtre ??? C'est hyper important dans notre cas. Hein ? ???
J'ai réfléchit a tout ça... autant du coté programmeux que grapheux. Je pense qu'il est temps qu'on se fixe des objectifs à atteindre pour la version 1 de l'économiseur : Je serais ravi d'avoir sur ces point l'avis de Bru et de Boris Cargo (je donne le mien entre parenthèses) :
- Partons-nous sur un nombre de fenêtre fixe, ou serait-il paramêtrable dans les préférences de l'économiseur : 5 par défaut, variable de 3 à 20. (Si vous vous sentez, je préfèrerai que ce soit paramêtrable dès la version 1, sachant que ça va tourner sur des machines très différentes en terme de puissance. Peut-on imaginer une valeur par défaut qui se rêgle automatiquement en fonction de la machine détectée ?)
- Vu le fait que finalement, on peut récupérer n'importe quelle fenêtre (et non plus uniquement les COCOA), on a plus besoin d'avoir un fondu en début d'animation (voir ma version eco17v3). Ca va vraiment simplifier. Confirmez-vous cela ?
- Il faut définir une liste de variables (input spliter), avec le nom exact, et la fonction exacte. Qui s'y colle ? (je pense qu'il vaut mieux que ce soit le programmeux.)
- Le module graphique n'a pas besoin d'obtenir la taille des images via des input spliter. Seul l'image elle même, et ces coordonnées de position en pixel sont nessecaisse. (QC sait lire la taille d'une image qu'on lui donne)
- Message au programmeux : il est prévu un input spliter "On Off" qui libère ou qui ramène l'ensemble de l'animation des fenêtres. C'est automatique. Il suffit de le passer à 1 (True) quand tout est prêt a être animé, et à 0 (False) quand on veux que toutes les fenêtres reviennent en place. Voir ma version eco17v3 où cet input spliter est implémenté.
- Je repose ici ma question sur la notion d'ordre (de profondeur) des fenêtres. Donc... la récupère-t-on ? (sans quoi c'est la cata...). A noter que c'est le programmeux qui doit les envoyer à QC dans l'ordre inverse : fond est rendu en premier, puis ima1, puis ima2, puis ima3... etc... ce qui fait que c'est la dernière imaX envoyé qui apparaà®tra au premier plan puisque c'est la dernière à être rendue.
- Question au grapheux : comptes-tu faire passer le fond au rang d'une simple fenêtre... (j'ai bien lu que t'as finalement pas trop de raison de la laisser mise de coté). Il me semble que ça simplifirai le tout. Mais c'est toi le chef !
- Proposition au grapheux : ne pourrait-on pas filer le plus rapidement possible une version avec tous les inputs spliters définitifs (qu'on va lister ci-dessus) au programmeux, même si l'animation n'est pas fignolée. Comme ça, vous pourrez avancer en parallèle ?! Oui ? Je peux m'y coller si tu veux. Ca je sais faire !
- Enfin, question au programeux : est-il possible, dans un économiseur d'écran, de se passer du fondu au noir lorsqu'il s'active ?
- Et, dans le même genre, toujours dans un eco d'écran, est-il possible qu'il ne quitte QUE lorsque toutes les fenêtres sont revenues en place ? Genre, on bouge la souris, le système demande à l'éco d'écran de quitter ; ce dernier prend le temps (très rapide) de faire revnir toutes les fenêtres, et enfin il quitte. (ma crainte, c'est que quand on bouge la souris, ce soit fait de telle manière que le système masque et force a quitter instantanément l'eco d'écran ; ce qui serait dommage : on ne verrai pas les fenêtres toutes revenir très vite...)
Voilà !
Une chose très importante : si vous trouver que je n'use pas de la bonne méthode pour aider à faire avancer le projet avec toutes ces question, il faut me le dire. Je le prendrai pas mal. Je ne souhaite qu'une chose, c'est qu'il voit le jour !
pour le fun, j'ai regardé un peu. En mettant un break sur CGContextCopyWindowCaptureContentsToRect (0x90504600) on a bien une interruption lorsqu'on capture une fenêtre. En regardant les arguments j'ai pas réussi à avoir grand chose (je débute), dans r3 on a "<NSCFType: 0x3ab150>" et on a un argument en r1. J'ai pas retrouvé le symbole avec otool, donc apparemment y'a qu'un seul argument mais je ne l'affirme pas. En désassemblant, on trouve qu'il y a un appel à "contextCopyWindowContentsToRect". Bon ça fait pas vraiment avancer le truc... c'était juste pour regarder...
Je suis plus intéressé par la démarche que par la finalité, je cherche à mieux me servir de gdb... donc coups de main / indices bienvenus.
pour le fun, j'ai regardé un peu. En mettant un break sur CGContextCopyWindowCaptureContentsToRect (0x90504600) on a bien une interruption lorsqu'on capture une fenêtre. En regardant les arguments j'ai pas réussi à avoir grand chose (je débute), dans r3 on a "<NSCFType: 0x3ab150>" et on a un argument en r1. J'ai pas retrouvé le symbole avec otool, donc apparemment y'a qu'un seul argument mais je ne l'affirme pas. En désassemblant, on trouve qu'il y a un appel à "contextCopyWindowContentsToRect". Bon ça fait pas vraiment avancer le truc... c'était juste pour regarder...
Je suis plus intéressé par la démarche que par la finalité, je cherche à mieux me servir de gdb... donc coups de main / indices bienvenus.
CGContextCopyWindowCaptureContentsToRect utilise 5 arguments en entrée (je te laisse chercher un peu...) et aucun argument en retour.
R1 n'est pas un argument (il pointe sur la frame de la fonction courante). R3 est effectivement le 1er argument, et il contient un CGContextRef.
CGContextCopyWindowCaptureContentsToRect utilise 5 arguments en entrée (je te laisse chercher un peu...) et aucun argument en retour.
R1 n'est pas un argument (il pointe sur la frame de la fonction courante). R3 est effectivement le 1er argument, et il contient un CGContextRef.
Bon courage pour la suite...
.
merci, sympa 8) Ah zut je croyait que r3 était toujours le registre de retour. Bon j'ai tous les registres sous les yeux, "y'a plus qu'à " chercher ce qu'ils représentent.
houlà , que de changements ce WE. Terrible, ce projet va enfin prendre vie. Cool.
dans 1134338370:
sachant que ça va tourner sur des machines très différentes en terme de puissance. Peut-on imaginer une valeur par défaut qui se rêgle automatiquement en fonction de la machine détectée ?)
la limitation vient en faite énormement de la taille de la mémoire vidéo. Sur mon Mac mini j'ai 32MO, il suffit de faire un rapide calcul pour voir qu'on peut pas stocker beaucoup d'écrans, sinon après il doit les charger et décharger de la mémoire vidéo (ce qui réduit les perfs.). On doit donc pourvoir ce baser la dessus pour déterminer le nombre de fenetres. Dans QC il ya un noeud qui récupère les infos de ce genre. Mais ça doit etre plus souple en programmation.
dans 1134338370:
- Il faut définir une liste de variables (input spliter), avec le nom exact, et la fonction exacte. Qui s'y colle ? (je pense qu'il vaut mieux que ce soit le programmeux.)
à ce sujet, il est fastidieux, et puis c'est pas très élégant de remonter les inputs jusqu'à la racine du QTZ. Il serait plus simple, et plus sur pour l'avenir, de passer les arguments en structure (engros une liste texte avec les différents paramètres). Je sais pas faire ça en programmation mais QC les gère, voir le fichier joint, il regarde dans un dossier les images et fournit cette liste d'ou on extrait l'image à afficher. C'est peut-etre pas clair mais Bru doit voir de quoi je parle. Si c'est possible ça annule bien sur le problème des noms des input splitter.
dans 1134338370:
- Question au grapheux : comptes-tu faire passer le fond au rang d'une simple fenêtre... (j'ai bien lu que t'as finalement pas trop de raison de la laisser mise de coté). Il me semble que ça simplifirai le tout. Mais c'est toi le chef !
oui c'est fasaible facilement.
dans 1134338370:
Une chose très importante : si vous trouver que je n'use pas de la bonne méthode pour aider à faire avancer le projet avec toutes ces question, il faut me le dire. Je le prendrai pas mal. Je ne souhaite qu'une chose, c'est qu'il voit le jour !
en tout cas tu es tenance, vu la date du premier post... ::)
C'est vrai aussi. R3 correspond au premier paramètre en entrée , et au paramètre de retour de la fonction.
.
aaah ok merci. C'est balèze Shark, j'avais jamais utilisé avant, y'a même l'aide asm intégrée... Bon étant donné que je découvre totalement, j'ai pas avancé. On dirait qu'il y a un des params qui vaut nil, je dirais le 2e. Je ressaie encore plus tard...
Boris ! Ravi de te retrouver parmi nous !!! Cool ! bon, je comprends pas trop de quoi tu parles, mais Bru, lui, doit mieux s'y retrouver ! LOL ! Je vous laisse donc voir entre vous (via le forum si possible... ça me pemettra d'essayer d'y comprendre quelque chose)
Bon, je viens de travailler sur le projet. En découle une version eco18v2, à laquelle j'ai juste ajouté le système d'aller/retour automatique que j'ai modifié. C'est la seul raison d'être de cette version eco18v2 : elle sert de support pour vous transmettre la macro en question. (Elle sert aussi à la faire fonctionner... bien sur)
Objectif : Permettre au Grapheux et au Programmeux de pouvoir travailler en parallèle : - BorisCargo, tu peux intégrer cette marco définitivement même dans tes versions de travail en gardant la possibilité de choisir manuellement la position de recul (Mode manuel activé) - Bru, tu peux commander au module QC un aller ou retour automatique des fenêtres par le simple interrupteur True/False "ReculAutoOnOff" de cette macro (Le mode manuel doit être désactivé)
C'est hyper simple à utiliser. Lancer cette version eco18v2, faites Pomme+T, et faites joujou avec les commandes ReculAutoOnOff, ModeReculManuel, ValeurReculManuel.
Voilà donc cette macro s'appelle "Aller retour progressif v2". Elle dispose de 5 inputs : - "ReculAutoOnOff" : fonctionne que si le mode manuel si dessous est désactivé. Prend les valeurs FALSE ou TRUE - "ModereculManuel" : permet à BorisCargo de bosser en mode manuel, et donc de pouvoir choisir la valeur de recul ci-dessous - "ValeurReculManuel" : BorisCargo peut ainsi choisir une position de recul particulière pour travailler. - "DureeAller" actuellement à 8 secondes (je ne l'ai pas publié pour le module de programmation... ça n'apparaà®t donc pas dans le panneau Pomme+T) - "DureeRetour" actuellement à 0.5 secondes (idem)
Et un output : - "Valeur de recul" qui varie de 0 à 1 ; 0 pour proche, 1 pour éloignée.
Si vous trouvez que j'ai mal choisi les noms de variables, dites le moi, donnez-moi les bonnes... Si finalement vous décidez de passer exclusivement par le système dont tu viens de parler Boris... euh...ben c'est vous qui voyez ! (sauf que je vais rien y comprendre...)
Enfin, petits détails : Dans cette macro v2, j'ai aussi viré tout ce qui commandait l'apha de la capture d'écran général puisqu'on en a plus besoin grace au fait que Bru ai trouvé le moyen de capturer tout type de fenêtre.
Voilà ! J'espère avoir fait positivement avancer le projet. Ca devrait permettre a vous deux d'avancer en parallèle.
Aller, un peu de ne fait jamais de mal !<br /> A très vite de vos nouvelles,
En fait, il faut comprendre le mécanisme de passage des paramètres... Je te renvoie vers la doc Apple sur les conventions d'appel de procédure (ici).
Pour te mettre sur la voie, le second argument est une structure...
.
aà¯e raté Merci pour le lien. Ok je pense comprendre pourquoi le premier argument est en r3. J'ai découvert aussi "$pc" et qu'avec "x $sp" je retombe sur r1... c'est déjà ça :P Merci pour les indices. Je vais continuer encore un peu a chercher comment fonctionne cette fonction. J'espère que j'ai pas trop pollué le topic...
Edit: bon j'ai fait un petit programme pour voir comment sont placés les paramètres dans les registres. Puisque le 1e est CGContextRef qui est un pointeur, il n'occupe que r3. r4 est donc le 2e paramètre (en espérant qu'il ne soit pas dans f1). Comme c'est une structure, ça occupe plusieurs registres (c'est le résultat de la recherche que j'ai faite avec mon petit prog). Je pense qu'elle occupe jusqu'au r8 ou r11, je sais pas vraiment encore. Le prog de test à 2fr 6 sous Le résultat gdb du prog de test où on voit que le int est dans r4 et la structure dans r5+r6. Ok ok, ça avance pas vite je sais
bon j'ai fait un petit programme pour voir comment sont placés les paramètres dans les registres. Puisque le 1e est CGContextRef qui est un pointeur, il n'occupe que r3. r4 est donc le 2e paramètre (en espérant qu'il ne soit pas dans f1). Comme c'est une structure, ça occupe plusieurs registres (c'est le résultat de la recherche que j'ai faite avec mon petit prog). Je pense qu'elle occupe jusqu'au r8 ou r11, je sais pas vraiment encore. ... Ok ok, ça avance pas vite je sais
Ben, c'est plutôt sur la bonne voie...
Note que les paramètres dans les registres utilisent R3 à R10. Au delà , le paramètres sont transmis en mémoire via le parameter block qui se trouve sur la pile.
Note que les paramètres dans les registres utilisent R3 à R10. Au delà , le paramètres sont transmis en mémoire via le parameter block qui se trouve sur la pile.
.
Ok merci. J'ai essayé un truc "un peu barbare", c'est de mettre
et d'appeler la fonction avec plein de trucs pour essayer d'obtenir une erreur, mais ça mène à rien du tout :P Je vois plus qu'une solution: décoder la fonction, mais là c'est carrément balèze.. je coince déjà au 3e mnémonic
Euh... je comprends pas tout là ; au début, je pensais que vous parliez d'un truc entre vous sur une fonction qu'utilise Bru dans son superissimmmmme moyen de capturer toutes les fenêtres ; mais là , j'y cromprends plus rien dutout... ça va permettre quoi ? Vous pouvez décoder ??? (Désolé, en fait je suis pas trop à ma place... je suis censé être développeur ici et comprendre votre langage ... j'aimerai telement si vous saviez !!! Mais j'arrive pas a tout faire ce que j'aimerai !!! Ca vous fait pareil à vous ?)
Je crois que maconnect essaye de retrouver la route suivie par le "cachottier" (comme tu le dis si bien!) de Bru lequel a annoncé qu'il ferait part de ses avancées dans un prochaine article... ce qui démontre la grande impatience de maconnect!!!Â
Et ne t'inquiètes pas, c'est notre lot à tous de ne pas maà®triser tous les domaines que l'on voudrait; mais tant que l'on fait notre possible pour avancer, après, c'est selon les possibilités de chacun...
En tout cas, je profite de ce message pour adresser mes plus sincères félicitations à tous les intervenants qui viennent de redonner un nouvel élan à ce projet pour le moins prometteur : encore bravo et... au boulot! Je suis sûr de ne pas être le seul à suivre ce sujet (presque depuis le tout début) et à attendre avec impatience [moi aussi je suis un impatient, mais Bru a dû déjà le remarquer!!] une première version!
Vous pouvez compter sur moi pour bêta-tester! [c'est malheureusement tout ce que je suis certain d'être capable de faire pour vous aider... :-\\ ]
/Jlm.
[c'est bizarre : le forum n'accepte pas les ... faits avec alt+; il les transforme en ? ]
La fonction n'étant pas documentée, il faut deviner comment elle s'utilise. Je vois 2 possibilités, soit elle capture toutes les fenêtres qui ont au moins un point dans un certain rectange, soit elle capture la fenêtre la plus proche de nous qui a "le plus de points visibles". Je penche pour la 1ere solution.
Cela dit, le nom indique que cette fonction crée un tableau de CGContext à partir du contenu des fenêtres qui se trouve dans le rectange Rect.
La partie documentée dit que le rectange retourné (pour une autre fonction) est dans l'ordre d'affichage des fenêtre (enfin, l'ordre inverse, la fenêtre la plus proche de nou étant la première).
J'imagine que c'est pareil ici (à vérifier donc).
enfin, les arguments sont : - La valeur de retour (un tableau de pointeurs sur un CGContextRef selon ma théorie, un pointeur sur un CGContextRef si on ne capture qu'une fenêtre à la fois. ) - Un NSRect (pour connaà®tre l'endroit du capteur) - La "taille" du CGContext x puis y (nombre de pixel simplement) (valeurs retournée apparement) - Un espace de couleur RGB* (ou un nombre de bit par couleur... à voir)(valeur retournée et/ou proposée)
En fait, en s'inspirant de fonctions existantes, on peut lire dans la doc Apple :
<br />You use the Quartz 2D function CGGLContextCreate to create the OpenGL flavor of a Quartz graphics context. You need to pass:<br /><br />A pointer to the GL context<br />The width and height of the OpenGL viewport rectangle<br />An RGB color space that serves as the destination space when rendering device-independent colors, or NULL if you want to use the default RGB color space<br />
Et l'habitude est de mettre d'abord la sortie, puis les arguments puis les "infos suplémentaires" ou entrée-sortie. D'où l'ordre supposé des arguments.
Voilà , j'espère ne pas être trop éloigné d'une explication claire et de la vérité, n'hésitez pas à critiquer mes explications, c'est comme celà qu'on progresse.
En ne comprenant que 1% de ton message, je commence quand même à voir poindre un début de réponse à la question fondamentale que je pose depuis pas mal de jour : Est-ce que l'on peut récupérer l'ordre (la profondeur) des fenêtres !? C'est très important pour le projet dont nous parlons depuis... si longtemps ici !
"J'imagine que c'est pareil ici (à vérifier donc)."
En fait, j'ai cherché du coté des "apple event" puisque toutes les applications de capture l'utilisent.
Mais je me rend compte que la fonction nommée ci dessus intéroge directement Quartz et fait fit des fenêtres et applications...
Pour récupérer l'ordre des fenêtres, tout dépend du retour de cette fonction. Si c'est la première fenêtre (enfin élément graphique) au dessus de tout qui est renvoyé, il suffit de faire une boucle intelligente pour récupérer l'ordre des fenêtres, si c'est un tableau, il faut comprendre comment il est renvoyé. Si c'est "par ordre alphabétique des applications, par ordre d'affichage" par exemple, il faut aller cherche de l'information complémentaire.
celà dit, j'arrête d'extrapoler et je vais tester cette fonction, espérant que le hasard fasse bien les choses
La fonction n'étant pas documentée, il faut deviner comment elle s'utilise. Je vois 2 possibilités, soit elle capture toutes les fenêtres qui ont au moins un point dans un certain rectange, soit elle capture la fenêtre la plus proche de nous qui a "le plus de points visibles". Je penche pour la 1ere solution.
Cela dit, le nom indique que cette fonction crée un tableau de CGContext à partir du contenu des fenêtres qui se trouve dans le rectange Rect.
La partie documentée dit que le rectange retourné (pour une autre fonction) est dans l'ordre d'affichage des fenêtre (enfin, l'ordre inverse, la fenêtre la plus proche de nou étant la première).
J'imagine que c'est pareil ici (à vérifier donc).
enfin, les arguments sont : - La valeur de retour (un tableau de pointeurs sur un CGContextRef selon ma théorie, un pointeur sur un CGContextRef si on ne capture qu'une fenêtre à la fois. ) - Un NSRect (pour connaà®tre l'endroit du capteur) - La "taille" du CGContext x puis y (nombre de pixel simplement) (valeurs retournée apparement) - Un espace de couleur RGB* (ou un nombre de bit par couleur... à voir)(valeur retournée et/ou proposée)
En fait, en s'inspirant de fonctions existantes, on peut lire dans la doc Apple :
<br />You use the Quartz 2D function CGGLContextCreate to create the OpenGL flavor of a Quartz graphics context. You need to pass:<br /><br />A pointer to the GL context<br />The width and height of the OpenGL viewport rectangle<br />An RGB color space that serves as the destination space when rendering device-independent colors, or NULL if you want to use the default RGB color space<br />
Et l'habitude est de mettre d'abord la sortie, puis les arguments puis les "infos suplémentaires" ou entrée-sortie. D'où l'ordre supposé des arguments.
Voilà , j'espère ne pas être trop éloigné d'une explication claire et de la vérité, n'hésitez pas à critiquer mes explications, c'est comme celà qu'on progresse.
waaa joli, j'étais encore loin d'en arriver là . Le truc qui m'étonne c'est que tu donnes pas le numéro de la fenêtre en argument. PS pour l'ordre des fenêtres je m'inquiéterais pas trop (on a NSWindowList qui les donne dans l'ordre 1e plan --> arrière plan).
EDIT: pour les coordonnées, le (0,0) c'est en bas à gauche de l'écran principal. Les autres écrans ont des valeurs négatives à gauche et positives à droite. J'ai placé une fenêtre en (1002, 840) et je l'ai capturée, mais je trouve rien dans les arguments qui ne donne ces coordonnées ou même la taille de la fenêtre... je m'y prends mal ? (edit, après réflexion ça me paraà®t normal)
EDIT2: YOUPIIII j'ai avancé un petit chouillas de peu: dans $r9 on a le numéro de la fenêtre. C'est le 4e argument a mon avis!
EDIT3: encore un truc: si je capture 2 fois la même fenêtre, alors seul r3 change (normal, on sait que c'est un pointeur). r4-r10 ne changent pas et je suppose alors que ce sont des trucs qui dépendent de la fenêtre. Si je déplace la fenêtre rien ne change, ce qui est logique puisque le numéro de fenêtre suffit entièrement à avoir toutes les infos sur celle-ci comme sa position...
EDIT4: encore un truc magique. En mettant un break sur 0x90504644 (c'est la fin de la fonction, just avant le return) on s'aperçoit que f4-f7 représente un NSRect en coordonnées locales de la fenêtre. Cà d: (0, 0, w, h)
Sky.x s'est éloigné de la vérité. Maconnects 'en est rapproché.
Effectivement, le but du jeu est de découvrir comment on "grab" une fenêtre.
Voici la méthode que j'ai utilisé :
étape 1 : utilisation de la commande nm en lui passant comme argument le framework CoreGraphics. Le résultat est l'ensemble des fonctions référencées dans la framework (fonction externe utilisée ou fonction interne déclarée). Ensuite, en regardant toutes les fonctions, j'en ai trouvé 2 qui, selon leur nom, me titillent.
étape 2 : nm sur la commande screencapture. Comme par hazard, les 2 commandes sus-citées sont utilisées par la commande.
étape 3 : un petit coup de gdb avec arrêt sur les 2 fonctions...
étape 4 : Toujours gdb pour examiner l'état des registres et de la mémoire suite à l'arrêt.
étape 5 : un coup de otool pour récupérer l'asm de la commande screencapture, afin de voir comment sont alimentés les registres avent l'appel aux fonctions.
Résultat : void CGContextCopyWindowCaptureContentsToRect(CGContextRef ctxref, CGRect rect, int cid, int wid, int 0) ctxref est un contexte graphique préalablement créé pour contenir l'image de la capture rect est le rectangle dans la fenêtre dont on veut faire la copie cid est l'id de connection au window server wid est l'id (ou numéro) de la fenêtre int0 est un argument dont la fonction m'est encore inconnue...
Voilà .
Note, le rect, le cid et le wid sont visibles en utilisant l'appli QuartzDebug présente dans les applis de développement (dans le répertoire performance tools).
J'allais justement dire que le 5e params était nil (ouais enfin c'est 0, mais c'est la même chose...) J'avais aussi remarqué que le 3e params ne changeait jamais, mais j'avais pas pigé pourquoi...
Ha donc il faut bien récupérer les connections de toutes les applications ouvertes et pour chacune leur demander leurs windows id ?
Si j'ai vu comment avoir les Windows ID, je vois toujours pas comment le demander à toutes les applications...
Bon je relis la la liste des fonctions
(Y'a bien CGSFindWindowByGeometry avec comme définition de Geometry : This topic describes the Cocoa types used to represent geometry primitives such as points, rectangles, and sizes. It also describes NSRange, which represents a measurement of a segment of something linear, such as a byte stream.
Mais je ne vois toujours pas comment sortir un des éléments qui sont tout au fond si on a pas à un moment un tableau de fenêtre situé sous un certain point (notez le singulier de CGSFindWindowByGeometry)
Pour l'ordre de la fenêtre, il y a peut être un "CGSOrderWindow" qui est interessant ?
tu as toutes les fenêtres.. ici j'en ai 103. D'ailleurs c'est précisé: "list of ALL onscreen windows". Donc ça à l'air d'être ce qu'il faut... en plus c'est ce que Bru utilises :P
Réponses
Grande nouvelle !
Depuis un prog cocoa, je peux charger le eco18 pour le jouer dans une fenêtre.
Je peux aussi lui passer des paramètres (ça s'appelle input splitter dans Quartz Composer).
J'ai modifié (légèrement) le eco18 en ajoutant un input splitter de type Image. Cet input a été relié à la première image (celle de TextEdit je crois) de la Macro "windows" (et remplace le input Image Importer "TextEdit")
Dans le prog, j'ai récupéré une image d'une fenêtre à l'écran, et je l'ai passé en paramètre à l'input.
J'ai ensuite lancé l'animation.
Résultat : j'ai bien une image de ma fenêtre qui danse dans l'animation.
Conclusion : pas besoin de récupérer le contenu des fenêtres en fichier. Tout peut rester en mémoire.
Maintenant, messieurs les grapheux, à vous de jouer, sachant que les programmeux vous fourniront des données de type image, des numeriques (position x & y et taille largeur & hauteur de la fenêtre à l'écran).
Pour les images, il y aura l'image de fond, et les quelques images (5 j'ai cru lire plus haut) des fenêtres standards présentes à l'écran.
On attend donc un eco19.qtx !
.
Le petit test que je vous ai joint fait le strict minimum. Il n'y a aucun test, ni contrôle des valeurs de retour des appels des différentes fonctions du Core Graphics.
Or, certaines fenêtres ont des configs très bizarres du style taille à 0 ou profondeur de couleur à 1 bit (au lieu de 32 bits usuellement).
Ces fenêtres sont mal capturées, et peuvent provoquer des plantages. Il faut normalement les éliminer de la liste des fenêtres visibles (ce que je n'ai pas fait).
.
MAIS, qu'en est-il de la récupération de la profondeur ? Première fenêtre jusqu'à dernière fenêtre ??? C'est hyper important dans notre cas. Hein ? ???
J'ai réfléchit a tout ça... autant du coté programmeux que grapheux. Je pense qu'il est temps qu'on se fixe des objectifs à atteindre pour la version 1 de l'économiseur : Je serais ravi d'avoir sur ces point l'avis de Bru et de Boris Cargo (je donne le mien entre parenthèses) :
- Partons-nous sur un nombre de fenêtre fixe, ou serait-il paramêtrable dans les préférences de l'économiseur : 5 par défaut, variable de 3 à 20. (Si vous vous sentez, je préfèrerai que ce soit paramêtrable dès la version 1, sachant que ça va tourner sur des machines très différentes en terme de puissance. Peut-on imaginer une valeur par défaut qui se rêgle automatiquement en fonction de la machine détectée ?)
- Vu le fait que finalement, on peut récupérer n'importe quelle fenêtre (et non plus uniquement les COCOA), on a plus besoin d'avoir un fondu en début d'animation (voir ma version eco17v3). Ca va vraiment simplifier. Confirmez-vous cela ?
- Il faut définir une liste de variables (input spliter), avec le nom exact, et la fonction exacte. Qui s'y colle ? (je pense qu'il vaut mieux que ce soit le programmeux.)
- Le module graphique n'a pas besoin d'obtenir la taille des images via des input spliter. Seul l'image elle même, et ces coordonnées de position en pixel sont nessecaisse. (QC sait lire la taille d'une image qu'on lui donne)
- Message au programmeux : il est prévu un input spliter "On Off" qui libère ou qui ramène l'ensemble de l'animation des fenêtres. C'est automatique. Il suffit de le passer à 1 (True) quand tout est prêt a être animé, et à 0 (False) quand on veux que toutes les fenêtres reviennent en place. Voir ma version eco17v3 où cet input spliter est implémenté.
- Je repose ici ma question sur la notion d'ordre (de profondeur) des fenêtres. Donc... la récupère-t-on ? (sans quoi c'est la cata...). A noter que c'est le programmeux qui doit les envoyer à QC dans l'ordre inverse : fond est rendu en premier, puis ima1, puis ima2, puis ima3... etc... ce qui fait que c'est la dernière imaX envoyé qui apparaà®tra au premier plan puisque c'est la dernière à être rendue.
- Question au grapheux : comptes-tu faire passer le fond au rang d'une simple fenêtre... (j'ai bien lu que t'as finalement pas trop de raison de la laisser mise de coté). Il me semble que ça simplifirai le tout. Mais c'est toi le chef !
- Proposition au grapheux : ne pourrait-on pas filer le plus rapidement possible une version avec tous les inputs spliters définitifs (qu'on va lister ci-dessus) au programmeux, même si l'animation n'est pas fignolée. Comme ça, vous pourrez avancer en parallèle ?! Oui ? Je peux m'y coller si tu veux. Ca je sais faire !
- Enfin, question au programeux : est-il possible, dans un économiseur d'écran, de se passer du fondu au noir lorsqu'il s'active ?
- Et, dans le même genre, toujours dans un eco d'écran, est-il possible qu'il ne quitte QUE lorsque toutes les fenêtres sont revenues en place ? Genre, on bouge la souris, le système demande à l'éco d'écran de quitter ; ce dernier prend le temps (très rapide) de faire revnir toutes les fenêtres, et enfin il quitte. (ma crainte, c'est que quand on bouge la souris, ce soit fait de telle manière que le système masque et force a quitter instantanément l'eco d'écran ; ce qui serait dommage : on ne verrai pas les fenêtres toutes revenir très vite...)
Voilà !
Une chose très importante : si vous trouver que je n'use pas de la bonne méthode pour aider à faire avancer le projet avec toutes ces question, il faut me le dire. Je le prendrai pas mal. Je ne souhaite qu'une chose, c'est qu'il voit le jour !
Dans l'attente : plein des BRAVOS !
En mettant un break sur CGContextCopyWindowCaptureContentsToRect (0x90504600) on a bien une interruption lorsqu'on capture une fenêtre.
En regardant les arguments j'ai pas réussi à avoir grand chose (je débute), dans r3 on a "<NSCFType: 0x3ab150>" et on a un argument en r1. J'ai pas retrouvé le symbole avec otool, donc apparemment y'a qu'un seul argument mais je ne l'affirme pas.
En désassemblant, on trouve qu'il y a un appel à "contextCopyWindowContentsToRect".
Bon ça fait pas vraiment avancer le truc... c'était juste pour regarder...
Je suis plus intéressé par la démarche que par la finalité, je cherche à mieux me servir de gdb... donc coups de main / indices bienvenus.
CGContextCopyWindowCaptureContentsToRect utilise 5 arguments en entrée (je te laisse chercher un peu...) et aucun argument en retour.
R1 n'est pas un argument (il pointe sur la frame de la fonction courante).
R3 est effectivement le 1er argument, et il contient un CGContextRef.
Bon courage pour la suite...
.
thanks
C'est vrai aussi.
R3 correspond au premier paramètre en entrée , et au paramètre de retour de la fonction.
.
la limitation vient en faite énormement de la taille de la mémoire vidéo. Sur mon Mac mini j'ai 32MO, il suffit de faire un rapide calcul pour voir qu'on peut pas stocker beaucoup d'écrans, sinon après il doit les charger et décharger de la mémoire vidéo (ce qui réduit les perfs.). On doit donc pourvoir ce baser la dessus pour déterminer le nombre de fenetres. Dans QC il ya un noeud qui récupère les infos de ce genre. Mais ça doit etre plus souple en programmation.
à ce sujet, il est fastidieux, et puis c'est pas très élégant de remonter les inputs jusqu'à la racine du QTZ. Il serait plus simple, et plus sur pour l'avenir, de passer les arguments en structure (engros une liste texte avec les différents paramètres). Je sais pas faire ça en programmation mais QC les gère, voir le fichier joint, il regarde dans un dossier les images et fournit cette liste d'ou on extrait l'image à afficher. C'est peut-etre pas clair mais Bru doit voir de quoi je parle. Si c'est possible ça annule bien sur le problème des noms des input splitter.
oui c'est fasaible facilement.
en tout cas tu es tenance, vu la date du premier post... ::)
[Fichier joint supprimé par l'administrateur]
Bon étant donné que je découvre totalement, j'ai pas avancé. On dirait qu'il y a un des params qui vaut nil, je dirais le 2e. Je ressaie encore plus tard...
bon, je comprends pas trop de quoi tu parles, mais Bru, lui, doit mieux s'y retrouver ! LOL ! Je vous laisse donc voir entre vous (via le forum si possible... ça me pemettra d'essayer d'y comprendre quelque chose)
Bon, je viens de travailler sur le projet. En découle une version eco18v2, à laquelle j'ai juste ajouté le système d'aller/retour automatique que j'ai modifié. C'est la seul raison d'être de cette version eco18v2 : elle sert de support pour vous transmettre la macro en question. (Elle sert aussi à la faire fonctionner... bien sur)
Objectif : Permettre au Grapheux et au Programmeux de pouvoir travailler en parallèle :
- BorisCargo, tu peux intégrer cette marco définitivement même dans tes versions de travail en gardant la possibilité de choisir manuellement la position de recul (Mode manuel activé)
- Bru, tu peux commander au module QC un aller ou retour automatique des fenêtres par le simple interrupteur True/False "ReculAutoOnOff" de cette macro (Le mode manuel doit être désactivé)
C'est hyper simple à utiliser. Lancer cette version eco18v2, faites Pomme+T, et faites joujou avec les commandes ReculAutoOnOff, ModeReculManuel, ValeurReculManuel.
Voilà donc cette macro s'appelle "Aller retour progressif v2". Elle dispose de 5 inputs :
- "ReculAutoOnOff" : fonctionne que si le mode manuel si dessous est désactivé. Prend les valeurs FALSE ou TRUE
- "ModereculManuel" : permet à BorisCargo de bosser en mode manuel, et donc de pouvoir choisir la valeur de recul ci-dessous
- "ValeurReculManuel" : BorisCargo peut ainsi choisir une position de recul particulière pour travailler.
- "DureeAller" actuellement à 8 secondes (je ne l'ai pas publié pour le module de programmation... ça n'apparaà®t donc pas dans le panneau Pomme+T)
- "DureeRetour" actuellement à 0.5 secondes (idem)
Et un output :
- "Valeur de recul" qui varie de 0 à 1 ; 0 pour proche, 1 pour éloignée.
Si vous trouvez que j'ai mal choisi les noms de variables, dites le moi, donnez-moi les bonnes... Si finalement vous décidez de passer exclusivement par le système dont tu viens de parler Boris... euh...ben c'est vous qui voyez ! (sauf que je vais rien y comprendre...)
Enfin, petits détails : Dans cette macro v2, j'ai aussi viré tout ce qui commandait l'apha de la capture d'écran général puisqu'on en a plus besoin grace au fait que Bru ai trouvé le moyen de capturer tout type de fenêtre.
Voilà ! J'espère avoir fait positivement avancer le projet. Ca devrait permettre a vous deux d'avancer en parallèle.
Aller, un peu de ne fait jamais de mal !<br />
A très vite de vos nouvelles,
Vinc'26
[Fichier joint supprimé par l'administrateur]
Faux...
En fait, il faut comprendre le mécanisme de passage des paramètres... Je te renvoie vers la doc Apple sur les conventions d'appel de procédure (ici).
Pour te mettre sur la voie, le second argument est une structure...
.
Merci pour le lien. Ok je pense comprendre pourquoi le premier argument est en r3. J'ai découvert aussi "$pc" et qu'avec "x $sp" je retombe sur r1... c'est déjà ça :P
Merci pour les indices. Je vais continuer encore un peu a chercher comment fonctionne cette fonction. J'espère que j'ai pas trop pollué le topic...
Edit:
bon j'ai fait un petit programme pour voir comment sont placés les paramètres dans les registres. Puisque le 1e est CGContextRef qui est un pointeur, il n'occupe que r3. r4 est donc le 2e paramètre (en espérant qu'il ne soit pas dans f1). Comme c'est une structure, ça occupe plusieurs registres (c'est le résultat de la recherche que j'ai faite avec mon petit prog). Je pense qu'elle occupe jusqu'au r8 ou r11, je sais pas vraiment encore.
Le prog de test à 2fr 6 sous
Le résultat gdb du prog de test où on voit que le int est dans r4 et la structure dans r5+r6.
Ok ok, ça avance pas vite je sais
Ben, c'est plutôt sur la bonne voie...
Note que les paramètres dans les registres utilisent R3 à R10. Au delà , le paramètres sont transmis en mémoire via le parameter block qui se trouve sur la pile.
.
Je vois plus qu'une solution: décoder la fonction, mais là c'est carrément balèze.. je coince déjà au 3e mnémonic
Et ne t'inquiètes pas, c'est notre lot à tous de ne pas maà®triser tous les domaines que l'on voudrait; mais tant que l'on fait notre possible pour avancer, après, c'est selon les possibilités de chacun...
En tout cas, je profite de ce message pour adresser mes plus sincères félicitations à tous les intervenants qui viennent de redonner un nouvel élan à ce projet pour le moins prometteur : encore bravo et... au boulot! Je suis sûr de ne pas être le seul à suivre ce sujet (presque depuis le tout début) et à attendre avec impatience [moi aussi je suis un impatient, mais Bru a dû déjà le remarquer!!] une première version!
Vous pouvez compter sur moi pour bêta-tester! [c'est malheureusement tout ce que je suis certain d'être capable de faire pour vous aider... :-\\ ]
/Jlm.
[c'est bizarre : le forum n'accepte pas les ... faits avec alt+; il les transforme en ? ]
La fonction n'étant pas documentée, il faut deviner comment elle s'utilise.
Je vois 2 possibilités, soit elle capture toutes les fenêtres qui ont au moins un point dans un certain rectange, soit elle capture la fenêtre la plus proche de nous qui a "le plus de points visibles".
Je penche pour la 1ere solution.
Cela dit, le nom indique que cette fonction crée un tableau de CGContext à partir du contenu des fenêtres qui se trouve dans le rectange Rect.
La partie documentée dit que le rectange retourné (pour une autre fonction) est dans l'ordre d'affichage des fenêtre (enfin, l'ordre inverse, la fenêtre la plus proche de nou étant la première).
J'imagine que c'est pareil ici (à vérifier donc).
enfin, les arguments sont :
- La valeur de retour (un tableau de pointeurs sur un CGContextRef selon ma théorie, un pointeur sur un CGContextRef si on ne capture qu'une fenêtre à la fois. )
- Un NSRect (pour connaà®tre l'endroit du capteur)
- La "taille" du CGContext x puis y (nombre de pixel simplement) (valeurs retournée apparement)
- Un espace de couleur RGB* (ou un nombre de bit par couleur... à voir)(valeur retournée et/ou proposée)
En fait, en s'inspirant de fonctions existantes, on peut lire dans la doc Apple :
Et l'habitude est de mettre d'abord la sortie, puis les arguments puis les "infos suplémentaires" ou entrée-sortie. D'où l'ordre supposé des arguments.
Voilà , j'espère ne pas être trop éloigné d'une explication claire et de la vérité, n'hésitez pas à critiquer mes explications, c'est comme celà qu'on progresse.
:why?:
"J'imagine que c'est pareil ici (à vérifier donc)."
En fait, j'ai cherché du coté des "apple event" puisque toutes les applications de capture l'utilisent.
Mais je me rend compte que la fonction nommée ci dessus intéroge directement Quartz et fait fit des fenêtres et applications...
Pour récupérer l'ordre des fenêtres, tout dépend du retour de cette fonction.
Si c'est la première fenêtre (enfin élément graphique) au dessus de tout qui est renvoyé, il suffit de faire une boucle intelligente pour récupérer l'ordre des fenêtres, si c'est un tableau, il faut comprendre comment il est renvoyé.
Si c'est "par ordre alphabétique des applications, par ordre d'affichage" par exemple, il faut aller cherche de l'information complémentaire.
celà dit, j'arrête d'extrapoler et je vais tester cette fonction, espérant que le hasard fasse bien les choses
waaa joli, j'étais encore loin d'en arriver là . Le truc qui m'étonne c'est que tu donnes pas le numéro de la fenêtre en argument.
PS pour l'ordre des fenêtres je m'inquiéterais pas trop (on a NSWindowList qui les donne dans l'ordre 1e plan --> arrière plan).
EDIT: pour les coordonnées, le (0,0) c'est en bas à gauche de l'écran principal. Les autres écrans ont des valeurs négatives à gauche et positives à droite. J'ai placé une fenêtre en (1002, 840) et je l'ai capturée, mais je trouve rien dans les arguments qui ne donne ces coordonnées ou même la taille de la fenêtre... je m'y prends mal ? (edit, après réflexion ça me paraà®t normal)
EDIT2: YOUPIIII j'ai avancé un petit chouillas de peu: dans $r9 on a le numéro de la fenêtre. C'est le 4e argument a mon avis!
EDIT3: encore un truc: si je capture 2 fois la même fenêtre, alors seul r3 change (normal, on sait que c'est un pointeur). r4-r10 ne changent pas et je suppose alors que ce sont des trucs qui dépendent de la fenêtre. Si je déplace la fenêtre rien ne change, ce qui est logique puisque le numéro de fenêtre suffit entièrement à avoir toutes les infos sur celle-ci comme sa position...
EDIT4: encore un truc magique. En mettant un break sur 0x90504644 (c'est la fin de la fonction, just avant le return) on s'aperçoit que f4-f7 représente un NSRect en coordonnées locales de la fenêtre. Cà d: (0, 0, w, h)
Sky.x s'est éloigné de la vérité.
Maconnects 'en est rapproché.
Effectivement, le but du jeu est de découvrir comment on "grab" une fenêtre.
Voici la méthode que j'ai utilisé :
étape 1 :
utilisation de la commande nm en lui passant comme argument le framework CoreGraphics.
Le résultat est l'ensemble des fonctions référencées dans la framework (fonction externe utilisée ou fonction interne déclarée).
Ensuite, en regardant toutes les fonctions, j'en ai trouvé 2 qui, selon leur nom, me titillent.
étape 2 :
nm sur la commande screencapture.
Comme par hazard, les 2 commandes sus-citées sont utilisées par la commande.
étape 3 :
un petit coup de gdb avec arrêt sur les 2 fonctions...
étape 4 :
Toujours gdb pour examiner l'état des registres et de la mémoire suite à l'arrêt.
étape 5 :
un coup de otool pour récupérer l'asm de la commande screencapture, afin de voir comment sont alimentés les registres avent l'appel aux fonctions.
Résultat :
void CGContextCopyWindowCaptureContentsToRect(CGContextRef ctxref, CGRect rect, int cid, int wid, int 0)
ctxref est un contexte graphique préalablement créé pour contenir l'image de la capture
rect est le rectangle dans la fenêtre dont on veut faire la copie
cid est l'id de connection au window server
wid est l'id (ou numéro) de la fenêtre
int0 est un argument dont la fonction m'est encore inconnue...
Voilà .
Note, le rect, le cid et le wid sont visibles en utilisant l'appli QuartzDebug présente dans les applis de développement (dans le répertoire performance tools).
.
J'allais justement dire que le 5e params était nil (ouais enfin c'est 0, mais c'est la même chose...)
J'avais aussi remarqué que le 3e params ne changeait jamais, mais j'avais pas pigé pourquoi...
Si j'ai vu comment avoir les Windows ID, je vois toujours pas comment le demander à toutes les applications...
Bon je relis la la liste des fonctions
(Y'a bien CGSFindWindowByGeometry avec comme définition de Geometry :
This topic describes the Cocoa types used to represent geometry primitives such as points, rectangles, and sizes. It also describes NSRange, which represents a measurement of a segment of something linear, such as a byte stream.
Mais je ne vois toujours pas comment sortir un des éléments qui sont tout au fond si on a pas à un moment un tableau de fenêtre situé sous un certain point (notez le singulier de CGSFindWindowByGeometry)
Pour l'ordre de la fenêtre, il y a peut être un "CGSOrderWindow" qui est interessant ?
Donc ça à l'air d'être ce qu'il faut... en plus c'est ce que Bru utilises :P
Pour transformer les données en image:
http://www.cocoabuilder.com/archive/message/cocoa/2003/12/3/854
Au passage on remarquera "CGSGetWindowBounds()".
Merci Bru
[Fichier joint supprimé par l'administrateur]