아티클

NVDA 추가 기능 개발 가이드라인 5부: 앱 모듈 제작

2019-07-25 18:43:30

안녕하세요. 엔비전스입니다.

'NVDA 추가 기능 개발 가이드라인 4부'에서는 글로벌 추가 기능 제작에 대해 살펴보았습니다. 5부에서는 글로벌 플러그인 제작에 이어 NVDA의 앱 모듈 작성 방법에 대해 살펴보겠습니다.

앱 모듈은 특정 응용 프로그램의 기능(스크린 리더 사용자가 컨트롤의 상호작용 방법의 변경, 커스텀 컨트롤에 초점 제공 등) 작업을 통해 스크린 리더 사용자가 프로그램을 이용하는 데 기능을 향상시킬 목적으로 작성하는 NVDA의 추가 기능의 한 형태입니다.

 

앱 모듈이란?

앱 모듈(APPModule)은 메모장, Chrome, Firefox와 같은 특정 프로그램에 대한 지원을 향상시킵니다. 예를 들어 화면의 다양한 부분을 읽는 데 편리한 명령을 추가하는 앱 모듈을 작성하거나 특정 컨트롤의 상호작용 방법을 변경하여 프로그램에서 어떻게 작동해야 하는지 정의할 수 있습니다.

앱 모듈은 프로그램의 실행 파일 이름에 해당하는 이름을 가진 Python (.py) 파일입니다. 예를 들어 chrome의 실행 파일 이름은 chrome.exe 이므로 Chrome 프로그램 앱 모듈의 이름은 chrome.py입니다.

NVDA에는 Firefox, Adobe Reader, Microsoft Office 프로그램 등과 같은 여러 앱 모듈이 제공되며, 개발자는 NVDA에 포함된 앱 모듈을 재사용하여 기존의 앱 모듈을 더욱 향상시킬 수도 있습니다.

 

앱 모듈과 글로벌 플러그인의 차이점

앱 모듈 작성을 위해 필요한 모듈 및 구현해야 할 클래스는 다음과 같습니다:

  • globalPluginHandler 대신 appModuleHandler 모듈을 import 해야 합니다. 구현할 클래스는 AppModule (appModuleHandler.AppModule) 입니다.
    • 앱 모듈은 appModules 폴더에 저장되며 프로그램의 실행 파일 이름과 동일한 이름이 지정됩니다.
  • 자체 음성 또는 점자 지원이 가능한 프로그램의 경우 NVDA가 일시 중지되도록 앱 모듈에서 처리할 수 있습니다.
  • event_NVDAObject_init를 통해 앱이 실행될 때 NVDA가 특정 객체의 이름, 역할 등을 변경하도록 요청할 수 있습니다.

- NVDA 사용자가 다른 앱을 사용하고 있을 때 이벤트를 처리할 객체를 감시하도록 요청할 수 있습니다.

이번 아티클에서는 앱 모듈 작성하기 첫 번째 시간으로, 기존에 정의된 컨트롤의 레이블(name) 변경과 컨트롤의 역할을 변경하는 과정을 통해 NVDA의 앱 모듈 작성 과정을 살펴보겠습니다.

앱 모듈 작성 시 컨트롤의 역할(role), 상태(states), window의ControlID, WindowClassName 등을 알아야 앱의 각 컨트롤의 조건을 올바로 검사할 수 있습니다. 이러한 정보는 NVDA 로그 뷰어(Insert+N) -> 도구(T) -> NVDA로그 뷰어 또는 Insert+F1 키를 통해 확인하거나, NVDA 파이썬 콘솔(Control+Insert+Z) 에서 <focus.devInfo, nav.devInfo를 통해 확인할 수 있습니다. Focus, nav는 NVDA의 파이썬 콘솔에서 사용할 수 있는 포커스 객체와 탐색 객체를 편리하게 검사하기 위해 사용할 수 있는 변수입니다. NVDA 파이썬 콘솔에서 사용할 수 있는 모든 변수 목록을 보려면, NVDA Developer Guide의 <5.2.2. Snapshot Variables> 섹션을 참고합니다.

 

주의

NVDA 2019.1 버전부터 추가 기능 테스트를 위해 기존의 NVDA 사용자 디렉터리 내 APPModules 디렉터리에 추가 기능 테스트 코드를 저장하는 방식에서 NVDA 설정 -> 고급 설정 패널의 개발자용 옵션 중 <Developer Scratchpad 디렉터리에서 코드를 불러들일 수 있습니다> 옵션을 선택한 후 <Developer Scratchpad 디렉터리를 엽니다> 버튼을 눌러 Scratchpad 폴더의 APPModules 폴더에 추가 기능 테스트 코드를 넣을 수 있도록 변경되었습니다. 글로벌 플러그인 및 점자 디스플레이, synth 드라이버 또한 동일한 영향을 받습니다. Developer Scratchpad 폴더를 여는 방법은 다음과 같습니다.

  1. NVDA 메뉴(Insert+N) -> 설정(P) -> NVDA 설정 메뉴 항목을 클릭합니다.
  2. 설정 메뉴가 열리면, 아래 방향 키를 눌러 고급 패널까지 이동합니다.
  3. <이 설정을 변경하면 NVDA가 비정상적으로 동작할 수 있다는 점을 이해합니다. 체크 상자를 선택하여 개발자용 설정 항목을 활성화합니다.
  4. <Developer Scratchpad 디렉터리에서 코드를 불러들일 수 있습니다> 체크 상자를 선택한 다음, <Developer Scratchpad 디렉터리를 엽니다> 버튼을 클릭하여 scratchpad 폴더를 엽니다.
  5. appModules 폴더에 앱 모듈 추가 기능 파일을 넣은 다음 플러그인 새로 고침(Insert+Control+F3) 또는 NVDA 메뉴(Insert+N) -> 도구 -> 플러그인 새로 고침 메뉴 항목을 클릭하여 추가 기능을 새로 고칩니다.

 

추가 기능 앱 모듈 테스트하기

이번 아티클에서 작성한 앱 모듈 추가 기능을 테스트하는 방법은 다음과 같습니다:

  1. 이전 섹션을 참고하여 Developer Scratchpad 옵션을 활성화합니다.
  2. <Developer Scratchpad 디렉터리를 엽니다> 버튼을 클릭하여 scratchpad 폴더를 엽니다.
  3. 폴더가 열리면, editbox.py 또는 py 파일을 scratchpad 내 appModules 폴더에 붙여 넣습니다.
  4. 첨부된 애플리케이션(editbox.exe 또는 exe)를 실행합니다.
  5. 앱 모듈 적용 전 상황을 테스트하려면, 3번의 과정을 생략하고, 첨부된 애플리케이션(editbox.exe 또는 exe)를 실행합니다.

예제 파일 다운로드

 

앱 모듈 작성 #1: 컨트롤의 이름 변경하기

처음 작성해볼 앱 모듈은 텍스트 입력 필드를 가진 간단한 애플리케이션의 텍스트 입력 필드의 name(객체의 레이블)을 변경하는 앱 모듈을 작성해볼 것입니다. 앱 모듈 작성 과정은 다음과 같습니다.

  1. exe를 실행하면, 처음 초점을 받는 텍스트 필드의 이름(text)를 스크린 리더 사용자가 의미를 명확히 파악할 수 있도록 변경할 것입니다.
  2. 객체의 이름(name)을 변경하기 위해 event_NVDAObject_init 이벤트를 사용하여 객체의 이름을 덮어씁니다.

 

앱 모듈의 예제 코드는 다음과 같습니다.

 

# -*- coding: utf-8 -*-

 

# example/editbox.py

 

import appModuleHandler

import controlTypes

 

 

class AppModule(appModuleHandler.AppModule):

 

         def event_NVDAObject_init(self, obj):

                 if obj.windowClassName == "Edit" and obj.role == controlTypes.ROLE_EDITABLETEXT:

                          obj.name = u"텍스트 입력 필드"

 

 

