En esta página se describe el procedimiento necesario para que NVDA soporte un nuevo atributo aria al navegar por la web.

Modo foco

Comenzaremos con el modo foco, ya que es un poco más simple.

Descripción

En el modo foco, rellenamos un objeto de la clase NVDAObject con la información del elemento sobre el que se encuentra el foco. A continuación, en speech.py, debemos indicar cómo se verbaliza este elemento.

Extensión de la interfaz NVDAObject

Para hacerlo, se debe añadir una nueva propiedad a la clase base NVDAObject en NVDAObjects/init.py. Necesitaremos ofrecer una solución para todos los navegadores. Una forma de hacerlo podría parecerse al siguiente ejemplo, que añadirá un mensaje al registro (y producirá un sonido de error) con el nombre de la clase concreta que utiliza la implementación base, y una traza con la pila de llamadas que nos llevan hasta ese punto.
def _get_isCurrent(self):
log.debugWarning(«impl required for: %s» % repr(self), stack_info=True)
Nota: una vez que hayamos hecho pruebas e investigado lo suficiente debemos devolver None, False o potencialmente lanzar una excepción del tipo NotImplementedError. En este caso no queremos lanzar una excepción porque el código que va a usar esta implementación no va a recoger el valor de isCurrent, y no queremos que emitan un sonido de error o un mensaje al registro.
Otra opción sería pulsar NVDA+f1 o usar la consola Python para investigar los atributos en un objeto mientras navegamos.
Las clases donde se debe implementar el atributo son:

  • clase Ia2Web en NVDAObjects/IAccessible/ia2Web.py
    • Aquí se puede imprimir en el registro el valor de self.IA2Attributes para estar seguro que el atributo que quieres añadir está disponible. Cuando estés seguro de que existe (y sepas cómo se llama), consíguelo y devuélvelo. Por ejemplo, para aria-current:
      return self.IA2Attributes.get(«current», False)
    • Con un poco de suerte esto añadirá soporte para el atributo en Firefox y Chrome, pero no olvides hacer pruebas.
  • clase MSHTML en NVDAObjects/IAccessible/MSHTML.py
    • De forma similar a Chrome y Firefox, primero intenta imprimir por registro el valor de self.HTMLAttributes. Después, cuando estés seguro del nombre, intenta devolver el valor de tu nueva propiedad. Por ejemplo:
      return self.HTMLAttributes[«aria-current»]
  • clase EdgeNode en NVDAObjects/UIA/edge.py
    • En el caso de Edge, primero necesitarás imprimir por registro self.UIAElement.currentAriaProperties. Después, construye una expresión regular para obtener el valor de la propiedad.

Saber cómo hablarlo

En speech.py extraemos los valores de la propiedad (en speakObjectProperties) que nos interesan (con frecuencia basados en los ajustes de voz) y los relacionamos con la voz (en getSpeechTextForProperties).

Modo revisión

El modo revisión funciona de manera un poco diferente a como lo hace el modo foco:

  • Text Infos en vez de NVDAObjects
  • Algunos objetos Text Info se implementan con buffers virtuales
  • Debemos ser capaces de operar con navegación rápida, por lo que tenemos que poder saltar rápidamente a un elemento (encabezado anterior, siguiente enlace, etc.). De esta manera, el modo revisión debe estar mucho más preparado que el modo foco, que sólo trabaja con un objeto.
  • Vale la pena destacar que los buffers virtuales se usan con Firefox, Chrome e Internet Explorer, pero no son la base del modo revisión en Microsoft Edge, Kindle o Word.

Cómo obtener el valor desde el buffer virtual

Para anunciar texto en el modo revisión, debemos asegurarnos dónde está expuesto y extraer el atributo desde el buffer virtual que usan Chrome, Firefox e Internet Explorer.

Chrome y Firefox

El nuevo atributo debería estar expuesto en el argumento attrs que se pasa a la función _normalizeControlField en la clase Gecko_ia2_TextInfo (archivo virtualBuffers/gecko_ia2.py). Es bastante probable que tengas que imprimir en el registro de NVDA el contenido del argumento attrs para saber el nombre del atributo, para después relacionarlo con la propiedad deseada. Por ejemplo:
ariaCurrent = attrs.get(«IAccessible2::attribute_current»)
if ariaCurrent != None:
attrs[‘current’]= ariaCurrent

Internet Explorer

Para Internet Explorer, debemos exponer el atributo desde el buffer virtual. Mira en nvdaHelper/vbufBackends/mshtml/mshtml.cpp, mira la función void getAttributesFromHTMLDOMNode y añade una línea como:
macro_addHTMLAttributeToMap(L»aria-current»,false,pHTMLAttributeCollection2,attribsMap,tempVar,tempAttribNode);
A continuación necesitamos exponer, y relacionar con la propiedad que usemos para la verbalización. En este caso deseamos relacionar ‘aria-current’ con ‘current’. Para hacerlo, mira en la función _normalizeControlField de la clase MSHTMLTextInfo (archivo virtualBuffers/MSHTML.py). Podemos hacer algo como:
ariaCurrent = attrs.get(‘HTMLAttrib::aria-current’, None)
if ariaCurrent is not None:
attrs[‘current’]=ariaCurrent

Microsoft Edge

Es un poco diferente de los demás, ya que no usamos buffers virtuales. Podemos extraer el valor del NVDAObject que establecimos para el modo foco. En la función _getControlFieldForObject de NVDAObjects/UIA/edge.py se puede hacer algo como:
field[‘current’]=obj.isCurrent

Verbalización del valor

A continuación, necesitamos «permitir» la propiedad en la función getControlFieldSpeech de speech.py. Para hacerlo hay que añadir algo como valueForCurrent = attrs.get(‘current’, None), y después obtener el texto para la voz para este valor: speechForCurrent = getSpeechTextForProperties(reason=reason,current=valueForCurrent).
La parte difícil de esto es que hay que saber cuándo añadir el texto según el texto devuelto.

Braille

No olvides programar y probar la salida braille. Consulta (todo en braille.py):

  • def getBrailleTextForProperties
  • def getControlFieldBraille
  • def update en la clase NVDAObjectRegion para pasar los argumentos adecuados a getBrailleTextForProperties

Hacer pruebas con braille

Si no tienes una pantalla braille, consulta la documentación relacionada con pruebas sin pantalla braille.

Ejemplo completo

Para ver un ejemplo completo, consulta la solicitud de cambios #6860