Obtenir le numéro de fenêtre via L'API D'accessibilité D'OSX

je travaille sur une application qui déplace les fenêtres des applications tierces sur l'écran.

pour avoir un aperçu de toutes les fenêtres actuellement ouvertes, j'utilise

CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);

renvoie un tableau de dictionnaires définissant chaque fenêtre ouverte. Voici un dictionnaire exemplaire retourné:

{
    kCGWindowAlpha = 1;
    kCGWindowBounds =         {
        Height = 442;
        Width = 475;
        X = 3123;
        Y = "-118";
    };
    kCGWindowIsOnscreen = 1;
    kCGWindowLayer = 0;
    kCGWindowMemoryUsage = 907184;
    kCGWindowName = Untitled;
    kCGWindowNumber = 7328;
    kCGWindowOwnerName = TextEdit;
    kCGWindowOwnerPID = 20706;
    kCGWindowSharingState = 1;
    kCGWindowStoreType = 2;
    kCGWindowWorkspace = 3;
},

le dictionnaire est plein de bonnes informations utilisées ailleurs mais manque d'un objet d'accessibilité qui pourrait être utilisé pour modifier le windows. Les fenêtres sont clairement identifiées par le numéro de la fenêtre.

j'utilise maintenant le PID (kCGWindowOwnerPID) pour créer un objet accessibility pour l'application de la fenêtre:

AXUIElementRef app = AXUIElementCreateApplication(pid);

suivi d'une liste de toutes les fenêtres que L'application a ouvertes en utilisant AXUIElementCopyAttributeValues:

NSArray *result;

AXUIElementCopyAttributeValues(
                               (AXUIElementRef) app, 
                               kAXWindowsAttribute,
                               0,
                               99999,
                               (CFArrayRef *) &result
                               );

cela fonctionne et renvoie un tableau D'AXUIElements. C'est là que je suis bloqué. Il ne semble pas y avoir D'appel API pour récupérer le numéro de fenêtre d'un objet accessibility. Est-il possible soit de

a) trouver le numéro de fenêtre de l'objet accessibility (pour finalement itérer sur le tableau et trouver la fenêtre de droite)

ou

B) correspondent-elles clairement à une fenêtre décrite dans le tableau retourné par CGWindowListCopyWindowInfo aux objets D'accessibilité retournés par AXUIElementCopyAttributeValues?

21
demandé sur 0x90 2011-05-30 20:52:38

2 réponses

nous avons fini par embaucher un développeur dédié à L'accessibilité pour cette tâche.

il s'avère qu'il n'y a aucun moyen de le faire sans utiliser des API sans papiers (un non-go dans notre cas).

heureusement, il y a une solution pratique:

boucle sur toutes les fenêtres ouvertes de l'application. Obtenez leur position, taille et titre:

AXUIElementCopyAttributeValue(target, kAXPositionAttribute, CFTypeRef*)&posValue);
AXUIElementCopyAttributeValue(target, kAXSizeAttribute, (CFTypeRef*)&sizeValue);
AXUIElementCopyAttributeValue(target, kAXTitleAttribute, (CFTypeRef*)&titleValue);

ensuite, convertir la position et la taille en réelle CGPoint et CGSize valeurs:

AXValueGetValue(posValue, kAXValueCGPointType, &point);
AXValueGetValue(sizeValue, kAXValueCGSizeType, &size);

comparer la taille, la position et le titre avec les valeurs retournées par l'objet dans CGWindowListCopyWindowInfo() . Si elles concordent, vous pouvez en toute sécurité supposer que c'est la fenêtre que vous cherchiez et utiliser L'AXUIElement déjà ouvert ( target dans notre cas) pour le travailler.

le ciel pour la boucle à travers toutes les fenêtres ouvertes s'avère être négligeable sur OSX. Il est assez bas de plafond sur plusieurs fenêtres sont ouvertes en même temps.

aussi, bien que ce ne soit pas 100% précis (il est possible que 2 fenêtres aient la même position, taille et titre), nous n'avons pas rencontré de situation dans l'utilisation réelle où cela se produit jusqu'à présent.

23
répondu 0x90 2011-06-15 22:19:10

il y a une fonction privée pour obtenir le numéro de la fenêtre CG pour un objet AX donné pour la fenêtre: _AXUIElementGetWindow . Plus de détails dans la discussion SO identifier uniquement la fenêtre active sur OS X Il semble qu'il n'y ait pas D'API publique pour effectuer la tâche avec une probabilité de 100%. L'identification des fenêtres par titre et par cadre (tel que décrit dans la réponse ci-dessus) fonctionnera dans 99,9% des cas.

8
répondu Oleksiy Ivanov 2017-05-23 12:02:37