JAWS Scripts For Discord
Doug Lee
Last Revised July, 2024

This document describes the scripts for Discord and provides tips for using this application with JAWS. This document can be opened from within the application via a double press of JAWSKey+F1 (or Insert+F1) when the scripts are running.

These scripts are written for both the Discord Windows app and the web client that can be run from http://discord.com/app. The scripts are more often tested against the Windows app, however.

Warning: Discord is an evolving application and is sometimes subject to sudden and significant change. As a result, the commands and behaviors supported by and documented for these scripts may also be subject to change or failure without warning if a change in Discord causes scripts to fail.

Table of Contents

System Requirements For JAWS Users

In addition to any system requirements for the application, the following apply for JAWS users:

Script Installation Instructions

To install these scripts on a new system:

  1. Load JAWS if this has not already been done. This will require administrative privileges on the computer.
  2. Run JAWS as the user for whom the scripts are to be installed. This and the following steps must be performed for each user of the computer who will be using JAWS with these scripts.
  3. Download and run, or run directly, the installer for these scripts; and follow the on-screen directions. Be sure to install the scripts in the currently running JAWS version if a JAWS version list is presented.
  4. To verify successful installation, type Insert+Q from within the application. Part of the JAWS spoken response should be a revision number. If you do not hear a revision number, the scripts are not correctly loaded. In some cases, restarting JAWS may fix this issue.

Key Sequences

These scripts incorporate commands that consist of sequences of keystrokes, all beginning with a common prefix, or "command keystroke." This approach allows many script commands without the risk of conflicting with application keystrokes. See the "Multi-Key Command Sequences" section of the "Common Script Elements" document for further details, including how to explore the available script commands (similar to exploring a menu system), and how to change the Command keystroke if necessary.

