Aiguillage sur la route à prendre pour simuler la souris

Joan

Membre confirmé
28 Novembre 2003
18
0
Bonjour.

Voici mon petit problème : je cherche à créer un programme qui émule en quelque sorte un clic de souris. Par exemple je charge un swf dans une fenêtre de safari. On peut voir une balle qui roule d'un bord à l'autre et un bouton qui permet de rembobiner l'animation.

Le programme en question permettrait par exemple de simuler un clic de souris sur à un endroit "x,y" de l'écran spécifié (le bouton par exemple) à intervalle régulier.

Peut on réaliser cela en applescript ? sinon vers quel type de programmation dois je me tourner ?

Merci d'avance pour vos conseilles :)
 
j'ai trouvé une piste avec applescript : "keystroke".
Mais je n'arrive pas à trouver l'équivalent souris de ctte petite merveille.
 
Joan a dit:
j'ai trouvé une piste avec applescript : "keystroke".
Mais je n'arrive pas à trouver l'équivalent souris de ctte petite merveille.
Si j'ai bien compris, il ne s'agit pas de reproduire l'apparence du pointeur, mais d'automatiser un clic de souris sur un point précis de l'écran et pendant une durée déterminée (ou non). Si c'est bien ce que tu souhaites faire, je te suggère de te pencher sur les commandes de scriptage de l'interface détaillées dans la "Processes Suite" du dictionnaire de l'application "System Events".

Par exemple, le code suivant...
Bloc de code:
activate application "Finder"
tell application "System Events"
	tell application process "Finder"
		click group 1 of scroll area 1 at {100, 100}
	end tell
end tell
... simule un clic sur le Finder à la position 100 px, 100 px.
 
Merci enormement c'est exactement cela que je recherche : un clic de souris à un endroit de l'écran sauf qu'aucun utilisateur appuie sur le bouton de la souris.
 
J'ai réussi cela

tell application "iCal"
activate
end tell
tell application "System Events"
tell process "ical"
click at {60, 60}
end tell
end tell

Ca marche super bien. Donc ce que je fais c'est un imprime ecran que j'ouvre avec graphicconverter ce qui me donne la position en pixel. En placant le bouton rouge pour fermer la fenêtre d'iCal ca marche super.

Je fais la même chose, sauf que je remplace iCal par Safari. Pour un lien ca marche super. Par contre si i y a un fichier flash dans la page il ne veut pas cliquer dans l'animation flash si le point du click se trouve dnas celle-ci : comment faire ?

Merci de votre patience avec le grand débutant que je suis.
 
Joan a dit:
Je fais la même chose, sauf que je remplace iCal par Safari. Pour un lien ca marche super. Par contre si i y a un fichier flash dans la page il ne veut pas cliquer dans l'animation flash si le point du click se trouve dnas celle-ci : comment faire ?
J'ai fait quelques essais afin de te venir en aide, mais tous ont échoué. À vrai dire, à moins que quelqu'un propose une solution, cela ne me semble tout bonnement pas possible. Avec AppleScript du moins...
Si j'en ai le temps, je vais essayer de pousser mes investigations, mais je ne suis pas très optimiste.
 
Merci beaucoup d'avance pour tes recherches, même si elles ne sont pas fructueuses. J'en fais de même de mon côté.
 
Voila ce que l'on m'a répondu dans un autre forum :

Dans ce cas, il est probable que Flash ne passe pas par la gestion d'évènements du système, et fonctionne à plus bas niveau que Carbon pour récupérer les évènements. Je pense qu'AppleScript passe sûrement par des fonctions Carbon, donc passer directement par Carbon ne va peut-être rien faire de plus, mais ça n'empêche pas d'essayer pour être sûr.
 
A un niveau plus bas que Carbon? Il va lire les registres du contrôleur USB de la souris ou quoi?

Non, c'est très improbable.

Cocoa gère de façon transparente les AppleEvents (événements passés par AppleScript, entre autres), ce n'est pas le cas des applis Carbon, où il est nécessaire de programmer soi-même cette gestion des AppleEvents. Tu sais, c'est la distinction entre les applis qui sont scriptables et celles qui ne le sont pas...

Le plug-in Flash n'est très certainement pas scriptable, il faut justement utiliser des fonctions Carbon pour simuler la souris.
 
Céroce a dit:
A un niveau plus bas que Carbon? Il va lire les registres du contrôleur USB de la souris ou quoi?

Non, c'est très improbable.

Cocoa gère de façon transparente les AppleEvents (événements passés par AppleScript, entre autres), ce n'est pas le cas des applis Carbon, où il est nécessaire de programmer soi-même cette gestion des AppleEvents. Tu sais, c'est la distinction entre les applis qui sont scriptables et celles qui ne le sont pas...

Le plug-in Flash n'est très certainement pas scriptable, il faut justement utiliser des fonctions Carbon pour simuler la souris.

hier

