Skip to content

Convert ui.browseableMessage to wx.html2.WebView#20251

Draft
LeonarddeR wants to merge 21 commits into
nvaccess:masterfrom
LeonarddeR:browsableWebview
Draft

Convert ui.browseableMessage to wx.html2.WebView#20251
LeonarddeR wants to merge 21 commits into
nvaccess:masterfrom
LeonarddeR:browsableWebview

Conversation

@LeonarddeR
Copy link
Copy Markdown
Collaborator

@LeonarddeR LeonarddeR commented May 29, 2026

Link to issue number:

Fixes #18878

Summary of the issue:

NVDA shows browseable messages (formatting info, etc.) in a legacy Internet Explorer control, driven by MSHTML's ShowHTMLDialogEx (COM URL monikers + Scripting.Dictionary).

Description of user facing changes:

Browseable messages now render in a wx.html2.WebView hosted inside NVDA's standard message dialog instead of a standalone IE/MSHTML window. The dialog now has native NVDA buttons (Close, and Copy where requested) rather than HTML buttons. Escape closes the dialog and Alt+C copies. Copying announces a simple "Copied to clipboard" confirmation (spoken and brailled), matching the About dialog; the message text itself is not echoed.

Description of developer facing changes:

  • New gui.message.HtmlMessageDialog(MessageDialog) that renders a full HTML document in a WebView. Public API: registerAction(action, handler) to handle nvda-action://<action> URLs triggered from JavaScript, and focusMessage(). The backend is a class attribute _webViewBackend (defaults to WebViewBackendIE) that subclasses can override.
  • MessageDialog gains two protected extension hooks, _createMessageControl() and _wrapMessageControl(), replacing the inline wx.StaticText creation and Wrap call, so the message control can be swapped without branching.
  • ui.browseableMessage rewritten: removed the comtypes / winBindings.mshtml / winBindings.urlmon machinery (ShowHTMLDialogEx, URL monikers, Scripting.Dictionary) and _warnBrowsableMessageComponentFailure. It now fills the message.html template ({{TITLE}} / {{MESSAGE}}) and builds an HtmlMessageDialog, reusing api.copyToClip for copy (matching the About dialog).
  • message.html reduced from ~110 lines of MSHTML-specific JS to a minimal template plus a small keydown handler that routes Escape / Alt+C to nvda-action:// URLs.
  • IAccessible: ShellDocObjectView moves from an imperative event_gainFocus to a declarative _get_focusRedirect (which now also covers the wx WebView case); WxWebView is only applied for OBJID_CLIENT and suppresses the redundant focus report on the outer control.

Description of development approach:

The wx WebView is hosted in the existing MessageDialog rather than reimplementing dialog chrome, buttons, and fallback handling in HTML. Because the WebView captures keyboard focus and the dialog is shown modeless, keyboard activation (Escape / Alt+C) is bridged from JS to Python via nvda-action:// URLs intercepted in the navigating event; mouse activation uses the native buttons.

Testing strategy:

  • Manual testing: opened browseable messages with and without a copy button on both the IE and Edge backends; confirmed focus lands in the content, Escape closes, and the Copy button and Alt+C both copy to the clipboard and announce the result.
    • New System Tests

Known issues with pull request:

Deliberately not switching to the default Edge WebView2 backend yet: Edge is very slow to initialise from a cold state, and keeping a permanent WebView2 singleton alive to hide that cost is debatable. So the IE backend (WebViewBackendIE) is retained for now, but the backend is made overridable (_webViewBackend) and Show is deferred until the EVT_WEBVIEW_LOADED event, so an Edge-backed subclass can be adopted later without further rework. A switch to Edge requires WXPython 4.3 at least.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

🤖 Generated with Claude Code

LeonarddeR and others added 8 commits May 29, 2026 22:40
Replace the old COM/MSHTML ShowHTMLDialogEx approach with a wx.html2.WebView
embedded in MessageDialog. Move the HTML template to message.html with
{{TITLE}} and {{MESSAGE}} placeholders. Handle keyboard shortcuts (Escape,
Alt+C) via JS navigation to nvda-action:// URLs intercepted in Python.
Fix focus routing for Shell DocObject View and WxWebView overlay classes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract HtmlMessageDialog(MessageDialog) owning all WebView concerns
  (control creation, SetPage, nvda-action:// bridge, focus), replacing the
  isHtmlMessage flag and its branches in __init__, setMessage and
  _realizeLayout with the _createMessageControl/_wrapMessageControl hooks.
- ui.browseableMessage no longer pokes _messageControl or imports wx.html2;
  it registers a "copy" action and calls focusMessage().
- Reuse api.copyToClip(notify=True) for the copy button instead of a
  hand-rolled clipboard write.
- Make the WebView backend overridable via the _webViewBackend class attr.
- Defer focusMessage() until EVT_WEBVIEW_LOADED so async backends (Edge)
  focus the inner document only once its content has loaded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Use api.copyToClip(message) plus a flat ui.message("Copied to clipboard")
confirmation instead of copyToClip(notify=True), so the (potentially large)
message content is not echoed, and reuse the existing translatable string.
Use the stock wx.ID_COPY button id.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@amirsol81
Copy link
Copy Markdown

@LeonarddeR Thanks for working on this!

@LeonarddeR LeonarddeR marked this pull request as ready for review May 30, 2026 08:32
@LeonarddeR LeonarddeR requested a review from a team as a code owner May 30, 2026 08:32
@LeonarddeR LeonarddeR requested review from Copilot and seanbudd May 30, 2026 08:32
@LeonarddeR LeonarddeR requested review from Copilot and removed request for Copilot May 30, 2026 10:33
LeonarddeR and others added 9 commits May 30, 2026 20:28
- Override _FAIL_ON_NO_BUTTONS to False so HtmlMessageDialog can be
  shown without any buttons (the HTML content handles its own actions).
- Override _getFallbackAction to return a synthetic close command when
  no commands are registered, so Escape and Alt+F4 still close the
  dialog even without buttons.
- Add wx accelerator table for Escape so IE backend (which consumes the
  key natively before JS keydown fires) still triggers Close().
- Replace focusMessage() with Show() override: defers showing the dialog
  until the WebView content has loaded, fixing a blank-dialog flash with
  the Edge backend. Rename _focusContentWhenLoaded to _deferShowUntilLoaded.

Co-Authored-By: Leonard de Ruijter <leonard@nvaccess.org>
@LeonarddeR LeonarddeR requested review from Copilot and removed request for Copilot June 1, 2026 20:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR modernizes NVDA’s browseable message experience by replacing the legacy MSHTML dialog with a wx.html2.WebView-based dialog, and adds system tests to validate the new behavior.

Changes:

  • Introduces gui.message.HtmlMessageDialog and extensibility hooks on MessageDialog for custom message controls.
  • Updates ui.browseableMessage to render templated HTML with a WebView and route actions via nvda-action://….
  • Adds a new Robot system test suite for browseable messages and wires it into CI.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
user_docs/en/changes.md Documents the dialog modernization and new/updated APIs.
tests/system/robot/browseableMessageTests.robot Adds Robot test suite entry points for browseable message scenarios.
tests/system/robot/browseableMessageTests.py Implements system-test logic for open/navigation/close behaviors.
tests/system/nvdaSettingsFiles/browseableMessage-gestures.ini Provides a deterministic gesture mapping used by the system tests.
source/ui.py Migrates browseableMessage to the new HtmlMessageDialog and updated templating/copy behavior.
source/message.html Replaces legacy IE dialog scripting with a simple HTML template and action URL routing.
source/gui/message.py Adds hooks to MessageDialog and implements HtmlMessageDialog with WebView/action routing.
source/NVDAObjects/IAccessible/wx.py Refines wxWebView overlay selection and suppresses redundant focus reporting.
source/NVDAObjects/IAccessible/init.py Changes focus redirection behavior for ShellDocObjectView.
.github/workflows/testAndPublish.yml Adds the new browseableMessage system tests to the CI matrix (with runner exclusions).

Comment thread source/gui/message.py
Comment thread source/ui.py Outdated
Comment thread source/ui.py Outdated
Comment thread source/ui.py
Comment on lines +144 to +146
gui.mainFrame.prePopup()
dialog.Show()
gui.mainFrame.postPopup()
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about this one. We can remove the Show override, but then a webview with Edge will show, then the content loads async and NVDA has issues to focus it.

Comment thread source/NVDAObjects/IAccessible/__init__.py Outdated
@seanbudd seanbudd added the conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review. label Jun 1, 2026
Comment thread source/NVDAObjects/IAccessible/__init__.py Outdated
Comment thread source/ui.py
Comment thread source/ui.py Outdated
Comment thread source/ui.py Outdated
@seanbudd seanbudd marked this pull request as draft June 2, 2026 04:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

conceptApproved Similar 'triaged' for issues, PR accepted in theory, implementation needs review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

convert ui.browseableMessage to wx.html2.WebView

4 participants