Projet d'économiseur d'écran

Vinc26Vinc26 Membre
17:29 modifié dans Vos applications #1
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 !  o:)
«13456725

Réponses

  • Eddy58Eddy58 Membre
    17:29 modifié #2
    Salut Vinc26 et bienvenu sur OC ! :)

    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]
  • BruBru Membre
    17:29 modifié #3
    Bon, je viens de jetter un oeil sur MacG et MacB...

    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.

    .
  • Vinc26Vinc26 Membre
    17:29 modifié #4
    Bon moi perso j'y comprend rien mais je transmet au gars qui a déjà  bien planché dessus ! Merci !

    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 
  • Vinc26Vinc26 Membre
    17:29 modifié #5
    Déjà  : Génial ! Bravo ! Merci ! Je sens qu'ici il y a du monde ! Y'a de l'écho ! Coool ! J'espère que l'un d'entre vous aura envie de se pencher aussi sur mon idée de plugin video pour garageband... mais c'est pas le sujet ici.


    dans 1108041257:

    D'autre part, que se passe t'il si la fenêtre est animée ?


    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!:
  • Eddy58Eddy58 Membre
    17:29 modifié #6
    J'ai fait un peu joujou :o avec tout ça ce soir, dans une appli qui grabbe elle-même sa propre fenêtre, et voici ce qu'il en ressort :

    - 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]
  • BruBru Membre
    17:29 modifié #7
    dans 1108081205:

    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... 


    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]

    .
  • Eddy58Eddy58 Membre
    17:29 modifié #8
    J'ai essayé ce que tu as proposé Bru mais ca ne fait rien du tout...:-\\
    [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]
  • BruBru Membre
    17:29 modifié #9
    dans 1108147835:

    J'ai essayé ce que tu as proposé Bru mais ca ne fait rien du tout...:-\\


    En fait, pour donner le "focus" à  une fenêtre c'est tout con :
    [tt][[laFenetre contentView] lockFocus];
    [/tt]

    Voilà ...

    .
  • BruBru Membre
    17:29 modifié #10
    En fait, ce weekend, j'ai un peu joué avec les fenêtres.

    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é...

    .
  • Eddy58Eddy58 Membre
    17:29 modifié #11
    Effectivement Bru ! :)
    J'avais aussi réglé le problème avec NSGraphicsContext :
    [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithWindow:mainWindow]];
  • Vinc26Vinc26 Membre
    17:29 modifié #12
    Bon, donc il est maintenant clair que la seule solution est de faire du reverse ingénieurtruc ? C'est bien ça ? Pour reverser soit Imagecapture, soit SnapProX ?

    Et vous connaissez personne qui touche un peu là  dedans ?

    :crackboom:-
  • BruBru Membre
    17:29 modifié #13
    dans 1108373687:

    Bon, donc il est maintenant clair que la seule solution est de faire du reverse ingénieurtruc ? C'est bien ça ? Pour reverser soit Imagecapture, soit SnapProX ?


    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...

    .
  • Eddy58Eddy58 Membre
    février 2005 modifié #14
    Non Vinc26, on a trouvé le moyen de récupérer des images des fenêtres : avec initWithFocusedRect:, et en jouant avec le focus pour choisir les fenêtres. Mais bon pour l'instant ça marche que dans le cadre des fenêtres de l'application de test elle-même. Maintenant il faudrait essayer ce principe avec les pointeurs de fenêtre fourni par WindowList, mais normalement ça devrait marcher.
    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....
  • BruBru Membre
    17:29 modifié #15
    dans 1108374093:

    Maintenant il faudrait essayer ce principe avec les pointeurs de fenêtre fourni par WindowList, mais normalement ça devrait marcher.


    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.

    .
  • Eddy58Eddy58 Membre
    17:29 modifié #16
    Ok....donc il ne "reste" plus qu'à  trouver la fonction magique qui retourne les pointeurs de fenêtres...avec la rétro-ingénierie sur des applis telles que QuartzDebug, ImageCapture ou autre, mais là  c'est pas du gâteau. Mais peut-être y-a-t-il quelque chose de bien planqué dans les docs Apple ? Ou alors pourquoi pas en lorgnant du côté de l'open source, peut-être qu'il traà®ne des sources sur le net qui nous aideraient à  régler ce problème...???
  • Eddy58Eddy58 Membre
    17:29 modifié #17
    En faisant un petit tour sur SourceForge, j'ai trouvé un projet, un Desktop Manager, qui comporte un header "CGSPrivate.h" (Core Graphics). Avec des fonctions pour le moins intéressantes. :)
    [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
  • mpergandmpergand Membre
    17:29 modifié #18
    Faire, aussi, une recherche sur Google avec "site:lists.apple.com Private APIs "
  • Eddy58Eddy58 Membre
    17:29 modifié #19
    Merci mpergand pour cette méthode de recherche dans les devlists Apple que je ne connaissais pas...:) Je l'utiliserais plus dans le futur...mais je n'ai rien appris de nouveau, à  part le faites que les appels directs aux fonctions CGS sont fortements déconseillés :

    APPLE:
    > DO NOT USE the CGSMoveWindow or any CGS* functions. These are private
    > functions to CoreGraphics. We reserve the right to change these in any
    > Mac OS X release or update and therefore will break your application.
    > Maybe it's time to mangle the names of the private functions so they
    > are harder to find :-)
    >
    > You should use the Carbon or Cocoa equivalent versions of the
    > function. If you need any windowing functionality that is missing at
    > the Carbon / Cocoa level, file an enhancement request at
    > http://bugreport.apple.com, but do not use any private functions. You
    > do so at your own risk.

    DEV:
    Of course, but the problem is that i'm writing a program which handles
    move and resize of any window in real time (like in some Unix window
    manager as Fluxbox). So I think I can't use Cocoa functions because I
    'm not the owner of the window.

    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
  • Vinc26Vinc26 Membre
    17:29 modifié #20
    Bon... ben il semble que se soit de plus en plus compromis...  :'(

    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  :o

    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... ...)

  • Eddy58Eddy58 Membre
    17:29 modifié #21
    dans 1108540607:

    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).

    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... :) 

    dans 1108540607:

    (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... ...)

    Cette idée est bien plus compliquée Vinc26 ! Récupérer les fenêtres est une chose, le Finder en est une autre...
  • Vinc26Vinc26 Membre
    17:29 modifié #22
    A mais je parle pas du finder. Je parle juste de récupérer tout l'écran tel quel ! Comme le fait SnapzProX. Comme on le fait avec Maj+Pomme+3. Juste un screenshot (comme le font quelques petits programme tels http://www.bainsware.com/snapperhead/ ...)

    Non ? je me trompe ?  :o
  • Vinc26Vinc26 Membre
    17:29 modifié #23
    Celà  dit, envisagez-vous de bosser dessus via les CSG ?
  • Eddy58Eddy58 Membre
    17:29 modifié #24
    dans 1108558908:

    A mais je parle pas du finder. Je parle juste de récupérer tout l'écran tel quel ! Comme le fait SnapzProX. Comme on le fait avec Maj+Pomme+3. Juste un screenshot (comme le font quelques petits programme tels http://www.bainsware.com/snapperhead/ ...)

    Non ? je me trompe ?  :o

    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... :o


    Celà  dit, envisagez-vous de bosser dessus via les CSG ?

    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. :)
  • Vinc26Vinc26 Membre
    17:29 modifié #25
    Cool !  <3
  • BaardeBaarde Membre
    17:29 modifié #26
    Creating an NSWindow Object for the Carbon Window

    ça ne pourrait pas fonctionner avec la méthode initWithWindowRef: ?
    (soyez indulgents si j'ai dit une bêtise)
  • Eddy58Eddy58 Membre
    février 2005 modifié #27
    NLBDC, dis toi bien qu'il n'y a que ceux qui ne font rien qui ne font pas de conneries...;)
    Bien sur, cette méthode m'est connue, mais ce n'est pas là  qu'est le problème...???
  • BruBru Membre
    17:29 modifié #28
    Bon, je comence pas mal à  jouer avec les core graphics services.

    Je pense que pour les fenêtres, je tiens le bon bout.

    Par contre, je séche pour le bureau.

    .
  • Vinc26Vinc26 Membre
    17:29 modifié #29
    Coooool !  :o

    eh ? dès qu't'as un truc à  montrer... même minime... t'hésite pô ?!  :adios!:
  • BaardeBaarde Membre
    17:29 modifié #30
    Pour le bureau, on peut p'tet faire un masquage momentané de toutes les fenêtres.
    (ai-je encore dit une bêtise ?)
  • BruBru Membre
    17:29 modifié #31
    dans 1109168178:

    Pour le bureau, on peut p'tet faire un masquage momentané de toutes les fenêtres.
    (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...

    .
Connectez-vous ou Inscrivez-vous pour répondre.