http://www.mainevent.com/articles.html
http://devworld.apple.com/dev/techsupport/develop/issue21/21simone.html
http://developer.apple.com/documentation/AppleScript/Conceptual/AppleEvents/dispatch_aes_aepg/chapter_4_section_2.html#//apple_ref/doc/uid/TP40001449-CH204-BABDBIGA

http://developer.apple.com/samplecode/MoreOSL/MoreOSL.html

on peut voir avec ça que
AppleScriptCarbonKit.framework est à inventer

AppleScript 1.3.4 SDK (DMG)

->
1999-01-23

aujourd'hui
quand on créee une application carbon
dans IB tu peux ajouter un composant applescript
 
tatouille a dit:
aujourd'hui
quand on créee une application carbon
dans IB tu peux ajouter un composant applescript

Ce qui veut bien dire qu'il faut délibéremment choisir d'implémenter les AppleEvents dans ton appli Carbon, non? C'est très bien qu'on puisse le faire simplement sous IB, mais ça ne remet pas en cause mon explication. Je ne prétends pas que c'est la bonne, mais elle est meilleure que dire que ça se passe à un niveau plus bas que Carbon.

Tous les exemples que Joan nous a donné d'appli qui marchent sont des applis scriptables (iCal, Safari). A mon humble avis, pour simuler un clic, AppleScript passe un AppleEvent "Clic de souris au point x,y". Il faudrait donc que le destinataire du clic soit scriptable.
 
Céroce a dit:
Tous les exemples que Joan nous a donné d'appli qui marchent sont des applis scriptables (iCal, Safari). A mon humble avis, pour simuler un clic, AppleScript passe un AppleEvent "Clic de souris au point x,y". Il faudrait donc que le destinataire du clic soit scriptable.
Précisément. Or une animation Flash (ou un lien dans une vidéo Quicktime) au sein d'une page HTML est perçue par AppleScript comme un groupe dont les différents composants restent indéterminés. Ainsi, il n'est tout bonnement pas possible d'utiliser le scriptage d'interface pour intervenir sur l'un des éléments de ce groupe (un bouton, une animation, une URL, etc.) Les autres méthodes évoquées (Cocoa/Carbon) dépassent de loin mes maigres compétences. ;)
 
Céroce a dit:
Ce qui veut bien dire qu'il faut délibéremment choisir d'implémenter les AppleEvents dans ton appli Carbon, non? C'est très bien qu'on puisse le faire simplement sous IB, mais ça ne remet pas en cause mon explication. Je ne prétends pas que c'est la bonne, mais elle est meilleure que dire que ça se passe à un niveau plus bas que Carbon.

Tous les exemples que Joan nous a donné d'appli qui marchent sont des applis scriptables (iCal, Safari). A mon humble avis, pour simuler un clic, AppleScript passe un AppleEvent "Clic de souris au point x,y". Il faudrait donc que le destinataire du clic soit scriptable.

heu c'étaitdans ton sens c'était juste pour noter ironiquement le belle effort d'apple :D en trois ans
 
DocEvil a dit:
(un bouton, une animation, une URL, etc.)

tous ces éléments dont tu parles font partie du fichier swf... on est bien d'accord la dessus ??? une URL mais une URL dans un flash...

Donc si j'y suis bien lol faut que je me plonge dans cocoa... ???
 
Joan a dit:
tous ces éléments dont tu parles font partie du fichier swf... on est bien d'accord la dessus ??? une URL mais une URL dans un flash...
Oui, c'est exactement ce dont je voulais parler.
En ce qui concerne Cocoa, je cède la place aux experts. ;)
 
Bonsoir

Il est possible de fabriquer un petit programme avec Xcode pour simuler le fonctionnement de la souris.

Je n'ai pas trop le temps de regarder en ce moment, mais en revanche j'ai déjà un début de piste.

Une recherche sur "IOHIDPostEvent()" "NX_LMOUSEUP" "NX_LMOUSEDOWN" et "NX_MOUSEMOVED" devrait vous permettre de trouver votre bonheur.
 
PA5CAL a dit:
Bonsoir

Il est possible de fabriquer un petit programme avec Xcode pour simuler le fonctionnement de la souris.

Je n'ai pas trop le temps de regarder en ce moment, mais en revanche j'ai déjà un début de piste.

Une recherche sur "IOHIDPostEvent()" "NX_LMOUSEUP" "NX_LMOUSEDOWN" et "NX_MOUSEMOVED" devrait vous permettre de trouver votre bonheur.

Super Merci Pascal c'est ce qui me faut des pistes, si vraiment j'y arrive pas je reposte.
 
Ça y est :) ! J'ai pu trouver un peu de temps, alors j'ai concocté un petit programme en C++, type ligne de commande, qui simule les clics souris. Il faut le compiler avec le framework IOKit.

