Projet d'économiseur d'écran
Vinc26
Membre
Salut à tous !
Bon ben ça fait un bout de temps que j'ai une idée d'économiseur d'écran un peu particulier pour osx. J'ai déjà posté mon projet sur MacG, et quelqu'un qui a commencé à y bosser bloque actuellement sur un truc... alors je viens faire appel à vous. C'est là que ça se passe :why?:
http://forums.macgeneration.com/vbulletin/showthread.php?t=81705
Merci d'avance !
Bon ben ça fait un bout de temps que j'ai une idée d'économiseur d'écran un peu particulier pour osx. J'ai déjà posté mon projet sur MacG, et quelqu'un qui a commencé à y bosser bloque actuellement sur un truc... alors je viens faire appel à vous. C'est là que ça se passe :why?:
http://forums.macgeneration.com/vbulletin/showthread.php?t=81705
Merci d'avance !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Je pense qu'il faudrait explorer les pistes suivantes :
1) Récupérer la liste des fenêtres avec la fonction NSWindowList.
2) Essayer de récupérer les pointeurs des fenêtres fournies dans la WindowList pour les utiliser avec la méthode de la classe NSWindow dataWithPDFInsideRect:, pour mettre une par une le contenu des fenêtres dans des instances NSImage.
3) Si ça marche, il ne reste plus qu'à mapper les NSImage sur des objets OpenGL, les animer, puis mettre le tout sous forme de screensaver au sens système su terme...
[tt]
NSWindowList
Gets information about onscreen windows.
void NSWindowList(int size, int list[])
Discussion
Provides an ordered list of all onscreen windows. It fills list with up to size window numbers; the order of windows in the array is the same as their order in the window server?s screen list (their front-to-back order on the screen). Use the count obtained by NSCountWindows to specify the size of the array for NSWindowList.
[/tt]
[tt]
dataWithPDFInsideRect:
- (NSData *)dataWithPDFInsideRect:(NSRect)aRect
Returns PDF data that draws the region of the receiver within aRect (expressed in the receiver?s base coordinate system). This data can be placed on a pasteboard, written to a file, or used to create an NSImage object.
See Also: ? dataWithPDFInsideRect: (NSView), ? writePDFInsideRect:toPasteboard: (NSView)
[/tt]
Je ne veux pas te décourager, mais ce projet "irréalisable" avec les outils/documentations fournis par Apple.
Compter le nombre de fenêtre (et récupérer leur windowref) n'est pas compliqué à faire :
il suffit d'utiliser la fonction NSWindowList pour obtenir la liste des fenêtres visibles.
Par contre, récupérer le contenu de chaque fenêtre n'est pas simple.
La solution d'utiliser initWithFocusedViewRect de NSBitmapImagrect ne résout pas les choses. En effet, on ne pourra récupérer que le contentView de la fenêtre, mais pas la barre de titre ni le cadre...
D'autre part, que se passe t'il si la fenêtre est animée ?
Enfin, je ne parle pas bien sûr du bureau ni de la barre des menus...
La seule solution, à mon avis, est de tenter un reverse-engeneering d'Exposé, qui arrive bien à manipuler les fenêtres (en entier) et d'afficher en temps réèl leur contenu.
.
Je crois avoir compris que son probleme pour l'instant, c'est de récupérer le contenu des fenêtres... les lister etc... ça a l'air ok. Mais c'est pour chopper leur contenu que ça coincait... a suivre...
Si d'autres ont des précisions
Ben pour les fenêtres au contenu animé... j'imagine que seul Apple peut continuer à faire animer le contenu dans un tel éco d'écran...
De not' coté, si déjà ça fait un simple arrêt sur image... ce sera parfait !
Pour ce qui est du reverse ingeniering... je vous laisse voir... si vous ou l'une de vos connaisance si connait :adios!:
- J'ai d'abord essayé la méthode dataWithPDFInsideRect:, celle-ci récupère entièrement la fenêtre, mais pas son canal alpha, et les coins de fenêtres sont donc abominables (carrés noirs)... . C'est dommage, car cette méthode on peut lui refiler le pointeur de fenêtre que l'on veut...
- J'ai ensuite essayé la méthode initWithFocusedViewRect:, celle-ci récupère entièrement la fenêtre, canal alpha compris, ce qui donne une représentation correcte de la fenêtre, mais comment faire pour lui faire comprendre d'aller grabber une autre fenêtre ? En intégrant une autre fenêtre au projet, j'ai essayé des trucs du genre becomeFirstResponder, makeMainWindow, avant la récupération, pour changer le focus, mais ça n'a pas marché ou alors je ne m'y suis pas pris correctement de ce côté là ... ???
Peut-être qu'il ne manque plus grand chose pour focaliser où l'on veut la méthode initWithFocusedViewRect, je fournis le projet si quelqu'un veut continuer les recherches...
[Fichier joint supprimé par l'administrateur]
Pour "focaliser" sur n'importe quelle fenêtre, il faudrait essayer la fonction carbon SetPort (dans l'api QuicDraw).
Ca donnerait un truc du style :
[tt]SetPort(GetWindowPort ([uneFenetre windowRef]));[/tt]
.
[tt]
CGrafPtr mainWindowPort=GetWindowPort([mainWindow windowRef]);
SetPort(mainWindowPort);
[/tt]
J'obtiens un warning sur la première ligne, dont je n'arrive pas à me débarasser : "Initialization makes pointer from integer without a cast."
J'ai aussi essayé sans plus de succés :
[tt]
SetPortWindowPort([mainWindow windowRef]);
[/tt]
J'ai ensuite essayé, toujours sans succés :
[tt]
GrafPtr mainWindowPort;
SetPortWindowPort([mainWindow windowRef]);
GetPort(&mainWindowPort);
SetPort(mainWindowPort);
[/tt]
En cherchant dans la doc Carbon, j'ai trouvé la fonction suivante qui permettrait de récupérer la structure bitmap d'un grafport : A essayer.....
[tt]
GetPortBitMapForCopyBits
const BitMap * GetPortBitMapForCopyBits (
  CGrafPtr port
);
[/tt]
En fait, pour donner le "focus" à une fenêtre c'est tout con :
[tt][[laFenetre contentView] lockFocus];
[/tt]
Voilà ...
.
Mais un problème s'est immédiatement posé.
En effet, via NSWindoList, on récupère bien toutes les fenêtres visibles à l'écran sous forme de numéro.
La seule méthode pour récupérer un objet NSWindow à partir d'un numéro, c'est d'utiliser windowWithWindowNumber de NSApplication.
Or, cette méthode ne retourne l'objet NSWindow que pour les fenêtres appartenant au process, alors que pour les fenêtres des autres process, c'est nil qui est retourné.
Ceci est logique, puisque chaque process n'a théoriquement pas le droit d'aller regarder ce qui se passe chez les autres (mémoire partagée et protégée).
A mon avis, il doit exister une fonction liée au window server qui permet de récupérer la fenêtre à partir de son numéro... mais comme le window server n'est pas documenté...
.
J'avais aussi réglé le problème avec NSGraphicsContext :
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithWindow:mainWindow]];
Et vous connaissez personne qui touche un peu là dedans ?
:crackboom:-
J'ai commencé à étudier l'appli QuartzDebug dans les utilitaires Graph Tools des applis developer. En effet ce programme permet de lister toutes les fenêtres, quelque soit le process.
Mais le temps me manque un peu...
.
Le seul gros problème réside en effet au niveau de la récupération du Finder, et là c'est une toute autre paire de manche....
[EDIT]
Je n'avais pas lu ce que tu avais mis Bru, car on postait en même temps, donc WindowList ne fourni pas ce qu'on veut, en effet ça complique la chose....
Non, NSWindowList ne fournit pas de pointeurs, mais des "numéros" de fenêtre. Il s'agit d'une numérotation interne propre au window manager.
Le mystère pour le moment est donc bien de savoir comment récupérer la fenêtre elle même (son pointeur, son contexte ou son instance) à partir de ce numéro.
.
[tt]
// Get on-screen window counts and lists.
extern OSStatus CGSGetWindowCount(const CGSConnection cid, CGSConnection targetCID, int* outCount);
extern OSStatus CGSGetWindowList(const CGSConnection cid, CGSConnection targetCID,
 int count, int* list, int* outCount);