앱 모듈 작성 #1 예제 설명

  1. 앱 모듈 작성을 위해 appModuleHandler 모듈을 import 합니다. appModuleHandler 모듈은 앱 모듈 작성뿐만 아니라, 기존 앱 모듈 관리를 위한 여러 함수 및 메서드를 제공합니다.
  2. 객체의 이름 변경을 위해 controlTypes 모듈을 import 합니다. controlTypes 모듈은 객체의 역할(role), 상태(states)를 관리하는 모듈입니다.
  3. AppModule에서 상속된 AppModule 클래스를 정의합니다.
  4. event_NVDAObject_init은 두 개의 인자를 취하며 self는 앱 모듈의 인스턴스(editbox 앱이 될 것입니다)이며, obj는 변경하고자 하는 객체를 가리키는 인자입니다.
  5. obj의 windowClassName이 Edit이고, 컨트롤이 편집 창일 때 컨트롤의 이름 변경 수행을 위한 조건문을 정의합니다.
  6. 5번의 조건이 충족되면, obj.name의 값으로 편집 창의 레이블이 지정됩니다.

컨트롤의 조건을 검사하는 방법에는 className, role 외에도 다양한 방법이 있습니다.

 

앱 모듈 작성 #2: 컨트롤의 역할(role) 변경하기

두 번째로 작성해볼 앱 모듈은 컨트롤의 역할을 변경하는 앱 모듈을 작성할 것입니다. 컨트롤의 역할 변경은 프로그램의 컨트롤 역할이 잘못 정의될 경우 스크린 리더 사용자가 컨트롤과 상호작용하는 데 혼란이 있을 수 있습니다. 컨트롤의 역할 변경은 이러한 이슈가 발생할 때 스크린 리더 사용자에게 올바른 컨트롤과의 상호작용을 가능케 합니다.

주의

이번 아티클에서는 컨트롤의 역할을 단순히 변경하는 앱 모듈을 작성합니다. 컨트롤 역할 변경 후 변경된 역할과 상호작용하기 위한 추가적인 작업이 필요할 수 있으며, 앞으로 다루어질 아티클에서 관련 내용을 다룰 것입니다.

 

두 번째 앱 모듈은 하나의 체크 상자로 이루어진 간단한 애플리케이션입니다. 이 체크 상자 역할을 라디오 버튼으로 변경해볼 것입니다. 두 번째 앱 모듈 소스 코드는 다음과 같습니다.

 

# -*- coding: utf-8 -*-

 

# example/checkbox.py

 

import appModuleHandler

import controlTypes

 

 

class AppModule(appModuleHandler.AppModule):

 

         def event_NVDAObject_init(self, obj):

                 if obj.windowClassName == "Button" and obj.role == controlTypes.ROLE_CHECKBOX:

                          obj.role = controlTypes.ROLE_RADIOBUTTON

 

 

  1. 앞에서 살펴본 앱 모듈 작성하기 #1 코드의 1~5번의 작업을 통해 컨트롤의 조건을 검사합니다. 달라지는 부분은, obj의 역할을 재정의한다는 점이 다릅니다.
  2. obj의 역할이 기존에 체크 상자(ROLE_CHECKBOX )인 컨트롤을 라디오 버튼(ROLE_RADIOBUTTON) 역할로 재정의하여 스크린 리더 사용자가 라디오 버튼으로 인지하도록 합니다.

 

controlTypes 모듈을 통해 체크 상자, 라디오 버튼과 같은 객체의 역할 및 상태를 관리할 수 있습니다. 더 많은 역할 정보는 controlTypes 모듈을 import 한 다음, Python 콘솔에서 dir(controlTypes)를 입력하여 controlTypes 모듈에서 사용할 수 있는 전체 메서드 및 함수 목록을 확인할 수 있습니다.

이번 아티클에서 사용된 NVDA 추가 기능 제작을 위한 Python 모듈은 다음과 같습니다:

appModuleHandler: 앱 모듈 관리를 위한 모듈로, 기존 앱 모듈 관리 및 앱 모듈 작성을 위해 사용됩니다.

controlTypes: 버튼, 체크 상자와 같은 객체의 역할, 상태 정보를 관리하기 위해 사용되며, 앱 모듈 제작 #2 예제에서 컨트롤의 역할을 변경할 목적으로 사용되었습니다.

 

이번 아티클에서는 간단한 앱 모듈 작성을 통해 NVDA의 앱 모듈 작성 과정을 살펴보았습니다. 다음 아티클에서는 좀 더 심층적인 앱 모듈 작성 과정을 살펴볼 것입니다.

댓글 0
댓글을 작성하려면 해주세요.