Bloc de code:
/* Click (C) 2006 PA5CAL for MacGeneration
 * 
 *  Purpose: Simulate mouse events
 *  Syntax:
 *        click <x> <y> [l|2|r]
 *  Options:
 *        l = left button click (default)
 *        2 = left button double click
 *        r = right button click
 */

#include <ApplicationServices/ApplicationServices.h>
#include <IOKit/hidsystem/IOHIDShared.h>
#include <IOKit/IOKitLib.h>


class HIDService
{
private:
    io_connect_t event_driver;
    mach_port_t io_master_port;
public:
    HIDService();
    ~HIDService();
    kern_return_t Open();
    kern_return_t Close();
    void SendMouseEvent(int right, int down, SInt32 x, SInt32 y);
    void Click(int right, SInt32 x, SInt32 y);
    void DoubleClick(int right, SInt32 x, SInt32 y);
};

#pragma mark -
#pragma mark HIDService

HIDService::HIDService()
{
    event_driver = MACH_PORT_NULL;
    Open();
}

HIDService::~HIDService()
{
    Close();
}

kern_return_t HIDService::Close()
{
    kern_return_t r = KERN_SUCCESS;
    if (event_driver!=MACH_PORT_NULL)
        r = IOServiceClose(event_driver);
    event_driver = MACH_PORT_NULL;
    return r;
}

kern_return_t HIDService::Open()
{
    kern_return_t kr;
    mach_port_t ev, service;

    if (KERN_SUCCESS==(kr = Close())) {
        if (KERN_SUCCESS!=(kr = IOMasterPort(MACH_PORT_NULL, &io_master_port)))
            return kr;
        if (io_master_port!=MACH_PORT_NULL) {
            if (service = IOServiceGetMatchingService(kIOMasterPortDefault, 
                                        IOServiceMatching(kIOHIDSystemClass))) {
                kr = IOServiceOpen(service, mach_task_self(), 
                                    kIOHIDParamConnectType, &ev);
                IOObjectRelease(service);

                if (KERN_SUCCESS==kr)
                    event_driver = ev;
            }
        }
    }
    return kr;
}

void HIDService::SendMouseEvent(int right, int down, SInt32 x, SInt32 y)
{
    if (event_driver==MACH_PORT_NULL)
        return;

    int eventType;
    if (right){
        if (down)
            eventType = NX_RMOUSEDOWN;
        else
            eventType = NX_RMOUSEUP;
    } else {
        if (down)
            eventType = NX_LMOUSEDOWN;
        else
            eventType = NX_LMOUSEUP;
    }

    IOGPoint scrPos;
    scrPos.x = x;
    scrPos.y = y;

    NXEventData eventData;
    eventData.mouse.subType = NX_SUBTYPE_TABLET_POINT;
    eventData.mouse.subx = 0;
    eventData.mouse.suby = 0;
    eventData.mouse.click = 0;
    eventData.mouse.pressure = (down ? 255 : 0);
    eventData.mouse.tablet.point.x = x;
    eventData.mouse.tablet.point.y = y;
    eventData.mouse.tablet.point.buttons = 0x0000;
    eventData.mouse.tablet.point.tilt.x = 0;
    eventData.mouse.tablet.point.tilt.y = 0;
    eventData.mouse.tablet.point.deviceID = 0x81;

    (void)IOHIDPostEvent(event_driver, eventType, scrPos, &eventData,
                         kNXEventDataVersion, 0, kIOHIDSetCursorPosition);

    struct timespec rqtp = {0, 50000000};
    nanosleep(&rqtp, NULL);
}

void HIDService::Click(int right, SInt32 x, SInt32 y)
{
    SendMouseEvent(right, 1, x, y);
    SendMouseEvent(right, 0, x, y);
}

void HIDService::DoubleClick(int right, SInt32 x, SInt32 y)
{
    Click(right, x, y);
    Click(right, x, y);
}

#pragma mark -

void usage()
{
    printf("Click (C) 2006 PA5CAL for MacGeneration\n\n"
           "Purpose:\n"
           "\tSimulate mouse events\n"
           "Syntax:\n"
           "\tclick <x> <y> [l|2|r]\n"
           "Options:\n"
           "\tl = left button click (default)\n"
           "\t2 = left button double click\n"
           "\tr = right button click\n\n");
}

int main (int argc, char * const argv[])
{
    if (argc<3) {
        usage();
        return 0;
    }
    
    SInt32 x, y;
    x = atol(argv[1]);
    y = atol(argv[2]);

    int right = 0;
    int dbl = 0;
    if (argc>=4) {
        if (argv[3][0]=='r')
            right = 1;
        else
        if (argv[3][0]=='2')
            dbl = 1;
    }
    
    HIDService *hs;
    try {
        hs = new HIDService();
    }
    catch (const char *err) {
        printf("- failed -\n\n");
        delete hs;
        return 0;
    }
    
    if (dbl)
        hs->DoubleClick(right, x, y);
    else
        hs->Click(right, x, y);
    
    delete hs;
    
    return 0;
}