Notification Manager for NVDA

Version 0.3.0-dev, available in Spanish and English. GPL version 2 or later.

Notification history, filters, personal WAV sound rules, favorites, later review, export, and scheduled Do Not Disturb.

Development version: the engine has automated tests, the adapter has been tested with simulated APIs, and the dialogs use real wxPython controls. The native API has been tested from Python on this computer; testing the installed package inside NVDA and checking screen reader output are still pending. The manifest's NVDA 2024.1–2026.1 range is provisional; lastTestedNVDAVersion does not certify manual testing on those versions. The supplied NVDA source identifies itself as 2027.1dev.

Easy mode and accessibility

The window opens in easy mode by default: search, list, Refresh, Details, Read, and Copy. Enter opens the full text in a reading dialog; Read announces it with NVDA. F5 adds newly received notifications to the view. The list does not refresh automatically while you read and retains the selected notification on refresh when it is still present.

Advanced mode exposes filters, favorites, export, rules, settings, and Windows API options. Easy mode switches back. The choice is saved; advanced filters are reset when entering easy mode so they cannot hide notifications. Switching modes does not delete notifications or rules.

Accessibility…, available in both modes, lets you choose which fields accompany the text when navigating rows: date, application, category, and status. Text is always included. Explore columns using Left/Right arrows or Control+1 through Control+5 (date, application, category, status, text). Choose whether to announce the row number, heading, and content. If all three are disabled, content is read. Category and status columns are visually hidden in easy mode but remain available through these shortcuts.

The list retains full text beyond native ListView's 511-character retrieval limit. The NVDA adaptation is restricted to this window and supplies row names to normal speech and braille processing, without adding a second announcement when selecting a row. General speech and braille preferences remain controlled by NVDA. Integrated screen reader output still requires testing inside an installed NVDA instance.

Installation and access

  1. Open notificationManager-0.3.0-dev.nvda-addon with NVDA, install it, and restart when prompted.
  2. Open NVDA → Tools → Notification Manager, or press NVDA+Alt+N.
  3. Generate a new notification and press Refresh in History.
  4. Use the arrow keys to select an entry. Enter opens its details. Tab and Shift+Tab move between controls.

Shortcuts: NVDA+Alt+N opens the manager; NVDA+Alt+L reads the latest retained entry; NVDA+Alt+M toggles manual Do Not Disturb. Reassign them under Preferences → Input Gestures → Notification Manager. A Pause or resume notification capture command is also available, without a default shortcut. Resolve conflicts with other add-ons by changing the key combination. The schedule may keep Do Not Disturb active after you disable manual mode.

The interface and manual follow NVDA's selected language. English regional variants such as en_US and en_GB use the English translation. Spanish remains available. Restart NVDA after changing its language. Your rule names, application names, notification text, and previously stored entries are not translated.

Actual coverage

When available, entries retain the date, text, process, PID, type, NVDA event, window class, role, object class, UIA kind and processing, activity, live region politeness, matched rule, and read/favorite status.

The process may be an intermediary, such as explorer, ShellExperienceHost, or a browser, rather than the originating application. Combine process, text, type, and activity filters. The NVDA event channel does not query the Notification Center or retrieve earlier notifications. The Windows API channel can retrieve notifications Windows still retains. Neither channel reads the private database or retrieves deleted notifications or another user's notifications.

Some web ARIA regions go directly to NVDAHelper through IA2 and do not generate the global liveRegionChange event: that path is not captured. The add-on does not record all speech, status bars, ordinary tooltips, or every interface change. NVDA and other add-ons may filter events beforehand. Capturing every Windows notification is not guaranteed. Terminal UIA notifications may arrive; exclude their process with a rule if needed.

UIA notification text comes from displayString, not the object's name. Other notifications combine name, description, value, and up to 24 child objects over three levels. Text is limited to 16384 characters per entry. An approximate 40 ms budget between queries cannot interrupt a blocked COM call. COM objects are not retained, and buttons on old toasts are not activated: use the application or Windows to act on a notification.

History

The most recent entries appear first. Details are selectable, read-only text. Combine filters for text, process, type, numeric UIA kind, activity, window class, time period, favorites, and unread entries. Text filters are case insensitive; the UIA kind number must match exactly.

The view is a snapshot: Refresh adds new notifications without automatically rearranging the list while you read. Actions include details, read, copy information, toggle favorite, toggle read/unread, create a rule from an entry, delete the selected entry, and clear all history. Reading marks an entry as read; opening details does not. Clearing history includes favorites.

JSON/CSV export writes only the filtered view. JSON preserves the fields. CSV uses UTF-8 with a BOM and neutralizes prefixes that spreadsheet applications might interpret as formulas. Exports are independent files and are not deleted when you clear history.