By default, the Command keystroke for these scripts is [. This document may refer to this keystroke as [ or Command; so, for example, [ Tab and Command Tab both refer to typing the prefix keystroke, then separately the Tab key. Some sequences may consist of more than two keystrokes, or "levels"; for example, [ d r would refer to typing [, then d, then finally r.

Native Discord Accessibility Features

Discord itself includes various accessibility features as of this writing. Chief among these is a large set of keyboard shortcuts, documented on the Discord site under "Windows Discord hotkeys."

One pair of keystrokes that may not be mentioned in the Discord keyboard shortcuts document is Ctrl+Tab and Ctrl+Shift+Tab, which cycle forward and backward through the servers in the server list.

Script Commands and Features

These scripts provide a number of commands and features beyond those provided by Discord itself. These will be described in subsections organized by category.

General Commands

The sequence [ A will announce the contents of the "Active Now" section of the Friends page, if it is showing. (Note that typing Ctrl+1 twice is a fast way to reach this page from many places in Discord.) This section tends to list friends who are in voice channels, playing games, etc. The language spoken comes directly from Discord and may sometimes seem a bit redundant. At this writing for example (April, 2023), two friends in one voice channel may be announced as, "Doug, Online Doug and Bob In a Voice Channel MAM Men Against Madness General Doug Bob."

[ B brings up a list of buttons for activation. This is similar but not identical to the built-in JAWS JAWSKey+Ctrl+B command for listing buttons in an HTML document:

JAWSKey+Q, along with announcing the active configuration name, will announce the revision number of these scripts.

Insert+F1, typed twice in quick succession, opens this document in the default browser.

Navigating Among Discord Areas

[ E moves to the first edit control on the current screen. This is intended to speed the finding of the chat message entry box for channels and direct messages. Discord natively makes Esc move to this box, but this does not seem to work in all circumstances.

[ S moves to the server tree and activates forms mode if necessary. The Home link and links to any new items appear at the top of this tree. If this command does not at first move to the tree, press Tab once and then try again.

Call and Channel Connection Management

[ D presses the Disconnect button when available on screen. This includes both the normal Disconnect button for a voice channel and the "Disconnect Quietly" button for a stage channel. If more than one is present, this sequence clicks the last one. This can happen when the user has turned on and back off the camera, in which case there can be two Disconnect buttons that do the same thing (tested in Discord 0.0308 as updated on Monday, October 5, 2020).

[ P reports, when visible on screen, the ping time between this Discord client and the server. This will only be on screen when you are in a voice channel.

Handling Chats (Text Conversations)

These scripts provide three sets of commands for efficiently reading chat messages (direct and in-channel). Note that these commands will not work when a modal dialog has been opened on top of a chat window. Examples of such dialogs include the Inbox, opened with Ctrl+I, and an event dialog, which can automatically pop open when some servers or channels take focus and which can be closed by pressing Esc.

The following two sets of commands keep track of a current position among messages that will be remembered until changed or until JAWS is restarted or the current Discord window is replaced with another that supports chat navigation. A position is remembered separately for each Discord chat navigated with this system.

the third set of commands, by contrast, read messages without altering the scripts' idea of which message is "current": Note: These message navigation commands are limited to visible messages due to the way Discord is written. However, reading messages via this system also scrolls the messages being read onto the screen, which may cause repositioning in a long chat history. This behavior is subject to change as the preferred behavior becomes clear through experience and experimentation.

In a chat or text channel, [ T announces whether someone is currently typing. Discord may also natively announce who is typing when multiple persons are typing at once.

[ W announces information about the current direct message or channel. For a DM, this includes any other names by which the person is known on other servers, each with the server name. For a channel, this command speaks the topic for the channel.

These scripts include a modification to the command for virtualizing the current control, JAWSKey+Shift+V, so that it virtualizes the current message in a conversation history. This may also apply to other elements across Discord, depending on how Discord itself implements various controls. Note that the format of text that appears for this command is solely dependent on Discord's UIA implementation. In particular, lines may split or not split at surprising points in the text. This representation will, however, include bullets and numbers in lists that appear inside a message, which at this writing is not true otherwise because of how Discord presents messages to assistive technology.

How is this implemented? Discord provides accessible names to assistive technology such as JAWS for chat messages. These names include various items as appropriate - message text, web preview material, etc. However, at this writing (August 30, 2023), bullets and numbers from lists are not included in these names. These scripts implement the virtualization of chat messages by obtaining text from the focused UIA element's DocumentRange text, wherever the focused element supports this request. This text, again at this writing, is not always formatted just as it appears: lines may be unexpectedly divided or merged, list items may not begin on a new line, etc.

The scripts also cause newly arriving messages in the currently focused chat to speak as they appear.

Handling Pinned Messages

A channel can have "pinned messages" which stay easily available though the message list may grow very long. The scripts provide a [ Shift+P command to press the Pinned Messages button for the current channel. This will pop up a list of any pinned messages for the channel. When there are no pinned messages, a message to this effect will instead appear. Note though that this "no pinned messages" message may appear briefly and be spoken even when pinned messages exist, while Discord is collecting them for display.

To read any messages that do appear, use the Up and Down arrow keys. The chat navigation system just discussed does not work for this list of pinned messages. Press Esc when done reading, to return to the original channel screen.

Handling Threads

Regular text channels may contain "threads," or subtopic areas, whose messages do not appear in the main conversation window. The scripts provide the key sequence [ Shift+T to open and close the dialog that lists any threads in the active channel. This dialog also provides a button for creating a new thread.

When the thread dialog is open, Tab will move through the available threads, which show as buttons. Pressing Space or Enter on one of these will open the thread. Messages then appear in the same manner as for channel messages. The scripted chat navigation system also works for thread messages. To return to the channel, move to the channel list, locate the channel, and press Enter to redisplay its messages. The thread itself may also appear below the channel in the list of channels.

While focus is on a thread's entry in either the Threads dialog or the channel list, the Application menu for the thread will contain a "Join" or "Leave" option. A thread can also be joined from the text channel message where it was created, by tabbing to the button for the thread and opening the Application menu for the button. There are distinct advantages to joining a thread that you wish to follow; see the section on joining threads and following forum posts for further information.

Handling Forum Channels and Posts

A Discord "forum channel" is a channel in which all messages are grouped into topics, called "posts," much as some messages in a normal channel may be grouped into threads. A forum channel contains no messages outside of this topic-oriented structure.

In place of the message list normally seen for a channel, a forum channel will show a list of posts by subject. Pressing Enter on a post will open it and reveal all of its messages. Posts are ordered so that those with the most recent activity appear first.

Up and Down arrows will move among posts in a forum's post list. However, whereas the input edit box for a new message appears below the message list in a channel, the edit box for a forum channel will appear at the top of the list when you use arrows to navigate.

A forum post can be "followed," much as a thread from a regular channel can be "joined," from the Application menu for the post. See the section on joining threads and following forum posts for more on the advantages of doing this for interesting posts.

Joining Threads and Following Forum Posts

Discord allows you to join a thread and to follow a forum post. In practice, these two actions have the same effects:

Handling the Inbox Dialog

The scripts improve the user experience in the Inbox dialog in several ways. The Inbox dialog can be opened by typing Ctrl+I.

Additional Script Features

These scripts also provide the following features:

Tips and Tricks

The Confusing Functions of the Up Arrow Key In a Message Box

Three different things can happen if Up is pressed while focus is in a message entry edit box:

To make sure Up moves to the last message in the message list from the message entry box,

  1. Make sure the edit box is empty.
  2. Press Tab or Shift+Tab after typing and sending a message. This has the effect of preventing the Up arrow key from starting an edit of the last sent message.

Catching Up With Unread Messages

A quick way to catch up with messages across all servers:

  1. If you are already in a chat window, use the script command sequence [ Shift+H to find the New Messages bar, then read sequential messages by pressing L until you hear a click indicating the end of the message list. Press Esc at that point to exit the message reading layer.
  2. Use Alt+Shift+Down to move to the next server with unread messages. If this command does nothing, use Insert+T to see if any alerts are on screen. If so, press Esc to clear them and then try Alt+Shift+Down again. As a last resort if Alt+Shift+Down still does nothing, type the sequence [ U and then try again. This last suggestion gets focus out of servers where the message edit box is disabled, the messages are divided into topics, etc.
  3. Repeat these steps until the above command does not move to another server.

Finding Active Voice Channels

A quick way to find all participants in all voice channels on a server (not including stage channels):

  1. Move to the channel list for the server, such as by typing the scripted command sequence [ N until you reach it.
  2. Press Home to move to the top entry in the list. On a community server, this will often be an events channel.
  3. Start pressing Tab. This will move through tabbable buttons.
  4. If you land on a button that is named after a Discord participant, you have found an active voice channel. Press the Up arrow to find out which channel, and to hear a list of everyone in it.
  5. Press Down to move to the next channel after the active one, then start tabbing again to look for more participants. Repeat the above step on finding any.
  6. Stop when your tabbing reaches the Status button in the user area.

Determining Who Posted Reactions

There are two ways to do this:

  1. When focus is on the message, use the Application menu's "View Reactions" option, then use the JAWS virtual cursor to examine reactions and who posted each. Remember to turn the virtual cursor back off when done, and press Esc to close the dialog. OR
  2. From a message, Tab until focus reaches a reaction; then RouteJAWSToPC to hear who posted the reaction. Unfortunately, it may be necessary to Alt+Tab out of and back into Discord to return focus to the conversation window.

Known Issues

The following issues are known and may be encountered during use of the application with these JAWS scripts. These issues may be fixed in a future update to the scripts or to the application itself.

JAWS does not announce bullets or numbers from lists that appear in a chat message. This is because these items do not appear in Discord's names for these chat elements. As a workaround, use JAWSKey+Shift+V to virtualize a chat message; but note that the format of this result may include unexpected splits and merges of lines.

JAWS does not indicate the presence of block quotes in a chat message. Again this is because Discord does not indicate this condition to assistive technology in its name for the focused chat message element. The JAWSKey+Shift+V workaround just mentioned will also miss the presence of block quotes at this time, as there is no reasonable way for Discord to include this information in the UIA DocumentRange text for a chat element. The JAWS virtual cursor will show where block quotes exist in a message.

In User Settings, Notifications tab, Sounds section, enabling the "Enable same-channel message notifications" option makes Discord produce a unique sound when a message arrives in the channel or DM that is currently on screen. However, it also causes Discord to cease sending Windows Desktop notifications for such messages while that channel is in focus. This remains true even when Discord itself is not displayed on screen. This is a Discord issue and is not related to JAWS or scripts.

Pending event counts may be out of date from time to time in the JAWS virtual view of the Discord window. Typing the screen refresh command, Insert+Esc, will fix this.

The "Roles" list control in a user information popup dialog is not reachable via the keyboard; only its heading can be found in the JAWS virtual view. To find out what roles a user has, press the Menu or Application key on the user's name, rather than pressing Enter. In the resulting context menu, arrow Up to the Roles submenu, then arrow Right and then Up and Down to read any assigned roles.

Braille support is not well tested and is likely incomplete.

Revision History

This is the revision history of these scripts, most recent revision first:

Revision 245, July 15, 2024, tested against application version 1.0.9153

Translators: There are changes in one message file.

Diff showing message file changes Lines starting with a dash are old, with a plus are new, and with a space are for context. This material is offered experimentally to see if it helps translators keep up with project changes.
=== modified file 'discord_lang.xml'
--- old/discord_lang.xml	2024-04-14 21:06:17 +0000
+++ new/discord_lang.xml	2024-07-15 15:17:15 +0000
@@ -23,9 +23,11 @@
 a=Say who is active now if the Friends page is showing
 b=List buttons
 d=Disconnect from voice or video
+e=Move to the first edit box
 n=@
 shift+n=@
 p=Say ping time if visible
+Shift+p=Show pinned messages
 s=Move into the server tree
 t=Say who is typing
 Shift+t=Toggle threads when the button is visible
@@ -80,6 +82,10 @@
 <message name="scThreads">
 Threads
 </message>
+<!-- The exact, case-sensitive name of the Pinned Messages button when present for a channel. -->
+<message name="scPinnedMessages">
+Pinned Messages
+</message>
 <!-- The suffix on the name of the server area. Case insensitive but punctuation matters. -->
 <message name="msgServerSuffix">
 (server)
@@ -88,10 +94,18 @@
 <message name="scDisconnect">
 Disconnect
 </message>
+<!-- The on-screen name of the disconnect button in a stage channel. -->
+<message name="scDisconnectStage">
+Disconnect Quietly
+</message>
 <!-- The exact, case-sensitive text shown when a Discord update is available. -->
 <message name="scUpdateName">
 Update Ready!
 </message>
+<!-- The exact, case-sensitive name of the Members screen area for a channel. -->
+<message name="scMembers">
+Members
+</message>
 <!-- What to say in a special focus situation like a menu or JAWS buffer when the user-initiated script is not meant for that setting. -->
 <message name="msgSpecial">
 This command does not work in menus or JAWS dialogs
@@ -118,6 +132,10 @@
 <message name="msgForumChannel">
 (text forum channel)
 </message>
+<!-- The exact, case-sensitive text displayed for the current client when connected to a voice channel from another client. -->
+<message name="scConnectedElsewhere">
+Connected on another client
+</message>
 <!-- The exact, case-sensitive name of the "Active Now" section of the Friends page. -->
 <message name="scActiveNow">
 Active Now
@@ -190,6 +208,10 @@
 <message name="chat___scMessagesPrefix">
 Messages in
 </message>
+<!-- An on-screen text identifier used to identify polls in a chat message list. Case sensitive. -->
+<message name="chat___scPollOptions">
+Poll options
+</message>
 <!-- A list of words/phrases, in order, to remove from reaction descriptions to make them shorter. -->
 <!-- These are case sensitive. -->
 <message name="chat___scReactionRemovals">

Revision 233, April 18, 2024, tested against application version 1.0.9042

Translators: There are a few additions to one message file.

Diff showing message file changes Lines starting with a dash are old, with a plus are new, and with a space are for context. This material is offered experimentally to see if it helps translators keep up with project changes.
=== modified file 'discord_lang.xml'
--- old/discord_lang.xml	2024-03-09 16:37:50 +0000
+++ new/discord_lang.xml	2024-04-18 16:11:36 +0000
@@ -28,6 +28,7 @@
 p=Say ping time if visible
 s=Move into the server tree
 t=Say who is typing
+Shift+t=Toggle threads when the button is visible
 u=Move to the user area
 w=Say who is the current chat participant in more detail
 Home or h=Read first visible chat message
@@ -71,6 +72,14 @@
 <message name="scUserArea">
 User area
 </message>
+<!-- The exact, case-sensitive name of the channel header area. -->
+<message name="scChannelHeader">
+Channel header
+</message>
+<!-- The exact, case-sensitive name of the Threads button when present for a channel. -->
+<message name="scThreads">
+Threads
+</message>
 <!-- The suffix on the name of the server area. Case insensitive but punctuation matters. -->
 <message name="msgServerSuffix">
 (server)
@@ -181,6 +190,15 @@
 <message name="chat___scMessagesPrefix">
 Messages in
 </message>
+<!-- A list of words/phrases, in order, to remove from reaction descriptions to make them shorter. -->
+<!-- These are case sensitive. -->
+<message name="chat___scReactionRemovals">
+press to remove your reaction
+press to react
+Add Reaction
+reactions
+reaction
+</message>

 <!-- Messages for the ev (event handling) module. -->
 <!-- What to say when event setup fails. -->

Revision 220, March 9, 2024, tested against application version 1.0.9035

Updates to the chat navigation system:

Other updates:

Translators: There are several changes to one message file.

Diff showing message file changes Lines starting with a dash are old, with a plus are new, and with a space are for context. This material is offered experimentally to see if it helps translators keep up with project changes.
=== modified file 'discord_lang.xml'
--- old/discord_lang.xml	2024-03-01 16:32:56 +0000
+++ new/discord_lang.xml	2024-03-09 17:35:03 +0000
@@ -34,7 +34,7 @@
 Shift+Home or Shift+H=Go to and announce the Unread chat message marker if visible
 LeftArrow or J=Read previous chat message
 K or NumPad5=Read current chat message and its position and the message count
-Shift+K or Shift+NumPad5=Jump virtual cursor to current message
+Shift+K or Shift+NumPad5=Move PC focus to the current message.
 L or RightArrow=Read next chat message
 End or Semicolon=Read latest visible chat message
 1 through 9 and 0=Read most recent visible chat messages without altering remembered position
@@ -63,6 +63,10 @@
 <message name="scHome">
 Home
 </message>
+<!-- The name of the Inbox Unreads tab links that jump to unread messages. -->
+<message name="scJump">
+Jump
+</message>
 <!-- The name of the user area. This may not need translation from English. Case matters. -->
 <message name="scUserArea">
 User area
@@ -79,15 +83,6 @@
 <message name="scUpdateName">
 Update Ready!
 </message>
-<!-- The names of the video controls labeled by these scripts. -->
-<!-- The Mute/Unmute label is also used for the mute button for a stream. -->
-<message name="msgVideoControlNames">
-Play/Pause|Mute/Unmute|Expand/Restore
-</message>
-<!-- The label of the "control volume" control that is actually a mute button for streams. Case sensitive. -->
-<message name="scControlVolume">
-Control volume
-</message>
 <!-- What to say in a special focus situation like a menu or JAWS buffer when the user-initiated script is not meant for that setting. -->
 <message name="msgSpecial">
 This command does not work in menus or JAWS dialogs
@@ -172,6 +167,10 @@
 <message name="chat___msgNoContent">
 No content
 </message>
+<!-- What to say when the user tries to focus a message separator element (generally a date header). -->
+<message name="chat___msgNoSep">
+Can't focus a message separator
+</message>
 <!-- How to name the unread-messages separator element. -->
 <!-- This is actually the (non-punctuation) text of the bar's UIA element automationId. -->
 <message name="chat___msgUnreadBar">

Revision 207, March 2, 2024, tested against application version 1.0.9034

This is an interim script release that continues to address serious performance concerns under at least JAWS 2024. It also improves the reliability of message reaction reporting. Specific changes in this release:

Revision 196, February 26, 2024, tested against application version 1.0.9034

Revision 179, January 8, 2024, tested against application version 1.0.9028

Revision 161, August 30, 2023, tested against application version 1.0.9016

Revision 151, July 10, 2023, tested against application version 1.0.9012

Revision 149, June 24, 2023, tested against application version 1.0.9012

Revision 131, January 15, 2023, tested against application version 1.0.9008

Revision 130, January 1, 2023, tested against application version 1.0.9008

Revision 129, December 26, 2022, tested against application version 1.0.9008

Revision 125, November 19, 2022, tested against application version 1.0.9007

Revision 114, January 31, 2022, tested against application version 1.0.9003

Note: This is a significant revision, and installing it correctly requires use of the script installer rather than just the BX Update approach, for those who frequently use that. For those who must install the scripts without using the installer, note that there are additions to the discord_directives.txt file in this revision. Finally, note that some commands are removed from this revision as explained below.

Changes:

Revision 96, January 27, 2021, tested against application version 0.0.308 as updated November 6, 2020

Revision 92, December 08, 2020, tested against application version 0.0.308 as updated November 6, 2020

Revision 90, November 29, 2020, tested against application version 0.0.308 as updated November 6, 2020

Revision 78, November 07, 2020, tested against application version 0.0.308 as updated November 6, 2020

Revision 74, November 02, 2020, tested against application version 0.0.308 as updated October 30, 2020

This release is largely aimed at addressing some problems that appeared in the Friday, October 30, 2020 Discord release. This Discord version can be identified by the Home link being part of, rather than above, the server tree. There are also other features that are not related to the Discord update, as listed below.

Revision 68, October 25, 2020, tested against application version 0.0.308 as updated October 12, 2020

Revision 16, May 9, 2019, tested against application version 0.0.305

Initial release for Aleric to test: