visualizacion todas teclado tecla simbolos pegar para opciones mac las imagenes funciones expulsar cortar como comandos comando carpetas arranque objective-c macos cocoa

objective-c - todas - teclado mac funciones



Identificar de forma Ășnica la ventana activa en OS X (2)

Estoy tratando de parchar una aplicación que cambia el tamaño de las ventanas usando la API de accesibilidad.

Necesito mantener un diccionario con los tamaños anteriores de ventanas. La clave debe identificar la ventana activa actualmente. En este momento, esta ventana activa se recupera a través de NSAccessibilityFocusedWindowAttribute al presionar una tecla de NSAccessibilityFocusedWindowAttribute rápido.

Sin embargo, cada vez que se llama a este método, el AXUIElementRef devuelto que identifica la ventana es diferente . Esto, por supuesto, significa que no puedo usarlo como una clave de diccionario; el diccionario no encontrará la entrada correspondiente.

El siguiente código reproduce el problema:

-(IBAction)testWindowIdentification:(id)sender{ AXUIElementRef focusedApp; AXUIElementRef focusedWindow; AXUIElementCopyAttributeValue(_systemWideElement, (CFStringRef) kAXFocusedApplicationAttribute, (CFTypeRef*) &focusedApp); AXUIElementCopyAttributeValue((AXUIElementRef) focusedApp, (CFStringRef) NSAccessibilityFocusedWindowAttribute, (CFTypeRef*) &focusedWindow); CFShow(focusedWindow); }

_systemWideElement se ha inicializado en el método init mediante una llamada a AXUIElementCreateSystemWide() .

La declaración de CFShow muestra claramente diferentes ID cada vez que se llama al método (aunque la misma ventana está activa), lo que no me sirve de nada:

<AXUIElement 0x47e850> {pid=42463} <AXUIElement 0x47e890> {pid=42463} <AXUIElement 0x47e2c0> {pid=42463} …

La documentación sobre AXUIElement no muestra ningún método que recupere un atributo único para el elemento UI, y tampoco lo hace el protocolo NSAccessibility . El PID único no es suficiente para mí, ya que un proceso puede tener varias ventanas.

¿Cómo puedo recuperar algún identificador único de la ventana activa en Cocoa?

(Por cierto, el código real está verificando los códigos de retorno en las llamadas anteriores; no hay error, las llamadas tienen éxito).


Creo que podría usar las funciones de los Servicios de ventanas de Quartz, específicamente CGWindowListCreateDescriptionFromArray para enumerar las ventanas actualmente activas en una aplicación en particular.

Esta llamada es de nivel inferior a AppKit y no le dirá cuál es la ventana activa, pero le proporcionará ID de ventana que son únicas para la sesión de usuario actual. No es una gran solución, pero puede comparar la información de los límites de las ventanas con lo que recibe de las API de accesibilidad para asociar las ventanas con sus ID reales.


Rob Keniger tiene la estrategia correcta con su respuesta aquí . Lo único que falta en esta respuesta (y, de hecho, el motivo de la colocación de la recompensa) es una implementación viable que tome la ventana activa actual y la traduzca en una clave única adecuada para la indexación en el contexto de la aplicación actual.

La solución de Rob dibuja esto mediante el uso del CGWindowID dado en el contexto de los servicios de ventana de cuarzo. Por supuesto, está fuertemente implícito que esta referencia de ventana solo es útil para su aplicación actual .

Obtener esta referencia de ventana es complicado, ya que no existen garantías sólidas entre la API de accesibilidad y los servicios de ventana de cuarzo. Sin embargo, puede solucionar esto de las siguientes maneras:

  1. Use extern "C" AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out); , como se documenta aquí . No se garantiza que funcione, pero funciona como una prueba en la planta baja para comenzar si funciona en su versión de OSX.

  2. Obtenga el CGWindowID directamente, utilizando, por ejemplo, HIWindowGetCGWindowID() . Puede encontrar más detalles sobre la selección de la ventana activa y la extracción de la ID en el manual de referencia de Carbon Window Manager (advertencia: PDF grande).

  3. Catalogue su conjunto de CGWindowID usando algo como CGWindowListCreateDescriptionFromArray , exactamente como Rob sugirió. El objetivo aquí es encontrar algún esquema para enlazar la API de accesibilidad y Quartz, pero esto es posible utilizando, por ejemplo, una devolución de llamada vinculada al contexto de su ventana activa actual. Sin embargo, honestamente no conozco un ejemplo óptimo de esto que esté debidamente preparado para el futuro .

De las opciones, recomiendo ir con 2. para sus necesidades actuales, si no puede crear algún otro decorador para sus ventanas para identificarlas de manera única. Actualmente está definido en la base de código heredado, pero hará lo que desees.

Mucha suerte con tu aplicación.