Personal rules

Press New in Rules. The rule editor has Matching, Advanced source filters, and Actions and testing tabs. All filters must match; an empty filter imposes no restriction. The first enabled matching rule determines all actions. Rules do not accumulate. Edit, duplicate, enable/disable, delete, or reorder them with Move up/Move down. Up to 200 rules are supported.

Filters include Contains/Exact text/Limited regular expression, text case sensitivity, process, type, window class, UIA kind, and activity. Process, window class, and activity use case-insensitive substring matching. UIA kinds are 0 added, 1 removed, 2 action completed, 3 action aborted, and 4 other. Unknown numeric values are retained. UIA processing appears in Details.

Presentation options:

Other actions include saving/excluding the notification from history and quick review, marking it as a favorite, and setting a minimum sound interval for the rule from 0 to 86400 seconds.

Choose an absolute path to an existing WAV file and test it with Preview WAV. Files are not copied. Playback uses nvwave and NVDA's audio preferences; there is no separate per-rule volume or sound queue. Sounds close together may replace one another.

Test matching uses the test text and process; other metadata comes from the rule's matching filters, including Advanced source filters. It tests that rule alone, not the entire list, and does not record a notification. Disabled rules do not match.

Doorbell example

Create a rule named “Doorbell”, with text doorbell pressed, Contains mode, all other filters empty, and WAV path C:\sounds\doorbell.wav. Choose to keep the announcement or replace it with sound. You can later restrict the process using the value observed in a real history entry.

To exclude an application from history, place a rule at the top, filter by process, and uncheck Save in history. Keep the normal announcement if you still want to hear it.

Limited regular expressions

Literals, alternatives, non-repeated groups, anchors, character classes, and a single repetition of a character, dot, or character class are supported. Examples: doorbell pressed, error|warning, ^Download, doorbell.*pressed, code [0-9]+.

Backreferences, lookahead/lookbehind, repeated groups, and two quantifiers are not supported. Patterns such as (a+)+, a*b*, and (ab)+ are rejected. A pattern may contain up to 256 characters and checks the first 2048 characters of a notification. Contains/Exact text check all retained text. These restrictions avoid exponential patterns on NVDA's event thread.

Import and export

Export rules creates JSON with schema version 1. Import appends rules with new IDs without replacing existing ones. Imported rules are disabled so you can review their actions and WAV paths before enabling them.

Import notificationSounds.conf lets you select the original file, usually in %APPDATA%\nvda. Each line must contain an expression, an actual tab, and a WAV path. Empty lines and comments starting with # are allowed. Invalid lines or unsupported patterns are reported and skipped; those patterns need to be rewritten. The original file is not modified. Disable the earlier basic plugin to avoid playing the same sound twice.

Settings and privacy

Press Save settings to apply that tab's changes. Closing without saving discards those changes. Rule operations are saved when accepted. Windows API has its own Save channel options button.

By default, history is stored only in memory. Keeping history on disk allows it to survive an NVDA restart. It is saved approximately every 15 seconds, when closing the manager, and when NVDA exits. A forced shutdown may lose the most recent seconds.

Data is stored in notificationManager inside the NVDA profile:

These are readable, unencrypted text files. They are not transmitted over the network. Diagnostics shows the exact location, which may differ for portable NVDA or a custom profile. Disabling persistence deletes the history file but retains the current session in memory. Initial limits are 1000 entries and 30 days, configurable to 10–10000 entries and 1–365 days. Age and size limits also apply to favorites.

Deduplication only affects history and the add-on's sounds. It compares process, PID, type, text, activity, UIA kind, and processing; each repetition renews the window. The default is 2 seconds; 0 disables it. Two legitimate identical notifications may be grouped. Normal NVDA announcements are not globally suppressed.

Do Not Disturb saves notifications allowed by the rules without announcements or WAV sounds. The schedule uses local time and can cross midnight. Equal start and end times mean all day. It does not change Windows focus settings or banners, or sounds played by other applications. It only affects captured events. When capture is paused, events pass through and Do Not Disturb does not apply.

History is not loaded in secure mode, and opening history or capturing notifications is not allowed while the session is locked. The interface closes when a lock is detected; the session remains in memory for review after unlocking. Data is not copied to NVDA's secure configuration.

If files are damaged, the manager enters read-only mode rather than overwriting them. Check Diagnostics, close NVDA, keep a backup, and rename the damaged file. Default values are used at the next startup; saving creates a new file.

Uninstalling intentionally preserves profile data. To remove it, clear history, disable persistence, and delete the folder shown in Diagnostics while NVDA is closed. WAV files and exports are independent.