[/tt]
Pour l'instant, je n'ai pas le temps de m'amuser avec ça, mais je donne le lien du projet si certains veulent regarder ça de plus près :
Desktop Manager
En effet, il est contre-nature d'accéder aux fenêtres qui appartiennent a une autre appli, et de telles fonctionnalitées ne seront jamais implémentées dans les APis officielles lors de futures versions d'OS X. Bien sûr si les privates fonctions changent de nom dans le futur, c'est plantage assuré pour le soft qui tape dans ces fonctions...
Je ne sais pas où le gars qui a développé le Desktop Manager a bien pu se procurer ce header sur des fonctions CGS spécialisées dans le fenêtrage, mais en tout cas c'est surement le seul moyen pour récupérer les pointeurs de fenêtres.... :P
Peut-être ne reste-t-il qu'une solution "stratégique" : faire l'éco écran malgré tout basé sur ces fonctions interdites (parce que éphémères). Même un peu buggé, il aura surement un succè énorme. A la sortie de Tiger, il marchera probablement plus... MAIS Apple aura vu qu'il a telement de succès (comme Flurry à son époque), qu'il le réécrira et l'intergrera en standart dans le système
Z"en dites quoi ?
(Bon, j'ai une solution beaucoup moins élégante : au lieu que ce soient les fenêtres qui reculent et se mettent à flotter, se serait juste tout l'écran, tel quel en entier, qui reculerai, et flotterai sur le même principe que mon idée de départ... au mouvement de souris, il revient immédiatement se remettre en place. Et dernière idée : que l'écran se fragmente en plusieurs morceaux... que ces morceau flottent... etc... ...)
Ces fonctions ne sont pas éphémères, peut-être par leur nom si c'est comme ça que tu l'entends. Elles sont vitales pour le système, car la machinerie Quartz en fait usage, ainsi que des softs comme Exposé ou ImageCapture qui utilisent certainement ces fonctions CGS. Donc rien ne dis que dans leur état actuel elles ne fonctionneront plus sous Tiger, et si elles changent de nom, il y aura toujours des petits malins pour se procurer le nouveau fichier header, qui se retrouvera surement tot ou tard dans un projet OpenSource, bon faut le chercher mais rien n'est impossible... Â
Cette idée est bien plus compliquée Vinc26 ! Récupérer les fenêtres est une chose, le Finder en est une autre...
Non ? je me trompe ?
Bien sûr que l'on peut récupérer l'écran, mais il faut voir de quelle manière, je ne me suis jamais penché sur ce problème...
Sur OC on se tutoie Vinc26 !
J'ai des projets en cours très demandeurs en temps, mais pour me changer un peu, et aussi toucher à d'autres aspects de la programmation (Economiseur d'écran, OpenGL), je veux bien quand j'en trouve le temps faire avancer ce projet.
ça ne pourrait pas fonctionner avec la méthode initWithWindowRef: ?
(soyez indulgents si j'ai dit une bêtise)
Bien sur, cette méthode m'est connue, mais ce n'est pas là qu'est le problème...???
Je pense que pour les fenêtres, je tiens le bon bout.
Par contre, je séche pour le bureau.
.
eh ? dès qu't'as un truc à montrer... même minime... t'hésite pô ?! :adios!:
(ai-je encore dit une bêtise ?)
Non, ce n'est pas une bétise. C'est l'une des solutions que j'ai envisagé.
J'ai seulement peur de "l'inesthétisme" que ça pourrait faire...
.