Skip to main content

Core Modules

appModuleHandler

Handles application-specific modules.
AppModule
class
Base class for app modulesProperties:
  • processID (int): Process ID
  • appName (str): Application name
  • processHandle (int): Process handle
  • sleepMode (bool): Whether NVDA sleeps in this app
  • productName (str): Product name from executable
  • productVersion (str): Product version
  • is64BitProcess (bool): Whether process is 64-bit
  • isWindowsStoreApp (bool): Whether this is a Store app
Methods:
  • chooseNVDAObjectOverlayClasses(obj, clsList): Choose overlay classes
  • event_appModule_gainFocus(): Called when app gains focus
  • event_appModule_loseFocus(): Called when app loses focus
getAppModuleFromProcessID
function
Get app module for a process
mod = appModuleHandler.getAppModuleFromProcessID(processID)
registerExecutableWithAppModule
function
Register custom executable-to-module mapping
appModuleHandler.registerExecutableWithAppModule(
    "myapp", 
    "myAppModule"
)

globalPluginHandler

Handles global plugins.
GlobalPlugin
class
Base class for global pluginsMethods:
  • terminate(): Called when plugin is unloaded
  • chooseNVDAObjectOverlayClasses(obj, clsList): Choose overlay classes
runningPlugins
set
Set of currently running global plugins

api

Core API functions for accessing NVDA state.
import api

# Get focused object
obj = api.getFocusObject()

# Get focus ancestors (parent chain)
ancestors = api.getFocusAncestors()

# Set focus
api.setFocusObject(obj)

# Get foreground object
fg = api.getForegroundObject()

ui

User interface feedback.
import ui

# Simple message
ui.message("Hello")

# Browse mode message (interruptible)
ui.browseableMessage("Long text...", title="Title")

# Report status
ui.reportTextCopied(text)
ui.reportTextNotCopied()

controlTypes

Control roles and states.
import controlTypes

# Common roles
controlTypes.Role.BUTTON
controlTypes.Role.EDITABLETEXT
controlTypes.Role.CHECKBOX
controlTypes.Role.RADIOBUTTON
controlTypes.Role.COMBOBOX
controlTypes.Role.LIST
controlTypes.Role.LISTITEM
controlTypes.Role.LINK
controlTypes.Role.TREEVIEW
controlTypes.Role.TREEVIEWITEM
controlTypes.Role.TABLE
controlTypes.Role.TABLECELL
controlTypes.Role.MENU
controlTypes.Role.MENUITEM
controlTypes.Role.DIALOG
controlTypes.Role.WINDOW

scriptHandler

Script decorator and utilities.
script
decorator
Decorator for defining scripts
from scriptHandler import script

@script(
    description="My script",
    category="My Category",
    gesture="kb:NVDA+shift+m"
)
def script_myScript(self, gesture):
    pass
Parameters:
  • description (str): User-visible description
  • category (str): Category for Input Gestures
  • gesture (str): Single gesture string
  • gestures (list[str]): Multiple gestures
  • canPropagate (bool): Allow on ancestors
  • bypassInputHelp (bool): Run in input help
  • allowInSleepMode (bool): Run in sleep mode
  • resumeSayAllMode: Resume say all mode
  • speakOnDemand (bool): Speak on-demand

speech

Speech output.
import speech

# Speak text
speech.speak(["Hello world"])

# Cancel speech
speech.cancelSpeech()

# Spell text
speech.speakSpelling("word")

# Speak character
speech.speakCharacter("a")

tones

Audio feedback.
tones.py
import tones

# Beep (frequency, duration in ms)
tones.beep(550, 50)

# Error beep
tones.beep(220, 150)

# Success beep
tones.beep(880, 100)

config

Configuration management.
import config

# Access settings
rate = config.conf["speech"]["rate"]
verbosity = config.conf["speech"]["symbolLevel"]

# Check if value exists
if "myAddon" in config.conf:
    enabled = config.conf["myAddon"]["enabled"]

textInfos

Text access and manipulation.
import textInfos

# Get text
info = obj.makeTextInfo(textInfos.POSITION_CARET)
text = info.text

# Move
info.move(textInfos.UNIT_CHARACTER, 1)
info.move(textInfos.UNIT_WORD, -1)
info.move(textInfos.UNIT_LINE, 1)

# Expand
info.expand(textInfos.UNIT_LINE)
info.expand(textInfos.UNIT_PARAGRAPH)

queueHandler

Thread-safe queue operations.
queueHandler.py
import queueHandler
import ui

# Queue function on main thread
def myFunction(arg1, arg2):
    ui.message(f"{arg1}, {arg2}")

queueHandler.queueFunction(
    queueHandler.eventQueue,
    myFunction,
    "hello",
    "world"
)

# Register generator (for long operations)
def myGenerator():
    for i in range(10):
        yield lambda: ui.message(str(i))

queueHandler.registerGeneratorObject(myGenerator())

winUser

Windows API functions.
winUser.py
import winUser

# Window functions
hwnd = winUser.getForegroundWindow()
winUser.setForegroundWindow(hwnd)
winUser.isWindow(hwnd)

# Window text
text = winUser.getWindowText(hwnd)
winUser.setWindowText(hwnd, "New title")

# Window class
className = winUser.getClassName(hwnd)

# Process/thread
threadId, processId = winUser.getWindowThreadProcessID(hwnd)

# Send messages
winUser.sendMessage(hwnd, message, wParam, lParam)

# Get control ID
controlId = winUser.getControlID(hwnd)

gui

GUI dialogs and utilities.
import gui
import wx

# Message dialog
gui.messageBox(
    "Message text",
    "Title",
    wx.OK | wx.ICON_INFORMATION
)

# Input dialog
result = gui.textEntryDialog(
    "Enter text:",
    "Title",
    defaultValue=""
)

NVDAObjects Classes

Base Classes

from NVDAObjects.IAccessible import IAccessible

class MyControl(IAccessible):
    """MSAA/IAccessible object."""
    pass

Behaviors

behaviors.py
from NVDAObjects.behaviors import (
    EditableText,      # Editable text with caret
    Dialog,            # Dialog handling
    ProgressBar,       # Progress announcements
    RowWithFakeNavigation,  # Table row navigation
    KeyboardHandlerBasedTypedCharSupport,  # Typed chars
)

Events

Common NVDA Object events:
event_gainFocus
event
Object gained keyboard focus
event_loseFocus
event
Object lost keyboard focus
event_focusEntered
event
Focus moved inside container (object is ancestor)
event_foreground
event
Object became foreground window
event_nameChange
event
Object’s name changed
event_valueChange
event
Object’s value changed
event_stateChange
event
Object’s state changed
event_selection
event
Selection changed in container
event_caret
event
Caret moved within object
event_locationChange
event
Object’s screen location changed

Gesture Identifiers

Keyboard

# Standard
"kb:NVDA+shift+v"
"kb:control+alt+delete"
"kb:f1"

# Laptop layout
"kb(laptop):NVDA+t"

# Named keys
"kb:escape"
"kb:enter" 
"kb:space"
"kb:tab"
"kb:backspace"
"kb:delete"
"kb:home"
"kb:end"
"kb:pageUp"
"kb:pageDown"
"kb:upArrow"
"kb:downArrow"
"kb:leftArrow"
"kb:rightArrow"
"kb:numpad0" through "kb:numpad9"
"kb:numpadPlus"
"kb:numpadMinus"
"kb:numpadMultiply"
"kb:numpadDivide"
"kb:numpadEnter"

Braille

# Freedom Scientific
"br(freedomScientific):leftWizWheelUp"
"br(freedomScientific):rightWizWheelDown"

# Alva
"br(alva):t1"
"br(alva):etouch1"

# Generic
"br:space+dot1"

Touch

"ts:tap"
"ts:2finger_tap"
"ts:3finger_flickRight"
"ts:4finger_flickUp"

Logging

logging.py
from logHandler import log

# Log levels
log.debug("Debug info")
log.info("Information")
log.warning("Warning") 
log.error("Error")
log.exception("Exception with traceback")

# With exc_info for stack traces
log.error("Error occurred", exc_info=True)

# Stack info without exception
log.warning("Check this", stack_info=True)

Utility Modules

locationHelper

locationHelper.py
import locationHelper

# Rectangle operations
rect1 = locationHelper.RectLTWH(0, 0, 100, 100)
rect2 = locationHelper.RectLTWH(50, 50, 100, 100)

# Check if rectangles intersect
if rect1.intersection(rect2):
    pass

# Get center point
center = rect1.center

textUtils

textUtils.py
import textUtils

# Unicode normalization
normalized = textUtils.normalizeText(text)

# Word boundaries
words = textUtils.WideStringOffsetConverter(text)

Best Practices

  • Always import from the original module (check source code)
  • Don’t rely on transitive imports
  • Private symbols (starting with _) may change without notice
  • Package pip dependencies with your add-on
  • Use ui.message() for user feedback
  • Use log.debug() for development
  • Use queueHandler for thread safety
  • Cache expensive operations
  • Handle exceptions gracefully

Version Compatibility

Check NVDA version:
version.py
import versionInfo

# Version tuple: (year, major, minor)
if versionInfo.version_year >= 2024:
    # Use newer API
    pass

# Version string
version = versionInfo.version  # e.g., "2024.1"

Build docs developers (and LLMs) love