Diagnostics and development

If a notification is missing, enable capture, refresh, clear view filters, and check exclusion rules. Enable live regions when appropriate. The notification may use a path that is not captured. Diagnostics and the NVDA log report data/audio issues; notification text is not deliberately added to the log.

The source includes research in docs/INVESTIGACION.md, the pending manual test matrix in docs/PRUEBAS_MANUALES.md, and tests. Build with python -m SCons using Python 3.13, SCons 4.10.1, Markdown, and GNU Gettext tools. Run tests with python -m unittest discover -s tests -v; GUI tests require wxPython. The template copies the Spanish root manual to addon/doc/es, compiles the English catalog, generates both HTML manuals, and packages the add-on.

No external binary dependencies or NVDA source tree are bundled. The interface is available in Spanish and English through NVDA's standard gettext mechanism. License: GPL-2.0-or-later; see COPYING.txt.

Windows API channel introduced in 0.2

This version provides an independent UserNotificationListener channel without installing winrt, winsdk, comtypes, or other external packages. Calls use Windows' COM/WinRT ABI through Python's ctypes. The interface continues to use wxPython supplied with NVDA.

Enabling it

  1. Open Windows API and press Check access.
  2. If access has not been granted, press Request access from Windows and respond to the system dialog if one appears. The request is asynchronous and must be initiated from this interface.
  3. Check Read the Windows Notification Center and press Save channel options.
  4. Wait a few seconds and press Refresh in History. You can select the Notification Center (Windows API) type.

The channel is disabled initially. It does not modify the Registry, NVDA's identity, Windows manifests, or access grants. If Windows denies access or does not support the API for this installation, an error is shown and the NVDA channel remains operational. Permission already granted to Python does not imply permission for nvda.exe. Microsoft's documentation describes a manifest containing the userNotificationListener capability; availability without packaging must be checked on each system. No helper MSIX package is installed.

Queries run on a dedicated thread every 5 seconds, configurable between 2 and 60. Queries do not accumulate. Errors progressively increase the delay up to 5 minutes. The asynchronous operation has an 8-second deadline with cooperative cancellation; a blocked individual COM call may exceed that deadline. The implementation does not rely on NotificationChanged, which has documented failures in some unpackaged desktop applications.

Additional information

It retrieves notifications Windows still retains, including notifications published before the add-on started. It obtains the application name, AUMID, Windows ID, original creation time, title, body, and capture time. Details show whether the notification is still in Windows, is no longer listed, or could not be checked. Disappearance does not necessarily mean the user read it: a notification can expire or be withdrawn by the application.

AUMID provides a better application filter than an intermediary shell process, although it does not always identify the website or account that originated a notification within an application. It is available under Advanced source filters when editing rules. The Application / AUMID history filter searches both fields. Creating a rule from a native entry fills in these values.

New notifications, text changes, and disappearances are detected between queries. Disappearances do not delete the add-on's history. Text changes are retained as new entries with the same Windows identity. An empty initial snapshot is valid if Windows still grants access. Partial queries are not used to conclude that a notification has been withdrawn.

The first query, queries resumed after pause/lock, and recovery from an error are silent. Already retained entries are not reimported after a restart if their identity and text match. Clearing or deleting an entry does not make it reappear on every query during the same session. If the channel is later restarted or resumed and Windows still retains that notification, it may be imported again. To exclude it persistently, use a rule with Save in history unchecked.

Sounds and differences from the NVDA channel

Sounds from this channel are initially disabled to avoid duplication. Enable them with Allow rule sounds for new notifications from this channel. Per-rule sound intervals, Do Not Disturb, and history exclusions are respected. Historical notifications never trigger sounds.

The native channel arrives after publication: it cannot retract an announcement NVDA has already made, or silence Windows sounds or banners. For this channel, Mute/Replace rule actions do not intercept that earlier presentation; only the NVDA event channel can do that. The new channel can add the configured WAV if native sounds are enabled.

A notification may arrive through both channels with different text or application information. Approximate merging is not used, to avoid combining legitimate distinct notifications. Notification type distinguishes the channels. If you enable native sounds, restrict rules to a specific type to avoid playing two sounds. The native channel deduplicates by application, ID, and creation time, independently of the NVDA channel's duplicate window.

It does not retrieve deleted notifications, notifications missed between queries, messages not published as toasts, every kind of web alert, or all IA2 regions. It does not use deletion APIs: deleting an entry from the add-on's history does not delete it from Windows. Native notifications follow the same history privacy, retention, and storage settings.

For source references, see docs/API_WINDOWS.md in the source project.